Why Spend More Than Five Minutes on a GUI?
This item was originally posted on the Wolfram Research blog at http://blog.wolfram.com/2007/05/17/why-spend-more-than-five-minutes-on-a-gui/
I've been a "professional" user-interface programmer for 20 years. In that time I've written a grand total of three little apps just for the fun of it. Two of them I snuck in as hidden buttons in the Mathematica About Box, because it was just too difficult to start a new application from scratch. All of them can be replicated in a few minutes using Version 6. In my experience, writing GUI (graphical user interface) applications in C or Java or Visual Basic--or whatever--is fine if you plan to spend weeks or months on a program, but prohibitively horrible if you really only have a few minutes to dedicate to the task.
You have to allocate windows, store pointers to them, then allocate controls or read them from some kind of resource file, store pointers to them, blah, blah, blah. It might be two or three pages of code before you can even start thinking about what this program is actually supposed to do.
Cocoa and other such frameworks make it marginally easier. I enjoyed programming in NeXTSTEP (which is what Cocoa was called before Apple took over NeXT). It's the environment in which I wrote RealTimeAlgebra in 1989, the one just-for-fun app I wrote not as an About Box button. (RealTimeAlgebra was basically what we now call Manipulate.)
But it is still a pain. Instead of starting by writing pages of code to deal with windows, you start by using an annoying graphical tool to lay out controls and define who is connected to whom. Then you get to write pages of code defining the actions of all these controls before you can start working on the actual content.
When I'm working on a fun little app, I'm like most other people who are not professional user-interface programmers. I want to think about the subject matter, the content of my program, first. I don't have hours to spend worrying about window pointers or event handlers.
If I want an interactive graphical tree to play with, I want to worry about the algorithm for defining the tree, not about how I'm going to read mouse coordinates. That is the great beauty of Mathematica: you get to start on the content right now.
Here's a little bit of Mathematica code that draws a pretty tree:
Graphics[Map[Line, NestList[Flatten[Map[ {{#[[2]], #[[2]] + .7 RotationMatrix[.3].(#[[2]] - #[[1]])}, {#[[2]], #[[2]] + .7 RotationMatrix[-.3].(#[[2]] - #[[1]])}} &, #], 1] &, {{{0, -1}, {0, 0}}}, 7]]]
I first wrote a version of this code in 1989. That version still works, but this is shorter because I've gotten smarter in the meantime. (The old version was pretty short too, by the way.)
Back in 1989 I had an idea that this would make a neat museum display. Imagine a metal post with two arms forming a Y shape, like the trunk and first two branches of this tree. Imagine that you can grab handles on the ends of the two branches and move them up and down, in and out, with some kind of telescoping mechanism. Now imagine a huge video screen behind the stand with a tree like this waving back and forth based on the position you move the arms to (recursively replicated in each successive generation of branches). Kids would love it.
I really, really wanted to make an interactive version of this tree--one where you could drag the first branch point around and have all the other branches recursively follow. This ended up as a secret button in the Mac version of Mathematica's About Box, involving hundreds of lines of C code.
Here is the same code for the tree made interactive using the Manipulate function. In Mathematica or the free Mathematica Player, you can use those two Locator objects to manipulate the tree. Notice that it's only a few lines longer than the non-interactive version:
Manipulate[ Module[{m1 = {Reverse[pt1], {-1, 1} pt1}, m2 = {Reverse[pt2], {-1, 1} pt2}}, Graphics[Map[Line, NestList[Flatten[Map[ {{#[[2]], #[[2]] + m1.(#[[2]] - #[[1]])}, {#[[2]], #[[2]] + m2.(#[[2]] - #[[1]])}} &, #], 1] &, {{{0, -1}, {0, 0}}}, 8]], PlotRange -> {{-3, 3}, {-1, 5}}]], {{pt1, {-0.25, 0.75}}, {-3, 0}, {3, 6}, Locator}, {{pt2, {0.25, 0.75}}, {-3, 0}, {3, 6}, Locator}]
alt="Instant dynamic interactivity" title="Instant dynamic interactivity" border="0">
Now in fairness, the C-code version I wrote supported three features this version does not: it had lines that got thinner the farther out they went, it had seasonal colors, and it had wind. Without those features the C code might have been only 300 lines (plus a few hundred more if I hadn't borrowed the framework of Mathematica's About Box to put it in). Adding them to the Mathematica version doesn't make it a whole lot longer. For example, here's a version with thinning and a Slider for the number of recursions:
Manipulate[ Module[{m1 = {Reverse[pt1], {-1, 1} pt1}, m2 = {Reverse[pt2], {-1, 1} pt2}}, Graphics[MapIndexed[{Thickness[0.01 th^#2[[1]]], Line[#]} &, NestList[Flatten[Map[ {{#[[2]], #[[2]] + m1.(#[[2]] - #[[1]])}, {#[[2]], #[[2]] + m2.(#[[2]] - #[[1]])}} &, #], 1] &, {{{0, -1}, {0, 0}}}, gen]], PlotRange -> {{-3, 3}, {-1, 5}}]], {{gen, 7, "generations"}, 3, 10, 1}, {{th, 0.7, "thickness ratio"}, 0.01, 1.2}, {{pt1, {-0.25, 0.75}}, {-3, 0}, {3, 6}, Locator}, {{pt2, {0.25, 0.75}}, {-3, 0}, {3, 6}, Locator}]
alt="Add more interactive features with minimal code" title="Add more interactive features with minimal code" border="0">
Unfortunately these versions, and my C-code version, suffer from one big problem: the mouse has only two degrees of freedom, while this example has four.
In the museum installation I imagined you would be able to move all four degrees of freedom simultaneously.
But guess what? With the Mathematica version of this code, I can plug in a dual-joystick gamepad, select the output, and the two joysticks automatically grab onto the two control points and let me control all four degrees of freedom simultaneously. Totally automatic--not a single line of new code needed.
I don't even want to think about how hard it would be to write in gamepad support in the C-code version of my tree toy. Don't even want to go there. (And I deny any rumors that we added gamepad support to Mathematica just so that I'd finally be able to see what this example feels like when you can control it properly.)
Sadly, no museum has yet built this exhibit, but since Mathematica started to become able to create this sort of interactive content, I've written dozens and dozens of similar live interactive interfaces. I would have done that years ago, but there was no tool in existence that made it possible.
"Possible?" you say. "Surely it's possible in C code, or Java, or Visual Basic, or Squeak, or something."
Well, no, it's not possible for me in C or any other such serious environment, because I'm busy and these are just fun little things. If it's going to take hours or days to do, it's not possible for me to do. And it's not possible in any of the cute visual programming environments because they are just not flexible or powerful enough. They're great for making the kind of thing, whatever it is, that they happen to be good at, but what if that's not what I want to make?
The beauty of Mathematica is that it's a good language first and foremost: it's a language in which you can write just about anything that can be written. And once you've worked out a little program that does something interesting, it's a very slippery slope (this being a good thing here) to start adding interactive elements to it.
Two minutes--not two days--to go from a neat program to a neat program with sliders.