view src/indyvon/component.clj @ 33:439f6ecee119

Include graphics into context. Event dispatcher respects clipping.
author Mikhail Kryshen <mikhail@kryshen.net>
date Wed, 07 Jul 2010 07:17:08 +0400
parents 0b3757d263db
children 6975b9a71eec
line wrap: on
line source

;;
;; Copyright (C) 2010 Mikhail Kryshen <mikhail@kryshen.net>
;;
;; This file is part of Indyvon.
;;

(ns indyvon.component
  (:use indyvon.core indyvon.layers)
  (:import (indyvon.core Size Location)
           (java.awt Component Graphics2D Dimension Color)
           (javax.swing JFrame JPanel)))

(defn- font-context [^Component component]
  (.getFontRenderContext (.getFontMetrics component (.getFont component))))

(defn paint-component
  [^Component component layer context ^Graphics2D graphics]
  (let [size (.getSize component)
        width (.width size)
        height (.height size)
        context (assoc context
                  :x 0
                  :y 0
                  :width width
                  :height height
                  :clip (indyvon.core.Bounds. 0 0 width height)
                  :target component
                  :graphics graphics
                  :font-context (.getFontRenderContext graphics)
                  :update-fn #(.repaint component))]
    (.clearRect graphics 0 0 width height)
    (draw! layer context))
  (commit (:event-dispatcher context)))

(defn preferred-size [component layer context]
  (let [context (assoc context
                  :target component
                  :font-context (font-context component))
        s (size layer context)]
    (Dimension. (:width s) (:height s))))

(defn make-jpanel
  ([layer]
     (make-jpanel layer (root-event-dispatcher)))
  ([layer event-dispatcher]
     (let [context (default-context)
           context (assoc context :event-dispatcher event-dispatcher)
           panel
           (proxy [JPanel] []
             (paintComponent [g]
                (paint-component this layer context g))
             (getPreferredSize []
                (preferred-size this layer context)))]
       (listen! event-dispatcher panel)
       (.setBackground panel (-> context :theme :back-color))
       panel)))

(comment
  (do
    (def frame (JFrame. "Test"))
    
    (def layer1
         (reify
          Layer
          (render! [this context]
             (let-handlers this [context]
               (doto (graphics context)
                 (.setColor Color/RED)
                 (.fillRect 0 0 (:width context) (:height context)))
               (:mouse-entered e (println e))
               (:mouse-exited e (println e))
               (:mouse-moved e (println e))))
          (size [this context] (Size. 30 20))))
    
    (def layer1b (border-layer layer1 2 3))
    
    (def layer2
         (reify
          Layer
          (render! [this context]
             (doto (graphics context)
               (.setColor Color/YELLOW)
               (.fillRect 0 0 (:width context) (:height context)))
             (draw! layer1b context 10 5)
             (draw! layer1 context 55 5))
          (size [this context] (Size. 70 65))))
    
    (def layer3
         (border-layer (text-layer "Sample\ntext" :right :center)))

    (defn fps-layer [fps]
      (border-layer (text-layer (format "%.1f" fps) :right :bottom) 0 5))
    
    (def fps
         (let [update-interval 0.1
               frames (ref 0)
               last (ref 0)
               fl (ref (fps-layer 0.0))]
           (reify
            Layer
            (render! [this c]
               (draw! @fl c)
               (dosync
                (alter frames + 1)
                (let [time (System/currentTimeMillis)
                      elapsed (/ (- time @last) 1000.0)]
                  (when (> elapsed update-interval)
                    (ref-set fl (fps-layer (/ @frames elapsed)))
                    (ref-set frames 0)
                    (ref-set last time)))))
            (size [this c] (size @fl c)))))
    
    (def layer
         (reify Layer
           (render! [this context]
             (update context)
             (doto (graphics context)       
               (.setColor (rand-nth [Color/BLACK Color/BLUE Color/RED]))
               (.drawLine 0 0 (:width context) (:height context)))
             (draw! layer2 context 15 20)
             (draw! layer3 context 100 100 80 50)
             (draw! fps context))
           (size [this context] (Size. 400 300))))
    
    (doto frame
      (.addWindowListener
       (proxy [java.awt.event.WindowAdapter] []
         (windowClosing [event] (.dispose frame))))
      (.. (getContentPane) (add (make-jpanel (viewport layer))))
      (.pack)
      (.setVisible true))
    )
  )