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 diff
1.1 --- a/src/net/kryshen/indyvon/component.clj Sat Aug 14 19:03:10 2010 +0400 1.2 +++ b/src/net/kryshen/indyvon/component.clj Thu Aug 19 20:20:21 2010 +0400 1.3 @@ -11,6 +11,7 @@ 1.4 (:import 1.5 (net.kryshen.indyvon.core Size Bounds) 1.6 (java.awt Graphics2D Component Dimension Color) 1.7 + (java.awt.geom Rectangle2D$Double) 1.8 (javax.swing JFrame JPanel))) 1.9 1.10 (defn- font-context [^Component component] 1.11 @@ -25,11 +26,14 @@ 1.12 (let [bounds (Bounds. 0 0 width height)] 1.13 (binding [*graphics* graphics 1.14 *font-context* (.getFontRenderContext graphics) 1.15 + *initial-transform* (.getTransform graphics) 1.16 + *inverse-initial-transform* 1.17 + (-> graphics .getTransform .createInverse) 1.18 *target* component 1.19 *event-dispatcher* event-dispatcher 1.20 *update* #(.repaint component) 1.21 *bounds* bounds 1.22 - *clip* bounds] 1.23 + *clip* (Rectangle2D$Double. 0 0 width height)] 1.24 (render! layer) 1.25 (commit event-dispatcher))))) 1.26
2.1 --- a/src/net/kryshen/indyvon/core.clj Sat Aug 14 19:03:10 2010 +0400 2.2 +++ b/src/net/kryshen/indyvon/core.clj Thu Aug 19 20:20:21 2010 +0400 2.3 @@ -6,8 +6,8 @@ 2.4 2.5 (ns net.kryshen.indyvon.core 2.6 (:import 2.7 - (java.awt Graphics2D Component Color Font AWTEvent) 2.8 - (java.awt.geom AffineTransform) 2.9 + (java.awt Graphics2D Component Color Font AWTEvent Shape) 2.10 + (java.awt.geom AffineTransform Point2D$Double Rectangle2D$Double Area) 2.11 (java.awt.event MouseListener MouseMotionListener) 2.12 (java.awt.font FontRenderContext))) 2.13 2.14 @@ -15,10 +15,13 @@ 2.15 (def ^FontRenderContext *font-context*) 2.16 (def ^Component *target*) 2.17 (def *bounds*) 2.18 -(def *clip*) 2.19 +(def ^Shape *clip*) 2.20 (def *update*) 2.21 (def *event-dispatcher*) 2.22 2.23 +(def ^AffineTransform *initial-transform*) 2.24 +(def ^AffineTransform *inverse-initial-transform*) 2.25 + 2.26 (defrecord Theme [fore-color back-color alt-back-color border-color font]) 2.27 2.28 (defn default-theme [] 2.29 @@ -97,6 +100,35 @@ 2.30 y2 (min y12 y22)] 2.31 (Bounds. x1 y1 (- x2 x1) (- y2 y1))))) 2.32 2.33 +(defn- relative-transform 2.34 + "AffineTransform: layer -> absolute -> component." 2.35 + [] 2.36 + (let [tr (.getTransform *graphics*)] 2.37 + (.preConcatenate tr *inverse-initial-transform*) 2.38 + tr)) 2.39 + 2.40 +(defn- inverse-relative-transform 2.41 + "AffineTransform: component (event) -> absolute -> layer." 2.42 + [] 2.43 + (let [tr (.getTransform *graphics*)] 2.44 + (.invert tr) ; absolute -> layer 2.45 + (.concatenate tr *initial-transform*) ; component -> absolute 2.46 + tr)) 2.47 + 2.48 +(defn clip 2.49 + "Intersect clipping area with the specified shape or bounds. 2.50 + Returns new clip (Shape or nil if empty)." 2.51 + ([x y w h] 2.52 + (clip (Rectangle2D$Double. x y w h))) 2.53 + ([shape] 2.54 + (let [a1 (Area. shape) 2.55 + a2 (if (instance? Area *clip*) *clip* (Area. *clip*))] 2.56 + (.transform a1 (relative-transform)) 2.57 + (.intersect a1 a2) 2.58 + (if (.isEmpty a1) 2.59 + nil 2.60 + a1)))) 2.61 + 2.62 (defn ^Graphics2D create-graphics 2.63 ([] 2.64 (create-graphics 0 0 (:width *bounds*) (:height *bounds*))) 2.65 @@ -105,10 +137,9 @@ 2.66 2.67 (defmacro with-bounds [x y w h & body] 2.68 `(let [bounds# (Bounds. (+ ~x (:x *bounds*)) 2.69 - (+ ~y (:y *bounds*)) 2.70 - ~w ~h) 2.71 - clip# (intersect bounds# *clip*)] 2.72 - (when (and (pos? (:width clip#)) (pos? (:height clip#))) 2.73 + (+ ~y (:y *bounds*)) ~w ~h) 2.74 + clip# (clip ~x ~y ~w ~h)] 2.75 + (when clip# 2.76 (let [graphics# (create-graphics ~x ~y ~w ~h)] 2.77 (try 2.78 (binding [*bounds* bounds# 2.79 @@ -215,7 +246,9 @@ 2.80 java.awt.event.MouseEvent/MOUSE_PRESSED :mouse-pressed 2.81 java.awt.event.MouseEvent/MOUSE_RELEASED :mouse-released}) 2.82 2.83 -(defrecord DispatcherNode [handle handlers parent bounds bindings] 2.84 +(defrecord DispatcherNode [handle handlers parent 2.85 + ^Shape clip ^AffineTransform transform 2.86 + bindings] 2.87 EventDispatcher 2.88 (listen! [this component] 2.89 (listen! parent component)) 2.90 @@ -226,6 +259,7 @@ 2.91 2.92 (defn- make-node [handle handlers] 2.93 (DispatcherNode. handle handlers *event-dispatcher* *clip* 2.94 + (inverse-relative-transform) 2.95 (get-thread-bindings))) 2.96 2.97 (defn- assoc-cons [m key val] 2.98 @@ -234,31 +268,27 @@ 2.99 (defn- add-node [tree node] 2.100 (assoc-cons tree (:parent node) node)) 2.101 2.102 -(defn- inside? 2.103 - ([x y bounds] 2.104 - (inside? x y (:x bounds) (:y bounds) 2.105 - (:width bounds) (:height bounds))) 2.106 - ([px py x y w h] 2.107 - (and (>= px x) 2.108 - (>= py y) 2.109 - (< px (+ x w)) 2.110 - (< py (+ y h))))) 2.111 - 2.112 (defn- under-cursor 2.113 "Returns a vector of child nodes under cursor." 2.114 [x y tree node] 2.115 - (some #(if (inside? x y (:bounds %)) 2.116 + (some #(if (.contains (:clip %) x y) 2.117 (conj (vec (under-cursor x y tree %)) %)) 2.118 (get tree node))) 2.119 2.120 (defn- remove-all [coll1 coll2 pred] 2.121 (filter #(not (some (partial pred %) coll2)) coll1)) 2.122 2.123 -(defn- translate-mouse-event [^java.awt.event.MouseEvent event x y id] 2.124 - (MouseEvent. id (.getWhen event) 2.125 - (- (.getX event) x) (- (.getY event) y) 2.126 - (.getXOnScreen event) (.getYOnScreen event) 2.127 - (.getButton event))) 2.128 +(defn- transform [^AffineTransform tr x y] 2.129 + (let [p (Point2D$Double. x y)] 2.130 + (.transform tr p p) 2.131 + [(.x p) (.y p)])) 2.132 + 2.133 +(defn- translate-mouse-event [^java.awt.event.MouseEvent event 2.134 + ^AffineTransform tr id] 2.135 + (let [[x y] (transform tr (.getX event) (.getY event))] 2.136 + (MouseEvent. id (.getWhen event) x y 2.137 + (.getXOnScreen event) (.getYOnScreen event) 2.138 + (.getButton event)))) 2.139 2.140 (defn- translate-and-dispatch 2.141 ([nodes first-only ^java.awt.event.MouseEvent event] 2.142 @@ -270,8 +300,7 @@ 2.143 (do 2.144 (with-bindings* (:bindings node) 2.145 handler 2.146 - (translate-mouse-event event 2.147 - (-> node :bounds :x) (-> node :bounds :y) id)) 2.148 + (translate-mouse-event event (:transform node) id)) 2.149 (if-not first-only 2.150 (recur (rest nodes) false event id))) 2.151 (recur (rest nodes) first-only event id)))))
3.1 --- a/src/net/kryshen/indyvon/demo.clj Sat Aug 14 19:03:10 2010 +0400 3.2 +++ b/src/net/kryshen/indyvon/demo.clj Thu Aug 19 20:20:21 2010 +0400 3.3 @@ -71,7 +71,7 @@ 3.4 (reify 3.5 Layer 3.6 (render! [layer] 3.7 - (*update*) 3.8 + ;;(*update*) 3.9 (doto *graphics* 3.10 (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED])) 3.11 (.drawLine 0 0 (:width *bounds*) (:height *bounds*)))