changeset 104:491152048c89

Added Scene record to enclose state retained between repaints.
author Mikhail Kryshen <mikhail@kryshen.net>
date Thu, 19 May 2011 20:10:45 +0400
parents 9b81174f0511
children f3dedece38f3
files src/net/kryshen/indyvon/async.clj src/net/kryshen/indyvon/component.clj src/net/kryshen/indyvon/core.clj src/net/kryshen/indyvon/layers.clj
diffstat 4 files changed, 102 insertions(+), 87 deletions(-) [+]
line diff
     1.1 --- a/src/net/kryshen/indyvon/async.clj	Thu May 19 17:01:46 2011 +0400
     1.2 +++ b/src/net/kryshen/indyvon/async.clj	Thu May 19 20:10:45 2011 +0400
     1.3 @@ -119,23 +119,21 @@
     1.4        (.setComposite g AlphaComposite/Clear)
     1.5        (.fillRect g 0 0 (:width async-layer) (:height async-layer))
     1.6        (.setComposite g AlphaComposite/Src)
     1.7 -      (draw-root! (:content async-layer)
     1.8 -                  g
     1.9 -                  (:width async-layer)
    1.10 -                  (:height async-layer)
    1.11 -                  ;; TODO: use operational event dispatcher.
    1.12 -                  dummy-event-dispatcher))
    1.13 +      (draw-scene! (:scene async-layer)
    1.14 +                   g
    1.15 +                   (:width async-layer)
    1.16 +                   (:height async-layer)))
    1.17      (update async-layer)))
    1.18  
    1.19  (defn- draw-offscreen-async [async-layer]
    1.20    (.execute ^ThreadPoolExecutor (:executor async-layer)
    1.21              #(draw-offscreen async-layer)))
    1.22  
    1.23 -(defrecord AsyncLayer [content width height executor buffers]
    1.24 +(defrecord AsyncLayer [scene width height executor buffers]
    1.25    Layer
    1.26    (render! [layer]
    1.27      (repaint-on-update layer)
    1.28 -    (add-context-observer content (fn [_ _] (draw-offscreen-async layer)))
    1.29 +    (add-context-observer scene (fn [_ _] (draw-offscreen-async layer)))
    1.30      (when-not @buffers
    1.31        ;; TODO: dynamic size, recreate buffers when size increases.
    1.32        (let [device-conf (.getDeviceConfiguration *graphics*)
    1.33 @@ -173,6 +171,9 @@
    1.34    ([content width height]
    1.35       (async-layer content width height nil))
    1.36    ([content width height priority]
    1.37 -     (AsyncLayer. content width height
    1.38 +     ;; TODO: use operational event dispatcher.
    1.39 +     (AsyncLayer. (make-scene content)
    1.40 +                  width
    1.41 +                  height
    1.42                    (create-executor priority)
    1.43                    (ref nil))))
     2.1 --- a/src/net/kryshen/indyvon/component.clj	Thu May 19 17:01:46 2011 +0400
     2.2 +++ b/src/net/kryshen/indyvon/component.clj	Thu May 19 20:10:45 2011 +0400
     2.3 @@ -36,23 +36,28 @@
     2.4                 *font-context* (font-context c#)]
     2.5         ~@body)))
     2.6  
     2.7 +(defn- paint-component [^Component c ^Graphics g scene]
     2.8 +  (let [size (.getSize c)]
     2.9 +    (.setColor g (:back-color *theme*))
    2.10 +    (.fillRect g 0 0 (.width size) (.height size))
    2.11 +    (draw-scene! scene g (.width size) (.height size))))
    2.12 +
    2.13 +(defn- preferred-size [^Component c scene]
    2.14 +  (let [s (scene-size scene (font-context c))]
    2.15 +    (Dimension. (:width s) (:height s))))
    2.16 +
    2.17  (defn ^JPanel make-jpanel
    2.18    ([layer]
    2.19       (make-jpanel layer (root-event-dispatcher)))
    2.20    ([layer event-dispatcher]
    2.21 -     (let [panel
    2.22 -           (proxy [JPanel] []
    2.23 -             (paintComponent [^Graphics g]
    2.24 -               (let [size (.getSize ^Component this)]
    2.25 -                 (.setColor g (:back-color *theme*))
    2.26 -                 (.fillRect g 0 0 (.width size) (.height size))
    2.27 -                 (draw-root! layer g (.width size) (.height size)
    2.28 -                             event-dispatcher this)))
    2.29 -             (getPreferredSize []
    2.30 -               (let [s (root-size layer (font-context this) this)]
    2.31 -                 (Dimension. (:width s) (:height s)))))]
    2.32 +     (let [panel (proxy [JPanel] [])
    2.33 +           scene (make-scene layer event-dispatcher panel)]
    2.34 +       (update-proxy
    2.35 +        panel
    2.36 +        {"paintComponent" #(paint-component %1 %2 scene)
    2.37 +         "getPreferredSize" #(preferred-size % scene)})
    2.38         (.setBackground panel (:back-color *theme*))
    2.39 -       (add-observer panel layer (fn [w _]
    2.40 +       (add-observer panel scene (fn [w _]
    2.41                                     ;; Use the first observer argument
    2.42                                     ;; instead of closing over panel to
    2.43                                     ;; allow the panel and associated
     3.1 --- a/src/net/kryshen/indyvon/core.clj	Thu May 19 17:01:46 2011 +0400
     3.2 +++ b/src/net/kryshen/indyvon/core.clj	Thu May 19 20:10:45 2011 +0400
     3.3 @@ -19,7 +19,8 @@
     3.4  
     3.5  (ns net.kryshen.indyvon.core
     3.6    (:import
     3.7 -   (java.awt Graphics2D RenderingHints Component Color Font Shape)
     3.8 +   (java.awt Graphics2D RenderingHints Component Color Font Shape
     3.9 +             Cursor EventQueue)
    3.10     (java.awt.geom AffineTransform Point2D$Double Rectangle2D$Double Area)
    3.11     (java.awt.event MouseListener MouseMotionListener
    3.12                     MouseWheelListener MouseWheelEvent)
    3.13 @@ -57,14 +58,14 @@
    3.14    *clip*)
    3.15  
    3.16  (def ^{:dynamic true
    3.17 -       :doc "The root (background) layer of the scene."}
    3.18 -  *root*)
    3.19 -
    3.20 -(def ^{:dynamic true
    3.21         :doc "Time in nanoseconds when the rendering of the current
    3.22               frame starts."}
    3.23    *time*)
    3.24  
    3.25 +(def ^{:dynamic true
    3.26 +       :doc "Encloses state that should be retained between repaints."}
    3.27 +  *scene*)
    3.28 +
    3.29  (def ^{:dynamic true}
    3.30    *event-dispatcher*)
    3.31  
    3.32 @@ -217,22 +218,21 @@
    3.33  
    3.34  (defn add-context-observer
    3.35    "Observer registered with this function will be automatically
    3.36 -  removed after the next frame rendering is complete."
    3.37 +  removed after the next repaint is complete."
    3.38    [target f]
    3.39 -  (let [root *root*]
    3.40 -    (add-observer root target f)))
    3.41 +  (add-observer *scene* target f))
    3.42  
    3.43  (defn repaint-on-update
    3.44    "Trigger repaint of the current scene when the target updates."
    3.45    [target]
    3.46 -  (let [root *root*]
    3.47 -    (if (not= root target)
    3.48 -      (add-observer root target (fn [w _] (update w))))))
    3.49 +  (let [scene *scene*]
    3.50 +    (if-not (identical? scene target)
    3.51 +      (add-observer scene target (fn [w _] (update w))))))
    3.52  
    3.53  (defn repaint
    3.54    "Repaint the current scene."
    3.55    []
    3.56 -  (update *root*))
    3.57 +  (update *scene*))
    3.58  
    3.59  ;;
    3.60  ;; Rendering
    3.61 @@ -427,56 +427,6 @@
    3.62       (let [anchor (anchor layer h-align v-align)]
    3.63         (draw! layer (- x (:x anchor)) (- y (:y anchor)) w h))))
    3.64  
    3.65 -(defn draw-root!
    3.66 -  "Draws the root layer."
    3.67 -  ([layer graphics width height event-dispatcher]
    3.68 -     (draw-root! layer graphics width height event-dispatcher nil))
    3.69 -  ([layer ^Graphics2D graphics width height event-dispatcher target]
    3.70 -     ;; (.setRenderingHint graphics
    3.71 -     ;;                    RenderingHints/KEY_INTERPOLATION
    3.72 -     ;;                    RenderingHints/VALUE_INTERPOLATION_BILINEAR)
    3.73 -     ;; (.setRenderingHint graphics
    3.74 -     ;;                    RenderingHints/KEY_ALPHA_INTERPOLATION
    3.75 -     ;;                    RenderingHints/VALUE_ALPHA_INTERPOLATION_QUALITY)
    3.76 -     ;; (.setRenderingHint graphics
    3.77 -     ;;                    RenderingHints/KEY_ANTIALIASING
    3.78 -     ;;                    RenderingHints/VALUE_ANTIALIAS_ON)
    3.79 -     ;; (.setRenderingHint graphics
    3.80 -     ;;                    RenderingHints/KEY_TEXT_ANTIALIASING
    3.81 -     ;;                    RenderingHints/VALUE_TEXT_ANTIALIAS_ON)
    3.82 -     (binding [*root* layer
    3.83 -               *target* target
    3.84 -               *graphics* graphics
    3.85 -               *font-context* (.getFontRenderContext graphics)
    3.86 -               *initial-transform* (.getTransform graphics)
    3.87 -               *inverse-initial-transform*
    3.88 -                 (-> graphics .getTransform .createInverse)
    3.89 -               *event-dispatcher* event-dispatcher
    3.90 -               *width* width
    3.91 -               *height* height
    3.92 -               *clip* (Rectangle2D$Double. 0 0 width height)
    3.93 -               *time* (System/nanoTime)]
    3.94 -       (apply-theme)
    3.95 -       (let [tmp-watcher (Object.)]
    3.96 -         ;; Keep current context observers until the rendering is
    3.97 -         ;; complete. Some observers may be invoked twice if they
    3.98 -         ;; appear in both groups until tmp-watcher is removed.
    3.99 -         (replace-observers-watcher layer tmp-watcher)
   3.100 -         (try
   3.101 -           (render! layer)
   3.102 -           (finally
   3.103 -            (remove-observers tmp-watcher)
   3.104 -            (commit event-dispatcher)))))))
   3.105 -
   3.106 -(defn root-size
   3.107 -  ([layer font-context]
   3.108 -     (root-size layer font-context nil))
   3.109 -  ([layer font-context target]
   3.110 -     (binding [*root* layer
   3.111 -               *target* target
   3.112 -               *font-context* font-context]
   3.113 -       (layer-size layer))))
   3.114 -
   3.115  ;;
   3.116  ;; Event handling.
   3.117  ;;
   3.118 @@ -667,3 +617,64 @@
   3.119         (translate-and-dispatch @picked true event))
   3.120       (mouseMoved [this event]
   3.121         (dispatch-mouse-motion hovered @tree this event)))))
   3.122 +
   3.123 +;;
   3.124 +;; Scene
   3.125 +;;
   3.126 +
   3.127 +(defrecord Scene [layer event-dispatcher component])
   3.128 +
   3.129 +(defn make-scene
   3.130 +  ([layer]
   3.131 +     (make-scene layer dummy-event-dispatcher nil))
   3.132 +  ([layer event-dispatcher]
   3.133 +     (make-scene layer event-dispatcher nil))
   3.134 +  ([layer event-dispatcher component]
   3.135 +     (Scene. layer event-dispatcher component)))
   3.136 +
   3.137 +(defn draw-scene!
   3.138 +  [scene ^Graphics2D graphics width height]
   3.139 +  ;; (.setRenderingHint graphics
   3.140 +  ;;                    RenderingHints/KEY_INTERPOLATION
   3.141 +  ;;                    RenderingHints/VALUE_INTERPOLATION_BILINEAR)
   3.142 +  ;; (.setRenderingHint graphics
   3.143 +  ;;                    RenderingHints/KEY_ALPHA_INTERPOLATION
   3.144 +  ;;                    RenderingHints/VALUE_ALPHA_INTERPOLATION_QUALITY)
   3.145 +  ;; (.setRenderingHint graphics
   3.146 +  ;;                    RenderingHints/KEY_ANTIALIASING
   3.147 +  ;;                    RenderingHints/VALUE_ANTIALIAS_ON)
   3.148 +  ;; (.setRenderingHint graphics
   3.149 +  ;;                    RenderingHints/KEY_TEXT_ANTIALIASING
   3.150 +  ;;                    RenderingHints/VALUE_TEXT_ANTIALIAS_ON)
   3.151 +  (binding [*scene* scene
   3.152 +            *graphics* graphics
   3.153 +            *font-context* (.getFontRenderContext graphics)
   3.154 +            *initial-transform* (.getTransform graphics)
   3.155 +            *inverse-initial-transform* (-> graphics
   3.156 +                                            .getTransform
   3.157 +                                            .createInverse)
   3.158 +            *event-dispatcher* (:event-dispatcher scene)
   3.159 +            *width* width
   3.160 +            *height* height
   3.161 +            *clip* (Rectangle2D$Double. 0 0 width height)
   3.162 +            *time* (System/nanoTime)]
   3.163 +    (apply-theme)
   3.164 +    (let [tmp-watcher (Object.)]
   3.165 +      ;; Keep current context observers until the rendering is
   3.166 +      ;; complete. Some observers may be invoked twice if they
   3.167 +      ;; appear in both groups until tmp-watcher is removed.
   3.168 +      (replace-observers-watcher scene tmp-watcher)
   3.169 +      (try
   3.170 +        (render! (:layer scene))
   3.171 +        (finally
   3.172 +         (remove-observers tmp-watcher)
   3.173 +         (commit (:event-dispatcher scene)))))))
   3.174 +  
   3.175 +(defn scene-size [scene font-context]
   3.176 +  (binding [*scene* scene
   3.177 +            *font-context* font-context]
   3.178 +    (layer-size (:layer scene))))
   3.179 +
   3.180 +(defn set-cursor! [^Cursor cursor]
   3.181 +  (when-let [^Component component (:component *scene*)]
   3.182 +    (EventQueue/invokeLater #(.setCursor component cursor))))
     4.1 --- a/src/net/kryshen/indyvon/layers.clj	Thu May 19 17:01:46 2011 +0400
     4.2 +++ b/src/net/kryshen/indyvon/layers.clj	Thu May 19 20:10:45 2011 +0400
     4.3 @@ -333,11 +333,9 @@
     4.4         (dosync
     4.5          (ref-set fix-x (:x-on-screen e))
     4.6          (ref-set fix-y (:y-on-screen e)))
     4.7 -       (when *target*
     4.8 -         (->> Cursor/MOVE_CURSOR Cursor. (.setCursor *target*))))
     4.9 +       (set-cursor! (Cursor. Cursor/MOVE_CURSOR)))
    4.10        (:mouse-released e
    4.11 -       (when *target*
    4.12 -         (->> Cursor/DEFAULT_CURSOR Cursor. (.setCursor *target*))))
    4.13 +       (set-cursor! (Cursor. Cursor/DEFAULT_CURSOR)))
    4.14        (:mouse-dragged e
    4.15         (dosync
    4.16          (alter transform pre-translate