Cross-platform dressing not always a travesty
Friday is a news reader that is fed by an obscure, non-Google service known as “NewsGator,” as explained in last week’s post. And so many things have happened since then! The technology that drives Friday’s visuals, Processing, had a splashy 1.0 release. The Thanksgiving holiday was observed in the United States and we proved once more that our domestic travel infrastructure does not scale. Then on “Black” Friday, a Wal-Mart employee was trampled to death in a stampede of discount shoppers. All the while our Friday related these stories with unflappable grace and charm.
In celebration and exhaustion, let’s take this opportunity to write an easy post with lots of pictures.
Platform swingers
In the opera of Java, the tragicomic figure of Swing is rivaled in pathos only by El Duque himself (riding a swing). Swing was conceived in the midst of an object-oriented resource-based interface revolution, but the toolkit somehow managed to escape the paradigm that would have made it an unmitigated success. Instead, it opted for interface definition in code, which is great for writing Hello World and terrible for Usable Application. Ten years later Swing is popular for internal corporate apps that employees must use, or be fired.
Processing doesn’t advertise any support for traditional graphical user interface controls, because that is not its bag. The recommended way to do anything so boring is to embed the sketch inside a larger externally coded application, which is great for people that would rather work in an IDE anyway. But Friday and its Swing setup screen are developed entirely within the PDE (the Spde fork of it), because why crash the party with an IDE for something so simple?
One useful trick for apps with such a setup screen is to return false for displayable
in the main sketch class, so the sketch window won’t display until you tell it to. To pop up a separate Swing frame, it’s just a matter of instantiating the object and setting it to visible. Here is some scala-swing code to lay out the first three elements of Friday’s setup frame:
contents = new GridBagPanel {
add(new Label("NewsGator Account") {
font = font.deriveFont(java.awt.Font.BOLD)
}, new Constraints {
gridwidth = 2
anchor = Anchor.West
insets = new Insets(0, 0, 30, 0)
})
add(new Label("Don’t have an account?"), new Constraints {
gridwidth = 2
gridy = 1
anchor = Anchor.West
insets = new Insets(0, 0, 5, 0)
})
add(new Button("Sign Up…") {
reactions += {
case ButtonClicked(_) =>
link("http://www.newsgator.com/ngs/order1.aspx")
name_field.requestFocus()
}
}, new Constraints {
gridwidth = 2
gridy = 2
anchor = Anchor.West
insets = new Insets(0, 0, 30, 0)
})
...
UGHHHHHH. Did you think that a Scala wrapper would make code-based interfaces breezy and fun? Sorry to disappoint! This is probably nicer than the equivalent in regular Java Swing, but it’s still pretty annoying. And boy, wasn’t it fun adjusting each gridy
value to mock up different arrangements? (It was not fun.) That process should be done with an interface tool (an “interface builder”, one might call it) that produces resource files. Generating Java code is not the same and is particularly unhelpful in this circumstance where Java is not the language and the the code is not under any IDE’s obsessive control. No, an interface descriptor to go in data/
along with the fonts and images would be a thousand times better.
Anywho, this code-based layout is actually decent looking, even on practically abandoned Java platforms:
So if you have some hours to kill, yes you can cajole Swing layouts into looking passably native. The problem is not the pixels (although they are not perfect or else Quaqua would not exist). The problem is that tweaking layouts is tedious and most programmers won’t bother with it, even with a good layout tool. And without one, nobody is willing to sit through the two hundred tweak-compile-run cycles that a typically complicated interface will require to get right.
Don’t worry though, Friday’s simple setup screen only required fifteen head-smacking cycles.
Please download in an orderly fashion.
Codercomments
<rant mode=”maybetoolong”>
I would love to do GUI coding with Scala but just looking at a “Swing Ubuntu” theme makes me throw up. Wrong font anti-aliasing, no menu shadows, sluggish feel, wrong resizing behaviour. That is the reason why so many people I know hate Java - it just feels alien to the platform.
SWT looks a lot better, and I scalaified it a little but there are no designers for it so it is awkward to use.
I wish there was something as nice as GTK# for JVM/Scala :) But oh wait - GTK looks like Garbage on other platforms. Hrm Qt for Scala maybe? WxWidgets?
There are so many choices but not a single one that looks really convincing to me. So back to Delphi for Windows for VirtualBox and feel like being in the stone age of computer languages - but at least there is a nice gui designer.
</rant>
Oh nice post btw :)
Swing rendering on Ubuntu improved a lot with sun-java6 but I guess it is still not there for discerning eyes (I thought my screenshot looked good!). And without good tools, those quirks are likely just the icing on a sloppy layout cake. My impression is that GTK# and Glade are the closest that free software has come to doing it right, but like you say their output on non-free platforms lags. Still, at least a full solution is possible with that approach. You could very well make customized layout descriptors for targeted platforms, all bound to one executable codebase.
Well your swing screenshots certainly looks better and feels more natural than GTK+ on Windows (like in Gimp).
What do you think about SWT? I tried it a little and thought it did quite well, but I am by no means a Java expert (did mostly Delphi, C# before and fell in love with Scala recently cause I was attracted by the portability and open-sourcyness of the JVM without the ugly Java language). Eclipse is based on SWT and looks fine (except for those ugly tabs ;) ).
You can turn off those hideous tabs! (Show traditional tabs, under Appearance.) It is the first thing I do with a new Eclipse configuration. As a mostly Mac user SWT has never been my favorite. It tends too look crammed together on anything but Windows; Swing will at least space things out in accordance with platform norms, as the different setup screenshots show pretty dramatically. As far as I know SWT, like Swing, doesn’t have any provision for separating layout from code. It’s the GUI special olympics.
Cool, the tabs look almost good now, thank you!
I understand your concern about SWT, but still your Ubuntu picture looks at me and screams SWING :)
I really don’t understand why all those toolkits are in such a sorry state. In my dream world there would be a way to “somehow” define the rules for the gui layout (like your code but - well - not via code ;) ) and the toolkit should adapt it to the specific UI guidelines. There are of course several platform specialties, for example on Gnome/Ubuntu:
I am sure there are tons of those rules specifically for MacOS, as it cares more about consistency than any other OS. And for Windows we need theming and glass.
Besides that, my dream ui library has hooks to implement platform specific stuff: tray icons, resizing widgets bla bla ;)
So basically I want a more declarative variant of SWT with a nice UI designer that minimizes platform specific code as far as possible but allows it when necessary.
/me goes to SourceForge and prepares the workspace… ;)
My dream is similar, but with pixel perfect redering lower on the list. (By the way my Ubuntu’s font settings may be contributing to that image looking foreign; I prefer autohinter over native.) I’d say the layout binding side of things is actually doable for a free software project, and that a Glade binding for Scala could be awesome. But nailing down rendering glitches across all platforms really is the pits and may never happen without a profit motive.
I think that with recent Nokia move to license QT under GPL we get new great alternative. QT looks good (IMO) on all supported platforms. I’m not sure the better way would be to use Jambi (QT java version) or get SWT to integrate with QT (kind of cross-platform SWT). So my dream would be: Scala DSL -> SWT -> QT. It would mean nice static API and cross-platform nice looking GUI-s (at least in theory).
I was thinking that Jambi might be the way out, but trolltech pulled the plug on it right after I first heard of it. It seems like open-source, cross-platform, object-oriented, resource-based interfaces are not meant to be. (Or at least, are not meant to be popular. Libglade could fit the bill, but it’s not much used outside of c/c# and gnome.)
Add a comment