Mercurial > hg > indyvon
changeset 60:7e456697924d
Asynchronous drawing (continue).
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Mon, 23 Aug 2010 21:24:33 +0400 |
parents | b68de6a43f29 |
children | 88bb47e3a401 |
files | src/net/kryshen/indyvon/component.clj src/net/kryshen/indyvon/core.clj src/net/kryshen/indyvon/layers.clj |
diffstat | 3 files changed, 59 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/component.clj Mon Aug 23 14:06:13 2010 +0400 +++ b/src/net/kryshen/indyvon/component.clj Mon Aug 23 21:24:33 2010 +0400 @@ -21,22 +21,11 @@ [^Component component layer ^Graphics2D graphics event-dispatcher] (let [size (.getSize component) width (.width size) - height (.height size)] + height (.height size) + update-fn #(.repaint component)] (.clearRect graphics 0 0 width height) - ;; Setup the root layer context (move to core?). - (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) - *width* width - *height* height - *clip* (Rectangle2D$Double. 0 0 width height)] - (render! layer) - (commit event-dispatcher)))) + (context-draw! layer component graphics event-dispatcher update-fn + width height))) (defn preferred-size [component layer] (binding [*target* component
--- a/src/net/kryshen/indyvon/core.clj Mon Aug 23 14:06:13 2010 +0400 +++ b/src/net/kryshen/indyvon/core.clj Mon Aug 23 21:24:33 2010 +0400 @@ -19,7 +19,9 @@ (def ^FontRenderContext *font-context*) -(def ^Component *target*) +(def ^{:tag Component + :doc "Target AWT component, may be nil if drawing off-screen."} + *target*) (def *width*) @@ -238,6 +240,26 @@ ([layer x y width height] (with-bounds* x y width height render! layer))) +(defn context-draw! + "Sets up layer context, draws layer and commits event dispatcher." + ([layer graphics event-dispatcher update-fn width height] + (draw! layer nil graphics event-dispatcher update-fn width height)) + ([layer component ^Graphics2D graphics event-dispatcher update-fn + width height] + (binding [*graphics* graphics + *font-context* (.getFontRenderContext graphics) + *initial-transform* (.getTransform graphics) + *inverse-initial-transform* + (-> graphics .getTransform .createInverse) + *target* component + *update* update-fn + *event-dispatcher* event-dispatcher + *width* width + *height* height + *clip* (Rectangle2D$Double. 0 0 width height)] + (render! layer) + (commit event-dispatcher)))) + (defn draw-anchored! "Draws layer. Location is relative to the layer's anchor point for the specified alignment." @@ -261,6 +283,13 @@ java.awt.event.MouseEvent/MOUSE_PRESSED :mouse-pressed java.awt.event.MouseEvent/MOUSE_RELEASED :mouse-released}) +(def dummy-event-dispatcher + (reify + EventDispatcher + (listen! [this component]) + (create-dispatcher [this handle handlers] this) + (commit [this]))) + (defrecord DispatcherNode [handle handlers parent ^Shape clip ^AffineTransform transform bindings]
--- a/src/net/kryshen/indyvon/layers.clj Mon Aug 23 14:06:13 2010 +0400 +++ b/src/net/kryshen/indyvon/layers.clj Mon Aug 23 21:24:33 2010 +0400 @@ -173,16 +173,6 @@ height (if (pos? height) height 1)] (Size. width height)))))) -;; (defn- validate-buffer [^Image image restore-fn] -;; (if (and image -;; (>= (.getWidth image nil) *width*) -;; (>= (.getHeight image nil) *height*)) -;; image -;; ;;(let [image (BufferedImage. *width* *height* BufferedImage/TYPE_INT_ARGB)] -;; (let [image (.createImage *target* *width* *height*)] -;; (restore-fn image) -;; image))) - (defn async-layer "Creates layer that draws the content asynchroniously in an offscreen buffer." @@ -191,38 +181,42 @@ (let [executor (ThreadPoolExecutor. 1 1 0 TimeUnit/SECONDS (ArrayBlockingQueue. 1) (ThreadPoolExecutor$DiscardOldestPolicy.)) - buffers (ref - [(BufferedImage. width height BufferedImage/TYPE_INT_ARGB) - (BufferedImage. width height BufferedImage/TYPE_INT_ARGB)]) + buffers (ref [nil nil]) updated (ref false) + create-buffer + #(BufferedImage. width height BufferedImage/TYPE_INT_ARGB) draw-offscreen - (fn [] - (let [b (dosync (let [b (peek @buffers)] - (alter buffers pop) - b))] - ;; TODO: set complete layer context. - (binding [*graphics* (.getGraphics b) - *width* width - *height* height - ;; !!! - *update* #(.execute executor draw-offscreen)] - (render! content)) - (dosync - (alter buffers conj b) - (ref-set updated true))))] + (fn draw-offscreen [] + (let [b (dosync (let [b (peek @buffers)] + (alter buffers pop) + b))] + ;; TODO: use operational event dispatcher. + (context-draw! (.getGraphics b) + dummy-event-dispatcher + #(.execute executor draw-offscreen) + width height) + (dosync + (alter buffers conj b) + (ref-set updated true))))] (reify Layer (render! [layer] - (let [b (dosync + (let [buffer (dosync (if @updated (do (peek @buffers) (alter buffers pop) (ref-set updated false)) (do (first @buffers) (alter buffers next))))] - (.drawImage *graphics* b) - (dosync - (alter buffers #(cons b %))))) + (when buffer + (.drawImage *graphics* buffer)) + (let [new-buffer (or buffer (create-buffer))] + (dosync + (alter buffers #(cons new-buffer %))) + (when (not buffer) + ;; No cached image to draw. + ;; TODO: draw immediately. + (.execute executor draw-offscreen))))) (layer-size [layer] (Size. width height)))))