Archive

Archive for June, 2011

Ad Hoc Stylesheets in Seesaw

June 22nd, 2011 2 comments

Following up on my last post, I decided to try that distributed pi calculation in Clojure. That’s not going so great, mostly due to my own weak sauce. Luckily, it’s not the subject of this post.

While I was doing that, I kind of got sidetracked into making a little UI that shows the estimate for pi over time, using Seesaw of course. As I fiddled with the look (UIs are such a timehole), I realized I already had the building blocks for rudimentary stylesheet support. I wrote a simple function that iterates over a map (the “stylesheet”), looks up widgets with selectors, and then applies styling using the seeseaw.core/config! function:

(defn apply-stylesheet [root stylesheet]
  (doseq [[sel style] stylesheet]
    (apply config! (select root sel) (reduce concat style)))
  root)

The end result was a nice separation of style from structure with only four lines of code.

Yes, it’s still ugly, but I never claimed to be a designer :)

Here’s the full code which uses Seesaw 1.0.7. Note that I can style classes of widgets (e.g. JButton) as well as individual widgets by id.

If you see no code, look here

Note that I’ve omitted my abomination of a pi calculation. The Clojure mailing list will probably hear from me shortly :)

Categories: clojure, seesaw Tags:

Clojure and Akka: A match made in …

June 15th, 2011 2 comments

Akka has been in the news lately. It’s an actor framework, STM, etc rolled into one and generally joined at the hip with Scala. Despite that, it does have a Java API, so after seeing an interesting Akka talk by Nilanjan Raychaudhuri at Detroit Cloud Dev Day over the weekend, I thought I’d try using it from Clojure. Why? Because it’s there!

Source code for everything here can be found on github

Now, Clojure already has pretty equivalent concurrency constructs built into the language, so the utility of this little adventure is a little suspect. But Clojure’s constructs are strictly local, so Akka’s support for distributed actors keeps it interesting (*).

Anyway, after an evening with Clojure and Akka, I have to say they weren’t made for each other. I decided to do a straight port of the Java-based Pi calculation example from the Akka tutorial. I figured porting from Java to Clojure would be simpler than Scala to Clojure. It turns out that Akka, at least in the example, makes heavy use of sub-classing and further more the class literals of those sub-classes. In particular, you need a class literal to create a new instance of an actor. You can’t just “new it up” on your own. Now, Clojure has (proxy) which will let you extend Java classes just fine, but it creates a new instance of an anonymous class. It doesn’t really give you a class to work with. There’s also (gen-class), but I wanted to see if I could avoid that for the time being.

As luck would have it, Akka also supports actor factories in addition to the class literal approach, so I was able to add an additional layer of proxy fun and get the effect I wanted. Wrap it in a macro and you get something like this:

(defactor worker [] []
  (onReceive [work]
    (let [result (calculate-pi-for (:start work) (:num-elements work))]
      (.. this getContext (replyUnsafe (Result. result))))))

and then use it like this:

(make-actor worker)

Not beautiful by any stretch, but ok for an evening experiment.

One interesting “feature” of Akka that I stumbled upon is an error message like this:

You can not create an instance of an actor explicitly using 'new MyActor'.
You have to use one of the factory methods in the 'Actor' object to create a new actor.
Either use:
'val actor = Actor.actorOf[MyActor]', or
'val actor = Actor.actorOf(new MyActor(..))' 

Well, I was using factories throughout, but it turns out that the way this is enforced is with a thread local “current actor under construction” variable which apparently doesn’t play nicely if actor creation is nested within factories. Once I flattened out my actor creation, the error went away. Here’s the output from a run (full of warnings because I didn’t bother with actually installing Akka and just used Maven to get the jars):

61 [21:29:42] [~/Documents/projects/clojak]$ lein run -m clojak.pi
Can't load 'akka.conf'.
One of the three ways of locating the 'akka.conf' file needs to be defined:
        1. Define the '-Dakka.config=...' system property option.
        2. Put the 'akka.conf' file on the classpath.
        3. Define 'AKKA_HOME' environment variable pointing to the root of the Akka distribution.
I have no way of finding the 'akka.conf' configuration file.
Using default values everywhere.
        Pi estimate:             3.1435501812459323
        Calculation time:        11841 millis

In conclusion, here are my observations from this experience:

  • My conversion of the PI calculation function to Clojure is an unreadable atrocity.
  • It’s probably worth investigating why this is more than 10x slower than the sample output in the tutorial.
  • (*) Although I got it working with actor factories, this evidently makes distributing the actors difficult/impossible, which kind of eliminates any benefit that Akka would bring to Clojure.
  • By resorting to (gen-class), I should be able to generate “real” classes in Clojure for use by Akka. A simple stubbed implementation that delegates to a map of functions should make it pretty easy to use. I did something similar in Seesaw’s nascent applet support.
  • Clojure’s Java interop is generally awesome, but it works better with some API styles than others.

There’s a good chance that I just don’t know what I’m doing, so feel free to correct any egregious mistakes.

Ok. That’s it. Source code’s here.

Categories: clojure Tags: , ,

JSplitPainInTheAss: A less abominable fix for setDividerLocation

June 12th, 2011 9 comments

Update: Some discussion of this idea and code updates are in the gist here. Hubris.

If you use Swing much there will come a time when you’d like to create a splitter, aka JSplitPane. Overall, it works fine, but it has one lame, lame, lame feature; if you want to set the divider’s initial position proportionally, you’re screwed. I say feature, because the documentation for JSplitPane.setDividerLocation clearly states that it won’t work if the component hasn’t been “displayed” yet.

I bet that 95% of the time the programmer using this function is calling it at start-up before anything is displayed. Way to cover the 5% case there.

Anyway, you’ll go to Google and try to find a solution to this problem and you’ll find a lot of discussion and many variations on the same workaround. But they inevitably rely on sub-classing (isn’t that the solution to everything in Swing?) and hacking in some logic to fix things right before the splitter gets painted the first time. Nasty.

I’ve been thinking about this in terms of Seesaw, a Clojure/Swing API I’ve been working on. I want setDividerLocation to cover the 95% case and I don’t want to sub-class anything if I can help it. It’s not composable. So I thought about it a bit and came up with a much more elegant solution that works on a vanilla JSplitPane. Since I think this will be much more interesting to the Java Swing developers toiling away out there, I’ve coded it in pure Java. Here it is, a simple function:

If you can’t see any code, look here.

By the way, this code is insanely shorter in Clojure. Just sayin’.

The basic idea is to keep putting off the call to setDividerLocation using invokeLater until the splitter is realized on the screen. No fuss, no muss. … strike that. The invokeLater approach did indeed work, but under certain circumstances, a split pane that wasn’t displayed very soon would result in an infinite cascade of invokeLater events. The main problem with this is that the processor never gets to sleep, etc, etc. So I came up with an alternate approach which takes advantage of a HierarchyChange event to detect when the split pane is displayed (learn something new every day) optionally followed by a resize listener because the hierarchy event may arrive before the split pane’s been laid out by its parent. Swing’s exhausting.

Cheers!

Categories: java, swing Tags: , ,

Painting Widgets with Seesaw

June 10th, 2011 1 comment

The functionality describe here will be in the 1.0.7 release of Seesaw in the next week or so.

Say for some reason, you want a label with a red X on it. A bad, bad label. If you’re working with Swing in Java, you’ll create a new class, extend JLabel, override paintComponent, make some drawing calls, etc. Not terrible, but not that fun either. Something like this:

public class BadLabel extends JLabel {
  public BadLabel(String text) {
    super(text);
  }
  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    final int w = getWidth();
    final int h = getHeight();
    final int d = 5;
    g.setColor(Color.RED);
    g.drawLine(d, d, w - d, h - d);
    g.drawLine(w-d, d, d, h - d); 
  }
}

That’s pretty minimal if we ignore imports and stuff. Enabling anti-aliasing would be nice. It’d also be nice to set the width of the lines. And if you wanted to draw the X on a button or something else, you could pull all the drawing code into a function, but you couldn’t avoid a new, possibly anonymous, class for each type of component you want to use it on.

In Seesaw, we use the paintable macro to do all the dirty work for us. Give it a function to handle the painting and a description of the widget you want, and you’re done. It handles anti-aliasing and there’s functions that make styling the lines a little less tedious.

Below is the equivalent Clojure code using Seesaw. Note that here we can easily apply the red X to a label or a button. Of course this also puts the widgets in a frame and displays them too. I’ll spare you that part in Java :)

The code for this example is also here.

(ns seesaw.examples.paintable
  (:use [seesaw core graphics]))

(defn draw-a-red-x 
  "Draw a red X on a widget with the given graphics context"
  [c g]
  (let [w          (width c)
        h          (height c)
        line-style (style :foreground "#FF0000" :stroke 3 :cap :round)
        d 5]
    (draw g
      (line d d (- w d) (- h d)) line-style
      (line (- w d) d d (- h d)) line-style)))

(defn content []
  (flow-panel 
    :border 5
    :items [
      (label           :text "I'm a good label!" :font "ARIAL-BOLD-40" :foreground "#00AA00")
      ; *** Make a label and button with a red X on them ***
      (paintable label :text "I'm a bad label!"  :font "ARIAL-BOLD-40" 
                              :paint draw-a-red-x)
      (paintable button :text "I'm a bad button!"  :font "ARIAL-BOLD-40"
                                :paint draw-a-red-x)]))

(defn -main [& args]
  (invoke-later
    (->
      (frame :title "Seesaw (paintable) example"
             :content (content))
      pack!
      show!)))

(paintable) is still a macro so it comes with all the limitations associated with them. Unfortunately with Swing you have to sub-class to paint on a widget and in Clojure you can’t (as far as I know) sub-class at run-time.

Categories: clojure, seesaw, swing Tags: , ,

A Brief Note on Seesaw Selectors

June 8th, 2011 No comments

Just wanted to note that I finally got around to a full implementation of CSS-style selectors in Seesaw, the Clojure UI library I’ve been working on. The updated doc for the (seesaw.core/select) function has most of the details, but here are a couple examples:

      ; All JLabels, no sub-classes allowed
      (select root [:<javax.swing.JLabel!>])

      ; All JSliders that are descendants of a JPanel with id foo
      (select root [:JPanel#foo :JSlider])

      ; All JSliders (and sub-classes) that are immediate children of a
      ; JPanel with id foo
      (select root [:JPanel#foo :> :<javax.swing.JSlider>])

To implement the selectors, I hacked up the zipper-based selector code in the very cool Enlive project. It was surprisingly straightforward:

  • Modify zipper construction to create a zipper over a Swing widget hierarchy instead of an HTML doc
  • Hack up the parser a little bit to allow my Java-class-matching extensions
  • Update the predicate sets to work on widgets instead of DOM nodes

Hats off to Christophe Grand for writing such a well-factored piece of Clojure code that I could get this working in an evening.

I’ll write more (like what this could be useful for) when it’s not the middle of the night.

p.s. this will be in the 1.0.6 release on Clojars sometime this week after I beat on it a bit more.

Categories: clojure, seesaw, swing Tags: , ,