factor/basis/ui/gadgets/panes/panes.factor

399 lines
10 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: arrays ui.gadgets ui.gadgets.borders ui.gadgets.buttons
2008-07-16 01:12:47 -04:00
ui.gadgets.labels ui.gadgets.scrollers
ui.gadgets.paragraphs ui.gadgets.incremental ui.gadgets.packs
ui.gadgets.theme ui.clipboards ui.gestures ui.traverse ui.render
hashtables io kernel namespaces sequences io.styles strings
quotations math opengl combinators math.vectors
sorting splitting io.streams.nested assocs
ui.gadgets.presentations ui.gadgets.slots ui.gadgets.grids
ui.gadgets.grid-lines classes.tuple models continuations
destructors accessors math.geometry.rect ;
2007-09-20 18:09:08 -04:00
IN: ui.gadgets.panes
TUPLE: pane < pack
2008-07-16 01:12:47 -04:00
output current prototype scrolls?
selection-color caret mark selecting? ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: clear-selection ( pane -- pane ) f >>caret f >>mark ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: add-output ( pane current -- pane ) [ >>output ] [ add-gadget ] bi ;
: add-current ( pane current -- pane ) [ >>current ] [ add-gadget ] bi ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: prepare-line ( pane -- pane )
clear-selection
dup prototype>> clone add-current ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: pane-caret&mark ( pane -- caret mark ) [ caret>> ] [ mark>> ] bi ;
2007-09-20 18:09:08 -04:00
: selected-children ( pane -- seq )
[ pane-caret&mark sort-pair ] keep gadget-subtree ;
M: pane gadget-selection? pane-caret&mark and ;
2008-07-16 01:12:47 -04:00
M: pane gadget-selection ( pane -- string/f ) selected-children gadget-text ;
2007-09-20 18:09:08 -04:00
: pane-clear ( pane -- )
2008-07-16 01:12:47 -04:00
clear-selection
[ pane-output clear-incremental ]
[ pane-current clear-gadget ]
bi ;
: new-pane ( class -- pane )
new-gadget
{ 0 1 } >>orientation
<shelf> >>prototype
2008-07-16 01:12:47 -04:00
<incremental> add-output
prepare-line
selection-color >>selection-color ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: <pane> ( -- pane ) pane new-pane ;
2007-09-20 18:09:08 -04:00
GENERIC: draw-selection ( loc obj -- )
: if-fits ( rect quot -- )
>r clip get over intersects? r> [ drop ] if ; inline
M: gadget draw-selection ( loc gadget -- )
swap offset-rect [ rect-extent gl-fill-rect ] if-fits ;
M: node draw-selection ( loc node -- )
2dup node-value swap offset-rect [
drop 2dup
[ node-value rect-loc v+ ] keep
2008-01-09 17:36:30 -05:00
node-children [ draw-selection ] with each
2007-09-20 18:09:08 -04:00
] if-fits 2drop ;
M: pane draw-gadget*
dup gadget-selection? [
dup pane-selection-color set-color
2007-09-20 18:09:08 -04:00
origin get over rect-loc v- swap selected-children
2008-01-09 17:36:30 -05:00
[ draw-selection ] with each
2007-09-20 18:09:08 -04:00
] [
drop
] if ;
: scroll-pane ( pane -- )
dup pane-scrolls? [ scroll>bottom ] [ drop ] if ;
TUPLE: pane-stream pane ;
C: <pane-stream> pane-stream
: smash-line ( current -- gadget )
2008-08-29 19:44:19 -04:00
dup children>> {
2007-09-20 18:09:08 -04:00
{ [ dup empty? ] [ 2drop "" <label> ] }
{ [ dup length 1 = ] [ nip first ] }
2008-04-11 13:54:33 -04:00
[ drop ]
2007-09-20 18:09:08 -04:00
} cond ;
: smash-pane ( pane -- gadget ) pane-output smash-line ;
2008-07-16 01:12:47 -04:00
: pane-nl ( pane -- pane )
2007-09-20 18:09:08 -04:00
dup pane-current dup unparent smash-line
over pane-output add-incremental
prepare-line ;
: pane-write ( pane seq -- )
2008-07-16 01:12:47 -04:00
[ pane-nl ]
2007-09-20 18:09:08 -04:00
[ over pane-current stream-write ]
interleave drop ;
: pane-format ( style pane seq -- )
2008-07-16 01:12:47 -04:00
[ pane-nl ]
2008-01-11 17:02:44 -05:00
[ 2over pane-current stream-format ]
2007-09-20 18:09:08 -04:00
interleave 2drop ;
GENERIC: write-gadget ( gadget stream -- )
2008-07-16 01:12:47 -04:00
M: pane-stream write-gadget ( gadget pane-stream -- )
pane>> current>> swap add-gadget drop ;
2007-09-20 18:09:08 -04:00
2008-05-21 02:36:15 -04:00
M: style-stream write-gadget
stream>> write-gadget ;
2007-09-20 18:09:08 -04:00
: print-gadget ( gadget stream -- )
tuck write-gadget stream-nl ;
: gadget. ( gadget -- )
output-stream get print-gadget ;
2007-09-20 18:09:08 -04:00
: ?nl ( stream -- )
2008-08-29 19:44:19 -04:00
dup pane-stream-pane pane-current children>> empty?
2007-09-20 18:09:08 -04:00
[ dup stream-nl ] unless drop ;
: with-pane ( pane quot -- )
over scroll>top
over pane-clear >r <pane-stream> r>
over >r with-output-stream* r> ?nl ; inline
2007-09-20 18:09:08 -04:00
: make-pane ( quot -- gadget )
<pane> [ swap with-pane ] keep smash-pane ; inline
: <scrolling-pane> ( -- pane )
<pane> t over set-pane-scrolls? ;
TUPLE: pane-control < pane quot ;
2007-11-13 18:51:10 -05:00
2008-07-16 01:12:47 -04:00
M: pane-control model-changed ( model pane-control -- )
[ value>> ] [ dup quot>> ] bi* with-pane ;
2007-11-13 18:51:10 -05:00
2007-09-20 18:09:08 -04:00
: <pane-control> ( model quot -- pane )
pane-control new-pane
swap >>quot
swap >>model ;
2007-09-20 18:09:08 -04:00
: do-pane-stream ( pane-stream quot -- )
>r pane-stream-pane r> keep scroll-pane ; inline
M: pane-stream stream-nl
2008-07-16 01:12:47 -04:00
[ pane-nl drop ] do-pane-stream ;
2007-09-20 18:09:08 -04:00
M: pane-stream stream-write1
[ pane-current stream-write1 ] do-pane-stream ;
M: pane-stream stream-write
[ swap string-lines pane-write ] do-pane-stream ;
M: pane-stream stream-format
[ rot string-lines pane-format ] do-pane-stream ;
M: pane-stream dispose drop ;
2007-09-20 18:09:08 -04:00
M: pane-stream stream-flush drop ;
M: pane-stream make-span-stream
2008-04-04 09:44:32 -04:00
swap <style-stream> <ignore-close-stream> ;
2007-09-20 18:09:08 -04:00
! Character styles
: apply-style ( style gadget key quot -- style gadget )
>r pick at r> when* ; inline
: apply-foreground-style ( style gadget -- style gadget )
foreground [ over (>>color) ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-background-style ( style gadget -- style gadget )
2008-06-18 23:30:54 -04:00
background [ solid-interior ] apply-style ;
2007-09-20 18:09:08 -04:00
: specified-font ( style -- font )
[ font swap at "monospace" or ] keep
[ font-style swap at plain or ] keep
font-size swap at 12 or 3array ;
: apply-font-style ( style gadget -- style gadget )
over specified-font over (>>font) ;
2007-09-20 18:09:08 -04:00
: apply-presentation-style ( style gadget -- style gadget )
presented [ <presentation> ] apply-style ;
: style-label ( style gadget -- gadget )
2007-09-20 18:09:08 -04:00
apply-foreground-style
apply-background-style
apply-font-style
apply-presentation-style
nip ; inline
: <styled-label> ( style text -- gadget )
<label> style-label ;
2007-09-20 18:09:08 -04:00
! Paragraph styles
: apply-wrap-style ( style pane -- style pane )
wrap-margin [
2008-06-18 23:30:54 -04:00
2dup <paragraph> >>prototype drop
<paragraph> >>current
2007-09-20 18:09:08 -04:00
] apply-style ;
: apply-border-color-style ( style gadget -- style gadget )
2008-06-18 23:30:54 -04:00
border-color [ solid-boundary ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-page-color-style ( style gadget -- style gadget )
2008-06-18 23:30:54 -04:00
page-color [ solid-interior ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-path-style ( style gadget -- style gadget )
presented-path [ <editable-slot> ] apply-style ;
: apply-border-width-style ( style gadget -- style gadget )
border-width [ <border> ] apply-style ;
: apply-printer-style ( style gadget -- style gadget )
2008-06-18 23:30:54 -04:00
presented-printer [ [ make-pane ] curry >>printer ] apply-style ;
2007-09-20 18:09:08 -04:00
: style-pane ( style pane -- pane )
apply-border-width-style
apply-border-color-style
apply-page-color-style
apply-presentation-style
apply-path-style
apply-printer-style
nip ;
TUPLE: nested-pane-stream < pane-stream style parent ;
2007-09-20 18:09:08 -04:00
: new-nested-pane-stream ( style parent class -- stream )
new
swap >>parent
swap <pane> apply-wrap-style [ >>style ] [ >>pane ] bi* ;
inline
2007-09-20 18:09:08 -04:00
: unnest-pane-stream ( stream -- child parent )
dup ?nl
dup style>>
over pane>> smash-pane style-pane
swap parent>> ;
2007-09-20 18:09:08 -04:00
TUPLE: pane-block-stream < nested-pane-stream ;
2007-09-20 18:09:08 -04:00
M: pane-block-stream dispose
2007-09-20 18:09:08 -04:00
unnest-pane-stream write-gadget ;
M: pane-stream make-block-stream
pane-block-stream new-nested-pane-stream ;
2007-09-20 18:09:08 -04:00
! Tables
: apply-table-gap-style ( style grid -- style grid )
table-gap [ over (>>gap) ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-table-border-style ( style grid -- style grid )
2008-08-29 19:44:19 -04:00
table-border [ <grid-lines> over (>>boundary) ]
2007-09-20 18:09:08 -04:00
apply-style ;
: styled-grid ( style grid -- grid )
<grid>
f over (>>fill?)
2007-09-20 18:09:08 -04:00
apply-table-gap-style
apply-table-border-style
nip ;
TUPLE: pane-cell-stream < nested-pane-stream ;
2007-09-20 18:09:08 -04:00
M: pane-cell-stream dispose ?nl ;
2007-09-20 18:09:08 -04:00
M: pane-stream make-cell-stream
pane-cell-stream new-nested-pane-stream ;
2007-09-20 18:09:08 -04:00
M: pane-stream stream-write-table
>r
swap [ [ pane-stream-pane smash-pane ] map ] map
styled-grid
r> print-gadget ;
! Stream utilities
M: pack dispose drop ;
2007-09-20 18:09:08 -04:00
M: paragraph dispose drop ;
2007-09-20 18:09:08 -04:00
: gadget-write ( string gadget -- )
2008-06-18 23:30:54 -04:00
over empty?
2008-07-13 02:25:44 -04:00
[ 2drop ] [ >r <label> text-theme r> swap add-gadget drop ] if ;
2007-09-20 18:09:08 -04:00
M: pack stream-write gadget-write ;
: gadget-bl ( style stream -- )
2008-07-13 02:25:44 -04:00
>r " " <word-break-gadget> style-label r> swap add-gadget drop ;
2007-09-20 18:09:08 -04:00
M: paragraph stream-write
swap " " split
[ H{ } over gadget-bl ] [ over gadget-write ] interleave
drop ;
: gadget-write1 ( char gadget -- )
>r 1string r> stream-write ;
M: pack stream-write1 gadget-write1 ;
M: paragraph stream-write1
over CHAR: \s =
[ H{ } swap gadget-bl drop ] [ gadget-write1 ] if ;
: gadget-format ( string style stream -- )
pick empty?
2008-07-13 02:25:44 -04:00
[ 3drop ] [ >r swap <styled-label> r> swap add-gadget drop ] if ;
2007-09-20 18:09:08 -04:00
M: pack stream-format
gadget-format ;
M: paragraph stream-format
presented pick at [
gadget-format
] [
rot " " split
[ 2dup gadget-bl ]
2008-01-11 17:02:44 -05:00
[ 2over gadget-format ] interleave
2007-09-20 18:09:08 -04:00
2drop
] if ;
2008-07-16 01:12:47 -04:00
: caret>mark ( pane -- pane )
dup caret>> >>mark
dup relayout-1 ;
2007-09-20 18:09:08 -04:00
GENERIC: sloppy-pick-up* ( loc gadget -- n )
M: pack sloppy-pick-up* ( loc gadget -- n )
[ orientation>> ] [ children>> ] bi (fast-children-on) ;
2007-09-20 18:09:08 -04:00
M: gadget sloppy-pick-up*
2008-08-29 19:44:19 -04:00
children>> [ inside? ] with find-last drop ;
2007-09-20 18:09:08 -04:00
M: f sloppy-pick-up*
2drop f ;
: wet-and-sloppy ( loc gadget n -- newloc newgadget )
swap nth-gadget [ rect-loc v- ] keep ;
: sloppy-pick-up ( loc gadget -- path )
2dup sloppy-pick-up* dup
[ [ wet-and-sloppy sloppy-pick-up ] keep prefix ]
2007-09-20 18:09:08 -04:00
[ 3drop { } ]
if ;
2008-07-16 01:12:47 -04:00
: move-caret ( pane -- pane )
dup hand-rel
over sloppy-pick-up
over set-pane-caret
dup relayout-1 ;
2007-09-20 18:09:08 -04:00
: begin-selection ( pane -- )
2008-07-16 01:12:47 -04:00
move-caret f swap set-pane-mark ;
2007-09-20 18:09:08 -04:00
: extend-selection ( pane -- )
hand-moved? [
2008-06-18 23:30:54 -04:00
dup selecting?>> [
2008-07-16 01:12:47 -04:00
move-caret
2007-09-20 18:09:08 -04:00
] [
dup hand-clicked get child? [
2008-06-18 23:30:54 -04:00
t >>selecting?
2007-09-20 18:09:08 -04:00
dup hand-clicked set-global
2008-07-16 01:12:47 -04:00
move-caret
caret>mark
2007-09-20 18:09:08 -04:00
] when
] if
dup dup pane-caret gadget-at-path scroll>gadget
2007-09-20 18:09:08 -04:00
] when drop ;
: end-selection ( pane -- )
2008-06-18 23:30:54 -04:00
f >>selecting?
2007-09-20 18:09:08 -04:00
hand-moved? [
2008-06-18 23:30:54 -04:00
[ com-copy-selection ] [ request-focus ] bi
2007-09-20 18:09:08 -04:00
] [
relayout-1
] if ;
: select-to-caret ( pane -- )
2008-07-16 01:12:47 -04:00
dup pane-mark [ caret>mark ] unless
move-caret
2007-09-20 18:09:08 -04:00
dup request-focus
com-copy-selection ;
pane H{
{ T{ button-down } [ begin-selection ] }
{ T{ button-down f { S+ } 1 } [ select-to-caret ] }
{ T{ button-up f { S+ } 1 } [ drop ] }
{ T{ button-up } [ end-selection ] }
{ T{ drag } [ extend-selection ] }
{ T{ copy-action } [ com-copy ] }
} set-gestures