EDT:DataGrid Widget

From Eclipsepedia

Revision as of 03:59, 20 February 2012 by Cdlwuxin.cn.ibm.com (Talk | contribs)

Jump to: navigation, search

Contents

 Introduction

A Rich UI dataGrid widget defines an array of row values in a table. This topic gives general information about the widget and then provides reference detail.

An understanding of the data grid requires that you be familiar with the following issues:
• How to define column headings and data rows.
• How to define a behavior, which is a property that takes an array of functions. The functions for a given behavior run in array-element order when the grid is being rendered.
• How to define a listener, which is also a property that takes an array of functions. The functions for a given listener run in array-element order in response to a user action such as a click or, in some cases, in response to a function call that selects or deselects a row or that updates a check box.
• How to customize a mechanism for sorting the grid by column.
• How to customize a formatter to DataGridColumn.
• Other tips when using DataGrid, Paging, Using Data Loader, etc.


Behaviors and listeners can affect style characteristics and can invoke logic of various kinds; for example, to cause a sort by column; to access a service; to calculate a value and place it into a grid column; or to configure a widget and place it into a grid column. You can build on these ideas in various ways; for example, you might do as follows:
1. Access a user ID from a row of the data grid.
2. Use that ID in a REST service invocation that returns a photograph to a callback function.
3. Embed that photograph in an image widget, which is defined globally in the handler.
4. Place that widget in a data grid column, in the same row as the user ID.


You can use the useful properties, functions and extensions of DataGrid to do many thing you want. I’m sure you can not wait any longer to start the DataGrid travel. So let’s start form creating a RUI DataGrid in RUI Handler.


Create a Simple DataGrid

In this section we will provide a step by step introduction about creating a DataGrid in EDT.
'1. 'Right click on a EGL project/package --> New --> Handler. The New EGL Handler wizard will pop up.

EGL Handler.JPG

Fill the Name field and select Rich UI Handler as the templates, the click Finish. The Hand will be created to the target package.

'2. 'When the Handler created, it will be opened in EGL Rich UI Editor automatically. And also you can open it by double click or right click on the handler  Open With  EGL Rich UI Editor.
Switch to design view, the Palette is on the right side of the EGL Rich UI Editor. You can find the DataGrid widget in “Display and Input” tab of the Palette. Then you can drag the DataGrid from the Palette to anywhere of the design panel.

Design.JPG
When the mouse up, the “New Variable” wizard will pop up.

New Variable.JPG

Type in the Variable name for the DataGrid and then click OK. The DataGrid will appears in design panel. And the source code have also changed.

3. Define a Record part to be the basis of an array of records. Each record holds a set of values that you want to display in a single row of a data grid. You can create a new record source file to maintain the record or just paste it at the bottom of the RUI Handler.

Record Stock 
   Symbol string;
   NumShares int;
   Quote  decimal(5,2);
   SelectQuote boolean;
end

4. Declare the array of data records, as in the following example:

stockList Stock[] =[new Stock{SelectQuote = false, Symbol = "Company1", Quote = 100.00, NumShares = 40},
                      new Stock{SelectQuote = false, Symbol = "Company2", Quote = 200.00, NumShares = 10}];

5. Change the DataGrid declaration to the target record structure.

DataGrid DataGrid{layoutData = new GridLayoutData{row = 1, column = 1}, behaviors =[], headerBehaviors =[], columns =[
                    new DataGridColumn{name = "Symbol", displayName = "Company Symbol"},
                    new DataGridColumn{name = "Quote", displayName = "Price Per Share"},
                    new DataGridColumn{name = "NumShares", displayName = "Number of Shares"},
                    new DataGridColumn{name = "Total", displayName = "Value of Shares", formatters =[totalFormatter]
                 }]};

Each of the first three declarations of type DataGridColumn references a record field in the array of Stock records. The fourth declaration identifies a calculated column, which is a column that has no corresponding record field; in this case, no record field named Total.
The order of the DataGridColumn elements determines the order in which the columns are displayed.
For the data property, assign the array of records of type Stock. Here is an example setting:
     DataGrid.data = stockList as any[];

You can just put this code in function start. Each element in the array provides a subset of the data required for a row in the data grid.


6. Add formatter function You set the behaviors and listeners by assigning values to properties. Each of those properties is related to a Delegate type, which identifies the parameter list and return value that are required for any of the functions assigned to the property. In the example, the DataGridColumn formatters property is set for the fourth column and causes the invocation of a function that takes three parameters and has no return value. Here is the function:

function totalFormatter(class string inOut, value string inOut, rowData any in)
    // display the total value of the shares after calculating the value 
    // from the content of two other columns in the same row
        value = rowData.NumShares as int * rowData.Quote as decimal(5, 2);
end

The invocation of a function referenced in the formatters property occurs once per row, before the grid is rendered. The content of the entire row is available in the third parameter, and you can update the column-specific cell by setting either the first parameter, which controls the CSS class, or the second parameter, which controls the value.

7. Switch to Preview

The DataGrid should have shown in the preview mode.

Preview DG.JPG

DataGridColumn fields

You assign an array of records of type DataGridColumn when you set the columns property for a data grid. Each of those records includes the following fields:

  • alignment: an constant integer that affects the horizontal alignment in the displayed column:

DataGridLib.ALIGN_LEFT (the default)  ---  The column content is left aligned
DataGridLib.ALIGN_RIGHT   ---   The column content is right aligned.
DataGridLib.ALIGN_CENTER   ---   The column content is center aligned.


  • columnComparator: references a comparator function during a column sort. A comparator function is invoked repeatedly to order the cell content.

Here is the Delegate part to which a custom function must conform:

Delegate ColumnComparator(data1 any in, data2 any in) returns (int) end

data1: The content of the first cell being compared
data2: The content of the second cell. The function returns the following integer value:
        -1 if the content of the first cell is less than the content of the second.
        1  if the opposite is true.
        0  if the content of the two cells are equal.

Here is an example function, which might be used if the previous example were extended to include company names Company3 through Company10:


Function CompareTwo(myFirst ANY in, mySecond ANY in) returns (int)
   if ( (myFirst as string )[8:8] == "6")
      return(-1);
   else
      return(1);  
   end
end

If the columnComparator property refers to the CompareTo function, the user's click places Company6 at the top or bottom of the column.

  • displayName: a string to display as the column title. If the displayName field is not specified, the column title is the value of the name field.
  • enableSorting: a Boolean value to indicate whether the user can sort the column with a click. The default value is true. the sort is affected by the setting of the ignoreCase property, but only if you do not specify the columnComparator property.
  • formatters: an array of functions that run in array-element order before the grid is rendered. These functions run once for every cell in the column.

Here is the Delegate part to which each function must conform:

Delegate CellFormatter(class String inout, value String inout, rowData any in) end

class: The CSS class for the cell in the column.
value: The cell content, which is always of type STRING. If the content is a checkbox, the value is true or false.
rowData: The data of the row in which the cell resides. The example in the Introduction shows how to handle the input.
          The functions for the formatters field are invoked in the order in which the DataGridColumn entries are defined in the DataGrid columns property. Those             functions run before the functions specified in the following DataGrid properties, which are listed in runtime order: headerBehaviors, behaviors, and               editingBehaviors.
          A set of functions are provided for use with the formatters property. For details, see the following file in the com.ibm.egl.rui project,                           com.ibm.egl.rui.widgets package: DataGridFormatters.egl.

  • headerAlignment: an integer value that affects the horizontal alignment in the displayed header. The values are as follows:

DataGridLib.ALIGN_LEFT (the default)   ---   The column content is left aligned
DataGridLib.ALIGN_RIGHT   ---   The column content is right aligned.
DataGridLib.ALIGN_CENTER   ---   The column content is center aligned.
You can set all the column headers by including a entry like the following one in the CSS file, specifying left, center, or right for the text-align attribute:

.EglRuiDataGridHeaderCell {
   text-align: center;
}
  • ignoreCase: a Boolean value to indicate whether the case of the column content is ignored during the default sort. The default is false. The property value has an effect only if you do not set the columnComparator property.
  • name: a string that is both the default column title and the name of the record field that provides the column value.
  • sortDirection: one of the following constants, to indicate what the user's next request for a sort will do:

DataGridLib.SORT_UP (the initial default)   ---   The user's click will sort the column in ascending order.
DataGridLib.SORT_DOWN   ---   The user's click will sort the column in descending order.
DataGridLib.SORT_NONE   ---   The user's click will have no effect.
You might access the sortDirection field in a comparator function.

  • width: an integer that specifies the column width, in pixels.


DataGrid properties

The following properties are supported in the DataGrid widget:


  • behaviors: an array of function references. The functions are invoked sequentially for each grid cell when the data grid is rendered. This property does not apply to the header cells.

Here is the Delegate part to which each function must conform:

Delegate 
   DataCellBehavior(grid DataGrid in, cell Widget in, rowData ANY in, rowNumber INT in, column DataGridColumn in)
end

grid: The data grid.
cell: A widget that represents the grid cell. That widget is based on the HTML DIV tag.
rowData: The record that represents the row data.
rowNumber: The row number, which ranges from 1 to the number of rows in the grid.
column: The record that represents the column description.
The DataGrid properties are processed in the following order: headerBehaviors, behaviors, and editingBehaviors.

  • cellBorder: an integer value that specifies, in pixels, the width of the cell border. The cell border is only on the right side of the column, and the value of this property does not affect the last column in each row. The default value is 1.
  • cellPadding: an integer value that specifies, in pixels, the width of the padding that is added in two locations: above the content in a cell and to the left of the content in a cell. The default value is 4.
  • checkBoxListeners: an array of function references. The listener functions run in response to the user's selecting or clearing a check box or in response to the invocation of any of the following functions: setChecked, checkAll, or unCheckAll.

  Here is the Delegate part to which each listener function must conform:

Delegate 
   CheckBoxListener(grid DataGrid in) end
end
  • checkBoxWidth: an integer value that specifies the width of the system-provided check boxes, in pixels. The default value is 20.
  • columns: an array of records of type DataGridColumn.
  • data: an array of records. The property is of type ANY[].
  • editorBehaviors: an array of function references. The functions are invoked sequentially for each cell when the data grid is rendered. The purpose is to place a widget in each cell.
    Here is the Delegate part to which each function must conform:
Delegate 
   EditorBehavior(grid dataGrid in, cell Widget in, rowData any in, 
                  rowNumber INT in, column DataGridColumn in, value ANY in) 
                  returns (Widget)
end

grid: The data grid.
cell: A widget that represents the grid cell. That widget is based on the HTML DIV tag. Its content includes the effects, if any, that are caused by the formatters property setting.
rowData: The record that represents the row data.
rowNumber: The row number, which ranges from 1 to the number of rows in the grid.
column: The record that represents the column description.
value:The content of the cell. This content include the effects, if any, that are caused by the DataGridColumn formatters property setting.
        The return value is a widget or null.
The DataGrid properties are processed in the following order: headerBehaviors, behaviors, and editingBehaviors.

  • headerBehaviors: an array of function references. The functions are invoked sequentially for each header cell whenever the data grid is rendered. Each function is based on the Delegate part that is described in the entry for the behaviors property.
  • pageSize: an integer that indicates how many rows to display. The default value is 10. For further details, see the entries for the showButtonBar and showScrollBar properties.
  • rowHeight: an integer value that specifies, in pixels, the minimum height of a row. If any content requires more vertical space, the height of the row reflects the need.
  • selectionListeners: an array of function references. When row selection is valid, the selection listeners run in response to the user's clicking a row or in response to the invocation of any of the following functions: setSelection, selectAll, or deSelectAll.

  Here is the Delegate part to which each selection listener must conform:

Delegate 
   SelectionListener(grid DataGrid in) end
end
  • sortListeners: an array of function references. The functions are invoked sequentially when the user sorts a column. The functions are invoked only if the sort occurs, as is possible only if the value of the DataGrid enableSort property is true.

Here is the Delegate part to which each function must conform:

Delegate 
   SortListener(grid DataGrid in, sortColumn DataGridColumn in) end
end

grid: The data grid that was sorted.
sortColumn: The column that was sorted.


  • startRow: an integer that indicates a row to display on the first page, when a button bar is present. The default value is 1. For further details, see the entry for showButtonBar.
  • selectionMode: A constant that indicates whether the user or code can select multiple rows. This constant also specifies whether the functions setSelection and selectAll can select multiple rows. One of these values:

 DataGridLib.MULTIPLE_SELECTION (the default)   ---   The user can select a single row or can select multiple rows in either of two ways:
       By holding down the CTRL key when clicking each row after the first; or,
       By holding down the SHIFT key when clicking the last row in a set of contiguous rows.
  The selected rows can span multiple grid pages.
  DataGridLib.SINGLE_SELECTION   ---   The user can select a single row. Selection of a second row deselects the first.
 DataGridLib.DISABLE_SELECTION   ---   The user cannot select any rows.

  • showButtonBar: a Boolean value that specifies whether to include a button bar, which is a navigation bar at the bottom of the grid so that the user can click to another page, whether that page is next, previous, first, or last. If the value of the showButtonBar property is true, the following properties are also relevant:

  pageSize specifies how many rows to display at one time.
  startRow tells which row must be displayed to the user. For example, if you have 20 rows, pageSize = 4, and startRow = 6, the second page is displayed, with row   6 in the second position.
  The showButtonBar property can have an effect only in the following case:
       The value of the pageSize property is greater than the number of rows available to the grid; and
       The value of the showScrollBar property is false.
  If you set the showButtonBar property to false when more rows are available than can be seen, and if you do not set the showScrollBar property to true, the user   cannot access the unseen rows.

  • showCheckBoxes: a Boolean value that indicates whether to make the system-provided check boxes visible. The default is false. When the check boxes are visible, they are displayed at the left of each row.

  The user's check box selections are retained even if you set the showCheckBoxes to false at run time. Also, your code can always do as follows, regardless of       whether the check boxes are visible:
       Check some or all of the hidden check boxes by invoking the setChecked or checkAll function.
       Use the getChecked function to review the status of the check boxes in each row.

  • showHeader: a Boolean value that indicates whether to display the grid header. The default is true.
  • showScrollBar: a Boolean value that indicates whether to display the rows with a scrollbar so that the user can navigate to other rows. The default is false. If the value of this property is true, the pageSize property specifies how many rows to display at one time, and the showButtonBar property has no effect.

Modify the DataGrid Properties In Properties View

In last section, we simply demonstrated how to create a typical RuiHandler including a DataGrid widget. That only using the default DataGrid property settings. If you want to get a better usability and UI, you need to change the property of DataGrid. The Rich UI Editor got the properties view, all useful properties are listed here. You can just modify them in this view, and the source code will be modified accordingly. Here is a screenshot of the properties view.

Properties DG.JPG

In this view, all properties were sorted to 7 categories. General, Border, Spacing, Position, Appearance, Accessbility, Layout and Events. For widgets got some common properties like padding, position and some other render or UI properties. We will focusing on the properties only for DataGrid. All of them are listed in General tab. You can find the property pageSize, startRow, checkBoxWidth, rowHeight, cellBorder, cellPadding, selectionMode, showHeader, showButtonBar, enableSorting, showScrollbar andshowCheckBoxes.


DataGrid functions

The following functions are supported in the DataGrid widget:


  • cancelDataLoader: Used primarily in an exception handler to indicate that the data required by the data loader is not available. The cancelDataLoader function does not stop subsequent invocations of the data loader, but has two effects: it ends the animation that is characteristic of a waiting data loader, and it re-renders the grid with the data that was last provided.
  • checkAll: to check all the system-provided check boxes. You can check the check boxes even when they are hidden.
  • deSelectAll: to deselect all the rows that are currently selected. This function is part of the row-selection mechanism, which is independent of the system-provided check boxes.
  • getChecked: to retrieve the data in the rows where the system-provided check boxes are selected. Here is the function signature:
function getChecked() returns (any[])

  In relation to the first example in the current topic, consider the following event handler, which displays stock symbols:

function myResponse (e event in)
   columnRetrieve Stock[];
   columnRetrieve = grid.getChecked() as Stock[];
   numberOfRows int = columnRetrieve.getSize();

   if (numberOfRows > 0)
      for (i int from 1 to numberOfRows)
         sysLib.writeStdOut(columnRetrieve[i].Symbol + " is checked.");
      end
   end
end

  The getChecked function retrieves the records referenced by the DataGrid data property. However, the order in which the data is returned depends on the current     display, which is affected by the user's sort.

  • getCurrentPageIndex: to get the current page number. Here is the function signature:
function getCurrentPageIndex() returns (int)
  • getPageCount: to get the number of pages available. Here is the function signature:
function getPageCount() returns (int)
  • getSelection: to retrieve the data in the currently selected rows. Here is the function signature:
function getSelection() returns (any[])

  In relation to the first example in the current topic, consider the following event handler, which displays stock symbols in response to the user's clicking a     button:

function myResponse (e event in)
   columnRetrieve Stock[];
   columnRetrieve = grid.getSelection() as Stock[];
   numberOfRows int = columnRetrieve.getSize();

   if (numberOfRows > 0)
      for (i int from 1 to numberOfRows)
         sysLib.writeStdOut(columnRetrieve[i].Symbol + " is selected.");
      end
      grid.deSelectAll();
   else
      sysLib.writeStdOut("Select one or more rows.");                    
   end 
end

The getSelection function retrieves the records referenced by the DataGrid data property. However, the order in which the data is returned depends on the current display, which is affected by the user's sort.


  • goToPage: to display the specified page. If you specify a page number that is less than or equal to 1, the first page is displayed. If you specify a page number that is greater than or equal to the number of the last page, the last page is displayed.

Here is the function signature:

function goToPage(pageNumber int in)
  • selectAll: to select all rows in the data grid.
  • setChecked: to select one or more of the system-provided check boxes. You can select check boxes even when they are hidden.

Here is the function signature:

function setChecked(selection any[] in)

When you invoke the setChecked function, specify elements from the data array. For example, here is an on-construction function that invokes the setChecked function in two ways:

function start()
   grid.setChecked([grid.data[2], grid.data[3]]);
   // alternative coding
   myAny ANY[] = [grid.data[2], grid.data[3]];
   grid.setChecked(myAny);
end
  • setSelection: to select one or more rows in the data grid. In most cases, the purpose is to preset the grid before it is rendered. Here is the function signature:
function setSelection(selection any[] in)

When you invoke the setSelection function, specify elements from the data array. For example, here is an on-construction function that invokes the setSelection function in two ways:

function start()
   grid.setSelection([grid.data[3], grid.data[2]]);
   // alternative coding
   myAny ANY[] = [grid.data[3], grid.data[2]];
   grid.setSelection(myAny);
end

The ability to select rows depends on the setting of the DataGrid selectionMode property. For example, only the first entry submitted to the setSelection function is selected if your code tries to select two rows when the selectionMode property allows only one.

  • unCheckAll: to clear all the system-provided check boxes. You can clear the check boxes even when they are hidden.

DataGrid Selection

The DataGrid widget provides two ways of identifying that a row is of interest:

  •   First is a mechanism for selecting rows, for deselecting rows, for and reviewing the current selections.
  • Second is a mechanism for checking a set of check boxes that are provided automatically, for clearing them, and for reviewing the status of those check boxes.


Those two mechanisms are independent of one another. First, consider selection:

  • Four functions are used: setSelection, selectAll, deSelectAll, and getSelection.
  • The value of the DataGrid selectionMode property specifies whether row selection is valid and, if so, how many rows can be selected. That property affects row selection by the user or by the code.
  • When row selection is valid, listener functions run in response to the user's clicking a row or in response to the invocation of any of the following functions: setSelection, selectAll, or deSelectAll.
  • The listener functions are referenced from the DataGrid selectionListeners property.


Second, consider the check boxes:

  • Four functions are used in relation to the provided check boxes: setChecked, checkAll, unCheckAll, and getChecked.
  • Your code can check, clear, and process the check boxes regardless of whether they are visible. You change the visibility of those check boxes by assigning a value to the DataGrid showCheckBoxes property.
  • Listener functions run in response to the user's selecting or clearing a check box or in response to the invocation of any of the following functions: setChecked, checkAll, or unCheckAll.
  • The listener functions are referenced from the DataGrid checkBoxListeners property.

DataGrid Paging

In the previous sections, we have introduced all properties of DataGrid. There are three properties will affect the DataGrid paging, pageSize, showButtonBar and showScrollBar. You can modify the paging setting by these three properties. In this section we’ll give a simple demo for DataGrid paging. This page using function gotoPage to switch the different page, and also added a pageChangeListener for DataGrid.

package client;

// RUI Handler

import org.eclipse.edt.rui.widgets.Button;
import org.eclipse.edt.rui.widgets.DataGrid;
import eglx.lang.SysLib;
import eglx.persistence.id;
import eglx.ui.rui.Event;
import eglx.ui.rui.RUIHandler;

//
//
handler PageDemo type RUIhandler {initialUI = [ grid, FirstPage, Button, Button1, LastPage ],onConstructionFunction = start, title="PageDemo"}
	
	grid DataGrid {
		id = "pageDemo", 
		pageSize = 5,
		margin = 20,
		showButtonBar = false,
		pageChangeListeners = [myPageChangeListener,myPageChangeListener1]		
	};
	FirstPage Button{ text = "FirstPage", onClick ::= FirstPage_onClick };
	Button Button{ text = "Previous Page", onClick ::= Button_onClick };
	Button1 Button{ text = "Next Page", onClick ::= Button1_onClick };
	LastPage Button{ text = "Last Page", onClick ::= LastPage_onClick };
	
	function start()
		data GridEmployee[];
		names String[] = [ "Jane", "Joe", "Mary", "Fred" ];
		for (n int from 1 to 92)
			data.appendElement(new GridEmployee { 
				id = n, age = 20 + n % 6,  name = names[1+n%4],home = n%2 == 1
			});
		end
		data[2].name="";
		data[4].name="";
		grid.data = data as any[]; 
	end
	
	function FirstPage_onClick(event Event in)
		grid.gotoPage(1);
	end	
	
	function Button_onClick(event Event in)
		grid.gotoPage(grid.getCurrentPageIndex() - 1);
	end
	
	function Button1_onClick(event Event in)
		grid.gotoPage(grid.getCurrentPageIndex() + 1);
	end
	
	function LastPage_onClick(event Event in)
		grid.gotoPage(grid.getPageCount());
	end
	
	function myPageChangeListener(grid DataGrid in, oldPageIndex int in, newPageIndex int in)
		syslib.writeStdout("Page Change from " + oldPageIndex + " to "+ newPageIndex);
	end
	
	function myPageChangeListener1(grid DataGrid in, oldPageIndex int in, newPageIndex int in)
		syslib.writeStdout("The second page change listener is invoked");
	end
end

record GridEmployee

	id int;
	name String;
	age int;
	home boolean;  
		
end

Behavior Demo

In the previous sections, we have already introduced the behaviors, headerBehaviors and editorBehaviors properties. They use a delegate function to let user add there own functions to the DataGrid to modify the cell/header behaviors. Here is a simple demo for editorBehaviors. In this demo, different column use different widgets, and the onChange listener are set differently for each column.

package client;

// RUI Handler

import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.CheckBox;
import org.eclipse.edt.rui.widgets.Combo;
import org.eclipse.edt.rui.widgets.DataGrid;
import org.eclipse.edt.rui.widgets.DataGridColumn;
import org.eclipse.edt.rui.widgets.HTML;
import org.eclipse.edt.rui.widgets.TextField;
import eglx.java.class;
import eglx.persistence.id;
import eglx.persistence.sql.Column;
import eglx.rbd.StrLib;
import eglx.ui.rui.Event;
import eglx.ui.rui.RUIHandler;
import eglx.ui.rui.Widget;

//
//
handler EditorBehaviorDemo type RUIhandler {initialUI = [ ui ],onConstructionFunction = start}
	
	grid DataGrid {
		editorBehaviors = [myFunction],
		id = "EditorBehaviorDemo", 
		columns = [
			new DataGridColumn { name = "id", displayName = "ID"},
			new DataGridColumn { name = "age", displayName = "Age"},
			new DataGridColumn { name = "name", displayName = "First Name"},
			new DataGridColumn { name = "home", displayName = "@Home"}
		],
		pageSize = 7,
		margin = 20
	};
	
	html HTML = new HTML{ text = "<h3>EditorBehaviorDemo shows how to set cell widget for DataGrid.</h3><br/>" + 
	"Enter row index and column index in the textfield, then click enable cell widget to toggle cell widget for the specified row/column <br/>" +
	"Click Get Cell Widget, the age column of row 2 should have red background.<br/>" +
	"The buttons should only affect 1 grid<br/>" + 
	"The \"FirstName\" value in the first grid should be stored after paging and sorting"};
	ui Box{ padding=8 ,columns=1, children=[ html, grid ]};
	TextField1 TextField{maxlength=2,marginRight=12, width=10};
	TextField2 TextField{maxlength=2,marginRight=12, width=10};
	TextField3 TextField{maxlength=2,marginRight=12, width=10};
	TextField4 TextField{maxlength=2,marginRight=12, width=10};
	isActivated boolean = true;
	
	function start()
		data GridEmployee[];
		names String[] = [ "Jane", "Joe", "Mary", "Fred" ];
		for (n int from 1 to 10)
			data.appendElement(new GridEmployee { 
				id = n, age = 20 + n % 6, name = names[1+n%3], home = n%2 == 1
			});
		end
		grid.data = data as any[];
	end
	
	function myFunction(grid DataGrid in, cell Widget in,rowData any in, rowIndex int in, column DataGridColumn in, value any in) returns (Widget) 
		case(column.name)
			when("name") 
				combo Combo { values = [ "Jane", "Joe", "Mary", "Fred" ], onChange ::= handleComboChange };
				selIndex int = 0;
				for (n int from 1 to combo.values.getSize() by 1)
					if (value as String == combo.values[n])
						selIndex = n;
						exit for;
					end
				end
		 		combo.selection = selIndex;
				return (combo);
			when("age")
				editor TextField { 
					backgroundColor = "transparent",
					borderWidth = 1,
					padding = 0,
					marginTop = -1,
					marginBottom = -1,
					text = value,
					fontSize = "1.0em",
					onChange ::= handleTextFieldChange,
//					onFocusLost ::= textFieldFocusLost, 
//					onKeyPress ::= textFieldKeyPress,
					class = "EditableGridEditor"		
				};
				return (editor);
			when("home")
				editor CheckBox {
					selected = (value as String == "true"),
					onChange ::= handleCheckBoxChange,
					class = "EditableGridCheckBox"		
				};
				return (editor);
			otherwise
				return (null);
		end
	end	
	
	function handleTextFieldChange(e Event in)
		text TextField = e.widget;
		cell Widget = text.parent;
		rowNumber int = cell.getAttribute("row");			
		columnNumber int = cell.getAttribute("column");
		columnName String = strlib.lowerCase(grid.columns[columnNumber].name);
		grid.data[rowNumber][columnName] = text.text;	
	end
	function handleCheckBoxChange(e Event in)
		check CheckBox = e.widget;
		cell Widget = check.parent;
		rowNumber int = cell.getAttribute("row");			
		columnNumber int = cell.getAttribute("column");
		columnName String = strlib.lowerCase(grid.columns[columnNumber].name);
		grid.data[rowNumber][columnName] = check.selected;	
	end
	function handleComboChange(e Event in)
		combo Combo = e.widget;
		cell Widget = combo.parent;
		rowNumber int = cell.getAttribute("row");			
		columnNumber int = cell.getAttribute("column");
		columnName String = strlib.lowerCase(grid.columns[columnNumber].name);
		grid.data[rowNumber][columnName] = combo.values[combo.selection];	
	end
end

DataGrid Tooltips

If you wish to include a tooltip for a data grid, you have two main alternatives:

  • If you wish the tooltip to be displayed whenever the cursor hovers over the data grid and not to vary according to the cell, row, or column, assign the data grid as a whole to a tooltip. For details, see “Rich UI Tooltip.” You might declare a tooltip as a global widget and enable it (making it active) in some function; for example, in the on-construction function or in a function identified in the behaviors or headerBehaviorsproperty.
  • If you wish the tooltip to specify different tooltip information for a given cell, row, or column outside of the header, you can specify a data- grid tooltip, which is similar to a tooltip but always requires that you specify a grid-tooltip provider function. That function returns a box that provides the content to display to the user. You can specify only one tooltip.

Here is the process for creating a data-grid tooltip:

  • Declare a grid-tooltip handler globally, as in the following example, which references a grid-tooltip provider (the function to invoke) and a delay (the number of milliseconds between the start of the hover and the invocation of the provider):
gridTooltip DataGridTooltip { provider = tooltipText, tooltip.delay = 1000 };

That declaration requires that you include the following import statement:

import egl.rui.widgets.DataGridToolTip;
  • Reference a function in the grid-tooltip handler when you assign an array for the behaviors property. In this example, the function isgridToolTip.setToolTips.
  • Create a grid-tooltip provider function with the name specified in the DataGridToolTip provider property (in this example, the function istooltipText). The grid-tooltip provider function has the parameter and return-value characteristics outlined in the following Delegate part:
Delegate DataGridTooltipTextProvider(rowData any in, fieldName String in, td Widget in) returns(Box)  end

row: The row provided to the function. You can use the input argument to access a specific value. For example, consider the case in which the data is as follows:

stocks Stock[] = [
		 new Stock{Symbol = "Company1", Quote = 100, NumShares = 40, SelectQuote = false}, 
		 new Stock{Symbol = "Company2", Quote = 200, NumShares = 10, SelectQuote = false}
	]; 

Inside the provider function, you can determine which row is being hovered over by writing code such as this:

if (rowData.Quote as int == 200)
   // place content in a box (the tooltip) and return the tooltip
end

fieldName: Name of the column provided to the function.
td: An internal widget that represents the grid cell.


  • You do not enable the data-grid tooltip; it is enabled as soon as you declare it.
  • If your users are accessing a Rich UI application by way of Microsoft Internet Explorer 8 or less, be aware of the issue described in “Rich UI memory management for Microsoft Internet Explorer.”

DataGrid Formatter

DataGrid formatter allows user to add an array of functions that run in array-element order before the grid is rendered. These functions run once for every cell in the column. User can use these function to adopt different formatter for different cell values.
There are many build-in formatters in org.eclipse.edt.rui.widgets.DataGridFormatters.egl. For example, percentage, fontWeightItalic, makeLink etc. Or user can add there own formatter functions to DataGrid. Actually, the simple DataGrid demo in second section included the formatter property.

Add Customized Sorting Function

When user clicking on the header, the DataGrid items will be sort by default sorting functions. User can also create there own sorting functions. Here is a demo for customized sorting functions. In this demo, the columnComparator field of “Age” column is set to a customized function “myColumnComparator”. It will always set 23 as the smallest number. And also sorting listeners are added to this DataGrid.

package client;

// RUI Handler

import org.eclipse.edt.rui.widgets.Button;
import org.eclipse.edt.rui.widgets.ColumnComparator;
import org.eclipse.edt.rui.widgets.DataGrid;
import org.eclipse.edt.rui.widgets.DataGridColumn;
import org.eclipse.edt.rui.widgets.DataGridLib;
import org.eclipse.edt.rui.widgets.HTML;
import eglx.lang.SysLib;
import eglx.persistence.id;
import eglx.ui.rui.Event;
import eglx.ui.rui.RUIHandler;


//
//
handler ListenersDemo type RUIhandler {initialUI = [ html, grid ],onConstructionFunction = start, title="ListenersDemo"}
	
	grid DataGrid {
		id = "SimplestGrid", 
		pageSize = 5,
		margin = 20,
		showCheckBoxes = true,
		sortListeners = [mySortListener,mySortListener1],
		columns = [
			new DataGridColumn{name = "iD", displayName = "ID"},
			new DataGridColumn{name = "Name", displayName = "Name"},
			new DataGridColumn{name = "Age", displayName = "Age", columnComparator = myColumnComparator},
			new DataGridColumn{name = "Home", displayName = "Home"}
		]
	};

	html HTML { text="Use Comparator delegate to rewrite age sorting. <br/> Age = 23 will always be the smallest when sorting age. "};
	function start()
		data GridEmployee[];
		names String[] = [ "Jane", "joe", "Mary", "Fred" ];
		for (n int from 1 to 96)
			data.appendElement(new GridEmployee { 
				id = n, age = 20 + n % 6, name = names[1+n%3], home = n%2 == 1
			});
		end
		grid.data = data as any[]; 
	end	

	
	function mySortListener(grid DataGrid in, sortColumn DataGridColumn in)
		direction string;
		if(sortColumn.sortDirection == DataGridLib.SORT_DOWN)
			direction = "Down";
		else
			if(sortColumn.sortDirection == DataGridLib.SORT_UP)
				direction = "Up";
			else
				direction = "None";
			end
		end
		syslib.writeStdout("Sort column "+ sortColumn.name + " with direction " + direction);
	end
	
	function mySortListener1(grid DataGrid in, sortColumn DataGridColumn in)
		syslib.writeStdout("The second sort listener is invoked");
	end
	
	function myColumnComparator(data1 any in, data2 any in) returns(int)
		if(data1 as int==23) return (-1); end
		if(data2 as int==23) return (1); end
		if(data1 as int - data2 as int > 0) return (1);
		else return(-1); end
	end
end

Use dataLoader

dataLoader is a function reference. The function itself is hereafter called the data loader and is invoked repeatedly at run time to provide a subset of values for display on the grid. Typically, each subset is a page of data, and you set the showButtonBar property to true so that the user can click from one page to the next. By using a data loader, you access a subset of data in response to the user's request, rather than accessing all the data at once.
Here is the Delegate part to which each function must conform:

Delegate DataLoader(startRow int in, endRow int in, sortFieldName string in, 
                    sortDirection int in) returns(boolean)
end

startRow: The number of the first row for which data is being requested.
endRow: The number of the last row for which data is being requested.
sortFieldName: The value of the name field of the column that the user last sorted. If the user did not sort a column, this value is the name of the leftmost column in the grid.
sortDirection: One of the following constants, to indicate what the user's next request for a sort will do
    DataGridLib.SORT_UP (the initial default)   ---   The user's click will sort the column in ascending order.
    DataGridLib.SORT_DOWN   ---   The user's click will sort the column in descending order.
    DataGridLib.SORT_NONE   ---   The user's click will have no effect.

The return value indicates whether the data was already loaded for the specified rows. Set this value to false to indicate that your logic is going to update the data array. Set the value to true to prevent the data loader from running unnecessarily. For example, your code might read as follows:


if (dataComplete) 
   return(true);
else
   // do the processing needed to add data to the specified rows
end  

The example assume that, after a service provides all that data that can be shown, you are setting a variable named dataComplete to true. The condition in the if statement prevents the data loader from doing subsequent work in your application.

Here are additional details:

  • If the dataLoader property is set in the dataGrid declaration, the data loader is invoked before the on-construction function. In any case, the data loader is invoked whenever a value is assigned to the data property and during other assignments.To keep the data loader from accessing Rich UI handler fields before they are initialized, omit the data and dataLoader properties from the dataGrid declaration. Include statements like the following two at the end of the on-construction function:
myGrid.dataLoader = myDataLoader;
myGrid.data = myDataList as ANY[];
  • The process of loading a subset of data starts with an invocation of the data loader and continues as values are placed in the data array. You end the process by invoking the grid-specific render function; for example, in the callback function that you set up to retrieve data from a service.
  • If the data loader cannot receive data for a given set of rows, invoke the grid-specific cancelDataLoader function; for example, in the exception handler that you set up to respond to a service failure.
  • Your use of a button bar will work best if you provide a complete data array early in processing, even if the content of that array is provided as the user clicks the button bar. You can preset the number of elements, but might fulfill a process like this: include a single element in the data array and then retrieve the final count of elements during a first invocation of a stateful service.