[Previous] [Contents] [Index] [Next]

Tutorials

The best way to get to know PhAB is to use it. This chapter provides hands-on sessions to give you a jump start on creating applications:

We'll take a closer look at using PhAB in the chapters that follow.

The first two tutorials cover the basics: creating widgets, changing how widgets look and behave, generating code, running your application, and so on.

The remaining tutorials go beyond the basics to show you how to create working menus, dialogs, and windows. When you've completed these tutorials, you'll be ready to start building almost any Photon application.

Before you start...

Launch PhAB from the Desktop Manager by clicking on its icon:

PhAB icon

Before you start the tutorials, take a moment to make yourself familiar with PhAB's user interface:


phab at a glance


Overview of PhAB's user interface.


Widget bar
Makes it easy to add widgets to your application. Just click on the widget you want, then click where you want it.

If you wish to identify any icon in the widget bar by name, just pause the mouse pointer on that icon.

Menubar
Import graphics, create windows and dialogs, generate C and/or C++ code to implement your entire user interface, and more.
Speedbar
Save time with the speedbar-with a couple of mouse clicks you can duplicate, move, align, group or resize any number of widgets.
Work area
Provides a flexible area where you can work on several application modules all at once.
Control Panel
Lets you fully customize your application's widgets. You can choose text fonts, modify colors, customize bitmaps, and attach callbacks that will pop up dialogs or invoke C and/or C++ code you've supplied.

If you close the Control Panel, you can redisplay it by selecting Control Panel from the View menu.

Tutorial 1 - Hello World

In this tutorial you learn how to use PhAB to create and compile a simple application.

Creating the application

  1. From the File menu, choose New to create a new application. You'll see the new application's default base window and PhAB's Control Panel.
  2. Go to the widget bar and click on the PtLabel widget icon:

    PtLabel icon

  3. Move the pointer into the application's base window (the pointer changes to a crosshair) and click anywhere near the center of the window.

    PhAB automatically does the following:

  4. Go to the Control Panel and click on the "Label Text" resource. You'll see PhAB's multiline text editor, which displays the current value ("Label") for this resource.
  5. Change the text to Hello World, then click on Done.

    The widget now displays "Hello World":

    Hello World widget

  6. You're almost ready to generate code! But first, you must save the application and give it a name.

    From the File menu, choose Save As to open the Application Selector dialog. Click on the Application Name field, type tut1, then press Enter or click on Save Application.

  7. Look at PhAB's titlebar. It now indicates that the current application is named tut1.

Generating code

Now that you've saved your application, you're ready to generate, compile, and execute it.

  1. From the Application menu, choose Build & Run. You'll see the Build & Run dialog.
  2. Click on the Generate button to start the code generation process. You'll see a progress dialog:

    Generate Progress dialog

    Wait for the generation process to complete, then click on Done to close the dialog.

  3. Click on Make to compile the code. You'll see the Make Application dialog, which displays the files as they're compiled.
  4. Once the application has been compiled and linked, PhAB will enable the dialog's Done button. Click on Done to close the dialog.
  5. Click on Run Application to run your new application. The application will appear in its own window, with the text "Hello World" in the center and the default title "My application" in the title bar:

    Hello World application

    Congratulations! You've just created your first Photon application using PhAB.

  6. To quit the application, click on the window menu button in its top-left corner, then choose the Close item.
  7. Click on Done to close the Build & Run dialog.

Want more info?

For more info on compiling, running, and debugging an application, see the section "Making and running your application" in the Generating, Compiling, & Running Code chapter.

Tutorial 2 - Editing Resources

This tutorial introduces you to PhAB's resource editors, which let you change how widgets look and behave. You'll find out how to edit virtually any kind of resource a widget may have, including:


Note: In this tutorial, you'll be asked to select various resources in the Control Panel. If you don't see a resource, resize the Control Panel and/or use its scrollbar.

Adding a button widget

  1. From the File menu, choose New to create a new application.
  2. Click on PtButton in the widget bar:

    PtButton

  3. Click near the center of the application's window. You'll see a button widget.
  4. Drag any of the button's resize handles until the button matches the following picture:

    button in window

Changing the border width

Let's now edit a numerical resource-the button's border width.

  1. Click on the "Border Width" resource in the Control Panel. You'll see the number editor:

    Number editor

    This editor lets you change the value of any numerical widget resource.

  2. Change the value from 2 to 6. To do this, you can:
  3. To apply the new value and close the editor, press Enter or click on Done.

Changing the font

Let's change the font of the button's text:

  1. Click on the "Font" resource. You'll see the font editor, which displays the button's current font:

    Font editor

    This editor lets you change the text font of any widget that has text.

  2. Click on the font-name box or the point-size box, select a typeface or size from the displayed list, and click on Apply.

    The button now displays the new font.

  3. Click on Default. The editor displays the widget's default font, but doesn't apply the font to the widget.
  4. If you want to keep the new font that you selected, click on Cancel to ignore the default. If you want to apply the default, click on Done. Either way, the editor closes.

Changing the text alignment

Now let's change the button's horizontal text alignment:

  1. Scroll through the Control Panel to find the "Horz Alignment" resource, then click on it. You'll see the flag/option editor, which displays the widget's current text alignment:

    Flag/option editor

    This editor serves a dual purpose in PhAB:

  2. Click on Pt_LEFT or Pt_RIGHT, then click on Apply. You'll see the button text move to the left or right edge of the button.
  3. Click on Done.

Setting flags

Let's now use the flag/option editor to set one of the widget's flags:

  1. Scroll through the Control Panel to find the "Flags" resource, then click on it. The flag/option editor reopens, but this time it shows the widget's current flag settings:

    Flag/option editor

    A flags resource isn't exclusive, so this time you can use the editor to select multiple options, if desired.

  2. Select the Pt_ETCH_HIGHLIGHT flag, then click on Done. PhAB draws the button with an etched border:

    Button with etched border

Changing the fill color

Let's change a color resource-the button's fill color.

  1. Click on the button's "Color: Fill" resource. You'll see the color editor, which displays the current fill color:

    Color editor

    This editor lets you edit any color resource. It provides several preset base colors, which should work well with all graphic drivers, and 48 customizable colors for drivers that support 256 or more colors.

  2. Click on any color in the Base Colors set, then click on Apply. The button is filled with the color you selected.
  3. Select a color from the Custom Colors set. The sliders will display the color's Red/Green/Blue (RGB) values. Change these values till you get a color you want, then apply your changes.

    If you'd like to experiment with the Hue/Saturation/Brightness (HSB) color model, click on the HSB Model button.

  4. Click on Done when you've finished experimenting with the editor.

Editing a pixmap

Let's now use the pixmap editor to edit a PtBitmap widget. This editor is called "pixmap" instead of "bitmap" since it lets you edit many types of image resources besides bitmaps.

A PtBitmap widget can be used as a button, or as a static graphic- which is what we'll create here.

  1. Click on PtBitmap in the widget bar:

    PtBitmap icon


    Note: If you don't see this widget, add it to the widget bar. To do this, choose the Customize Widget Bar item from the Options menu. You'll see a dialog that lets you add the widget. For more info, see "Widget bar" section in the PhAB Environment chapter.

  2. Move the pointer into the main window and click below the button widget you created. You'll see a PtBitmap widget.
  3. Click on the Border Width resource in the Control Panel, and set the border width to 0. Click on Done. Removing the border makes the widget look like a graphic instead of a button.
  4. Click on the "Bitmap" resource in the Control Panel to bring up the pixmap editor.
  5. Next, bring up the color editor to select a draw color. Just click on the following button:

    Color Fill button

  6. Select a color. You'll see that the draw color in the pixmap editor changes immediately. You'll also see that the color editor's Apply, Default, and Cancel buttons are dimmed-they aren't required for the pixmap editor.
  7. To draw a simple bitmap, you can:

    Feel free to try the other drawing tools.

  8. When you're done, click on the pixmap editor's Done button to apply your changes and close the editor.

Editing multiline text

Next, we'll edit a multiline text resource-the text of a PtMultiText widget.

  1. Click on PtMultiText in the widget bar:

    PtMultiText icon

  2. Move the pointer below the bitmap widget you've just created, and drag until the new PtMultiText widget appears big enough to hold a few lines of text.
  3. Click on the "Text String" resource in the Control Panel to bring up the multiline text editor:

    Multiline text editor

  4. Type a few lines of text. To create a new line, press Enter. For example:

    Mary hadEnter
    aEnter
    little lamb.Enter

  5. Click on Done. Your text should appear exactly as you typed it. If it doesn't, try resizing the widget-the widget might not be wide enough or tall enough.
  6. For a different effect, select the "Horz Alignment" resource and change the text alignment to Pt_CENTER. As you can see, each line is now centered individually.
  7. If you haven't already, resize the widget by dragging on one of its resize handles. You'll see the text update automatically to adjust to the new size. For example:

    Multiline text example

Editing a list of text items

Let's now create a PtList widget and add text to the widget using the list editor. This editor lets you add and edit text for any widget that provides a list of text items.

  1. Click on PtList in the widget bar:

    PtList icon


    Note: If you don't see this widget, add it to the widget bar. To do this, choose the Customize Widget Bar item from the Options menu. You'll see a dialog that lets you add the widget. For more info, see "Widget bar" section in the PhAB Environment chapter.

  2. Move the pointer into the application's base window, and drag the pointer until the new PtList widget appears big enough to hold a few lines of text.
  3. Click on the "List of Items" resource to bring up the list editor:

    List editor

  4. Click on the text box at the bottom of the editor. You'll see the text-input cursor.
  5. Type some text, then click on Insert After to place the first item in the list.
  6. Now let's create the second item. Click in the text box, and type Ctrl -U to erase the text in the text box, then type some new text.

    Click on Insert After to place this new item after the previous item.

  7. Repeat the above step as often as you'd like.
  8. Click on Apply. The PtList widget should now display the list you've created.
  9. Now try editing the list:
  10. When you're finished experimenting, click on Done to apply your changes and close the editor.

If you wish to save this application, follow the steps from the first tutorial to save the application as tut2. After saving, feel free to generate, make, and run the application.

Want more info?

You now know the basics of editing any widget resource in PhAB. For more information, see the following sections in the Editing Resources and Callbacks in PhAB chapter:

To edit: See this section:
Bitmaps or images Pixmap editor
Colors Color editor
Flags Flag/option editor
Fonts Font editor
Lists of text items List editor
Numbers Number editor or Flag/option editor
Single-line text strings Text editor
Multiline text strings Multiline text editor

Tutorial 3 - Creating Menus and Menubars

About link callbacks

In this tutorial you'll learn how to set up a link callback, one of the key components of PhAB. To understand what a link callback is, let's start with some background info on widget callbacks.

Almost all widgets support a variety of callbacks. These callbacks enable your application's interface to interact with your application code. For example, let's say you want your application to perform an action when the user clicks on a button. In that case, you would attach a callback function to the button's "Activate" callback.

In a typical windowing environment, you can attach only code functions to widget callbacks. But whenever you use PhAB to create a callback, you can go one step further and attach entire windows, dialogs, menus, and much more. It's this extended functionality that we call a link callback.

PhAB provides two basic types of link callbacks:

About instance names

To access a widget from your application code, you must first give the widget an instance name. Since all widget instance names reside in the same global namespace, no two widgets within an application can have the same instance name.

We recommend that you start every instance name with a module prefix. For example, if your base window has a PtButton widget that contains the label text "Blue," you could give this widget an instance name of base_blue.

Creating a menubar

To learn about using link callbacks, let's create two functioning menus-File and Help-that you can later incorporate into your own applications.

In PhAB, menus are built in two pieces:

Using link callbacks, you'll link the menu modules to the File and Help buttons in a menubar. You'll also link a code-type callback to the Quit menu item in the File menu module. This callback will enable the Quit item to close the application.

  1. From PhAB's File menu, choose New to start a new application.
  2. Select the PtMenuBar widget from the widget bar, then click anywhere in the main window. The menubar is automatically positioned at the top of the window, and is as wide as the window.

    The menubar grows and shrinks as you change the width of the window, and it always stays at the top of the window. You can see this by clicking in the titlebar of the window, then resizing the window by dragging on one of its resize handles.


    Note: If you accidentally click on the Test tab, the window won't resize or accept new widgets. If this happens, just click on the Wind tab.

    By the time you're finished the following steps, the menubar will look like this:

    Finished menubar

  3. Place a PtMenuButton widget in the menubar you just created. The menu button is automatically centered vertically in the menubar.
  4. Go to the Control Panel and click on the text box labeled "Widget Instance Name." Change the button's instance name to base_file, and press Enter:

    Instance name

  5. Change the button's Label Text resource to File.
  6. Place another PtMenuButton widget next to the first. Change its instance name to base_help and its text to Help.

Creating the File menu module

Now that you have menu buttons, you need to create your menu modules. Let's start with the File menu.

  1. From the Application menu, choose Menus to open the module selector. This selector lets you create or view any type of PhAB module.
  2. In the Name text box, type filemenu, then press Enter. Since this menu module doesn't exist yet, PhAB asks you if it should create the module. Click on Yes.

    You'll see the menu module appear in your work area and the module's name in the module selector's scrolling list.

  3. The module selector stays onscreen, allowing you to create more modules. However, you need to create only one menu right now, so click on Done to close the selector.

Adding menu items

Let's now add the following menu items to the File menu:

File menu items


Note: If you click on another module, the menu module will become deselected, which means you won't be able to work on it. To reselect the menu module, click on its titlebar.

  1. Click on the Menu Items resource in the Control Panel. You'll see the menu editor:

    Menu Items editor

    If you look at the Menu Items list, you'll see that the <NEW> item is selected. This special item lets you add new menu items to the menu.

  2. To add your first menu item-which also happens to be called "New"-click on the Item Text field, then type New.
  3. Now give the item an instance name. In the Inst Name field, type file_new.
  4. Click on Apply to add the item to the menu. You'll see the item's name in Menu Items list, prefixed by C:. The C: means this is a Command item; that is, an item that invokes a PhAB callback.
  5. Repeat the above steps to create the two menu items labeled "Save" and "Save As." Give these items the instance names file_save and file_as.
  6. Up to now, you've added Command-type menu items. You'll now add a Separator item. Just click on the Separator button near the upper-right corner. You'll see a list of separator styles:

    Menu separators

  7. Choose a style or just click on Apply to get the default separator style, which is Etched - In.
  8. Now let's add the Quit item. Click on the Command button, then specify Quit as the item text and file_quit as the instance name.
  9. You're finished with this menu module for now, so click on Done. The module displays the items you just created:

    Menu module

  10. You'll want to keep this module neatly out of the way while you work on your next task. So click on the module's Work menu button (upper-left corner) and choose Minimize.

Creating the Help menu module

Using what you just learned about creating a menu module, do the following:

  1. Create your Help menu module and give it a name of helpmenu.
  2. In this module, place a single command item called About Demo and give the item an instance name of help_about. When you're finished, minimize the module.
  3. Save the application as tut3. (For info on saving, see the previous tutorials or "Saving an application" in the Working with Applications chapter.)

Note: If one of your menu modules seems to "disappear" (you may have accidentally closed it or placed it behind another module), it's easy to bring the module back into view. See the " Finding lost modules and icons" in the Working with Modules chapter.

Attaching link callbacks

Let's return to the menu buttons you created earlier and attach link callbacks so that the buttons can pop up your menu modules.

Attaching a module-type link callback

  1. Select the File menu button, then click on the Control Panel's Callbacks button (at the bottom of the panel). You'll see the File button's callback list:

    Callback list

  2. To have the File menu module pop up when you press the File button, you need to attach an Arm callback to the button. By attaching an Arm callback, you can open the menu using either click-move-click or press-drag-release.

    Click on Arm to bring up the callback editor.

  3. The Module Types area of the editor let you choose the type of module you wish to link to. Because you want to link the File button to a menu module, click on Menu.
  4. Click on the Name field and type filemenu, which is the name you gave your File menu module. This links the menu button to that module.

    You can also select filemenu from a popup list of available modules. To bring up the list, click on the icon to the right of the Name field.

  5. Click on Apply to add the link callback, then click on Done to close the callback editor.
  6. Repeat the above steps to link the Help menu button to the Help menu module.

Attaching a code-type link callback

Let's now attach a code-type link callback to the File menu's Quit item so that it can terminate the application.

  1. Double-click on the iconified filemenu module. This opens and selects the module.
  2. Switch the Control Panel to Resources mode, then click on the Menu Items resource.
  3. Select the Quit item in the Menu Items list.
  4. Click on the icon next to the Callback field to open the callback editor:

    Callback icon

  5. When the editor opens, the default callback type is Code. Since this is the type you want, all you have to do is specify the name of the function you want to call.

    The function should have a meaningful name. So type quit in the Function field.

  6. Click on Apply to update the Callbacks list, then click on Done to close the editor.
  7. Click on Done again to close the menu editor.

Setting up the code

You'll now generate the code for your application and edit a generated code stub so that the Quit item will cause your application to exit.

  1. If you haven't done so yet, save the application as tut3.
  2. From the Application menu, choose Build & Run and generate the application code.
  3. After the generation process is complete, the Build & Run dialog displays a list of generated files.

    Scroll through the list until you see the quit.c file. This is the generic code template that PhAB generated for your quit() function.

  4. You need to make the function exit the program. To do this, select quit.c from the file list, click on the Edit button, then change the quit() function to the following:
    int
    quit( PtWidget_t *widget, ApInfo_t *apinfo, 
          PtCallbackInfo_t *cbinfo ) 
    
         {
    
         /* eliminate 'unreferenced' warnings */
         widget = widget, 
         apinfo = apinfo, 
         cbinfo = cbinfo;
    
         exit( EXIT_SUCCESS );
    
         /* This statement won't be reached, but it
            will keep the compiler happy. */
    
         return( Pt_CONTINUE );
         }
  5. After you've edited the code, saved your changes, and closed the editor, click on Make to compile the code.
  6. Click on Run Application to run the application.
  7. Once your application is running, try clicking on the File button to bring up the File menu. Then choose Quit. Your application will immediately terminate and close.

Want more info?

For more info on: See the section: In the chapter:
Widget callbacks Callbacks Editing Resources and Callbacks in PhAB
Editing callbacks Editing Resources and Callbacks in PhAB
Instance names Instance names Creating Widgets in PhAB
Menu modules Menu modules Working with Modules

Tutorial 4 - Creating Dialogs


Note: This tutorial uses the application you created in Tutorial 3.

What you'll learn

This tutorial provides a good example of how you can use setup code to modify a widget's resources before the widget appears onscreen.

In this tutorial, you will:

About dialogs

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

Since you don't usually need to get the same information twice, dialogs are single-instance modules. That is, you can't realize the same dialog more than once at the same time. If you try create a second instance of a dialog, PhAB simply brings the existing dialog to the front and gives it focus.

If you need to create a window that supports multiple instances, use a window module. You'll learn about window modules in the next tutorial.

More on instance names

To make it easier for you to access widgets from within your application code, PhAB generates a global variable and a manifest. Both of these are based on the widget's instance name.

The global variable, which has the prefix "ABN," represents the widget's name. The manifest, which has the prefix "ABW," represents the widget's instance pointer.


Note: The value of a widget's ABN_... variable is unique only in the module that contains the widget. The variables for widgets in other modules might have the same value.

For example, let's say you have a widget named about_version. PhAB will use this name to generate a global variable named ABN_about_version and a manifest named ABW_about_version.

In this tutorial you'll learn how to use these generated names.

Attaching a dialog module

  1. Open the tut3 application you created and use the File menu's Save As item to save the application as tut4.
  2. Open the Help menu module you created (it may still be iconified).
  3. Click on the Menu Items resource in the Control Panel to open the menu editor.
  4. Select the "About Demo" item, then click on the icon next to the Callback field to open the callback editor:

    Callback icon

  5. When the editor opens, the default callback type is Code. Go to the Module Types group and change the callback type to Dialog.
  6. In the Name field, type aboutdlg as the name of the dialog module you want to link to. (This dialog doesn't exist yet, but PhAB will ask you later to create it.)
  7. In the Setup Function field, type aboutdlg_setup. This is the name we're giving to the setup function that will be called before the dialog is realized.

    Using this function, we'll change the content of a label widget within the dialog to display a version number.

  8. Since you want the aboutdlg_setup function to be called before the dialog is realized, make sure the Prerealize button is enabled.
  9. Click on the Location icon to specify where you want the dialog to appear when it gets realized. (The "Center Screen" location is a good choice.) Click on Done.

    Your callback information should now look like this:

    Callback information

  10. Click on Apply to add the link callback. Since the dialog module you want to link to doesn't exist yet, PhAB asks you whether it should create the module. Click on Yes.

    You'll see the new dialog in the work area. You'll also see the new callback in the Callbacks list in the callback editor.

  11. Click on Done to close the callback editor, then click on Done again to close the menu editor.

Adding widgets to the dialog

  1. Place two PtLabel widgets in the top half of the dialog, and a PtButton near the bottom:

    Dialog with widgets

  2. Select the top PtLabel widget and change its label text resource to About this Demo. Then change its horizontal alignment to Pt_CENTER.
  3. Select the other PtLabel widget and change its label text to a blank string. Then change its horizontal alignment to Pt_CENTER.

    Later, you'll fill in the aboutdlg_setup() function so that it changes the blank text of this label to display a version number.

  4. You must give this blank PtLabel widget an instance name since you'll be referring to it in code. So change its instance name to about_version, then press Enter.
  5. Select the PtButton widget and change its button text resource to Done. Then change its instance name to about_done and press Enter.
  6. Let's center the widgets horizontally in the dialog. Select both PtLabel widgets and the PtButton widget, and click on the speedbar's Alignment icon:

    Alignment icon

    You'll see the Align Widgets dialog.

  7. In the Horizontally column, click on Center and on Align to Container. Then click on Align Widgets.

    You'll see that the two labels and the button are now centered horizontally within your dialog.

    Your aboutdlg module should now look like this:

    aboutdlg module

Adding a callback to the Done button

Now let's add a callback to the Done button so that the dialog closes when the user clicks on the button.

  1. Select the Done button, then switch the Control Panel to Callbacks mode.
  2. Click on Activate to add an activate callback. You'll see the callback editor.
  3. Select the Done code type, then click on Apply. Don't enter anything in the Function field.

    Selecting the Done code type tells the widget to perform a "Done" operation when the widget is activated. That is, the widget will call the function specified in the Function field (if one is specified) and then close the dialog module.

  4. Close the editor. The callback list now indicates that you've added an Activate callback called Done:

    Activate callback

Modifying a generated code function

You'll now modify the generated aboutdlg_setup() function so that it changes the text of the about_version label to show a version number.

  1. Save your application.
  2. Open the Build & Run dialog and generate the code.
  3. When code generation is complete, select aboutdlg_setup.c from the file list and click on the Edit button (or double-click on the filename).

    Change the code from:

    int
    aboutdlg_setup( PtWidget_t *link_instance, 
                    ApInfo_t *apinfo, 
                    PtCallbackInfo_t *cbinfo )
    
        {
    
        /* eliminate 'unreferenced' warnings */
        link_instance = link_instance, 
                        apinfo = apinfo, 
                        cbinfo = cbinfo;
    
        return( Pt_CONTINUE );
    
        }

    to the following:

    int
    aboutdlg_setup( PtWidget_t *link_instance, 
                    ApInfo_t *apinfo, 
                    PtCallbackInfo_t *cbinfo )
    
        {
        PtArg_t      args[1];
    
        /* eliminate 'unreferenced' warnings */
        link_instance = link_instance, apinfo = apinfo, 
                        cbinfo = cbinfo;
    
        PtSetArg(&args[0], Pt_ARG_TEXT_STRING, "1.00", 0);
        PtSetResources(ABW_about_version, 1, args);
    
        return( Pt_CONTINUE );
    
        }

    The code is placing the version number (1.00) into the text string resource for the about_version widget. To do this, the code:

  4. Save your changes and exit the text editor.

Compiling and Running

You're now ready to compile and run the program:

  1. Click on the Make button. If your program compiles and links without errors (which it should if you edited the function correctly), click on Run Application button to start the application.
  2. From the running application, open the Help menu and choose About Demo. The dialog will open, and you'll see the version number (1.00) under the label "About this Demo." Note that the dialog appears in the location you specified.
  3. Now try to bring up a second instance of the dialog. As you see, it won't work. PhAB always ensures that there is only one instance of a Dialog widget.
  4. Click on Done to close the dialog, then quit the application by choosing the Quit item from its File menu. Finally, close the Build & Run dialog.

Want more info?

For more info on: See the section: In the chapter:
Using dialogs Dialog modules Working with Modules
Instance names Instance names Creating Widgets in PhAB
Variables and manifests Working with Code
Callbacks Callbacks Editing Resources and Callbacks in PhAB
Code-callback functions Working with Code
Generating code Making and running your application Generating, Compiling, & Running Code

Tutorial 5 - Creating Windows


Note: This tutorial uses the application you created in Tutorial 4.

What you'll learn

In the previous tutorial, you learned how to handle dialog modules, which support just one instance. In this tutorial you'll learn how to handle window modules, which support multiple instances.

By supporting multiple instances, window modules provide more flexibility than dialogs. But to take advantage of this flexibility, you must keep track of each window's instance pointer. Doing so ensures that you correctly reference the widgets within each instance of a window. You can't safely use the generated global ABW_xxx manifest since it refers only to the last instance created.

To simplify the task of working with multiple instances, PhAB provides API library functions that let you access any widget by means of its global variable name (ABN_xxx).

Creating a window

To start, let's create a window module and attach it to the New menu item in the File menu in tut4. This window will contain buttons that change the color of another widget.

In the previous tutorial, you created a dialog module from within the callback editor. But this time you'll use the module selector to create the module you want. In the future, use whatever method you prefer.

  1. Open the tut4 application if you removed it from the PhAB workspace.
  2. Save the application as tut5.
  3. Iconify the aboutdlg dialog module.
  4. From the Application menu, choose the Windows item to open the module selector.
  5. In the Name field, type newwin for the window's instance name, then press Enter or click on Open.

    When PhAB prompts you to create the window, click on Yes.

  6. Close the module selector. The window module should now be the currently selected item.

Attaching callbacks

Because a window module supports multiple instances, you have to create code functions that will be called whenever the window opens or closes (i.e. whenever the window is created or destroyed). So let's first set up a callback to detect when the window closes:

  1. Make sure the Control Panel is in Callbacks mode.
  2. From the list of callbacks, choose Window Manager. You want to use the Window Manager callback since it's invoked when the Photon Window Manager closes the window.
  3. In the Function field, type newwin_close. You don't have to choose a callback type since the default, Code, is the one you want.

    Click on Apply, then on Done.

  4. Switch the Control Panel to Resources mode and select the "Flags: Notify" resource. Choose the Ph_WM_CLOSE flag, then click on Done.

    This flag tells the Window Manager to notify your application when the window is closed.

  5. Now let's set up a function that's invoked when the window opens.

    Open the filemenu menu module, then select the Menu Items resource in the Control Panel. You'll see the menu editor.

  6. Make sure the menu's C:New item is currently selected in the Menu Items list, then click on the Callback icon to open the callback editor.
  7. Choose the Window module type, then click on the icon next to the Name field. You'll see the list of existing window modules.
  8. Choose newwin, which is the window you just created.
  9. In the Setup Function field, enter newwin_setup as the name of the setup function. Later, you'll modify newwin_setup() to handle the window's multiple instances.
  10. Click Apply, then on Done. Click on Done again to close the menu editor.

Adding widgets

Let's now add some widgets to the newwin window module. Using these widgets, you'll learn how to update information in the current or other instances of a window module.

  1. Add a PtRect widget and four PtButton widgets as follows:

    New window 1

  2. Now modify the left button:
  3. Modify the middle button:
  4. Modify the right button:
  5. Modify the large button:
  6. Last of all, give the rectangle an instance name of color_rect, then press Enter. You need to specify this name so that the color_change() function can change the color of the rectangle.

Your window should now look something like this:

New window 2

Generating and modifying the code

In the last tutorial, you used the generated ABW_xxx manifest to access a dialog's instance pointer. You can't use this manifest when dealing with multiple instances of a window module since it refers only to the last window created. Instead, you have to add code to the generated window-setup function so that it stores a copy of each window-instance pointer in a global widget array. In this tutorial, you'll need these pointers for the "Change Previous Window Color" button to work.

Generating the code

Open the Build & Run dialog and regenerate the code.

Modifying the setup function

Now let's modify the newwin_setup() function so that it:

Edit the newwin_setup.c file as follows:

int         win_ctr = 0;
PtWidget_t *win[5];

int
newwin_setup( PtWidget_t *link_instance, 
              ApInfo_t *apinfo, 
              PtCallbackInfo_t *cbinfo )

    {
    PtArg_t args[1];
    char    buffer[40];

    /* eliminate 'unreferenced' warnings */
    apinfo = apinfo, cbinfo = cbinfo;

// Note: Returning Pt_END in a prerealize setup
//       function will tell PhAB to destroy the
//       module without realizing it

    /* allow only 5 windows max */
    if ( win_ctr == 5 ) {
        return( Pt_END );
    }

    /* save window-module instance pointer */
    win[win_ctr] = link_instance;

    sprintf( buffer, "Window %d", win_ctr + 1 );
    PtSetArg( &args[0], Pt_ARG_WINDOW_TITLE, 
              buffer, 0 );
    PtSetResources( win[win_ctr], 1, args );
    win_ctr++;

    return( Pt_CONTINUE );

    }

Modifying the color-change function

Now let's modify the color_change() function so that:

If this were a dialog module you could use the ABW_color_rect manifest to update the color of the rectangle. However, because these are window modules, you must use the instance pointer for the window in which the button is being pressed.

To get the instance pointer, you need to call the ApGetWidgetPtr() and ApGetInstance() functions with the instance pointer of the selected widget and the global variable name ABN_color_rect.

If only one instance of the window were guaranteed, the following would work:

PtSetResources( ABW_color_rect, 1, args );

But in this case color_change() has to use:

PtSetResources( ApGetWidgetPtr( ApGetInstance( widget ), 
                ABN_color_rect ), 1, args );

So you need to change color_change.c to look like:

PgColor_t          colors[5] = {Pg_BLACK, Pg_YELLOW, Pg_MAGENTA,
                                Pg_CYAN, Pg_DGREEN};
int                base_clr = -1;
extern int         win_ctr;
extern PtWidget_t *win[5];

int
color_change( PtWidget_t *widget, ApInfo_t *apinfo, 
              PtCallbackInfo_t *cbinfo )
  {
  int     i, prev;
  PtArg_t args[1];

  /* eliminate 'unreferenced' warnings */
  widget = widget, apinfo = apinfo, cbinfo = cbinfo;

  if ( ApName( widget ) == ABN_btn_red ) {
      PtSetArg( &args[0], Pt_ARG_FILL_COLOR, Pg_RED, 0 );
  } else if ( ApName( widget ) == ABN_btn_green ) {
      PtSetArg( &args[0], Pt_ARG_FILL_COLOR, Pg_GREEN, 0 );
  } else if ( ApName( widget ) == ABN_btn_blue ) {
      PtSetArg( &args[0], Pt_ARG_FILL_COLOR, Pg_BLUE, 0 );
  } else if ( ApName( widget ) == ABN_btn_prev ) {

// Note: Here we use the window-module instance 
//       pointers saved in newwin_setup to update 
//       the window previous to the current window
//       provided it hasn't been closed.

       /* determine which window 
        * is previous to this window 
        */
       prev = -1;
       for ( i = 0; i < win_ctr; i++ ) {
           if ( win[i] == ApGetInstance( widget ) ) {
               prev = i - 1;
               break;
           }
       }

       /* if window still exists,update its background color */
       if ( prev != -1 && win[prev] ) {
           base_clr++;
           if (base_clr >= 5) {
               base_clr = 0;
           }
           PtSetArg( &args[0], Pt_ARG_FILL_COLOR, 
                     colors[base_clr], 0 );
           PtSetResources( win[prev], 1, args );
       }

       return( Pt_CONTINUE );
   }

   PtSetResources( ApGetWidgetPtr( ApGetInstance( widget ), 
                   ABN_color_rect ), 1, args );

   return( Pt_CONTINUE );

   }

Modifying the window-close function

Last of all, you need to modify newwin_close() so that it sets the win array of instance pointers to NULL for a window when it's closed. That way, you can check for NULL in the win array to determine whether the window still exists.

Modify newwin_close.c as follows:

extern int         win_ctr;
extern PtWidget_t *win[5];

int
newwin_close( PtWidget_t *widget, ApInfo_t *apinfo, 
              PtCallbackInfo_t *cbinfo )
    {
    PhWindowEvent_t *we = cbinfo->cbdata;
    int              i;

    /* eliminate 'unreferenced' warnings */
    apinfo = apinfo;

    /* only process WM close events */
    if ( we->event_f != Ph_WM_CLOSE ) {
        return( Pt_CONTINUE );
    }

    /* okay it's a close so who is it? */
    for ( i = 0; i < win_ctr; i++ ) {
        if ( win[i] == widget ) {
            win[i] = NULL;
            break;
        }
    }

    return( Pt_CONTINUE );

    }

Compiling and running

  1. Make the application and run it.
  2. From the application's File menu, choose New several times to create multiple windows. You'll see each window's relative number in its titlebar.
  3. Click on a color button to make the rectangle change color. Then click on the Change Previous Window Color button in any window to change the background color of the previous window.

Want more info?

For more info on: See the section: In the chapter:
Using windows Window modules Working with Modules
Instance names Instance names Creating Widgets in PhAB
Variables and manifests Working with Code chapter
Callbacks Callbacks Editing Resources and Callbacks in PhAB
Code-callback functions Working with Code
Generating code Making and running your application Generating, Compiling, & Running Code

[Previous] [Contents] [Index] [Next]