Created
July 22, 2015 00:51
-
-
Save CarlSmotricz/78f616ec90b478cf1007 to your computer and use it in GitHub Desktop.
A tiny CAD-like program in Clojure. Uses SeeSaw for the GUI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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