Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 150 lines (101 sloc) 6.815 kB
cdb4045 @daveray readme and various cleanup
authored
1 # Seesaw: a Clojure/Swing experiment
2
3 Seesaw's a *primordial* experiment to see what I can do to make Swing funner in Clojure. It's maybe inspired by [Shoes](http://shoesrb.com/), [Stuart Sierra's Swing posts](http://stuartsierra.com/tag/swing), etc. [clojure.contrib.swing-utils](http://richhickey.github.com/clojure-contrib/swing-utils-api.html) is useful, but minimal and still means a lot of "Java-in-Clojure" coding.
4
5 ## Usage
6 See tests and src/seesaw/examples. Seriously, the tests are pretty descriptive of how things work.
7
8 Let's create a `JFrame`:
9
10 (frame :title "Hello" :content "Hi there")
11
12 This will create a `JFrame` with title "Hello" and a single label "Hi there". The `:content` property expects something that can be turned into a widget and uses it as the content pane of the frame. Any place where a widget is expected, one will be created depending on the argument...
13
14 ### Widget Coercion
15
16 <table>
17 <tr><td>Input</td><td>Result</td></tr>
18 <tr><td>java.awt.Component</td><td>return argument unchanged</td></tr>
19 <tr><td>java.awt.Dimension</td><td>return Box/createRigidArea</td></tr>
20 <tr><td>java.swing.Action</td><td>return a button using the action</td></tr>
21 <tr><td>java.util.EventObject (for example in an event handler)</td><td>return the event source</td></tr>
22 <tr><td>:fill-h</td><td>Box/createHorizontalGlue</td></tr>
23 <tr><td>:fill-v</td><td>Box/createVerticalGlue</td></tr>
24 <tr><td>[:fill-h n], e.g. <code>[:fill-h 99]<code></td><td>Box/createHorizontalStrut with width n</td></tr>
25 <tr><td>[:fill-v n]</td><td>Box/createVerticalStrut with height n</td></tr>
26 <tr><td>[width :by height]</td><td>create rigid area with given dimensions</td></tr>
27 <tr><td>A URL</td><td>a label with the image located at the url</td></tr>
28 <tr><td>A non-url string</td><td>a label with the given text</td></tr>
29 </table>
30
31
32 Most of Seesaw's container functions (`flow-panel`, `grid-panel`, etc) take an `:items` property which is a list of these widget-able values. For example:
33
34 (let [choose (fn [e] (alert "I should open a file chooser"))]
35 (flow-panel
36 :items ["File" [:fill-h 5]
37 (text (System/getProperty "user.dir")) [:fill-h 5]
38 (action choose :name "...")]))
39
40 creates a panel with a "File" label, a text entry field initialized to the current working directory and a button that doesn't do much. Each component is separated by 5 pixel padding.
41
42 ### Default Properties
43 All of Seesaw's widget creation functions (`label`, `text`, `horizontal-panel`, etc) support a base set of properties:
44
45 <table>
46 <tr><td>Property</td><td>Description</td></tr>
47 <tr><td><code>:opaque</code></td><td>(boolean) Set whether the background of the widget is opaque.</td></tr>
48 <tr><td><code>:background</code></td><td>Background color by coercing into a Color (see below)</td></tr>
49 <tr><td><code>:foreground</code></td><td>Foreground color by coercing into a Color (see below)</td></tr>
50 <tr><td><code>:border</code></td><td>Set the border of the widget by coercing into a Border. See below.</td></tr>
51 <tr><td><code>:font</code></td><td>Set the font of the widget by coercing into a Font. See below.</td></tr>
52 <tr><td><code>:on-action</code></td><td>Set the widget's default action handler by coercing into an action. See below.</td></tr>
53 <tr><td><code>:on-mouse-clicked</code>, <code>:on-mouse-entered</code>,<code>:on-mouse-exited</code> </td><td>Handle mouse events using the given event handler functions.</td></tr>
54 </table>
55
56 ### Containers
57
58 There are container creation functions which basically create `JPanel` instances with particular layouts. Here are some examples. Any place that a widget or list of widgets is expected, the widget coercion rules described above apply.
59
60 A `FlowLayout` with some items:
61
62 (flow-panel
63 :align :left
64 :hgap 20
65 :items ["Label" (action alert "Button") "Another label"])
66
67 A `GridLayout` with 2 columns and a titled border:
68
69 (grid-panel
70 :border "Properties"
71 :columns 2
72 :items ["Name" (text "Frank")
73 "Address" (text "123 Main St")])
74
75 A `BorderLayout`:
76
77 (border-panel :hgap 10 :vgap 10 :center "CENTER" :north "NORTH" :south "SOUTH" :east "EAST" :west "WEST")
78
79 ### Event Handlers
80 Event handler functions are single-argument functions that take an event object whose type depends on the event being fired, e.g. `MouseEvent`. For example, we can execute a function when a checkbox is checked:
81
82 (let [handler (fn [e] (alert (.. (.getSource e) (isSelected))))]
83 (checkbox :text "Check me" :on-selection-changed handler))
84
85 ### Color Coercion
86
87 Colors can be specified in the following ways (using the `:foreground` property as an example):
88
89 :foreground java.awt.Color/BLACK (a raw color object)
90 :foreground (color 255 255 224) (RGB bytes)
91 :foreground (color 255 255 224 128) (RGBA bytes)
92 :foreground "#FFEEDD" (hex color string)
93 :foreground (color "#FFEEDD" 128) (hex color string + alpha)
94
95 Here's a label with blue text and a red background:
96
97 (label :text "Hideous"
98 :opaque true
99 :foreground (color 0 0 255)
100 :background "#FF0000")
101
102 Of course, a raw `Color` object can also be used.
103
104 ### Font Coercion
105
106 Fonts can be specified in the following ways (using the `:font` property as an example):
107
108 :font "ARIAL-BOLD-18" (Swing-style font spec string)
109 :font {:name "ARIAL" :style :bold :size 18} (using a properties hash)
110 :font (font :name "ARIAL" :style :bold :size 18) (using properties with font function)
111
112 So, you could make a monospaced text area like this:
113
114 (text :text "Type some code here"
115 :multi-line? true
116 :font {:name :monospaced :size 15})
117
118 Of course, a raw `Font` object can also be used.
119
120 ### Border Coercion
121
122 Widget borders can be passed to the `:border` property to create many border styles:
123
124 :border "Title" (creates a plain title border)
125 :border 10 (creates an empty 10 pixel border)
126 :border [10 "Title" 5] (compound empty/title/empty border)
127 :border (line-border :thickness 3 :color "#FF0000") (red, 3 pixel border)
128 :border (line-border :top 5 :left 5) (5 pixel black border on top and left)
129
130 Of course, a raw `Border` object can also be used.
131
132 ### Scrolling
133
134 Use the `(scrollable)` function to make a widget scrollable:
135
136 (scrollable (text :multi-line? true))
137
138 ### Splitters
139
140 Use the `(top-bottom-split)` or `(left-right-split)` functions to make a splitter each takes two widget args:
141
142 (top-bottom-split "Top" "Bottom")
143 (left-right-split "Top" "Bottom")
144
145 ## License
146
147 Copyright (C) 2011 Dave Ray
148
149 Distributed under the Eclipse Public License, the same as Clojure.
Something went wrong with that request. Please try again.