view src/net/kryshen/indyvon/component.clj @ 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 9874107e3e96
children f3dedece38f3
line wrap: on
line source

;;
;; Copyright 2010, 2011 Mikhail Kryshen <mikhail@kryshen.net>
;;
;; This file is part of Indyvon.
;;
;; Indyvon is free software: you can redistribute it and/or modify it
;; under the terms of the GNU Lesser General Public License version 3
;; only, as published by the Free Software Foundation.
;;
;; Indyvon is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public
;; License along with Indyvon.  If not, see
;; <http://www.gnu.org/licenses/>.
;;

(ns net.kryshen.indyvon.component
  "Integrating Indyvon into AWT and Swing components."
  (:use
   net.kryshen.indyvon.core)
  (:import
   (net.kryshen.indyvon.core Size Bounds)
   (java.awt Graphics Component Dimension Color)
   (java.awt.geom Rectangle2D$Double)
   (javax.swing JFrame JPanel JOptionPane)))

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

(defmacro with-component [component & body]
  `(let [c# ~component]
     (binding [*target* c#
               *font-context* (font-context c#)]
       ~@body)))

(defn- paint-component [^Component c ^Graphics g scene]
  (let [size (.getSize c)]
    (.setColor g (:back-color *theme*))
    (.fillRect g 0 0 (.width size) (.height size))
    (draw-scene! scene g (.width size) (.height size))))

(defn- preferred-size [^Component c scene]
  (let [s (scene-size scene (font-context c))]
    (Dimension. (:width s) (:height s))))

(defn ^JPanel make-jpanel
  ([layer]
     (make-jpanel layer (root-event-dispatcher)))
  ([layer event-dispatcher]
     (let [panel (proxy [JPanel] [])
           scene (make-scene layer event-dispatcher panel)]
       (update-proxy
        panel
        {"paintComponent" #(paint-component %1 %2 scene)
         "getPreferredSize" #(preferred-size % scene)})
       (.setBackground panel (:back-color *theme*))
       (add-observer panel scene (fn [w _]
                                   ;; Use the first observer argument
                                   ;; instead of closing over panel to
                                   ;; allow the panel and associated
                                   ;; observer to be gc'd.
                                   (.repaint ^Component w)))
       (listen! event-dispatcher panel)
       panel)))

(defn make-jframe [title layer]
  (doto (JFrame. title)
    (.. (getContentPane) (add (make-jpanel layer)))
    (.pack)))

(defn message [m]
  (JOptionPane/showMessageDialog *target* m))