]> gitweb.factorcode.org Git - factor.git/blob - basis/ui/gadgets/sliders/sliders.factor
Fix comments to be ! not #!.
[factor.git] / basis / ui / gadgets / sliders / sliders.factor
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 ;
7 IN: ui.gadgets.sliders
8
9 TUPLE: slider < track elevator thumb saved line ;
10
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* ;
16
17 : slider-length ( gadget -- n ) [ slider-max ] [ slider-min ] bi - ;
18 : slider-length* ( gadget -- n ) [ slider-max* ] [ slider-min ] bi - ;
19
20 : slide-by ( amount slider -- ) model>> move-by ;
21 : slide-by-page ( amount slider -- ) model>> move-by-page ;
22
23 : slide-by-line ( amount slider -- ) [ line>> * ] keep slide-by ;
24
25 <PRIVATE
26
27 TUPLE: elevator < gadget direction ;
28
29 : find-slider ( gadget -- slider/f ) [ slider? ] find-parent ;
30
31 CONSTANT: elevator-padding 4
32
33 : elevator-length ( slider -- n )
34     [ elevator>> dim>> ] [ orientation>> ] bi v.
35     elevator-padding 2 * - ;
36
37 CONSTANT: min-thumb-dim 30
38
39 : visible-portion ( slider -- n )
40     [ slider-page ]
41     [ slider-length 1 max ]
42     bi / 1 min ;
43
44 : thumb-dim ( slider -- h )
45     [
46         [ visible-portion ] [ elevator-length ] bi *
47         min-thumb-dim max
48     ]
49     [ elevator-length ] bi min ;
50
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 ]
57     bi / ;
58
59 : slider>screen ( m slider -- n ) slider-scale * ;
60 : screen>slider ( m slider -- n ) slider-scale / ;
61
62 M: slider model-changed nip elevator>> relayout-1 ;
63
64 TUPLE: thumb < track ;
65
66 : begin-drag ( thumb -- )
67     find-slider dup slider-value >>saved drop ;
68
69 : do-drag ( thumb -- )
70     find-slider {
71         [ orientation>> drag-loc v. ]
72         [ screen>slider ]
73         [ saved>> + ]
74         [ model>> set-range-value ]
75     } cleave ;
76
77 thumb H{
78     { T{ button-down } [ begin-drag ] }
79     { T{ button-up } [ drop ] }
80     { T{ drag } [ do-drag ] }
81 } set-gestures
82
83 CONSTANT: horizontal-thumb-tiles
84     {
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 }
90     }
91
92 CONSTANT: vertical-thumb-tiles
93     {
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 }
99     }
100
101 : build-thumb ( thumb -- thumb )
102     dup orientation>> {
103         { horizontal [ horizontal-thumb-tiles ] }
104         { vertical [ vertical-thumb-tiles ] }
105     } case
106     [ [ theme-image <icon> ] dip track-add ] assoc-each ;
107
108 : <thumb> ( orientation -- thumb )
109     thumb new-track
110         0 >>fill
111         1/2 >>align
112         build-thumb
113         t >>root? ;
114
115 : compute-direction ( elevator -- -1/1 )
116     [ hand-click-rel ] [ find-slider ] bi
117     [ orientation>> v. ]
118     [ screen>slider ]
119     [ slider-value - sgn ]
120     tri ;
121
122 : elevator-hold ( elevator -- )
123     [ direction>> ] [ find-slider ] bi slide-by-page ;
124
125 : elevator-click ( elevator -- )
126     dup compute-direction >>direction
127     elevator-hold ;
128
129 elevator H{
130     { T{ drag } [ elevator-hold ] }
131     { T{ button-down } [ elevator-click ] }
132 } set-gestures
133
134 : <elevator> ( vector -- elevator )
135     elevator new
136         swap >>orientation ;
137
138 : thumb-loc ( slider -- loc )
139     [ slider-value ]
140     [ slider-min - ]
141     [ slider>screen elevator-padding + ] tri ;
142
143 : layout-thumb-loc ( thumb slider -- )
144     [ thumb-loc ] [ orientation>> ] bi n*v vfloor >>loc drop ;
145
146 : layout-thumb-dim ( thumb slider -- )
147     [ dim>> ] [ thumb-dim ] [ orientation>> ] tri [ n*v ] keep set-axis
148     vceiling >>dim drop ;
149
150 : slider-enabled? ( slider -- ? )
151     visible-portion 1 = not ;
152
153 : layout-thumb ( slider -- )
154     [ thumb>> ] keep
155     [ slider-enabled? >>visible? drop ]
156     [ layout-thumb-loc ]
157     [ layout-thumb-dim ]
158     2tri ;
159
160 M: elevator layout*
161     find-slider layout-thumb ;
162
163 : add-thumb-to-elevator ( object -- object )
164     [ elevator>> ] [ thumb>> ] bi add-gadget ;
165
166 : <slide-button-pen> ( orientation left right -- pen )
167     [ horizontal = ] 2dip ?
168     [ f f ] [ theme-image <image-pen> f f ] bi* <button-pen> ;
169
170 TUPLE: slide-button < repeat-button ;
171
172 : <slide-button> ( orientation amount left right -- button )
173     [ swap ] 2dip
174     [
175         [ <gadget> ] dip
176         '[ _ swap find-slider slide-by-line ]
177         slide-button new-button
178     ] 3dip
179     <slide-button-pen> >>interior ;
180
181 M: slide-button pref-dim* dup interior>> pen-pref-dim ;
182
183 : <up-button> ( orientation -- button )
184     -1
185     "horizontal-scroller-leftarrow-clicked"
186     "vertical-scroller-uparrow-clicked"
187     <slide-button> ;
188
189 : <down-button> ( orientation -- button )
190     1
191     "horizontal-scroller-rightarrow-clicked"
192     "vertical-scroller-downarrow-clicked"
193     <slide-button> ;
194
195 TUPLE: slider-pen enabled disabled ;
196
197 : <slider-pen> ( orientation -- pen )
198     {
199         { horizontal [
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
204         ] }
205         { vertical [
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
210         ] }
211     } case
212     [ f f <tile-pen> ] bi-curry@ 2bi slider-pen boa ;
213
214 : current-pen ( slider pen -- pen )
215     [ slider-enabled? ] [ [ enabled>> ] [ disabled>> ] bi ] bi* ? ;
216
217 M: slider-pen draw-interior
218     dupd current-pen draw-interior ;
219
220 M: slider-pen draw-boundary
221     dupd current-pen draw-boundary ;
222
223 M: slider-pen pen-pref-dim
224     enabled>> pen-pref-dim ;
225
226 M: slider pref-dim*
227     [ dup interior>> pen-pref-dim ] [ drop { 100 100 } ] [ orientation>> ] tri
228     set-axis ;
229
230 PRIVATE>
231
232 : <slider> ( range orientation -- slider )
233     slider new-track
234         swap >>model
235         16 >>line
236         dup orientation>> {
237             [ <slider-pen> >>interior ]
238             [ <thumb> >>thumb ]
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 ]
244         } cleave ;