modulization of ui.frp
parent
f5b539bb00
commit
27b745dcc8
|
@ -4,8 +4,8 @@ USING: accessors arrays classes.mixin classes.parser
|
||||||
classes.tuple classes.tuple.parser combinators effects
|
classes.tuple classes.tuple.parser combinators effects
|
||||||
effects.parser fry generic generic.parser generic.standard
|
effects.parser fry generic generic.parser generic.standard
|
||||||
interpolate io.streams.string kernel lexer locals.parser
|
interpolate io.streams.string kernel lexer locals.parser
|
||||||
locals.rewrite.closures locals.types make namespaces parser
|
locals.rewrite.closures locals.types make macros namespaces
|
||||||
quotations sequences vocabs.parser words words.symbol ;
|
parser quotations sequences vocabs.parser words words.symbol ;
|
||||||
IN: functors
|
IN: functors
|
||||||
|
|
||||||
! This is a hack
|
! This is a hack
|
||||||
|
@ -111,6 +111,11 @@ SYNTAX: `GENERIC:
|
||||||
complete-effect parsed
|
complete-effect parsed
|
||||||
\ define-simple-generic* parsed ;
|
\ define-simple-generic* parsed ;
|
||||||
|
|
||||||
|
SYNTAX: `MACRO:
|
||||||
|
scan-param parsed
|
||||||
|
parse-declared*
|
||||||
|
\ define-macro parsed ;
|
||||||
|
|
||||||
SYNTAX: `inline [ word make-inline ] over push-all ;
|
SYNTAX: `inline [ word make-inline ] over push-all ;
|
||||||
|
|
||||||
SYNTAX: `call-next-method T{ fake-call-next-method } parsed ;
|
SYNTAX: `call-next-method T{ fake-call-next-method } parsed ;
|
||||||
|
@ -142,6 +147,7 @@ DEFER: ;FUNCTOR delimiter
|
||||||
{ "SYNTAX:" POSTPONE: `SYNTAX: }
|
{ "SYNTAX:" POSTPONE: `SYNTAX: }
|
||||||
{ "SYMBOL:" POSTPONE: `SYMBOL: }
|
{ "SYMBOL:" POSTPONE: `SYMBOL: }
|
||||||
{ "inline" POSTPONE: `inline }
|
{ "inline" POSTPONE: `inline }
|
||||||
|
{ "MACRO:" POSTPONE: `MACRO: }
|
||||||
{ "call-next-method" POSTPONE: `call-next-method }
|
{ "call-next-method" POSTPONE: `call-next-method }
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
|
@ -927,4 +927,6 @@ PRIVATE>
|
||||||
list empty?
|
list empty?
|
||||||
[ identity ]
|
[ identity ]
|
||||||
[ list rest identity quot reduce-r list first quot call ] if ;
|
[ list rest identity quot reduce-r list first quot call ] if ;
|
||||||
inline recursive
|
inline recursive
|
||||||
|
|
||||||
|
:: combos ( list1 list2 -- result ) list2 [ [ 2array ] curry list1 swap map ] map concat ;
|
|
@ -0,0 +1,7 @@
|
||||||
|
USING: accessors assocs kernel lexer locals namespaces sequences
|
||||||
|
vocabs vocabs.parser ;
|
||||||
|
IN: modules.util
|
||||||
|
SYNTAX: EXPORT-FROM: [let | v [ in get ] |
|
||||||
|
v vocab words>> ";" parse-tokens
|
||||||
|
[ load-vocab vocab-words [ clone v >>vocabulary ] assoc-map ] map
|
||||||
|
assoc-combine update ] ;
|
|
@ -22,6 +22,7 @@ M: monad return monad-of return ;
|
||||||
M: monad fail monad-of fail ;
|
M: monad fail monad-of fail ;
|
||||||
|
|
||||||
: bind ( mvalue quot -- mvalue' ) swap >>= call( quot -- mvalue ) ;
|
: bind ( mvalue quot -- mvalue' ) swap >>= call( quot -- mvalue ) ;
|
||||||
|
: bind* ( mvalue quot -- mvalue' ) '[ drop @ ] bind ;
|
||||||
: >> ( mvalue k -- mvalue' ) '[ drop _ ] bind ;
|
: >> ( mvalue k -- mvalue' ) '[ drop _ ] bind ;
|
||||||
|
|
||||||
:: lift-m2 ( m1 m2 f monad -- m3 )
|
:: lift-m2 ( m1 m2 f monad -- m3 )
|
||||||
|
|
|
@ -1,167 +1,4 @@
|
||||||
USING: accessors arrays colors fonts fry generalizations kernel
|
USING: modules.util ui.frp.functors monads ;
|
||||||
lexer macros math math.parser models models.product monads
|
|
||||||
sequences ui.gadgets ui.gadgets.buttons ui.gadgets.buttons.private
|
|
||||||
ui.gadgets.editors ui.gadgets.scrollers ui.gadgets.tables
|
|
||||||
ui.gadgets.tracks ;
|
|
||||||
QUALIFIED: make
|
|
||||||
IN: ui.frp
|
IN: ui.frp
|
||||||
|
EXPORT-FROM: ui.frp.signals ui.frp.gadgets ui.frp.instances ui.frp.layout ;
|
||||||
! !!! Model utilities
|
FMAPS: $> <$ fmap FOR & | ;
|
||||||
TUPLE: multi-model < model ;
|
|
||||||
GENERIC: (model-changed) ( model observer -- )
|
|
||||||
: <multi-model> ( models kind -- model ) f swap new-model [ [ add-dependency ] curry each ] keep ;
|
|
||||||
M: multi-model model-changed over value>> [ (model-changed) ] [ 2drop ] if ;
|
|
||||||
M: multi-model model-activated dup dependencies>> dup length 1 =
|
|
||||||
[ first swap model-changed ] [ 2drop ] if ;
|
|
||||||
|
|
||||||
TUPLE: basic-model < multi-model ;
|
|
||||||
M: basic-model (model-changed) [ value>> ] dip set-model ;
|
|
||||||
: <merge> ( models -- model ) basic-model <multi-model> ;
|
|
||||||
: <basic> ( value -- model ) basic-model new-model ;
|
|
||||||
|
|
||||||
TUPLE: filter-model < multi-model quot ;
|
|
||||||
M: filter-model (model-changed) [ value>> ] dip 2dup quot>> call( a -- ? )
|
|
||||||
[ set-model ] [ 2drop ] if ;
|
|
||||||
: <filter> ( model quot -- filter-model ) [ 1array filter-model <multi-model> ] dip >>quot ;
|
|
||||||
|
|
||||||
TUPLE: fold-model < multi-model oldval quot ;
|
|
||||||
M: fold-model (model-changed) [ [ value>> ] [ [ oldval>> ] [ quot>> ] bi ] bi*
|
|
||||||
call( val oldval -- newval ) ] keep set-model ;
|
|
||||||
: <fold> ( oldval quot model -- model' ) 1array fold-model <multi-model> swap >>quot
|
|
||||||
swap [ >>oldval ] [ >>value ] bi ;
|
|
||||||
|
|
||||||
TUPLE: updater-model < multi-model values updates ;
|
|
||||||
M: updater-model (model-changed) tuck updates>> =
|
|
||||||
[ [ values>> value>> ] keep set-model ]
|
|
||||||
[ drop ] if ;
|
|
||||||
: <updates> ( values updates -- updater ) [ 2array updater-model <multi-model> ] 2keep
|
|
||||||
[ >>values ] [ >>updates ] bi* ;
|
|
||||||
|
|
||||||
TUPLE: switch-model < multi-model original switcher on ;
|
|
||||||
M: switch-model (model-changed) 2dup switcher>> =
|
|
||||||
[ [ value>> ] [ t >>on ] bi* set-model ]
|
|
||||||
[ dup on>> [ 2drop ] [ [ value>> ] dip set-model ] if ] if ;
|
|
||||||
: <switch> ( signal1 signal2 -- signal' ) [ 2array switch-model <multi-model> ] 2keep
|
|
||||||
[ >>original ] [ >>switcher ] bi* ;
|
|
||||||
M: switch-model model-activated [ original>> ] keep model-changed ;
|
|
||||||
|
|
||||||
TUPLE: mapped-model < multi-model model quot ;
|
|
||||||
: new-mapped-model ( model quot class -- const-model ) [ over 1array ] dip
|
|
||||||
<multi-model> swap >>quot swap >>model ;
|
|
||||||
: <mapped> ( model quot -- mapped ) mapped-model new-mapped-model ;
|
|
||||||
M: mapped-model (model-changed)
|
|
||||||
[ [ value>> ] [ quot>> ] bi* call( old -- new ) ] [ nip ] 2bi
|
|
||||||
set-model ;
|
|
||||||
|
|
||||||
TUPLE: side-effect-model < mapped-model ;
|
|
||||||
M: side-effect-model (model-changed) [ [ value>> ] [ quot>> ] bi* call( old -- ) ] keep t swap set-model ;
|
|
||||||
: $> ( model quot -- side-effect-model ) side-effect-model new-mapped-model ;
|
|
||||||
|
|
||||||
TUPLE: quot-model < mapped-model ;
|
|
||||||
M: quot-model (model-changed) nip [ quot>> call( -- b ) ] keep set-model ;
|
|
||||||
: <$ ( model quot -- quot-model ) quot-model new-mapped-model ;
|
|
||||||
|
|
||||||
TUPLE: frp-product < multi-model ;
|
|
||||||
: <frp-product> ( models -- product ) frp-product <multi-model> ;
|
|
||||||
M: frp-product model-changed
|
|
||||||
nip
|
|
||||||
dup dependencies>> [ value>> ] all?
|
|
||||||
[ dup [ value>> ] product-value >>value notify-connections
|
|
||||||
] [ drop ] if ;
|
|
||||||
M: frp-product update-model
|
|
||||||
dup value>> swap [ set-model ] set-product-value ;
|
|
||||||
M: frp-product model-activated dup model-changed ;
|
|
||||||
|
|
||||||
TUPLE: action-value < basic-model parent ;
|
|
||||||
: <action-value> ( parent value -- model ) action-value new-model swap >>parent ;
|
|
||||||
M: action-value model-activated dup parent>> dup activate-model model-changed ; ! a fake dependency of sorts
|
|
||||||
|
|
||||||
! Update at start
|
|
||||||
TUPLE: action < multi-model quot ;
|
|
||||||
M: action (model-changed) [ [ value>> ] [ quot>> ] bi* call( a -- b ) ] keep value>>
|
|
||||||
[ swap add-connection ] 2keep model-changed ;
|
|
||||||
: <action> ( model quot -- action ) [ 1array action <multi-model> ] dip >>quot dup f <action-value> >>value value>> ;
|
|
||||||
|
|
||||||
! Gadgets
|
|
||||||
TUPLE: frp-button < button hook ;
|
|
||||||
: <frp-button> ( text -- button ) [
|
|
||||||
[ dup hook>> [ call( button -- ) ] [ drop ] if* ] keep
|
|
||||||
t swap set-control-value
|
|
||||||
] frp-button new-button border-button-theme f <basic> >>model ;
|
|
||||||
|
|
||||||
TUPLE: frp-table < table { quot initial: [ ] } { val-quot initial: [ ] } color-quot column-titles column-alignment ;
|
|
||||||
M: frp-table column-titles column-titles>> ;
|
|
||||||
M: frp-table column-alignment column-alignment>> ;
|
|
||||||
M: frp-table row-columns quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
|
||||||
M: frp-table row-value val-quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
|
||||||
M: frp-table row-color color-quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
|
||||||
|
|
||||||
: <frp-table> ( model -- table ) f frp-table new-table dup >>renderer
|
|
||||||
V{ } clone <basic> >>selected-values V{ } clone <basic> >>selected-indices* ;
|
|
||||||
: <frp-table*> ( -- table ) V{ } clone <model> <frp-table> ;
|
|
||||||
: <frp-list> ( model -- table ) <frp-table> [ 1array ] >>quot ;
|
|
||||||
: <frp-list*> ( -- table ) V{ } clone <model> <frp-list> ;
|
|
||||||
: indexed ( table -- table ) f >>val-quot ;
|
|
||||||
|
|
||||||
: <frp-field> ( -- field ) "" <model> <model-field> ;
|
|
||||||
|
|
||||||
! Layout utilities
|
|
||||||
TUPLE: layout gadget width ; C: <layout> layout
|
|
||||||
|
|
||||||
GENERIC: output-model ( gadget -- model )
|
|
||||||
M: gadget output-model model>> ;
|
|
||||||
M: table output-model dup multiple-selection?>>
|
|
||||||
[ dup val-quot>> [ selected-values>> ] [ selected-indices*>> ] if ]
|
|
||||||
[ dup val-quot>> [ selected-value>> ] [ selected-index*>> ] if ] if ;
|
|
||||||
M: model-field output-model field-model>> ;
|
|
||||||
M: scroller output-model viewport>> children>> first output-model ;
|
|
||||||
|
|
||||||
GENERIC: , ( uiitem -- )
|
|
||||||
M: gadget , f <layout> make:, ;
|
|
||||||
M: model , activate-model ;
|
|
||||||
|
|
||||||
SYNTAX: ,% scan string>number [ <layout> make:, ] curry over push-all ;
|
|
||||||
SYNTAX: ->% scan string>number '[ [ _ <layout> make:, ] [ output-model ] bi ] over push-all ;
|
|
||||||
|
|
||||||
GENERIC: -> ( uiitem -- model )
|
|
||||||
M: gadget -> dup , output-model ;
|
|
||||||
M: model -> dup , ;
|
|
||||||
|
|
||||||
: <spacer> ( -- ) <gadget> 1 <layout> make:, ;
|
|
||||||
: <box> ( gadgets type -- track )
|
|
||||||
[ { } make:make ] dip <track> swap [ [ gadget>> ] [ width>> ] bi track-add ] each ; inline
|
|
||||||
: <box*> ( gadgets type -- track ) [ <box> ] [ [ model>> ] map <product> ] bi >>model ; inline
|
|
||||||
: <hbox> ( gadgets -- track ) horizontal <box> ; inline
|
|
||||||
: <hbox*> ( gadgets -- track ) horizontal <box*> ; inline
|
|
||||||
: <vbox> ( gadgets -- track ) vertical <box> ; inline
|
|
||||||
: <vbox*> ( gadgets -- track ) vertical <box*> ; inline
|
|
||||||
|
|
||||||
! Instances
|
|
||||||
M: model fmap <mapped> ;
|
|
||||||
M: model >>= [ swap <action> ] curry ;
|
|
||||||
|
|
||||||
SINGLETON: gadget-monad
|
|
||||||
INSTANCE: gadget-monad monad
|
|
||||||
INSTANCE: gadget monad
|
|
||||||
M: gadget monad-of drop gadget-monad ;
|
|
||||||
M: gadget-monad return drop <gadget> swap >>model ;
|
|
||||||
M: gadget >>= output-model [ swap call( x -- y ) ] curry ;
|
|
||||||
|
|
||||||
! Macros
|
|
||||||
: lift ( int -- quot ) dup
|
|
||||||
'[ [ _ narray <frp-product> ] dip [ _ firstn ] prepend ] ; inline
|
|
||||||
|
|
||||||
MACRO: liftA-n ( int -- quot ) lift [ <mapped> ] append ;
|
|
||||||
|
|
||||||
MACRO: $>-n ( int -- quot ) lift [ $> ] append ;
|
|
||||||
|
|
||||||
MACRO: <$-n ( int -- quot ) lift [ <$ ] append ;
|
|
||||||
|
|
||||||
: liftA2 ( a b quot -- arrow ) 2 liftA-n ; inline
|
|
||||||
: liftA3 ( a b c quot -- arrow ) 3 liftA-n ; inline
|
|
||||||
|
|
||||||
: $>2 ( a b quot -- arrow ) 2 $>-n ; inline
|
|
||||||
: $>3 ( a b c quot -- arrow ) 3 $>-n ; inline
|
|
||||||
|
|
||||||
: <$2 ( a b quot -- arrow ) 2 <$-n ; inline
|
|
||||||
: <$3 ( a b c quot -- arrow ) 3 <$-n ; inline
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
USING: fry functors generalizations kernel macros peg peg-lexer
|
||||||
|
sequences ;
|
||||||
|
IN: ui.frp.functors
|
||||||
|
|
||||||
|
FUNCTOR: fmaps ( W P -- )
|
||||||
|
W IS ${W}
|
||||||
|
<p> IS <${P}>
|
||||||
|
w-n DEFINES ${W}-n-${P}
|
||||||
|
w-2 DEFINES 2${W}-${P}
|
||||||
|
w-3 DEFINES 3${W}-${P}
|
||||||
|
w-4 DEFINES 4${W}-${P}
|
||||||
|
WHERE
|
||||||
|
MACRO: w-n ( int -- quot ) dup '[ [ _ narray <p> ] dip [ _ firstn ] prepend W ] ;
|
||||||
|
: w-2 ( a b quot -- mapped ) 2 w-n ; inline
|
||||||
|
: w-3 ( a b c quot -- mapped ) 3 w-n ; inline
|
||||||
|
: w-4 ( a b c d quot -- mapped ) 4 w-n ; inline
|
||||||
|
;FUNCTOR
|
||||||
|
|
||||||
|
ON-BNF: FMAPS:
|
||||||
|
tokenizer = <foreign factor>
|
||||||
|
token = !("FOR"|";").
|
||||||
|
middle = "FOR" => [[ drop ignore ]]
|
||||||
|
endexpr = ";" => [[ drop ignore ]]
|
||||||
|
expr = token* middle token* endexpr => [[ first2 combos [ first2 fmaps ] each ignore ]]
|
||||||
|
;ON-BNF
|
|
@ -0,0 +1,26 @@
|
||||||
|
USING: accessors arrays kernel models ui.frp.signals ui.gadgets
|
||||||
|
ui.gadgets.buttons ui.gadgets.buttons.private
|
||||||
|
ui.gadgets.editors ui.gadgets.tables ;
|
||||||
|
IN: ui.frp.gadgets
|
||||||
|
|
||||||
|
TUPLE: frp-button < button hook ;
|
||||||
|
: <frp-button> ( text -- button ) [
|
||||||
|
[ dup hook>> [ call( button -- ) ] [ drop ] if* ] keep
|
||||||
|
t swap set-control-value
|
||||||
|
] frp-button new-button border-button-theme f <basic> >>model ;
|
||||||
|
|
||||||
|
TUPLE: frp-table < table { quot initial: [ ] } { val-quot initial: [ ] } color-quot column-titles column-alignment ;
|
||||||
|
M: frp-table column-titles column-titles>> ;
|
||||||
|
M: frp-table column-alignment column-alignment>> ;
|
||||||
|
M: frp-table row-columns quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
||||||
|
M: frp-table row-value val-quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
||||||
|
M: frp-table row-color color-quot>> [ call( a -- b ) ] [ drop f ] if* ;
|
||||||
|
|
||||||
|
: <frp-table> ( model -- table ) f frp-table new-table dup >>renderer
|
||||||
|
V{ } clone <basic> >>selected-values V{ } clone <basic> >>selected-indices* ;
|
||||||
|
: <frp-table*> ( -- table ) V{ } clone <model> <frp-table> ;
|
||||||
|
: <frp-list> ( model -- table ) <frp-table> [ 1array ] >>quot ;
|
||||||
|
: <frp-list*> ( -- table ) V{ } clone <model> <frp-list> ;
|
||||||
|
: indexed ( table -- table ) f >>val-quot ;
|
||||||
|
|
||||||
|
: <frp-field> ( -- field ) "" <model> <model-field> ;
|
|
@ -0,0 +1,12 @@
|
||||||
|
USING: accessors kernel models monads ui.frp.signals ui.frp.layout ui.gadgets ;
|
||||||
|
IN: ui.frp.instances
|
||||||
|
|
||||||
|
M: model >>= [ swap <action> ] curry ;
|
||||||
|
M: model fmap <mapped> ;
|
||||||
|
|
||||||
|
SINGLETON: gadget-monad
|
||||||
|
INSTANCE: gadget-monad monad
|
||||||
|
INSTANCE: gadget monad
|
||||||
|
M: gadget monad-of drop gadget-monad ;
|
||||||
|
M: gadget-monad return drop <gadget> swap >>model ;
|
||||||
|
M: gadget >>= output-model [ swap call( x -- y ) ] curry ;
|
|
@ -0,0 +1,34 @@
|
||||||
|
USING: accessors fry kernel lexer math.parser models sequences
|
||||||
|
ui.frp.signals ui.gadgets ui.gadgets.editors ui.gadgets.scrollers
|
||||||
|
ui.gadgets.tables ui.gadgets.tracks ;
|
||||||
|
QUALIFIED: make
|
||||||
|
IN: ui.frp.layout
|
||||||
|
TUPLE: layout gadget width ; C: <layout> layout
|
||||||
|
|
||||||
|
GENERIC: output-model ( gadget -- model )
|
||||||
|
M: gadget output-model model>> ;
|
||||||
|
M: table output-model dup multiple-selection?>>
|
||||||
|
[ dup val-quot>> [ selected-values>> ] [ selected-indices*>> ] if ]
|
||||||
|
[ dup val-quot>> [ selected-value>> ] [ selected-index*>> ] if ] if ;
|
||||||
|
M: model-field output-model field-model>> ;
|
||||||
|
M: scroller output-model viewport>> children>> first output-model ;
|
||||||
|
|
||||||
|
GENERIC: , ( uiitem -- )
|
||||||
|
M: gadget , f <layout> make:, ;
|
||||||
|
M: model , activate-model ;
|
||||||
|
|
||||||
|
SYNTAX: ,% scan string>number [ <layout> make:, ] curry over push-all ;
|
||||||
|
SYNTAX: ->% scan string>number '[ [ _ <layout> make:, ] [ output-model ] bi ] over push-all ;
|
||||||
|
|
||||||
|
GENERIC: -> ( uiitem -- model )
|
||||||
|
M: gadget -> dup , output-model ;
|
||||||
|
M: model -> dup , ;
|
||||||
|
|
||||||
|
: <spacer> ( -- ) <gadget> 1 <layout> make:, ;
|
||||||
|
: <box> ( gadgets type -- track )
|
||||||
|
[ { } make:make ] dip <track> swap [ [ gadget>> ] [ width>> ] bi track-add ] each ; inline
|
||||||
|
: <box*> ( gadgets type -- track ) [ <box> ] [ [ model>> ] map <|> ] bi >>model ; inline
|
||||||
|
: <hbox> ( gadgets -- track ) horizontal <box> ; inline
|
||||||
|
: <hbox*> ( gadgets -- track ) horizontal <box*> ; inline
|
||||||
|
: <vbox> ( gadgets -- track ) vertical <box> ; inline
|
||||||
|
: <vbox*> ( gadgets -- track ) vertical <box*> ; inline
|
|
@ -0,0 +1,81 @@
|
||||||
|
USING: accessors arrays kernel models models.product sequences ;
|
||||||
|
IN: ui.frp.signals
|
||||||
|
|
||||||
|
TUPLE: multi-model < model ;
|
||||||
|
GENERIC: (model-changed) ( model observer -- )
|
||||||
|
: <multi-model> ( models kind -- model ) f swap new-model [ [ add-dependency ] curry each ] keep ;
|
||||||
|
M: multi-model model-changed over value>> [ (model-changed) ] [ 2drop ] if ;
|
||||||
|
M: multi-model model-activated dup dependencies>> dup length 1 =
|
||||||
|
[ first swap model-changed ] [ 2drop ] if ;
|
||||||
|
|
||||||
|
TUPLE: basic-model < multi-model ;
|
||||||
|
M: basic-model (model-changed) [ value>> ] dip set-model ;
|
||||||
|
: <merge> ( models -- model ) basic-model <multi-model> ;
|
||||||
|
: <basic> ( value -- model ) basic-model new-model ;
|
||||||
|
|
||||||
|
TUPLE: filter-model < multi-model quot ;
|
||||||
|
M: filter-model (model-changed) [ value>> ] dip 2dup quot>> call( a -- ? )
|
||||||
|
[ set-model ] [ 2drop ] if ;
|
||||||
|
: <filter> ( model quot -- filter-model ) [ 1array filter-model <multi-model> ] dip >>quot ;
|
||||||
|
|
||||||
|
TUPLE: fold-model < multi-model oldval quot ;
|
||||||
|
M: fold-model (model-changed) [ [ value>> ] [ [ oldval>> ] [ quot>> ] bi ] bi*
|
||||||
|
call( val oldval -- newval ) ] keep set-model ;
|
||||||
|
: <fold> ( oldval quot model -- model' ) 1array fold-model <multi-model> swap >>quot
|
||||||
|
swap [ >>oldval ] [ >>value ] bi ;
|
||||||
|
|
||||||
|
TUPLE: updater-model < multi-model values updates ;
|
||||||
|
M: updater-model (model-changed) tuck updates>> =
|
||||||
|
[ [ values>> value>> ] keep set-model ]
|
||||||
|
[ drop ] if ;
|
||||||
|
: <updates> ( values updates -- updater ) [ 2array updater-model <multi-model> ] 2keep
|
||||||
|
[ >>values ] [ >>updates ] bi* ;
|
||||||
|
|
||||||
|
TUPLE: switch-model < multi-model original switcher on ;
|
||||||
|
M: switch-model (model-changed) 2dup switcher>> =
|
||||||
|
[ [ value>> ] [ t >>on ] bi* set-model ]
|
||||||
|
[ dup on>> [ 2drop ] [ [ value>> ] dip set-model ] if ] if ;
|
||||||
|
: <switch> ( signal1 signal2 -- signal' ) [ 2array switch-model <multi-model> ] 2keep
|
||||||
|
[ >>original ] [ >>switcher ] bi* ;
|
||||||
|
M: switch-model model-activated [ original>> ] keep model-changed ;
|
||||||
|
|
||||||
|
TUPLE: mapped-model < multi-model model quot ;
|
||||||
|
: new-mapped-model ( model quot class -- const-model ) [ over 1array ] dip
|
||||||
|
<multi-model> swap >>quot swap >>model ;
|
||||||
|
: <mapped> ( model quot -- mapped ) mapped-model new-mapped-model ;
|
||||||
|
M: mapped-model (model-changed)
|
||||||
|
[ [ value>> ] [ quot>> ] bi* call( old -- new ) ] [ nip ] 2bi
|
||||||
|
set-model ;
|
||||||
|
|
||||||
|
TUPLE: side-effect-model < mapped-model ;
|
||||||
|
M: side-effect-model (model-changed) [ [ value>> ] [ quot>> ] bi* call( old -- ) ] keep t swap set-model ;
|
||||||
|
: $> ( model quot -- side-effect-model ) side-effect-model new-mapped-model ;
|
||||||
|
|
||||||
|
TUPLE: quot-model < mapped-model ;
|
||||||
|
M: quot-model (model-changed) nip [ quot>> call( -- b ) ] keep set-model ;
|
||||||
|
: <$ ( model quot -- quot-model ) quot-model new-mapped-model ;
|
||||||
|
|
||||||
|
TUPLE: action-value < basic-model parent ;
|
||||||
|
: <action-value> ( parent value -- model ) action-value new-model swap >>parent ;
|
||||||
|
M: action-value model-activated dup parent>> dup activate-model model-changed ; ! a fake dependency of sorts
|
||||||
|
|
||||||
|
TUPLE: action < multi-model quot ;
|
||||||
|
M: action (model-changed) [ [ value>> ] [ quot>> ] bi* call( a -- b ) ] keep value>>
|
||||||
|
[ swap add-connection ] 2keep model-changed ;
|
||||||
|
: <action> ( model quot -- action ) [ 1array action <multi-model> ] dip >>quot dup f <action-value> >>value value>> ;
|
||||||
|
|
||||||
|
TUPLE: | < multi-model ;
|
||||||
|
: <|> ( models -- product ) | <multi-model> ;
|
||||||
|
M: | model-changed
|
||||||
|
nip
|
||||||
|
dup dependencies>> [ value>> ] all?
|
||||||
|
[ dup [ value>> ] product-value >>value notify-connections
|
||||||
|
] [ drop ] if ;
|
||||||
|
M: | update-model
|
||||||
|
dup value>> swap [ set-model ] set-product-value ;
|
||||||
|
M: | model-activated dup model-changed ;
|
||||||
|
|
||||||
|
TUPLE: & < | ;
|
||||||
|
: <&> ( models -- product ) & <multi-model> ;
|
||||||
|
M: & model-changed [ call-next-method ] keep
|
||||||
|
[ dependencies>> [ f swap set-model ] each ] with-locked-model ;
|
Loading…
Reference in New Issue