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

429 lines
11 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2009 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2009-02-14 22:53:39 -05:00
USING: arrays hashtables io kernel namespaces sequences
2009-02-11 05:53:33 -05:00
strings quotations math opengl combinators memoize math.vectors
sorting splitting assocs classes.tuple models continuations
2009-02-14 21:46:35 -05:00
destructors accessors math.rectangles fry fonts ui.pens.solid
ui.images ui.gadgets ui.gadgets.private ui.gadgets.borders
ui.gadgets.buttons ui.gadgets.labels ui.gadgets.scrollers
ui.gadgets.paragraphs ui.gadgets.incremental ui.gadgets.packs
ui.gadgets.menus ui.clipboards ui.gestures ui.traverse ui.render
ui.text ui.gadgets.presentations ui.gadgets.grids ui.gadgets.tracks
ui.gadgets.icons ui.gadgets.grid-lines ui.baseline-alignment
2009-03-16 21:11:36 -04:00
colors io.styles ;
2007-09-20 18:09:08 -04:00
IN: ui.gadgets.panes
TUPLE: pane < track
output current input last-line prototype scrolls?
selection-color caret mark selecting? ;
2007-09-20 18:09:08 -04:00
TUPLE: pane-stream pane ;
C: <pane-stream> pane-stream
2009-03-15 18:11:18 -04:00
M: pane-stream stream-element-type drop +character+ ;
<PRIVATE
: clear-selection ( pane -- pane )
f >>caret f >>mark ; inline
2007-09-20 18:09:08 -04:00
: prepare-last-line ( pane -- )
[ last-line>> ] keep
[ current>> f track-add ]
[ input>> [ 1 track-add ] when* ] bi
drop ; inline
: init-current ( pane -- pane )
dup prototype>> clone >>current ; inline
: focus-input ( pane -- )
input>> [ request-focus ] when* ;
: next-line ( pane -- )
clear-selection
[ input>> unparent ]
[ init-current prepare-last-line ]
[ focus-input ] tri ;
2007-09-20 18:09:08 -04:00
: pane-caret&mark ( pane -- caret mark )
[ caret>> ] [ mark>> ] bi ; inline
2007-09-20 18:09:08 -04:00
2009-04-02 10:09:09 -04:00
: selected-subtree ( pane -- seq )
2007-09-20 18:09:08 -04:00
[ pane-caret&mark sort-pair ] keep gadget-subtree ;
M: pane gadget-selection? pane-caret&mark and ;
M: pane gadget-selection ( pane -- string/f )
2009-04-02 10:09:09 -04:00
selected-subtree gadget-text ;
2007-09-20 18:09:08 -04:00
: init-prototype ( pane -- pane )
<shelf> +baseline+ >>align >>prototype ; inline
: init-output ( pane -- pane )
<incremental> [ >>output ] [ f track-add ] bi ; inline
: pane-theme ( pane -- pane )
1 >>fill
selection-color >>selection-color ; inline
: init-last-line ( pane -- pane )
horizontal <track> 0 >>fill +baseline+ >>align
2009-03-06 14:32:41 -05:00
[ >>last-line ] [ 1 track-add ] bi
dup prepare-last-line ; inline
2009-04-02 10:09:09 -04:00
M: pane selected-children
2007-09-20 18:09:08 -04:00
dup gadget-selection? [
2009-04-02 10:09:09 -04:00
[ selected-subtree leaves ]
[ selection-color>> ]
bi
] [ drop f f ] if ;
2007-09-20 18:09:08 -04:00
: 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
: 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 ;
: pane-nl ( pane -- )
[
[ current>> [ unparent ] [ smash-line ] bi ] [ output>> ] bi
add-incremental
] [ next-line ] bi ;
2007-09-20 18:09:08 -04:00
: ?pane-nl ( pane -- )
[ dup current>> children>> empty? [ pane-nl ] [ drop ] if ]
[ pane-nl ] bi ;
: smash-pane ( pane -- gadget ) [ pane-nl ] [ output>> smash-line ] bi ;
: pane-write ( seq pane -- )
[ pane-nl ] [ current>> stream-write ]
bi-curry interleave ;
2007-09-20 18:09:08 -04:00
: pane-format ( seq style pane -- )
[ nip pane-nl ] [ current>> stream-format ]
bi-curry bi-curry interleave ;
2007-09-20 18:09:08 -04:00
: do-pane-stream ( pane-stream quot -- )
[ pane>> ] dip keep scroll-pane ; inline
M: pane-stream stream-nl
[ pane-nl ] do-pane-stream ;
M: pane-stream stream-write1
[ current>> stream-write1 ] do-pane-stream ;
M: pane-stream stream-write
[ [ string-lines ] dip pane-write ] do-pane-stream ;
M: pane-stream stream-format
[ [ string-lines ] 2dip pane-format ] do-pane-stream ;
M: pane-stream dispose drop ;
M: pane-stream stream-flush drop ;
M: pane-stream make-span-stream
swap <style-stream> <ignore-close-stream> ;
PRIVATE>
: new-pane ( input class -- pane )
[ vertical ] dip new-track
swap >>input
pane-theme
init-prototype
init-output
init-current
init-last-line ; inline
: <pane> ( -- pane ) f pane new-pane ;
2007-09-20 18:09:08 -04:00
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 -- )
2009-01-25 18:55:27 -05:00
[ write-gadget ] [ nip stream-nl ] 2bi ;
2007-09-20 18:09:08 -04:00
: gadget. ( gadget -- )
output-stream get print-gadget ;
2007-09-20 18:09:08 -04:00
: pane-clear ( pane -- )
clear-selection
[ output>> clear-incremental ]
[ current>> clear-gadget ]
bi ;
2007-09-20 18:09:08 -04:00
: with-pane ( pane quot -- )
[ [ scroll>top ] [ pane-clear ] [ <pane-stream> ] tri ] dip
with-output-stream* ; inline
2007-09-20 18:09:08 -04:00
: make-pane ( quot -- gadget )
[ <pane> ] dip [ with-pane ] [ drop smash-pane ] 2bi ; inline
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 -- )
[ value>> ] [ dup quot>> ] bi*
'[ _ call( value -- ) ] with-pane ;
2007-11-13 18:51:10 -05:00
2007-09-20 18:09:08 -04:00
: <pane-control> ( model quot -- pane )
f pane-control new-pane
swap >>quot
swap >>model ;
2007-09-20 18:09:08 -04:00
! Character styles
<PRIVATE
2007-09-20 18:09:08 -04:00
MEMO: specified-font ( assoc -- font )
#! We memoize here to avoid creating lots of duplicate font objects.
[ monospace-font <font> ] dip
{
[ font-name swap at >>name ]
[
font-style swap at {
{ f [ ] }
{ plain [ ] }
{ bold [ t >>bold? ] }
{ italic [ t >>italic? ] }
{ bold-italic [ t >>bold? t >>italic? ] }
} case
]
[ font-size swap at >>size ]
[ foreground swap at >>foreground ]
[ background swap at >>background ]
} cleave
derive-font ;
2007-09-20 18:09:08 -04:00
: apply-font-style ( style gadget -- style gadget )
{ font-name font-style font-size foreground background }
pick extract-keys specified-font >>font ;
: apply-style ( style gadget key quot -- style gadget )
[ pick at ] dip when* ; inline
2007-09-20 18:09:08 -04:00
: apply-presentation-style ( style gadget -- style gadget )
presented [ <presentation> ] apply-style ;
2009-02-11 05:53:33 -05:00
: apply-image-style ( style gadget -- style gadget )
image [ nip <image-name> <icon> ] apply-style ;
: apply-background-style ( style gadget -- style gadget )
background [ <solid> >>interior ] apply-style ;
: style-label ( style gadget -- gadget )
2007-09-20 18:09:08 -04:00
apply-font-style
apply-background-style
2007-09-20 18:09:08 -04:00
apply-presentation-style
2009-02-11 05:53:33 -05:00
apply-image-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 )
2009-02-14 20:50:22 -05:00
border-color [ <solid> >>boundary ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-page-color-style ( style gadget -- style gadget )
2009-02-14 20:50:22 -05:00
page-color [ <solid> >>interior ] apply-style ;
2007-09-20 18:09:08 -04:00
: apply-border-width-style ( style gadget -- style gadget )
border-width [ dup 2array <border> ] 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
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 )
[ [ style>> ] [ pane>> smash-pane ] bi style-pane ] [ parent>> ] bi ;
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
2009-02-14 22:53:39 -05:00
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 drop ;
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 write-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 ;
2009-02-11 05:53:33 -05:00
: empty-output? ( string style -- ? )
[ empty? ] [ image swap key? not ] bi* and ;
2007-09-20 18:09:08 -04:00
: gadget-format ( string style stream -- )
2009-02-11 05:53:33 -05:00
[ [ empty-output? ] 2keep ] dip
'[ _ _ swap <styled-label> _ swap add-gadget drop ] unless ;
2007-09-20 18:09:08 -04:00
M: pack stream-format
gadget-format ;
M: paragraph stream-format
2009-02-11 05:53:33 -05:00
over { presented image } [ swap key? ] with any? [
2007-09-20 18:09:08 -04:00
gadget-format
] [
[ " " split ] 2dip
[ gadget-bl ] [ gadget-format ] bi-curry bi-curry
interleave
2007-09-20 18:09:08 -04:00
] if ;
: caret>mark ( pane -- )
dup caret>> >>mark 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*
children>> [ contains-point? ] 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 [ loc>> v- ] keep ;
2007-09-20 18:09:08 -04:00
: 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 -- )
over screen-loc v- over sloppy-pick-up >>caret
relayout-1 ;
2007-09-20 18:09:08 -04:00
2008-11-20 19:30:08 -05:00
: begin-selection ( pane -- )
f >>selecting?
dup 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? [
[
dup selecting?>> [
hand-loc get move-caret
] [
dup hand-clicked get child? [
t >>selecting?
[ hand-clicked set-global ]
[ hand-click-loc get move-caret ]
[ caret>mark ]
tri
] [ drop ] if
] if
] [ dup caret>> gadget-at-path scroll>gadget ] bi
] [ drop ] if ;
2007-09-20 18:09:08 -04:00
: end-selection ( pane -- )
2008-06-18 23:30:54 -04:00
f >>selecting?
hand-moved?
[ [ com-copy-selection ] [ request-focus ] bi ]
[ [ relayout-1 ] [ focus-input ] bi ]
if ;
2007-09-20 18:09:08 -04:00
: select-to-caret ( pane -- )
2008-11-20 19:30:08 -05:00
t >>selecting?
[ dup mark>> [ dup caret>mark ] unless hand-loc get move-caret ]
[ com-copy-selection ]
[ request-focus ]
tri ;
2007-09-20 18:09:08 -04:00
: pane-menu ( pane -- ) { com-copy } show-commands-menu ;
PRIVATE>
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 ] }
{ copy-action [ com-copy ] }
{ T{ button-down f f 3 } [ pane-menu ] }
2007-09-20 18:09:08 -04:00
} set-gestures