changeset 16:0fda22fc53d2

Remove anchor from Layer protocol. More function text layout calculation.
author Mikhail Kryshen <mikhail@kryshen.net>
date Thu, 17 Jun 2010 05:20:37 +0400
parents 87bd822aa815
children 31382464ef27
files src/indyvon/component.clj src/indyvon/core.clj
diffstat 2 files changed, 31 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/indyvon/component.clj	Tue Jun 15 06:31:11 2010 +0400
+++ b/src/indyvon/component.clj	Thu Jun 17 05:20:37 2010 +0400
@@ -47,7 +47,7 @@
   (do 
     (def frame (java.awt.Frame. "Test"))
     (def layer1
-         (reify-layer
+         (reify Layer
           (render! [this context g]
              (register-context context)
              (.setColor g Color/RED)
@@ -55,7 +55,7 @@
           (size [this context] [30 20])))
     (def layer1b (border-layer layer1 2 3))
     (def layer2
-         (reify-layer
+         (reify Layer
           (render! [this context g]
              (register-context context)
              (.setColor g Color/YELLOW)
@@ -66,7 +66,7 @@
     (def layer3
          (border-layer (text-layer "Sample\ntext" :right :bottom)))
     (def layer
-         (reify-layer
+         (reify Layer
           (render! [this context g]
              (.drawLine g 0 0 (:width context) (:height context))
              (draw! context layer2 g 15 20)
--- a/src/indyvon/core.clj	Tue Jun 15 06:31:11 2010 +0400
+++ b/src/indyvon/core.clj	Thu Jun 17 05:20:37 2010 +0400
@@ -10,8 +10,7 @@
 
 (defprotocol Layer
   (render! [this context graphics])
-  (size [this context])
-  (anchor [this context]))
+  (size [this context]))
 
 (defrecord Theme [fore-color back-color border-color font])
 
@@ -24,25 +23,6 @@
 (defn default-context []
   (LayerContext. nil nil 0 0 0 0 nil nil nil (default-theme)))
 
-(defn- spec-map
-  ([specs]
-     (spec-map {} specs))
-  ([mm specs]
-     (if-let [form (first specs)]
-       (recur (conj mm [(first form) (next form)])
-              (next specs))
-       mm)))
-
-(defn- merge-specs [s1 s2]
-  (for [spec (spec-map (spec-map s1) s2)]
-    (cons (first spec) (second spec))))
-     
-(defmacro reify-layer [& specs]
-  `(reify Layer ~@(merge-specs
-                   '((size [_ _] [0 0])
-                     (anchor [_ _] [0 0]))
-                   specs)))
-
 (defn- make-graphics [graphics x y w h clip]
   (if clip
     (.create graphics x y w h)
@@ -64,10 +44,10 @@
   ([context layer graphics x y clip]
      (let [s (size layer context)]
        (draw! context layer graphics
-                      x y (s 0) (s 1) clip)))
+              x y (s 0) (s 1) clip)))
   ([context layer graphics x y w h]
      (draw! context layer graphics
-                    x y w h true))
+            x y w h true))
   ([context layer graphics x y w h clip]
      (let [graphics (make-graphics graphics x y w h clip)
            graphics (apply-theme graphics (:theme context))]
@@ -84,14 +64,6 @@
          (finally
           (.dispose graphics))))))
 
-(defmacro decorate-layer [layer & specs]
-  `(let [layer# ~layer]
-     (reify Layer ~@(merge-specs
-                     `((~'render! [l# c# g#] (draw! c# layer# g#))
-                       (~'size [l# c#] (size layer# c#))
-                       (~'anchor [l# c#] (anchor layer# c#)))
-                     specs))))
-
 ;;
 ;; Layer implementations.
 ;;
@@ -104,7 +76,7 @@
      (border-layer content width 0))
   ([content width gap]
      (let [offset (+ width gap)]
-       (reify-layer
+       (reify Layer
         (render! [l c g]
            (let [w (:width c)
                  h (:height c)]
@@ -116,28 +88,20 @@
         (size [l c]
            (let [s (size content c)]
              [(+ (s 0) offset offset)
-              (+ (s 1) offset offset)]))
-        (anchor [l c]
-           (let [a (anchor content c)]
-             [(+ (a 0) offset)
-              (+ (a 1) offset)]))))))
+              (+ (s 1) offset offset)]))))))
 
 (defn- re-split [re s]
   (seq (.split re s)))
 
-(defn- text-size [lines font font-context]
-  (loop [lines lines
-         width 0
-         height 0]
-    (if-let [line (first lines)]
-      (let [layout (TextLayout. line font font-context)]
-        (recur (next lines)
-               (max width (.getAdvance layout))
-               (+ height
-                  (.getAscent layout)
-                  (.getDescent layout)
-                  (.getLeading layout))))
-      [width height])))
+(defn- layout-text [lines font font-context]
+  (map #(TextLayout. % font font-context) lines))
+
+(defn- text-width [layouts]
+  (reduce #(max %1 (.getAdvance %2)) 0 layouts))
+
+(defn- text-height [layouts]
+  (reduce #(+ %1 (.getAscent %2) (.getDescent %2) (.getLeading %2))
+          0 layouts))
 
 (defn text-layer
   "Creates a layer to display multiline text."
@@ -145,29 +109,31 @@
      (text-layer text :left :top))
   ([text h-align v-align]
      (let [lines (re-split #"\r\n|\n|\r|\u0085|\u2028|\u2029" text)]
-       (reify-layer
+       (reify Layer
         (render! [l c g]
            (let [w (:width c)
                  h (:height c)
                  font (.getFont g)
                  font-context (:font-context c)
+                 layouts (layout-text lines font font-context)
                  y (case v-align
                      :top 0
-                     :center (/ (- h ((text-size
-                                       lines font font-context) 1))
-                                2)
-                     :bottom (- h ((text-size
-                                    lines font font-context) 1)))]
-             (loop [lines lines, y y]
-               (when-first [line lines]
-                 (let [layout (TextLayout. line font font-context)
-                       ascent (.getAscent layout)
+                     :center (/ (- h (text-height layouts)) 2)
+                     :bottom (- h (text-height layouts)))]
+             (loop [layouts layouts, y y]
+               (when-first [layout layouts]
+                 (let [ascent (.getAscent layout)
                        lh (+ ascent (.getDescent layout) (.getLeading layout))
                        x (case h-align
                            :left 0
                            :center (/ (- w (.getAdvance layout)) 2)
                            :right (- w (.getAdvance layout)))]
                    (.draw layout g x (+ y ascent))
-                   (recur (next lines) (+ y lh)))))))
+                   (recur (next layouts) (+ y lh)))))))
         (size [l c]
-           (text-size lines (-> c :theme :font) (:font-context c)))))))
+           (let [layouts (layout-text lines
+                                      (-> c :theme :font)
+                                      (:font-context c))
+                 width (text-width layouts)
+                 height (text-height layouts)]
+             [width height]))))))