lice! : clojure swing in real world

clojure swing in real world

I’m currently working on a little tool for my work, one that requires a little gui, a menu, a combo box, two tree views and a text field, most of them interconnected. I’m lucky that I can develop this on clojure since to me it’s a great joy to write in this language. Now I said GUI, and fortunately I’d had clj-swing in my back of tricks and this was a great oportunity for me to test it in real world conditions, now I figured that I share the few things I’ve learned during this last days and weeks.

It works

As absurd this sounds, I was positively surprised of how well it worked and that I had to jump trough little loops to get things working. Of cause it wasn’t all smooth and nice, a few times I had to fall back to java interop but I think it was forgivable in the whole picture. Also it showed me a few things that clj-swing could do better and allowed me to improve it, which will continue to happen :).

The REPL is tricky

I am coding in EMACS+slime and I noticed that swing and slime don’t go along to well, all the seperate treads lead to the point where the swing app locks up for no reason – runnig it with java works fine so.

clojuires mutables are great

We all know this already but I mean great in another sense, it is super easy to store the data in them and see how things automatically update the GUI once the data changes, weehee!

And here how the gui code looks, somet things will go away with in the next clj-swing version and the code for actual actions is in extra functions (as it should be) but this is how you can generate a window with two tree vriews a splitter a combo box and a text field all interacting in one way and another over refs:

(defn -main []
  (let [matcher-cb (combo-box (keys @matchers)
            :maximum-size (java.awt.Dimension. Short/MAX_VALUE 25)
            :action ([e] (combo-box-change-action e)))
  menubar (make-menubar 
     [{:name "File"
       :mnemonic KeyEvent/VK_F
       :items 
       [{:action (make-action 
            {:name "Open..."
             :mnemonic KeyEvent/VK_O
             :handler (fn [_] (open-action matcher-cb))})}
        {:action (make-action
            {:name "Compile..."
             :mnemonic KeyEvent/VK_C
             :handler (fn [_] (compile-action (selected-item matcher-cb)))})}]}])
  text (text-field :editable false :str-ref tf :maximum-size (java.awt.Dimension. Short/MAX_VALUE 25))]
    (frame :show true :menubar menubar
     :default-close-operation :EXIT_ON_CLOSE
     :title "Config Generator 2.0"  :size [600 400] 
     [_ (split-horizontal
         (tree :model (mapref-tree-model raw-data "Data"))
         (stack
    [_ (panel :name p
        :layout (BoxLayout. p BoxLayout/PAGE_AXIS)
        [_ matcher-cb
         _ text])
     tr (tree 
         :action ([old-path new-path]
        (tree-change-action old-path new-path text))
         :model (mapref-tree-model 
           data {:name "Data" :good (good-data? @data)} 
           :node-wrapper (fn [node path] (Pathed. node (str (:name node)) path)))
         :cell-renderer renderer)]
    (add-action-listener text ([e] (check-validity)))))])))

Posted by Heinz N. 'Licenser' Gies Tue, 20 Jul 2010 10:47:00 GMT


Trackbacks

Use the following link to trackback from your own site:
http://blog.licenser.net/trackbacks?article_id=76

Comments

Leave a response

Leave a comment