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 diff
     1.1 --- a/src/net/kryshen/indyvon/component.clj	Mon Aug 23 14:06:13 2010 +0400
     1.2 +++ b/src/net/kryshen/indyvon/component.clj	Mon Aug 23 21:24:33 2010 +0400
     1.3 @@ -21,22 +21,11 @@
     1.4    [^Component component layer ^Graphics2D graphics event-dispatcher]
     1.5    (let [size (.getSize component)
     1.6          width (.width size)
     1.7 -        height (.height size)]
     1.8 +        height (.height size)
     1.9 +        update-fn #(.repaint component)]
    1.10      (.clearRect graphics 0 0 width height)
    1.11 -    ;; Setup the root layer context (move to core?).
    1.12 -    (binding [*graphics* graphics
    1.13 -              *font-context* (.getFontRenderContext graphics)
    1.14 -              *initial-transform* (.getTransform graphics)
    1.15 -              *inverse-initial-transform*
    1.16 -                (-> graphics .getTransform .createInverse)
    1.17 -              *target* component
    1.18 -              *event-dispatcher* event-dispatcher
    1.19 -              *update* #(.repaint component)
    1.20 -              *width* width
    1.21 -              *height* height
    1.22 -              *clip* (Rectangle2D$Double. 0 0 width height)]
    1.23 -      (render! layer)
    1.24 -      (commit event-dispatcher))))
    1.25 +    (context-draw! layer component graphics event-dispatcher update-fn
    1.26 +                   width height)))
    1.27  
    1.28  (defn preferred-size [component layer]
    1.29    (binding [*target* component
     2.1 --- a/src/net/kryshen/indyvon/core.clj	Mon Aug 23 14:06:13 2010 +0400
     2.2 +++ b/src/net/kryshen/indyvon/core.clj	Mon Aug 23 21:24:33 2010 +0400
     2.3 @@ -19,7 +19,9 @@
     2.4  
     2.5  (def ^FontRenderContext *font-context*)
     2.6  
     2.7 -(def ^Component *target*)
     2.8 +(def ^{:tag Component
     2.9 +       :doc "Target AWT component, may be nil if drawing off-screen."}
    2.10 +     *target*)
    2.11  
    2.12  (def *width*)
    2.13  
    2.14 @@ -238,6 +240,26 @@
    2.15    ([layer x y width height]
    2.16       (with-bounds* x y width height render! layer)))
    2.17  
    2.18 +(defn context-draw!
    2.19 +  "Sets up layer context, draws layer and commits event dispatcher."
    2.20 +  ([layer graphics event-dispatcher update-fn width height]
    2.21 +     (draw! layer nil graphics event-dispatcher update-fn width height))
    2.22 +  ([layer component ^Graphics2D graphics event-dispatcher update-fn
    2.23 +    width height]
    2.24 +     (binding [*graphics* graphics
    2.25 +               *font-context* (.getFontRenderContext graphics)
    2.26 +               *initial-transform* (.getTransform graphics)
    2.27 +               *inverse-initial-transform*
    2.28 +                 (-> graphics .getTransform .createInverse)
    2.29 +               *target* component
    2.30 +               *update* update-fn
    2.31 +               *event-dispatcher* event-dispatcher
    2.32 +               *width* width
    2.33 +               *height* height
    2.34 +               *clip* (Rectangle2D$Double. 0 0 width height)]
    2.35 +       (render! layer)
    2.36 +       (commit event-dispatcher))))
    2.37 +
    2.38  (defn draw-anchored!
    2.39    "Draws layer. Location is relative to the layer's anchor point for
    2.40     the specified alignment."
    2.41 @@ -261,6 +283,13 @@
    2.42        java.awt.event.MouseEvent/MOUSE_PRESSED  :mouse-pressed
    2.43        java.awt.event.MouseEvent/MOUSE_RELEASED :mouse-released})
    2.44  
    2.45 +(def dummy-event-dispatcher
    2.46 +     (reify
    2.47 +      EventDispatcher
    2.48 +      (listen! [this component])
    2.49 +      (create-dispatcher [this handle handlers] this)
    2.50 +      (commit [this])))
    2.51 +
    2.52  (defrecord DispatcherNode [handle handlers parent
    2.53                             ^Shape clip ^AffineTransform transform
    2.54                             bindings]
     3.1 --- a/src/net/kryshen/indyvon/layers.clj	Mon Aug 23 14:06:13 2010 +0400
     3.2 +++ b/src/net/kryshen/indyvon/layers.clj	Mon Aug 23 21:24:33 2010 +0400
     3.3 @@ -173,16 +173,6 @@
     3.4                height (if (pos? height) height 1)]
     3.5            (Size. width height))))))
     3.6  
     3.7 -;; (defn- validate-buffer [^Image image restore-fn]
     3.8 -;;   (if (and image
     3.9 -;;            (>= (.getWidth image nil) *width*)
    3.10 -;;            (>= (.getHeight image nil) *height*))
    3.11 -;;     image
    3.12 -;;     ;;(let [image (BufferedImage. *width* *height* BufferedImage/TYPE_INT_ARGB)]
    3.13 -;;     (let [image (.createImage *target* *width* *height*)]
    3.14 -;;       (restore-fn image)
    3.15 -;;       image)))
    3.16 -
    3.17  (defn async-layer
    3.18    "Creates layer that draws the content asynchroniously in an
    3.19     offscreen buffer."
    3.20 @@ -191,38 +181,42 @@
    3.21    (let [executor (ThreadPoolExecutor. 1 1 0 TimeUnit/SECONDS
    3.22                     (ArrayBlockingQueue. 1)
    3.23                     (ThreadPoolExecutor$DiscardOldestPolicy.))
    3.24 -        buffers (ref
    3.25 -                 [(BufferedImage. width height BufferedImage/TYPE_INT_ARGB)
    3.26 -                  (BufferedImage. width height BufferedImage/TYPE_INT_ARGB)])
    3.27 +        buffers (ref [nil nil])
    3.28          updated (ref false)
    3.29 +        create-buffer
    3.30 +          #(BufferedImage. width height BufferedImage/TYPE_INT_ARGB)
    3.31          draw-offscreen
    3.32 -         (fn []
    3.33 -           (let [b (dosync (let [b (peek @buffers)]
    3.34 -                             (alter buffers pop)
    3.35 -                             b))]
    3.36 -             ;; TODO: set complete layer context.
    3.37 -             (binding [*graphics* (.getGraphics b)
    3.38 -                       *width* width
    3.39 -                       *height* height
    3.40 -                       ;; !!!
    3.41 -                       *update* #(.execute executor draw-offscreen)]
    3.42 -               (render! content))
    3.43 -             (dosync
    3.44 -              (alter buffers conj b)
    3.45 -              (ref-set updated true))))]
    3.46 +          (fn draw-offscreen []
    3.47 +            (let [b (dosync (let [b (peek @buffers)]
    3.48 +                              (alter buffers pop)
    3.49 +                              b))]
    3.50 +              ;; TODO: use operational event dispatcher.
    3.51 +              (context-draw! (.getGraphics b)
    3.52 +                             dummy-event-dispatcher
    3.53 +                             #(.execute executor draw-offscreen)
    3.54 +                             width height)
    3.55 +              (dosync
    3.56 +               (alter buffers conj b)
    3.57 +               (ref-set updated true))))]
    3.58      (reify
    3.59       Layer
    3.60       (render! [layer]
    3.61 -        (let [b (dosync
    3.62 +        (let [buffer (dosync
    3.63                   (if @updated
    3.64                     (do (peek @buffers)
    3.65                         (alter buffers pop)
    3.66                         (ref-set updated false))
    3.67                     (do (first @buffers)
    3.68                         (alter buffers next))))]
    3.69 -          (.drawImage *graphics* b)
    3.70 -          (dosync
    3.71 -           (alter buffers #(cons b %)))))
    3.72 +          (when buffer
    3.73 +            (.drawImage *graphics* buffer))
    3.74 +          (let [new-buffer (or buffer (create-buffer))]
    3.75 +            (dosync
    3.76 +             (alter buffers #(cons new-buffer %)))
    3.77 +            (when (not buffer)
    3.78 +              ;; No cached image to draw.
    3.79 +              ;; TODO: draw immediately.
    3.80 +              (.execute executor draw-offscreen)))))
    3.81       (layer-size [layer]
    3.82          (Size. width height)))))
    3.83