This chapter describes the resource plugin API for creating your own resource editors for PhAB.
In PhAB, widgets have resources that are displayed in the Resources control panel. You modify these resources using either a small, specialized “frugal”editor directly in the control panel, or by opening a more complex “full”editor.
Previously the code for these resource editors was statically built into PhAB. Now the editors are resource editor plugins — they are small pieces of code and data put together into a DLL that PhAB loads at runtime. The purpose of this chapter is to describe how you can write your own resource editors.
Any resource has a type and a person that writes a resource editor plugin will write a plugin for one of these defined types:
Each of these types is described in the section Resource datatypes. If you write a custom widget and devise a new resource that doesn't seem to fit in any of the above types, then you should use RES_DATATYPE_ALLOC since it describes a general resource datatype. This resource type consists of a buffer of bytes, with a given length. A protocol for ensuring the endian safety when saving/loading the alloc resource is documented in the section Endian issues.
Once you've chosen one of these types for a newly devised resource, the resource type is recorded in the widget's palette file as a string. See the sections Editing palette.def and Creating a widget description table in the Binding Widgets into PhAB chapter.
You can put one, two or more editors into the same DLL, or you can put a frugal editor into one DLL and a full editor into a different DLL. You can choose to only write the full editor and let the frugal editor be the predefined one, or use the frugal editor written by another user, and so on.
To decide which resource editor should be used for a resource type, PhAB looks at the res_editors.def to match entries with the abstract_name_of_editor specified in the palette.def file. There is a res_editors.def file for each user on a system, and a global res_editors.def file for all users. See The res_editors.def file section for more information about the structure of this file.
With the resource editor plugin API, you can:
For instance, if you have a new widget class that has a new resource representing a date (time_t), the default numeric resource editor might be inappropriate. Instead, you can specify that for this date resource, an alternate custom resource editor is used.
This chapter contains:
See these chapters for more information about building a resource editor using the plugin API:
When you create a new resource, for example for a new widget, you need to tell PhAB about the resource and how it should be handled. You need to enroll the resource in one of the types listed below by entering the resource in the widget's palette file. For more information on this, see Creating a widget description table in the Binding Widgets into PhAB chapter.
A widget resource can be one of the following datatypes:
Resource data is passed from PhAB to the plugin instance via a call to ResPluginSetDataF_t, and passed from the plugin instance to PhAB with apply(), ResPluginAnyChangesF_t, or answer_changes(). Each of these functions has a value and an n parameter for the data, though for each resource type these parameters are used differently.
For some resource datatypes, additional format information is required. Format data is passed as a pointer to this structure:
typedef struct ResPluginFormatData_ { int n; const void *value; } ResPluginFormatData_t ;
Each resource data type uses the members of this structure differently. The resource editor should not assume that the pointer to ResPluginFormatData_t remains valid byond the call that passed the pointer.
For some datatypes, the “master copy rule” applies, which means PhAB maintains a master copy of the data and these conditions apply:
For other datatypes, the master copy rule doesn't apply. In these cases, when the data is passed, the recipient (either the plugin or PhAB) must make its own copy of the passed data.
This is the generic datatype that you can use for newly devised resources that do not fit any of the other predefined types. There is no predefined resource editor for this data type. An example of this resource type is Pt_ARG_ROW_LAYOUT_DATA (see below).
When this datatype is passed between the plugin and PhAB, in the passing function the parameter value is an array of bytes and n is the number of bytes being passed.
To allocate memory for this data type in your resource editor, you should use the alloc_mem() function exported by PhAB to allocate memory, and free_mem() to free it.
The palette file type string for this resource type is alloc.
Let's look at an example of implementing the Pt_ARG_ROW_LAYOUT_DATA resource editor.
This resource datatype does not require additional format information from ResPluginFormatData_t.
This data type represents a list of choices, which are string and numeric value pairs that a user can choose from. An example of this resource type is Pt_ARG_LABEL_TYPE.
When this datatype is passed between the plugin and PhAB, in the passing function the parameter value is not used. The n parameter contains the numeric value.
The master copy rule doesn't apply, so the plugin should make its own copy of the data when it is passed.
The ResPluginFormatData_t structure is used to indicate the list of choices and the associated numeric values. In the structure, value is an array of ResPluginChoiceFormat_t*, and n indicates the number of the items in the array.
The resource editor can safely assume that the array will remain valid beyond the call that passed this structure (that is, it will stay valid during the existence of the plugin ).
The ResPluginChoiceFormat_t is defined as:
typedef struct { char *name; long value; } ResPluginChoiceFormat_t;
The members are:
The value being passed to the plugin or from the plugin has to be one of the values indicated in the format structure.
The palette file type string for this resource type is choice.
This data type represents a function, for example Pt_ARG_RAW_DRAW_F. It is similar to the RES_DATATYPE_STRING resource type, except that the master copy rule doesn't apply. This means that you have to make a copy of the value in the resource editor plugin, because it might point to memory on the stack, which is invalid beyond the call that passed the value.
An editor for this resource should allow the user to edit one line of characters.
The resulting line of characters should be a valid string for specifying a function name in PhAB. For more information on properly formatting this string, see Function names and filenames in the Working with Code chapter of the Photon Programmer's Guide.
The ResPluginFormatData_t structure is used to indicate the prototype of the function. The n member is not used and the value member is a pointer to the following structure:
/* format for code datatype */ typedef struct { char *prototype; } ResPluginCodeFormat_t;
The prototype member should point to a function prototype string. For example:
PtWidget_t* @( PtWidget_t *window, PtWidget_t *widget, int position, char *text, char *font, PgColor_t fill_color, PgColor_t text_color )
The @ is used to indicate the function name place holder. The plugin could use the provided prototype to display a list of already defined functions that match the prototype.
The resource editor can safely assume that the value pointer in the format structure will remain valid beyond the call that passed this structure. In fact, it will stay valid during the existence of the plugin.
The palette file type string for this resource type is code.
This data type represents a color resource, for example Pt_ARG_FILL_COLOR.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is not used. The n parameter contains the color, which is a PgColor_t type.
The master copy rule doesn't apply, so your plugin should make a copy of this data when it receives it.
No format data is required.
The palette file type string for this resource type is crgb.
This data type represents a double-precision floating point value, such as Pt_ARG_NUMERIC_VALUE for PtNumericFloat.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is a pointer to a double representing the value, and the n parameter is not used.
The master copy rule applies.
The ResPluginFormatData_t structure indicates the range of values the resource editor should allow this resource to have. In ResPluginFormatData_t, the n member is not used and the value member is a pointer to this structure:
typedef struct { double min; double max; } ResPluginDoubleFormat_t;
The min and max members indicate the minimum and maximum values allowed for the data type. The resource editor can safely assume that the value pointer in the format structure will remain valid beyond the call that passed this information. In fact, it will remain valid during the existance of the plugin.
The palette file entry for this data type is double. The palette file string for this resource type indicates the range this way :
r=manifest_name,desc_name,resource_no,reserved, select_ind,type, default_value[,additional_info]
where:
For example:
r=Pt_ARG_NUMERIC_INCREMENT,Numeric increment,53003, 0,0,double,1,0/100
Also see the chapter Binding Widgets into PhAB in the Photon Programmer's Guide.
This data type represents a flag resource, for example Pt_ARG_FLAGS.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is an unsigned long integer representing the value, and the n parameter is not used.
The master copy rule doesn't apply.
The ResPluginFormatData_t structure is used to indicate the list of values, names and masks. In the ResPluginFormatData_t structure, the value member is an array of ResPluginFlagFormat_t* , and the n member is the number of items in the array.
The resource editor can safely assume that the array of ResPluginFlagFormat_t* will remain valid beyond the call that passed this structure. In fact, it will stay valid during the existence of the plugin.
The ResPluginFlagFormat_t is defined as:
typedef struct { char *name; unsigned long value; unsigned long mask; } ResPluginFlagFormat_t;
where name is the flag's name, value is the flag's value and mask is the associated mask.
The flags should be presented as names in the resource editor, so that a user can choose one or more values. When the user chooses more than one value, the resulting value is all selected values ORed together.
The mask controls how the different values interact with each other. All the values that match a bit in a mask are exclusive values, that is, they exclude each other.For instance if the current value of the resource is current_value and the user selects another flag of the value that has a mask associated, the resulting value will be:
(current_value & ( ~ mask ) ) | value
That means that first the mask is used to clear all the corresponding bits from the current_value and then the value is OR-ed in.
The mask can be 0, which means that the respective flag value doesn't interact with any other flag values.
The palette file type string for this resource type is flag.
This data type represents a font resource, such as Pt_ARG_TEXT_FONT.
This type is the same as the RES_DATATYPE_STRING resource type, but the resulting string has to be a valid font name. For more information on generating a valid font name, see PgGenerateFontName().
The ResPluginFormatData_t structure is used to pass extra information about the fonts allowed for selection. The value member is not used, and the n member can be:
To define a font resource in a palette file, use this string format:
r=manifest_name,desc_name,resource_no,reserved, select_ind, type,default_value[,additional_info]
where type is font and if the font is fixed-width, additional_info is fixed.
This resource type represents a list, such as Pg_ARG_ITEMS.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is an array of strings, the last item of the array being NULL, and the n parameter is the number of strings in the array, not including the last item.
The master copy rule applies.
No format data is required.
You should should use alloc_mem() exported from PhAB in your resource editor to allocate memory for this resource, and free_mem() to free it.
The palette file type string for this resource type is list.
This resource type represents a multi-line text string, such as Pt_ARG_TEXT_STRING.
This resource type is the same as the RES_DATATTYPE_STRING, with the difference that the RES_DATATYPE_MULTI type can contain newline \n characters. The resource editor should allow you to expand on multiple lines.
No format data is required.
The palette file type string for this resource type is multi.
This resource type represents a numeric value, including short, integer, long signed and unsigned values. An example is Pt_ARG_NUMERIC_VALUE.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is not used. The parameter n contains the numeric value.
The master copy rule doesn't apply.
The ResPluginFormatData_t structure is used to indicate the range of values the editor should allow. In the structure, the n parameter is not used and the value parameter is a pointer to this structure:
typedef struct { int64_t min; int64_t max; } ResPluginNumericFormat_t;
The min and max fields indicate the minimum and maximum values allowed in the editor. The resource editor can safely assume that the value pointer in the format structure will remain valid beyond the call that passed this structure. In fact, it will remain valid during the existence of the plugin.
The palette file type string for this resource type is numeric. The previous string short is deprecated, but it is still recognized for backward compatibility. The palette file string for this resource type indicates the range this way:
r=manifest_name,desc_name,resource_no,reserved, select_ind,type, default_value[,additional_info]
where type is numeric and additional_info can be:
Also see the chapter Binding Widgets into PhAB.
If the additional_info section is missing, the resources is assumed to be s32, a signed int.
This data type represents a pattern.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is a pointer to a PgPattern_t, and the n parameter is not used.
The master copy rule doesn't apply, so the value pointer might be allocated on the stack and your plugin should make a copy of the data as soon as it receives the data.
No format data is required.
The palette file type string for this resource type is pattern.
This data type represents an image map, for example Pt_ARG_LABEL_IMAGE.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is a PhImage_t pointer and the n parameter is not used.
The master copy rule applies over the whole image. When this value is passed, the PhImage_t* is passed together with all associated data such as the image data and image palette.
No format data is required.
You should use alloc_image() exported from PhAB to allocate the image pointer, and free_image() to free it.
The palette file type string for this resource type is pixmap.
This data type represents a string.
When this datatype is passed between the plugin and PhAB, in the passing function the value parameter is an array of characters, NULL terminated, and the n parameter is set to the length of the string.
The master copy rule applies.
You should use the exported PhABExportAllocMemF_t to allocate memory, and PhABExportFreeMemF_t to free the memory.
This is the same as the RES_DATATYPE_MULTI type , with the difference that the data cannot contain '\n' characters, and the resource editor should allow only one line of characters to be edited.
No format data is required.
The palette file type string for this resource type is string.
The life cycle of a plugin depends on how it is written. A resource editor plugin can be a frugal editor, or a full editor, and the full editor can be implemented to use an external application. Each scenario is described here.
The following scenario applies to a frugal resource editor:
The following scenario applies for a full resource editor that doesn't use an external application:
PhAB creates an instance of the plugin using its ResPluginFullCreateF_t method.
In this method:
When your full resource editor uses an external application, PhAB assumes that the plugin does not have access to the external application code — the external application is considered to be a black box. The only assumptions made are:
For an example of a resource editor that uses an external application, see the external application example in the Plugin Examples chapter. That example shows how you can use ped as an editor for a PtButton's Pt_ARG_TEXT_STRING resource.
The following scenario applies for a full resource editor that uses an external application:
The mapping between the abstract_name_of_editor in the palette files and the actual frugal and full editors is done in the res_editors.def file (see Creating a widget description table in the Binding Widgets into PhAB chapter).
There are two res_editors.def files, one at the user level file located under the user's home directory along with the other PhAB configuration files (~/.ph/phab), and a global file, located in the same directory as the PhAB executable. The user's res_editors.def file overrides the settings in the global file.
The format of both files is:
e=abstract_name_of_editor [p=path] [F=full_editor] [p=path] [f=frugal_editor]
Each resource definition in the palette files should have a corresponding abstract_name_of_editor definition (the r= line).
The lines that define resources in the palette file are supposed to have an abstract_name_of_editor for each resource definition line ( the lines that begin with r= ). See Creating a widget description table in the Binding Widgets into PhAB chapter. When the abstract_name_of_editor for a resource is missing, it is assumed that the abstract_name_of_editor is the datatype string.
For instance, for the Pt_ARG_CONTAINER_FLAGS definition, the abstract_name_of_editor and the datatype string are both flag:
r=Pt_ARG_CONTAINER_FLAGS,Container Flags,10005,10005, 1,flag,0x30,9
Each one of the abstract_name_of_editors specified in all the palette files must have a section in at least one of the res_editors.def files (either the user specific or the global file). This section indicates the path and the name of the DLL that contains the code for the plugin. Please note that the predefined editors are statically built into PhAB and are not specified in the res_editors.def files. You can override these predefined editors by adding sections to the res_editors.def file.
For instance you can define a section e=string to override the default resource editor for the RES_DATATYPE_STRING resource datatype.
The res_editors.def file defines these settings:
An optional setting, which can be used to specify the path to the next shared objects. It applies to only the shared objects specified inside the current e=abstract_name_of_editor section.
An empty line p= means the path is PhAB's standard location for the plugin editors, which is plugins/resource in PhAB's directory.
If the part following p= doesn't start with a slash /, the path is considered to be relative to the user's home directory.
If no path information is available when the F= or f= settings are parsed, then the path is considered to be PhAB's standard location for the plugin editors, which is plugins/resource in PhAB's directory.
If the setting is p=$, then the $LD_LIBRARY_PATH environment variable is used.
Specifies the full and frugal editors. These lines have the form editor@dll_name.
The dll_name includes the shared library extension. On QNX the extension for shared objects is .so, while on Windows it is .so or .dll.
For example, the frugal_editor can be specified as: date@editors.so). If the @dll_name part is missing, the dll name is considered to be the same as the editor's name plus the extension.
For instance, assume you want to write a resource editor to edit a date. The datatype used is numeric, but the default editors for the numeric dataype are not suitable for editing a date format:
a)
e=date p=/tmp/plugins F=date1@exp_date p= f=date2@date
In this example, the date type uses the full editor date1 located in the /tmp/plugins/exp_date.so, and the frugal editor date2, located in date.so, in PhAB's standard plugin directory plugins/resource under the PhAB's executable directory.
b)
e=date f=date2
This example uses the date2 editor for the frugal editor, located in plugins/resource/date2.so.
c)
e=date p=my_plugins F=date
This example uses the full editor date located in my_plugins/date.so, under the user's home directory.
If a palette file specifies an abstract name of an editor and there is no information about it in any of the res_editors.def files, and PhAB detects this at startup, it will exit with an error, except for the cases where it is safe to use the default datatype editor instead.
The def_res.def file in PhAB's executable directory lists the abstract editors (one editor per line) for which it is safe to use the default datatype editor, anytime something prevents a different editor from being used.
For instance, in the example c) above, the frugal editor for date is not specified (there is no “f=” entry). If the predefined frugal editor for the datatype numeric is to be used, def_res.def has to specify date inside.
The RES_DATATYPE_ALLOC datatype can't be listed in def_res.def since there is no default editor for it. |
Because you can run PhAB on one platform and target another platform with a different endianness, PhAB needs to know how to load and save the widget files and the aplib needs to know how to load the content of the resource file at run time.
For the predefined datatypes, this is already taken care of, because the widget files are saved in a endian-insensitive form, and at runtime they are converted to the right endian form.
For the RES_DATATYPE_ALLOC datatype, you can specify an endian signature. This is a string that you put in the palette files. Each time a resource is saved, the string tells PhAB how to save the resource data in a endian-insensitive form. The string is saved along the resource data in the widget files. When the widget files are loaded either at runtime by aplib, or by PhAB, the endian string is read before reading the actual data. The string tells aplib and PhAB how to convert the loaded data to the right endian form.
Here's an example of endian string:
24css+il4c
This string describes an endian structure with:
Use:
Each of these can be preceded by a number to indicate a sequence of the same type data.
Use a + to indicate the start of an array of structures. The number of items in the array is determined by looking at the length of the resource data that's left to be loaded for that particular resource.
You can only specify an endian string for RES_DATATYPE_ALLOC resource types, and it's optional. A RES_DATATYPE_ALLOC resource type that has no endian string will be considered to be endian insensitive and in this case it will be the widget's and the plugin's responsibilities to correctly interpret the array of bytes.
In other words, when the endian string is missing, it's the same as setting the endian string to +c.