IDL 5220 Week 6 - Widgets



  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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')
    
  7. 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.
  8. 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)
  9. 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.
  10. 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)
    
  11. 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 ?.
  12. 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.
  13. 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.
  14. 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.

Homework 6: Simple Calculator. Write a program that uses widgets to design a simple calculator that will add and subtract. You should have buttons for "+", "-", and "=" and a text field that allows the user to enter numbers and displays the result after the user clicks "=". Use xmanager to handle events. My program is 41 lines long and consists of the main program, two procedures, and a COMMON block to define 2 global variables.