USING: accessors arrays colors fonts kernel models models.product monads sequences ui.gadgets ui.gadgets.buttons ui.gadgets.editors ui.gadgets.line-support ui.gadgets.tables ui.gadgets.tracks ui.render ui.gadgets.scrollers ; QUALIFIED: make IN: ui.frp ! Gadgets : ( text -- button ) [ t swap set-control-value ] f >>model ; TUPLE: frp-table < table quot val-quot 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* ; : ( model -- table ) frp-table new-line-gadget dup >>renderer [ ] >>quot swap >>model f >>selected-value sans-serif-font >>font focus-border-color >>focus-border-color transparent >>column-line-color [ ] >>val-quot ; : ( -- table ) f ; : ( model -- table ) [ 1array ] >>quot ; : ( -- table ) f ; : ( -- field ) f ; ! Layout utilities GENERIC: output-model ( gadget -- model ) M: gadget output-model model>> ; M: frp-table output-model selected-value>> ; M: model-field output-model field-model>> ; M: scroller output-model children>> first model>> ; GENERIC: , ( uiitem -- ) M: gadget , make:, ; M: model , activate-model ; GENERIC: -> ( uiitem -- model ) M: gadget -> dup make:, output-model ; M: model -> dup , ; M: table -> dup , selected-value>> ; : ( gadgets type -- track ) [ { } make:make ] dip swap [ f track-add ] each ; inline : ( gadgets type -- track ) [ ] [ [ model>> ] map ] bi >>model ; inline : ( gadgets -- track ) horizontal ; inline : ( gadgets -- track ) horizontal ; inline : ( gadgets -- track ) vertical ; inline : ( gadgets -- track ) vertical ; inline ! !!! Model utilities TUPLE: multi-model < model ; : ( models kind -- model ) f swap new-model [ [ add-dependency ] curry each ] keep ; ! Events- discrete model utilities TUPLE: merge-model < multi-model ; M: merge-model model-changed [ value>> ] dip set-model ; : ( models -- model ) merge-model ; TUPLE: filter-model < multi-model quot ; M: filter-model model-changed [ value>> ] dip [ quot>> call( val -- bool ) ] 2keep [ set-model ] [ 2drop ] if ; : ( model quot -- filter-model ) [ 1array filter-model ] dip >>quot ; ! Behaviors - continuous model utilities TUPLE: fold-model < multi-model oldval quot ; M: fold-model model-changed [ [ value>> ] [ [ oldval>> ] [ quot>> ] bi ] bi* call( val oldval -- newval ) ] keep set-model ; : ( oldval quot model -- model' ) 1array fold-model swap >>quot swap [ >>oldval ] [ >>value ] bi ; TUPLE: switch-model < multi-model original switcher on ; M: switch-model model-changed 2dup switcher>> = [ over value>> [ [ value>> ] [ t >>on ] bi* set-model ] [ 2drop ] if ] [ dup on>> [ 2drop ] [ [ value>> ] dip set-model ] if ] if ; M: switch-model model-activated [ original>> ] keep model-changed ; : ( signal1 signal2 -- signal' ) [ 2array switch-model ] 2keep [ >>original ] [ >>switcher ] bi* ; TUPLE: mapped < model model quot ; : ( model quot -- arrow ) f mapped new-model swap >>quot over >>model [ add-dependency ] keep ; M: mapped model-changed [ [ value>> ] [ quot>> ] bi* call( old -- new ) ] [ nip ] 2bi set-model ; ! Instances M: model fmap ; SINGLETON: gadget-monad INSTANCE: gadget-monad monad INSTANCE: gadget monad M: gadget monad-of drop gadget-monad ; M: gadget-monad return drop swap >>model ; M: gadget >>= output-model [ swap call( x -- y ) ] curry ;