graft*/ungraft* refactoring

release
Slava Pestov 2007-11-16 01:19:13 -05:00
parent d8a0c08de9
commit cef837184b
26 changed files with 371 additions and 155 deletions

16
extra/tools/test/ui/ui.factor Executable file
View File

@ -0,0 +1,16 @@
USING: dlists ui.gadgets kernel ui namespaces io.streams.string
io ;
IN: tools.test.ui
! We can't print to stdio here because that might be a pane
! stream, and our graft-queue rebinding here would be captured
! by code adding children to the pane...
: with-grafted-gadget ( gadget quot -- )
[
<dlist> \ graft-queue [
over
graft notify-queued
swap slip
ungraft notify-queued
] with-variable
] string-out print ;

1
extra/ui/cocoa/cocoa.factor Normal file → Executable file
View File

@ -62,7 +62,6 @@ M: cocoa-ui-backend set-title ( string world -- )
M: cocoa-ui-backend (open-world-window) ( world -- ) M: cocoa-ui-backend (open-world-window) ( world -- )
dup gadget-window dup gadget-window
dup start-world
dup auto-position dup auto-position
world-handle second f -> makeKeyAndOrderFront: ; world-handle second f -> makeKeyAndOrderFront: ;

View File

@ -1,6 +1,7 @@
IN: temporary IN: temporary
USING: ui.commands ui.gadgets.buttons ui.gadgets.labels USING: ui.commands ui.gadgets.buttons ui.gadgets.labels
ui.gadgets tools.test namespaces sequences kernel models ; ui.gadgets tools.test namespaces sequences kernel models
tools.test.inference ;
TUPLE: foo-gadget ; TUPLE: foo-gadget ;
@ -27,6 +28,12 @@ T{ foo-gadget } <toolbar> "t" set
} <radio-buttons> "religion" set } <radio-buttons> "religion" set
] unit-test ] unit-test
{ 2 1 } [ <radio-buttons> ] unit-test-effect
{ 2 1 } [ <toggle-buttons> ] unit-test-effect
{ 2 1 } [ <checkbox> ] unit-test-effect
[ 0 ] [ [ 0 ] [
"religion" get gadget-child radio-control-value "religion" get gadget-child radio-control-value
] unit-test ] unit-test

5
extra/ui/gadgets/editors/editors-tests.factor Normal file → Executable file
View File

@ -1,6 +1,7 @@
USING: ui.gadgets.editors tools.test kernel io io.streams.plain USING: ui.gadgets.editors tools.test kernel io io.streams.plain
io.streams.string definitions namespaces ui.gadgets io.streams.string definitions namespaces ui.gadgets
ui.gadgets.grids prettyprint documents ui.gestures ; ui.gadgets.grids prettyprint documents ui.gestures
tools.test.inference ;
[ t ] [ [ t ] [
<editor> "editor" set <editor> "editor" set
@ -36,3 +37,5 @@ ui.gadgets.grids prettyprint documents ui.gestures ;
"editor" get position-caret "editor" get position-caret
"editor" get ungraft* "editor" get ungraft*
] unit-test ] unit-test
{ 0 1 } [ <editor> ] unit-test-effect

View File

@ -2,10 +2,9 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays documents ui.clipboards ui.commands ui.gadgets USING: arrays documents ui.clipboards ui.commands ui.gadgets
ui.gadgets.borders ui.gadgets.buttons ui.gadgets.labels ui.gadgets.borders ui.gadgets.buttons ui.gadgets.labels
ui.gadgets.scrollers ui.gadgets.theme ui.gadgets.scrollers ui.gadgets.theme ui.render ui.gestures io
ui.render ui.gestures io kernel math models namespaces opengl kernel math models namespaces opengl opengl.gl sequences strings
opengl.gl sequences strings io.styles math.vectors sorting io.styles math.vectors sorting colors combinators ;
colors combinators ;
IN: ui.gadgets.editors IN: ui.gadgets.editors
TUPLE: editor TUPLE: editor
@ -129,7 +128,7 @@ M: editor model-changed
line-height 0 swap 2array ; line-height 0 swap 2array ;
: scroll>caret ( editor -- ) : scroll>caret ( editor -- )
dup gadget-grafted? [ dup gadget-status second [
dup caret-loc over caret-dim { 1 0 } v+ <rect> dup caret-loc over caret-dim { 1 0 } v+ <rect>
over scroll>rect over scroll>rect
] when drop ; ] when drop ;

96
extra/ui/gadgets/gadgets-tests.factor Normal file → Executable file
View File

@ -1,6 +1,8 @@
IN: temporary IN: temporary
USING: ui.gadgets ui.gadgets.packs ui.gadgets.worlds tools.test USING: ui.gadgets ui.gadgets.packs ui.gadgets.worlds tools.test
namespaces models kernel ; namespaces models kernel tools.test.inference dlists math
math.parser ui sequences hashtables assocs io arrays
prettyprint io.streams.string ;
[ T{ rect f { 10 10 } { 20 20 } } ] [ T{ rect f { 10 10 } { 20 20 } } ]
[ [
@ -108,3 +110,95 @@ C: <fooey> fooey
{ 1 1 } "g4" get set-rect-dim { 1 1 } "g4" get set-rect-dim
[ t ] [ { 25 25 } "g1" get pick-up "g4" get eq? ] unit-test [ t ] [ { 25 25 } "g1" get pick-up "g4" get eq? ] unit-test
TUPLE: mock-gadget graft-called ungraft-called ;
: <mock-gadget>
0 0 mock-gadget construct-boa <gadget> over set-delegate ;
M: mock-gadget graft*
dup mock-gadget-graft-called 1+
swap set-mock-gadget-graft-called ;
M: mock-gadget ungraft*
dup mock-gadget-ungraft-called 1+
swap set-mock-gadget-ungraft-called ;
! We can't print to stdio here because that might be a pane
! stream, and our graft-queue rebinding here would be captured
! by code adding children to the pane...
[
<dlist> \ graft-queue [
[ ] [ <mock-gadget> dup queue-graft unqueue-graft ] unit-test
[ t ] [ graft-queue dlist-empty? ] unit-test
] with-variable
<dlist> \ graft-queue [
[ t ] [ graft-queue dlist-empty? ] unit-test
<mock-gadget> "g" set
[ ] [ "g" get queue-graft ] unit-test
[ f ] [ graft-queue dlist-empty? ] unit-test
[ { f t } ] [ "g" get gadget-status ] unit-test
[ ] [ "g" get graft-later ] unit-test
[ { f t } ] [ "g" get gadget-status ] unit-test
[ ] [ "g" get ungraft-later ] unit-test
[ { f f } ] [ "g" get gadget-status ] unit-test
[ t ] [ graft-queue dlist-empty? ] unit-test
[ ] [ "g" get ungraft-later ] unit-test
[ ] [ "g" get graft-later ] unit-test
[ ] [ notify-queued ] unit-test
[ { t t } ] [ "g" get gadget-status ] unit-test
[ t ] [ graft-queue dlist-empty? ] unit-test
[ ] [ "g" get graft-later ] unit-test
[ 1 ] [ "g" get mock-gadget-graft-called ] unit-test
[ ] [ "g" get ungraft-later ] unit-test
[ { t f } ] [ "g" get gadget-status ] unit-test
[ ] [ notify-queued ] unit-test
[ 1 ] [ "g" get mock-gadget-ungraft-called ] unit-test
[ { f f } ] [ "g" get gadget-status ] unit-test
] with-variable
: add-some-children
3 [
<mock-gadget> over <model> over set-gadget-model
dup "g" get add-gadget
swap 1+ number>string set
] each ;
: status-flags
{ "g" "1" "2" "3" } [ get gadget-status ] map prune ;
: notify-combo ( ? ? -- )
nl "===== Combo: " write 2dup 2array . nl
<dlist> \ graft-queue [
<mock-gadget> "g" set
[ ] [ add-some-children ] unit-test
[ V{ { f f } } ] [ status-flags ] unit-test
[ ] [ "g" get graft ] unit-test
[ V{ { f t } } ] [ status-flags ] unit-test
dup [ [ ] [ notify-queued ] unit-test ] when
[ ] [ "g" get clear-gadget ] unit-test
[ [ 1 ] [ graft-queue dlist-length ] unit-test ] unless
[ [ ] [ notify-queued ] unit-test ] when
[ ] [ add-some-children ] unit-test
[ { f t } ] [ "1" get gadget-status ] unit-test
[ { f t } ] [ "2" get gadget-status ] unit-test
[ { f t } ] [ "3" get gadget-status ] unit-test
[ ] [ [ "x" print notify ] graft-queue swap dlist-slurp ] unit-test
[ ] [ notify-queued ] unit-test
[ V{ { t t } } ] [ status-flags ] unit-test
] with-variable ;
{ { f f } { f t } { t f } { t t } } [ notify-combo ] assoc-each
] string-out print
{ 0 1 } [ <gadget> ] unit-test-effect
{ 1 0 } [ unparent ] unit-test-effect
{ 2 0 } [ add-gadget ] unit-test-effect
{ 2 0 } [ add-gadgets ] unit-test-effect
{ 1 0 } [ clear-gadget ] unit-test-effect
{ 1 0 } [ relayout ] unit-test-effect
{ 1 0 } [ relayout-1 ] unit-test-effect
{ 1 1 } [ pref-dim ] unit-test-effect

View File

@ -42,7 +42,7 @@ M: array rect-dim drop { 0 0 } ;
TUPLE: gadget TUPLE: gadget
pref-dim parent children orientation state focus pref-dim parent children orientation state focus
visible? root? clipped? grafted? visible? root? clipped? status
interior boundary interior boundary
model ; model ;
@ -59,10 +59,11 @@ M: gadget model-changed drop ;
: <zero-rect> ( -- rect ) { 0 0 } dup <rect> ; : <zero-rect> ( -- rect ) { 0 0 } dup <rect> ;
: <gadget> ( -- gadget ) : <gadget> ( -- gadget )
<zero-rect> { 0 1 } t { <zero-rect> { 0 1 } t { f f } {
set-delegate set-delegate
set-gadget-orientation set-gadget-orientation
set-gadget-visible? set-gadget-visible?
set-gadget-status
} gadget construct ; } gadget construct ;
: construct-gadget ( class -- tuple ) : construct-gadget ( class -- tuple )
@ -173,13 +174,13 @@ M: array gadget-text*
: forget-pref-dim ( gadget -- ) f swap set-gadget-pref-dim ; : forget-pref-dim ( gadget -- ) f swap set-gadget-pref-dim ;
: invalid ( -- queue ) \ invalid get-global ; : layout-queue ( -- queue ) \ layout-queue get ;
: add-invalid ( gadget -- ) : layout-later ( gadget -- )
#! When unit testing gadgets without the UI running, the #! When unit testing gadgets without the UI running, the
#! invalid queue is not initialized and we simply ignore #! invalid queue is not initialized and we simply ignore
#! invalidation requests. #! invalidation requests.
invalid [ push-front ] [ drop ] if* ; layout-queue [ push-front ] [ drop ] if* ;
DEFER: relayout DEFER: relayout
@ -187,7 +188,7 @@ DEFER: relayout
\ invalidate* over set-gadget-state \ invalidate* over set-gadget-state
dup forget-pref-dim dup forget-pref-dim
dup gadget-root? dup gadget-root?
[ add-invalid ] [ gadget-parent [ relayout ] when* ] if ; [ layout-later ] [ gadget-parent [ relayout ] when* ] if ;
: relayout ( gadget -- ) : relayout ( gadget -- )
dup gadget-state \ invalidate* eq? dup gadget-state \ invalidate* eq?
@ -195,7 +196,7 @@ DEFER: relayout
: relayout-1 ( gadget -- ) : relayout-1 ( gadget -- )
dup gadget-state dup gadget-state
[ drop ] [ dup invalidate add-invalid ] if ; [ drop ] [ dup invalidate layout-later ] if ;
: show-gadget t swap set-gadget-visible? ; : show-gadget t swap set-gadget-visible? ;
@ -241,27 +242,70 @@ M: gadget layout* drop ;
dup [ layout ] each-child dup [ layout ] each-child
] when drop ; ] when drop ;
: graft-queue \ graft-queue get ;
: unqueue-graft ( gadget -- )
dup graft-queue dlist-delete [ "Not queued" throw ] unless
dup gadget-status first { t t } { f f } ?
swap set-gadget-status ;
: queue-graft ( gadget -- )
{ f t } over set-gadget-status
graft-queue push-front ;
: queue-ungraft ( gadget -- )
{ t f } over set-gadget-status
graft-queue push-front ;
: graft-later ( gadget -- )
dup gadget-status {
{ { f t } [ drop ] }
{ { t t } [ drop ] }
{ { t f } [ unqueue-graft ] }
{ { f f } [ queue-graft ] }
} case ;
: ungraft-later ( gadget -- )
dup gadget-status {
{ { f f } [ drop ] }
{ { t f } [ drop ] }
{ { f t } [ unqueue-graft ] }
{ { t t } [ queue-ungraft ] }
} case ;
GENERIC: graft* ( gadget -- ) GENERIC: graft* ( gadget -- )
M: gadget graft* drop ; M: gadget graft* drop ;
! : graft ( gadget -- )
! dup gadget-grafted? [
! drop
! ] [
! t over set-gadget-grafted?
! dup graft*
! dup activate-control
! [ graft ] each-child
! ] if ;
: graft ( gadget -- ) : graft ( gadget -- )
t over set-gadget-grafted? dup graft-later [ graft ] each-child ;
dup graft*
dup activate-control
[ graft ] each-child ;
GENERIC: ungraft* ( gadget -- ) GENERIC: ungraft* ( gadget -- )
M: gadget ungraft* drop ; M: gadget ungraft* drop ;
! : ungraft ( gadget -- )
! dup gadget-grafted? [
! dup [ ungraft ] each-child
! dup deactivate-control
! dup ungraft*
! f swap set-gadget-grafted?
! ] [
! drop ! "Fuck you" throw
! ] if ;
: ungraft ( gadget -- ) : ungraft ( gadget -- )
dup gadget-grafted? [ dup [ ungraft ] each-child ungraft-later ;
dup [ ungraft ] each-child
dup deactivate-control
dup ungraft*
f over set-gadget-grafted?
] when drop ;
: (unparent) ( gadget -- ) : (unparent) ( gadget -- )
dup ungraft dup ungraft
@ -272,7 +316,14 @@ M: gadget ungraft* drop ;
tuck gadget-focus eq? tuck gadget-focus eq?
[ f swap set-gadget-focus ] [ drop ] if ; [ f swap set-gadget-focus ] [ drop ] if ;
SYMBOL: in-layout?
: not-in-layout
in-layout? get
[ "Cannot add/remove gadgets in layout*" throw ] when ;
: unparent ( gadget -- ) : unparent ( gadget -- )
not-in-layout
[ [
dup gadget-parent dup [ dup gadget-parent dup [
over (unparent) over (unparent)
@ -290,6 +341,7 @@ M: gadget ungraft* drop ;
f swap set-gadget-children ; f swap set-gadget-children ;
: clear-gadget ( gadget -- ) : clear-gadget ( gadget -- )
not-in-layout
dup (clear-gadget) relayout ; dup (clear-gadget) relayout ;
: ((add-gadget)) ( gadget box -- ) : ((add-gadget)) ( gadget box -- )
@ -299,12 +351,14 @@ M: gadget ungraft* drop ;
over unparent over unparent
dup pick set-gadget-parent dup pick set-gadget-parent
[ ((add-gadget)) ] 2keep [ ((add-gadget)) ] 2keep
gadget-grafted? [ graft ] [ drop ] if ; gadget-status second [ graft ] [ drop ] if ;
: add-gadget ( gadget parent -- ) : add-gadget ( gadget parent -- )
not-in-layout
[ (add-gadget) ] keep relayout ; [ (add-gadget) ] keep relayout ;
: add-gadgets ( seq parent -- ) : add-gadgets ( seq parent -- )
not-in-layout
swap [ over (add-gadget) ] each relayout ; swap [ over (add-gadget) ] each relayout ;
: parents ( gadget -- seq ) : parents ( gadget -- seq )

2
extra/ui/gadgets/incremental/incremental.factor Normal file → Executable file
View File

@ -42,6 +42,7 @@ M: incremental pref-dim*
dup forget-pref-dim dup pref-dim over set-rect-dim layout ; dup forget-pref-dim dup pref-dim over set-rect-dim layout ;
: add-incremental ( gadget incremental -- ) : add-incremental ( gadget incremental -- )
not-in-layout
2dup (add-gadget) 2dup (add-gadget)
over prefer-incremental over prefer-incremental
2dup incremental-loc 2dup incremental-loc
@ -50,6 +51,7 @@ M: incremental pref-dim*
gadget-parent [ invalidate* ] when* ; gadget-parent [ invalidate* ] when* ;
: clear-incremental ( incremental -- ) : clear-incremental ( incremental -- )
not-in-layout
dup (clear-gadget) dup forget-pref-dim dup (clear-gadget) dup forget-pref-dim
{ 0 0 } over set-incremental-cursor { 0 0 } over set-incremental-cursor
gadget-parent [ relayout ] when* ; gadget-parent [ relayout ] when* ;

7
extra/ui/gadgets/panes/panes-tests.factor Normal file → Executable file
View File

@ -1,7 +1,8 @@
IN: temporary IN: temporary
USING: alien ui.gadgets.panes ui.gadgets namespaces USING: alien ui.gadgets.panes ui.gadgets namespaces
kernel sequences io io.streams.string tools.test prettyprint kernel sequences io io.streams.string tools.test prettyprint
definitions help help.syntax help.markup splitting ; definitions help help.syntax help.markup splitting
tools.test.ui models ;
: #children "pane" get gadget-children length ; : #children "pane" get gadget-children length ;
@ -33,3 +34,7 @@ ARTICLE: "test-article" "This is a test article"
<pane> [ \ = see ] with-pane <pane> [ \ = see ] with-pane
<pane> [ \ = help ] with-pane <pane> [ \ = help ] with-pane
[ ] [
\ = <model> [ see ] <pane-control> [ ] with-grafted-gadget
] unit-test

View File

@ -2,7 +2,8 @@ IN: temporary
USING: ui.gadgets ui.gadgets.scrollers USING: ui.gadgets ui.gadgets.scrollers
namespaces tools.test kernel models ui.gadgets.viewports namespaces tools.test kernel models ui.gadgets.viewports
ui.gadgets.labels ui.gadgets.grids ui.gadgets.frames ui.gadgets.labels ui.gadgets.grids ui.gadgets.frames
ui.gadgets.sliders math math.vectors arrays sequences ; ui.gadgets.sliders math math.vectors arrays sequences
tools.test.inference tools.test.ui ;
[ ] [ [ ] [
<gadget> "g" set <gadget> "g" set
@ -23,9 +24,11 @@ ui.gadgets.sliders math math.vectors arrays sequences ;
<viewport> "v" set <viewport> "v" set
] unit-test ] unit-test
"v" get [
[ { 10 20 } ] [ "v" get gadget-model range-value ] unit-test [ { 10 20 } ] [ "v" get gadget-model range-value ] unit-test
[ { 10 20 } ] [ "g" get rect-loc vneg { 3 3 } v+ ] unit-test [ { 10 20 } ] [ "g" get rect-loc vneg { 3 3 } v+ ] unit-test
] with-grafted-gadget
[ ] [ [ ] [
<gadget> { 100 100 } over set-rect-dim <gadget> { 100 100 } over set-rect-dim
@ -36,8 +39,7 @@ ui.gadgets.sliders math math.vectors arrays sequences ;
[ ] [ "s" get layout ] unit-test [ ] [ "s" get layout ] unit-test
[ ] [ "s" get graft ] unit-test "s" get [
[ { 34 34 } ] [ "s" get scroller-viewport rect-dim ] unit-test [ { 34 34 } ] [ "s" get scroller-viewport rect-dim ] unit-test
[ { 106 106 } ] [ "s" get scroller-viewport viewport-dim ] unit-test [ { 106 106 } ] [ "s" get scroller-viewport viewport-dim ] unit-test
@ -55,8 +57,7 @@ ui.gadgets.sliders math math.vectors arrays sequences ;
[ { 10 20 } ] [ "s" get scroller-viewport gadget-model range-value ] unit-test [ { 10 20 } ] [ "s" get scroller-viewport gadget-model range-value ] unit-test
[ { 10 20 } ] [ "g" get rect-loc vneg { 3 3 } v+ ] unit-test [ { 10 20 } ] [ "g" get rect-loc vneg { 3 3 } v+ ] unit-test
] with-grafted-gadget
[ ] [ "s" get ungraft ] unit-test
<gadget> { 600 400 } over set-rect-dim "g1" set <gadget> { 600 400 } over set-rect-dim "g1" set
<gadget> { 600 10 } over set-rect-dim "g2" set <gadget> { 600 10 } over set-rect-dim "g2" set
@ -84,3 +85,5 @@ dup layout
[ f ] [ "s" get scroller-viewport find-scroller* ] unit-test [ f ] [ "s" get scroller-viewport find-scroller* ] unit-test
[ t ] [ "s" get @right grid-child slider? ] unit-test [ t ] [ "s" get @right grid-child slider? ] unit-test
[ f ] [ "s" get @right grid-child find-scroller* ] unit-test [ f ] [ "s" get @right grid-child find-scroller* ] unit-test
{ 1 1 } [ <scroller> ] unit-test-effect

View File

@ -28,7 +28,7 @@ scroller H{
{ T{ mouse-scroll } [ do-mouse-scroll ] } { T{ mouse-scroll } [ do-mouse-scroll ] }
} set-gestures } set-gestures
: viewport, ( -- ) : viewport, ( child -- )
g gadget-model <viewport> g gadget-model <viewport>
g-> set-scroller-viewport @center frame, ; g-> set-scroller-viewport @center frame, ;
@ -106,7 +106,7 @@ scroller H{
dup scroller-viewport viewport-dim { 0 1 } v* swap scroll ; dup scroller-viewport viewport-dim { 0 1 } v* swap scroll ;
: scroll>bottom ( gadget -- ) : scroll>bottom ( gadget -- )
find-scroller* [ find-scroller [
t over set-scroller-follows relayout-1 t over set-scroller-follows relayout-1
] when* ; ] when* ;

View File

@ -131,7 +131,7 @@ M: elevator layout*
: slide-by-line ( amount slider -- ) : slide-by-line ( amount slider -- )
[ slider-line * ] keep slide-by ; [ slider-line * ] keep slide-by ;
: <slide-button> ( vector polygon amount -- ) : <slide-button> ( vector polygon amount -- button )
>r gray swap <polygon-gadget> r> >r gray swap <polygon-gadget> r>
[ swap find-slider slide-by-line ] curry <repeat-button> [ swap find-slider slide-by-line ] curry <repeat-button>
[ set-gadget-orientation ] keep ; [ set-gadget-orientation ] keep ;
@ -144,7 +144,7 @@ M: elevator layout*
: <left-button> { 0 1 } arrow-left -1 <slide-button> ; : <left-button> { 0 1 } arrow-left -1 <slide-button> ;
: <right-button> { 0 1 } arrow-right 1 <slide-button> ; : <right-button> { 0 1 } arrow-right 1 <slide-button> ;
: build-x-slider ( slider -- slider ) : build-x-slider ( slider -- )
[ [
<left-button> @left frame, <left-button> @left frame,
{ 0 1 } elevator, { 0 1 } elevator,
@ -154,7 +154,7 @@ M: elevator layout*
: <up-button> { 1 0 } arrow-up -1 <slide-button> ; : <up-button> { 1 0 } arrow-up -1 <slide-button> ;
: <down-button> { 1 0 } arrow-down 1 <slide-button> ; : <down-button> { 1 0 } arrow-down 1 <slide-button> ;
: build-y-slider ( slider -- slider ) : build-y-slider ( slider -- )
[ [
<up-button> @top frame, <up-button> @top frame,
{ 1 0 } elevator, { 1 0 } elevator,

View File

@ -16,8 +16,7 @@ TUPLE: viewport ;
: <viewport> ( content model -- viewport ) : <viewport> ( content model -- viewport )
<gadget> viewport construct-control <gadget> viewport construct-control
t over set-gadget-clipped? t over set-gadget-clipped?
[ add-gadget ] keep [ add-gadget ] keep ;
[ model-changed ] keep ;
M: viewport layout* M: viewport layout*
dup rect-dim viewport-gap 2 v*n v- dup rect-dim viewport-gap 2 v*n v-

11
extra/ui/gadgets/worlds/worlds.factor Normal file → Executable file
View File

@ -112,12 +112,6 @@ world H{
{ T{ button-up f { A+ } 1 } [ T{ button-up f f 2 } swap resend-button-up ] } { T{ button-up f { A+ } 1 } [ T{ button-up f f 2 } swap resend-button-up ] }
} set-gestures } set-gestures
: start-world ( world -- )
dup graft
dup relayout
dup world-title over set-title
request-focus ;
: close-global ( world global -- ) : close-global ( world global -- )
dup get-global find-world rot eq? dup get-global find-world rot eq?
[ f swap set-global ] [ drop ] if ; [ f swap set-global ] [ drop ] if ;
@ -126,3 +120,8 @@ world H{
drop-prefix <reversed> drop-prefix <reversed>
T{ lose-focus } swap each-gesture T{ lose-focus } swap each-gesture
T{ gain-focus } swap each-gesture ; T{ gain-focus } swap each-gesture ;
M: world graft*
dup (open-world-window)
dup world-title over set-title
request-focus ;

2
extra/ui/render/render-docs.factor Normal file → Executable file
View File

@ -13,9 +13,9 @@ HELP: gadget
{ { $link gadget-visible? } " - a boolean indicating if the gadget should display and receive user input." } { { $link gadget-visible? } " - a boolean indicating if the gadget should display and receive user input." }
{ { $link gadget-root? } " - if set to " { $link t } ", layout changes in this gadget will not propagate to the gadget's parent." } { { $link gadget-root? } " - if set to " { $link t } ", layout changes in this gadget will not propagate to the gadget's parent." }
{ { $link gadget-clipped? } " - a boolean indicating if clipping will be enabled when drawing this gadget's children." } { { $link gadget-clipped? } " - a boolean indicating if clipping will be enabled when drawing this gadget's children." }
{ { $link gadget-grafted? } " - if set to " { $link t } ", the gadget is parented in a native window." }
{ { $link gadget-interior } " - an object whose class implements the " { $link draw-interior } " generic word." } { { $link gadget-interior } " - an object whose class implements the " { $link draw-interior } " generic word." }
{ { $link gadget-boundary } " - an object whose class implements the " { $link draw-boundary } " generic word." } { { $link gadget-boundary } " - an object whose class implements the " { $link draw-boundary } " generic word." }
{ { $link gadget-model } " - XXX" }
} }
"Gadgets delegate to " { $link rect } " instances holding their location and dimensions." } "Gadgets delegate to " { $link rect } " instances holding their location and dimensions." }
{ $notes { $notes

View File

@ -0,0 +1,6 @@
IN: temporary
USING: tools.test tools.test.ui ui.tools.browser
tools.test.inference ;
{ 0 1 } [ <browser-gadget> ] unit-test-effect
[ ] [ <browser-gadget> [ ] with-grafted-gadget ] unit-test

View File

@ -1,15 +1,18 @@
USING: continuations documents ui.tools.interactor USING: continuations documents ui.tools.interactor
ui.tools.listener hashtables kernel namespaces parser sequences ui.tools.listener hashtables kernel namespaces parser sequences
timers tools.test ui.commands ui.gadgets ui.gadgets.editors timers tools.test ui.commands ui.gadgets ui.gadgets.editors
ui.gadgets.panes vocabs words ; ui.gadgets.panes vocabs words tools.test.ui ;
IN: temporary IN: temporary
timers [ init-timers ] unless timers [ init-timers ] unless
[ f ] [ "word" source-editor command-map empty? ] unit-test [ f ] [ "word" source-editor command-map empty? ] unit-test
<listener-gadget> "listener" set [ ] [ <listener-gadget> [ ] with-grafted-gadget ] unit-test
[ ] [ <listener-gadget> "listener" set ] unit-test
"listener" get [
{ "kernel" } [ vocab-words ] map use associate { "kernel" } [ vocab-words ] map use associate
"listener" get listener-gadget-input set-interactor-vars "listener" get listener-gadget-input set-interactor-vars
@ -33,3 +36,4 @@ H{ } "i" get set-interactor-vars
"i" get gadget-model doc-end "i" get gadget-model doc-end
"i" get editor-caret* = "i" get editor-caret* =
] unit-test ] unit-test
] with-grafted-gadget

View File

@ -1,7 +1,7 @@
USING: assocs ui.tools.search help.topics io.files io.styles USING: assocs ui.tools.search help.topics io.files io.styles
kernel namespaces sequences source-files threads timers kernel namespaces sequences source-files threads timers
tools.test ui.gadgets ui.gestures vocabs tools.test ui.gadgets ui.gestures vocabs
vocabs.loader words ; vocabs.loader words tools.test.ui debugger ;
IN: temporary IN: temporary
timers get [ init-timers ] unless timers get [ init-timers ] unless
@ -12,12 +12,16 @@ timers get [ init-timers ] unless
T{ key-down f { C+ } "x" } swap search-gesture T{ key-down f { C+ } "x" } swap search-gesture
] unit-test ] unit-test
: assert-non-empty empty? f assert= ;
: update-live-search ( search -- seq )
dup [
300 sleep do-timers
live-search-list control-value
] with-grafted-gadget ;
: test-live-search ( gadget quot -- ? ) : test-live-search ( gadget quot -- ? )
>r dup graft 300 sleep do-timers >r update-live-search dup assert-non-empty r> all? ;
dup live-search-list control-value
dup empty? [ "Empty" throw ] when
r> all?
>r ungraft r> ;
[ t ] [ [ t ] [
"swp" all-words f <definition-search> "swp" all-words f <definition-search>
@ -26,11 +30,12 @@ timers get [ init-timers ] unless
[ t ] [ [ t ] [
"" all-words t <definition-search> "" all-words t <definition-search>
dup graft dup [
{ "set-word-prop" } over live-search-field set-control-value { "set-word-prop" } over live-search-field set-control-value
300 sleep 300 sleep
do-timers do-timers
search-value \ set-word-prop eq? search-value \ set-word-prop eq?
] with-grafted-gadget
] unit-test ] unit-test
[ t ] [ [ t ] [

View File

@ -2,7 +2,7 @@ USING: ui.tools ui.tools.interactor ui.tools.listener
ui.tools.search ui.tools.workspace kernel models namespaces ui.tools.search ui.tools.workspace kernel models namespaces
sequences timers tools.test ui.gadgets ui.gadgets.buttons sequences timers tools.test ui.gadgets ui.gadgets.buttons
ui.gadgets.labelled ui.gadgets.presentations ui.gadgets.labelled ui.gadgets.presentations
ui.gadgets.scrollers vocabs ; ui.gadgets.scrollers vocabs tools.test.ui ui ;
IN: temporary IN: temporary
[ [
@ -31,18 +31,22 @@ timers get [ init-timers ] unless
"w" get hide-popup "w" get hide-popup
] unit-test ] unit-test
[ ] [ [ ] [ <workspace> [ ] with-grafted-gadget ] unit-test
<workspace> "w" set
"w" get graft
"w" get "kernel" vocab show-vocab-words
] unit-test
"w" get workspace-popup closable-gadget-content "w" get [
live-search-list gadget-child "p" set
[ ] [ "w" get "kernel" vocab show-vocab-words ] unit-test
[ ] [ notify-queued ] unit-test
[ ] [ "w" get workspace-popup closable-gadget-content
live-search-list gadget-child "p" set ] unit-test
[ t ] [ "p" get presentation? ] unit-test [ t ] [ "p" get presentation? ] unit-test
"p" get <operations-menu> gadget-child gadget-child "c" set [ ] [ "p" get <operations-menu> gadget-child gadget-child "c" set ] unit-test
[ ] [ notify-queued ] unit-test
[ t ] [ "c" get button? ] unit-test [ t ] [ "c" get button? ] unit-test
@ -51,4 +55,5 @@ live-search-list gadget-child "p" set
3 handle-parse-error 3 handle-parse-error
] unit-test ] unit-test
[ ] [ "w" get ungraft ] unit-test [ ] [ notify-queued ] unit-test
] with-grafted-gadget

View File

@ -12,15 +12,6 @@ vocabs.loader tools.test ui.gadgets.buttons
ui.gadgets.status-bar mirrors ; ui.gadgets.status-bar mirrors ;
IN: ui.tools IN: ui.tools
: workspace-tabs ( -- seq )
{
<stack-display>
<browser-gadget>
<inspector-gadget>
<walker>
<profiler-gadget>
} ;
: <workspace-tabs> ( -- tabs ) : <workspace-tabs> ( -- tabs )
g gadget-model g gadget-model
"tool-switching" workspace command-map "tool-switching" workspace command-map
@ -28,7 +19,13 @@ IN: ui.tools
<toggle-buttons> ; <toggle-buttons> ;
: <workspace-book> ( -- gadget ) : <workspace-book> ( -- gadget )
workspace-tabs [ execute ] map g gadget-model <book> ; [
<stack-display> ,
<browser-gadget> ,
<inspector-gadget> ,
<walker> ,
<profiler-gadget> ,
] { } make g gadget-model <book> ;
: <workspace> ( -- workspace ) : <workspace> ( -- workspace )
0 <model> { 0 1 } <track> workspace construct-control [ 0 <model> { 0 1 } <track> workspace construct-control [

View File

@ -5,15 +5,15 @@ ui.commands ui.gadgets ui.gadgets.labelled
ui.gadgets.tracks ui.gestures ; ui.gadgets.tracks ui.gestures ;
IN: ui.tools.traceback IN: ui.tools.traceback
: <callstack-display> ( model -- ) : <callstack-display> ( model -- gadget )
[ [ continuation-call callstack. ] when* ] [ [ continuation-call callstack. ] when* ]
"Call stack" <labelled-pane> ; "Call stack" <labelled-pane> ;
: <datastack-display> ( model -- ) : <datastack-display> ( model -- gadget )
[ [ continuation-data stack. ] when* ] [ [ continuation-data stack. ] when* ]
"Data stack" <labelled-pane> ; "Data stack" <labelled-pane> ;
: <retainstack-display> ( model -- ) : <retainstack-display> ( model -- gadget )
[ [ continuation-retain stack. ] when* ] [ [ continuation-retain stack. ] when* ]
"Retain stack" <labelled-pane> ; "Retain stack" <labelled-pane> ;

View File

@ -0,0 +1,4 @@
IN: temporary
USING: tools.test tools.test.inference ui.tools ;
{ 0 1 } [ <workspace> ] unit-test-effect

6
extra/ui/ui-docs.factor Normal file → Executable file
View File

@ -18,11 +18,6 @@ HELP: find-window
{ $values { "quot" "a quotation with stack effect " { $snippet "( world -- ? )" } } { "world" "a " { $link world } " or " { $link f } } } { $values { "quot" "a quotation with stack effect " { $snippet "( world -- ? )" } } { "world" "a " { $link world } " or " { $link f } } }
{ $description "Finds a native window whose world satisfies the quotation, outputting " { $link f } " if no such world could be found. The front-most native window is checked first." } ; { $description "Finds a native window whose world satisfies the quotation, outputting " { $link f } " if no such world could be found. The front-most native window is checked first." } ;
HELP: start-world
{ $values { "world" world } }
{ $description "Starts a world." }
{ $notes "This word should be called by the UI backend after " { $link register-window } ", but before making the world's containing window visible on the screen." } ;
HELP: register-window HELP: register-window
{ $values { "world" world } { "handle" "a baackend-specific handle" } } { $values { "world" world } { "handle" "a baackend-specific handle" } }
{ $description "Adds a window to the global " { $link windows } " variable." } { $description "Adds a window to the global " { $link windows } " variable." }
@ -174,7 +169,6 @@ ARTICLE: "ui-backend-windows" "UI backend window management"
{ $subsection open-world-window } { $subsection open-world-window }
"This word should create a native window, store some kind of handle in the " { $link world-handle } " slot, then call two words:" "This word should create a native window, store some kind of handle in the " { $link world-handle } " slot, then call two words:"
{ $subsection register-window } { $subsection register-window }
{ $subsection start-world }
"The following words must also be implemented:" "The following words must also be implemented:"
{ $subsection set-title } { $subsection set-title }
{ $subsection raise-window } { $subsection raise-window }

52
extra/ui/ui.factor Normal file → Executable file
View File

@ -3,7 +3,8 @@
USING: arrays assocs io kernel math models namespaces USING: arrays assocs io kernel math models namespaces
prettyprint dlists sequences threads sequences words timers prettyprint dlists sequences threads sequences words timers
debugger ui.gadgets ui.gadgets.worlds ui.gadgets.tracks debugger ui.gadgets ui.gadgets.worlds ui.gadgets.tracks
ui.gestures ui.backend ui.render continuations init ; ui.gestures ui.backend ui.render continuations init
combinators ;
IN: ui IN: ui
! Assoc mapping aliens to gadgets ! Assoc mapping aliens to gadgets
@ -53,25 +54,23 @@ SYMBOL: windows
reset-world ; reset-world ;
: open-world-window ( world -- ) : open-world-window ( world -- )
dup pref-dim over set-gadget-dim dup pref-dim over set-gadget-dim dup relayout graft ;
dup (open-world-window)
draw-world ;
: open-window ( gadget title -- ) : open-window ( gadget title -- )
>r [ 1 track, ] { 0 1 } make-track r> >r [ 1 track, ] { 0 1 } make-track r>
f <world> open-world-window ; f <world> open-world-window ;
: find-window ( quot -- world ) : find-window ( quot -- world )
windows get 1 <column> windows get values
[ gadget-child swap call ] curry* find-last nip ; inline [ gadget-child swap call ] curry* find-last nip ; inline
: restore-windows ( -- ) : restore-windows ( -- )
windows get [ 1 <column> >array ] keep delete-all windows get [ values ] keep delete-all
[ dup reset-world (open-world-window) ] each [ dup reset-world (open-world-window) ] each
forget-rollover ; forget-rollover ;
: restore-windows? ( -- ? ) : restore-windows? ( -- ? )
windows get [ empty? not ] [ f ] if* ; windows get empty? not ;
: update-hand ( world -- ) : update-hand ( world -- )
dup hand-world get-global eq? dup hand-world get-global eq?
@ -79,7 +78,8 @@ SYMBOL: windows
: layout-queued ( -- seq ) : layout-queued ( -- seq )
[ [
invalid [ in-layout? on
layout-queue [
dup layout find-world [ , ] when* dup layout find-world [ , ] when*
] dlist-slurp ] dlist-slurp
] { } make ; ] { } make ;
@ -87,24 +87,40 @@ SYMBOL: windows
SYMBOL: ui-hook SYMBOL: ui-hook
: init-ui ( -- ) : init-ui ( -- )
<dlist> \ invalid set-global <dlist> \ graft-queue set-global
<dlist> \ layout-queue set-global
V{ } clone windows set-global ; V{ } clone windows set-global ;
: redraw-worlds ( seq -- )
[ dup update-hand draw-world ] each ;
: notify ( gadget -- )
dup gadget-status {
{ { f t } [ dup activate-control dup graft* ] }
{ { t f } [ dup activate-control dup ungraft* ] }
} case
dup gadget-status first { f f } { t t } ?
swap set-gadget-status ;
: notify-queued ( -- )
graft-queue [ notify ] dlist-slurp ;
: ui-step ( -- )
[
do-timers
notify-queued
layout-queued
redraw-worlds
10 sleep
] assert-depth ;
: start-ui ( -- ) : start-ui ( -- )
init-timers init-timers
restore-windows? [ restore-windows? [
restore-windows restore-windows
] [ ] [
init-ui ui-hook get call init-ui ui-hook get call
] if ; ] if ui-step ;
: redraw-worlds ( seq -- )
[ dup update-hand draw-world ] each ;
: ui-step ( -- )
[
do-timers layout-queued redraw-worlds 10 sleep
] assert-depth ;
: ui-running ( quot -- ) : ui-running ( quot -- )
t \ ui-running set-global t \ ui-running set-global

View File

@ -340,17 +340,23 @@ SYMBOL: hWnd
] ui-try ] ui-try
] alien-callback ; ] alien-callback ;
: do-events ( -- ) : peek-message? ( msg -- ? ) f 0 0 PM_REMOVE PeekMessage zero? ;
msg-obj get f 0 0 PM_REMOVE PeekMessage
zero? not [ : do-events ( msg -- )
msg-obj get MSG-message WM_QUIT = [ {
msg-obj get [ TranslateMessage drop ] keep DispatchMessage drop { [ windows get empty? ] [ drop ] }
] unless { [ dup peek-message? ] [ >r [ ui-step ] ui-try r> do-events ] }
] when ; { [ dup MSG-message WM_QUIT = ] [ drop ] }
{ [ t ] [
dup TranslateMessage drop
dup DispatchMessage drop
do-events
] }
} cond ;
: event-loop ( -- ) : event-loop ( -- )
windows get empty? [ windows get empty? [
[ do-events ui-step ] ui-try event-loop msg-obj get do-events
] unless ; ] unless ;
: register-wndclassex ( -- class ) : register-wndclassex ( -- class )
@ -414,8 +420,8 @@ M: windows-ui-backend (open-world-window) ( world -- )
[ rect-dim first2 create-window dup setup-gl ] keep [ rect-dim first2 create-window dup setup-gl ] keep
[ f <win> ] keep [ f <win> ] keep
[ swap win-hWnd register-window ] 2keep [ swap win-hWnd register-window ] 2keep
[ set-world-handle ] 2keep dupd set-world-handle
start-world win-hWnd show-window ; win-hWnd show-window ;
M: windows-ui-backend select-gl-context ( handle -- ) M: windows-ui-backend select-gl-context ( handle -- )
[ win-hDC ] keep win-hRC wglMakeCurrent win32-error=0/f ; [ win-hDC ] keep win-hRC wglMakeCurrent win32-error=0/f ;

1
extra/ui/x11/x11.factor Normal file → Executable file
View File

@ -224,7 +224,6 @@ M: x11-ui-backend set-title ( string world -- )
M: x11-ui-backend (open-world-window) ( world -- ) M: x11-ui-backend (open-world-window) ( world -- )
dup gadget-window dup gadget-window
dup start-world
world-handle x11-handle-window dup set-closable map-window ; world-handle x11-handle-window dup set-closable map-window ;
M: x11-ui-backend raise-window ( world -- ) M: x11-ui-backend raise-window ( world -- )