The following example adds the Motif ArrowButton widget to UNIX IDL in the form of an IDL program named widget_arrowb.pro.
The primary user interface to our arrow button widget is the WIDGET_ARROWB function. It presents an interface much like any of the built in WIDGET_* functions provided by IDL. WIDGET_ARROWB uses the MAKE_DLL procedure, and the AUTO_GLUE keyword to CALL_EXTERNAL to automatically build and load the C code required for this widget. This building and loading process is transparent to the IDL user, requiring only that you have a C compiler installed on your system. All the user has to do to use an arrow button widget is to call WIDGET_ARROWB
The WIDGET_ARROWB widget acts like a normal pushbutton. Events are sent when the button is pressed (VALUE=1) and released (VALUE=0). If the USE_OWN_SIZE keyword is set to zero, IDL performs its default sizing on the stub widget. A non-zero value causes a special routine provided by the WIDGET_ARROWB implementation to be registered to handle such sizing.
All of the code used in this example is available in the external/widstub directory of the UNIX IDL distribution. To run it, execute the following statements from IDL:
PUSHD, FILEPATH(’’, SUBDIRECTORY=[’external’,’widstub’])
WIDGET_ARROWB_TEST
POPD
When running WIDGET_ARROWB_TEST, you can specify the VERBOSE keyword to show you the compilation and linking steps it takes to build the sharable library from the C code. The use of PUSHD and POPD are due to the fact that your IDL search path (!PATH) is unlikely to have the directory containing these examples in it. PUSHD changes your working directory to the location where these files are found, and POPD restores it to its original location afterwards.
The IDL Program for WIDGET_ARROWB
The following text is the IDL program for WIDGET_ARROWB. It is found in the file named WIDGET_ARROWB.PRO:
FUNCTION WIDGET_ARROWB, parent, use_own_size, UVALUE=uvalue, $
VERBOSE=verbose, _EXTRA=extra
common WIDGET_ARROWB_BLK, shlib
build_lib = N_ELEMENTS(shlib) eq 0
IF (not build_lib) THEN build_lib = not FILE_TEST(shlib, /READ)
IF (build_lib) THEN BEGIN
arrowb_dir = FILEPATH(’’,SUBDIRECTORY=[’external’,’widstub’])
MAKE_DLL,’widget_arrowb’, ’widget_arrowb’, $
DLL_PATH=shlib, INPUT_DIR=arrowb_dir, $
VERBOSE=verbose,SHOW_ALL_OUTPUT=verbose
ENDIF
l_parent = LONG(parent)
l_use_own_size = $
(n_elements(use_own_size) eq 0) ? 0L: LONG(use_own_size)
result = WIDGET_STUB(parent, _extra=extra)
IF (N_ELEMENTS(uvalue) ne 0) then $
WIDGET_CONTROL, result, set_UVALUE=uvalue
JUNK = CALL_EXTERNAL(shlib, ’widget_arrowb’,l_parent,result,$
l_use_own_size, VALUE=[1, 1, 1], /AUTO_GLUE)
RETURN, result
END
The C Program for widget_arrowb.c
The C code invoked by the call to CALL_EXTERNAL in the above IDL code is contained in a file named widget_arrowb.c This file can be found in the widstub subdirectory of the external subdirectory of the IDL distribution. The contents of this file are shown below:
/*
* widget_arrowb.c - This file contains C code to be called from
* UNIX IDL via CALL_EXTERNAL. It uses the IDL stub widget to add
* a Motif ArrowButton to an IDL created widget hierarchy. The
* button issues a WIDGET_STUB_EVENT every time the button is
* released.
*
* While this code is Motif-centric, the principles apply across
* platforms and could be adapted to Microsoft Windows.
*/
#include <stdio.h>
#include <X11/keysym.h> /* Keysyms for text widget events */
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <Xm/ArrowB.h>
#include "idl_export.h"
/*ARGSUSED*/
static void arrowb_CB(Widget w, caddr_t client_data,
caddr_t call_data)
{
char *rec
XmArrowButtonCallbackStruct *abcs
IDL_WidgetStubLock(TRUE)
if (rec = IDL_WidgetStubLookup((unsigned long) client_data))
{
abcs = (XmArrowButtonCallbackStruct *) call_data
IDL_WidgetIssueStubEvent(rec, abcs->reason == XmCR_ARM)
}
IDL_WidgetStubLock(FALSE)
}
static void arrowb_size_func(IDL_ULONG stub, int width,
int height)
{
char *stub_rec
unsigned long t_id, b_id
char buf[128]
IDL_WidgetStubLock(TRUE)
if (stub_rec = IDL_WidgetStubLookup(stub)) {
IDL_WidgetGetStubIds(stub_rec, &t_id, &b_id)
sprintf(buf, "Setting WIDGET %d to width %d and height %d",
stub, width, height)
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, buf)
XtVaSetValues((Widget) b_id, XmNwidth, width, XmNheight,
height, NULL)
}
IDL_WidgetStubLock(FALSE)
}
int widget_arrowb(IDL_LONG parent, IDL_LONG stub, IDL_LONG
use_own_size_func)
{
Widget parent_w
Widget stub_w
char *parent_rec
char *stub_rec
unsigned long t_id, b_id
IDL_WidgetStubLock(TRUE)
if ((parent_rec = IDL_WidgetStubLookup(parent))
&& (stub_rec = IDL_WidgetStubLookup(stub))) {
/* Bottom widget of parent is parent to arrow button */
IDL_WidgetGetStubIds(parent_rec, &t_id, &b_id)
parent_w = (Widget) b_id
stub_w = XtVaCreateManagedWidget("arrowb"
xmArrowButtonWidgetClass,
parent_w, NULL)
IDL_WidgetSetStubIds(stub_rec, (unsigned long) stub_w,
(unsigned long) stub_w)
XtAddCallback(stub_w, XmNarmCallback,
(XtCallbackProc) arrowb_CB, (XtPointer) stub)
XtAddCallback(stub_w, XmNdisarmCallback,
(XtCallbackProc) arrowb_CB, (XtPointer) stub)
if (use_own_size_func)
IDL_WidgetStubSetSizeFunc(stub_rec, arrowb_size_func)
}
IDL_WidgetStubLock(FALSE)
return stub
}
An IDL Program to Test the External Widget
This is an IDL widget program to test the ARROWB widget. This program is found in the file widget_arrowb_test.pro in the IDL distribution:
PRO widget_arrowb_test_event, ev
WIDGET_CONTROL, GET_UVALUE=val, ev.id
IF (val EQ 0) THEN BEGIN
WIDGET_CONTROL, /DESTROY, ev.top
ENDIF ELSE BEGIN
HELP, /STRUCT, ev
IF (ev.value EQ 1) THEN BEGIN
WIDGET_CONTROL, val, SET_VALUE=’New label string’
tmp = WIDGET_INFO(ev.id, /GEOMETRY)
WIDGET_CONTROL, XSIZE=tmp.xsize+25, $
YSIZE=tmp.ysize+25, ev.id
ENDIF
ENDELSE
END
PRO widget_arrowb_test, VERBOSE=verbose
a = WIDGET_BASE(/COLUMN)
b = WIDGET_BUTTON(a, VALUE=’Done’, UVALUE=0)
label = WIDGET_LABEL(a, VALUE=’A label’)
arrow_w = WIDGET_ARROWB(a, 0, XSIZE=100, YSIZE=100, $
UVALUE=label, VERBOSE=verbose)
arrow_w = WIDGET_ARROWB(a, 1, XSIZE=100, YSIZE=50, $
UVALUE=label, VERBOSE=verbose)
WIDGET_CONTROL,/REAL, a
xmanager, ’WIDGET_ARROWB_TEST’, a, /NO_BLOCK
end