Seesaw

Intro

I discovered the Seesaw library and instantly fell in love with the style of its creator. It is so wonderful to see documentation that wants to be helpful. This post is my walk through the library trying to set up a GUI display-only table (for a personal project).

Seesaw seems to have 2 recommended options, a table and the MigLayout with more widgets.

;; deps.edn
{:deps {seesaw/seesaw {:mvn/version "1.5.0"}}}

Namespace Setup

user> (use 'seesaw.core 'seesaw.table)
nil

Frame Setup

Following the Seesaw wiki. Things seem to be going well so this is the last direct use of the REPL; from here the flow switches to executing from a file.

user> (-> (frame :title "Seesaw Walkthrough" :content "Aye") show!)
; #object[seesaw.core.proxy$javax.swing.JFr...
img
user> (def f (frame :title "Seesaw Walkthrough" :content "Aye"))
#'user/f
user> (-> f show!)
;; ...

Option 1 - table

I go in blind to create a table using the wiki as a guide. It is gloriously simple.

;; this was secretly a false start.
;; seesaw.table namespace isn't used directly to create tables.
(def t (table-model :columns [:yan
                              :tan
                              :tethera]
                    :rows [{:yan 1 :tan 2 :tethera 3}
                           {:yan 1 :tethera 3}
                           {:yan "Aye" :tan "Nay" :tethera "Silence"}
                           {:yan '(3 2 1) :tan {:a :b :c :d} :tethera [1 2 3]}]))

(def u (table :model t))
(-> (frame :title "Demo" :content u) show!)
img

That has to be about as easy as using HTML. What a wonderful library. It isn’t often things work first try!

Option 2 - Mig

This will have to be a real contender to knock out table, but this library is on a roll so why not. Layouts are usually more flexible and more effort to work with so this probably won’t be as gloriously simple. Preparatory reading of the MigLayout web page was done, including the white paper because everyone loves a white paper (it rewards the reader with this sentence: The API version will not be handleled furthere here since that would mostly be reiterating the same things twice). It looks like a comprehensive layout, and the quickstart guide is also appealing.

At this point the wiki fails and I have to look for a tutorial (wow, table, you are a jewel among functions).

(def mig (mig-panel))
(-> (frame :title "Demo MigLayout" :content mig) show!)

;; Maybe there is an "add" function like in normal swing? Aha, there is an add! in seesaw.core
(add! mig (label "A"))
(add! mig (label "B"))
(add! mig (label "C"))
(add! mig (label "D") "wrap") ; Doesn't wrap.  Read docs and...
(add! mig [(label "e") "wrap"]) ; Works as expected.
(add! mig (label "F"))
(add! mig (label "G"))
(add! mig (label "H") (label "I") (label "J") (label "K"))
img

I’ll probably stick to table but this layout is going to be my go-to in the future. It is nice.

Conclusions

This library has now exceeded all my expectations. It has hit an inspired design that:

  1. Completely anticipates what I want to do.
  2. Provides documentation hits a perfect pitch between API descriptions and practical hints (like “use MigLayout”).
  3. No interaction with Swing is happening in the API, but it respects Swing knowledge and doesn’t try to hide Swing objects.

10/10, recommended library.