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

412 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
ui.gadgets.labels ui.gadgets.scrollers ui.gadgets.paragraphs
ui.gadgets.incremental ui.gadgets.packs ui.gadgets.theme
ui.gadgets.menus ui.clipboards ui.gestures ui.traverse ui.render
hashtables io kernel namespaces sequences io.styles strings
quotations math opengl combinators math.vectors sorting
splitting assocs ui.gadgets.presentations
ui.gadgets.slots ui.gadgets.grids ui.gadgets.grid-lines
classes.tuple models continuations destructors accessors
math.geometry.rect fry ;
2007-09-20 18:09:08 -04:00
IN: ui.gadgets.panes
TUPLE: pane < pack
output current prototype scrolls?
selection-color caret mark selecting? ;
2007-09-20 18:09:08 -04:00
: clear-selection ( pane -- pane )
f >>caret f >>mark ;
2007-09-20 18:09:08 -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
: 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 ;
M: pane gadget-selection ( pane -- string/f )
selected-children gadget-text ;
2007-09-20 18:09:08 -04:00
: pane-clear ( pane -- )
clear-selection
[ output>> clear-incremental ]
[ 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 -- )
[ clip get over intersects? ] dip [ drop ] if ; inline
2007-09-20 18:09:08 -04:00
M: gadget draw-selection ( loc gadget -- )
swap offset-rect [
dup loc>> [
dim>> gl-fill-rect
] with-translation
] if-fits ;
2007-09-20 18:09:08 -04:00
M: node draw-selection ( loc node -- )
2dup value>> swap offset-rect [
2007-09-20 18:09:08 -04:00
drop 2dup
[ value>> rect-loc v+ ] keep
children>> [ draw-selection ] with each
2007-09-20 18:09:08 -04:00
] if-fits 2drop ;
M: pane draw-gadget*
dup gadget-selection? [
dup selection-color>> gl-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 -- )
2008-08-31 02:42:30 -04:00
dup scrolls?>> [ scroll>bottom ] [ drop ] if ;
2007-09-20 18:09:08 -04:00
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 ;
2008-08-31 02:42:30 -04:00
: smash-pane ( pane -- gadget ) output>> smash-line ;
2007-09-20 18:09:08 -04:00
2008-07-16 01:12:47 -04:00
: pane-nl ( pane -- pane )
2008-08-31 02:42:30 -04:00
dup current>> dup unparent smash-line
over output>> add-incremental
2007-09-20 18:09:08 -04:00
prepare-line ;
: pane-write ( pane seq -- )
2008-07-16 01:12:47 -04:00
[ pane-nl ]
2008-08-31 02:42:30 -04:00
[ over current>> stream-write ]
2007-09-20 18:09:08 -04:00
interleave drop ;
: pane-format ( style pane seq -- )
2008-07-16 01:12:47 -04:00
[ pane-nl ]
2008-08-31 02:42:30 -04:00
[ 2over 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 -- )
2008-09-27 19:44:51 -04:00
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-31 02:42:30 -04:00
dup 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 [ <pane-stream> ] dip
over [ with-output-stream* ] dip ?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 >>scrolls? ;
2007-09-20 18:09:08 -04:00
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 -- )
2008-09-27 19:44:51 -04:00
[ 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 -- )
[ pane>> ] dip keep scroll-pane ; inline
2007-09-20 18:09:08 -04:00
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
2008-08-31 02:42:30 -04:00
[ current>> stream-write1 ] do-pane-stream ;
2007-09-20 18:09:08 -04:00
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 )
[ pick at ] dip when* ; inline
2007-09-20 18:09:08 -04:00
: apply-foreground-style ( style gadget -- style gadget )
foreground [ >>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 >>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 )
presented-printer [ '[ _ make-pane ] >>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 [ >>gap ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-table-border-style ( style grid -- style grid )
table-border [ <grid-lines> >>boundary ]
2007-09-20 18:09:08 -04:00
apply-style ;
: styled-grid ( style grid -- grid )
<grid>
f >>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
[
swap [ [ pane>> smash-pane ] map ] map
styled-grid
] dip print-gadget ;
2007-09-20 18:09:08 -04:00
! 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 -- )
swap dup empty?
[ 2drop ] [ <label> text-theme add-gadget drop ] if ;
2007-09-20 18:09:08 -04:00
M: pack stream-write gadget-write ;
: gadget-bl ( style stream -- )
swap " " <word-break-gadget> style-label 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 -- )
[ 1string ] dip stream-write ;
2007-09-20 18:09:08 -04:00
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 -- )
spin dup empty?
[ 3drop ] [ <styled-label> 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 )
2008-09-27 19:44:51 -04:00
[ 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 ;
: move-caret ( pane loc -- pane )
over screen-loc v- over sloppy-pick-up >>caret
dup relayout-1 ;
2007-09-20 18:09:08 -04:00
2008-11-20 19:30:08 -05:00
: begin-selection ( pane -- )
f >>selecting?
hand-loc get move-caret
2008-11-20 19:30:08 -05:00
f >>mark
drop ;
2007-09-20 18:09:08 -04:00
: extend-selection ( pane -- )
hand-moved? [
2008-06-18 23:30:54 -04:00
dup selecting?>> [
hand-loc get 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
hand-click-loc get move-caret
2008-07-16 01:12:47 -04:00
caret>mark
2007-09-20 18:09:08 -04:00
] when
] if
2008-08-31 02:42:30 -04:00
dup dup 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-11-20 19:30:08 -05:00
t >>selecting?
2008-08-31 02:42:30 -04:00
dup mark>> [ caret>mark ] unless
hand-loc get move-caret
2007-09-20 18:09:08 -04:00
dup request-focus
com-copy-selection ;
: pane-menu ( pane -- ) { com-copy } show-commands-menu ;
2007-09-20 18:09:08 -04:00
pane H{
{ T{ button-down } [ begin-selection ] }
{ T{ button-down f { S+ } 1 } [ select-to-caret ] }
2008-11-22 03:24:17 -05:00
{ T{ button-up f { S+ } 1 } [ end-selection ] }
2007-09-20 18:09:08 -04:00
{ T{ button-up } [ end-selection ] }
{ T{ drag } [ extend-selection ] }
{ T{ copy-action } [ com-copy ] }
{ T{ button-down f f 3 } [ pane-menu ] }
2007-09-20 18:09:08 -04:00
} set-gestures