15 Comments

Clojure Desktop Applications with Swing

Starting a Clojure Desktop Application

We’re starting up our first desktop application in Clojure. We’re a heavy vim and ruby shop. We’ve done several desktop applications in JRuby. This is the first time we’ve tackled swing UIs and GUI testing in Clojure. It’s still early in the process, but here’s what we’ve found so far.

Swing

For Swing, we’re using seesaw. It provides Clojure bindings to standard Swing widgets and MigLayout, which was all I set out looking for. What really impressed me, however, was its CSS selector engine, allowing you to query a frame for particular widgets for event subscription or manipulation. It also offers an impressive data binding mechanism similar to UNIX pipes, complete with transformations and tee.

Testing

We’re using Brian Marick’s Midje for unit testing and fest to automate system tests.

Packaging

Leiningen manages our dependencies and packages our jars. We’ve found it helpful to set up a local maven repository in our vendor directory for a couple of cases where we needed a jar that was neither in the main maven repository nor clojars.

Editing

We’re heavy Vim users here at AO, but as fantastic as VimClojure is, paredit.vim from slimv just doesn’t compare to Emacs’ glorious mode. I’m pretty incompetent in Emacs, but the Emacs starter kit and a weekend of practice with Emacs and ParEdit has taken the shine off my beloved vim for lisp editing. (It’s actually been a while since I last used Emacs, so I’m sticking with vim in the short term while I ramp back up with Emacs).

State mediation between model and view

So far things are going well with Clojure, but rethinking our approach to structuring GUI applications is definitely a challenge. We normally use MVP/Presenter First when building web applications, but the pattern doesn’t map as easily to Clojure as it does to new object oriented languages. Decoupling domain model and UI with a stateless definition defining communication between the two still seems like a winning combination. We’re using Clojure reference types (refs, atoms, actors) to represent entities in our application domain and using event handlers and data binding with selector-identified Swing widgets. This seems like a workable approach but there are still questions to answer. More to come.