Skip to content

Instantly share code, notes, and snippets.

@CarlSmotricz
Created July 22, 2015 00:51
Show Gist options
  • Save CarlSmotricz/78f616ec90b478cf1007 to your computer and use it in GitHub Desktop.
Save CarlSmotricz/78f616ec90b478cf1007 to your computer and use it in GitHub Desktop.
A tiny CAD-like program in Clojure. Uses SeeSaw for the GUI.
; a tiny, simple CAD program prototype in Clojure.
; Carl Smotricz, 2015-07-22
(ns nanocad.core
(:use [seesaw core graphics])
(:require [seesaw.mouse :refer [location]])
(:import [javax.swing AbstractAction]))
(def CANVAS-WIDTH 400)
(def CANVAS-HEIGHT 300)
(def CLICK-TEXT "Click here to draw!")
(def line-style (style :foreground "#FF0000" :stroke 2 :cap :round)
(defn -main [& args]
(declare on-kanvas-click) ; forward declaration, resolves circular dependencies
(let
[
; ---define a bunch of variables needed later.
; some of those vars refer to functions.
; our only data structure.
; a list of points for drawing as lines.
points (atom [])
draw-lines (fn [c g] ; function to draw lines from 'points' on canvas
(loop [segments (partition 2 @points)]
(when (not-empty segments)
(let [s1 (first segments)
p1 (first s1)
p2 (second s1)]
(invoke-later (prn "segments:" segments "; p1:" p1 "; p2:" p2))
(draw g (line (first p1) (second p1) (first p2) (second p2)) line-style))
(recur (next segments)))))
; creates a label we use as our canvas.
; the name "canvas" is already taken by seesaw.
kanvas (label
:text CLICK-TEXT
:size [CANVAS-WIDTH :by CANVAS-HEIGHT]
:halign :center
:tip "Click here to draw"
:paint draw-lines)
on-kanvas-click (fn [evt] ; function to be called on canvas click
; a new line will be drawn for every 2 clicks (= points).
(let [new-pt (location evt)]
(swap! points conj new-pt)
(invoke-later (prn "new-pt:" new-pt "; points:" points)))
(config! kanvas :text "Clicked. Again!")
(repaint! kanvas))
on-clear-click (fn [evt] ; function to be called on clear click
(invoke-later (prn "Cleared. points: " points))
(reset! points [])
(config! kanvas :text CLICK-TEXT)
(repaint! kanvas))
; creates a button with the given action
clear-action (action
:name "Clear"
:tip "Clear the drawing pane"
:handler on-clear-click)
; --- end of variables. the following code executes in the context of those vars.
]
(prn "nanoCAD starting")
; causes on-kanvas-click to be executed if canvas clicked
(listen kanvas :mouse-clicked on-kanvas-click)
; assembles and displays the little GUI.
(invoke-later
(-> (frame :title "nanoCAD",
:content (vertical-panel
:items [kanvas
clear-action])
:on-close :exit)
pack!
show!))))
(-main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment