UI Scripts Basics

A xibless UI script is a Python script that describes a UI to build through Objective-C code that xibless is going to generate from that script. It creates objects like Window or Button, sets their properties and place them in their superview.

When a UI script is generated, it creates an Objective-C unit with one function that takes one argument, the “File Owner”, and returns the script’s result (see next section). Here’s an example of what its signature might look like:

NSWindow* createMainWindow(AppDelegate *owner);

Namespace and special variables

Every class described in the xibless API section are directly in the script namespace. Therefore, if you want to create a Label, you do it thus:

label = Label(parent, text="hello!")

Other than class references, there’s also a few special variables to keep in mind.

  1. result. This is where you must assign the main “result” of the script, most of the time a main menu or a window. All you have to do to assign it is to do so in the module’s global namespace.
result = Window(400, 200, title="My Window")
  1. owner. This is a bit like a XIB’s “File’s owner”. You can reference to it when setting properties and you can also set its own properties. Of course, the owner has to actually have the property you’re trying to set on it, otherwise, you’ll have a compilation error.
button.action = Action(target=owner, selector='myAction:')
owner.mySuperButton = button
  1. NSApp. A bit like owner except it references Cocoa’s NSApp.
menu.addItem("Quit", action=Action(NSApp, 'terminate:'), shortcut='cmd+q')
  1. ownerclass. If you want to send an owner, you have to set the ownerclass variable in your script to the name of the class the owner is going to be. If you do that, you also have to set ownerimport to the name of the unit to import to have ownerclass definition.
ownerimport = 'AppDelegate.h'
ownerclass = 'AppDelegate'
  1. const. See Literal Constants below.
  2. defaults. A reference to [NSUserDefaultsController sharedUserDefaultsController]. For now, it’s only useful when you call View.bind().

Literal Constants

Some widget attributes require literal constants from the Cocoa framework. For example, NSButton.state is either NSOnState, NSOffState or NSMixedState. You can’t use strings to set these values because they will be wrapped around @"" during code generation. When you need these types of values, use the const identifier which is present in the UI script namespace. For example:

findMenu.addItem("Find...", Action(None, 'performFindPanelAction:'), 'cmd+f', tag=const.NSFindPanelActionShowFindPanel)

The API documentation will indicate when such a constant is required. Ideally, there will be a constant in xibless (see Constants) wrapping every Cocoa constant, but doing so is boring work and I’m often too excited doing not-boring work to spend time wrapping constants. But eventually...

Bitwise OR-ed flags. Some attributes are actually masks, which required bitwise-OR-ed values. Well, you can do that in xibless. Use the | char as in const.flag1 | const.flag2.

Memory Management

Everything created inside a UI script is auto-released, which means that you have to retain it when you store the result and in your owner’s properties set by the script.

Of course, if an object is “naturally” retained by another object created in the script, such as a NSMenuItem added to a Menu or a view added to a superview, then you don’t have to manually retain those objects.

Unsupported Properties

xibless being in early development, it doesn’t support everything Cocoa has to offer yet. If you find yourself in a situation where an attribute you want to set on an instance isn’t supported, you can always try to set it in its properties dictionary, for example with:

foo.properties['delegate'] = bar

It’s not guaranteed to work, but it very well might.

Custom subclasses

In XCode’s interface builder, it’s possible to specify a custom class to instantiate instead of the base class. For example, if you have a home grown NSTableView subclass and want to instantiate it in an XIB, you’d change the table view’s class name to MyTableView. In xibless, you can do the same by setting the OBJC_CLASS attribute in this fashion:

table = TableView(window)
table.OBJC_CLASS = 'MyTableView'

Of course, as is the case with XIB’s your custom class will be instantiated with the same arguments as a typical NSTableView would.

Import from modules

Because UI scripts are Python modules, it’s possible to import from other modules. The folder in which the UI script is will be in PYTHONPATH, so you can do stuff like add a common.py unit and then do from common import MyLabelSubclass in your UI scripts.

The only thing to remember, however, is that the magic that goes on in UI scripts to put all xibless classes in your UI script’s global namespace doesn’t work for imported modules. Therefore, if your module use any xibless classes, you have to import them yourself from the xibless package (and you’ll have to figure out where they live in the package). That’s far from ideal, I’ll fix that some day.

Table Of Contents

Previous topic

Usage

Next topic

Layout

This Page