! Copyright (C) 2025 Serre. ! See https://factorcode.org/license.txt for BSD license. USING: accessors arrays combinators grouping hashtables kernel math math.parser models parser sequences splitting ui.gadgets ui.gadgets.buttons ui.gadgets.buttons.private ui.gadgets.labels ui.gadgets.packs ui.gestures words ; IN: quickbinds ! Syntax words and GUI tool for quickly developing and ! modifying UI gestures, including support for modal keybinds. ! == Core interface : parse-mods ( strings -- mods ) [ empty? not ] 1guard [ { { "S" [ S+ ] } { "C" [ C+ ] } { "A" [ A+ ] } { "M" [ M+ ] } } case ] map ; : string>keys ( string -- key-up/down ) [ first CHAR: ^ = ] keep over [ rest ] when "+" split unclip-last [ parse-mods ] dip rot [ key-up boa ] [ key-down boa ] if ; SYNTAX: KEYSTROKE: scan-object string>keys suffix! ; TUPLE: quickbind quot key-gesture mode desc ; C: quickbind : modal-hashtable ( quickbinds mode -- hashtable ) [ swap mode>> = ] curry filter [ [ key-gesture>> ] [ quot>> ] bi 2array ] map >hashtable ; : update-qb-gestures ( class -- ) dup [ "quickbinds" word-prop ] [ "quickbinds-mode" word-prop ] bi modal-hashtable set-gestures ; : change-qb-mode ( class mode -- ) dupd "quickbinds-mode" set-word-prop update-qb-gestures ; ! Would probably benefit from tying mode to model. : (quickbind) ( class quickbinds -- ) [ "quickbinds" set-word-prop ] curry [ 0 "quickbinds-mode" set-word-prop ] [ update-qb-gestures ] tri ; : * ( quot str mode desc -- quickbind ) [ [ string>keys ] [ dup number? [ def>> call( -- x ) ] unless ] bi* ] dip ; SYNTAX: QUICKBINDS: scan-word \ ; parse-until 4 group [ first4 * ] map (quickbind) ; ! == Quickbind UI tools (quickbinds.ui?) ! (Can't subclass buttons and init w/button-new?) TUPLE: quickbind-button < pack index class grab? ; :: set-quickbind ( gesture qb-index class -- ) class "quickbinds" [ dup [ qb-index ] dip [ gesture >>key-gesture ] change-nth ] change-word-prop class update-qb-gestures ; : update-qb-button ( quickbind-button -- ) dup [ gadget-child gadget-child ] [ index>> ] [ class>> "quickbinds" word-prop ] tri nth key-gesture>> gesture>string >>string drop relayout-1 ; : (grab) ( button -- ) parents second t >>grab? drop ; : ( index class -- button ) [ quickbind-button new vertical >>orientation "Loading..." [ (grab) ] add-gadget ] 2dip [ >>index ] [ >>class ] bi* [ update-qb-button ] keep ; M: quickbind-button handle-gesture ( gesture gadget -- ? ) 2dup [ key-down? ] [ grab?>> ] bi* and [ [ [ index>> ] [ class>> ] bi set-quickbind ] keep f >>grab? update-qb-button f ] [ 2drop t ] if ; TUPLE: quickbind-gadget < pack class ; : ( quickbind index class -- pack ) swap [ desc>> " " " " surround