changeset 44:064b21604f74

Improved performance. Added image layer.
author Mikhail Kryshen <mikhail@kryshen.net>
date Mon, 19 Jul 2010 15:36:08 +0400
parents 7d67064f0880
children 33d836041cef
files src/kryshen/indyvon/core.clj src/kryshen/indyvon/graph.clj src/kryshen/indyvon/layers.clj
diffstat 3 files changed, 99 insertions(+), 46 deletions(-) [+]
line diff
     1.1 --- a/src/kryshen/indyvon/core.clj	Mon Jul 12 03:52:21 2010 +0400
     1.2 +++ b/src/kryshen/indyvon/core.clj	Mon Jul 19 15:36:08 2010 +0400
     1.3 @@ -95,33 +95,32 @@
     1.4             y2 (min y12 y22)]
     1.5         (Bounds. x1 y1 (- x2 x1) (- y2 y1)))))
     1.6  
     1.7 -(defn- ^Graphics2D create-graphics
     1.8 +(defn ^Graphics2D create-graphics
     1.9    ([]
    1.10       (create-graphics 0 0 (:width *bounds*) (:height *bounds*)))
    1.11    ([x y w h]
    1.12       (apply-theme (.create *graphics* x y w h) *theme*)))
    1.13  
    1.14 -(defn with-bounds* [x y w h f & args]
    1.15 -  (let [graphics (create-graphics x y w h)
    1.16 -        bounds (Bounds. (+ x (:x *bounds*))
    1.17 -                        (+ y (:y *bounds*))
    1.18 -                        w h)]
    1.19 -    (try
    1.20 -      (apply with-bindings* {#'*bounds* bounds
    1.21 -                             #'*clip* (intersect bounds *clip*)
    1.22 -                             #'*graphics* graphics}
    1.23 -             f args)
    1.24 -      (finally
    1.25 -       (.dispose graphics)))))
    1.26 +(defmacro with-bounds [x y w h & body]
    1.27 +  `(let [bounds# (Bounds. (+ ~x (:x *bounds*))
    1.28 +                          (+ ~y (:y *bounds*))
    1.29 +                          ~w ~h)
    1.30 +         clip# (intersect bounds# *clip*)]
    1.31 +     (when (and (pos? (:width clip#)) (pos? (:height clip#)))
    1.32 +       (let [graphics# (create-graphics ~x ~y ~w ~h)]
    1.33 +         (try
    1.34 +           (binding [*bounds* bounds#
    1.35 +                     *clip* clip#
    1.36 +                     *graphics* graphics#]
    1.37 +             ~@body)
    1.38 +           (finally
    1.39 +            (.dispose graphics#)))))))
    1.40  
    1.41 -(defmacro with-bounds [x y w h & body]
    1.42 -  `(with-bounds* ~x ~y ~w ~h (fn [] ~@body)))
    1.43 -
    1.44 -(defn with-handlers* [handle handlers f & args]
    1.45 -  (apply with-bindings*
    1.46 -         {#'*event-dispatcher*
    1.47 -          (create-dispatcher *event-dispatcher* handle handlers)}
    1.48 -         f args))
    1.49 +(defmacro with-handlers* [handle handlers & body]
    1.50 +  `(binding
    1.51 +       [*event-dispatcher*
    1.52 +        (create-dispatcher *event-dispatcher* ~handle ~handlers)]
    1.53 +     ~@body))
    1.54  
    1.55  (defmacro with-handlers
    1.56    "specs => (:event-id name & handler-body)*
    1.57 @@ -134,14 +133,15 @@
    1.58                         `(fn [~(second spec)]
    1.59                            ~@(nnext spec)))) {}
    1.60                            specs)
    1.61 -     (fn [] ~form)))
    1.62 +     ~form))
    1.63  
    1.64  (defn with-theme* [theme f & args]
    1.65    (apply with-bindings* {#'*theme* (merge *theme* theme)}
    1.66           f args))
    1.67  
    1.68  (defmacro with-theme [theme & body]
    1.69 -  `(with-theme* ~theme (fn [] ~@body)))
    1.70 +  `(binding [*theme* (merge *theme* ~theme)]
    1.71 +     ~@body))
    1.72  
    1.73  (defmacro with-color [color & body]
    1.74    `(let [color# (.getColor *graphics*)]
    1.75 @@ -160,14 +160,16 @@
    1.76    ([layer]
    1.77       (let [graphics (create-graphics)]
    1.78         (try
    1.79 -         (with-bindings* {#'*graphics* graphics} render! layer)
    1.80 +         (binding [*graphics* graphics]
    1.81 +           (render! layer))
    1.82           (finally
    1.83            (.dispose graphics)))))
    1.84    ([layer x y]
    1.85       (let [size (layer-size layer)]
    1.86         (draw! layer x y (:width size) (:height size))))
    1.87    ([layer x y width height]
    1.88 -     (with-bounds* x y width height render! layer)))
    1.89 +     (with-bounds x y width height
    1.90 +       (render! layer))))
    1.91  
    1.92  (defn draw-anchored!
    1.93    "Draw with location relative to the anchor point."
    1.94 @@ -305,7 +307,8 @@
    1.95       (mousePressed [this event]
    1.96          (dispatch-mouse-button picked hovered event))
    1.97       (mouseReleased [this event]
    1.98 -        (dispatch-mouse-button picked hovered event))
    1.99 +        (translate-and-dispatch @picked true event))
   1.100 +        ;;(dispatch-mouse-button picked hovered event))
   1.101       MouseMotionListener
   1.102       (mouseDragged [this event]
   1.103          (translate-and-dispatch @picked true event))
     2.1 --- a/src/kryshen/indyvon/graph.clj	Mon Jul 12 03:52:21 2010 +0400
     2.2 +++ b/src/kryshen/indyvon/graph.clj	Mon Jul 19 15:36:08 2010 +0400
     2.3 @@ -76,29 +76,29 @@
     2.4      (.draw *graphics* path)))
     2.5    (.translate *graphics* (- x) (- y)))
     2.6  
     2.7 -(defrecord GraphLayer [graph-layout movable dragged fix-x fix-y]
     2.8 +(defrecord GraphLayer [layout movable dragged fix-x fix-y]
     2.9    Layer
    2.10    (render! [layer]
    2.11 -     (let [bounds (.getBounds graph-layout)
    2.12 +     (let [bounds (.getBounds layout)
    2.13             x (- (.getX bounds))
    2.14             y (- (.getY bounds))]
    2.15 -       (draw-edges! graph-layout x y)
    2.16 +       (draw-edges! layout x y)
    2.17         (if movable
    2.18 -         (draw-movable-vertices! graph-layout x y dragged fix-x fix-y)
    2.19 -         (draw-vertices! graph-layout x y))))
    2.20 +         (draw-movable-vertices! layout x y dragged fix-x fix-y)
    2.21 +         (draw-vertices! layout x y))))
    2.22    (layer-size [layer]
    2.23 -     (let [bounds (.getBounds graph-layout)]
    2.24 +     (let [bounds (.getBounds layout)]
    2.25         (Size. (.getWidth bounds) (.getHeight bounds))))
    2.26    Anchored
    2.27    (anchor [layer x-align y-align]
    2.28 -          (let [bounds (.getBounds graph-layout)]
    2.29 +          (let [bounds (.getBounds layout)]
    2.30              (Location. (- (.getX bounds))
    2.31                         (- (.getY bounds))))))
    2.32  
    2.33  (defn graph-layer
    2.34    ([graph-layout]
    2.35       (graph-layer graph-layout false))
    2.36 -  ([^GraphGraph-Layout graph-layout movable]
    2.37 +  ([^GraphLayout graph-layout movable]
    2.38       (GraphLayer. graph-layout movable (ref nil) (ref 0) (ref 0))))
    2.39  
    2.40  (defn build-graph
     3.1 --- a/src/kryshen/indyvon/layers.clj	Mon Jul 12 03:52:21 2010 +0400
     3.2 +++ b/src/kryshen/indyvon/layers.clj	Mon Jul 19 15:36:08 2010 +0400
     3.3 @@ -7,7 +7,9 @@
     3.4  (ns kryshen.indyvon.layers
     3.5    (:use kryshen.indyvon.core)
     3.6    (:import (kryshen.indyvon.core Size Location)
     3.7 -           (java.awt Font Cursor)
     3.8 +           (java.lang.ref SoftReference)
     3.9 +           (java.awt Font Cursor Image Toolkit)
    3.10 +           (java.awt.image ImageObserver)
    3.11             (java.awt.font FontRenderContext TextLayout)))
    3.12  
    3.13  ;; Define as macro to avoid unnecessary calculation of inner and outer
    3.14 @@ -25,12 +27,13 @@
    3.15    `(align-xy ~inner ~outer ~align :top :center :bottom))
    3.16  
    3.17  (defmacro decorate-layer [layer & render-tail]
    3.18 -  `(reify
    3.19 -    Layer
    3.20 -    (render! ~@render-tail)
    3.21 -    (layer-size [t#] (layer-size ~layer))
    3.22 -    Anchored
    3.23 -    (anchor [t# xa# ya#] (anchor ~layer xa# ya#))))
    3.24 +  `(let [layer# ~layer]
    3.25 +     (reify
    3.26 +      Layer
    3.27 +      (render! ~@render-tail)
    3.28 +      (layer-size [t#] (layer-size layer#))
    3.29 +      Anchored
    3.30 +      (anchor [t# xa# ya#] (anchor layer# xa# ya#)))))
    3.31  
    3.32  (defn padding
    3.33    ([content pad]
    3.34 @@ -81,8 +84,24 @@
    3.35  (defn- re-split [^java.util.regex.Pattern re s]
    3.36    (seq (.split re s)))
    3.37  
    3.38 -(defn- layout-text [lines ^Font font ^FontRenderContext font-context]
    3.39 -  (map #(TextLayout. ^String % font font-context) lines))
    3.40 +(def text-layout-cache (atom {}))
    3.41 +
    3.42 +(defn- get-text-layout
    3.43 +  [^String line ^Font font ^FontRenderContext font-context]
    3.44 +  (let [key [line font font-context]]
    3.45 +    (or (if-let [softref (@text-layout-cache key)]
    3.46 +          (.get softref)
    3.47 +          (do (swap! text-layout-cache dissoc key)
    3.48 +              false))
    3.49 +        (let [layout (TextLayout. line font font-context)]
    3.50 +          (println "text-layout-cache miss" line)
    3.51 +          (swap! text-layout-cache assoc key (SoftReference. layout))
    3.52 +          layout))))
    3.53 +
    3.54 +(defn- layout-text
    3.55 +  [lines ^Font font ^FontRenderContext font-context]
    3.56 +  (map #(get-text-layout % font font-context) lines))
    3.57 +  ;;(map #(TextLayout. ^String % font font-context) lines))
    3.58  
    3.59  (defn- text-width [layouts]
    3.60    (reduce (fn [w ^TextLayout tl] (max w (.getAdvance tl))) 0 layouts))
    3.61 @@ -119,6 +138,34 @@
    3.62                   height (text-height layouts)]
    3.63               (Size. width height)))))))
    3.64  
    3.65 +(defn- image-observer [update-fn]
    3.66 +  (reify
    3.67 +   ImageObserver
    3.68 +   (imageUpdate [this img infoflags x y width height]
    3.69 +      (update-fn)
    3.70 +      (zero? (bit-and infoflags
    3.71 +                      (bit-or ImageObserver/ALLBITS
    3.72 +                              ImageObserver/ABORT))))))
    3.73 +
    3.74 +(defn image-layer
    3.75 +  [image-or-uri]
    3.76 +  (let [^Image image (if (isa? image-or-uri Image)
    3.77 +                       image-or-uri
    3.78 +                       (.createImage (Toolkit/getDefaultToolkit)
    3.79 +                                     ^java.net.URL image-or-uri))]
    3.80 +    (.prepareImage (Toolkit/getDefaultToolkit) image -1 -1 nil)
    3.81 +    (reify
    3.82 +     Layer
    3.83 +     (render! [layer]
    3.84 +        (.drawImage *graphics* image 0 0 (image-observer *update*)))
    3.85 +     (layer-size [layer]
    3.86 +        (let [observer (image-observer *update*)
    3.87 +              width (.getWidth image observer)
    3.88 +              height (.getHeight image observer)
    3.89 +              width (if (pos? width) width 1)
    3.90 +              height (if (pos? height) height 1)]
    3.91 +          (Size. width height))))))
    3.92 +
    3.93  (defn viewport
    3.94    "Creates scrollable viewport layer."
    3.95    ([content] (viewport content :left :top))
    3.96 @@ -175,9 +222,12 @@
    3.97      (reify
    3.98       Layer
    3.99       (render! [t]
   3.100 -        (with-theme* theme render! layer))
   3.101 +        (with-theme theme
   3.102 +          (render! layer)))
   3.103       (layer-size [t]
   3.104 -        (with-theme* theme layer-size layer))
   3.105 +        (with-theme theme
   3.106 +          (layer-size layer)))
   3.107       Anchored
   3.108       (anchor [t xa ya]
   3.109 -        (with-theme* theme anchor layer xa ya)))))
   3.110 +        (with-theme theme
   3.111 +          (anchor layer xa ya))))))