- COMMON Blocks:
COMMON blocks allow variables to be shared globally (across different
procedures). This can be useful when programming with Widgets and using
Xmanager. A COMMON block is defined at the top of a procedure by the
syntax COMMON, name, var1, var2, ... where name is the name you assign to
the block, and var1, var2, and so on are the variables you wish to share.
You can then repeat this command at the top of another procedure, and you
will have access to the variables in the block. When referencing a common
block, you do not have to list all the variables, nor do you have to use
the same names. Example:
pro add
COMMON numbers, x, y
print,x+y
end
COMMON numbers, x, a, b
x=5
a=3
b=4
add
end
In this example, the block is defined in the main program as COMMON numbers,
x, a, b. It is referenced in the procedure as COMMON numbers, x, y. This
means that when it is referenced in add it assigns the values of x and a
from the main program to the variables x and y in the procedure. a and b
are undefined within the procedure. The result is 8 printed to the screen.
y is undefined within the main program.
- Widgets:
Widgets in IDL are tools that can be used to build an interactive GUI
(graphical user interface) for a program. Widgets are very customizeable
and there are over 200 pages of documentation on widgets in the IDL
reference guide, so I will cover the basics of some of the types of widgets
I have used and refer you to the reference guide for more advanced options.
- Base Widgets:
Base widgets are containers for other widgets. Before you create any widget,
whether it is a text widget, a button, a checkbox, or a draw widget, you must
first create a base widget to contain it. Like all widgets, base widgets
return a result that refers to the widget's ID. The syntax for creating
base widgets is:
result = WIDGET_BASE(xsize=pixels, ysize=pixels, title='String', options)
For instance, the base widget for GatorPlot is given by:
base=widget_base(xsize=800,ysize=640,title='GatorPlot v3.02 by: Craig Warner')
The options are listed in the help for WIDGET_BASE. They include /column and
/row, which if set will automatically determine the position of the widgets
within the base widget either column-major or row-major. This will overrule
any manual positioning of the widgets. It is sometimes good to use these
options to make a widget platform independent, but in other cases you may
want to manually set the layout yourself by specifying x and y pixel values
for each of the widgets within the base widget.
- Widget Hierarchies:
All widgets other than the top base widget must specify their parent widget,
which is a base widget The ID of the parent widget is a mandatory argument
when creating any type of widget other than a base widget. It is optional in
a base widget. There can be many levels of base widgets, as well
as groups that can be specified by the GROUP_LEADER=id option. Groups are
iconified or destroyed by iconifying or destroying just the group leader,
which is a base widget.
- Label Widgets:
Label Widgets are used to display static text, such as a label. The syntax is:
result=WIDGET_LABEL(parent, value=string, options)
Among the options
are xoffset=pixels and yoffset=pixels, which allow you to position the label
wherever you want on the base widget. For example,
labeltitle=widget_label(base,value='Title:',yoffset=162)
displays the label 'Title:' in GatorPlot.
- Button Widgets:
Button Widgets are buttons that can be clicked on by the mouse. The syntax
is:
result=WIDGET_BUTTON(parent, value=string, uvalue=value, options)
uvalue is a very important option for widgets. It is a user value that can
be set to any datatype and later recalled to determine which widget was
acted upon. Again, xoffset and yoffset are other options. From GatorPlot:
export=widget_button(base,value='Export',yoffset=136,xoffset=40,uvalue='export')
- Text Widgets:
Text Widgets create text fields that can display text and/or take input text
from the user. It can contain one or more lines of text. It can be optionally
set to editable, meaning that a user can change the value. When input is taken
via a text widget, it is represented by a string array. The syntax is:
result=WIDGET_TEXT(parent, value=string, uvalue=value, options)
Among the options for text widgets are /editable, which allows the text field
to be edited, /all_event, which causes an event to be generated whenever the
user changes the contents of the text area, /scroll, which gives the widget
scrollbars if necessary, xoffset and yoffset, and xsize and ysize, which
specify how many characters big the text field should be in the x-direction
and how many rows it should be. Examples from GatorPlot:
filelist=widget_text(base,xsize=18,ysize=5,/scroll,/editable,/all_events,yoffset
=28,uvalue='filelist')
titletext=widget_text(base,xsize=10,/editable,/all_events,yoffset=180,uvalue='ti
tletext')
These create the text fields for the list of files and for a string to
label the title of the plot, respectively.
- Draw Widgets:
Draw Widgets are rectangular areas that are treated just like standard IDL
graphics windows. Any graphical output that can be produced by IDL can be
directed to a draw widget. The syntax is:
result=widget_draw(parent, xsize=pixels, ysize=pixels, uvalue=value, options)
Among the options are /button_events which makes the draw widget generate
events when the mouse buttons are pressed or released anywhere in the draw
window. It also takes the xoffset and yoffset options among others. The
draw widget in GatorPlot is defined by:
draw=widget_draw(base,xsize=640,ysize=512,xoffset=160,uvalue='draw',/button_events)
- File Selection:
File Selection can be provided by dialog_pickfile. The format is:
result=dialog_pickfile(options)
The options include /multiple_files for
multiple file selection and filter=string, which specifies a default file
filter. result is a string or string array containing the choice or choices.
The value of a text widget can be set to this result.
- Button Groups:
Button Groups are compound widgets given by the cw_bgroup command. They are
represented by a list of items with checkboxes by them. One or more of the
checkboxes can be selected. The syntax is:
result=cw_bgroup(parent, titles, uvalue=value, options)
titles is a string array containing the text for each item in the list. The
options include /row which lists the items all in the same row, /column which
lists the items all in the same column, /frame which draws a border around the
widget, /exclusive which means only 1 item can be selected at the same time,
label_top=string which labels the widget with text, set_value=int which selects
the option to be selected by default (set_value=0 would select the first
option by default), and of course xoffset and yoffset. From GatorPlot:
xlinlog=cw_bgroup(base,['Linear','Log'],yoffset=580,xoffset=300,/row,/frame,/exclusive,
uvalue='xlinlog',label_top='X-axis:',set_value=0)
- Other Widgets:
Other Widgets which I have used less often include WIDGET_COMBOBOX,
WIDGET_DROPLIST, WIDGET_LIST, WIDGET_SLIDER, WIDGET_TAB, WIDGET_TABLE,
WIDGET_TREE, CW_FSLIDER, CW_PDMENU, and DIALOG_MESSAGE. They should all be
created similarly to the above widgets and you can find out their specific
functions by looking them up in ?.
- Widget_control:
Typing in anything above will not noticeably do anything. You have to first
call upon the widget_control procedure to realize your widgets. To realize
a widget (make it visible on the screen):
widget_control, base_widget_id, /realize
from Gatorplot:
widget_control,base,/realize
Widgets can be destroyed by widget_control, base_widget_id, /destroy.
- Xmanager:
Now that you have the widget realized, you need to handle widget events. It
is recommended especially for novice users to use xmanager to register your
widgets and send events to an event handling routine. For example:
xmanager,'Widget1',base,event_handler='click'
registers the widget base
under the name 'Widget1' and if any event occurs in any widget contained in
base, the procedure click is called:pro click,ev
This is where uvalue comes in. Before I register with xmanager, I use the line
widget_control,base,set_uvalue=[filelist,draw,titletext,subtitletext,xtitletext,ytitletext,xrmin,xrmax,
yrmin,yrmax,ytick,offsets,labels,chsz,dl,cut,stackoplot,usepsym,xlinlog,ylinlog,axcol,aycol,usecolor,lstyle]
This sets the uvalue of base to an array containing the widget ids of many
widgets contained within base. Then in click, I use the following two lines:
widget_control,ev.id,get_uvalue=uval
widget_control,ev.top,get_uvalue=t
The first line gets the uvalue of ev.id. ev.id refers to the id of the
widget that created the event. So if I were to click the 'Export' button,
the uvalue of that widget ('export') would be assigned to uval and I would
know that the button had been pressed.
The second line gets the uvalue of ev.top. ev.top refers to the top widget
in the hierarchy of the widget that generated the event, or more specifically
the top base widget, base in this case. t is now an array containing all
the widget ids that I passed to the uvalue using the set_uvalue option. I
can now use the command:
widget_control,t[0],get_value=files
t[0] is the widget id for the file list. get_value gets the value
currently in the text field and assigns it to the string array files. In
this way, you can detect the contents of a text field when a certain button
is pressed.
- widget_event:
widget_event allows you to manually detect and handle widget events without
xmanager. Here is an example from GatorPlot. This handles the widget that
is brought up when you click the Export button.
widget_control,exportw,set_uvalue=[exportf,exporttp,exportclr]
widget_control,exportw,/realize
exuval=''
while exuval ne 'exportb' and exuval ne 'exportcancel' do begin
exportev=widget_event(exportw)
widget_control,exportev.id,get_uvalue=exuval
endwhile
widget_control,exportev.top,get_uvalue=exportt
widget_control,exportt[0],get_value=exportfile
You'll recognize the top 2 widget_control calls from above. I then set up
a loop until the user clicks either the Export or Cancel button, and get
the event. exportw is the id of the base widget in this case and exportev
receives the event. exportev.id is the id of the widget that generated
the event and its uvalue is assigned to exuval. The bottom 2 widget_control
statements should also look familiar from above as I get the uvalue of the
base widget and the value entered into the filename text field.