Mercurial > hg > indyvon
changeset 21:a70609bad3a4
Simpler event dispatching.
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Sat, 19 Jun 2010 04:27:29 +0400 |
parents | 357bdd7d0550 |
children | dc81033d4122 |
files | src/indyvon/component.clj src/indyvon/event.clj |
diffstat | 2 files changed, 60 insertions(+), 88 deletions(-) [+] |
line diff
1.1 --- a/src/indyvon/component.clj Fri Jun 18 04:39:56 2010 +0400 1.2 +++ b/src/indyvon/component.clj Sat Jun 19 04:27:29 2010 +0400 1.3 @@ -49,32 +49,44 @@ 1.4 (comment 1.5 (do 1.6 (def frame (JFrame. "Test")) 1.7 + 1.8 + (defn handler [context event] 1.9 + (println (:layer context) (.paramString event))) 1.10 + 1.11 (def layer1 1.12 (reify Layer 1.13 (render! [this context g] 1.14 - (register-context context) 1.15 + (mouse-handler context handler) 1.16 (.setColor g Color/RED) 1.17 (.fillRect g 0 0 (:width context) (:height context))) 1.18 - (size [this context] [30 20]))) 1.19 + (size [this context] [30 20]) 1.20 + (toString [this] "layer1"))) 1.21 + 1.22 (def layer1b (border-layer layer1 2 3)) 1.23 + 1.24 (def layer2 1.25 (reify Layer 1.26 (render! [this context g] 1.27 - (register-context context) 1.28 + (mouse-handler context handler) 1.29 (.setColor g Color/YELLOW) 1.30 (.fillRect g 0 0 (:width context) (:height context)) 1.31 (draw! context layer1b g 10 5) 1.32 (draw! context layer1 g 55 5)) 1.33 - (size [this context] [70 65]))) 1.34 + (size [this context] [70 65]) 1.35 + (toString [this] "layer2"))) 1.36 + 1.37 (def layer3 1.38 (border-layer (text-layer "Sample\ntext" :right :bottom))) 1.39 + 1.40 (def layer 1.41 (reify Layer 1.42 (render! [this context g] 1.43 (.drawLine g 0 0 (:width context) (:height context)) 1.44 (draw! context layer2 g 15 20) 1.45 (draw! context layer3 g 100 100 80 50)) 1.46 - (size [this context] [400 300]))) 1.47 + (size [this context] [400 300]) 1.48 + (toString [this] "layer"))) 1.49 + 1.50 (doto frame 1.51 (.addWindowListener 1.52 (proxy [java.awt.event.WindowAdapter] [] 1.53 @@ -82,20 +94,5 @@ 1.54 (.. (getContentPane) (add (make-jpanel layer))) 1.55 (.pack) 1.56 (.setVisible true)) 1.57 - 1.58 - (add-listener layer1 MouseEvent/MOUSE_ENTERED 1.59 - (fn [context event] (println "1 ENTERED"))) 1.60 - (add-listener layer1 MouseEvent/MOUSE_EXITED 1.61 - (fn [context event] (println "1 EXITED"))) 1.62 - (add-listener layer1 MouseEvent/MOUSE_MOVED 1.63 - (fn [context event] (println "1 MOVED"))) 1.64 - (add-listener layer2 MouseEvent/MOUSE_ENTERED 1.65 - (fn [context event] (println "2 ENTERED"))) 1.66 - (add-listener layer2 MouseEvent/MOUSE_EXITED 1.67 - (fn [context event] (println "2 EXITED"))) 1.68 - (add-listener layer2 MouseEvent/MOUSE_MOVED 1.69 - (fn [context event] (println "2 MOVED"))) 1.70 - (add-listener layer2 MouseEvent/MOUSE_DRAGGED 1.71 - (fn [context event] (println "2 DRAGGED"))) 1.72 ) 1.73 )
2.1 --- a/src/indyvon/event.clj Fri Jun 18 04:39:56 2010 +0400 2.2 +++ b/src/indyvon/event.clj Sat Jun 19 04:27:29 2010 +0400 2.3 @@ -9,54 +9,18 @@ 2.4 (:import (java.awt.event MouseEvent MouseListener MouseMotionListener) 2.5 java.lang.ref.WeakReference)) 2.6 2.7 -;; map event-id -> [layer-weak-ref1 fn1, layer-weak-ref2 fn2...] 2.8 -(def listeners-map (ref {})) 2.9 - 2.10 -(defn- assoc-conj [map key & vals] 2.11 - (assoc map key (apply conj (vec (get map key)) vals))) 2.12 - 2.13 -(defn add-listener 2.14 - "The supplied function will be invoked with context, event and 2.15 - additional args when an event with the specified id occurs on the 2.16 - specified layer." 2.17 - [layer event-id f & args] 2.18 - (let [f (if args #(apply f %1 %2 args) f)] 2.19 - (dosync 2.20 - (alter listeners-map assoc-conj event-id (WeakReference. layer) f)) 2.21 - nil)) 2.22 - 2.23 -(defn- listeners 2.24 - "Returns list of listener fns for event and target-layer. Listeners 2.25 - for garbage-collected layers are removed." 2.26 - [event-id target-layer] 2.27 - (dosync 2.28 - (loop [ref-vec (@listeners-map event-id) cleared-ref-vec [] listeners []] 2.29 - (if-let [layer-ref (first ref-vec)] 2.30 - (if-let [layer (.get layer-ref)] 2.31 - (let [lfn (second ref-vec)] 2.32 - (recur (nnext ref-vec) 2.33 - (conj cleared-ref-vec layer-ref lfn) 2.34 - (if (= layer target-layer) 2.35 - (conj listeners lfn) 2.36 - listeners))) 2.37 - (recur (nnext ref-vec) cleared-ref-vec listeners)) 2.38 - (do 2.39 - (alter listeners-map assoc event-id cleared-ref-vec) 2.40 - listeners))))) 2.41 - 2.42 -(defn dispatch-event [context event] 2.43 - (doseq [listener (listeners (.getID event) (:layer context))] 2.44 - (listener context event))) 2.45 - 2.46 (defprotocol EventDispatcher 2.47 (listen! [this component]) 2.48 - (register [this context]) 2.49 + (register-mouse-handler [this context handler]) 2.50 (commit [this]) 2.51 (hovered? [this layer]) 2.52 (picked? [this layer])) 2.53 2.54 -(defn register-context [context] 2.55 - (register (:dispatcher context) context)) 2.56 +(defn mouse-handler [context handler & args] 2.57 + "The supplied handler function will be invoked with context, event 2.58 + and additional args when mouse event occurs on the context." 2.59 + (let [handler (if args #(apply handler %1 %2 args) handler)] 2.60 + (register-mouse-handler (:dispatcher context) context handler))) 2.61 2.62 (defn- registered-parent 2.63 "Returns first context parent registered for event processing." 2.64 @@ -70,7 +34,7 @@ 2.65 (defn- add-context 2.66 [context-tree context] 2.67 (let [parent (registered-parent context-tree context)] 2.68 - (assoc context-tree parent (conj (context-tree parent) context) 2.69 + (assoc context-tree parent (cons context (context-tree parent)) 2.70 context nil))) 2.71 2.72 (defn- inside? 2.73 @@ -108,19 +72,23 @@ 2.74 (getXOnScreen [] (.getXOnScreen event)) 2.75 (getYOnScreen [] (.getYOnScreen event)))) 2.76 2.77 +(defn- dispatch-event [handlers context event] 2.78 + ((handlers context) context event)) 2.79 + 2.80 (defn- translate-and-dispatch 2.81 - ([contexts event] 2.82 - (translate-and-dispatch contexts event (.getID event))) 2.83 - ([contexts event id] 2.84 + ([contexts handlers event] 2.85 + (translate-and-dispatch contexts handlers event (.getID event))) 2.86 + ([contexts handlers event id] 2.87 (doseq [context contexts] 2.88 (dispatch-event 2.89 + handlers 2.90 context 2.91 (translate-mouse-event event (:x context) (:y context) id))))) 2.92 2.93 (defn- dispatch-mouse-motion* 2.94 "Dispatches mouse motion events. Returns a new set of contexts which 2.95 currently are under cursor." 2.96 - [hovered context-tree event] 2.97 + [hovered context-tree handlers event] 2.98 (let [x (.getX event) 2.99 y (.getY event) 2.100 hovered2 (under-cursor context-tree x y) 2.101 @@ -128,34 +96,39 @@ 2.102 exited (remove-all hovered hovered2 pred) 2.103 entered (remove-all hovered2 hovered pred) 2.104 moved (remove-all hovered2 entered pred)] 2.105 - (translate-and-dispatch exited event MouseEvent/MOUSE_EXITED) 2.106 - (translate-and-dispatch entered event MouseEvent/MOUSE_ENTERED) 2.107 - (translate-and-dispatch moved event MouseEvent/MOUSE_MOVED) 2.108 + (translate-and-dispatch 2.109 + exited handlers event MouseEvent/MOUSE_EXITED) 2.110 + (translate-and-dispatch 2.111 + entered handlers event MouseEvent/MOUSE_ENTERED) 2.112 + (translate-and-dispatch 2.113 + moved handlers event MouseEvent/MOUSE_MOVED) 2.114 hovered2)) 2.115 2.116 (defn- dispatch-mouse-motion 2.117 - [hovered-ref context-tree event] 2.118 + [hovered-ref context-tree handlers event] 2.119 (dosync 2.120 - (alter hovered-ref dispatch-mouse-motion* context-tree event))) 2.121 + (alter hovered-ref dispatch-mouse-motion* context-tree handlers event))) 2.122 2.123 (defn- dispatch-mouse-button* 2.124 "Dispatches mouse button events. Returns a new set of contexts which 2.125 currently are picked with a pressed button." 2.126 - [picked hovered context-tree event] 2.127 - (translate-and-dispatch hovered event) 2.128 + [picked hovered handlers event] 2.129 + (translate-and-dispatch hovered handlers event) 2.130 (if (= (.getID event) MouseEvent/MOUSE_PRESSED) 2.131 hovered 2.132 nil)) 2.133 - 2.134 + 2.135 (defn- dispatch-mouse-button 2.136 - [picked-ref hovered-ref context-tree event] 2.137 + [picked-ref hovered-ref handlers event] 2.138 (dosync 2.139 (alter picked-ref dispatch-mouse-button* 2.140 - @hovered-ref context-tree event))) 2.141 + @hovered-ref handlers event))) 2.142 2.143 (defn make-event-dispatcher [] 2.144 (let [context-tree-r (ref {}) ; register 2.145 + handlers-r (ref {}) ; 2.146 context-tree (ref {}) ; dispatch 2.147 + handlers (ref {}) ; 2.148 hovered (ref '()) 2.149 picked (ref '())] 2.150 (reify 2.151 @@ -164,27 +137,29 @@ 2.152 (doto component 2.153 (.addMouseListener this) 2.154 (.addMouseMotionListener this))) 2.155 - (register [this context] 2.156 - (dosync (alter context-tree-r add-context context))) 2.157 + (register-mouse-handler [this context handler] 2.158 + (dosync (alter context-tree-r add-context context) 2.159 + (alter handlers-r assoc context handler))) 2.160 (commit [this] 2.161 (dosync (ref-set context-tree @context-tree-r) 2.162 - (ref-set context-tree-r {}))) 2.163 + (ref-set context-tree-r {}) 2.164 + (ref-set handlers @handlers-r) 2.165 + (ref-set handlers-r {}))) 2.166 (picked? [this layer] false) 2.167 (hovered? [this layer] false) 2.168 MouseListener 2.169 (mouseEntered [this event] 2.170 - (dispatch-mouse-motion hovered context-tree event)) 2.171 + (dispatch-mouse-motion hovered context-tree handlers event)) 2.172 (mouseExited [this event] 2.173 - (dispatch-mouse-motion hovered context-tree event)) 2.174 + (dispatch-mouse-motion hovered context-tree handlers event)) 2.175 (mouseClicked [this event] 2.176 - (dispatch-mouse-button picked hovered context-tree event)) 2.177 + (dispatch-mouse-button picked hovered handlers event)) 2.178 (mousePressed [this event] 2.179 - (dispatch-mouse-button picked hovered context-tree event)) 2.180 + (dispatch-mouse-button picked hovered handlers event)) 2.181 (mouseReleased [this event] 2.182 - (dispatch-mouse-button picked hovered context-tree event)) 2.183 + (dispatch-mouse-button picked hovered handlers event)) 2.184 MouseMotionListener 2.185 (mouseDragged [this event] 2.186 - (translate-and-dispatch @picked event)) 2.187 + (translate-and-dispatch @picked handlers event)) 2.188 (mouseMoved [this event] 2.189 - (dispatch-mouse-motion hovered context-tree event))))) 2.190 - 2.191 + (dispatch-mouse-motion hovered context-tree handlers event)))))