# Programming with Direct Graphics

# Using Direct Graphics in Draw Widgets

By default, draw widgets use IDL Direct graphics. (To create a draw widget that uses Object graphics, set the GRAPHICS_LEVEL keyword to WIDGET_DRAW equal to two..) Once created, draw widgets using Direct graphics are used in the same way as standard Direct graphics windows created using the WINDOW procedure.

All IDL Direct graphics windows are referred to by a window number. Unlike windows created by the WINDOW procedure, the window number of a Direct graphics draw widget cannot be assigned by the user. In addition, the window number of a draw widget is not assigned until the draw widget is actually realized, and thus cannot be returned by WIDGET_DRAW when the widget is created. Instead, you must use the WIDGET_CONTROL procedure to retrieve the window number, which is stored in the value of the draw widget, after the widget has been realized.

Unlike normal graphics windows, creating a draw widget does not cause the current graphics window to change to the new widget. You must use the WSET procedure to explicitly make the draw widget the current graphics window. The following IDL statements demonstrate the required steps:

;Create a base widget.

base = WIDGET_BASE()

;Attach a 256 x 256 draw widget.

draw = WIDGET_DRAW(base, XSIZE = 256, YSIZE = 256)

;Realize the widgets.

WIDGET_CONTROL, /REALIZE, base

;Obtain the window index.

WIDGET_CONTROL, draw, GET_VALUE = index

;Set the new widget to be the current graphics window

WSET, index

If you attempt to get the value of a draw widget before the widget has been realized, WIDGET_CONTROL returns the value -1, which is not a valid index.

## Example Using APP_SCROLL with Direct Graphics

We can easily rework the previous example to use the APP_SCROLL keyword rather than the SCROLL keyword. Using APP_SCROLL has the following consequences:

1. IDL no longer automatically displays the appropriate portion of the image when the scroll bars are adjusted. As a result, we must add code to our event-handling procedure to check for the viewport event and display the appropriate part of the image. Here is the new event-handler routine:

   ; Event-handler routine.

   PRO draw_app_scroll_event, ev

   COMMON app_scr_ex, image

   IF (ev.TYPE EQ 3) THEN TVSCL, image, 0-ev.X, 0-ev.Y

   END

   First, notice that since we need access to the image array in both the widget creation routine and the event handler, we place the array in a COMMON block. This is appropriate since the image data itself is not altered by the widget application.

   Second, we check the `TYPE` field of the event structure to see if it is equal to `3`, which is the code for a viewport event. If it is, we use the values of the `X` and `Y` fields of the event structure as the Position arguments to the TVSCL routine to display the appropriate portion of the image array.

2. We must add the COMMON block to the widget creation routine.
3. We change the call to WIDGET_DRAW to include the APP_SCROLL keyword rather than the SCROLL keyword. In this context, the values of the XSIZE and YSIZE keywords are interpreted as the size of the virtual drawable area, rather than the actual drawable area.

The modified example is included in the file `draw_app_scroll.pro` in the `examples/doc/widgets` subdirectory of the IDL distribution. Run this example procedure by entering `draw_app_scroll` at the IDL command prompt or view the file in an IDL Editor window by entering `.EDIT draw_app_scroll.pro`.

On the surface the two examples appear identical. The difference is that the example using APP_SCROLL uses only the memory necessary to create the smaller drawable area described by the size of the viewport, whereas the example using SCROLL uses the memory necessary to create the full drawable area described by the XSIZE and YSIZE keywords. While the example image is not so large that this makes much difference, if the image contained several hundred million pixels rather than a few hundred thousand, the memory saving could be significant.