This chapter discusses adding custom widgets to PhAB, including widget design considerations as well as the steps to follow:
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. |
This section describes the issues you need to consider when you add custom widgets to the PhAB widget palette:
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 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.
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.
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.
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).
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:
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:
This setting starts the definition of a new widget:
w=class_name
Example:
w=ShadowedBox
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.
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.
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_2 … additional_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
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:
In addition, these types are supported for backwards compatibility, but are deprecated:
Here's an example of a data_type(endian_string)/ abstract_name_of_editor string: alloc(24css+il4c)/foo_editor
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
The value can be specified as:
If there aren't any lines of additional information, omit additional_info. Don't specify a value of 0.
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.
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 );
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:
Callbacks can also be inherited from other widgets. See “Inherited resources and callbacks (i=, n=)”, below.
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=).”
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.
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.
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.
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 |
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_2 … definition_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.
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. |
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. |