1 ! Copyright (C) 2005, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs combinators fry kernel math math.order
4 math.vectors models models.range ui.gadgets ui.gadgets.buttons
5 ui.gadgets.icons ui.gadgets.theme ui.gadgets.tracks ui.gestures
6 ui.pens ui.pens.image ui.pens.tile ;
9 TUPLE: slider < track elevator thumb saved line ;
11 : slider-value ( gadget -- n ) model>> range-value ;
12 : slider-page ( gadget -- n ) model>> range-page-value ;
13 : slider-min ( gadget -- n ) model>> range-min-value ;
14 : slider-max ( gadget -- n ) model>> range-max-value ;
15 : slider-max* ( gadget -- n ) model>> range-max-value* ;
17 : slider-length ( gadget -- n ) [ slider-max ] [ slider-min ] bi - ;
18 : slider-length* ( gadget -- n ) [ slider-max* ] [ slider-min ] bi - ;
20 : slide-by ( amount slider -- ) model>> move-by ;
21 : slide-by-page ( amount slider -- ) model>> move-by-page ;
23 : slide-by-line ( amount slider -- ) [ line>> * ] keep slide-by ;
27 TUPLE: elevator < gadget direction ;
29 : find-slider ( gadget -- slider/f ) [ slider? ] find-parent ;
31 CONSTANT: elevator-padding 4
33 : elevator-length ( slider -- n )
34 [ elevator>> dim>> ] [ orientation>> ] bi v.
35 elevator-padding 2 * - ;
37 CONSTANT: min-thumb-dim 30
39 : visible-portion ( slider -- n )
41 [ slider-length 1 max ]
44 : thumb-dim ( slider -- h )
46 [ visible-portion ] [ elevator-length ] bi *
49 [ elevator-length ] bi min ;
51 : slider-scale ( slider -- n )
52 #! A scaling factor such that if x is a slider co-ordinate,
53 #! x*n is the screen position of the thumb, and conversely
54 #! for x/n. The '1 max' calls avoid division by zero.
55 [ [ elevator-length ] [ thumb-dim ] bi - 1 max ]
56 [ slider-length* 1 max ]
59 : slider>screen ( m slider -- n ) slider-scale * ;
60 : screen>slider ( m slider -- n ) slider-scale / ;
62 M: slider model-changed nip elevator>> relayout-1 ;
64 TUPLE: thumb < track ;
66 : begin-drag ( thumb -- )
67 find-slider dup slider-value >>saved drop ;
69 : do-drag ( thumb -- )
71 [ orientation>> drag-loc v. ]
74 [ model>> set-range-value ]
78 { T{ button-down } [ begin-drag ] }
79 { T{ button-up } [ drop ] }
80 { T{ drag } [ do-drag ] }
83 CONSTANT: horizontal-thumb-tiles
85 { "horizontal-scroller-handle-left" f }
86 { "horizontal-scroller-handle-middle" 1/2 }
87 { "horizontal-scroller-handle-grip" f }
88 { "horizontal-scroller-handle-middle" 1/2 }
89 { "horizontal-scroller-handle-right" f }
92 CONSTANT: vertical-thumb-tiles
94 { "vertical-scroller-handle-top" f }
95 { "vertical-scroller-handle-middle" 1/2 }
96 { "vertical-scroller-handle-grip" f }
97 { "vertical-scroller-handle-middle" 1/2 }
98 { "vertical-scroller-handle-bottom" f }
101 : build-thumb ( thumb -- thumb )
103 { horizontal [ horizontal-thumb-tiles ] }
104 { vertical [ vertical-thumb-tiles ] }
106 [ [ theme-image <icon> ] dip track-add ] assoc-each ;
108 : <thumb> ( orientation -- thumb )
115 : compute-direction ( elevator -- -1/1 )
116 [ hand-click-rel ] [ find-slider ] bi
119 [ slider-value - sgn ]
122 : elevator-hold ( elevator -- )
123 [ direction>> ] [ find-slider ] bi slide-by-page ;
125 : elevator-click ( elevator -- )
126 dup compute-direction >>direction
130 { T{ drag } [ elevator-hold ] }
131 { T{ button-down } [ elevator-click ] }
134 : <elevator> ( vector -- elevator )
138 : thumb-loc ( slider -- loc )
141 [ slider>screen elevator-padding + ] tri ;
143 : layout-thumb-loc ( thumb slider -- )
144 [ thumb-loc ] [ orientation>> ] bi n*v vfloor >>loc drop ;
146 : layout-thumb-dim ( thumb slider -- )
147 [ dim>> ] [ thumb-dim ] [ orientation>> ] tri [ n*v ] keep set-axis
148 vceiling >>dim drop ;
150 : slider-enabled? ( slider -- ? )
151 visible-portion 1 = not ;
153 : layout-thumb ( slider -- )
155 [ slider-enabled? >>visible? drop ]
161 find-slider layout-thumb ;
163 : add-thumb-to-elevator ( object -- object )
164 [ elevator>> ] [ thumb>> ] bi add-gadget ;
166 : <slide-button-pen> ( orientation left right -- pen )
167 [ horizontal = ] 2dip ?
168 [ f f ] [ theme-image <image-pen> f f ] bi* <button-pen> ;
170 TUPLE: slide-button < repeat-button ;
172 : <slide-button> ( orientation amount left right -- button )
176 '[ _ swap find-slider slide-by-line ]
177 slide-button new-button
179 <slide-button-pen> >>interior ;
181 M: slide-button pref-dim* dup interior>> pen-pref-dim ;
183 : <up-button> ( orientation -- button )
185 "horizontal-scroller-leftarrow-clicked"
186 "vertical-scroller-uparrow-clicked"
189 : <down-button> ( orientation -- button )
191 "horizontal-scroller-rightarrow-clicked"
192 "vertical-scroller-downarrow-clicked"
195 TUPLE: slider-pen-tuple enabled disabled ;
197 : <slider-pen> ( orientation -- pen )
200 "horizontal-scroller-left" theme-image
201 "horizontal-scroller-middle" theme-image
202 "horizontal-scroller-right" theme-image
203 "horizontal-scroller-right-disabled" theme-image
206 "vertical-scroller-top" theme-image
207 "vertical-scroller-middle" theme-image
208 "vertical-scroller-bottom" theme-image
209 "vertical-scroller-bottom-disabled" theme-image
212 [ f f <tile-pen> ] bi-curry@ 2bi \ slider-pen-tuple boa ;
214 : slider-pen ( slider pen -- pen )
215 [ slider-enabled? ] [ [ enabled>> ] [ disabled>> ] bi ] bi* ? ;
217 M: slider-pen-tuple draw-interior
218 dupd slider-pen draw-interior ;
220 M: slider-pen-tuple draw-boundary
221 dupd slider-pen draw-boundary ;
223 M: slider-pen-tuple pen-pref-dim
224 enabled>> pen-pref-dim ;
227 [ dup interior>> pen-pref-dim ] [ drop { 100 100 } ] [ orientation>> ] tri
232 : <slider> ( range orientation -- slider )
237 [ <slider-pen> >>interior ]
239 [ <elevator> >>elevator ]
240 [ drop dup add-thumb-to-elevator 1 track-add ]
241 [ <up-button> f track-add ]
242 [ <down-button> f track-add ]
243 [ drop <gadget> { 1 1 } >>dim f track-add ]