Interface Builder vs. Macromedia Flex Builder 2

I recently tried out the beta of Macromedia Flex Builder 2, and was quite impressed. I normally avoid Flash on principle, but it has some pretty powerful tools built in. It feels more limited than Apple’s Interface Builder, but it has one feature that I’ve been dying to see in IB: You can flip between visual drag-and-drop widget mode, and editing the layout as XML. Interface Builder so needs this ability. It would help for folks writing about developing for OS X (sometimes 100 words is better than half a dozen pictures, and trying to show CTRL-dragging in a still picture is an exercise in futility), and it would help when you come to a new project (or one you haven’t worked on in awhile) and want to get a feel for what methods and event handlers are hooked in to various widgets. Heck, it would help with automated tools, with testing, with grep. Just do it, Apple, or hire me to do it.

The other part that was interesting for me was that Flex Builder runs inside of Eclipse. It’s been a long time since I’ve tried Eclipse and I was pleasantly suprised. It was fairly snappy, not too confusing to find my way around in, and looked better than I remembered. Of course, I was running it on a dual 3GHz Windows box, so I might be disappointed once more if I ran it on my Powerbook, but my brief encounter with it didn’t suck, which was a big improvement.

Of course, neither of these developments are going to lure me away from Python and Vim any time soon.


My posts have been infrequent, in part because I’ve been working on lots of things to talk about. I’m in the last stages of putting together info on creating NSStatusItems (tools which show up in the menu bar across all applications in OS X) in PyObjC. I’ve also got some cool Quicktime and iSight tools coming soon. And I’ve renamed ZenPaint to DrawingBoard, but it’s working and just waiting for a little GUI cleanup before I post the first binary and source.

Two of my back-burner projects, better blue-screening, and easy lightsabre effects, have been done by others recently. Inspired by the same BoingBoing piece on rotoscoping your own lightsabres as I was, but Naked Software actually sat down and wrote the code. It’s pretty slick, too. For blue-screen effects (and many more), check out Sam Kass’ Quartz Composer Compositions. Very neat stuff, Tiger-only though [Update: now Leopard]. Some of the compositions require a newer system with a higher-end video card than my three-year-old PowerBook.

But to be honest, the real point of this post is not to tease with coming attractions, but to point out my first paid publication. My friend David Mertz asked me to collaborate with him on his XML Matters column for IBM developerWorks, and my first column went live last Friday: Beyond the DOM.

I’ve wanted to be a writer for as long as I can remember, with poetry notebooks and 200 pages of a novel gathering dust on my bookshelves, so finally getting around to finishing something and having it published leaves me pleased as punch. And more will be forthcoming.

Not dead yet

I’m still here. I’m going to post the previous examples .dmg with some corrections pointed out by Bob Ippolito (4-space indents, don’t modify data directly in the Bundle). I’ve been quiet because a) I’ve been hitting some walls with Renaissance and investigating work-arounds and alternatives, and b) my coding/blogging time is pretty much between the time I get the kids to bed and the time my wife comes home from tutoring.

I’m investigating the PyGUI and Wax APIs, to see if they are worth porting to run on top of Cocoa (PyGUI runs on Carbon, Wax runs on top of wxPython). Both are attempts to make GUI creation more “Pythonic,” which is a Good Thing™. I have figured out how to get the menus initialized using pure Python (on top of PyObjC, of course), or maybe the newer pyobjc/py2app has fixed the problem, but it is possible to build applications in Python with no Nib file (or Renaissance .gsmarkup file) at all. My earlier inabillity to do that is what drove me to Renaissance in the first place.

I’ve also discovered the nibtool utility, which I did not know about. This allows you to see a textual representation of the nibs created by Interface Builder, search and replace strings (class names, etc.). This is a major discovery. Now if you could take the textual representation and put it back… I’m going to have to investigate this further.

In other news, I will be giving a presentation on Tuesday, February 1 at the Vancouver Zope and Python Users Group (VanPyZ) at 7:00 p.m. It will be a variation on the talk I gave in December to the XML users group, updated with what I’ve been exploring since then. Specifically I will show a simple (Hello World) application built three different ways, with Renaissance, with Interface Builder, and in pure Python. I’ll also show some apps written in other toolkits (wxPython, tkinter) for comparison. I hope some of my readers are close enough to make it.

I’ll also be attending the Northern Voice blogging conference here in Vancouver on Saturday, February 19th. I’m looking forward to meeting some fellow bloggers face to face, rather than RSS to RSS.

Finally, I managed to install Python 2.4 today, and so far nothing has been obviously screwed up, so I’ll be exploring some of the crunchy new features here in the near future.

More posts coming soon. Honest!

Slides and code posted

My talk at VanX last night was a success. Not many people showed (too close to Xmas), but the ones who did seemed to enjoy my presentation on Cocoa, Python, and Renaissance. Gerald was a great host, SchemaSoft provided a good (and convenient!) venue, Paul came to show support, and BlastRadius (my employer) sponsored the snacks. After we went to Mira in Yaletown for beers and tech talk, had the whole place to ourselves, and a musician playing Flamenco guitar, then I walked across the bridge to home. A great end to a great evening.

I’ve posted my slides at using Eric Meyer’s neat S5 tool to put the whole slideshow into one HTML file.

I’ve also built a new .dmg containing all the source code and built, runnable examples (seven of them now), although they’re not all fully functional yet. More example gsmarkup to view, improved setup scripts, and they all have icons now. The file is examples 2004-12-17 on SourceForge.

I’ve been working hard to put this all together, which hasn’t left much time for posting, but I will have a lot more to say real soon now.

GMarkup Browser

Today’s exercise was to port the GMarkup Browser, an Objective-C program which comes with Renaissance, to Python. Using this allows you to see what various gmarkup files will look like when they are loaded, which is very handy as you’re developing a program’s UI, without having to build a program around them. The source code of Renaissance (available separately from the binary we installed a few entries ago) contains an Examples folder showing all of the tags in use, both as small toy examples and tests, and as full-fledged applications. It’s well worth downloading this and poking around in it with the Browser.

There are three files today, the, a simple MainMenu.gsmarkup, and the application. Note that loading resources, especially menu resources, into a running program can cause bad side effects. So far I’ve been able to exit by ctrl-clicking the application icon and selecting quit, even when the menus disappeared, but use caution. Also, buttons wired up to the “terminate:” selector will exit your program if you click on them. With great power comes great responsibility, or something like that. Caveats aside, you can open multiple gsmarkup files at a time, just use the File->Open menu or Cmd-O.


<?xml version="1.0"?>
<!DOCTYPE gsmarkup>
        <menu type="main">
            <menu title="GSMarkup Browser" type="apple">
                <menuItem title="About GSMarkup Browser"
                <menu title="Services" type="services"/>
                <menuItem title="Hide GSMarkup Browser" action="hide:" key="h"/>
                <menuItem title="Hide Others" action="hideOtherApplications:"/>
                <menuItem title="Show All" action="unhideAllApplications:"/>
                <menuItem title="Quit GSMarkup Browser" action="terminate:" key="q"/>
            <menu title="File">
                <menuItem title="Open" action="open:" key="o"/>
            <menu title="Window" type="windows">
                <menuItem title="Minimize Window" action="performMiniaturize:" key="m"/>
                <menuItem title="Bring All to Front" action="arrangeInFront:"/>

Port of GSMarkupBrowser from Objective-C to Python
from Foundation import *
from AppKit import *
from Renaissance import *
class Owner(NSObject):
def takeValue_forKey_(self, obj, key):
    #print 'Set value %s for key %s of NSOwner' % (obj, key)
def bundleDidLoadGSMarkup_(self, notification):
    if NSUserDefaults.standardUserDefaults().boolForKey_('DisplayAutoLayout'):
        topLevelObjects = notification.userInfo().objectForKey_('NSTopLevelObjects')
        for obj in topLevelObjects:
            if obj.isKindOfClass_(NSWindow) or obj.isKindOfClass_(NSView):
def applicationDidFinishLaunching_(self, notification):
def open_(self, notification):
    filetypes = ['gsmarkup']
    panel = NSOpenPanel.openPanel()
    result = panel.runModalForDirectory_file_types_(None, None, filetypes)
    if result == NSOKButton:
        self.pathname = panel.filenames()[0]
        #print 'Loading', self.pathname
        didLoad = NSBundle.loadGSMarkupFile_externalNameTable_withZone_localizableStringsTable_inBundle_(
            {'NSOwner': self}, None, None, None)
        if didLoad:
            print self.pathname, 'loaded!'
            #print 'Could not load', self.pathname
def main():
    defaults = NSUserDefaults.standardUserDefaults()
    defaults.registerDefaults_({'DisplayAutoLayout': 'NO'})
    app = NSApplication.sharedApplication()
    owner = Owner.alloc().init()
    NSBundle.loadGSMarkupNamed_owner_('MainMenu', owner)
if __name__ == '__main__': main()

Minimal example, run with:
% python py2app
from distutils.core import setup
import py2app
    data_files = ['MainMenu.gsmarkup'],
    app = [''],

« Previous Page« Previous entries « Previous Page · Next Page » Next entries »Next Page »