Example Interactive Box

This is a tutorial for new IDL users on how to make a simple interactive graphics box. A number of IDL techniques are covered and also some comments on program style. Extra details are given with new IDL users in mind.
Here is a copy of the routine for you to try. The routine is discussed in detail below.

What does this box routine to do?

This routine plots an elastic box on the graphics window. The box is made and controlled using the mouse. Move the cursor to one of the corners of the desired box, press and hold down the left mouse button. Then while holding the left button down move the mouse to one of the other corners of the desired box. Release the button to lock the box in place. If the box is not what is wanted repeat the process for a new box. Press the middle button to exit and accept the box, or the right button to exit and reject the box.

IDL techniques and routines illustrated

Programming style

Program neatness makes it easier to read and understand. Use lots of white space (spaces, tabs, blank lines). There is no penalty in execution time since all the spaces are compiled away. The minor additional disk space is well worthwhile.

I don't normally spend a lot of effort to avoid gotos, especially for quick and dirty routines. But for simple cases such as this they are easy to avoid by using the right IDL loop statement. Remember, Whiles test at the front, Repeats test at the end of the loop.

Several types of comment statements make sense. Section divider type comments should stand out from the code, I add dashes or even equals for a bolder effect, and blank lines. Detailed comments may be added to the ends of the lines. They are much easier to read if they are lined up in a column as far as possible (the starting column must sometimes change).

Every routine should have a minimal header giving its name, author, and creation date. The example here is not the standard IDL header, that may be found in the file template.pro in the IDL distribution.

Built in help makes a routine self documenting. Most routines never have a manual written for them and even if they did it would soon be lost. With built in help the instructions are always there.

Indenting the code to reflect the current nesting level is very helpful in avoiding or finding problems. Code within Ifs or loops should be indented to make it apparent. Ifs and Loops commonly contain multiple statements. These are called statement blocks and are terminated by some form of the end statement: endif, endelse, endwhile, endrep, ... A useful trick to get the correct termination is to add it before any of the code inside.

The Interactive Box Algorithm

The terms left mouse button and button 1 are used interchangeably.

A rough version of the algorithm:

  1. Wait until a mouse button is pressed.
  2. Save the cursor position where button 1 was pressed.
  3. While button 1 is held down and position changes:
  4. Repeat the above until a button other than 1 is pressed.
More details

Steps 2 and 3 above are only done if button 1 was pressed, so in the routine these steps appear inside an if statement.

Near the front of this if statement any previous box must be erased. This allows repeated boxes.

Before any looping or processing the mouse button flag in the IDL system variable !mouse must be cleared. Also define an initial previous box.

Listing of the Routine

This listing is numbered for reference. This is not the output of the IDL .run -L executive command which does its own indenting (very useful sometimes).
  1  ;=================================================================
  2  ;	boxarea.pro = Select an area with a box
  3  ;	R. Sterner, 1995 Oct 31
  4  ;=================================================================
  5  
  6  	pro boxarea, x1, y1, x2, y2, flag=flag, help=hlp
  7  
  8  	if keyword_set(hlp) then begin
  9  	  print,' Select an area with a box.'
 10  	  print,' boxarea, x1, y1, x2, y2'
 11  	  print,'   x1,y1 = first box point.   out'
 12  	  print,'   x2,y2 = second box point.  out'
 13  	  print,' Keywords:'
 14  	  print,'   FLAG=flg  Exit flag: 0=ok, 1=abort.'
 15  	  print,' Notes: Open a box by dragging with left mouse button.'
 16  	  print,'   Repeat to get desired box.'
 17  	  print,'   Accept box with middle button.'
 18  	  print,'   Reject box with right button.'
 19  	  print,'   All coordinates are device coordinates.'
 20  	  return
 21  	endif
 22  
 23  	!mouse.button = 0		; Clear button flag.
 24  	device, set_graphics = 6	; Set XOR mode.
 25  	x1=100  &  y1=100		; Initial old box.
 26  	x2=100  &  y2=100
 27  
 28  	;------  Loop until button 2 or 3 pressed  ----------
 29  	repeat begin
 30  
 31  	  ;-----  Loop until any button pressed  ----------
 32  	  while !mouse.button eq 0 do cursor,/dev,xa,ya
 33  
 34  	  ;-----  Process button 1 hold  ---------
 35  	  if !mouse.button eq 1 then begin
 36  	    plots,/dev,[x1,x2,x2,x1,x1],[y1,y1,y2,y2,y1]      	; Erase old box.
 37  	    x1=xa  &  y1=ya					; New pt 1.
 38  	    x2=x1  &  y2=y1					; Initial pt 2.
 39  
 40  	    ;------  Loop until button 1 released (drag) -------
 41  	    repeat begin
 42  	      cursor,/dev,/change,xb,yb				; Get new pt 2.
 43  	      plots,/dev,[x1,x2,x2,x1,x1],[y1,y1,y2,y2,y1]	; Erase old box.
 44  	      plots,/dev,[x1,xb,xb,x1,x1],[y1,y1,yb,yb,y1]	; Draw new box.
 45  	      x2=xb  &  y2=yb					; Save new pt 2.
 46  	    endrep until !mouse.button eq 0	; End button 1 drag.
 47  
 48  	  endif					; End process button 1.
 49  
 50  	endrep until !mouse.button ge 2		; End wait for button 2.
 51  
 52  	device, set_graphics = 3		; Restore plot mode.
 53  	flag = !mouse.button ne 2		; Exit flag.
 54  
 55  	end

Program Notes