Working with Modules

Modules are the major pieces of the user interface in a PhAB application. This chapter describes how to work with them, and includes:

Modules serve as containers to hold your application's widgets. Some modules, such as windows and dialogs, are actually Photon container-class widgets and let you place widgets directly inside them. Others, such as icons and menus, have either predefined widgets or a specialized editor for creating the widgets that they contain.

Module types

PhAB provides a number of types of modules, each with a specific usage. The module type is identified by:


Caution: Module files are binary; don't edit them with a text editor or you could damage them.

Module Usage Extension
Window Major application activities .wgtw
Dialog Obtain additional information from the user .wgtd
Menu Multilevel text-only menus .wgtm
Picture Change the contents of an existing module, or create a widget database .wgtp

Anatomy of a module

PhAB displays each module as a window in its work area. Like windows, modules have a set of controls in their frames.


Anatomy of a module


Anatomy of a typical PhAB module.

Most modules include these elements:

Work menu button
Brings up the module's Work menu:

Module Work menu


The Work menu for a module.

The Work menu includes:

Title bar
Displays the module's instance name. To move a module, point to this bar and drag the pointer.
Collapse button
Minimize button
Close button
These buttons iconify the module.
Test button (some modules only)
Like the Test item in the Work menu, this lets you switch the module into test mode.


Note: When the render flags for a module's title bar are off, PhAB displays an area around the module that you can use to manipulate the module. This is useful if you are designing embedded applications, which usually have windows with no title bar and no decorations.

Selecting a module

To select a module that's in the PhAB work area:

Whichever method you choose, you'll see resize handles that indicate the module is selected.

How modules are saved

When you save your application, PhAB stores all the application's modules as files within the application's wgt directory. Each module is saved in its own file with a file extension based on the module's type. Later, when you “make” your application, PhAB binds all the modules into the binary executable. This makes the application a single free-standing program that you can distribute easily.

For more info, see How application files are organized in the Generating, Compiling, and Running Code chapter.

Changing module resources

When you select a module within PhAB, the Resources control panel changes to display the list of widget resources available for that module's class. Depending on which resources you change, you may see no immediate effect. All changes will take effect, however, when you run the application.

Because PhAB displays all modules as child windows within its work area, you can work with any number of modules at the same time.

Creating a new module

To create any new module, follow these simple steps:

  1. From the Project menu, choose a command for the module type you want to create, which is one of:
  2. For window and dialog modules, PhAB asks you to choose the style from a dialog that displays the available choices.

    For other types of modules, PhAB simply asks whether or not it should create the new module. Press Enter or click on Yes. You'll see the new module in PhAB's work area.

  3. Click on Done.

PhAB creates the module for you. You can change the default instance name on the Resources control panel.

For more info on creating specific types of modules, see the sections on each type of module in this chapter.

You can also import modules from other PhAB applications. For more information, see Importing files in the Working with Applications chapter.

Deleting a module

To delete a module:

  1. Select the module you want to delete.
  2. Press the Delete key, or select Edit-->Delete.

Note: Deleting a module doesn't delete the module's file; it just removes the name from the list. Any callbacks belonging to the module or its children are deleted.

Iconifying modules

PhAB's work area lets you work on several application modules at once. You can iconify modules to organize your work area. To reduce any module in the work area to an icon:

Once it's iconified, the module positions itself at the bottom of the work area. You can drag it anywhere in the work area, so (for example) you can group commonly used or related icons.

Displaying modules at run time

Your application needs a way to make modules appear when you run it. You can:

Positioning a module

You can specify where a module will display when you create a link callback from a widget to that module. To do this, you use the location dialog.

To open the Location dialog and select a module's location:

  1. When creating or editing a link callback to a module, click on the Location field or on the icon to the right of the field. You'll see a list of locations:

    Location dialog


    Location dialog.

    For windows and dialogs, the default location is Default (0,0), which places the window at the next available position defined by the Window Manager. The default location for a menu module is Below Widget.

  2. Click on the location you want.
  3. You can also specify x and y offsets. For example, if you set the location to the bottom-right corner and set the x offset to -100, the window will be displayed so that its bottom-right corner is 100 pixels to the left of the bottom-right corner of the screen.

    Note: If you choose Default as the location, the offsets are ignored.

  4. Click on Done.

Finding lost modules and icons

To find a lost module or icon:

Window modules

Widget class File extension Widget creation
PtWindow .wgtw Directly from the widget palette

Typically, you use window modules for your application's major activities. Since most applications use a window module for their main window, PhAB automatically generates a window module named base when you first create any application. It also presets the application's startup information to make the base window open when the application starts up. (See Specifying your project properties in the Working with Applications chapter.)


Window module icon


The icon for a Window module.

Window modules can support multiple instances. That is, two or more copies of the same window module can be displayed at the same time. As a result, you should keep track of each window's instance pointer, which is generated when you create the window. That way, you'll always know which window you're dealing with when you process callbacks. For more information, see Handling multiple instances of a window in the Working with Code chapter.

Even though your application's base window is a window module, you usually display it only once, at startup. So unless your application needs to display more than one copy of the base window at the same time, you don't have to keep track of the base window's instance pointer.

For an example of code for handling multiple instances of window modules, see Creating Windows in the Tutorials chapter.

Resizing a window module

When you set a window module's size in PhAB, that's the size it will be when you run the application.

Dialog modules

Widget class File extension Widget creation
PtWindow .wgtd Directly from the widget palette

Dialog modules let you obtain additional information from the user. Typically, you use this information to carry out a particular command or task.


Window module icon


The icon for a Dialog module.

Most dialog modules include the following buttons:

From PhAB's perspective, dialog modules are almost identical to window modules, with one important difference—a dialog module can have only one active instance. So if you invoke a dialog that's already open, the PhAB API simply brings the existing instance of the dialog to the front of the screen. This behavior fits with the nature of a dialog—you rarely want to get the same information twice. If for any reason you need a dialog that can support multiple instances, use a window module.

Limiting a dialog to a single instance makes callback handling simpler since you can use the widget manifests that PhAB generates to access the widgets within the dialog. For more info, see the discussion on instance names in the Creating Widgets in PhAB chapter.

Resizing a dialog module

When you set a dialog module's size in PhAB, that's the size it will be when you run the application.

Predefined dialogs

The Photon libraries include convenience functions that define various handy dialogs:

ApError()
Display an error message dialog
PtAlert()
Display a message and request a response
PtFileSelection()
Create a file-selection dialog
PtFontSelection()
Create a font-selection dialog
PtMessageBox()
Pop up a message box
PtNotice()
Display a message and wait for acknowledgment
PtPassword()
Prompt for a password
PtPrintPropSelect()
Change the printing options for a selected printer via a modal dialog
PtPrintSelect()
Display a custom modal dialog for selecting print options
PtPrintSelection()
Display a modal dialog for selecting print options
PtPrompt()
Display a message and get textual input from the user

Menu modules

Widget class File extension Widget creation
PtMenu .wgtm Special editor

A menu module provides a multilevel text-only menu. Unlike most other modules, a menu module doesn't let you create widgets directly inside it. Instead, you use PhAB's menu editor to create the menu's items.


Window module icon


The icon for a Menu module.

Opening the menu editor

To open the menu editor:

  1. Select a menu module.
  2. Click on Menu Items in the Resources control panel. PhAB displays the menu editor:

    Menu editor


    PhAB's Menu editor.

    In the upper-right corner you'll see buttons that represent the types of menu items you can create:

These buttons are at the bottom of the dialog:

When you want to: Use this button:
Apply any changes and close the editor Done
Apply any changes and continue editing the menu Apply
Cancel any changes made since you opened the editor Cancel

Specifying instance names

To create any command or toggle menu item (that is, any item that can invoke a callback), you must enter a unique instance name—PhAB enforces this. The instance name lets you access the menu item from within your application code.

When PhAB generates the code for your application, it generates an ABN_... constant for each menu item that requires it. You use this constant with the menu-item related API functions, ApModifyItemAccel(), ApModifyItemState(), and ApModifyItemText().

For example, let's say a menu item isn't available when the user clicks on the widget that brings up the menu. Using the instance name, you can dim that item before displaying the menu. For more information, see Initializing menus in the Working with Code chapter.

Creating hotkeys and shortcuts

To help the user select a menu item more quickly, you can:

A keyboard shortcut works only when the menu is currently visible. A hotkey, on the other hand, should work whether the menu is visible or not.

Creating a keyboard shortcut is easy. When you're entering the Item Text, simply place & in front of the character that will act as the shortcut. For example, let's say you're creating a “Save As” item. You could enter Save &As, which will underline the “A.” When the menu opens, the user can press either A or a to invoke the callback associated with “Save As”.

Creating a hotkey takes a bit more work, but it's still easy to do. First, you want to make sure that the hotkey accelerator appears next to the menu item when the menu is displayed. To do this, use the Accel Text field. For example, let's say the hotkey accelerator for a “Save” menu item will be Ctrl-S. In that case, you would type S in the Accel Text field and check the Ctrl toggle button.

Next, you need to create a hotkey callback for Ctrl-S. Since the menu might not be created when the user presses Ctrl-S, you can't attach the hotkey callback to the menu or to the menu item. Rather, you must attach the callback to the application's main module, which is usually the base window module. When you specify the hotkey callback's function, use the same function you defined for the menu item's callback.

If for some reason you need to differentiate between the two methods of invoking the callback, look at the callback's reason code. Hotkeys always have a reason code of Pt_CB_HOTKEY.

For more info on creating hotkey callbacks, see Hotkey callbacks in the Editing Resources and Callbacks in PhAB chapter.

Resizing a menu module

Feel free to resize a menu module to make it more readable or take up less space. When you run the application, the actual size of the PtMenu widget will be determined by the menu items.

Creating command items

A command item lets you invoke application code or display a module.

Field Description
Item Text The text that will be displayed
Accel Text The hotkey to invoke the command
Inst Name The name used within the application code
Callback The function that will be called when the item is selected
Image The icon to use for the menu item

To create a command item:

  1. Click on <NEW>.
  2. Click on the Command button in the upper-right corner.
  3. In the Item Text field, enter the item's text. To create a shortcut key, place & in front of the character that will act as the shortcut.

    For example, let's say you enter &File. In that case, the user can select the item by pressing F.

  4. In the Inst Name field, enter the instance name you'll use.
  5. If you plan to have a hotkey callback for this item, enter the hotkey string and modifier key (for example, Ctrl-S) in the Accel Text field. The hotkey is displayed in the menu as a reminder to the user.
  6. Add a PhAB callback by clicking on the Callback icon:

    Callback icon

    For more info on creating a callback, see Editing callbacks in the Editing Resources and Callbacks in PhAB chapter.

  7. Add an image, if appropriate.
  8. Click on Apply to add the item to the menu.

Creating submenu items

A submenu item lets you create another menu level.

Field Description
Item Text The text that will be displayed
Inst Name The name used within the application code

To create a submenu item:

  1. Click on <NEW>.
  2. Click on the Submenu button in the upper-right corner.
  3. In the Item Text field, type the name of the submenu. To create a keyboard shortcut, place & in front of the character that will act as the shortcut (just like command items, above).
  4. Click on Apply.
  5. The Menu Items list displays the submenu:

    Submenu

  6. You can now add items to the submenu by selecting <NEW> in the submenu.

Creating separator items

A separator item lets you add a line between menu items. You'll find this item type handy for creating logical groupings of menu items.

To create a menu separator:

  1. Click on <NEW>.
  2. Click on the Separator button in the upper-right corner.
  3. Click on Apply.

Creating toggle items

A toggle item lets you change or display an application state, which can be either on or off.

Field Description
Item Text The text that will be displayed
Accel Text The hotkey to invoke the command
Inst Name The name used within the application code
Callback The function that will be called when the item is selected
Image The icon to use for the menu item

To create a toggle item:

  1. Click on <NEW>, then click on the Toggle button.
  2. Follow the same procedure used to create command items.

Creating function items

A function item lets you specify an application function that dynamically adds menu items to the menu at runtime. For example, you could use a function item in a File menu to display the last three files the user worked on.

The PhAB library invokes the specified function as the menu is built. The dynamically created menu items appear where you've positioned the function item in the menu.

Field Description
Function The function that will be called

To create a function item:

  1. Click on <NEW>, then click on the Function button.
  2. In the Function field, enter the name of the application function that will dynamically add menu items to the menu.

    If you specify this function name, PhAB will generate a stub function; for information on specifying the language (C or C++) and the filename, see Function names and filenames in the Working with Code chapter.

  3. You can edit the function right away by clicking on the button to the right of the function name.
  4. Click on Apply.

For information on the application function, see Generating menu items in the Working with Code chapter.

Moving menu items

The Menu Items scrolling list lets you move a menu item to a new position in the menu.

Let's say you want to move an item named Browse so it appears just before an item named Edit. You would:

  1. Drag the Browse item until its outline is directly over Edit.
  2. Release the mouse button. The Browse item appears in its new position.

Using a menu module

Once you've created a menu module, you need a way to make your application display it. Typically, you do the following:

  1. Create a PtMenuBar at the top of a window.
  2. Add a PtMenuButton to the menu bar, giving it an appropriate instance name and text string.
  3. Add a module-link callback to the menu button's Pt_CB_ARM callback list.

    Note: You could add the callback to the Pt_CB_ACTIVATE list, but adding it to Pt_CB_ARM allows the user to access it in two ways:
    • by pressing the left mouse button on the menu button widget, dragging to highlight a menu item, and releasing to select it. This is known as the press-drag-release (PDR) method.
    • by clicking on the menu, and then clicking on a menu item

    If you use an Activate callback, the user can only use the second method.


  4. Have the callback display the menu module. See Module callbacks in the Editing Resources and Callbacks in PhAB chapter.
  5. If you need to initialize the menu whenever it's displayed, specify a setup function for it. See Initializing menus in the Working with Code chapter.

If you want your menu to appear when you press the right mouse button while pointing at a widget, you'll need to use an internal link. For more information, see the Accessing PhAB Modules from Code chapter — there's even an example.

Picture modules

Widget class File extension Widget creation
Not applicable .wgtp Directly from the widget palette

Using a picture module, you can change the contents of an existing module or create a convenient database of widgets. You always display a picture inside a container-class widget or another module, such as a window or dialog.


Picture module icon


The icon for a Picture module.

Like windows, picture modules support multiple instances. So you should keep track of the instance pointer of the container that each picture is placed into. That way, you'll always know which picture you're dealing with when you process callbacks.

If you're sure that your application will use only one instance of the picture at any given point, you don't have to keep track of instance pointers. Instead, you can use PhAB-generated manifests to access the picture's widgets.

Displaying a picture

You always access picture modules from within your application code. To access a picture, you must create an internal link to it. This tells PhAB to generate a manifest that you can use with PhAB's API functions, such as ApCreateModule(), to access the picture.

For more information, see the Accessing PhAB Modules from Code chapter.

Using pictures as widget databases

You can use a picture module as a widget database. A widget database contains predefined widgets that you can copy at any time into a window, dialog, or container.

When using a widget database, you don't have worry about handling multiple instances since the generated PhAB widget manifests don't apply to widget databases: each widget you create is a new instance. The instance pointer is returned to you when you create the widget using ApCreateWidget(). You'll need to keep track of this pointer manually if you need to access the widget in the future.

For more info, see Widget databases in the Accessing PhAB Modules from Code chapter.

Resizing a picture module

It doesn't matter how large or small you make a picture module. That's because it has no associated widget class. Only the widgets inside the module are used.