So Windows Longhorn includes a new .NET application framework called WinFX, code-named "Avalon."
Turns out I was overly optimistic in my estimation of what Avalon was. It turns out Avalon is just a system for specifying your application's human interface in an XML-based language, XAML, and even specifying what actions in your code will be invoked by different interface elements. And then, get this:
You generate C# code from this that actually creates your interface!Gosh wow, golly gee! You mean I can use XML to drive a code generator? Ooo! Where do I sign up?
Why the hell does it need to generate code just to create an interface? Why the hell does it need to generate code just to associate a control with an action method? What
decade are we living in again? Interface Builder on NEXTSTEP was doing this stuff
right in 1988. Why are people acting like Longhorn's getting it marginally less wrong than previous Windows frameworks is such a big deal?
There's even a system like XAML available for Cocoa:
GNUstep Renaissance. Renaissance lets you specify your interface in an XML file, too, and has for quite a while. (
Nicola Pero first released it on December 26, 2002.) The big difference is that with Renaissance, you just load this "gsmarkup" file at run time and it generates the interface and binds it to your objects right then!
What's more, it includes a layout manager system similar to Java's for automatic interface layout. So you don't even need to specify sizes of controls, you can just let the layout manager handle everything.
Here's what a simple gsmarkup looks like (taken from the
Renaissance Tutorial):
<gsmarkup>
<objects>
<window title="This is a test window" closable="no">
<button title="Print Hello!" action="printHello:" target="#NSOwner" />
</window>
</objects>
</gsmarkup>This gsmarkup file specifies an NSWindow with no close box and the title "This is a test window", which contains an NSButton titled "Print Hello!" that sends
-printHello: to the object that owns gsmarkup (set when the gsmarkup is loaded). Note that you don't have to specify the size of the button, where in the window it is, etc. You
can if you want (or need) to, you just don't
have to. And if you don't specify a target for a control, its target is assumed to be
nil (the First Responder).
You can use
id attributes in a markup to name objects and then refer to them using the standard reference (
#foo) notation to wire them together within the same gsmarkup file.
And here's something even cooler: When a gsmarkup is loaded, an associated strings file is also loaded if one exists. This makes it very easy to translate gsmarkup-based applications into other languages. You don't even need to change the gsmarkup (especially if you're using layout managers) — you just have to supply a strings files for the other languages!
And possibly the best part: Renaissance works on both GNUstep and Mac OS X. You only need to maintain a different menu structure between the two; for everything else, you can use a single set of markup files (assuming you're using layout managers). One codebase, one interface spec, multiple platforms.
For more information, check out the
Renaissance Manual.