Home | Categories | Alphabetical | Classes | All Contents | [ < ] | [ > ]

Using Table Widgets


Table widgets display two-dimensional data and allow in-place data editing.

See WIDGET_TABLE for a complete description of the function used to create table widgets.

This section discusses the following topics:

Default Table Size

Table widgets are sized according to the value of the following pairs of keywords to WIDGET_TABLE, in order of precedence: SCR_XSIZE/SCR_YSIZE, XSIZE/YSIZE, X_SCROLL_SIZE/Y_SCROLL_SIZE, VALUE. If either dimension remains unspecified by one of the above keywords, the default value of six (columns or rows) is used when the table is created. If the width or height specified is less than the size of the table, scroll bars are added automatically.

Note
The default row height and column width vary with different user interface toolkits.

Selection Modes

Groups of table cells can be selected either manually (using the mouse or keyboard) or programmatically. The table widget supports two selection modes - standard and disjoint. Both modes can be used either by an interactive table user or by the IDL programmer. See Retrieving Data for information on retrieving data from various types of selections.

Standard Selection Mode

In standard selection mode, exactly one rectangular area (of a single cell or multiple cells) can be selected at a given time.

Interactive Selection

Interactive users select cells by clicking the left mouse button on a cell, holding the mouse button down, and dragging the mouse until the desired cells are selected. Selections can be extended by holding down the Shift key and selecting additional cells.

Programmatic Selection

Programmers select cells by specifying a four-element array, of the form [ left, top, right, bottom ], as the value of the SET_TABLE_SELECT keyword to WIDGET_CONTROL.

Disjoint Selection Mode

In disjoint selection mode, multiple rectangular areas can be selected at once. In order to place a table in disjoint selection mode, the programmer must either specify the DISJOINT_SELECTION keyword to WIDGET_TABLE when creating the table, or set the TABLE_DISJOINT_SELECTION keyword to WIDGET_CONTROL after the table has been created.

Interactive Selection

Interactive users select multiple disjoint cell regions by:

  1. Creating an initial selection as described above.
  2. Holding down the Control key and selecting an unselected cell by clicking and holding down the left mouse button.
  3. Releasing the Control key (while continuing to hold the mouse button down) and dragging the mouse until the next desired region is selected.
  4. Repeating as necessary.

Selections can be extended by holding down the Shift key and selecting additional cells.

Programmatic Selection

Programmers create select multiple disjoint cell regions by providing a 2 x n element array of column/row pairs specifying the cells to act upon as the value of the SET_TABLE_SELECT keyword to WIDGET_CONTROL.

Data Types

Table data can be of any IDL data type or types.

Single Data Type

If all of the table data is of the same data type, the table value is specified as a two-dimensional array.

Values returned by the GET_VALUE keyword to WIDGET_CONTROL are either a two-dimensional array (for full tables or selections when the table is in standard selection mode) or a one-dimensional array (for tables in disjoint selection mode). (See Retrieving Data for details.)

Multiple Data Types

If the table contains data of several data types, the table value is specified as a vector of structures. All of the structures must be of the same type, and must contain one field for each row (if the COLUMN_MAJOR keyword to WIDGET_TABLE is set) or column (if the ROW_MAJOR keyword to WIDGET_TABLE is set; this is the default) in the table.

Values returned by the GET_VALUE keyword to WIDGET_CONTROL are either a vector of structures (for full tables or selections when the table is in standard selection mode) or a single structure with one field per cell (for selections when the table is in disjoint selection mode). (See Retrieving Data for details.)

Retrieving Data

To retrieve data from a table widget, use the GET_VALUE keyword to WIDGET_CONTROL. You can retrieve the entire contents of the table or the contents of either a standard or disjoint selection. The format of the variable returned by the GET_VALUE keyword depends on the type of data displayed in the table (see Data Types) and the type of selection (see Selection Modes).

Entire Table

To retrieve data from the entire table, use the following command:

WIDGET_CONTROL, table, GET_VALUE=table_value 

where table is the widget ID of the table widget. The table_value variable will contain either:

Standard Selection

To retrieve data for a group of selected cells, use the following command:

WIDGET_CONTROL, table, GET_VALUE=selection_value /USE_TABLE_SELECT 

where table is the widget ID of the table widget. In standard selection mode, the selection_value variable will contain either:

Note
You can also set the USE_TABLE_SELECT keyword equal to a four-element array of the form [ lefttoprightbottom ] containing the zero-based indices of the columns and rows that should be selected.

To retrieve the list of selected cells, use the following command:

selected_cells = WIDGET_INFO(table, /TABLE_SELECT) 

where table is the widget ID of the table widget. The selected_cells variable will contain a four-element array of the form [ lefttoprightbottom ] containing the zero-based indices of the columns and rows that are selected.

Disjoint Selection

To retrieve data for a group of selected cells, use the following command:

WIDGET_CONTROL, table, GET_VALUE=selection_value, /USE_TABLE_SELECT 

where table is the widget ID of the table widget. In disjoint selection mode, the selection_value variable will contain either:

Note
You can also set the USE_TABLE_SELECT keyword equal to a 2 x n element array of column/row pairs specifying the cells that should be selected.

To retrieve the list of selected cells, use the following command:

selected_cells = WIDGET_INFO(table, /TABLE_SELECT) 

where table is the widget ID of the table widget. The selected_cells variable will contain 2 x n array of column/row pairs containing the zero-based indices of the selected cells.

Converting Between Cell List Formats

With the addition of the ability to create disjoint table selections in IDL 5.6, the format of the list of selected cells returned by WIDGET_INFO was altered to accommodate non-rectangular regions when disjoint selections are enabled. To preserve backwards-compatibility, the format of the list was not changed for tables using standard selection mode, which guarantees a rectangular selection region.

If your application allows the table widget to switch between standard and disjoint selection mode, or if you have selection-handling routines that can be used with tables in either mode, you may want to modify the rectangular selection values returned for standard selections to match the lists of cells returned for disjoint selections. The following is a template for such a utility function. It accepts a four-element array of the form [ lefttoprightbottom ] containing the zero-based indices of the columns and rows that are selected and converts it into a 2 x n array of column/row pairs containing the zero-based indices the selected cells.

FUNCTION Make_Cell_List, Selection_Vector 
  num_cells = (Selection_Vector[2]-(Selection_Vector[0]-1)) * $ 
    (Selection_Vector[3]-(Selection_Vector[1]-1)) 
  return_arr = intarr(2,num_cells) 
  n=0 
  FOR i=Selection_Vector[1], Selection_Vector[3] DO BEGIN 
    FOR j=Selection_Vector[0], Selection_Vector[2] DO BEGIN 
      return_arr(n)=j 
      return_arr(n+1)=i 
      n=n+2 
    ENDFOR 
  ENDFOR 
  RETURN, return_arr 
END 

With this function compiled, you could retrieve the four-element selection array from a standard selection and turn it into a 2 x n element array with the following commands:

selected_cells = WIDGET_INFO(table, /TABLE_SELECT) 
cell_list = Make_Cell_List(selected_cells) 

where table is the widget ID of a table widget in standard selection mode.

To reform the array returned by

WIDGET_CONTROL, table, GET_VALUE=Selection_Value  

for a standard selection into one-dimensional array like those returned for disjoint selections, use the following command:

REFORM(Selection_Value, N_ELEMENTS(Selection_Value), 1) 

Edit Mode

Edit mode allows a user to select and change the contents of a table cell. There are numerous ways to enter and exit Edit mode, including:

Example: Single Data Type Data

The following procedures build a simple application that allows the user to select data from a table, plotting the data in a draw window and optionally displaying the data values in a text widget. The user can switch the table between standard and disjoint selection modes.

Note
This example is included in the file table_widget_example1.pro in the examples/widgets subdirectory of the IDL distribution. You can either open the file in an IDL editor window and compile and run the code using items on the Run menu, or simply enter
   table_widget_example1
at the IDL command prompt. See Running the Example Code if IDL does not run the program as expected.

; Event-handler routine 
PRO table_widget_example1_event, ev 
 
  ; Retrieve the anonymous structure contained in the user value of 
  ; the top-level base widget. 
  WIDGET_CONTROL, ev.top, GET_UVALUE=stash 
 
  ; Retrieve the table's selection mode and selection. 
  disjoint = WIDGET_INFO(stash.table, /TABLE_DISJOINT_SELECTION) 
  selection = WIDGET_INFO(stash.table, /TABLE_SELECT) 
 
  ; Check to see whether a selection exists, setting the 
  ; variable 'hasSelection' accordingly. 
  IF (selection[0] ne -1) THEN hasSelection = 1 $ 
    ELSE hasSelection = 0 
 
  ; If there is a selection, get the value. 
  IF (hasSelection) THEN WIDGET_CONTROL, stash.table, $ 
    GET_VALUE=value, /USE_TABLE_SELECT 
 
  ; The following sections define the application's reactions to 
  ; various types of events. 
 
  ; If the event came from the table, plot the selected data. 
  IF ((ev.ID eq stash.table) AND hasSelection) THEN BEGIN 
    WSET, stash.draw 
    PLOT, value 
  ENDIF 
 
  ; If the event came from the 'Show Selected Data' button, display 
  ; the data in the text widget. 
  IF ((ev.ID eq stash.b_value) AND hasSelection) THEN BEGIN 
    IF (disjoint eq 0) THEN BEGIN 
      WIDGET_CONTROL, stash.text, SET_VALUE=STRING(value, /PRINT) 
    ENDIF ELSE BEGIN 
      WIDGET_CONTROL, stash.text, SET_VALUE=STRING(value) 
    ENDELSE 
  ENDIF 
 
  ; If the event came from the 'Show Selected Cells' button, 
  ; display the selection information in the text widget. Use 
  ; different displays for standard and disjoint selections. 
  IF ((ev.ID eq stash.b_select) AND hasSelection) THEN BEGIN 
    IF (disjoint eq 0) THEN BEGIN 
      ; Create a string array containing the column and row 
      ; values of the selected rectangle. 
      list0 = 'Standard Selection' 
      list1 = 'Left:   ' + STRING(selection[0]) 
      list2 = 'Top:    ' + STRING(selection[1]) 
      list3 = 'Right:  ' + STRING(selection[2]) 
      list4 = 'Bottom: ' + STRING(selection[3]) 
      list = [list0, list1, list2, list3, list4] 
    ENDIF ELSE BEGIN 
      ; Create a string array containing the column and row 
      ; information for the selected cells. 
      n = N_ELEMENTS(selection) 
      list = STRARR(n/2+1) 
      list[0] = 'Disjoint Selection' 
      FOR j=0,n-1,2 DO BEGIN 
        list[j/2+1] = 'Column: ' + STRING(selection[j]) + $ 
          ', Row: ' + STRING(selection[j+1]) 
      ENDFOR 
    ENDELSE 
    WIDGET_CONTROL, stash.text, SET_VALUE=list 
  ENDIF 
 
  ; If the event came from the 'Change Selection Mode' button, 
  ; change the table selection mode and the title of the button. 
  IF (ev.ID eq stash.b_change) THEN BEGIN 
    IF (disjoint eq 0) THEN BEGIN 
      WIDGET_CONTROL, stash.table, TABLE_DISJOINT_SELECTION=1 
      WIDGET_CONTROL, stash.b_change, $ 
        SET_VALUE='Change to Standard Selection Mode' 
    ENDIF ELSE BEGIN 
      WIDGET_CONTROL, stash.table, TABLE_DISJOINT_SELECTION=0 
      WIDGET_CONTROL, stash.b_change, $ 
        SET_VALUE='Change to Disjoint Selection Mode' 
    ENDELSE 
  ENDIF 
 
  ; If the event came from the 'Quit' button, close the 
  ; application. 
  IF (ev.ID eq stash.b_quit) THEN WIDGET_CONTROL, ev.TOP, /DESTROY 
 
END 
 
; Widget creation routine. 
PRO table_widget_example1 
 
  ; Create data to be displayed in the table. 
  data = DIST(7) 
 
  ; Create initial text to be displayed in the text widget. 
  help = ['Select data from the table below using the mouse.'] 
 
  ; Create the widget hierarchy. 
  base = WIDGET_BASE(/COLUMN) 
  subbase1 = WIDGET_BASE(base, /ROW) 
  draw = WIDGET_DRAW(subbase1, XSIZE=250, YSIZE=250) 
  subbase2 = WIDGET_BASE(subbase1, /COLUMN) 
  text = WIDGET_text(subbase2, XS=50, YS=8, VALUE=help, /SCROLL) 
  b_value = WIDGET_BUTTON(subbase2, VALUE='Show Selected Data') 
  b_select = WIDGET_BUTTON(subbase2, VALUE='Show Selected Cells') 
  b_change = WIDGET_BUTTON(subbase2, $ 
    VALUE='Change to Disjoint Selection Mode') 
  b_quit = WIDGET_BUTTON(subbase2, VALUE='Quit') 
  table = WIDGET_TABLE(base, VALUE=data, /ALL_EVENTS) 
 
  ; Realize the widgets. 
  WIDGET_CONTROL, base, /REALIZE 
 
  ; Get the widget ID of the draw widget. 
  WIDGET_CONTROL, draw, GET_VALUE=drawID 
 
  ; Create an anonymous structure to hold widget IDs. This 
  ; structure becomes the user value of the top-level base 
  ; widget. 
  stash = {draw:drawID, table:table, text:text, b_value:b_value, $ 
           b_select:b_select, b_change:b_change, b_quit:b_quit} 
 
  ; Set the user value of the top-level base and call XMANAGER 
  ; to manage everything. 
  WIDGET_CONTROL, base, SET_UVALUE=stash 
  XMANAGER, 'table_widget_example1', base 
 
END 

The following things about this example are worth noting:

Example: Structure Data

The following procedures build a simple application that displays the same structure data in two table widgets; one in row-major format and one in column-major format.

Note
This example is included in the file table_widget_example2.pro in the examples/widgets subdirectory of the IDL distribution. You can either open the file in an IDL editor window and compile and run the code using items on the Run menu, or simply enter
   table_widget_example2
at the IDL command prompt. See Running the Example Code if IDL does not run the program as expected.

; Event-handler routine for 'Quit' button 
PRO table_widget_example2_quit_event, ev 
  WIDGET_CONTROL, ev.TOP, /DESTROY 
END 
 
; Widget creation routine. 
PRO table_widget_example2 
 
  ; Create some structure data. 
  d0={planet:'Mercury', orbit:0.387, radius:2439, moons:0} 
  d1={planet:'Venus', orbit:0.723, radius:6052, moons:0} 
  d2={planet:'Earth', orbit:1.0, radius:6378, moons:1} 
  d3={planet:'Mars', orbit:1.524, radius:3397, moons:2} 
 
  ; Combine structure data into a vector of structures. 
  data = [d0, d1, d2, d3] 
 
  ; Create labels for the rows or columns of the table. 
  labels = ['Planet', 'Orbit Radius (AU)', 'Radius (km)', 'Moons'] 
 
  ; To make sure the table looks nice on all platforms, 
  ; set all column widths to the width of the longest string 
  ; that can be a header. 
  max_strlen = strlen('Orbit Radius (AU)') 
  maxwidth = max_strlen * !d.x_ch_size + 6   ; ... + 6 for padding 
 
  ; Create base widget, two tables (column- and row-major, 
  ; respectively), and 'Quit' button. 
  base = WIDGET_BASE(/COLUMN) 
  table1 = WIDGET_TABLE(base, VALUE=data, /COLUMN_MAJOR, $ 
    ROW_LABELS=labels, COLUMN_LABELS='', $ 
    COLUMN_WIDTHS=maxwidths, /RESIZEABLE_COLUMNS) 
  table2 = WIDGET_TABLE(base, VALUE=data, /ROW_MAJOR, $ 
    ROW_LABELS='', COLUMN_LABELS=labels, /RESIZEABLE_COLUMNS) 
  b_quit = WIDGET_BUTTON(base, VALUE='Quit', $ 
    EVENT_PRO='table_widget_example2_quit_event') 
 
  ; Realize the widgets. 
  WIDGET_CONTROL, base, /REALIZE 
 
  ; Retrieve the widths of the columns of the first table. 
  ; Note that we must realize the widgets before retrieving 
  ; this value. 
  col_widths = WIDGET_INFO(table1, /COLUMN_WIDTHS) 
 
  ; We need the following trick to get the first column (which is 
  ; a header column in our first table) to reset to the width of 
  ; our data columns. The initial call to keyword COLUMN_WIDTHS 
  ; above only set the data column widths. 
  WIDGET_CONTROL, table1, COLUMN_WIDTHS=col_widths[0], $ 
    USE_TABLE_SELECT=[-1,-1,3,3] 
  ; This call gives table 2 the same cell dimensions as table 1 
  WIDGET_CONTROL, table2, COLUMN_WIDTHS=col_widths[0], $ 
    USE_TABLE_SELECT=[-1,-1,3,3] 
 
  ; Call XMANAGER to manage the widgets. 
  XMANAGER, 'table_widget_example2', base 
 
END 

The following things about this example are worth noting:


Home | Categories | Alphabetical | Classes | All Contents | [ < ] | [ > ]