1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays ui.gadgets ui.gadgets.borders ui.gadgets.buttons
4 ui.gadgets.labels ui.gadgets.scrollers ui.gadgets.paragraphs
5 ui.gadgets.incremental ui.gadgets.packs ui.gadgets.theme
6 ui.clipboards ui.gestures ui.traverse ui.render hashtables io
7 kernel namespaces sequences io.styles strings quotations math
8 opengl combinators math.vectors sorting splitting
9 io.streams.nested assocs ui.gadgets.presentations
10 ui.gadgets.slots ui.gadgets.grids ui.gadgets.grid-lines
11 classes.tuple models continuations destructors accessors
17 output current prototype scrolls?
18 selection-color caret mark selecting? ;
20 : clear-selection ( pane -- pane )
23 : add-output ( pane current -- pane )
24 [ >>output ] [ add-gadget ] bi ;
26 : add-current ( pane current -- pane )
27 [ >>current ] [ add-gadget ] bi ;
29 : prepare-line ( pane -- pane )
31 dup prototype>> clone add-current ;
33 : pane-caret&mark ( pane -- caret mark )
34 [ caret>> ] [ mark>> ] bi ;
36 : selected-children ( pane -- seq )
37 [ pane-caret&mark sort-pair ] keep gadget-subtree ;
39 M: pane gadget-selection? pane-caret&mark and ;
41 M: pane gadget-selection ( pane -- string/f )
42 selected-children gadget-text ;
44 : pane-clear ( pane -- )
46 [ output>> clear-incremental ]
47 [ current>> clear-gadget ]
50 : new-pane ( class -- pane )
54 <incremental> add-output
56 selection-color >>selection-color ;
58 : <pane> ( -- pane ) pane new-pane ;
60 GENERIC: draw-selection ( loc obj -- )
62 : if-fits ( rect quot -- )
63 >r clip get over intersects? r> [ drop ] if ; inline
65 M: gadget draw-selection ( loc gadget -- )
66 swap offset-rect [ rect-extent gl-fill-rect ] if-fits ;
68 M: node draw-selection ( loc node -- )
69 2dup value>> swap offset-rect [
71 [ value>> rect-loc v+ ] keep
72 children>> [ draw-selection ] with each
76 dup gadget-selection? [
77 dup selection-color>> set-color
78 origin get over rect-loc v- swap selected-children
79 [ draw-selection ] with each
84 : scroll-pane ( pane -- )
85 dup scrolls?>> [ scroll>bottom ] [ drop ] if ;
87 TUPLE: pane-stream pane ;
89 C: <pane-stream> pane-stream
91 : smash-line ( current -- gadget )
93 { [ dup empty? ] [ 2drop "" <label> ] }
94 { [ dup length 1 = ] [ nip first ] }
98 : smash-pane ( pane -- gadget ) output>> smash-line ;
100 : pane-nl ( pane -- pane )
101 dup current>> dup unparent smash-line
102 over output>> add-incremental
105 : pane-write ( pane seq -- )
107 [ over current>> stream-write ]
110 : pane-format ( style pane seq -- )
112 [ 2over current>> stream-format ]
115 GENERIC: write-gadget ( gadget stream -- )
117 M: pane-stream write-gadget ( gadget pane-stream -- )
118 pane>> current>> swap add-gadget drop ;
120 M: style-stream write-gadget
121 stream>> write-gadget ;
123 : print-gadget ( gadget stream -- )
124 tuck write-gadget stream-nl ;
126 : gadget. ( gadget -- )
127 output-stream get print-gadget ;
130 dup pane>> current>> children>> empty?
131 [ dup stream-nl ] unless drop ;
133 : with-pane ( pane quot -- )
135 over pane-clear >r <pane-stream> r>
136 over >r with-output-stream* r> ?nl ; inline
138 : make-pane ( quot -- gadget )
139 <pane> [ swap with-pane ] keep smash-pane ; inline
141 : <scrolling-pane> ( -- pane ) <pane> t >>scrolls? ;
143 TUPLE: pane-control < pane quot ;
145 M: pane-control model-changed ( model pane-control -- )
146 [ value>> ] [ dup quot>> ] bi* with-pane ;
148 : <pane-control> ( model quot -- pane )
149 pane-control new-pane
153 : do-pane-stream ( pane-stream quot -- )
154 >r pane>> r> keep scroll-pane ; inline
156 M: pane-stream stream-nl
157 [ pane-nl drop ] do-pane-stream ;
159 M: pane-stream stream-write1
160 [ current>> stream-write1 ] do-pane-stream ;
162 M: pane-stream stream-write
163 [ swap string-lines pane-write ] do-pane-stream ;
165 M: pane-stream stream-format
166 [ rot string-lines pane-format ] do-pane-stream ;
168 M: pane-stream dispose drop ;
170 M: pane-stream stream-flush drop ;
172 M: pane-stream make-span-stream
173 swap <style-stream> <ignore-close-stream> ;
177 : apply-style ( style gadget key quot -- style gadget )
178 >r pick at r> when* ; inline
180 : apply-foreground-style ( style gadget -- style gadget )
181 foreground [ >>color ] apply-style ;
183 : apply-background-style ( style gadget -- style gadget )
184 background [ solid-interior ] apply-style ;
186 : specified-font ( style -- font )
187 [ font swap at "monospace" or ] keep
188 [ font-style swap at plain or ] keep
189 font-size swap at 12 or 3array ;
191 : apply-font-style ( style gadget -- style gadget )
192 over specified-font >>font ;
194 : apply-presentation-style ( style gadget -- style gadget )
195 presented [ <presentation> ] apply-style ;
197 : style-label ( style gadget -- gadget )
198 apply-foreground-style
199 apply-background-style
201 apply-presentation-style
204 : <styled-label> ( style text -- gadget )
205 <label> style-label ;
209 : apply-wrap-style ( style pane -- style pane )
211 2dup <paragraph> >>prototype drop
212 <paragraph> >>current
215 : apply-border-color-style ( style gadget -- style gadget )
216 border-color [ solid-boundary ] apply-style ;
218 : apply-page-color-style ( style gadget -- style gadget )
219 page-color [ solid-interior ] apply-style ;
221 : apply-path-style ( style gadget -- style gadget )
222 presented-path [ <editable-slot> ] apply-style ;
224 : apply-border-width-style ( style gadget -- style gadget )
225 border-width [ <border> ] apply-style ;
227 : apply-printer-style ( style gadget -- style gadget )
228 presented-printer [ [ make-pane ] curry >>printer ] apply-style ;
230 : style-pane ( style pane -- pane )
231 apply-border-width-style
232 apply-border-color-style
233 apply-page-color-style
234 apply-presentation-style
239 TUPLE: nested-pane-stream < pane-stream style parent ;
241 : new-nested-pane-stream ( style parent class -- stream )
244 swap <pane> apply-wrap-style [ >>style ] [ >>pane ] bi* ;
247 : unnest-pane-stream ( stream -- child parent )
250 over pane>> smash-pane style-pane
253 TUPLE: pane-block-stream < nested-pane-stream ;
255 M: pane-block-stream dispose
256 unnest-pane-stream write-gadget ;
258 M: pane-stream make-block-stream
259 pane-block-stream new-nested-pane-stream ;
262 : apply-table-gap-style ( style grid -- style grid )
263 table-gap [ >>gap ] apply-style ;
265 : apply-table-border-style ( style grid -- style grid )
266 table-border [ <grid-lines> >>boundary ]
269 : styled-grid ( style grid -- grid )
272 apply-table-gap-style
273 apply-table-border-style
276 TUPLE: pane-cell-stream < nested-pane-stream ;
278 M: pane-cell-stream dispose ?nl ;
280 M: pane-stream make-cell-stream
281 pane-cell-stream new-nested-pane-stream ;
283 M: pane-stream stream-write-table
285 swap [ [ pane>> smash-pane ] map ] map
290 M: pack dispose drop ;
292 M: paragraph dispose drop ;
294 : gadget-write ( string gadget -- )
296 [ 2drop ] [ <label> text-theme add-gadget drop ] if ;
298 M: pack stream-write gadget-write ;
300 : gadget-bl ( style stream -- )
301 swap " " <word-break-gadget> style-label add-gadget drop ;
303 M: paragraph stream-write
305 [ H{ } over gadget-bl ] [ over gadget-write ] interleave
308 : gadget-write1 ( char gadget -- )
309 >r 1string r> stream-write ;
311 M: pack stream-write1 gadget-write1 ;
313 M: paragraph stream-write1
315 [ H{ } swap gadget-bl drop ] [ gadget-write1 ] if ;
317 : gadget-format ( string style stream -- )
319 [ 3drop ] [ <styled-label> add-gadget drop ] if ;
321 M: pack stream-format
324 M: paragraph stream-format
330 [ 2over gadget-format ] interleave
334 : caret>mark ( pane -- pane )
338 GENERIC: sloppy-pick-up* ( loc gadget -- n )
340 M: pack sloppy-pick-up* ( loc gadget -- n )
341 [ orientation>> ] [ children>> ] bi (fast-children-on) ;
343 M: gadget sloppy-pick-up*
344 children>> [ inside? ] with find-last drop ;
349 : wet-and-sloppy ( loc gadget n -- newloc newgadget )
350 swap nth-gadget [ rect-loc v- ] keep ;
352 : sloppy-pick-up ( loc gadget -- path )
353 2dup sloppy-pick-up* dup
354 [ [ wet-and-sloppy sloppy-pick-up ] keep prefix ]
358 : move-caret ( pane -- pane )
359 dup hand-rel over sloppy-pick-up >>caret
362 : begin-selection ( pane -- ) move-caret f >>mark drop ;
364 : extend-selection ( pane -- )
369 dup hand-clicked get child? [
371 dup hand-clicked set-global
376 dup dup caret>> gadget-at-path scroll>gadget
379 : end-selection ( pane -- )
382 [ com-copy-selection ] [ request-focus ] bi
387 : select-to-caret ( pane -- )
388 dup mark>> [ caret>mark ] unless
394 { T{ button-down } [ begin-selection ] }
395 { T{ button-down f { S+ } 1 } [ select-to-caret ] }
396 { T{ button-up f { S+ } 1 } [ drop ] }
397 { T{ button-up } [ end-selection ] }
398 { T{ drag } [ extend-selection ] }
399 { T{ copy-action } [ com-copy ] }