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:
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 |
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.
In standard selection mode, exactly one rectangular area (of a single cell or multiple cells) can be selected at a given time.
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.
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.
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 users select multiple disjoint cell regions by:
Selections can be extended by holding down the Shift key and selecting additional cells.
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.
Table data can be of any IDL data type or types.
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.)
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.)
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).
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:
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 |
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 [ left, top, right, bottom ] containing the zero-based indices of the columns and rows that are selected.
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 |
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.
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 [ left, top, right, bottom ] 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 allows a user to select and change the contents of a table cell. There are numerous ways to enter and exit Edit mode, including:
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 |
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:
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 |
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:
'').-1 using the USE_TABLE_SELECT keyword.