     (fn [x y] ((widget action-type)
                  (- x offset-x) (- y offset-y)))))
 
-(defn match-shapes [[x y] data]
+(defn shapes-containing-point
+  "Returns the shapes in data that contain the
+   point [x y]."
+  [[x y] data]
   (->> data
        (filter #(-> (.createTransformedShape
-                           (% :transform) (% :shape)) (.contains x y)))))
-
-(defn triggered-mouse-actions [action-type [x y] data]
+                       (% :transform) (% :shape))
+                    (.contains x y)))))
+
+(defn shape-by-action [action-type [x y] data]
   (->> data
        expand-memo
        (filter action-type)
-       (match-shapes [x y])
-       (map #(create-action % action-type))))
+       (shapes-containing-point [x y])))
 
 (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]
+    (doseq [shape (shape-by-action action-type [x y] @reference)]
+      ((:action-type shape) x y))))
+
+(defn mouse-is-over
+  "Returns the shapes that contain the point [x y] and
+   expect a hovering mouse."
+  [[x y] data]
   (->> data
        expand-memo
        (remove #(empty? (select-keys % [:mouse-in :mouse-out])))
-       (match-shapes [x y])))
+       (shapes-containing-point [x y])))
 
 (defn handle-mouse-move [e reference canvas]
   ;(println "move" (now))

    (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)]
    (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]
  (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])
    (when-let [action (canvas-meta ::dragging-action)]
      (action dx dy))))

(defn interactive-canvas
  [reference]

        mouse-adapter
        (proxy [MouseAdapter] []
          (mouseClicked [e] (run-mouse-actions e :mouse-click reference))
          (mousePressed [e] (initiate-dragging! e reference canvas)
                            (run-mouse-actions e :mouse-down reference))
          (mouseReleased [e] (finish-dragging! canvas)
                             (run-mouse-actions e :mouse-up reference))
          (mouseMoved [e] (handle-mouse-move e reference canvas))
          (mouseDragged [e] 
                        (continue-dragging! e canvas)
                        (handle-mouse-move e reference canvas)))]
    (doto canvas
      (.addMouseListener mouse-adapter)
