Archive

Archive for April, 2011

20 Minute File Explorer with Seesaw

April 30th, 2011 3 comments

Seesaw, my Clojure/Swing experiment has been making a lot of progress. Earlier today I added basic support for JTree which is kind of the last major Swing component that had no support in Seesaw. As an test, I thought I’d try making a file explorer with the directory tree on the left and file list on the right. It took about 20 minutes and was way less tedious than the equivalent raw Swing code you’d write in Java or Clojure.

The full code for the example can be found on github.

Here’s what it ended up looking like:

Code Highlights

There are three code highlights.

Set up a model for the tree using the same pattern as (cloure.core/tree-seq):

; Make a model for the directory tree
(def tree-model
  (simple-tree-model
    #(.isDirectory %)
    (fn [f] (filter #(.isDirectory %) (.listFiles f)))
    (File. ".")))

Set up the structure of the frame. I think this reads pretty nicely:

  (frame :title "File Explorer" :width 500 :height 500 :pack? false :content
    (border-panel :border 5 :hgap 5 :vgap 5
      :north (label :id :current-dir :text "Location")

      :center (left-right-split
                (scrollable (tree :id :tree :model tree-model :renderer render-file-item))
                (scrollable (listbox :id :list :renderer render-file-item)))

      :south (label :id :status :text "Ready")))

Set up selection event handling:

  (listen (select [:#tree]) :selection
    (fn [e]
      (if-let [dir (-> (selection e) first last)]
        (let [files (.listFiles dir)]
          (config (select [:#current-dir]) :text (.getAbsolutePath dir))
          (config (select [:#status]) :text (format "Ready (%d items)" (count files)))
          (config (select [:#list]) :model files))))))

Here, the widgets are being retrieved by id with the (select) function. Alternatively, I could have just bound them to variables and used them directly. I’m still thinking about how this should work.

Conclusion

This is obviously still a toy (no sorting, doesn’t update, etc, etc), but I think shows promise. I like the separation of the structure and behavior, but the selector stuff needs more thought. Probably the biggest gain over raw Swing is that Seesaw takes care of all the yucky reify and proxy stuff for you. In this example alone, a raw implementation would need two (reify)s and a (proxy) call. Building up the widget structure is also pretty tedious with raw Swing.

I’d love to to hear feedback and criticism of the API since this is my first attempt at real Clojure code. Thanks!

A nice evening with the Clojure REPL

April 25th, 2011 4 comments

I’ve been working on Seesaw a lot lately. It’s a Swing wrapper/dsl/whatever for Clojure and I’ve had a great time working on it. Tonight, I was testing some very simple graphics stuff I added (namely, the (push) macro) and I had a nice moment with the REPL. Here’s my session where I paint some text to an image and display it in a JFrame:

Clojure
user=> (use 'seesaw.core)
nil
user=> (use 'seesaw.graphics)
nil
user=> (use 'seesaw.color)
nil
user=> (def image (buffered-image 200 200))
#'user/image
user=> (let [g (.getGraphics image)]
 (.setColor g (to-color "#FF0000"))
 (.drawString g "This is RED" 5 20)
 (push g
   (.setColor g (to-color "#0000FF"))
   (.drawString g "This is BLUE" 5 40))
 (.drawString g "This is RED again" 5 60))
nil
user=> (frame :content (label :icon image))
#<JFrame ...>
user=>

and up pops:

All the yucky Java-y graphics calls need to be cleaned up, but I would never be able to type in the equivalent code in Java without liberal use of ctrl+space.

Ok, back to work.

 

 

Categories: clojure Tags: ,

Here Comes Clojure: A Clojure Talk in Clojure

April 6th, 2011 5 comments

TL;DR: I did a talk on Clojure and wrote the slides in Clojure. Code here.

Edit: Fixed apostrophes. That’s embarrassing.

On kinda short notice I found out I was giving a talk on Clojure at this week’s CraftsmanGuild meeting in Ann Arbor. I’m not an expert, but “in the land of the blind, the one-eyed man is king” or something, so I was happy to do it. CraftsmanGuild is low pressure and fun.

So, I fired up PowerPoint, wrote a title slide, and then stared at the screen for a bit. This is no fun. Then it was the kids’ bedtime, which means I got to sit in my daughter’s room for a bit and just ponder. Like Hammock Driven Development, I guess. And as I sat there, in the glow of the nightlight, I got it: Why not implement my talk in Clojure, driven by some simple vim macros? It’s either brilliant, or really stupid.

If anything, the benefits outweighed the risks:

  • Practice Clojure while preparing my talk
  • Practice Vim while preparing my talk
  • No PowerPoint

The main risk was totally bombing in front of a friendly audience that’s just there to learn and have fun. Not too scary.

Here’s a screenshot of the title “slide”:

The implementation is super simple. Basically just a vector of strings and a current atom which points at the current slide. The advance! function moves the pointer, formats the slide (nice ascii borders and padding) and prints it.  It’s super simple, and can certainly be written better. I ran all of this in a VimClojure REPL set up as described in a previous post. There were a few cool things about this:

  • I got syntax highlighting of sample code (and admittedly, the rest of the text) for free.
  • I could immediately type examples or elaborate ideas directly in the REPL without leaving my “slides”.
  • I could evaluate code samples right from the slide and expand on them live.

I hacked (I mean they’re really kludgy) together some simple vim macros to:

  • Reload the presentation code
  • Go back to the beginning
  • Advance to the next slide
  • Evaluate the form under the cursor in the REPL. This was slightly tricky because it had to strip out the slide “borders” first.

Overall, I think the effect was pretty cool. Everything ran well, with the major problem being that the projector’s red wasn’t working so it was hard to see some of the text. Oh, and at one point I accidentally hit my caps lock with the usual confusion that accompanies it. Bygones. The actual content was probably the weakest part of the talk, but not terrible. Passable for two nights prep.

Here’s one last screenshot showing some syntax highlighting and simple ascii diagramming:

The code for the talk is all up on github: https://github.com/daveray/here-comes-clojure. Note that vim isn’t required. It will run in a normal REPL, it just won’t look as nice. And, of course, I’m sure something much more impressive is already built-in to Emacs :)

Categories: clojure, vim Tags: , ,