Using Controllers

Nano applications are built around the Model View Controller design pattern, which separates an application's data model, user interface, and control logic into three distinct components.

Models are typically represented by application-specific objects, while views are implemented using HIViews.

Controller objects provide the third aspect of this pattern, and are responsible for updating the application model and views in response to user input or other events.

The two main classes of controller within Nano are NWindowController and NPanelController.

NWindowController

NWindowController is typically used as a sub-class, to provide default behaviour for application-specific objects such as documents or sheets.

A NWindowController object is associated with an NHIWindow, and is responsible for window-related tasks such as attaching sheets or updating the status of toolbar items.

The most common sub-class of NWindowController is NDocument. This object extends the default behaviour with a HIG-compliant document model, providing an extensible cross-platform file format as well as automatic save/load/revert/print support.

Application windows whose state was backed by a file would typically sub-class from NDocument, inheriting the default document behaviour and extending it with their own model and views.

Windows that are not file-based, such as sheets, can inherit directly from NWindowController.

Defining a Controller

A window controller's window is typically placed in a .nib using Interface Builder, and instantiated as a controller using two standard macros.

For example, a sheet window might be defined as:

    MySheet.h
    class MySheet : public NWindowController {
        ...
        DECLARE_WINDOW_CONTROLLER(MySheet);
        ...
    };

    MySheet.cpp
    DEFINE_WINDOW_CONTROLLER(MySheet, "MyNib", "MyWindow");

These macros will introduce two additional functions into the class:

    class MySheet : public NWindowController {
        ...
        MySheet *MySheet::Create(void);

        MySheet *MySheet::GetInstance(void);
        ...
    };

The Create function will create a new instance of the controller, basing it on the "MyWindow" window from the "MyNib" .nib file.

The GetInstance function can be used to create a singleton instance of the controller, ensuring that only a single copy of the window exists at any one time.

NPanelController

NPanelControler is typically used as a mix-in class with another controller, providing that controller with the means to set the contents of a view to one of multiple panels.

Each panel is defined by the contents of a window within a .nib file, allowing views to be laid out using Interface Builder then swapped dynamically at runtime.

Most applications will not sub-class NPanelController directly, but will sub-class from NWindowPanels, which combines an NWindowController with an NPanelController. This is used by NWindowPreferences to provide a standard toolbar-based preferences window, where each toolbar item selects a particular panel.

NWindowPanels would also be a suitable parent for an Inspector palette, where the contents of the palette are context sensitive and vary based on the current selection.