;;; -*- Mode:LISP; Package:OBIE; Base:10 -*- ;;; Tools #| A tool is a metaphor for a mode. A user picks a tool from a toolbox menu and uses it to perform some operation on display (usually on a specific objects). Picking up a tool changes the mouse icon and the mouse sensitivity: only objects that the tool can act on are sensitive. To make the interface more flexible, the user can mouse on an object and get a pop-up menu of tools. This corresponds to a noun-verb grammer rather than the verb-noun grammer of modes. Implementation: a tool is an object... |# (defobclass tool () manager ;The owner of this tool (active? nil) object-class ;The class of objects this tool can act on. icon-class ;The general icon class for the tool ; mouse-icon ;An instance for mouse blinker mouse-char ;Temp until icons can be mouse blinkers (mouse-font fonts:mouse) (mouse-hot-x 0) (mouse-hot-y 0) menu-icon) ;An instance for a toolbox menu (defobclass tool-menu-item (menu-item) tool (value '(frobnitz))) ; This returns an icon appropriate for a menu (defobfun (toolbox-menu-icon tool) (&rest args) (apply #'oneof (list tool-menu-item icon-class) 'tool obj:*object args)) (defobfun (tool-mouse-icon tool) (&rest args) (apply #'oneof (list dynamic-icon icon-class) args)) (defobfun (mouse-click tool-menu-item) (char x y) (ask tool (pick-up))) (defobfun (pick-up tool) () (ask-funcall manager 'picked-up (current-obj)) ; (unless mouse-icon ;init mouse-icon ; (setq mouse-icon (tool-mouse-icon 'window (ask manager tv-window) 'x (ask menu-icon x) 'y (ask menu-icon y)))) ; (ask mouse-icon (be-the-mouse-blinker)) (tv:mouse-set-blinker-definition :character mouse-hot-x mouse-hot-y :on :set-character mouse-char mouse-font) ;; set mouse-sensitivity list ;; highlight the menu icon ) (defobfun (put-down tool) () ) ; This is the default handler for mouse-clicks when the tool is picked up. (defobfun (mouse-click tool) (char object) (ask-funcall object 'mouse-click char class-name)) ; An application-level window can have this mixed into itself. (defobclass tool-manager (object-managing-window) (tools nil) (held-tool nil)) (defobfun (picked-up tool-manager) (tool) (unless (eq tool held-tool) (when held-tool (ask held-tool (put-down))) (setq held-tool tool) (setq mouse-char (ask tool mouse-char) mouse-font (ask tool mouse-font) mouse-hot-x (ask tool mouse-hot-x) mouse-hot-y (ask tool mouse-hot-y)))) ; If a tool is held, pass call to it, else let window handle it (defobfun (mouse-click tool-manager) (char x y) (or (and held-tool (dolist (obj mouseable-objects) (when (and (obj-classp (ask held-tool object-class) obj) ;+++ take ask out of loop (ask-funcall obj 'point-in-region x y)) (ask-funcall held-tool 'mouse-click char obj) (return t)))) (shadowed-mouse-click char x y)))