Mercurial > hg > indyvon
changeset 54:1d2dfe5026a8
Support transformations.
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Thu, 19 Aug 2010 20:20:21 +0400 |
parents | 042fae9cb24e |
children | 6adbc03a52cb |
files | src/net/kryshen/indyvon/component.clj src/net/kryshen/indyvon/core.clj src/net/kryshen/indyvon/demo.clj |
diffstat | 3 files changed, 61 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/component.clj Sat Aug 14 19:03:10 2010 +0400 +++ b/src/net/kryshen/indyvon/component.clj Thu Aug 19 20:20:21 2010 +0400 @@ -11,6 +11,7 @@ (:import (net.kryshen.indyvon.core Size Bounds) (java.awt Graphics2D Component Dimension Color) + (java.awt.geom Rectangle2D$Double) (javax.swing JFrame JPanel))) (defn- font-context [^Component component] @@ -25,11 +26,14 @@ (let [bounds (Bounds. 0 0 width height)] (binding [*graphics* graphics *font-context* (.getFontRenderContext graphics) + *initial-transform* (.getTransform graphics) + *inverse-initial-transform* + (-> graphics .getTransform .createInverse) *target* component *event-dispatcher* event-dispatcher *update* #(.repaint component) *bounds* bounds - *clip* bounds] + *clip* (Rectangle2D$Double. 0 0 width height)] (render! layer) (commit event-dispatcher)))))
--- a/src/net/kryshen/indyvon/core.clj Sat Aug 14 19:03:10 2010 +0400 +++ b/src/net/kryshen/indyvon/core.clj Thu Aug 19 20:20:21 2010 +0400 @@ -6,8 +6,8 @@ (ns net.kryshen.indyvon.core (:import - (java.awt Graphics2D Component Color Font AWTEvent) - (java.awt.geom AffineTransform) + (java.awt Graphics2D Component Color Font AWTEvent Shape) + (java.awt.geom AffineTransform Point2D$Double Rectangle2D$Double Area) (java.awt.event MouseListener MouseMotionListener) (java.awt.font FontRenderContext))) @@ -15,10 +15,13 @@ (def ^FontRenderContext *font-context*) (def ^Component *target*) (def *bounds*) -(def *clip*) +(def ^Shape *clip*) (def *update*) (def *event-dispatcher*) +(def ^AffineTransform *initial-transform*) +(def ^AffineTransform *inverse-initial-transform*) + (defrecord Theme [fore-color back-color alt-back-color border-color font]) (defn default-theme [] @@ -97,6 +100,35 @@ y2 (min y12 y22)] (Bounds. x1 y1 (- x2 x1) (- y2 y1))))) +(defn- relative-transform + "AffineTransform: layer -> absolute -> component." + [] + (let [tr (.getTransform *graphics*)] + (.preConcatenate tr *inverse-initial-transform*) + tr)) + +(defn- inverse-relative-transform + "AffineTransform: component (event) -> absolute -> layer." + [] + (let [tr (.getTransform *graphics*)] + (.invert tr) ; absolute -> layer + (.concatenate tr *initial-transform*) ; component -> absolute + tr)) + +(defn clip + "Intersect clipping area with the specified shape or bounds. + Returns new clip (Shape or nil if empty)." + ([x y w h] + (clip (Rectangle2D$Double. x y w h))) + ([shape] + (let [a1 (Area. shape) + a2 (if (instance? Area *clip*) *clip* (Area. *clip*))] + (.transform a1 (relative-transform)) + (.intersect a1 a2) + (if (.isEmpty a1) + nil + a1)))) + (defn ^Graphics2D create-graphics ([] (create-graphics 0 0 (:width *bounds*) (:height *bounds*))) @@ -105,10 +137,9 @@ (defmacro with-bounds [x y w h & body] `(let [bounds# (Bounds. (+ ~x (:x *bounds*)) - (+ ~y (:y *bounds*)) - ~w ~h) - clip# (intersect bounds# *clip*)] - (when (and (pos? (:width clip#)) (pos? (:height clip#))) + (+ ~y (:y *bounds*)) ~w ~h) + clip# (clip ~x ~y ~w ~h)] + (when clip# (let [graphics# (create-graphics ~x ~y ~w ~h)] (try (binding [*bounds* bounds# @@ -215,7 +246,9 @@ java.awt.event.MouseEvent/MOUSE_PRESSED :mouse-pressed java.awt.event.MouseEvent/MOUSE_RELEASED :mouse-released}) -(defrecord DispatcherNode [handle handlers parent bounds bindings] +(defrecord DispatcherNode [handle handlers parent + ^Shape clip ^AffineTransform transform + bindings] EventDispatcher (listen! [this component] (listen! parent component)) @@ -226,6 +259,7 @@ (defn- make-node [handle handlers] (DispatcherNode. handle handlers *event-dispatcher* *clip* + (inverse-relative-transform) (get-thread-bindings))) (defn- assoc-cons [m key val] @@ -234,31 +268,27 @@ (defn- add-node [tree node] (assoc-cons tree (:parent node) node)) -(defn- inside? - ([x y bounds] - (inside? x y (:x bounds) (:y bounds) - (:width bounds) (:height bounds))) - ([px py x y w h] - (and (>= px x) - (>= py y) - (< px (+ x w)) - (< py (+ y h))))) - (defn- under-cursor "Returns a vector of child nodes under cursor." [x y tree node] - (some #(if (inside? x y (:bounds %)) + (some #(if (.contains (:clip %) x y) (conj (vec (under-cursor x y tree %)) %)) (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 x y id] - (MouseEvent. id (.getWhen event) - (- (.getX event) x) (- (.getY event) y) - (.getXOnScreen event) (.getYOnScreen event) - (.getButton event))) +(defn- transform [^AffineTransform tr x y] + (let [p (Point2D$Double. x y)] + (.transform tr p p) + [(.x p) (.y p)])) + +(defn- translate-mouse-event [^java.awt.event.MouseEvent event + ^AffineTransform tr id] + (let [[x y] (transform tr (.getX event) (.getY event))] + (MouseEvent. id (.getWhen event) x y + (.getXOnScreen event) (.getYOnScreen event) + (.getButton event)))) (defn- translate-and-dispatch ([nodes first-only ^java.awt.event.MouseEvent event] @@ -270,8 +300,7 @@ (do (with-bindings* (:bindings node) handler - (translate-mouse-event event - (-> node :bounds :x) (-> node :bounds :y) id)) + (translate-mouse-event event (:transform node) id)) (if-not first-only (recur (rest nodes) false event id))) (recur (rest nodes) first-only event id)))))
--- a/src/net/kryshen/indyvon/demo.clj Sat Aug 14 19:03:10 2010 +0400 +++ b/src/net/kryshen/indyvon/demo.clj Thu Aug 19 20:20:21 2010 +0400 @@ -71,7 +71,7 @@ (reify Layer (render! [layer] - (*update*) + ;;(*update*) (doto *graphics* (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED])) (.drawLine 0 0 (:width *bounds*) (:height *bounds*)))