Renaissance
Menu Structure
The menu structure for GNUstep apps is different when they’re running on macOS than on other platforms. macOS has a special “app menu” named after the app that contains the About, Settings, Services, and Quit items, among others.
On other platforms, the GNUstep menu structure follows the NeXTstep/OpenStep convention, in which the first menu is “Info”, which contains the “Info Panel…”, “Preferences”, and “Help” items. The Services menu is at the top level of the app’s menu bar, as are the hide and quit menu items. Use this structure on non-macOS desktop platforms, regardless of whether the active theme draws a vertical, NeXT-style menu, or a horizontal, Apple- or Windows-style menu bar.
Renaissance Forms
An NSForm is a matrix of NSFormCell objects that associate labels with text fields.
To create one in Renaissance, use the <form/> element, where each child is a <formItem>, as in this example:
<form>
<formItem id="idField" title="User ID:"/>
<formItem id="emailField" title="Email Address:"/>
</form>
You can’t nest arbitrary views, for example NSTextField, inside a Renaissance form. Consider whether you need to use NSForm at all, or whether you can lay out text fields in the view directly instead.
Renaissance Lifecycle
Load markup programmatically during controller initialization, by calling -[NSBundle loadGSMarkupNamed:owner:]. The file’s #NSOwner reference is set to the object you pass as the owner. Call this method at the following points in your app’s lifecycle:
- To set the main menu, load markup that defines the menu after you initialize the app delegate, but before you call
NSApplicationMain. - To create UI that’s owned by the app delegate, load markup in your app delegate’s
-applicationDidFinishLaunching:method. - To create UI that’s owned by a controller, for example an
NSWindowController, load markup in the controller’s-initmethod. Don’t call methods that load other types of view files, for example,initWithWindowNibName:.
When Renaissance initializes and configures the view based on the contents of the markup file, it sends every object the -awakeFromGSMarkup message. Override this message to perform any actions after the view is configured and before someone interacts with it. Objects might receive other methods, like -windowDidLoad or -viewDidLoad, before Renaissance configures all of their connections.
Renaissance Outlets and Actions
Use XML elements and attributes in your .gsmarkup file to wire up outlets and actions between objects in the markup, and to the file’s owner.
Object references
Set the id attribute on an object element to give that object a unique identifier that you use when you reference it in outlets and actions. For example, if you define an NSImageView as <image id="profileImageView" editable="YES"/>, then you refer to it in an outlet or action as #profileImageView.
Split View Orientation
In AppKit, NSSplitView’s -isVertical/-setVertical: property refers to the orientation of the divider, not the axis on which the views are ordered. In other words, a split view with isVertical equal to YES has a leading view (on the left in locales that read left-to-right), and vertical dividers splitting subviews that are organized horizontally. A split view with isVertical equal to NO has a top view, and horizontal dividers splitting subviews that are organized vertically.
Split View Sizing
An NSSplitView might assign a zero size to a subview that doesn’t request an explicit size. Provide an explicit initial size, and use autoresizing masks or autolayout constraints that allow the subview to occupy the space provided by the split view.
In Renaissance, use the hexpand attribute for horizontal stretching, and the vexpand attribute for vertical stretching.
