Monday, April 30, 2012

Smalltalk meets Cubism

Everytime I meet up with Alexandre Bergel at a Smalltalk conference, we talk about Mondrian. And I always ask him a question: "Why is it that every time I see Mondrian, it's always about Rectangles?" In some ways, it's appropriate that Mondrian is always about rectangles. Google Mondrian, and the first images you'll see are all about rectangles. Nearly all of the artwork associated with Piet Mondrian is a love affair with rectangles.

Anyway, I thought it was time to put up or shut up. I want a new question to bug Alexandre about when we cross paths in the future. So I decided to play a little. I wasn't interested in rewriting all that Mondrian is. I just wanted to experiment a little with other polyshapes to express multiple simultaneous attributes of subjects I was trying to visualize. Mostly, I was interested in playing with MeshGradients using Cairo, because I was curious if I could find an interesting problem I could use mesh gradients with.

If you google Cubism, you'll see the artwork that I was inspired by. According to Wikipedia

In cubist artworks, objects are broken up, analyzed, and re-assembled in an abstracted form—instead of depicting objects from one viewpoint, the artist depicts the subject from a multitude of viewpoints to represent the subject in a greater context.

That sounded exactly like what I was trying to do. I published my couple-day-prototype in the Open Repository in a package called TAG-Cubist.  I realized in playing with this how it's not just about rectangles (of course), but how important layout of the per-subject-graphics is. I didn't do anything, other than present then in a tiled format. I'll leave that kind of thing to others. Here are screencaptures of the four example methods I put on the Portfolio class (a Portfolio is a collection of similar drawings for a group of different subjects).

Some of the methods found in the Portfolio object, showing clockwise, from noon high position: LoC, inst var ref count, selector size, argument count, and bytecodes.

Some of the top-level packages found in my image, showing clockwise, from noon high position: prerequisites, defined classes, extended classes.
Classes found in the ArithmeticValue class hierarchy, showing clockwise, from noon high position: methods, inst vars, refs to globals, global refs to the class (attributes suggested by Bob Hartwig, thanks!).

Top-level bundles in my image, showing clockwise, from noon high position: child packages, child bundles, prerequisites, comment size, defined classes, methods of defined classes, extended classes, extension methods.

If I was to go on playing, I'd basically start to reinvent Mondrian. Which is not something I really wanted to do. I might play with the way the shape is generated some more, make it more of a star graph (whereas it's a sort of spider plot right now). And I'd definitely figure out how to do a legend plot.

Wednesday, April 11, 2012

Cairo 1.12.0

A couple weeks ago, the good folks that give us Cairo announced that version 1.12.0 is ready for consumption.

In the last couple weeks, at sundry moments, I've been updating the VisualWorks binding to it, and playing with it some. There's some exciting news and some not-yet-good news. First, the good.

Doing a build for Linux was quite simple. And that allowed me to update/play right away. You can build it yourself, or ask me, I'm curious how portable the binaries I built are for consumption.

On of the exciting things new in 1.12.0 is at long last, Mesh Gradients. Mesh gradients are the "you can do anything with it" gradient. They can be used to simulate any other kind of gradient. Radial and Linear gradients can be done with them (Cairo gives us first class versions of these already). You can also do the elusive conical gradient.

Here'a round one (they don't have to be round) which varies evenly on hue. This can be fun to build pie charts with. Or you can build a conical gradient useful for doing highlighting masks after clipping to a shape

You can do more complex things with them, such as display map data, but I didn't find any simple ones to read and map to mesh (if anyone knows of some, let me know). Other than cones I haven't done to much with the meshes yet. But I'm excited to figure out what kinds of data visualization one could do with them for an application that might be written with VisualWorks. I have an idea of something, but... that'll have to wait for a later post if it works out.

The not-yet-good news is that so far, I only have this working on Linux. The build method I've used in the past, doesn't seem to work with this new version (it could just as well be that I'm now running Lion and newer versions of Xcode). I did manage to grab a binary from someone who had built just prior to release. While that worked for many things, it crashed when using the MeshGradient stuff. And the same goes for Windows so far. I hope to do some looking and have more/better news on these fronts in the weeks to come.

A Post STIC Talk Thought

At STIC I gave a talk about Skins. Skins are a way of separating display behavior from widgets, and trying to rectify some of what we see as "no longer sound" design decisions. At one point, I had put this graphic up on the screenfollowed by this one

It describes the central, fatter role, we're trying to give widgets we develop with the Skin mindset in mind. The one thing this kind of Widget does not do, is actual drawing.

I was asked later on "so, if we wanted to do some new widgets in with this newer GUI approach, how would we do this? Would we make a new skin?

The answer is no. Or at least, most likely not. The whole point of separating the drawing behavior into stateless policy objects, is to deal with having a single widget object, that can be rendered in different look and feels. But for most custom widget development, you don't care about different looks. You're not trying to ape Windows or OSX or something else, the look of your widget tends to be uniform. And so you don't need the whole separation/decoupling that a skin approach provides. You just have your Widget do it's own #displayOn: method.