     (doseq [action (map :mouse-in in)] (when action (action)))
     (doseq [action (map :mouse-out out)] (when action (action)))))
     
-(defn activate-dragging! [e reference canvas]
-  (let [x (.getX e) y (.getY e)]
+(defn initiate-dragging!
+  "Initiates a dragging session."
+  [e reference canvas]
+  (let [x0 (.getX e) y0 (.getY e)
+        dragee (last (shape-by-action :on-mouse-drag [x0 y0] @reference))
+        {:keys [x y]} dragee
+        dx (- x x0) dy (- y y0)]
     (alter-meta! canvas assoc
                  ::dragging-action
-                   (last (triggered-mouse-actions
-                           :on-mouse-drag [x y] @reference))
-                 ::last-drag-position [x y])))
-
-(defn stop-dragging! [canvas]
-  (alter-meta! canvas dissoc ::dragging-action))
-
-(defn continue-dragging [e canvas]
+                 (:on-mouse-drag dragee)
+                 ::dragging-offset [dx dy])))
+
+(defn continue-dragging!
+  "Updates a dragging session."
+  [e canvas]
   (let [x (.getX e) y (.getY e)
         canvas-meta (meta canvas)
-        [x0 y0] (::last-drag-position canvas-meta)
-        dx (- x x0) dy (- y y0)]
-    (alter-meta! canvas assoc
-                 ::last-drag-position [x y])
+        [dx dy] (::dragging-offset canvas-meta)
+        xnew (+ x dx) ynew (+ y dy)]
     (when-let [action (canvas-meta ::dragging-action)]
-      (action dx dy))))
+      (action xnew ynew))))
+
+(defn finish-dragging!
+  "Halts a dragging session."
+  [canvas]
+  (alter-meta! canvas dissoc ::dragging-action))
 
 (defn interactive-canvas
   [reference]

    (fn [x y] ((widget action-type)
                 (- x offset-x) (- y offset-y)))))

(defn match-shapes [[x y] data]
  (->> data
       (filter #(-> (.createTransformedShape
                           (% :transform) (% :shape)) (.contains x y)))))

(defn triggered-mouse-actions [action-type [x y] data]
  (->> data
       expand-memo
       (filter action-type)
       (match-shapes [x y])
       (map #(create-action % action-type))))

(defn run-mouse-actions [e action-type reference]
  (let [x (.getX e) y (.getY e)]                    
    (doseq [action (triggered-mouse-actions action-type [x y] @reference)]
      (action x y))))

(defn mouse-is-over [[x y] data]
  (->> data
       expand-memo
       (remove #(empty? (select-keys % [:mouse-in :mouse-out])))
       (match-shapes [x y])))

(defn handle-mouse-move [e reference canvas]
  ;(println "move" (now))

        panel (proxy [JPanel clojure.lang.IReference] []
                (paintComponent [^Graphics graphics]
                  (proxy-super paintComponent graphics)
                  (paint/paint-buffered graphics
                    #(try
                       (draw % @reference)
                       (catch Throwable e (draw-error % e)))))
                (alterMeta [alter args]
                  (apply swap! meta-atom alter args))
                (resetMeta [m]
                  (reset! meta-atom m))
                (meta []
                  @meta-atom))]
    (add-watch reference panel (fn [_ _ old-val new-val]
                                 (when (not= old-val new-val)
                                   (.repaint panel))))
    (alter-meta! panel assoc ::data-source reference)
    panel))
