changeset 34:6975b9a71eec

Finally use var bindings instead of a context record.
author Mikhail Kryshen <mikhail@kryshen.net>
date Thu, 08 Jul 2010 05:27:54 +0400
parents 439f6ecee119 828795987d4c
children 0d593970cb76
files src/indyvon/component.clj src/indyvon/core.clj src/indyvon/layers.clj
diffstat 3 files changed, 182 insertions(+), 186 deletions(-) [+]
line diff
     1.1 --- a/src/indyvon/component.clj	Wed Jul 07 07:17:08 2010 +0400
     1.2 +++ b/src/indyvon/component.clj	Thu Jul 08 05:27:54 2010 +0400
     1.3 @@ -5,54 +5,50 @@
     1.4  ;;
     1.5  
     1.6  (ns indyvon.component
     1.7 -  (:use indyvon.core indyvon.layers)
     1.8 -  (:import (indyvon.core Size Location)
     1.9 -           (java.awt Component Graphics2D Dimension Color)
    1.10 +  (:use indyvon.core
    1.11 +        indyvon.layers)
    1.12 +  (:import (indyvon.core Size Bounds)
    1.13 +           (java.awt Graphics2D Component Dimension Color)
    1.14             (javax.swing JFrame JPanel)))
    1.15  
    1.16  (defn- font-context [^Component component]
    1.17    (.getFontRenderContext (.getFontMetrics component (.getFont component))))
    1.18  
    1.19  (defn paint-component
    1.20 -  [^Component component layer context ^Graphics2D graphics]
    1.21 +  [^Component component layer ^Graphics2D graphics event-dispatcher]
    1.22    (let [size (.getSize component)
    1.23          width (.width size)
    1.24 -        height (.height size)
    1.25 -        context (assoc context
    1.26 -                  :x 0
    1.27 -                  :y 0
    1.28 -                  :width width
    1.29 -                  :height height
    1.30 -                  :clip (indyvon.core.Bounds. 0 0 width height)
    1.31 -                  :target component
    1.32 -                  :graphics graphics
    1.33 -                  :font-context (.getFontRenderContext graphics)
    1.34 -                  :update-fn #(.repaint component))]
    1.35 +        height (.height size)]
    1.36      (.clearRect graphics 0 0 width height)
    1.37 -    (draw! layer context))
    1.38 -  (commit (:event-dispatcher context)))
    1.39 +    (let [bounds (Bounds. 0 0 width height)]
    1.40 +      (binding [*graphics* graphics
    1.41 +                *font-context* (.getFontRenderContext graphics)
    1.42 +                *target* component
    1.43 +                *event-dispatcher* event-dispatcher
    1.44 +                *update* #(.repaint component)
    1.45 +                *bounds* bounds
    1.46 +                *clip* bounds]
    1.47 +        (render! layer nil)
    1.48 +        (commit event-dispatcher)))))
    1.49  
    1.50 -(defn preferred-size [component layer context]
    1.51 -  (let [context (assoc context
    1.52 -                  :target component
    1.53 -                  :font-context (font-context component))
    1.54 -        s (size layer context)]
    1.55 -    (Dimension. (:width s) (:height s))))
    1.56 +(defn preferred-size [component layer]
    1.57 +  (binding [*target* component
    1.58 +            *font-context*' (font-context component)]
    1.59 +    (let [s (size layer nil)]
    1.60 +      (Dimension. (:width s) (:height s)))))
    1.61  
    1.62  (defn make-jpanel
    1.63    ([layer]
    1.64       (make-jpanel layer (root-event-dispatcher)))
    1.65    ([layer event-dispatcher]
    1.66 -     (let [context (default-context)
    1.67 -           context (assoc context :event-dispatcher event-dispatcher)
    1.68 -           panel
    1.69 +     (let [panel
    1.70             (proxy [JPanel] []
    1.71               (paintComponent [g]
    1.72 -                (paint-component this layer context g))
    1.73 +                (paint-component this layer g event-dispatcher))
    1.74               (getPreferredSize []
    1.75 -                (preferred-size this layer context)))]
    1.76 +                (preferred-size this layer)))]
    1.77 +       (.setBackground panel (:back-color *theme*))
    1.78         (listen! event-dispatcher panel)
    1.79 -       (.setBackground panel (-> context :theme :back-color))
    1.80         panel)))
    1.81  
    1.82  (comment
    1.83 @@ -62,28 +58,28 @@
    1.84      (def layer1
    1.85           (reify
    1.86            Layer
    1.87 -          (render! [this context]
    1.88 -             (let-handlers this [context]
    1.89 -               (doto (graphics context)
    1.90 +          (render! [layer opts]
    1.91 +             (with-handlers layer
    1.92 +               (doto *graphics*
    1.93                   (.setColor Color/RED)
    1.94 -                 (.fillRect 0 0 (:width context) (:height context)))
    1.95 +                 (.fillRect 0 0 (:width *bounds*) (:height *bounds*)))
    1.96                 (:mouse-entered e (println e))
    1.97                 (:mouse-exited e (println e))
    1.98                 (:mouse-moved e (println e))))
    1.99 -          (size [this context] (Size. 30 20))))
   1.100 +          (size [layer opts] (Size. 30 20))))
   1.101      
   1.102      (def layer1b (border-layer layer1 2 3))
   1.103      
   1.104      (def layer2
   1.105           (reify
   1.106            Layer
   1.107 -          (render! [this context]
   1.108 -             (doto (graphics context)
   1.109 +          (render! [layer opts]
   1.110 +             (doto *graphics*
   1.111                 (.setColor Color/YELLOW)
   1.112 -               (.fillRect 0 0 (:width context) (:height context)))
   1.113 -             (draw! layer1b context 10 5)
   1.114 -             (draw! layer1 context 55 5))
   1.115 -          (size [this context] (Size. 70 65))))
   1.116 +               (.fillRect 0 0 (:width *bounds*) (:height *bounds*)))
   1.117 +             (draw! layer1b [10 5])
   1.118 +             (draw! layer1 [55 5]))
   1.119 +          (size [layer opts] (Size. 70 65))))
   1.120      
   1.121      (def layer3
   1.122           (border-layer (text-layer "Sample\ntext" :right :center)))
   1.123 @@ -98,8 +94,8 @@
   1.124                 fl (ref (fps-layer 0.0))]
   1.125             (reify
   1.126              Layer
   1.127 -            (render! [this c]
   1.128 -               (draw! @fl c)
   1.129 +            (render! [layer opts]
   1.130 +               (render! @fl nil)
   1.131                 (dosync
   1.132                  (alter frames + 1)
   1.133                  (let [time (System/currentTimeMillis)
   1.134 @@ -108,19 +104,19 @@
   1.135                      (ref-set fl (fps-layer (/ @frames elapsed)))
   1.136                      (ref-set frames 0)
   1.137                      (ref-set last time)))))
   1.138 -            (size [this c] (size @fl c)))))
   1.139 +            (size [layer opts] (size @fl nil)))))
   1.140      
   1.141      (def layer
   1.142           (reify Layer
   1.143 -           (render! [this context]
   1.144 -             (update context)
   1.145 -             (doto (graphics context)       
   1.146 +           (render! [layer opts]
   1.147 +             (*update*)
   1.148 +             (doto *graphics*
   1.149                 (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED]))
   1.150 -               (.drawLine 0 0 (:width context) (:height context)))
   1.151 -             (draw! layer2 context 15 20)
   1.152 -             (draw! layer3 context 100 100 80 50)
   1.153 -             (draw! fps context))
   1.154 -           (size [this context] (Size. 400 300))))
   1.155 +               (.drawLine 0 0 (:width *bounds*) (:height *bounds*)))
   1.156 +             (draw! layer2 [15 20])
   1.157 +             (draw! layer3 [100 100 80 50])
   1.158 +             (render! fps nil))
   1.159 +           (size [layer opts] (Size. 400 300))))
   1.160      
   1.161      (doto frame
   1.162        (.addWindowListener
     2.1 --- a/src/indyvon/core.clj	Wed Jul 07 07:17:08 2010 +0400
     2.2 +++ b/src/indyvon/core.clj	Thu Jul 08 05:27:54 2010 +0400
     2.3 @@ -6,24 +6,40 @@
     2.4  
     2.5  (ns indyvon.core
     2.6    (:import (java.awt Graphics2D Component Color Font)
     2.7 -           (java.awt.event MouseListener MouseMotionListener)))
     2.8 +           (java.awt.event MouseListener MouseMotionListener)
     2.9 +           (java.awt.font FontRenderContext)))
    2.10  
    2.11 -(defprotocol Layer
    2.12 -  "Basic UI element."
    2.13 -  (render! [this context])
    2.14 -  (size [this context]))
    2.15 +(def ^Graphics2D *graphics*)
    2.16 +(def ^FontRenderContext *font-context*)
    2.17 +(def ^Component *target*)
    2.18 +(def *bounds*)
    2.19 +(def *clip*)
    2.20 +(def *update*)
    2.21 +(def *event-dispatcher*)
    2.22 +
    2.23 +(defrecord Theme [fore-color back-color border-color font])
    2.24 +
    2.25 +(defn default-theme []
    2.26 +  (Theme. Color/BLACK Color/WHITE Color/BLUE (Font. "Sans" Font/PLAIN 12)))
    2.27 +
    2.28 +(def *theme* (default-theme))
    2.29  
    2.30  (defrecord Location [x y])
    2.31  (defrecord Size [width height])
    2.32  (defrecord Bounds [x y width height])
    2.33  
    2.34 +(defprotocol Layer
    2.35 +  "Basic UI element."
    2.36 +  (render! [this opts])
    2.37 +  (size [this opts]))
    2.38 +
    2.39  ;; TODO: modifiers
    2.40  (defrecord MouseEvent [id when x y x-on-screen y-on-screen button])
    2.41  
    2.42  (defprotocol EventDispatcher
    2.43    (listen! [this ^Component component]
    2.44       "Listen for events on the specified AWT Component.")
    2.45 -  (create-dispatcher [this context handle handlers]
    2.46 +  (create-dispatcher [this handle handlers]
    2.47       "Returns new event dispatcher associated with the specified event
    2.48        handlers (an event-id -> handler-fn map). Handle is used to
    2.49        match the contexts between commits.")
    2.50 @@ -32,18 +48,18 @@
    2.51  
    2.52  (defprotocol Anchored
    2.53    "Provide anchor point for Layers. Used by viewport."
    2.54 -  (anchor [this context h-align v-align]
    2.55 +  (anchor [this h-align v-align opts]
    2.56       "Anchor point: [x y], h-align could be :left, :center or :right,
    2.57        v-align is :top, :center or :bottom"))
    2.58  
    2.59  ;; Default implementation of Anchored for any Layer.
    2.60  (extend-protocol Anchored
    2.61    indyvon.core.Layer
    2.62 -  (anchor [this context h-align v-align]
    2.63 +  (anchor [this h-align v-align opts]
    2.64            (if (and (= h-align :left)
    2.65                     (= v-align :top))
    2.66              (Location. 0 0)
    2.67 -            (let [size (size this context)]
    2.68 +            (let [size (size this opts)]
    2.69                (Location.
    2.70                 (case h-align
    2.71                       :top 0
    2.72 @@ -54,26 +70,6 @@
    2.73                       :center (/ (:height size) 2)
    2.74                       :bottom (:height size)))))))
    2.75  
    2.76 -(defrecord Theme [fore-color back-color border-color font])
    2.77 -
    2.78 -(defn default-theme []
    2.79 -  (Theme. Color/BLACK Color/WHITE Color/BLUE (Font. "Sans" Font/PLAIN 12)))
    2.80 -  
    2.81 -(defrecord LayerContext [x y width height clip
    2.82 -                         update-fn font-context theme
    2.83 -                         target event-dispatcher])
    2.84 -
    2.85 -(defn default-context []
    2.86 -  (LayerContext. 0 0 0 0 nil nil nil (default-theme) nil nil))
    2.87 -
    2.88 -(defn update [context]
    2.89 -  ((:update-fn context)))
    2.90 -
    2.91 -(defn ^Graphics2D graphics
    2.92 -  "Get AWT Graphics2D from context."
    2.93 -  [context]
    2.94 -  (:graphics context))
    2.95 -
    2.96  (defn- ^Graphics2D make-graphics [^Graphics2D graphics x y w h]
    2.97    (.create graphics x y w h))
    2.98  
    2.99 @@ -82,69 +78,72 @@
   2.100      (.setColor (:fore-color theme))
   2.101      (.setFont (:font theme))))
   2.102  
   2.103 -(defn intersect [bounds x y w h]
   2.104 -  (let [x12 (+ x w)
   2.105 -        y12 (+ y h)
   2.106 -        x21 (:x bounds)
   2.107 -        y21 (:y bounds)
   2.108 -        x22 (+ x21 (:width bounds))
   2.109 -        y22 (+ y21 (:height bounds))
   2.110 -        x1 (max x x21)
   2.111 -        y1 (max y y21)
   2.112 +(defn intersect [b1 b2]
   2.113 +  (let [x11 (:x b1)
   2.114 +        y11 (:y b1)
   2.115 +        x12 (+ x11 (:width b1))
   2.116 +        y12 (+ y11 (:height b1))
   2.117 +        x21 (:x b2)
   2.118 +        y21 (:y b2)
   2.119 +        x22 (+ x21 (:width b2))
   2.120 +        y22 (+ y21 (:height b2))
   2.121 +        x1 (max x11 x21)
   2.122 +        y1 (max y11 y21)
   2.123          x2 (min x12 x22)
   2.124          y2 (min y12 y22)]
   2.125      (Bounds. x1 y1 (- x2 x1) (- y2 y1))))
   2.126  
   2.127 -(defn translate [context x y w h]
   2.128 -  (let [ax (+ (:x context) x)
   2.129 -        ay (+ (:y context) y)]
   2.130 -    (assoc context
   2.131 -      :x (+ (:x context) x)
   2.132 -      :y (+ (:y context) y)
   2.133 -      :width w
   2.134 -      :height h
   2.135 -      :clip (intersect (:clip context) ax ay w h)
   2.136 -      :graphics (apply-theme
   2.137 -                 (make-graphics (:graphics context) x y w h)
   2.138 -                 (:theme context)))))
   2.139 +(defn with-translate* [x y w h f & args]
   2.140 +  (let [graphics (apply-theme (.create *graphics* x y w h) *theme*)
   2.141 +        bounds (Bounds. (+ x (:x *bounds*))
   2.142 +                        (+ y (:y *bounds*))
   2.143 +                        w h)]
   2.144 +    (try
   2.145 +      (apply with-bindings* {#'*bounds* bounds
   2.146 +                             #'*clip* (intersect bounds *clip*)
   2.147 +                             #'*graphics* graphics}
   2.148 +             f args)
   2.149 +      (finally
   2.150 +       (.dispose graphics)))))
   2.151 +
   2.152 +(defmacro with-translate [x y w h & body]
   2.153 +  `(with-translate* ~x ~y ~w ~h (fn [] ~@body)))
   2.154 +
   2.155 +
   2.156 +
   2.157 +(defn with-handlers* [handle handlers f & args]
   2.158 +  (apply with-bindings*
   2.159 +         {#'*event-dispatcher*
   2.160 +          (create-dispatcher *event-dispatcher* handle handlers)}
   2.161 +         f args))
   2.162 +
   2.163 +(defmacro with-handlers
   2.164 +  "specs => (:event-id name & handler-body)*
   2.165 +
   2.166 +  Execute form with the specified event handlers."
   2.167 +  [handle form & specs]
   2.168 +  `(with-handlers* ~handle
   2.169 +     ~(reduce (fn [m spec]
   2.170 +                (assoc m (first spec)
   2.171 +                       `(fn [~(second spec)]
   2.172 +                          ~@(nnext spec)))) {}
   2.173 +                          specs)
   2.174 +     (fn [] ~form)))
   2.175 +
   2.176 +(defn- geometry-vec [geometry]
   2.177 +  (if (vector? geometry)
   2.178 +    geometry
   2.179 +    [(:x geometry) (:y geometry) (:width geometry) (:height geometry)]))
   2.180  
   2.181  (defn draw!
   2.182 -  "Render layer in a new graphics context."
   2.183 -  ([layer context]
   2.184 -     (render! layer context))
   2.185 -  ([layer context x y]
   2.186 -     (let [s (size layer context)]
   2.187 -       (draw! layer context x y (:width s) (:height s))))
   2.188 -  ([layer context x y w h]
   2.189 -     (let [context (translate context x y w h)]
   2.190 -       (try
   2.191 -         (render! layer context)
   2.192 -         (finally
   2.193 -          (.dispose (:graphics context)))))))
   2.194 -
   2.195 -(defn add-handlers [context handle handlers]
   2.196 -  "Returns new context with the specified event handlers."
   2.197 -  (assoc context
   2.198 -    :event-dispatcher
   2.199 -    (create-dispatcher (:event-dispatcher context) context
   2.200 -                       handle handlers)))
   2.201 -
   2.202 -(defmacro let-handlers [handle bindings form & specs]
   2.203 -  "bindings => [binding-form context] or [context-symbol]
   2.204 -   specs => (:event-id name & handler-body)*
   2.205 -
   2.206 -  Execute form with the specified event handlers."
   2.207 -  (let [[binding context] bindings
   2.208 -        context (or context binding)]
   2.209 -    `(let [context# ~context
   2.210 -           ~binding
   2.211 -           (add-handlers context# ~handle
   2.212 -             ~(reduce (fn [m spec]
   2.213 -                        (assoc m (first spec)
   2.214 -                               `(fn [~(second spec)]
   2.215 -                                  ~@(nnext spec)))) {}
   2.216 -                                  specs))]
   2.217 -           ~form)))
   2.218 +  "Draw a layer. Geometry is either a map or vector [x y] or
   2.219 +   [x y width height]."
   2.220 +  [layer geometry & args]
   2.221 +  (let [[x y w h] (geometry-vec geometry)
   2.222 +        size (if-not (and w h) (size layer args))
   2.223 +        w (or w (:width size))
   2.224 +        h (or h (:height size))]
   2.225 +    (with-translate* x y w h render! layer args)))
   2.226  
   2.227  ;;
   2.228  ;; EventDispatcher implementation
   2.229 @@ -159,17 +158,18 @@
   2.230        java.awt.event.MouseEvent/MOUSE_PRESSED  :mouse-pressed
   2.231        java.awt.event.MouseEvent/MOUSE_RELEASED :mouse-released})
   2.232  
   2.233 -(defrecord DispatcherNode [handle handlers parent bounds]
   2.234 +(defrecord DispatcherNode [handle handlers parent bounds bindings]
   2.235    EventDispatcher
   2.236    (listen! [this component]
   2.237       (listen! parent component))
   2.238 -  (create-dispatcher [this context handle handlers]
   2.239 -     (create-dispatcher parent context handle handlers))
   2.240 +  (create-dispatcher [this handle handlers]
   2.241 +     (create-dispatcher parent handle handlers))
   2.242    (commit [this]
   2.243       (commit parent)))
   2.244  
   2.245 -(defn- make-node [c handle handlers]
   2.246 -  (DispatcherNode. handle handlers (:event-dispatcher c) (:clip c)))
   2.247 +(defn- make-node [handle handlers]
   2.248 +  (DispatcherNode. handle handlers *event-dispatcher* *clip*
   2.249 +                   (get-thread-bindings)))
   2.250  
   2.251  (defn- assoc-cons [m key val]
   2.252    (assoc m key (cons val (get m key))))
   2.253 @@ -209,9 +209,10 @@
   2.254    ([nodes event id]
   2.255       (doseq [node nodes]
   2.256         (when-let [handler (get (:handlers node) id)]
   2.257 -         (handler
   2.258 -          (translate-mouse-event event
   2.259 -            (-> node :bounds :x) (-> node :bounds :y) id))))
   2.260 +         (with-bindings* (:bindings node)
   2.261 +           handler
   2.262 +           (translate-mouse-event event
   2.263 +             (-> node :bounds :x) (-> node :bounds :y) id))))
   2.264       id))
   2.265  
   2.266  (defn- dispatch-mouse-motion*
   2.267 @@ -259,8 +260,8 @@
   2.268          (doto component
   2.269            (.addMouseListener this)
   2.270            (.addMouseMotionListener this)))
   2.271 -     (create-dispatcher [this context handle handlers]
   2.272 -        (let [node (make-node context handle handlers)]
   2.273 +     (create-dispatcher [this handle handlers]
   2.274 +        (let [node (make-node handle handlers)]
   2.275            (dosync (alter tree-r add-node node))
   2.276            node))
   2.277       (commit [this]
     3.1 --- a/src/indyvon/layers.clj	Wed Jul 07 07:17:08 2010 +0400
     3.2 +++ b/src/indyvon/layers.clj	Thu Jul 08 05:27:54 2010 +0400
     3.3 @@ -7,7 +7,7 @@
     3.4  (ns indyvon.layers
     3.5    (:use indyvon.core)
     3.6    (:import (indyvon.core Size Location)
     3.7 -           (java.awt Cursor)
     3.8 +           (java.awt Font Cursor)
     3.9             (java.awt.font FontRenderContext TextLayout)))
    3.10  
    3.11  ;; Define as macro to avoid unnecessary calculation of inner and outer
    3.12 @@ -33,30 +33,33 @@
    3.13    ([content width gap]
    3.14       (let [offset (+ width gap)]
    3.15         (reify Layer
    3.16 -        (render! [l c]
    3.17 -           (let [w (:width c)
    3.18 -                 h (:height c)]
    3.19 -             (.setColor (graphics c) (-> c :theme :border-color))
    3.20 +        (render! [l opts]
    3.21 +           (let [w (:width *bounds*)
    3.22 +                 h (:height *bounds*)]
    3.23 +             (.setColor *graphics* (:border-color *theme*))
    3.24               (doseq [i (range 0 width)]
    3.25 -               (.drawRect (graphics c) i i (- w 1 i i) (- h 1 i i)))
    3.26 -             (draw! content c offset offset (- w offset offset)
    3.27 -                    (- h offset offset))))
    3.28 -        (size [l c]
    3.29 -           (let [s (size content c)]
    3.30 +               (.drawRect *graphics* i i (- w 1 i i) (- h 1 i i)))
    3.31 +             (apply draw! content
    3.32 +                    [offset offset (- w offset offset) (- h offset offset)]
    3.33 +                    opts)))
    3.34 +        (size [l opts]
    3.35 +           (let [s (size content opts)]
    3.36               (Size. (+ (:width s) offset offset)
    3.37                      (+ (:height s) offset offset))))))))
    3.38  
    3.39 -(defn- re-split [re s]
    3.40 +(defn- re-split [^java.util.regex.Pattern re s]
    3.41    (seq (.split re s)))
    3.42  
    3.43 -(defn- layout-text [lines font font-context]
    3.44 -  (map #(TextLayout. % font font-context) lines))
    3.45 +(defn- layout-text [lines ^Font font ^FontRenderContext font-context]
    3.46 +  (map #(TextLayout. ^String % font font-context) lines))
    3.47  
    3.48  (defn- text-width [layouts]
    3.49 -  (reduce #(max %1 (.getAdvance %2)) 0 layouts))
    3.50 +  (reduce (fn [w ^TextLayout tl] (max w (.getAdvance tl))) 0 layouts))
    3.51  
    3.52  (defn- text-height [layouts]
    3.53 -  (reduce #(+ %1 (.getAscent %2) (.getDescent %2) (.getLeading %2))
    3.54 +  (reduce (fn [w ^TextLayout tl] (+ w (.getAscent tl)
    3.55 +                                   (.getDescent tl)
    3.56 +                                   (.getLeading tl)))
    3.57            0 layouts))
    3.58  
    3.59  (defn text-layer
    3.60 @@ -66,24 +69,21 @@
    3.61    ([text h-align v-align]
    3.62       (let [lines (re-split #"\r\n|\n|\r|\u0085|\u2028|\u2029" text)]
    3.63         (reify Layer
    3.64 -        (render! [l c]
    3.65 -           (let [w (:width c)
    3.66 -                 h (:height c)
    3.67 -                 font (.getFont (graphics c))
    3.68 -                 font-context (:font-context c)
    3.69 -                 layouts (layout-text lines font font-context)
    3.70 +        (render! [layer opts]
    3.71 +           (let [w (:width *bounds*)
    3.72 +                 h (:height *bounds*)
    3.73 +                 font (.getFont *graphics*)
    3.74 +                 layouts (layout-text lines font *font-context*)
    3.75                   y (align-y (text-height layouts) h v-align)]
    3.76               (loop [layouts layouts, y y]
    3.77 -               (when-first [layout layouts]
    3.78 +               (when-first [^TextLayout layout layouts]
    3.79                   (let [ascent (.getAscent layout)
    3.80                         lh (+ ascent (.getDescent layout) (.getLeading layout))
    3.81                         x (align-x (.getAdvance layout) w h-align)]
    3.82 -                   (.draw layout (graphics c) x (+ y ascent))
    3.83 +                   (.draw layout *graphics* x (+ y ascent))
    3.84                     (recur (next layouts) (+ y lh)))))))
    3.85 -        (size [l c]
    3.86 -           (let [layouts (layout-text lines
    3.87 -                                      (-> c :theme :font)
    3.88 -                                      (:font-context c))
    3.89 +        (size [layer opts]
    3.90 +           (let [layouts (layout-text lines (:font *theme*) *font-context*)
    3.91                   width (text-width layouts)
    3.92                   height (text-height layouts)]
    3.93               (Size. width height)))))))
    3.94 @@ -100,31 +100,30 @@
    3.95          last-height (ref 0)]
    3.96      (reify
    3.97       Layer
    3.98 -     (render! [layer c]
    3.99 -        (let-handlers layer [c]
   3.100 -         (let [anchor (anchor content c h-align v-align)
   3.101 -               width (:width c)
   3.102 -               height (:height c)]
   3.103 +     (render! [layer opts]
   3.104 +        (with-handlers layer
   3.105 +         (let [anchor (anchor content h-align v-align opts)
   3.106 +               width (:width *bounds*)
   3.107 +               height (:height *bounds*)]
   3.108             (dosync
   3.109              (alter x + (align-x width @last-width h-align))
   3.110              (alter y + (align-y height @last-height v-align))
   3.111              (ref-set last-width width)
   3.112              (ref-set last-height height))
   3.113 -           (draw! content c
   3.114 -                  (- 0 @x (:x anchor))
   3.115 -                  (- 0 @y (:y anchor))))
   3.116 +           (apply draw! content
   3.117 +                  [(- 0 @x (:x anchor)) (- 0 @y (:y anchor))] opts))
   3.118           (:mouse-pressed e
   3.119            (dosync
   3.120             (ref-set fix-x (:x-on-screen e))
   3.121             (ref-set fix-y (:y-on-screen e)))
   3.122 -          (->> Cursor/MOVE_CURSOR Cursor. (.setCursor (:target c))))
   3.123 +          (->> Cursor/MOVE_CURSOR Cursor. (.setCursor *target*)))
   3.124           (:mouse-released e
   3.125 -          (->> Cursor/DEFAULT_CURSOR Cursor. (.setCursor (:target c))))
   3.126 +          (->> Cursor/DEFAULT_CURSOR Cursor. (.setCursor *target*)))
   3.127           (:mouse-dragged e
   3.128            (dosync
   3.129             (alter x + (- @fix-x (:x-on-screen e)))
   3.130             (alter y + (- @fix-y (:y-on-screen e)))
   3.131             (ref-set fix-x (:x-on-screen e))
   3.132             (ref-set fix-y (:y-on-screen e)))
   3.133 -          (update c))))
   3.134 -     (size [layer c] (size content c))))))
   3.135 +          (*update*))))
   3.136 +     (size [layer opts] (size content opts))))))