### XPanels Availability LightWave® 6.0 Component Layout, Modeler Header lwxpanel.h This global is a new addition to LightWave®'s system of platform-independent user interface components. To understand its place in that system and how it differs from Panels, it may help to know something about the history of user interfaces in LightWave®. XPanels is the third generation of LightWave® interface APIs. The first was the requester API, which in its original Modeler incarnation predates the plug-in architecture itself. Modeler requesters were always modal. You gave Modeler a list of controls and their initial values, Modeler formatted and displayed the dialog, and after the user closed the dialog, you read out the control values. The original requester API is now just another way of creating an xpanel, and you can use it in Layout as well as Modeler. Panels is the second generation, and it's pretty bohemian, like Algol was to Fortran. It introduced callbacks so that you can respond to the user interactively, and it comes with a list of 50 or so predefined control types and some drawing functions. You can set the size of a panel and the positions of its controls, and you can decorate your panels and tell them to send you a steady stream of mouse and keyboard events. As with requesters, controls are defined using a sequence of function calls. XPanels is a return to the Modeler requester philosophy of automation. You give up some control over the appearance and behavior of your controls, but in exchange, things that can require a lot of code with panels, like adding an E (envelope) button to a numeric edit field, along with all of the functionality that implies, are very easy to do with xpanels. And xpanels can be embedded in LightWave®'s own windows. Unlike the previous interface models, the controls on an xpanel are defined primarily through arrays of static data. Panels continues to support some control types, such as the OpenGL control, that have no xpanel equivalents, so it's still your best option in some cases. But you aren't forced to choose, since Panels also allows you to create xpanel controls--xpanels embedded within your panel. Global Call
       LWXPanelFuncs *xpanf;
       xpanf = global( LWXPANELFUNCS_GLOBAL, GFUSE_TRANSIENT );
The global function returns a pointer to an LWXPanelFuncs.
       typedef struct st_LWXPanelFuncs {
          int             version;
          LWXPDrawFuncs  *drawf;
          LWXPanelID     (*create)     (int type, LWXPanelControl *);
          void           (*destroy)    (LWXPanelID);
          void           (*describe)   (LWXPanelID, LWXPanelDataDesc *,
                                          LWXPanelGetFunc *,
                                          LWXPanelSetFunc *);
          void           (*hint)       (LWXPanelID, unsigned int,
                                          LWXPanelHint *);
          void *         (*getData)    (LWXPanelID, unsigned int);
          void           (*setData)    (LWXPanelID, unsigned int, void *);
          void *         (*formGet)    (LWXPanelID, unsigned int);
          void           (*formSet)    (LWXPanelID, unsigned int, void *);
          void           (*viewInst)   (LWXPanelID, void *);
          void           (*viewRefresh)(LWXPanelID);
          int            (*post)       (LWXPanelID);
          int            (*open)       (LWXPanelID);
       } LWXPanelFuncs;
A panel is a window or a dialog box containing buttons, edit fields, dropdown lists, image rectangles, and other user interface elements collectively called controls. You create panels to allow users to enter and change settings that affect the operation of your plug-in. The XPanels system distinguishes between two kinds of panels, called forms and views. They differ primarily in the method used to move data values into and out of controls. A view panel presents a "view" of a data instance, which is a pointer to some data owned by your plug-in, typically a handler's instance data. You pass this pointer to XPanels in the `viewInst` function. The callbacks you pass to the `describe` function will be called by XPanels to update this data. A form panel isn't passed a data instance pointer, so you have greater freedom in choosing how to represent your data within your plug-in. XPanels interacts with your data through the `formGet` and `formSet` functions and your change notification callback. Because they don't store a data instance pointer, forms have no way to distinguish between multiple instances of the same dataset, making it more difficult to use the same panel with different data. The significance of this may grow as XPanels evolves. In the future, for example, users may be able to multiselect every instance of your plug-in and edit the parameters for all of them simultaneously. `version` The version number of the interface. Certain control types or hints may not be available in older interfaces. `drawf` Drawing functions, which are explained in detail below. Custom drawing on xpanels is limited to contexts in which an LWXPDrArea region is defined. `panel = create( type, controls )` Create a new panel. The type can be `LWXP_VIEW` or `LWXP_FORM`. The `controls` argument is an array of LWXPanelControl structures describing the controls on the panel. It must have at least panel lifetime, meaning that the `controls` variable must be valid as long as the panel exists. The easiest way to ensure this is to declare the array static. See below for more about the controls list. `destroy( panel )` Free the panel and related resources allocated by `create`. `describe( panel, datadesc, getfunc, setfunc )` Define the data values for a panel. The `datadesc` argument is a list of value IDs and their types. Like the `controls` list passed to `create`, `datadesc` must have at least panel lifetime. For view panels, the values are updated interactively using your `getfunc` and `setfunc` callbacks. If the panel is a form, the `getfunc` and `setfunc` arguments are ignored and should be NULL. `hint( panel, id, hints )` Apply a hint array to the panel or one of its controls. This may be called multiple times, but only while the panel is closed. The hint array is applied to the panel if the ID is 0. Otherwise it's applied to the control with the corresponding ID. `data = getData( panel, id )` Returns the user data for the panel (`id == 0`) or for one of its controls, set by a previous call to `setData`. `setData( panel, id, data )` Set the user data for a panel (`id == 0`) or one of its controls. The `data` pointer is passed to several of the callbacks. It's also what `getData` returns. `value = formGet( panel, vid )` Read the value of a control on a form panel. Returns NULL if the value is undefined. `formSet( panel, vid, value )` Write a value to a control on a form panel. `viewInst( panel, instance )` Set the instance data pointer for a view panel. This is what is passed to the get and set callbacks you designate when you call the `describe` function. `viewRefresh( panel )` Refreshes a view panel by reloading control values from the instance data. Use this when the instance data has been modified by something other than the user's interaction with your interface. When called from a form, `viewRefresh` redraws the controls. `result = post( panel )` Display the panel for modal interaction. Modal means that the user must close the panel before continuing to work in LightWave®. This function won't return until the panel has been closed. It returns 1 if the user dismisses the panel with the "OK" button and 0 if the user presses "Cancel" (or if the panel couldn't be displayed). See the description of the `XpDLOGTYPE` macro for more information about the buttons, like "OK" and "Cancel," that are automatically added to modal panels. `result = open( panel )` Display the panel for non-modal interaction. This function returns immediately and the panel stays open until the user closes it. Returns 1 if the panel was opened successfully, otherwise it returns 0. Handlers generally won't need to call `open` (or `post`), since LightWave® takes care of opening the panel you return in the `panel` field of the LWInterface structure. Describing Controls and Data Each of the controls on a panel is described by an LWXPanelControl structure. An array of these is passed as the second argument to the `create` function when the panel is created.
       typedef struct st_LWXPanelControl {
          unsigned int   cid;
          const char     *label;
          const char     *ctrlclass;
       } LWXPanelControl;
The second argument to the `describe` function is an array of LWXPanelDataDesc.
       typedef struct st_LWXPanelDataDesc {
          unsigned int   vid;
          const char     *name;
          const char     *datatype;
       } LWXPanelDataDesc;
  The first member of both structures is an identifier. It can be any positive integer greater than or equal to 0x8000. Values less than 0x8000 are reserved for use by XPanels. The second member is a human-readable description. For controls, this string is used as a label that appears next to the control on the panel. The third member identifies the class of the control or the data type of the value. In most cases, your control array and data description array will be parallel, and the value IDs in the data description will match the control IDs in the control array. But some control types don't have an associated value, and you might declare some values to XPanels that aren't directly associated with any control. Control Types The following definitions list the control class (the string that goes in the `ctrlclass` field of the LWXPanelControl), the data type of the control's value (the string that goes in the `datatype` field of the LWXPanelDataDesc), and the C equivalent (the kind of variable your plug-in stores the value in). The definitions will often refer to hints and callbacks, both of which are described in later sections. `"string" : "string" : char[]` A text edit field. `"integer" : "integer" : int` An integer edit field. `"float" : "float" : double` An edit field for floating-point numbers. Variations on the floating-point control type are summarized in the following table. Controls that include envelope (E) and texture (T) buttons use variant parameters as their underlying data type.
  `"float"` | `"float"` | `double`
  `"float3"` | `"float3"` | `double[3]`
  `"float-env"` | `"float-env"` | `double[]` (vparm)
  `"float3-env"` | `"float3-env"` | `double[][3]` (vparm)
  `"distance"` | `"distance"` | `double`
  `"distance3"` | `"distance3"` | `double[3]`
  `"distance-env"` | `"distance-env"` | `double[]` (vparm)
  `"distance3-env"` | `"distance3-env"` | `double[][3]` (vparm)
  `"percent"` | `"percent"` | `double`
  `"percent3"` | `"percent3"` | `double[3]`
  `"percent-env"` | `"percent-env"` | `double[]` (vparm)
  `"percent3-env"` | `"percent3-env"` | `double[][3]` (vparm)
  `"angle"` | `"angle"` | `double`
  `"angle3"` | `"angle3"` | `double[3]`
  `"angle-env"` | `"angle-env"` | `double[]` (vparm)
  `"angle3-env"` | `"angle3-env"` | `double[][3]` (vparm)
  `"color"` | `"color"` | `double[3]`
  `"color-env"` | `"color-env"` | `double[][3]` (vparm)
  `"time"` | `"time"` | `double`
Distance controls display units; their internal values are in meters. Percent controls display percentages; their internal values are the percent values divided by 100 (100% is 1.0). Angle controls display angles in degrees and store them in radians. Times are stored as elapsed seconds, but are displayed in the units selected by the user elsewhere in LightWave®'s interface. `"vButton"` A button. XPanels calls the control's button click callback whenever the user presses the button. `"iBoolean" : "integer" : int` A checkbox. `"iSlider" : "integer" : int "iSliderText" : "integer" : int` A slider (a thumb button that can be dragged within a horizontal track). Use the `XpMIN` and `XpMAX` hints to define the range of the slider. The `Text` version includes an integer edit field. `"iChoice" : "integer" : int` An array of radio buttons (mutually exclusive boolean buttons). The value is a 0-based index into the list of choices. To initialize the choices, use the `XpSTRLIST` hint. `"axis" : "axis" : 0, 1, 2` Radio buttons for selecting X, Y or Z. `"iPopChoice" : "integer" : int` A scrolling popup menu. The value is a 0-based index. You can initialize a popup with the `XpSTRLIST` hint and a static array of strings, or the `XpPOPFUNCS` hint and popup item count and name callbacks. `"vPopCmd"` A popup menu that works like a multiple-choice button. Your popup command callback receives a 0-based index. `"sPresetText" : "string" : char[]` Combines a string edit field and a popup menu. The user can type into the edit field or fill the field with the value associated with one of the presets named in the menu. `"sFileName" : "string" : char[]` Combines a string edit field and a button that opens the file dialog. Use the `XpXREQCFG` macro to set the mode (load or save), the title string and the file type filter. `"iChoTransform" : "integer" : int "iPopTransform" : "integer" : int` Like iChoice and iPopChoice controls, but the value isn't the menu index. It is instead the value of an array element referenced by the index. The array contains values that are more useful to your plug-in than the 0, 1, 2... indexes into the menu. For the `i`-th menu item, the value is `map[i]`, where `map[]` is an integer array associated with the control using the `XpCHOXFORM` or `XpPOPXFORM` hints. `"dThumbnail"` A rectangular area that you can draw on using the drawing functions. Thumbnails generate mouse events. The user can click, double-click, or drag out a rectangular selection. `"sInfo" : "string" : char[]` A read-only text field. Hints The `hint` function accepts as one of its arguments an array of panel-building commands, called hints. These are packaged as macros defined in the `lwxpanel.h` header file. The macros are used as initializers for the hint array passed to `hint`. For example,
       static LWXPanelHint hints[] = {
          XpLABEL( 0, "My Panel Title" ),
          XpSTRLIST( MY_POP, choices_array ),
          ...
  There are currently over 50 hint macros. `XpH( x )` Cast the value to an LWXPanelHint. This is just a way to get values of different types into a single array. `XpEND` Terminate the hint array. Some macros are also followed by a sublist of hints which is terminated by `XpEND`. `XpCALL( hint_array )` Insert another hint array into this one. `XpLABEL( id, label )` Set the label string for a control or group. An ID of 0 sets the label for the panel. `XpVECLABEL( ctlID, labels )` Set the labels for each of the three elements of a vector control (integer3, float3, etc.). `labels` is an array of three strings. `XpSTRLIST( ctlID, strlist )` Set the string array for a popup control. `XpCLASS( id, class )` Change the class of a control. Hints previously applied to this control may be lost if they're incompatible with the new class. `XpADD( ctlID, class, valID )` Create a control. You can also create controls using the LWXPanelControl array passed to the `create` function and the LWXPanelDataDesc array passed to `describe`. `XpDELETE( id )` Remove a control from the panel. This doesn't remove the control's value from the data description. `XpCTRLCFG( ctlID, options )` Set class-specific option flags for a control. Currently this is only used by dThumbnail controls, which can be configured using the following bit flags combined using bitwise-or. `THUM_SNGL, THUM_SML, THUM_MED, THUM_LRG, THUM_XLG` Height of dThumbnail control `THUM_SQ, THUM_NTSC, THUM_35MM, THUM_PORT, THUM_LAND, THUM_WIDE, THUM_ANAW, THUM_EURO` Width of dThumbnail control given as aspect ratio with height `THUM_FULL` Width of dThumnail control is the full width of XPanel `THUM_BORDER_UP, THUM_BORDER_DOWN, THUM_BORDER_NONE` Sets the border around the thumbnail `XpXREQCFG( ctlID, mode, title, filter )` Set options for the file dialog opened by an sFileName control. The `mode` is one of the following.
      LWXPREQ_LOAD
      LWXPREQ_SAVE
      LWXPREQ_DIR
  The `title` is the string that will appear in the title bar of the dialog. The `filter` is a string that identifies the file type. It's the same string you'd pass to the File Type global. `XpFOCUS( id )` Identify the control that should receive focus when the panel is first displayed. An ID of 0 indicates the panel should use a default setting, usually the first editable text field. `XpVALUE( ctlID, valID )` Associate a control ID with a value ID. Ordinarily, a control and its value are implicitly bound together by having the same ID in the LWXPanelControl and LWXPanelDataDesc arrays passed to `create` and `describe`, but a control and value pair aren't required to share the same ID. `XpRESTORE( id ) XpRESTORE_() XpRESTORE_ON XpRESTORE_OFF` Define what happens to control values when the user presses the Cancel button in a modal `LWXP_VIEW` panel. By default, values are reset to what they were when the panel was opened. The `ON` and `OFF` macros set this behavior for all values, and the other two toggle the behavior for a single value or for a list of values. `XpLINK_( valID ) XpLINK( valID, link )` Link a value to another value, or to a list of values. Links create a dependency relationship. If the `link` value changes, then the dependent `valID` value is also updated. `XpENABLE_( valID ) XpENABLE_MAP_( valID, map ) XpENABLEMSG_( valID, msg ) XpENABLEMSG_MAP_( valID, map, msg )` Link the enable state of the controls in the trailing ID list to the `valID` value. The trailing ID list actually contains value IDs, and the control IDs are inferred from this. If the `valID` value is true (non-zero), the dependent controls are enabled, otherwise they're disabled. If you supply a map (an integer array containing boolean values), the enable state will be based on `map[value]` rather than on the value directly. If you supply a message string, it will be displayed whenever the user tries to manipulate a disabled control. The message typically explains why the control is disabled: "Sprinkles is only valid when the flavor is vanilla." `XpINTXFORM( ctlID, count, ilist ) XpPOPXFORM( ctlID, count, ilist ) XpCHOXFORM( ctlID, count, ilist )` Set the transform map for the control. Transform control classes such as iPopTrans and iChoTrans provide a mechanism for mapping the control's underlying integer value into a more useful value for the client. `ilist` is an array of 32-bit values that XPanels will substitute for the base value of the control. When the base value is 0, XPanels uses `ilist[0]`, and so on. `XpMIN( ctlID, min )` Set the minimum of a control's range. `min` is always an integer, as are the other range parameters in the following hints. `XpMAX( ctlID, max )` Set the maximum of a control's range. `XpSTEP( ctlID, step )` Set the increment of a range adjustment. `XpRANGE( ctlID, min, max, step )` Set all three range parameters. `XpHARDMINMAX( ctlID, bmin, bmax )` Enforce the range limits in the edit field component of a slider control. `bmin` and `bmax` are booleans that set or clear this for each end of the range. If the control is enveloped, the envelope values may still fall outside the limits. `XpCLRMINMAX( ctlID, bmin, bmax )` Remove a minimum or maximum set by `XpMIN`, `XpMAX` or `XpRANGE`. `XpSENS( ctlID, delta )` Set the sensitivity of a minislider. The delta scales the pixel to minislider translation. Larger deltas cause the minislider value to change more slowly. `XpTRACK( ctlID, track )` Indicate whether the control should generate intermediate (tracking) events. If the boolean track flag is true (non-zero), events will be generated for the control as long as the user manipulates it on the interface. In particular, components such as sliders and text fields will generate a constant stream of events to inform the client of user actions. If this is false, events are only generated after the user has set a new value. `XpIMMUPD_( ctlID ) XpIMMUPD( ctlID, dep )` Create an "immediate update" dependency relationship for a control, such as a slider, that can generate `LWXPEVENT_TRACK` events. Whenever the control is being modified by the user (and is generating tracking events), the dependent controls will be updated. `XpDESTROYNOTIFY( func )` Set the callback that XPanels will call after the panel has been destroyed. The argument points to an LWXPanelDestroyNotifyFunc. `XpCHGNOTIFY( func )` Set the callback that XPanels will call whenever a value is modified. The argument points to an LWXPanelChangeNotifyFunc. `XpBUTNOTIFY( ctlID, func )` Set the callback that XPanels will call when the button control is pressed. The argument points to an LWXPanelBtnClickFunc. `XpPOPCMDFUNC( ctlID, func )` Set the callback that XPanels will call when an item is selected in a popup control. The argument points to an LWXPanelPopCmdFunc. `XpPOPFUNCS( ctlID, countfunc, namefunc )` Set the callbacks that XPanels will call when the popup choice control is opened. The arguments point to an LWXPanelPopCntFunc and an LWXPanelPopNameFunc. The callbacks are an alternative to providing a static array of strings for the popup. `XpDRAWCBFUNC( ctlID, func )` Set the callback that XPanels will call when a drawable control needs to be drawn. The argument points to an LWXPanelControlDrawFunc. Currently this is restricted to use with dThumbnail controls. `XpZOOMCBFUNC( ctlID, func, rect )` Set the callback that XPanels will call when the user clicks and drags the mouse within the control. The function argument points to an LWXPanelControlZoomFunc. `rect` is a boolean that determines whether mouse dragging is reported. Currently this is only for dThumbnail controls. `XpALIAS_( aliasID )` Create a new alias group, or add controls, values or other aliases to an existing alias group. An alias group is just an ID with its own list of IDs. The groups created using the `ALIAS` tag define a logical grouping of IDs but otherwise do not have any default behaviour. Instead, alias group IDs are generally used as arguments to other panel hints. `XpUNALIAS_( aliasID )` Remove the IDs in the trailing list from the alias group. If the ID list is empty (this hint is followed immediately by `XpEND`), all the elements of the group are removed and the group is disbanded. `XpGROUP_( groupID )` Create a new group, or add the trailing list of IDs to an existing group. The trailing list may contain the IDs of controls, aliases, other groups, stacks or tabs. `XpORDER_( groupID )` Reorder the IDs in a group. If the group ID is 0, this reorders IDs for the panel. `XpSTACK_( groupID, valID ) XpSTACK_MAP_( groupID, valID, map )` Define a control stack. Only one control at a time is visible in a stack (the rest are "hidden underneath"). Which control is visible is determined by the `valID` value. The value must be of integer type. A value of 0 selects the first control in the group. If you supply a map (an integer array), the visible control depends on `map[value]` rather than the value directly. A value of -1 means that no control from this group should be visible. `XpTABS_( groupID )` Create a tab window. Additional tab windows will be created for the IDs in the trailing list. The text displayed on the tab is taken from the label assigned to the ID using the `XpLABEL` hint. `XpCTRLFRONT( ctlID )` Identify the tab that should be displayed on top of other tabs. By default, the first tab is on top. `XpORIENT( ctlID, orientation )` Set the control's orientation, where 0 is horizontal and 1 is vertical. The default is horizontal. Not all controls can be oriented. `XpLEFT( groupID ) XpLEFT_()` Attempt to left align the first control in a group or the trailing list. If possible, subsequent controls are moved up beside the left-aligned control. This hint is ignored for some control classes (but see the `XpNARROW` hint), and space constraints can also affect whether it can be applied. `XpNARROW( groupID ) XpNARROW_()` The client may override the default "move up" rules by indicating that the controls in the group or the trailing list are narrow. `XpDIVADD( id ) XpDIVADD_( id )` This suggests the panel should draw a divider after the control or group specified by the ID list. The hint has one fixed argument so that the client can specify one of the special divider locations, intended mostly for inline panels: 0 for the top of the panel, -1 for the bottom. `XpDIVREM( id ) XpDIVREM_( id )` This indicates that the panel should not place a divider after the control or group. The panel performs some built-in guesswork on divider placement. Typically, they're put at "transition points," examples of which include points between a standalone control and a group, between separate groups, and between a group and a tab group. It won't always be easy to determine the abstract location of a divider solely from its appearance. For example, a divider may appear to follow a control but actually follow the group to which the control belongs. `XpBORDER( type )` Suggests the kind of border the panel should be drawn with. Possible values are
      LWXPBDR_NONE
      LWXPBDR_UP
      LWXPBDR_DOWN
`XpDLOGTYPE( type )` Modal panels include buttons that allow the user to accept or cancel their input. This macro specifies which buttons will be added. The numbers in the following list are the values returned by the `post` function when the user dismisses the panel by pressing the corresponding button. `LWXPDLG_OKCANCEL` - OK 1, Cancel 0 (the default) `LWXPDLG_DONE` - Done 1 `LWXPDLG_OKONLY` - OK 1 `LWXPDLG_YESNO` - Yes 1, No 0 `LWXPDLG_YESNOALL` - Yes 1, No 0, Yes To All 2, Cancel 3 `LWXPDLG_YESNOCAN` - Yes 1, No 0, Cancel 3 `XpTEXTXFORMFUNC( ctlID, func )` Set the callback function that XPanel will call to transform between the text displayed in a control, and the text representing the actual value. The function argument points to an LWXPanelTextXFormFunc. The text transformation callback acts as a filter between the text representation of the control value used by XPanel, and the text that the user sees and enters. This can be used for the display and entry of custom units. The tag works with most control classes which display a value such as float, integer, angle3-env, etcetera. Callbacks Xpanels and its controls rely on callbacks to communicate with your plug-in. Except for the data get and set callbacks, you tell XPanels about them using hints. Data get/set
       typedef void *LWXPanelGetFunc (void *inst, unsigned int vid);
       typedef int   LWXPanelSetFunc (void *inst, unsigned int vid,
          void *value);
> Your get and set functions are passed as the third and fourth arguments to the `describe` function when you're creating an `LWXP_VIEW` panel. XPanels calls the get function to get a value from you. The function returns a pointer to the value. XPanels calls the set function to give you a value when it has changed. The set callback returns a refresh code indicating what, if any, redrawing should take place on the panel. The code can be one of the following.
>     LWXPRC_NONE
>     LWXPRC_DFLT
>     LWXPRC_DRAW
>     LWXPRC_FULL
Destroy event
       typedef void LWXPanelDestroyNotifyFunc (void *);
This is called after the panel has been destroyed. Provide one of these if you need to do any panel-specific cleanup. Use the `XpDESTROYNOTIFY` hint to set the callback. Value change event
       typedef void LWXPanelChangeNotifyFunc (LWXPanelID pan,
          unsigned int cid, unsigned int vid, int event_type);
> This is called when user interaction is changing the value of a control, and when your panel is receiving or losing the input focus. Use the `XpCHGNOTIFY` hint to set the callback. The event type is one of the following.
>     LWXPEVENT_TRACK
>     LWXPEVENT_VALUE
>     LWXPEVENT_HIT
>     LWXPEVENT_FOCUS
>     LWXPEVENT_LOSEFOCUS
Typically, `LWXP_FORM` panels use the `TRACK` and `VALUE` events to dynamically follow changes in the values of their controls, while `LWXP_VIEW` panels rely instead on their data set callback. Button click event
       typedef void LWXPanelBtnClickFunc (LWXPanelID pan, int cid);
Called when the user clicks a button control. Use the `XpBUTNOTIFY` hint to set the callback. Popup command
       typedef void LWXPanelPopCmdFunc (LWXPanelID pan, int cid, int cmd);
Called when the user selects an item from a popup menu. Use the `XpPOPCMDFUNC` hint to set the callback. Popup choice
       typedef int         LWXPanelPopCntFunc  (void *userdata);
       typedef const char *LWXPanelPopNameFunc (void *userdata, int idx);
Called when a popup is displayed. The count callback returns the number of items in the menu. The name callback is then called for each item and returns the string to be displayed for the item. Use the `XpPOPFUNCS` hint to set these callbacks. Draw event
       typedef void LWXPanelControlDrawFunc (LWXPanelID pan,
          unsigned int cid, LWXPDrAreaID reg, int w, int h);
Called when a drawable control (a dThumbnail) needs to be redrawn. Use the `XpDRAWCBFUNC` hint to set the callback. Zoom event
       typedef void LWXPanelControlZoomFunc (LWXPanelID pan,
          unsigned int cid, int x, int y, int *region, int clickcount );
Called when the user clicks and drags the mouse within the control (a dThumbnail). Use the `XpZOOMCBFUNC` hint to set the callback. Text transformation
       typedef const char *LWXPanelTextXFormFunc (LWXPanelID pan, unsigned int cid,
          const char *text, LWXPanelTextXFormMode mode );
> Called to transform a string representing the value of a control to a string to be displayed, or to transform a string entered by the user into a string representing the value of the control. The mode is one of:
>     LWXPTEXTXFORM_TODISPLAY
>     LWXPTEXTXFORM_FROMDISPLAY
When transforming to display, the given text is the text representation of the value of the control. The callback returns a pointer to a string which is to be displayed. When transforming from display, the given text is what is shown in the control, typically as a result of the user typing into it. The callback then returns a pointer to a string which is the text that XPanel will then parse to obtain the control's value. The callback may return NULL, in which case the same text as given to the callback will be used. Drawing Functions Drawing is limited to contexts in which a valid LWXPDrAreaID is available, currently the draw callback of a thumbnail control.
       typedef struct st_LWXPDrawFuncs {
          void (*drawPixel)    (LWXPDrAreaID, int c, int x, int y );
          void (*drawRGBPixel) (LWXPDrAreaID, int r, int g, int b, int x,
                                  int y );
          void (*drawLine)     (LWXPDrAreaID, int c, int x, int y, int x2,
                                  int y2 );
          void (*drawBox)      (LWXPDrAreaID, int c, int x, int y, int w,
                                  int h );
          void (*drawRGBBox)   (LWXPDrAreaID, int r, int g, int b, int x,
                                  int y, int w, int h );
          void (*drawBorder)   (LWXPDrAreaID, int indent, int x, int y,
                                  int w, int h );
          int  (*textWidth)    (LWXPDrAreaID, char *s );
          int  (*textHeight)   (LWXPDrAreaID, char *s );
          void (*drawText)     (LWXPDrAreaID, char *s, int c, int x, int y );
       } LWXPDrawFuncs;
`drawPixel( drawid, color, x, y ) drawRGBPixel( drawid, r, g, b, x, y )` Draw a pixel. The coordinates are relative to the upper-left corner of the drawing area. The color is specified as one of the palette colors defined in lwpanel.h or as levels of red, green and blue between 0 and 255. `drawLine( drawid, color, x1, y1, x2, y2 )` Draw a line connecting the endpoints. `drawBox( drawid, color, x, y, w, h ) drawRGBBox( drawid, r, g, b, x, y, w, h )` Draw a solid rectangle. `drawBorder( drawid, indent, x, y, w, h )` Draw a rectangular border similar to the ones use to mark the borders of controls. The `indent` is the thickness of the border. If `h` is 0, `drawBorder` creates a horizontal divider. `tw = textWidth( drawid, string ) th = textHeight( drawid, string )` The pixel width and height of the text in the font used by panels. `drawText( drawid, string, color, x, y )` Render a line of text. Example Many of the SDK samples (including blotch, hotvideo, kepler, mandfilt, NoisyChan, specular, and txchan) use XPanels for their interfaces. xpanchan, xpanlgen and xpanxtreme were written specifically to demonstrate XPanels features.