Widget Sizing

This section explains how IDL widgets size themselves, widget geometry concepts, and how to explicitly size and position widgets.

Widget Geometry Terms and Concepts

Widget size and layout is determined by many interrelated factors. In the following discussion, the following terms are used:

How Widget Geometry is Determined

IDL uses the following rules to determine the geometry of a widget:

Dynamic Resizing

Realized widgets, by default, do not automatically resize themselves when their values change. This is true whether the widget was created with an explicit size or the widget was allowed to size itself naturally. This behavior makes it easy to create widget layouts that don't change size too frequently or "flicker" due to small changes in a widget's natural size.

This default behavior can be changed for label, button, and droplist widgets. Set the DYNAMIC_RESIZE keyword to WIDGET_LABEL, WIDGET_BUTTON, or WIDGET_DROPLIST to make a widget that automatically resizes itself when its value changes. Note that the XSIZE and YSIZE keywords should not be used with DYNAMIC_RESIZE. Setting explicit sizing values overrides the dynamic resize property and creates a widget that will not resize itself.

Explicitly Specifying the Size and Location of Widgets

The XSIZE (and SCR_XSIZE), YSIZE (and SCR_YSIZE), XOFFSET, and YOFFSET keywords, when used with a standard base widget parent (a base created without the COLUMN or ROW keywords—also called a "bulletin board" base), allow you to specify exactly how the child widgets should be positioned. Sometimes this is a very useful option. However, in general, it is best to avoid this style of programming. Although these keywords are usually honored, they are merely hints to the widget toolkit and might be ignored.

Note
Draw widgets are the exception to this recommendation. In almost all cases, you will want to set the size of draw widgets explicitly, using the sizing keywords.

Explicitly specifying the size and offset makes a program inflexible and unable to run gracefully on various platforms. Often, a layout of this type will look good on one platform, but variations in screen size and how the toolkit works will cause widgets to overlap and not look good on another platform. The best way to handle this situation is to use nested row and column bases to hold the widgets and let the widgets arrange themselves. Such bases are created using the COLUMN and ROW keywords to the WIDGET_BASE function.

Sizing Keywords

When explicitly setting the size of a widget, IDL allows you to control three aspects of the size:

The following code shows an example of the WIDGET_DRAW command:

draw = WIDGET_DRAW(base, XSIZE=384, YSIZE=384,$ 
  X_SCROLL_SIZE=192, Y_SCROLL_SIZE = 192, SCR_XSIZE=200) 

This results in the following:

Figure 3-7: Visual description of widget sizes.

bldwid06.jpg

In this case, the XSIZE and YSIZE keywords set the virtual size to 384 x 384 pixels. The X_SCROLL_SIZE and Y_SCROLL_SIZE keywords set the viewport size to 192 x 192 pixels. Finally, the SCR_XSIZE keyword overrides the X_SCROLL_SIZE keyword and forces the screen size of the widget (in the X-dimension) to 200 pixels, including the scroll bar.

Controlling Widget Size after Creation

A number of keywords to the WIDGET_CONTROL procedure allow you to change the size of a widget after it has been created. (You will find a list of the keywords to WIDGET_CONTROL that apply to each type of widget at the end of the widget creation routine documentation.) Note that keywords to WIDGET_CONTROL may not control the same parameters as their counterparts associated with widget creation routines. For example, while the XSIZE and YSIZE keywords to WIDGET_DRAW control the virtual size of the draw widget, the XSIZE and YSIZE keywords to WIDGET_CONTROL (when called with the widget ID of a draw widget) control the viewport size of the draw widget. See the IDL Reference Guide for details.

Units of Measurement

You can specify the unit of measurement used for most widget sizing operations. When using a widget creation routine, or when using WIDGET_CONTROL or WIDGET_INFO, set the UNITS keyword equal to 0 (zero) to specify that all measurements are in pixels (this is the default), to 1 (one) to specify that all measurements are in inches, or to 2 (two) to specify that all measurements are in centimeters.

Note
The UNITS keyword does not affect all sizing operations. Specifically, the value of UNITS is ignored when setting the XSIZE or YSIZE keywords to WIDGET_LIST, WIDGET_TABLE, or WIDGET_TEXT.

Finding the Size of the Screen

When creating the top-level base for an application, sometimes it is useful to know the size of the screen. This information is available via the GET_SCREEN_SIZE function. GET_SCREEN_SIZE returns a two-element floating-point array specifying the size of the screen, in pixels. See "GET_SCREEN_SIZE" (IDL Reference Guide) for details.

Preventing Layout Flicker

After a widget hierarchy has been realized, adding or destroying widgets in that hierarchy causes IDL to recalculate and set new geometries for every widget in the hierarchy. When a number of widgets are added or destroyed, these calculations occur between each change to the hierarchy, resulting in unpleasant screen "flashing" as the user sees a brief display of each intermediate widget configuration. This behavior can be eliminated by using the UPDATE keyword to WIDGET_CONTROL.

The top-level base of every widget hierarchy has an UPDATE attribute that determines whether or not changes to the hierarchy are displayed on screen. Setting UPDATE to 0 turns off immediate updates and allows you to make a large number of changes to a widget hierarchy without updating the screen after each change. After all of your changes have been made, setting UPDATE to 1 causes the final widget configuration to be displayed on screen.

For example, consider the following main-level program that realizes an unmapped base, then adds 200 button widgets to the previously-realized base:

time = SYSTIME(1) 
b = WIDGET_BASE(/COLUMN, XSIZE=400, YSIZE=400, MAP=0) 
WIDGET_CONTROL, b, /REALIZE 
FOR i = 0, 200 DO button = WIDGET_BUTTON(b, VALUE=STRING(i)) 
WIDGET_CONTROL, b, /MAP 
PRINT, 'time used: ', SYSTIME(1) - time 
END 

This program takes approximately 1.5 seconds to run on a Red Hat linux workstation. If the base had been mapped, the user would see the base "flashing" as each button was added to the base. Altering the example to use the UPDATE keyword reduces the execution time to approximately 0.1 seconds and eliminates the flashing:

time = SYSTIME(1) 
b = WIDGET_BASE(/COLUMN, XSIZE=400, YSIZE=400, MAP=0) 
WIDGET_CONTROL, b, /REALIZE, UPDATE=0 
FOR i = 0, 200 DO button = WIDGET_BUTTON(b, VALUE=STRING(i)) 
WIDGET_CONTROL, b, /MAP, /UPDATE 
PRINT, 'time used: ', SYSTIME(1) - time 
END 

Note
Do not attempt to resize a widget on the Windows platform while UPDATE is turned off. Doing so may prevent IDL from updating the screen properly.