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:
- Geometry: The size and position of a widget.
- Natural Size: The natural, or implicit, size of a widget is the size a widget has if no external constraints are placed on it. For example, a label widget has a natural size that is determined by the size of the text it is displaying and space for margins. These values are influenced by such things as the size of the font being displayed and characteristics of the low-level (i.e., operating-system level) widget or control used to implement the IDL widget.
- Explicit Size: The explicit, or user-specified, size of a widget is the size set when an IDL programmer specifies one of the size keywords to an IDL widget creation function or WIDGET_CONTROL.
Note
To retrieve information about the geometry of an existing widget, use the GEOMETRY keyword to the WIDGET_INFO function.
How Widget Geometry is Determined
IDL uses the following rules to determine the geometry of a widget:
- The explicit size of a widget, if one is specified, takes precedence over the natural size. That is, the user-specified size is used if available.
- If an explicit size is not specified, the natural size of the widget—at the time the widget is realized—is used. Once realized, the size of a widget does not automatically change when the value of the widget changes, unless the widget's dynamic resize property has been set. Dynamic resizing is discussed in more detail below. Note that any realized widget can be made to change its size by calling WIDGET_CONTROL with any of the sizing keywords.
- Children of a "bulletin board" base (i.e., a base that was created without setting the COLUMN or ROW keywords) have an offset of (0,0) unless an offset is explicitly specified via the XOFFSET or YOFFSET keywords.
- The offset keywords to widgets that are children of ROW or COLUMN bases are ignored, and IDL calculates the offsets to lay the children out in a grid. This calculation can be influenced by setting any of the ALIGN or BASE_ALIGN keywords when the widgets are created.
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 virtual size is the size of the potentially viewable area of the widget. The virtual size may be larger than the actual viewable area on your screen. The virtual size of a widget is determined by either the widget's value, or the XSIZE and YSIZE keywords to the widget creation routine.
- The viewport size is the size of the viewable area on your screen. If the viewport size is smaller than the virtual size, scroll bars may be present to allow you to view different sections of the viewable area. When creating widgets for which scroll bars are appropriate, you can add scroll bars by setting the either SCROLL keyword or the APP_SCROLL keyword to the widget creation routine. (For information on the difference, see Scrolling Draw Widgets.) You can explicitly set the size of the viewport area using the X_SCROLL_SIZE and Y_SCROLL_SIZE keywords when creating base, draw, and table widgets.
- The screen size is the size of the widget on your screen. You can explicitly specify a screen size using the SCR_XSIZE and SCR_YSIZE keywords to the widget creation routine. Explicitly-set viewport sizes (set with X_SCROLL_SIZE or Y_SCROLL_SIZE) are ignored if you specify the screen 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:
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.
