Binding Widgets into PhAB

This chapter discusses adding custom widgets to PhAB, including widget design considerations as well as the steps to follow:


Note: Be sure to modify your application's Makefile so that it's linked with your new widget. Include your widget header in the global application header defined in the Application Start-up Info dialog.

Widget design considerations

This section describes the issues you need to consider when you add custom widgets to the PhAB widget palette:

Single-value resources

PhAB has builtin editors for handling certain types of single-value resources. It also provides multiple-value editors for some resource types. If you design your resources to use the types supported by PhAB, developers will be able to use the widget in PhAB easily. If you define resources that have no associated editor in PhAB, you can create a resource editor for them as described in Creating custom resource editors, otherwise developers will be able to set and use these resources only through application code. The list of currently supported types can be found in the section on Creating a widget description table.”

When to add custom widgets to palette files

When you define a widget class, you assign it a widget number. This number is combined with the resource number to create a series of unique resource numbers for the widget. When you add the widget to the PhAB widget palette, you define these resource values in the widget palette file.

PhAB uses these numbers when it stores the widget in the module files. If you change the resource number or widget number after it has been used in a PhAB application, you won't be able to continue using the old widget (defined in the PhAB module) because the resource numbers will no longer match. For this reason, you should add widgets to the PhAB palette file only when almost all the widget's functionality has been completed and the resource numbers will no longer change.

Displaying your custom widget

As described in Editing palette.def,” later in this chapter, you can tell PhAB the name of the shared library for your widget. If PhAB can open this library, it can display your custom widget, and you'll see the results of editing the widget's resources.

If PhAB can't open your widget library, you won't be able to see the widget change visually when you make changes to the resources. The widget will display properly when you actually compile, link, and test the application.

Remember to include the widget header file in the application header so that the generated abmain.c file will know about your widget. Also, add your widget to the MYOBJ object list defined in the indOfiles file.

Creating a shared object

After you've created your widget, you need to build it into a shared object. To do this, compile your source code like this:

cc -shared -o libmy_wgt.so my_wgt.c -v -Wl,-hlibmy_wgt.so

If you want to make a debug version of your widget library, add the compiler option -gdwarf-2 to the command line before the -shared option. For more information about compile options, see qcc in the QNX Neutrino Utilities Reference.

You need to place this library in a directory that's in the LD_LIBRARY_PATH path. You also need to put the header file for your custom widget in a place where you can find it later.

Creating a template

Use PhAB to create a template for your widget. For more information, see Templates in the Creating Widgets in PhAB chapter of the Photon Programmer's Guide).

Editing palette.def

Next, edit the /usr/photon/appbuilder/palette.def file. You need to add some lines that look like this:

l=PtWeb,<photon/PtWebClient.h>:ph
p=xpalette,Web Widgets

The first line is the library line, and starts with l=: It consists of:

The second line identifies the palette file for this widget, and starts with p=. It consists of:

Creating a widget description table

The description table for a single widget is stored in a widget palette file. The widget description table must describe all the resources and callbacks your custom widget understands.

The palette file can contain any number of widget description tables but must contain at least one. The name of your palette file must end with a .pal extension (e.g. mywidget.pal). To get a good idea of what a palette file should contain, look at the /use/photon/appbuilder/ptpalette.pal file.

Here's an example of a widget description table:

w=PwMenuWidget

h=4
PtWidget
PtBasic
PtContainer
PwMenuWidget

r=PW_LIST_DOWN,List Down Image,5001003,0,0,pixmap,NULL
r=PW_LIST_UP,List Up Image,5001004,0,0,pixmap,NULL
r=PW_SCROLL_DOWN,Scroll Down Image,5001005,0,0,pixmap,NULL
r=PW_SCROLL_UP,Scroll Up Image,5001006,0,0,pixmap,NULL
r=PW_SCROLL_LEFT,Scroll Left,5001007,0,0,pixmap,NULL
r=PW_SCROLL_RIGHT,Scroll Right, 5001008,0,0,pixmap,NULL

t=2
s=0xe906

The start of a new widget in the file is defined by a widget class name definition. This is followed by the widget hierarchy, resources, callbacks, type definition, and finally some initial default values to use when the widget is first created.

The widget description table defines the following settings:

Widget class name (w=)

This setting starts the definition of a new widget:

w=class_name

Example:

w=ShadowedBox

Note: Don't include spaces before or after the equals sign (=).

When PhAB encounters a class name setting, it allocates space in its internal list for the widget. Any settings found afterwards are applied to this widget until a new widget class name setting is encountered.

Widget hierarchy (h=)

This setting defines the widget hierarchy:

h=number_of_levels
highest_class_name
[next_highest_class_name]
…
custom_widget_class_name

Example:

h=3
PtWidget
PtBasic
ShadowedBox

The h= setting indicates the number of levels in the hierarchy. This is followed by the widget class hierarchy names in descending order of inheritance.

The widget hierarchy setting tells PhAB which class in the widget's hierarchy to use when different classes of widgets are selected. For example, if you select a PtLabel and PtButton widget at the same time, the PhAB Control Panel must show you resources that apply to both widgets. PhAB does this by walking up the hierarchy list until it finds the identical class name for both widgets.

List of resources (r=)

If you want to be able to edit a resource in PhAB, you'll need either an r= entry (for new resources or inherited resources with a different default value) or an i= entry (for inherited resources) — see Inherited resources and callbacks (i=, n=) below.

The r= setting defines a resource for the widget:

r=manifest_name,desc_name,resource_no,reserved,select_ind,
datatype[(endian_string)][/abstract_name_of_editor],default_value
[,additional_info]
[additional_info_1
additional_info_2additional_info_n]

Example:

r=SBW_SHADOW_COLOR,Shadow Color,5000000,0,1,crgb,0x0
r=Pt_ARG_HORIZONTAL_ALIGNMENT,Horizontal Alignment,3000,0,1,choice,2,3
Pt_LEFT,0
Pt_RIGHT,1
Pt_CENTER,2

Note: Don't create resource entries for the Pt_ARG_POS and Pt_ARG_DIM resources. All widgets must support these, so PhAB handles them internally.

The arguments of the resource entry have the following meanings:

manifest_name
The valid C manifest name to access this resource from application code.
desc_name
A descriptive version of the manifest name, which is easier to understand and takes up less space (allowing the Control Panel to stay small).
resource_no
The actual resource number (e.g. Pt_USER(0)=5000000, Pt_USER(1)=5001000, and so on — Pt_RESOURCE(Pt_USER(2),5)=5002005).
reserved
Always use a value of 0.
select_ind
Indicates whether this resource supports multiple selections. A value of 0 will hide the resource when two or more widgets are selected. A value of 1 enables the resource.
type
Indicates the type of editor PhAB should use for this resource. For more detailed information about resource types, see Resource datatypes in the Creating Custom Resource Editors chapter. Valid types are:
alloc
A generic resource type, not covered by the other types.
choice
An exclusive choice type.
code
A pointer to a function (see Pointer-to-function resources below).
crgb
A color value of type PgColor_t.
double
A double value.
flag
Flag resource.
font
Font specification (string).
list
Array of text strings.
multi
Multiline text string.
numeric
Numeric type.
pattern
A pattern type, for example Pt_ARG_FILL_COLOR.
pixmap
Supports the creation/modification of PhImage_t structures.
string
Single-line text string.
points
Used internally by PhAB for multisegment lines. PhAB manages this resource type so you can use the points array provided by PtGraphic.

In addition, these types are supported for backwards compatibility, but are deprecated:

datas
Single-line text string (Alloc type). Deprecated; use string instead.
float
A float value. Deprecated; use double instead.
short
Numeric value. Deprecated; use numeric instead.
ushort
Unsigned value (a C type of unsigned short, unsigned long, unsigned int, or unsigned char). Deprecated; use numeric instead.
endian_string
Indicates the endian string for the resource. This is optional and is used only for alloc resource types.

Here's an example of a data_type(endian_string)/ abstract_name_of_editor string: alloc(24css+il4c)/foo_editor

abstract_name_of_editor
Indicates the name of the editor for this resource, as defined in the res_editors.def file. PhAB parses a global res_editors.def file and a user specific res_editors.def file for the names of resource editors. See The res_editors.def file section of the Creating Custom Resource Editors chapter.
When abstract_name_of_editor is missing, it is assumed to be the same as the data_type string. Do not start your abstract_name_of_editor with a $. That's reserved for PhAB use.
default_value

This is the default value in the widget code itself. It's very important for this value to exactly match the real default value in the widget, because PhAB doesn't generate resource entries in the module files if it seems the resource matches the default value. This keeps the size of the module file to a minimum. If the default value you specify doesn't match, the widget may not behave as expected because a required resource setting will be missing from the module file.

If the resource datatype is alloc, you have to specify the total number of bytes for the default value, followed by a new line that contains the values. The values follow the endian string format. For instance, if your endian string is 2i3s then you will have to specify 2 integer values followed by 3 short values. Each value is either a decimal value (for instance: 79) or a hexadecimal value (for instance: 0x4f). If the endian string is missing, the default endian string (+c) is used.

Each value is endian-less and they are separated by space or \n new lines.

Here's an example:

r=Pt_ARG_MY_RESOURCE,My Resource,100220,0,0,alloc(11s)/my_resource,22
0x0100 1 1 0 0 0 0 0 0 0 0
additional_info
This optional value can be used to specify additional information about the resource:

The value can be specified as:

Option and flag pairs

For choice and flag resources, additional_info specifies the possible values. Each line is in the form:

description,value

where description is the text that PhAB is to display in the editor, and value is the corresponding value.

Pointer-to-function resources

For a resource that's a pointer to a function (i.e. type is code), additional_info specifies the number of following lines that define the function's prototype. The prototype should contain an @ in place of the function name, but no terminating semicolon.

The default_value specifies the code that will be used for the function body whenever PhAB generates a function for the resource. If the code will fit on the line and doesn't contain any commas, you can specify it directly as default_value. Otherwise, put the code on the lines that follow the function prototype, and set default_value to be the number of lines of code.

Here are some examples:

r=ARG_SIMPLEFUNCTION,A function,5000001,5000001,1,return 0;,1
int @( void )

r=Pt_ARG_RAW_DRAW_F,Draw Function,24000,24000,1,code,1,1
void @( PtWidget_t *widget, PhTile_t *damage )
    PtSuperClassDraw( PtBasic, widget, damage );

r=Pt_ARG_LIST_BALLOON,Inflate Function,23031,23031,1,code,6,5
PtWidget_t *@(
        PtWidget_t *widget, PtWidget_t *parent,
        PhArea_t *area, PtListColumn_t const *column, int coln,
        const char *item, unsigned index, const char *font
        )
    return
        PtGenListCreateTextBalloon(
            widget, parent,
            PtGenListSetColumnBalloon( area, column ),
            item, coln, font
            );

List of callbacks (c=, k=, e=)

These settings define callbacks:

c|k|e=manifest_name,desc_name,resource_num,reserved

Example:

c=Pt_CB_ACTIVATE,Activate,2009,0
k=Pt_CB_HOTKEY,Hotkey,1010,0
e=Pt_CB_RAW,Raw Event,1011,0

Photon supports three different types of callbacks. These are standard widget callbacks (c=), hotkey callbacks (k=), and raw callbacks ( e=). Make sure you use the type that matches the definition of the callback in the widget.

The arguments of the callback entries are identical and have the following meanings:

manifest_name
The valid C manifest name to access this resource through application code.
desc_name
A descriptive version of the manifest name, which is easier to understand and takes up less space (allowing the Control Panel to stay small).
resource_no
The actual resource number (e.g. Pt_USER(0)=5000000, Pt_USER(1)=5001000, and so on — Pt_RESOURCE(Pt_USER(2),5)=5002005).
reserved
Always use a value of 0.

Callbacks can also be inherited from other widgets. See “Inherited resources and callbacks (i=, n=)”, below.

Inherited resources and callbacks (i=, n=)

Resource descriptions can be shared by multiple widget classes. This saves memory on runtime and helps keep the palette files consistent (e.g. if a new flag is added to a resource of a parent class, you don't have to add it to the description of each child class manually).

These settings can be used to inherit resource or callback definitions from a widget defined earlier:

i=widget[,from[,to]]
n=widget[,from[,to]]

The i= line copies resources (defined by r= or i= lines). The n= line copies callbacks (defined by c=, k=, e=, or i= lines).

The from and to values are numbers that specify the resource numbers to be copied. If both are given, they define a range. If only the from value is given, it specifies one resource. If neither from nor to is given, all resources/callbacks will be copied.

The i= entry can be used only if the resource definitions for the child and parent classes are identical. If there are any differences (for example, the child class overrides the default value), you'll need to use an r= resource definition — but the child class can still inherit any additional_info that the parent class defines or inherits. For more information, see List of resources (r=).”

Base widget (b=)

This setting tells PhAB to use container emulation:

b=Container

Since PhAB can't display your widget directly, it must use a substitute widget in its place. If the widget isn't a container and you don't set this value, PhAB will use a PtBasic widget to emulate your widget. If the widget is a container, set the value as shown above and PhAB will use PtContainer to emulate your widget.

Change class definition (q=)

This definition table setting limits the classes the current container widget can be changed into, if it contains children:

q=widgetclass[,widgetclass]

Example:

q=PtContainer,PtGenList

The change class definition tells PhAB which classes this container widget class may be changed into, if it contains children widgets. This operation is performed when a user selects the Change Class command in PhAB.

The general rule is, if a widget class has a setting of q=a,b,c, it can only be class changed into a class that has a setting of q=a,... , q=b,..., or q=c,.... That is, the first item of the target class's q= setting must match a widget from the q= setting of the original class.

For example, all list and tree widgets have the setting q=PtGenList,PtContainer, and PtPane has q=PtContainer. This means you can change from a list with a child into a PtPane, but not from a PtPane with a child into a list.

If the change class definition q= is missing from a widget class's definition table, then that widget class cannot be used as a target when the original widget has children.

If a container widget has no children, it can be changed into any other type of widget.

Create-type definition (t=)

This setting defines the type of creation mode to use:

t=number

Example:

t=2

The type definition tells PhAB how this widget should be created. For example, if t=1, PhAB automatically creates the widget as soon as the user clicks in the module. This is because type 1 indicates the widget has a preset size. A value of t=2 means the user can drag out the size when creating the widget.

Valid values for number range from 1 through 6 and have the following meanings:

When number is: Create type is:
1 Preset, resizable
2 Resizable on create
3 Line (2 points)
4 Preset, Nonresizable
5 Polygon (multipoint)
6 Bezier (multipoint with handles)

For more information, see Creating a widget in the Creating Widgets in PhAB chapter of the Photon Programmer's Guide.

Cursor styles (s=)

This setting determines the cursor style when creating the widget:

s=start_cursor_style[,drag_cursor_style]

Example:

s=0xe914,0xe914

This setting defines the look of the cursor when the widget is being created in PhAB. The value you choose for a cursor style setting (s=) will depend on the value you specify for the create type setting (t=). For consistency with other widgets in PhAB, we recommend that you assign cursor style values according to the table below:

If create type is: Cursor style should be:
t=1 s=0xe906
t=2 s=0xe914,0xe914
t=3 s=0xe906
t=4 s=0xe906
t=5 s=0xe906
t=6 s=0xe906

Default values (d=)

This setting lets you give the widget some default values to override the defaults built into the widget:

d=class_name,no_of_resource_definitions
definition_1
definition_2definition_n

Each definition consists of three values:

For example:

// Resizable example.
d=ShadowedBox,1
1005
dim
1,1

// Preset example.
d=PtPrintSel,1
1005
dim
418,285

Each resource definition is made up of three lines, and only simple resource types can be used. In the example above, the Pt_ARG_DIM (1005) resource is set to 1 pixel high and 1 pixel wide. This is a good starting point for a widget with a create type number of 2.


Caution: You must always give a widget a default value and starting dimension. If you don't, you'll get unexpected results.

If t=1 or t=4, set the dim resource to the preset size. If the value is anything else, set dim to 1,1. The dim resource is defined as width,height in pixels.



Note: When used in conjunction with PhAB widget templates, these overrides are not used, and are simply ignored.

This is true for all default overrides, except for resources that can not be accessed through the PhAB resource editor.