changeset 134:16643a84b9e4

Refactored the event dispatcher. Update hover states at every commit.
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 24 Apr 2012 18:51:37 +0400
parents 2c2e4c639311
children 7eddb035d9c4
files src/net/kryshen/indyvon/core.clj
diffstat 1 files changed, 78 insertions(+), 59 deletions(-) [+]
line diff
     1.1 --- a/src/net/kryshen/indyvon/core.clj	Tue Apr 24 18:49:06 2012 +0400
     1.2 +++ b/src/net/kryshen/indyvon/core.clj	Tue Apr 24 18:51:37 2012 +0400
     1.3 @@ -615,7 +615,7 @@
     1.4  
     1.5  (defn- under-cursor
     1.6    "Returns a vector of child nodes under cursor."
     1.7 -  [x y tree node]
     1.8 +  [^long x ^long y tree node]
     1.9    (some #(if (and (:clip %)
    1.10                    (.contains ^Shape (:clip %) x y))
    1.11             (conj (vec (under-cursor x y tree %)) %))
    1.12 @@ -652,26 +652,40 @@
    1.13               (recur (rest nodes) false event id)))
    1.14           (recur (rest nodes) first-only event id)))))
    1.15  
    1.16 +(defn- process-mouse-position
    1.17 +  [dispatcher event]
    1.18 +  (dosync
    1.19 +   (let [{hovered-ref :hovered
    1.20 +          last-ref :last-motion
    1.21 +          tree-ref :tree} dispatcher
    1.22 +         ^java.awt.event.MouseEvent event (or event @last-ref)]
    1.23 +     (when event
    1.24 +       (let [x (.getX event)
    1.25 +             y (.getY event)
    1.26 +             old-hovered @hovered-ref
    1.27 +             hovered (under-cursor x y @tree-ref dispatcher)
    1.28 +             pred #(= (:handle %1) (:handle %2))
    1.29 +             exited (remove-all old-hovered hovered pred)
    1.30 +             entered (remove-all hovered old-hovered pred)
    1.31 +             moved (remove-all hovered entered pred)]
    1.32 +         (ref-set hovered-ref hovered)
    1.33 +         (ref-set last-ref event)
    1.34 +         [exited entered moved event])))))
    1.35 +
    1.36  (defn- dispatch-mouse-motion
    1.37 -  "Dispatches mouse motion events."
    1.38 -  [hovered-ref tree root ^java.awt.event.MouseEvent event]
    1.39 -  (let [x (.getX event)
    1.40 -        y (.getY event)
    1.41 -        [hovered hovered2] (dosync
    1.42 -                            [@hovered-ref
    1.43 -                             (ref-set hovered-ref
    1.44 -                                      (under-cursor x y tree root))])
    1.45 -        pred #(= (:handle %1) (:handle %2))
    1.46 -        exited (remove-all hovered hovered2 pred)
    1.47 -        entered (remove-all hovered2 hovered pred)
    1.48 -        moved (remove-all hovered2 entered pred)]
    1.49 +  [dispatcher source-event]
    1.50 +  (when-let [[exited entered moved event] (process-mouse-position
    1.51 +                                           dispatcher source-event)]
    1.52      (translate-and-dispatch exited false event :mouse-exited)
    1.53      (translate-and-dispatch entered false event :mouse-entered)
    1.54 -    (translate-and-dispatch moved true event :mouse-moved)))
    1.55 +    (when source-event
    1.56 +      (translate-and-dispatch moved true event :mouse-moved))))
    1.57  
    1.58  (defn- dispatch-mouse-button
    1.59 -  [picked-ref hovered-ref ^java.awt.event.MouseEvent event]
    1.60 -  (let [id (awt-events (.getID event))
    1.61 +  [dispatcher ^java.awt.event.MouseEvent event]
    1.62 +  (let [{picked-ref :picked
    1.63 +         hovered-ref :hovered} dispatcher
    1.64 +        id (awt-events (.getID event))
    1.65          nodes (case id
    1.66                 :mouse-pressed
    1.67                 (dosync
    1.68 @@ -684,50 +698,55 @@
    1.69                 @hovered-ref)]
    1.70      (translate-and-dispatch nodes true event id)))
    1.71  
    1.72 +(defrecord RootEventDispatcher [tree-r ; register
    1.73 +                                tree   ; dispatch
    1.74 +                                hovered
    1.75 +                                picked
    1.76 +                                last-motion]
    1.77 +  EventDispatcher
    1.78 +  (listen! [dispatcher component]
    1.79 +    (doto ^Component component
    1.80 +          (.addMouseListener dispatcher)
    1.81 +          (.addMouseWheelListener dispatcher)
    1.82 +          (.addMouseMotionListener dispatcher)))
    1.83 +  (create-dispatcher [dispatcher handle handlers]
    1.84 +    (let [node (make-node handle handlers)]
    1.85 +      (dosync (alter tree-r add-node node))
    1.86 +      node))
    1.87 +  (commit [dispatcher]
    1.88 +    ;; TODO: retain contexts that do not intersect graphics
    1.89 +    ;; clipping area in tree.
    1.90 +    (dosync (ref-set tree @tree-r)
    1.91 +            (ref-set tree-r {}))
    1.92 +    ;; Send mouse entered and exited events if necessary due to
    1.93 +    ;; updated layout.
    1.94 +    (dispatch-mouse-motion dispatcher nil))
    1.95 +  (handle-picked? [dispatcher handle]
    1.96 +    (some #(= handle (:handle %)) @picked))
    1.97 +  (handle-hovered? [dispatcher handle]
    1.98 +    (some #(= handle (:handle %)) @hovered))
    1.99 +  MouseListener
   1.100 +  (mouseEntered [dispatcher event]
   1.101 +    (dispatch-mouse-motion dispatcher event))
   1.102 +  (mouseExited [dispatcher event]
   1.103 +    (dispatch-mouse-motion dispatcher event))
   1.104 +  (mouseClicked [dispatcher event]
   1.105 +    (dispatch-mouse-button dispatcher event))
   1.106 +  (mousePressed [dispatcher event]
   1.107 +    (dispatch-mouse-button dispatcher event))
   1.108 +  (mouseReleased [dispatcher event]
   1.109 +    (dispatch-mouse-button dispatcher event))
   1.110 +  MouseWheelListener
   1.111 +  (mouseWheelMoved [dispatcher event]
   1.112 +    (dispatch-mouse-button dispatcher event))
   1.113 +  MouseMotionListener
   1.114 +  (mouseDragged [dispatcher event]
   1.115 +    (translate-and-dispatch @picked true event))
   1.116 +  (mouseMoved [dispatcher event]
   1.117 +    (dispatch-mouse-motion dispatcher event)))
   1.118 +
   1.119  (defn root-event-dispatcher []
   1.120 -  (let [tree-r (ref {})   ; register
   1.121 -        tree (ref {})     ; dispatch
   1.122 -        hovered (ref '())
   1.123 -        picked (ref '())]
   1.124 -    (reify
   1.125 -     EventDispatcher
   1.126 -     (listen! [this component]
   1.127 -       (doto ^Component component
   1.128 -         (.addMouseListener this)
   1.129 -         (.addMouseWheelListener this)
   1.130 -         (.addMouseMotionListener this)))
   1.131 -     (create-dispatcher [this handle handlers]
   1.132 -       (let [node (make-node handle handlers)]
   1.133 -         (dosync (alter tree-r add-node node))
   1.134 -         node))
   1.135 -     (commit [this]
   1.136 -       ;; TODO: retain contexts that do not intersect graphics
   1.137 -       ;; clipping area in tree.
   1.138 -       (dosync (ref-set tree @tree-r)
   1.139 -               (ref-set tree-r {})))
   1.140 -     (handle-picked? [this handle]
   1.141 -       (some #(= handle (:handle %)) @picked))
   1.142 -     (handle-hovered? [this handle]
   1.143 -       (some #(= handle (:handle %)) @hovered))
   1.144 -     MouseListener
   1.145 -     (mouseEntered [this event]
   1.146 -       (dispatch-mouse-motion hovered @tree this event))
   1.147 -     (mouseExited [this event]
   1.148 -       (dispatch-mouse-motion hovered @tree this event))
   1.149 -     (mouseClicked [this event]
   1.150 -       (dispatch-mouse-button picked hovered event))
   1.151 -     (mousePressed [this event]
   1.152 -       (dispatch-mouse-button picked hovered event))
   1.153 -     (mouseReleased [this event]
   1.154 -       (dispatch-mouse-button picked hovered event))
   1.155 -     MouseWheelListener
   1.156 -     (mouseWheelMoved [this event]
   1.157 -       (dispatch-mouse-button picked hovered event))
   1.158 -     MouseMotionListener
   1.159 -     (mouseDragged [this event]
   1.160 -       (translate-and-dispatch @picked true event))
   1.161 -     (mouseMoved [this event]
   1.162 -       (dispatch-mouse-motion hovered @tree this event)))))
   1.163 +  (->RootEventDispatcher (ref {}) (ref {}) (ref '()) (ref '()) (ref nil)))
   1.164  
   1.165  ;;
   1.166  ;; Scene