attempt at easy swing graphics in cloj

Jonathan Raphaelson
2010-07-08T04:54:37Z

graphix.clj

| (ns typoet.graphix
| (:import [javax.swing JFrame])
| (:import [java.awt Dimension Canvas])
| (:import [java.awt.event WindowAdapter KeyAdapter MouseAdapter MouseMotionAdapter])
| (:use [clojure.contrib.seq-utils]))
|
| (defstruct window :height :width :title :frame :canvas :handlers)
|
| (defn- get-handlers
| [window key]
| ((get window :handlers) key []))
|
| (defn add-handler
| [window key handler]
| (dosync
| (let [handler-ref (get window :handlers)
| orighandlers (get @handler-ref key [])
| newhandlers (conj orighandlers handler)]
| (alter handler-ref assoc key newhandlers))))
|
| (defn- proxy-event
| [window event & args]
| (let [handlers (get-handlers window event)]
| (doall (take-while (fn [handler] (true? (apply handler args))) handlers))))
|
| (defn- get-time
| []
| (/ (System/nanoTime) 1000000))
|
| (defn- event-loop
| [window]
| (loop [last-time (get-time)]
| (let [curr-time (get-time)
| delta (- curr-time last-time)]
| (proxy-event window :ontick delta (get window :canvas))
| (Thread/sleep 100)
| (recur curr-time))))
|
| (defn create-window
| "Create a window/canvas to draw on, and return it."
| [title width height]
| (let [frame (JFrame. title)
| canvas (Canvas.)
| panel (doto (.getContentPane frame)
| (.setPreferredSize (Dimension. width height))
| (.setLayout nil)
| (.add canvas))
| window (struct window height width title frame canvas (ref {}))]
|
| (doto frame
| (.addWindowListener (proxy [WindowAdapter] []
| (windowClosing [e] (proxy-event window :onclose e))))
| (.setResizable false)
| (.pack))
|
| (doto canvas
| (.addKeyListener (proxy [KeyAdapter] []
| (keyPressed [e] (proxy-event window :onkeypress e))))
| (.addMouseListener (proxy [MouseAdapter] []
| (mouseClicked [e] (proxy-event window :onmouseclick e))))
| (.addMouseMotionListener (proxy [MouseMotionAdapter] []
| (mouseMoved [e] (proxy-event window :onmousemove e))
| (mouseDragged [e] (proxy-event window :onmousedrag e))))
| (.setBounds 0 0 width height)
| (.setIgnoreRepaint true)
| (.createBufferStrategy 2))
|
| window))
|
| (defn start-window
| "Show the window, and start the painting/event loop, at the given FPS (try to get as close as possible."
| [window fps]
| (let [looper (agent window)]
| (.setVisible (get window :frame) true)
| (send-off looper event-loop)))
|
| (defn my-test []
| (let [w (create-window "test" 640 480)]
| (add-handler w :ontick (fn [delta canvas] (println delta)))
| (start-window w 1)))