1 ! Copyright (C) 2005, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays hashtables io kernel namespaces sequences
4 strings quotations math opengl combinators memoize math.vectors
5 sorting splitting assocs classes.tuple models continuations
6 destructors accessors math.rectangles fry fonts ui.pens.solid
7 ui.images ui.gadgets ui.gadgets.private ui.gadgets.borders
8 ui.gadgets.buttons ui.gadgets.labels ui.gadgets.scrollers
9 ui.gadgets.paragraphs ui.gadgets.incremental ui.gadgets.packs
10 ui.gadgets.menus ui.clipboards ui.gestures ui.traverse ui.render
11 ui.text ui.gadgets.presentations ui.gadgets.grids ui.gadgets.tracks
12 ui.gadgets.icons ui.gadgets.grid-lines ui.baseline-alignment
13 colors call io.styles ;
17 output current input last-line prototype scrolls?
18 selection-color caret mark selecting? ;
20 TUPLE: pane-stream pane ;
22 C: <pane-stream> pane-stream
26 : clear-selection ( pane -- pane )
27 f >>caret f >>mark ; inline
29 : prepare-last-line ( pane -- )
31 [ current>> f track-add ]
32 [ input>> [ 1 track-add ] when* ] bi
35 : init-current ( pane -- pane )
36 dup prototype>> clone >>current ; inline
38 : focus-input ( pane -- )
39 input>> [ request-focus ] when* ;
41 : next-line ( pane -- )
44 [ init-current prepare-last-line ]
47 : pane-caret&mark ( pane -- caret mark )
48 [ caret>> ] [ mark>> ] bi ; inline
50 : selected-children ( pane -- seq )
51 [ pane-caret&mark sort-pair ] keep gadget-subtree ;
53 M: pane gadget-selection? pane-caret&mark and ;
55 M: pane gadget-selection ( pane -- string/f )
56 selected-children gadget-text ;
58 : init-prototype ( pane -- pane )
59 <shelf> +baseline+ >>align >>prototype ; inline
61 : init-output ( pane -- pane )
62 <incremental> [ >>output ] [ f track-add ] bi ; inline
64 : pane-theme ( pane -- pane )
66 selection-color >>selection-color ; inline
68 : init-last-line ( pane -- pane )
70 [ >>last-line ] [ 1 track-add ] bi
71 dup prepare-last-line ; inline
73 GENERIC: draw-selection ( loc obj -- )
75 : if-fits ( rect quot -- )
76 [ clip get over contains-rect? ] dip [ drop ] if ; inline
78 M: gadget draw-selection ( loc gadget -- )
85 M: node draw-selection ( loc node -- )
86 2dup value>> swap offset-rect [
88 [ value>> loc>> v+ ] keep
89 children>> [ draw-selection ] with each
93 dup gadget-selection? [
94 [ selection-color>> gl-color ]
96 [ loc>> vneg ] keep selected-children
97 [ draw-selection ] with each
101 : scroll-pane ( pane -- )
102 dup scrolls?>> [ scroll>bottom ] [ drop ] if ;
104 : smash-line ( current -- gadget )
106 { [ dup empty? ] [ 2drop "" <label> ] }
107 { [ dup length 1 = ] [ nip first ] }
111 : pane-nl ( pane -- )
113 [ current>> [ unparent ] [ smash-line ] bi ] [ output>> ] bi
117 : ?pane-nl ( pane -- )
118 [ dup current>> children>> empty? [ pane-nl ] [ drop ] if ]
121 : smash-pane ( pane -- gadget ) [ pane-nl ] [ output>> smash-line ] bi ;
123 : pane-write ( seq pane -- )
124 [ pane-nl ] [ current>> stream-write ]
125 bi-curry interleave ;
127 : pane-format ( seq style pane -- )
128 [ nip pane-nl ] [ current>> stream-format ]
129 bi-curry bi-curry interleave ;
131 : do-pane-stream ( pane-stream quot -- )
132 [ pane>> ] dip keep scroll-pane ; inline
134 M: pane-stream stream-nl
135 [ pane-nl ] do-pane-stream ;
137 M: pane-stream stream-write1
138 [ current>> stream-write1 ] do-pane-stream ;
140 M: pane-stream stream-write
141 [ [ string-lines ] dip pane-write ] do-pane-stream ;
143 M: pane-stream stream-format
144 [ [ string-lines ] 2dip pane-format ] do-pane-stream ;
146 M: pane-stream dispose drop ;
148 M: pane-stream stream-flush drop ;
150 M: pane-stream make-span-stream
151 swap <style-stream> <ignore-close-stream> ;
155 : new-pane ( input class -- pane )
156 [ vertical ] dip new-track
162 init-last-line ; inline
164 : <pane> ( -- pane ) f pane new-pane ;
166 GENERIC: write-gadget ( gadget stream -- )
168 M: pane-stream write-gadget ( gadget pane-stream -- )
169 pane>> current>> swap add-gadget drop ;
171 M: style-stream write-gadget
172 stream>> write-gadget ;
174 : print-gadget ( gadget stream -- )
175 [ write-gadget ] [ nip stream-nl ] 2bi ;
177 : gadget. ( gadget -- )
178 output-stream get print-gadget ;
180 : pane-clear ( pane -- )
182 [ output>> clear-incremental ]
183 [ current>> clear-gadget ]
186 : with-pane ( pane quot -- )
187 [ [ scroll>top ] [ pane-clear ] [ <pane-stream> ] tri ] dip
188 with-output-stream* ; inline
190 : make-pane ( quot -- gadget )
191 [ <pane> ] dip [ with-pane ] [ drop smash-pane ] 2bi ; inline
193 TUPLE: pane-control < pane quot ;
195 M: pane-control model-changed ( model pane-control -- )
196 [ value>> ] [ dup quot>> ] bi*
197 '[ _ call( value -- ) ] with-pane ;
199 : <pane-control> ( model quot -- pane )
200 f pane-control new-pane
207 MEMO: specified-font ( assoc -- font )
208 #! We memoize here to avoid creating lots of duplicate font objects.
209 [ monospace-font <font> ] dip
211 [ font-name swap at >>name ]
216 { bold [ t >>bold? ] }
217 { italic [ t >>italic? ] }
218 { bold-italic [ t >>bold? t >>italic? ] }
221 [ font-size swap at >>size ]
222 [ foreground swap at >>foreground ]
223 [ background swap at >>background ]
227 : apply-font-style ( style gadget -- style gadget )
228 { font-name font-style font-size foreground background }
229 pick extract-keys specified-font >>font ;
231 : apply-style ( style gadget key quot -- style gadget )
232 [ pick at ] dip when* ; inline
234 : apply-presentation-style ( style gadget -- style gadget )
235 presented [ <presentation> ] apply-style ;
237 : apply-image-style ( style gadget -- style gadget )
238 image [ nip <image-name> <icon> ] apply-style ;
240 : apply-background-style ( style gadget -- style gadget )
241 background [ <solid> >>interior ] apply-style ;
243 : style-label ( style gadget -- gadget )
245 apply-background-style
246 apply-presentation-style
250 : <styled-label> ( style text -- gadget )
251 <label> style-label ;
255 : apply-wrap-style ( style pane -- style pane )
257 2dup <paragraph> >>prototype drop
258 <paragraph> >>current
261 : apply-border-color-style ( style gadget -- style gadget )
262 border-color [ <solid> >>boundary ] apply-style ;
264 : apply-page-color-style ( style gadget -- style gadget )
265 page-color [ <solid> >>interior ] apply-style ;
267 : apply-border-width-style ( style gadget -- style gadget )
268 border-width [ dup 2array <border> ] apply-style ;
270 : style-pane ( style pane -- pane )
271 apply-border-width-style
272 apply-border-color-style
273 apply-page-color-style
274 apply-presentation-style
277 TUPLE: nested-pane-stream < pane-stream style parent ;
279 : new-nested-pane-stream ( style parent class -- stream )
282 swap <pane> apply-wrap-style [ >>style ] [ >>pane ] bi* ;
285 : unnest-pane-stream ( stream -- child parent )
286 [ [ style>> ] [ pane>> smash-pane ] bi style-pane ] [ parent>> ] bi ;
288 TUPLE: pane-block-stream < nested-pane-stream ;
290 M: pane-block-stream dispose
291 unnest-pane-stream write-gadget ;
293 M: pane-stream make-block-stream
294 pane-block-stream new-nested-pane-stream ;
297 : apply-table-gap-style ( style grid -- style grid )
298 table-gap [ >>gap ] apply-style ;
300 : apply-table-border-style ( style grid -- style grid )
301 table-border [ <grid-lines> >>boundary ]
304 : styled-grid ( style grid -- grid )
307 apply-table-gap-style
308 apply-table-border-style
311 TUPLE: pane-cell-stream < nested-pane-stream ;
313 M: pane-cell-stream dispose drop ;
315 M: pane-stream make-cell-stream
316 pane-cell-stream new-nested-pane-stream ;
318 M: pane-stream stream-write-table
320 swap [ [ pane>> smash-pane ] map ] map
325 M: pack dispose drop ;
327 M: paragraph dispose drop ;
329 : gadget-write ( string gadget -- )
331 [ 2drop ] [ <label> text-theme add-gadget drop ] if ;
333 M: pack stream-write gadget-write ;
335 : gadget-bl ( style stream -- )
336 swap " " <word-break-gadget> style-label add-gadget drop ;
338 M: paragraph stream-write
340 [ H{ } over gadget-bl ] [ over gadget-write ] interleave
343 : gadget-write1 ( char gadget -- )
344 [ 1string ] dip stream-write ;
346 M: pack stream-write1 gadget-write1 ;
348 M: paragraph stream-write1
350 [ H{ } swap gadget-bl drop ] [ gadget-write1 ] if ;
352 : empty-output? ( string style -- ? )
353 [ empty? ] [ image swap key? not ] bi* and ;
355 : gadget-format ( string style stream -- )
356 [ [ empty-output? ] 2keep ] dip
357 '[ _ _ swap <styled-label> _ swap add-gadget drop ] unless ;
359 M: pack stream-format
362 M: paragraph stream-format
363 over { presented image } [ swap key? ] with any? [
367 [ gadget-bl ] [ gadget-format ] bi-curry bi-curry
371 : caret>mark ( pane -- )
372 dup caret>> >>mark relayout-1 ;
374 GENERIC: sloppy-pick-up* ( loc gadget -- n )
376 M: pack sloppy-pick-up* ( loc gadget -- n )
377 [ orientation>> ] [ children>> ] bi (fast-children-on) ;
379 M: gadget sloppy-pick-up*
380 children>> [ contains-point? ] with find-last drop ;
385 : wet-and-sloppy ( loc gadget n -- newloc newgadget )
386 swap nth-gadget [ loc>> v- ] keep ;
388 : sloppy-pick-up ( loc gadget -- path )
389 2dup sloppy-pick-up* dup
390 [ [ wet-and-sloppy sloppy-pick-up ] keep prefix ]
394 : move-caret ( pane loc -- )
395 over screen-loc v- over sloppy-pick-up >>caret
398 : begin-selection ( pane -- )
400 dup hand-loc get move-caret
404 : extend-selection ( pane -- )
408 hand-loc get move-caret
410 dup hand-clicked get child? [
412 [ hand-clicked set-global ]
413 [ hand-click-loc get move-caret ]
418 ] [ dup caret>> gadget-at-path scroll>gadget ] bi
421 : end-selection ( pane -- )
424 [ [ com-copy-selection ] [ request-focus ] bi ]
425 [ [ relayout-1 ] [ focus-input ] bi ]
428 : select-to-caret ( pane -- )
430 [ dup mark>> [ dup caret>mark ] unless hand-loc get move-caret ]
431 [ com-copy-selection ]
435 : pane-menu ( pane -- ) { com-copy } show-commands-menu ;
440 { T{ button-down } [ begin-selection ] }
441 { T{ button-down f { S+ } 1 } [ select-to-caret ] }
442 { T{ button-up f { S+ } 1 } [ end-selection ] }
443 { T{ button-up } [ end-selection ] }
444 { T{ drag } [ extend-selection ] }
445 { copy-action [ com-copy ] }
446 { T{ button-down f f 3 } [ pane-menu ] }