1 ! Copyright (C) 2005, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs kernel math namespaces sequences
4 vectors models models.range math.vectors math.functions quotations
5 colors colors.constants math.rectangles fry combinators ui.gestures
6 ui.pens ui.gadgets ui.gadgets.buttons ui.gadgets.tracks math.order
7 ui.gadgets.icons ui.pens.tile ui.pens.image ;
10 TUPLE: slider < track elevator thumb saved line ;
12 : slider-value ( gadget -- n ) model>> range-value >fixnum ;
13 : slider-page ( gadget -- n ) model>> range-page-value ;
14 : slider-max ( gadget -- n ) model>> range-max-value ;
15 : slider-max* ( gadget -- n ) model>> range-max-value* ;
17 : slide-by ( amount slider -- ) model>> move-by ;
18 : slide-by-page ( amount slider -- ) model>> move-by-page ;
20 : slide-by-line ( amount slider -- ) [ line>> * ] keep slide-by ;
24 TUPLE: elevator < gadget direction ;
26 : find-elevator ( gadget -- elevator/f ) [ elevator? ] find-parent ;
28 : find-slider ( gadget -- slider/f ) [ slider? ] find-parent ;
30 CONSTANT: elevator-padding 4
32 : elevator-length ( slider -- n )
33 [ elevator>> dim>> ] [ orientation>> ] bi v.
34 elevator-padding 2 * - ;
36 CONSTANT: min-thumb-dim 30
38 : visible-portion ( slider -- n )
39 [ slider-page ] [ slider-max 1 max ] bi / 1 min ;
41 : thumb-dim ( slider -- h )
43 [ visible-portion ] [ elevator-length ] bi *
46 [ elevator-length ] bi min ;
48 : slider-scale ( slider -- n )
49 #! A scaling factor such that if x is a slider co-ordinate,
50 #! x*n is the screen position of the thumb, and conversely
51 #! for x/n. The '1 max' calls avoid division by zero.
52 [ [ elevator-length ] [ thumb-dim ] bi - 1 max ]
56 : slider>screen ( m slider -- n ) slider-scale * elevator-padding + ;
57 : screen>slider ( m slider -- n ) [ elevator-padding - ] dip slider-scale / ;
59 M: slider model-changed nip elevator>> relayout-1 ;
61 TUPLE: thumb < track ;
63 : begin-drag ( thumb -- )
64 find-slider dup slider-value >>saved drop ;
66 : do-drag ( thumb -- )
68 [ orientation>> drag-loc v. ]
71 [ model>> set-range-value ]
75 { T{ button-down } [ begin-drag ] }
76 { T{ button-up } [ drop ] }
77 { T{ drag } [ do-drag ] }
80 CONSTANT: horizontal-thumb-tiles
82 { "horizontal-scroller-handle-left" f }
83 { "horizontal-scroller-handle-middle" 1/2 }
84 { "horizontal-scroller-handle-grip" f }
85 { "horizontal-scroller-handle-middle" 1/2 }
86 { "horizontal-scroller-handle-right" f }
89 CONSTANT: vertical-thumb-tiles
91 { "vertical-scroller-handle-top" f }
92 { "vertical-scroller-handle-middle" 1/2 }
93 { "vertical-scroller-handle-grip" f }
94 { "vertical-scroller-handle-middle" 1/2 }
95 { "vertical-scroller-handle-bottom" f }
98 : build-thumb ( thumb -- thumb )
100 { horizontal [ horizontal-thumb-tiles ] }
101 { vertical [ vertical-thumb-tiles ] }
103 [ [ theme-image <icon> ] dip track-add ] assoc-each ;
105 : <thumb> ( orientation -- thumb )
112 : compute-direction ( elevator -- -1/1 )
113 [ hand-click-rel ] [ find-slider ] bi
116 [ slider-value - sgn ]
119 : elevator-hold ( elevator -- )
120 [ direction>> ] [ find-slider ] bi slide-by-page ;
122 : elevator-click ( elevator -- )
123 dup compute-direction >>direction
127 { T{ drag } [ elevator-hold ] }
128 { T{ button-down } [ elevator-click ] }
131 : <elevator> ( vector -- elevator )
135 : thumb-loc ( slider -- loc )
136 [ slider-value ] keep slider>screen ;
138 : layout-thumb-loc ( thumb slider -- )
139 [ thumb-loc ] [ orientation>> ] bi n*v
140 [ floor ] map >>loc drop ;
142 : layout-thumb-dim ( thumb slider -- )
143 [ dim>> ] [ thumb-dim ] [ orientation>> ] tri [ n*v ] keep set-axis
144 [ ceiling ] map >>dim drop ;
146 : slider-enabled? ( slider -- ? )
147 visible-portion 1 = not ;
149 : layout-thumb ( slider -- )
151 [ slider-enabled? >>visible? drop ]
157 find-slider layout-thumb ;
159 : add-thumb-to-elevator ( object -- object )
160 [ elevator>> ] [ thumb>> ] bi add-gadget ;
162 : <slide-button-pen> ( orientation left right -- pen )
163 [ horizontal = ] 2dip ?
164 [ f f ] [ theme-image <image-pen> f f ] bi* <button-pen> ;
166 TUPLE: slide-button < repeat-button ;
168 : <slide-button> ( orientation amount left right -- button )
172 '[ _ swap find-slider slide-by-line ]
173 slide-button new-button
175 <slide-button-pen> >>interior ;
177 M: slide-button pref-dim* dup interior>> pen-pref-dim ;
179 : <up-button> ( orientation -- button )
181 "horizontal-scroller-leftarrow-clicked"
182 "vertical-scroller-uparrow-clicked"
185 : <down-button> ( orientation -- button )
187 "horizontal-scroller-rightarrow-clicked"
188 "vertical-scroller-downarrow-clicked"
191 TUPLE: slider-pen enabled disabled ;
193 : <slider-pen> ( orientation -- pen )
196 "horizontal-scroller-left" theme-image
197 "horizontal-scroller-middle" theme-image
198 "horizontal-scroller-right" theme-image
199 "horizontal-scroller-right-disabled" theme-image
202 "vertical-scroller-top" theme-image
203 "vertical-scroller-middle" theme-image
204 "vertical-scroller-bottom" theme-image
205 "vertical-scroller-bottom-disabled" theme-image
208 [ f f <tile-pen> ] bi-curry@ 2bi \ slider-pen boa ;
210 : slider-pen ( slider pen -- pen )
211 [ slider-enabled? ] [ [ enabled>> ] [ disabled>> ] bi ] bi* ? ;
213 M: slider-pen draw-interior
214 dupd slider-pen draw-interior ;
216 M: slider-pen draw-boundary
217 dupd slider-pen draw-boundary ;
219 M: slider-pen pen-pref-dim
220 enabled>> pen-pref-dim ;
223 [ dup interior>> pen-pref-dim ] [ drop { 100 100 } ] [ orientation>> ] tri
228 : <slider> ( range orientation -- slider )
233 [ <slider-pen> >>interior ]
235 [ <elevator> >>elevator ]
236 [ drop dup add-thumb-to-elevator 1 track-add ]
237 [ <up-button> f track-add ]
238 [ <down-button> f track-add ]
239 [ drop <gadget> { 1 1 } >>dim f track-add ]