HPGCC3 Documentation 3.0 R003

GUI controls overview

Controls are elements that perform some interaction with the user. The simplest controls display text or graphics and don't receive any input. Other more complex controls can receive user input, provide visual feedback, and/or perform specialized tasks. The GUI architecture is object oriented. Each control is represented by C++ classes that encapsulate their basic behavior.

A complete list of controls follows:

  • gApplication - Encapsulates the basic behavior of an application, initializing the hardware, reading the keyboard, generating events and distributing them among the controls. A program can only contain one gApplication object.
  • gControl - Encapsulates the common behavior of all controls. It doesn't have any particular purpose other than being the base class for the other controls. It is not used unless you need to derive your own controls from this class.
  • gForm - A form is a universal container control. It can contain other controls and distribute events among them. Always, user interaction happens within a form. A program may contain any number of forms. The user can switch between forms, but only one form can have the keyboard input at a time. Forms can take the entire screen or appear as windows, and they can optionally display a caption and a border.
  • gSoftMenu - The soft menu control makes it possible to use soft menus similar to the calculator's signature menus. This object is always created associated to a form. A form can have only one soft menu. Soft menus can be dynamically updated at any time (i.e. have its items removed, replaced, etc.). A soft menu can be single-line, just like the traditional calculator menus, or extended. Extended soft menus display 3 lines of options, corresponding to keys from A through L for a total of 12 items on-screen simultaneously.
  • gStaticText - The static text control simply shows a given text. The text can be updated at any time.
  • gStaticTextWrap - This is a more advanced static text that can word-wrap long text, becoming a multiline static text control.
  • gCheckBox - This simple control shows a check box and provides its behavior. The user can check/uncheck the box from the keyboard. The box can have several different styles. Unlike other GUI's, this check box does not have text associated with it.
  • gEditBox - This is the main text input control. It provides a space for the user to type text. The control supports single-line and multiline behavior, automatic scrolling, and an optional border.
  • gListBox - This control can display a list of items (with an optional tree structure), and let the user select items from the list. Its features include expand/collapse support, check mark support, auto scrolling and optional border.

Applications typically use arbitrary combinations of the above controls to achieve the desired behavior.

Creating controls

The first control that needs to be created in any program is gApplication. A gApplication object must be created when the program starts and destroyed only at program exit. The simplest way to achieve it is by creating it in the main() function as follows:

 #include <hpgcc3.h>
 #include <gui.h>
 
 int main()
 {
 gApplication myapp;
 // ... ADD YOUR PROGRAM HERE
 }

The next step is to create one or more forms. Forms require a parent object to be specified in the constructor. The parent object of a gForm *MUST* be the application object. The simplest constructor requires also a caption text and some style flags.

The following sample code creates an empty full screen form with a caption at the top (see other constructors at the gForm class documentation):

 #include <hpgcc3.h>
 #include <gui.h>
 
 int main()
 {
 gApplication myapp;
 gForm myform(myapp,"Form test",S_TOPCAPTION);
 
 // ... ADD MORE INITIALIZATION CODE HERE
 
 return myapp.Run();
 
 }

The above example goes one step forward: it shows how to run the application message loop. The member gApplication::Run starts the message pump for the recently created form. In case of multiple forms, a form can be passed as an argument, making it the active form.

Notice that the gForm object should NOT be deleted (or run out of scope) before the Form is properly closed. A form can be closed by calling gApplication::CloseForm(), which is automatically done when a program calls gApplication::Terminate(). It is the user's responsibility to check the lifespan of the objects, but it's safe to delete them after the Run() member returned.

Before executing the code example above we need to add one more thing: a way to close the form. Forms don't have any means to close themselves, so the above program will simply run forever, or until interrupted using On-A-F.

The next step is to provide that exit mechanism, which can be done through a soft menu. The gSoftMenu object constructor requires a parent control, which must be a form (other controls don't provide support for their own soft menus), and it also requires a style flag. Once we created the empty softmenu, we need to add items to it. This is achieved by the gSoftMenu::AddItem member. Adding an item is simple: just provide a short string of text to display, and the address of a function that will be called every time the user hits the soft menu. If you add more than the items that fit on the screen, the NXT key will begin to select pages, just like the standard calculator soft menus.

The function that is passed to AddItem is an event handler, and therefore it must follow certain rules in its declaration. For more details see GUI events overview but for now we'll use one of the standard event handlers, which provide the behavior we need. In this case, all the handler needs to do is to exit the application loop by calling gApplication::Terminate.

The complete sample code now becomes:

 #include <hpgcc3.h>
 #include <gui.h>
 
 int main()
 {
 gApplication myapp;
 gForm myform(myapp,"Form test",S_TOPCAPTION);
 gSoftMenu mymenu(myform,S_SINGLESOFTMENU);
 
 mymenu.AddItem("EXIT",&gOKEvent); // USING STANDARD HANDLER gOKEvent
 
 // ... ADD MORE INITIALIZATION CODE HERE
 
 return myapp.Run();
 
 }

At this point, any number and combination of other controls can be created within the form. All of them require a parent form in the constructor, the rest of the arguments varies according to each class (see each individual class documentation). Always the user is responsible for proper deletion of controls. Deleting a form will NOT delete its controls automatically.

Many controls require coordinates to specify its size and location. Always, the coordinates are measured in screen pixels (1 unit = 1 pixel on the screen). The origin (0,0) is always the top-left corner of the parent object client area. In a form with a top caption, this is right under the caption, to the left. Forms, whose parent is the application object, have the origin at the top-left corner of the screen. The X coordinate runs positive to the right, and the Y coordinate runs positive towards the bottom of screen.

Always keep in mind that the screen has 132 pixels wide x 80 pixels high when sizing your controls. Forms can be larger than the screen, and the user can scroll through the controls.

As an example, the code below will display a "Hello GUI world" message by creating a gStaticText control:

 #include <hpgcc3.h>
 #include <gui.h>

 int main()
 {
 gApplication myapp;
 gForm myform(myapp,"Form test",S_TOPCAPTION);
 gSoftMenu mymenu(myform,S_SINGLESOFTMENU);
 
 mymenu.AddItem("EXIT",&gOKEvent); // USING STANDARD HANDLER gOKEvent
 
 gFont SystemFont8(8);
 
 gStaticText higuitext(myform,10,10,"Hello GUI",&SystemFont8,GBLACK);
 
 // ... ADD MORE INITIALIZATION CODE HERE
 
 return myapp.Run();
 
 }

This example introduced a couple of new concepts that are common to several controls.

First, all controls that display text will require a pointer to a gFont object. The gFont object is not a control, it is a data structure that encapsulates the proportional fonts. Any number of gFont objects can be created, but they can be shared between controls so in many cases only one or two will suffice. The constructor of the gFont class takes an integer as the only argument. This integer is the font height in pixels of the system font. The GUI has a proportional version of the calculator's standard System8, System7 and System6 fonts, as well as a tiny font (5 pixels high). The example above creates a gFont object to refer to the System8 font, and then uses a pointer to this object when creating the gStaticText control. See Advanced GUI topics and internals for details on loading and using custom fonts.

The other concept introduced in this example is the colors. The last argument to the gStaticText constructor is the text color. In the example, the constant GBLACK was used. To specify other colors use the constants in the gColors enum. See Advanced GUI topics and internals for more details in colors and graphics in general.

Customizing controls

This section explains in detail all the constructors used by each class, as well as their styles and options.

Form objects can be created using one of four constructors The class constructors have the following form:

        gForm::gForm(gControl& Parent,const char *_Caption,gFormStyles _Style);
        gForm::gForm(gControl& Parent,const char *_Caption,gFormStyles _Style,int clientwidth,int clientheight);
        gForm::gForm(gControl& Parent,const char *_Caption,gFormStyles _Style,int x,int y,int width,int height);
        gForm::gForm(gControl& Parent,const char *_Caption,gFormStyles _Style,int x,int y,int width,int height,int clientwidth,int clientheight);

The first three arguments are common to all constructors. The arguments that follow determine how the form will be created. The meaning of the arguments is simple: x,y,width,height are the position and size of the window in the parent's client area. When these arguments are specified, the form is created as a window at the specified location. When these arguments are not specified, the form takes the entire space in the parent's client area, becoming a full-screen form.

So it's easy to see that constructors can be divided in 2 groups: the first two are full-screen forms, the last 2 are windowed forms. The first and third constructors are equivlent, and the second and fourth are similar, allowing an arbitrary size of client area (larger than visible on the screen). When the second or fourth constructors are used, a scroll bar will appear in either direction as required.

On all constructors, the Parent argument must be the gApplication object. The _Caption argument is used to display a text, but only if the proper style is selected (see below). The _Style argument is a combination of style flags (combined with OR or by addition). The following style flags are supported for Forms:

S_TOPCAPTION = Add a title bar with a caption text shown in 5-pixel tiny font. S_FORCEVSCROLL = Show a vertical scroll bar even if not needed. S_FORCEHSCROLL = Show a horizontal scroll bar even if not needed. S_FORMBORDER = Add a border line around the form (useful for windowed forms).

Notice that there are other flags in the gFormStyles enum. Some are simply not implemented yet, and some are automatically set/cleared, and the user doesn't need to specify those at creation.

There are two constructors available for gSoftMenu:

        gSoftMenu::gSoftMenu(gControl& Parent,int Style);
        gSoftMenu::gSoftMenu(gControl& Parent,int Style,struct gSoftMenuItem *List, int numitems);

In both constructors, the Parent control must be a gForm object. Only gForms are able to properly interact with soft menus. The Style argument is one of the following flags:

S_SINGLESOFTMENU = Create a standard single-line soft menu S_EXSOFTMENU = Create an extended 3-line soft menu

The single-line soft menu is a standard menu with 6 items. If more than 6 items are added to the menu, the NXT key performs page switching. The extended soft menu generates a 12-item menu in 3 lines, corresponding to keys A thru L. If more than 12 items are added to the menu, the NXT key becomes active. Notice that the last item in the menu will become NEXT on every page. The second constructor requires a list of items and the number of items in the list. This list should contain all the items in the menu and its handlers. It is completely equivalent to using the first constructor and then calling the member AddItemList. See gSoftMenu::AddItemList for details on how to assemble the list.

Using controls