! Copyright (C) 2005 Slava Pestov. ! See http://factor.sf.net/license.txt for BSD license. IN: gadgets-presentations DEFER: DEFER: DEFER: gadget. IN: gadgets-panes USING: arrays gadgets gadgets-editors gadgets-labels gadgets-layouts gadgets-scrolling gadgets-theme generic hashtables io kernel line-editor lists math namespaces prettyprint sequences strings styles threads ; ! A pane is an area that can display text. ! output: pile ! current: shelf ! input: editor TUPLE: pane output active current input continuation scrolls? ; : add-output 2dup set-pane-output add-gadget ; : ( current input -- line ) [ 2array ] [ 1array ] if* make-shelf ; : init-active-line ( pane -- ) dup pane-active unparent [ dup pane-current swap pane-input ] keep 2dup set-pane-active add-gadget ; : pop-continuation ( pane -- quot ) dup pane-continuation f rot set-pane-continuation ; : pane-eval ( string pane -- ) pop-continuation dup [ [ continue-with ] in-thread ] when 2drop ; SYMBOL: structured-input : elements. ( quot -- ) [ 2 nesting-limit set 5 length-limit set newline ] with-pprint ; : pane-call ( quot pane -- ) 2dup [ elements. ] with-stream* >r structured-input global set-hash "\"structured-input\" \"gadgets-panes\" lookup global hash call" r> pane-eval ; : editor-commit ( editor -- line ) #! Add current line to the history, and clear the editor. [ commit-history line-text get line-clear ] with-editor ; : replace-input ( string pane -- ) pane-input set-editor-text ; : print-input ( string pane -- ) [ dup bold font-style set-paint-prop gadget. ] with-stream* ; : pane-return ( pane -- ) dup pane-input dup [ editor-commit swap 2dup print-input 2dup pane-eval ] when 2drop ; : pane-clear ( pane -- ) dup pane-output clear-incremental pane-current clear-gadget ; : pane-actions ( line -- ) [ [[ [ button-down 1 ] [ pane-input [ click-editor ] when* ] ]] [[ [ "RETURN" ] [ pane-return ] ]] [[ [ "UP" ] [ pane-input [ [ history-prev ] with-editor ] when* ] ]] [[ [ "DOWN" ] [ pane-input [ [ history-next ] with-editor ] when* ] ]] [[ [ "CTRL" "l" ] [ pane get pane-clear ] ]] ] swap add-actions ; C: pane ( input? scrolls? -- pane ) #! You can create output-only panes. If the scrolls flag is #! set, the pane will scroll to the bottom when input is #! added. [ set-pane-scrolls? ] keep over set-delegate over add-output over set-pane-current swap [ "" over set-pane-input ] when dup init-active-line dup pane-actions ; M: pane focusable-child* ( pane -- editor ) pane-input [ t ] unless* ; : pane-write-1 ( style text pane -- ) pick not pick empty? and [ 3drop ] [ >r r> pane-current add-gadget ] if ; : prepare-print ( current -- gadget ) #! Optimization: if line has 1 child, add the child. dup gadget-children @{ @{ [ dup empty? ] [ 2drop ""