Mercurial > hg > indyvon
changeset 135:7eddb035d9c4
Further refactoring of the event dispatcher.
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Thu, 26 Apr 2012 19:23:04 +0400 |
parents | 16643a84b9e4 |
children | 1a5fd362114d |
files | src/net/kryshen/indyvon/core.clj |
diffstat | 1 files changed, 102 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/core.clj Tue Apr 24 18:51:37 2012 +0400 +++ b/src/net/kryshen/indyvon/core.clj Thu Apr 26 19:23:04 2012 +0400 @@ -615,15 +615,12 @@ (defn- under-cursor "Returns a vector of child nodes under cursor." - [^long x ^long y tree node] + [node tree ^long x ^long y] (some #(if (and (:clip %) (.contains ^Shape (:clip %) x y)) - (conj (vec (under-cursor x y tree %)) %)) + (conj (vec (under-cursor % tree x y)) %)) (get tree node))) -(defn- remove-all [coll1 coll2 pred] - (filter #(not (some (partial pred %) coll2)) coll1)) - (defn- translate-mouse-event [^java.awt.event.MouseEvent event ^AffineTransform tr id] (let [[x y] (inverse-transform-point tr (.getX event) (.getY event)) @@ -643,65 +640,86 @@ event (awt-events (.getID event)))) ([nodes first-only event id] (if-let [node (first nodes)] - (if-let [handler (get (:handlers node) id)] - (do - (let [translated (translate-mouse-event event (:transform node) id)] + (let [handlers (:handlers node) + handler (get handlers id)] + (if handler + (do (with-bindings* (:bindings node) - handler translated)) - (if-not first-only - (recur (rest nodes) false event id))) - (recur (rest nodes) first-only event id))))) + handler + (translate-mouse-event event (:transform node) id)) + (when-not first-only + (recur (rest nodes) false event id))) + (when-not (and (= id :mouse-dragged) + (or (contains? handlers :mouse-pressed) + (contains? handlers :mouse-released))) + (recur (rest nodes) first-only event id))))))) -(defn- process-mouse-position - [dispatcher event] - (dosync - (let [{hovered-ref :hovered - last-ref :last-motion - tree-ref :tree} dispatcher - ^java.awt.event.MouseEvent event (or event @last-ref)] - (when event - (let [x (.getX event) - y (.getY event) - old-hovered @hovered-ref - hovered (under-cursor x y @tree-ref dispatcher) - pred #(= (:handle %1) (:handle %2)) - exited (remove-all old-hovered hovered pred) - entered (remove-all hovered old-hovered pred) - moved (remove-all hovered entered pred)] - (ref-set hovered-ref hovered) - (ref-set last-ref event) - [exited entered moved event]))))) +(defn- process-mouse-event + [dispatcher ^java.awt.event.MouseEvent source-event] + (let [{active-ref :active + hovered-ref :hovered + picked-ref :picked + last-ref :last-motion + tree-ref :tree} dispatcher + pressed (and source-event + (== (.getID source-event) + java.awt.event.MouseEvent/MOUSE_PRESSED)) + released (and source-event + (== (.getID source-event) + java.awt.event.MouseEvent/MOUSE_RELEASED)) + ^java.awt.event.MouseEvent last-event @last-ref + ^java.awt.event.MouseEvent event (or source-event last-event)] + (when event + (let [x (.getX event) + y (.getY event) + active @active-ref + active (if (and active + source-event + (== (.getX last-event) x) + (== (.getY last-event) y)) + active + (ref-set active-ref + (under-cursor dispatcher @tree-ref x y))) + acted (cond + pressed (ref-set picked-ref active) + released (let [picked @picked-ref] + (ref-set picked-ref nil) + picked) + :else active) + picked (seq @picked-ref) + pred #(= (:handle %1) (:handle %2)) + hovered (if picked + (filter #(some (partial pred %) picked) active) + active) + remove-all (fn [c1 c2] + (filter #(not (some (partial pred %) c2)) c1)) + old-hovered @hovered-ref + exited (remove-all old-hovered hovered) + entered (remove-all hovered old-hovered) + moved (or picked (remove-all hovered entered))] + (ref-set hovered-ref hovered) + (ref-set last-ref event) + [exited entered moved acted event])))) -(defn- dispatch-mouse-motion - [dispatcher source-event] - (when-let [[exited entered moved event] (process-mouse-position - dispatcher source-event)] +(defn- dispatch-mouse-event + [dispatcher source-event button?] + (when-let [[exited + entered + moved + acted + event] (dosync (process-mouse-event dispatcher source-event))] + (when button? + (translate-and-dispatch acted true event)) (translate-and-dispatch exited false event :mouse-exited) (translate-and-dispatch entered false event :mouse-entered) - (when source-event - (translate-and-dispatch moved true event :mouse-moved)))) + (when-not button? + (translate-and-dispatch moved true source-event)))) -(defn- dispatch-mouse-button - [dispatcher ^java.awt.event.MouseEvent event] - (let [{picked-ref :picked - hovered-ref :hovered} dispatcher - id (awt-events (.getID event)) - nodes (case id - :mouse-pressed - (dosync - (ref-set picked-ref @hovered-ref)) - :mouse-released - (dosync - (let [picked @picked-ref] - (ref-set picked-ref nil) - picked)) - @hovered-ref)] - (translate-and-dispatch nodes true event id))) - -(defrecord RootEventDispatcher [tree-r ; register - tree ; dispatch - hovered - picked +(defrecord RootEventDispatcher [tree-r ;; register + tree ;; dispatch + active ;; nodes under cursor + hovered ;; mouse entered + picked ;; mouse pressed last-motion] EventDispatcher (listen! [dispatcher component] @@ -714,39 +732,49 @@ (dosync (alter tree-r add-node node)) node)) (commit [dispatcher] - ;; TODO: retain contexts that do not intersect graphics - ;; clipping area in tree. - (dosync (ref-set tree @tree-r) - (ref-set tree-r {})) - ;; Send mouse entered and exited events if necessary due to - ;; updated layout. - (dispatch-mouse-motion dispatcher nil)) + (let [[exited + entered + _ _ + event] (dosync + ;; TODO: retain contexts that do + ;; not intersect graphics + ;; clipping area in tree. + (ref-set tree @tree-r) + (ref-set tree-r {}) + (process-mouse-event dispatcher nil))] + ;; Send mouse entered and exited events if necessary due to + ;; updated layout. + (translate-and-dispatch exited false event :mouse-exited) + (translate-and-dispatch entered false event :mouse-entered))) (handle-picked? [dispatcher handle] (some #(= handle (:handle %)) @picked)) (handle-hovered? [dispatcher handle] (some #(= handle (:handle %)) @hovered)) MouseListener (mouseEntered [dispatcher event] - (dispatch-mouse-motion dispatcher event)) + (dispatch-mouse-event dispatcher event false)) (mouseExited [dispatcher event] - (dispatch-mouse-motion dispatcher event)) + (dispatch-mouse-event dispatcher event false)) (mouseClicked [dispatcher event] - (dispatch-mouse-button dispatcher event)) + (dispatch-mouse-event dispatcher event true)) (mousePressed [dispatcher event] - (dispatch-mouse-button dispatcher event)) + (dispatch-mouse-event dispatcher event true)) (mouseReleased [dispatcher event] - (dispatch-mouse-button dispatcher event)) + (dispatch-mouse-event dispatcher event true)) MouseWheelListener (mouseWheelMoved [dispatcher event] - (dispatch-mouse-button dispatcher event)) + (dispatch-mouse-event dispatcher event true)) MouseMotionListener (mouseDragged [dispatcher event] - (translate-and-dispatch @picked true event)) + (dispatch-mouse-event dispatcher event false)) (mouseMoved [dispatcher event] - (dispatch-mouse-motion dispatcher event))) + (dispatch-mouse-event dispatcher event false))) (defn root-event-dispatcher [] - (->RootEventDispatcher (ref {}) (ref {}) (ref '()) (ref '()) (ref nil))) + (->RootEventDispatcher + (ref {}) (ref {}) ;; trees + (ref nil) (ref nil) (ref nil) ;; node states + (ref nil))) ;; last event ;; ;; Scene