1458 Rate this article:
No rating

Using (New) Graphics in an IDL widget program, part I

Mark Alonzo
Here’s an example of embedding an IDL 8 (aka New) Graphics (NG) window in an IDL widget program with the WIDGET_WINDOW function. There’s quite a bit of code + explanation involved, so I’m breaking this example into two posts: I’ll go over the widget creation routine this week and the event handlers next week. Please download the final version of the program from here if you’d like to follow along with my explanation. Start the widget creation routine by reading some sample data included with the IDL distribution:
pro widget_window_ex1
   compile_opt idl2

   xsize = 80
   ysize = 100
   n_images = 57
   head = read_binary(file_which('head.dat'), $
      data_dims=[xsize,ysize,n_images])
The file head.dat is a flat binary file that holds 57 transverse MRI scans of Dave Stern’s head. Each image is 80 x 100 pixels. Next, declare a top-level base widget and use WIDGET_WINDOW to create a draw widget that embeds a NG window:
   wtop = widget_base( $
      /column, $
      title='NG event handling with IDL widgets')

   wdraw = widget_window(wtop, $
      xsize=500, $
      ysize=600, $
      mouse_wheel_handler='widget_window_ex1_mouse_wheel_event')
The MOUSE_WHEEL_HANDLER keyword acts as an analog to the combination of the EVENT_PRO and WHEEL_EVENTS keywords to WIDGET_DRAW. Here I’m using it to override the default NG user interaction with the scroll wheel (i.e., zooming). These events will be sent to the event handler WIDGET_WINDOW_EX1_MOUSE_WHEEL_EVENT (I like descriptive event handler names). All other NG events (e.g., panning, selection, etc.) will work in this window as they would by default. Finish the widget creation by 1) making a slider to index the images in the MRI stack, 2) realizing the widget hierarchy and 3) giving the draw widget the initial focus:
   windex = widget_slider(wtop, $
      title='Image index', $
      /drag, $
      value=0, $
      minimum=0, $
      maximum=n_images-1, $
      event_pro='widget_window_ex1_index_event')

   widget_control, wtop, /realize
   widget_control, wdraw, /input_focus
Note that the slider widget uses the traditional EVENT_PRO keyword to identify its event handler. Next, extract the NG window reference from the draw widget:
   widget_control, wdraw, get_value=w
This is analogous to getting the window index of a DG draw widget or the window object from an OG draw widget. Use the window reference w as the target for the IMAGE function to display the first image in the stack, enlarged by a factor of four:
   g = image(head[*,*,0], $
      current=w, $
      /interpolate, $
      title='MRI Image Stack: Transverse Plane', $
      name='head display')
   g.scale, 4.0, 4.0, 1.0
Note that I’ve set the NAME property in the call to IMAGE: this tags this NG visualization so I can retrieve its reference later (more on this here). I’ll use this in next week’s post. Next, set up a state variable to store information about the widget program that’ll be needed in the event handlers. In IDL 8, I like to use a hash as a state variable; I think it’s somewhat more readable than the pointer-referencing-a-structure technique.
   state = hash()
   state['image'] = head
   state['n_images'] = n_images
   state['index'] = 0
   state['index slider'] = windex
I’ve included the original image data, the number of images in the stack, the current image index and the widget identifier for the slider. Typically, we attach the state variable to the user value of the top-level base (TLB) widget, since the TLB is available in every event structure. When using WIDGET_WINDOW, however, we need a variation on this technique, since NG event handlers don’t accept the traditional IDL widget event structure. The technique that I’ve been using is to attach the state variable to the NG window's user value, then attach the NG window to the top-level base's user value. This ensures that state information is communicated to both the widget and NG event handlers.
   w.uvalue = state
   widget_control, wtop, set_uvalue=w
End the widget creation routine with a call to XMANAGER to register the program and start event handling:
   xmanager, 'widget_window_ex1', wtop, /no_block
end
Here’s a screenshot of the resulting widget interface from the Linux side of my laptop: A screenshot of the user interface for WIDGET_WINDOW_EX1 I’ll finish this program next week by looking at the widget event handlers and explaining how they hook into the interface.

1 comments on article "Using (New) Graphics in an IDL widget program, part I"

Paul

I have been looking at using the updated graphics doing rubber banding on areas. I am struggling with the fact that the image graphics can be selected ("blue handles") and can be rotated and zoomed when I don't want a user to be able to do this. Any suggestions?

Please login or register to post comments.