I've set up a Google Group for Seesaw discussion and questions: https://groups.google.com/group/seesaw-clj
Also see the API docs here: http://daveray.github.com/seesaw/
Also, there are a number of blog posts on various Seesaw features here: http://blog.darevay.com/category/seesaw/
and Release Notes.
Here's a brief tutorial that covers some Seesaw basics. It assumes no knowledge of Swing or Java.
For simple applications, NO. You might have to occasionally consult Javadocs. The doc string for most functions includes a link to the relevant Javadocs as necessary. BUT, Seesaw does it's best to make this unnecessary. Foremost in this effort are the
(seesaw.dev/show-events) functions. If you're ever wondering what options a widget takes, or what events it generates, you can ask at the repl. For example, with a label:
user=> (use 'seesaw.core) nil user=> (use 'seesaw.dev) nil user=> (show-options (label)) ... prints a long list of options along with example values ... user=> (show-events (label)) ... prints a long list of supported events ...
For complex applications, probably. Seesaw does its best to make the common case easy and everything else possible. Seesaw operates on and returns raw Swing objects so you can always drop down to raw Swing if you need to do something fancy. If you find you're doing this a lot, please ask on the mailing list. I'd love to hear about any holes in Seesaw's API.
Try out the Substance/Insubstantial skins. There's an example of using Seesaw with Substance here. It's really pretty easy to add and totally non-invasive. Just add a dependency and a function call or command-line option.
Let's create a
(-> (frame :title "Hello" :content "Hi there") pack! show!)
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 (see Widgets). Note that by default a new frame is invisible. The
pack! function sizes the frame for its content. The
show! function makes it visible. Same goes for dialogs.
There are many examples. They're all in the test/seesaw/test/examples directory. There's a launcher app that will run examples which you can start like this:
$ lein examples
Note that Seesaw uses Leiningen 2 now!
or you can run individual examples like this:
$ lein run -m seesaw.test.examples.<name-of-example>
To run the tests:
Hopefully you see a nice wall of green. Also,
./lazytest-watch.sh runs lazytest in "watch" mode. The tests will be re-run every time you modify a file. Basically all my development is like this:
One nice thing is that if you have an example (like in
test/seesaw/test/examples) if you call the main function there, lazytest will basically run the example over and over again. So you get a workflow like:
Of course, the examples should be tested, but they aren't :)
Here are topics covering most areas of Seesaw usage:
(native!) function early in your program (like before any other Swing or Seesaw function is called) to get a more "native" behavior. This includes correct menu bar placement in OSX, etc.
As noted here Swing is single threaded nearly all UI operations should be executed on the Swing UI dispatch thread. To facilitate this, Seesaw includes the
(invoke-later) macros. The former executes forms on the UI thread and waits for their completion, while the latter simply schedules the forms for execution sometime in the future.
A typical use for
(invoke-later) is to get things going in an app:
(defn -main [& args] (invoke-later (show! (frame :title "Hello" :content (button :text "Push me")))))