changeset 61:88bb47e3a401

Asynchronous drawing (first working version).
author Mikhail Kryshen <mikhail@kryshen.net>
date Wed, 25 Aug 2010 22:03:01 +0400
parents 7e456697924d
children 44a7acf60c16
files src/net/kryshen/indyvon/core.clj src/net/kryshen/indyvon/demo.clj src/net/kryshen/indyvon/layers.clj
diffstat 3 files changed, 47 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/net/kryshen/indyvon/core.clj	Mon Aug 23 21:24:33 2010 +0400
+++ b/src/net/kryshen/indyvon/core.clj	Wed Aug 25 22:03:01 2010 +0400
@@ -138,10 +138,12 @@
 (defn- ^Graphics2D apply-theme
   "Set graphics' color and font to match theme.
    Modifies and returns the first argument."
-  [^Graphics2D graphics theme]
+  ([]
+     (apply-theme *graphics* *theme*))
+  ([^Graphics2D graphics theme]
   (doto graphics
     (.setColor (:fore-color theme))
-    (.setFont (:font theme))))
+    (.setFont (:font theme)))))
 
 (defn- ^Graphics2D create-graphics
   ([]
@@ -243,7 +245,7 @@
 (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))
+     (context-draw! layer nil graphics event-dispatcher update-fn width height))
   ([layer component ^Graphics2D graphics event-dispatcher update-fn
     width height]
      (binding [*graphics* graphics
@@ -257,6 +259,7 @@
                *width* width
                *height* height
                *clip* (Rectangle2D$Double. 0 0 width height)]
+       (apply-theme)
        (render! layer)
        (commit event-dispatcher))))
 
--- a/src/net/kryshen/indyvon/demo.clj	Mon Aug 23 21:24:33 2010 +0400
+++ b/src/net/kryshen/indyvon/demo.clj	Wed Aug 25 22:03:01 2010 +0400
@@ -21,7 +21,7 @@
       (render! [layer]
          (with-handlers layer
            (doto *graphics*
-             (.setColor Color/RED)
+             (.setColor (rand-nth [Color/RED Color/ORANGE]))
              (.fillRect 0 0 *width* *height*))
            (:mouse-entered e (println e))
            (:mouse-exited e (println e))
@@ -30,6 +30,8 @@
 
 (def layer1b (border layer1 2 3))
 
+(def layer1c (async-layer layer1 20 30))
+
 (def layer2
      (reify
       Layer
@@ -39,7 +41,7 @@
            (.fillRect 0 0 *width* *height*))
          (with-rotate 0.5 0 0
            (draw! layer1b 30 25))
-         (draw! layer1 55 5))
+         (draw! layer1c 55 5))
       (layer-size [layer] (Size. 70 65))))
 
 (def layer3
@@ -71,7 +73,7 @@
      (reify
       Layer
       (render! [layer]
-         (*update*)
+         ;;(*update*)
          (doto *graphics*
            (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED]))
            (.drawLine 0 0 *width* *height*))
--- a/src/net/kryshen/indyvon/layers.clj	Mon Aug 23 21:24:33 2010 +0400
+++ b/src/net/kryshen/indyvon/layers.clj	Wed Aug 25 22:03:01 2010 +0400
@@ -177,46 +177,56 @@
   "Creates layer that draws the content asynchroniously in an
    offscreen buffer."
   [content width height]
-  ;; TODO: dynamic size.
-  (let [executor (ThreadPoolExecutor. 1 1 0 TimeUnit/SECONDS
+  (let [executor (ThreadPoolExecutor. (int 1) (int 1) (long 0) TimeUnit/SECONDS
                    (ArrayBlockingQueue. 1)
                    (ThreadPoolExecutor$DiscardOldestPolicy.))
-        buffers (ref [nil nil])
+        buffers (ref nil)
         updated (ref false)
+        update-fn (ref nil)
         create-buffer
           #(BufferedImage. width height BufferedImage/TYPE_INT_ARGB)
         draw-offscreen
           (fn draw-offscreen []
-            (let [b (dosync (let [b (peek @buffers)]
+            ;;(Thread/sleep 3000)
+            (let [^Image 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))))]
+              (try
+                ;; TODO: use operational event dispatcher.
+                (context-draw! content
+                               (.getGraphics b)
+                               dummy-event-dispatcher
+                               #(.execute executor draw-offscreen)
+                               width height)
+                (finally
+                 (dosync
+                  (alter buffers conj b)
+                  (ref-set updated true))))
+                (update-fn)))]
     (reify
      Layer
      (render! [layer]
+        (when-not @buffers
+          ;; TODO: dynamic size, recreate buffers when size increases.
+          (let [new-buffers [(create-buffer) (create-buffer)]]
+            (dosync
+             (ref-set buffers new-buffers)
+             (ref-set update-fn *update*)))
+          (.execute executor draw-offscreen))
         (let [buffer (dosync
+                 (ref-set update-fn *update*)
                  (if @updated
-                   (do (peek @buffers)
-                       (alter buffers pop)
-                       (ref-set updated false))
-                   (do (first @buffers)
-                       (alter buffers next))))]
-          (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)))))
+                   (let [b (peek @buffers)]
+                     (alter buffers pop)
+                     (ref-set updated false)
+                     b)
+                   (let [b (first @buffers)]
+                     (alter buffers subvec 1)
+                     b)))]
+          (.drawImage *graphics* ^Image buffer 0 0 nil)
+          (dosync
+           (alter buffers #(vec (cons buffer %))))))
      (layer-size [layer]
         (Size. width height)))))