Additional Topics > External Development Guide > Adding External Widgets to IDL > IDL and External Widgets

# IDL and External Widgets

This topic describes stub widgets, an IDL widget type not documented in the main IDL online help. Stub widgets allow CALL_EXTERNAL, LINKIMAGE, DLM, and Callable IDL users to add their own widgets to IDL widget hierarchies.

This feature depends on your system providing the window system libraries used by IDL (particularly the Motif libraries under UNIX) as sharable libraries. It will not work with versions of IDL that statically link against the window system libraries.

The next two sections describe IDL’s WIDGET_STUB function and changes to WIDGET_CONTROL when used with WIDGET_STUB. “Functions for Use with Stub Widgets” describes support functions that can be called from your external code to manipulate stub widgets. “Internal Callback Functions” describes how to make stub widgets generate IDL widget events. Finally, “UNIX WIDGET_STUB Example: WIDGET_ARROWB” illustrates the use of stub widgets with an external program.

Note: Although WIDGET_STUB can be used under Windows, this feature is primarily of interest on UNIX systems. Under Windows we recommend the use of the WIDGET_ACTIVEX functionality, which allows you to use ActiveX controls with IDL without requiring external programming.

## WIDGET_STUB

The WIDGET_STUB function creates a widget record that contains no actual underlying widgets. Stub widgets are place holders for integrating external widget types into IDL. Events from those widgets can then be processed in a manner consistent with the rest of the IDL widget system.

First, the programmer calls WIDGET_STUB to create the widget, and then uses CALL_EXTERNAL to call additional custom code to handle the rest. A number of internal functions are provided to manipulate widgets from this custom code. See “Functions for Use with Stub Widgets”for more information.

The returned value of this function is the widget ID of the newly-created stub widget.

### Calling Sequence

Result = WIDGET_STUB(Parent)

### Arguments

#### Parent

The widget ID of the parent widget. Stub widgets can only have bases or other stub widgets as their parents.

### Keywords

The following keywords are accepted by WIDGET_STUB and work the same as for other widget creation functions:

- EVENT_FUNC
- EVENT_PRO
- FUNC_GET_VALUE
- GROUP_LEADER
- KILL_NOTIFY
- NO_COPY
- PRO_SET_VALUE
- SCR_XSIZE
- UVALUE
- XOFFSET
- XSIZE
- YOFFSET
- YSIZE

## WIDGET_CONTROL/WIDGET_STUB

The WIDGET_CONTROL procedure has some differences and limitations when used with WIDGET_STUB, described below.

### Keywords

Only the most general keywords are allowed with WIDGET_CONTROL when used with stub widgets. All other keywords are ignored. Here is a list of those keywords that behave identically with all widgets including stub widgets:

- BAD_ID
- CLEAR_EVENTS
- EVENT_FUNC
- EVENT_PRO
- FUNC_GET_VALUE
- GET_UVALUE
- GROUP_LEADER
- HOURGLASS
- ICONIFY
- KILL_NOTIFY
- MANAGED
- NO_COPY
- PRO_SET_VALUE
- RESET
- SET_UVALUE
- SHOW
- TIMER
- TLB_GET_OFFSET
- TLB_GET_SIZE
- TLB_SET_TITLE
- TLB_SET_XOFFSET
- TLB_SET_YOFFSET
- XOFFSET
- YOFFSET

The following keywords also work with stub widgets, but require additional commentary:

#### DESTROY

When a widget hierarchy containing stub widgets is destroyed, the following steps are taken:

- The lower-level code that deals with the system toolkit destroys any real widgets currently used by the stub widgets.
- All IDL widget records are added to the free list for re-use.
- Any requested KILL_NOTIFY callbacks are called.

You should register KILL_NOTIFY callbacks on the topmost stub widget in each widget subtree. Remember that the actual widgets are gone before the callbacks are issued, so don’t attempt to access them. However, the callback provides an opportunity to clean up any related resources used by the widget.

#### MAP, REALIZE, and SENSITIVE

These keywords cause the toolkit-specific, lower layer of the IDL widgets implementation to be called. In the process of satisfying the specified request, any real widgets used by the stub widgets will be processed, along with the ones created by the non-stub widgets, in the usual way. Any additional processing must be provided via CALL_EXTERNAL.

#### XSIZE, SCR_XSIZE, YSIZE, and SCR_YSIZE

These keywords inform IDL how large the stub widget is expected to be. This information is necessary for IDL to calculate sizes and offsets of the surrounding widgets.

IDL tries to do something reasonable with these requests but, without knowledge of the actual widget being manipulated, it is possible that the results will not be satisfactory. In such cases, IDL_WidgetStubSetSizeFunc() can be used to specify a routine that IDL can call to perform the necessary sizing for your stub widget.

## Functions for Use with Stub Widgets

The following functions present a highly simplified interface to the stub widget class that gives the user enough access to IDL widget internals to make the stub widget work while hiding the details of the actual implementation.

### IDL_WidgetStubLock()

#### Syntax

void IDL_WidgetStubLock(int set);

IDL event processing occurs asynchronously, so any code that manipulates widgets must execute in a protected region. This function is used to create such a region. Any code that manipulates widgets must be surrounded by two calls to IDL_WidgetStubLock() as follows:

IDL_WidgetStubLock(TRUE);

/* Do your widget stuff */

IDL_WidgetStubLock(FALSE);

### IDL_WidgetStubLookup()

#### Syntax:

char *IDL_WidgetStubLookup(IDL_ULONG id);

When IDL creates a widget, it returns an integer value to the caller of the widget creation function. Internally, however, IDL widgets are represented by a pointer to memory. IDL_WidgetStubLookup() is used to translate the user-level integer value to this memory pointer. All the other internal routines use the memory pointer to reference the widget.

`Id` is the integer returned at the user level. Your call to CALL_EXTERNAL should pass this integer to your C-level code for use with IDL_WidgetStubLookup() which translates the integer to the pointer.

If the specified id does not represent a valid IDL widget, this function returns NULL. This situation can occur if a widget was killed but its integer handle is still lingering somewhere.

### IDL_WidgetIssueStubEvent()

#### Syntax:

void IDL_WidgetIssueStubEvent(char *rec, LONG value);

Given a handle to the IDL widget, obtained via IDL_WidgetStubLookup(), this function queues a WIDGET_STUB_EVENT. Such an event is a structure that contains the three standard fields (`ID`, `TOP`, and `HANDLER`) as well as an additional field named `VALUE` that contains the specified value.

`VALUE` can provide a way to access additional information about the widget, possibly by providing a memory address to the information.

### IDL_WidgetSetStubIds()

#### Syntax:

void IDL_WidgetSetStubIds(char *rec, unsigned long t_id, unsigned long b_id);

IDL widgets are built out of one or more actual widgets. Every IDL widget carries two pointers that are used to locate the top and bottom real widget for a given IDL widget. This function allows you to set these top and bottom pointers in the stub widget for later use.

Since the actual pointer type differs from toolkit to toolkit, this function declares `t_id` (the top real widget) and `b_id` (the bottom real widget) as unsigned long, an integer data type large enough to safely contain any pointer. Use a C cast operator to handle the difference.

After calling WIDGET_STUB to create an IDL stub widget, you will need to use CALL_EXTERNAL to call additional code that creates the real widgets that represent the stub. Having done that, use IDL_WidgetSetStubIds() to save the top and bottom widget pointers.

### IDL_WidgetGetStubIds()

#### Syntax:

void IDL_WidgetGetStubIds(char *rec, unsigned long *t_id, unsigned long *b_id);

This function returns the top (`t_id`) and bottom (`b_id`) real widget pointers for any specified widget (not just stub widgets). When using these values for non-stub widgets, it is the caller’s responsibility to avoid damaging the IDL-created widgets in any way.

### IDL_WidgetStubSetSizeFunc()

#### Syntax:

void IDL_WidgetStubSetSizeFunc(char *rec,

IDL_WIDGET_STUB_SET_SIZE_FUNC func)

typedef void (* IDL_WIDGET_STUB_SET_SIZE_FUNC);

(IDL_ULONG id, int width, int height);

When IDL needs to set the size of a stub widget, it attempts to set the size of the bottom real widget to the necessary dimensions. Often, this is the desired behavior, but cases can arise where it would be better to handle sizing differently. In such cases, use IDL_WidgetStubSetSizeFunc() to register a function that IDL will call to do the actual sizing.