OpenSwing Framework - advanced graphics Swing components - server side integration with Spring

 

5.6 Grid control

Grid control is based on org.openswing.swing.client.GridControl class. Inside this component a programmer che drop grid columns using the graphical designer of the IDE or by adding columns to the grid control directly on source code; grid columns are defined within org.openswing.swing.table.column.client package.

A grid is always connected to its data model, i.e. the class org.openswing.swing.table.model.client. VOListTableModel that stores inside it a list of value objects, one for each grid row, where each grid column is mapped in exclusive mode to a specific attribute of the value object. Value objects list and grid content are synchronized in real time: a change in a value object is immediately propagated on the grid content and a change applied to a cell in the grid fires an update on the related v.o.'s attribute.

To specifty the value object type supported by the grid, the programmer must call the method:

public final void setValueObjectClassName(String valueObjectClassName)

 

Data showed in grid can be loaded at all or loaded a page at a time. The vertical scrollbar of the grid can be used to scroll between pages of data, while the cursor of the bar is near the top/bottom ends; it is possible to scroll data pages also through two pagination buttons inside the scrollbar that can be hided/showed though the boolean property ClientSettings.SHOW_PAGINATION_BUTTONS_ON_GRID.

Example of grid content:

Optionally a filter/sort panel could be showed at the right margin of the gri, according to ClientSettings.FILTER_PANEL_ON_GRID value. If this setting is set to true, then when the mouse is over the right margin of the grid the filtering/sorting panel is automatically showed. This panel is equivalent to the dialog window opened from the filter button (described below).

 

5.6.1 Grid columns

OpenSwing supports many types of columns; each column has many properties that customize its usage. Tthere are properties that are common to all column types:

  • "columnName" –attribute name in the value object whose value will be showed inside the grid column; if the property "headerColumnName" is not defined, then the header column will have as text the translation of "columnName" value (see "Internationalization" paragraph). If a value object contains inner value objects, then it is possible to bind the controls to an attribute of an inner value object, by specifing the complete path from the outside attribute to the most inner attribute (e.g. "taskVO.taskCode", if the Form value object contains getTaskVO() method that returns the inner value object TaskVO and this one contains getTaskCode() method)
  • "headerColumnName" – text to show as column header; this property value will be automatically translated by the grid according to internationalization settings (se "Internationalization" paragraph)
  • "headerTextAlignment" – define horizontal alignement for text showed in the column header; allowed values: "SwingConstants.LEFT", "SwingConstants.RIGHT", "SwingConstants.CENTER"
  • "maxWidth" – maximum colunm width
  • "minWidth" – minimum colunm width
  • "preferredWidth" – colunm width
  • "sortingOrder" – position of the column in the ORDER BY clause included in the query used to populate the grid, when the column has to be sorted; this attribute must be filled only if the column is sorted when the grid is showed, i.e. only if "sortingVersus" attribute has been setted
  • "sortingVersus" – sorting versus for the column, that has to be sorted when the grid is showed; possible values: Consts.NO_SORTED, Consts.ASC_SORTED, Consts.DESC_SORTED
  • "columnDuplicable" – flag used to define if the value contained in a cell belonging to the column must be copied to the new row added to the grid
  • "columnFilterable" – flag used to define if grid content must be filtered by the condition: "columnName equals filteringValue"
  • "columnRequired" –define that the column is mandatory; when a column is declared as mandatory, the saving algorithm checks if there exist a void cell belonging to that mandatory column; if a void cell exists, then saving operation is interrupted and a warning message is showed
  • "columnSelectable" – flag used to declare as "selectable" the column, i.e. the column name will be inserted in the popup menu showed by right clicking the mouse on grid; the user can (de)select the column name from the popup menu to show/hide the related column in the grid
  • "columnSortable" – flag used to define if the column is sortable; if a column is declared sortable then it's allowed to sort the column by clicking on the column header; column header acts as a three state button: "column not sorted" -> "column sorted with ascending versus" -> "column sorted with descending versus" -> "column not sorted"
  • "columnVisible" – flag used to set column visibility
  • "columnEditableOnInsert" - enable column editing when the grid is switched to insert mode
  • "columnEditableOnEdit" – enable column editing when the grid is switched to edit mode
  • “headerFont" – allows to define the font to use for all column headers
  • "headerForegroundColor - allows to define the foregound color to use for all column headers
  • "textAlignment - allows to define the horizontal alignment to use for all cell content; allowed values: “SwingConstants.LEFT", "SwingConstants.RIGHT", "SwingConstants.CENTER"
  • "additionalHeaderColumnName" – allows to define the text in the additional column header, that must be showed above the standard column headers (only when additionalHeaderColumnSpan>0)
  • "additionalHeaderColumnSpan" – allows to define how many columns (col span) this additional column header must fill (above the standard column headers); the default value is zero, i.e. no additional column headers are showed. Note that when this property is activated (i.e. >0), column resizing is limited inside columns belonging to the same additional column header . Moreover, the panel that contains the additional column headers is showed only if the values of “additionalHeaderColumnSpan” property for all columns are compatible each other, i.e. there are not columns put on top of others.

 

In the following figure is showed an example of grid having the additional column headers.

 

The following table reports available column types and a brief description for each of them.

Column type

Description

Text column

org.openswing.swing.table.column.client.TextColumn – it allows to show/edit text on the column.

This column provides additional properties:

  • "maxCharacters" – maximum number of characters in insert/edit
  • "trimText" – define if text must be trimmed, i.e. if spaces characters at the left and on the right of text must be removed
  • "encryptText" – define if text must be encrypted, i.e. it's showed as *** and stored inside the data model in clear mode; it is useful when setting password
  • "rpadding" – define if must be applied right padding on the text (additional spaces added on the right of the text until the text length is exactly uquals to "maxCharacters"); this property is useful when the graphics control is linked to a database field of type CHAR.
  • "upperCase" - define if text is always expressed in uppercase

Numeric column –

integers only

org.openswing.swing.table.column.client.IntegerColumn – show/edit integer numbers only; number is formatted according to internationalization settings.

This column provides additional properties:

  • "maxValue" – maximum number allowed
  • "minValue" – minimum number allowed
  • "grouping" – define if thousand symbol must be showed

Optionally a programmer can invoke the method:

setDynamicSettings(IntegerColumnSettings dynamicSettings)

to dinamically change numeric column properties, for each grid row.

Numeric column –

decimals allowed

org.openswing.swing.table.column.client.DecimalColumn – show/edit decimal numbers; number is formatted according to internationalization settings.

This column provides additional properties:

  • "decimals" – maximum number of decimal digits
  • "maxValue" – maximum number allowed
  • "minValue" – minimum number allowed
  • "grouping" – define if thousand symbol must be showed
  • "hideZeroDigits" – define if zero digits (after decimal symbol) must be hided/showed

Optionally a programmer can invoke the method:

setDynamicSettings(DecimalColumnSettings dynamicSettings)

to dinamically change numeric column properties (or curreny column properties), for each grid row; in this way a programmer can define max number of decimals or the currency symbol, according to his needs, e.g. by showing in the same grid rows having prices expressed with several currencies.

Percentage column

org.openswing.swing.table.column.client.PercentageColumn – show/edit decimal numbers, expressed in percentage format; number is formatted according to internationalization settings.

This class extends DecimalColumn, so that it inherits all column properties.

Currency column

org.openswing.swing.table.column.client.CurrencyColumn – show/edit decimal numbers, expressed with a currency format, i.e. with a currency symbol, decimal and thousand symbols; number is formatted according to internationalization settings.

This class extends DecimalColumn, so that it inherits all column properties; moreover it has another property:

"currencySymbol" – that defines the currency symbol.

Date + calendar column

org.openswing.swing.table.column.client.DateColumn – show/edit a date + calendar; the date is formatted according to internationalization settings.

Date + calendar + hour column

org.openswing.swing.table.column.client.DateTimeColumn – show/edit a date + time + calendar; the date and time values are formatted according to internationalization settings.

Hour column

org.openswing.swing.table.column.client.TimeColumn – show/edit a time; the time value is formatted according to internationalization settings.

Lookup column

org.openswing.swing.table.column.client.CodLookupColumn – show a text or number when the cell is not edited and a lookup when the cell is currently in edit.

This column provides additional properties:

  • "controllerClassName" – an (optional) class name that represents a graphical functionality dedicated to the definition of codes selected in the lookup (i.e. for listing, inserting, editing, deleting of codes); this graphical functionality will be invoked by the lookup when the user clicks on "+" button; this button will be visible only if this property is setted
  • "maxCharacters" – maximum number of characters in insert/edit in the validation field
  • "allowOnlyNumbers" – define if a code is a numeric code (i.e. only digits are allowed) or an alphanumeric code; this property is useful when the code is related to a database field of numeric type
  • "codePadding" – define if must be applied right padding on the text inside the code field (additional spaces added on the right of the text until the text length is exactly uquals to "maxCharacters"); this property is useful when the graphics control is linked to a database field of type CHAR.
  • "enableCodBox" – define if the code field is enabled; code field could be disabled when the field is used to show a description that must not be validated but only selected by means of lookup button
  • "hideButton" – define if the lookup button must be hidden; button hiding could be useful to force the user to specify a code in the code field (a code that must be known a priori)
  • "hideCodBox" – define if code field must be hidden; code field hiding could be useful when there is no code to show and user has always to select a code from a list of codes (e.g. when the code is a progressive that must not be showed to the user)
  • "zeroLengthAsNull" – define if a zero length code in code field must be interpreted as null value
  • "autoCompletitionWaitTime" - wait time (expressed in ms) before showing code auto completition feature for lookup controls; default value: ClientSettings.LOOKUP_AUTO_COMPLETITION_WAIT_TIME ( = -1, i.e. do not enable auto completition)

 

Check-box column

org.openswing.swing.table.column.client.CheckBoxColumn – show a text when the cell is not edited and a check-box when the cell is currently in edit.

This column provides additional properties:

  • "positiveValue" – value that the combo-box interprets as a check-box selection, i.e. if the attribute value in the v.o. is equals to "positiveValue" then the check-box is selected and if the user selects the check-box then the attribute value in v.o. is set to "positiveValue"
  • "negativeValue" – value that the combo-box interprets as a check-box deselection, i.e. if the attribute value in the v.o. is equals to "negativeValue" then the check-box is unchecked and if the user uncheks the check-box then the attribute value in v.o. is set to "negativeValue"
  • "enableInReadOnlyMode", define if the chek-box is enabled also when the grid is in readonly mode; default value: "false" i.e. the check-box is enabled only in INSERT/EDIT modes, according to "editableOnEdit" and "editableOnInsert" properties
  • "allowNullValue", allows to add to check-box a third optional state: null, i.e a check box can be selected, deselected and set to null.

If the attribute value in the v.o. is null then the check-box is unchecked.

If the two properties reported above are not defined, then the check-box assumes that the positive value is Boolean.TRUE and the negative value is Boolean.FALSE.

A programmer can listen check-box selection events by registering an ItemListener on the column, through the addItemListener method.

 

Button column

org.openswing.swing.table.column.client.ButtonColumn – show a button inside the cell that is enabled only when the cell is currently in edit.

As default behaviour, the button shows a "…" text within it.

This column provides additional properties:

  • "text" – allows to define an alternative text to show inside the button, that replace the default "…" text
  • "showAttributeValue", define if the button must show a fixed text ("…" or the text defined through "text" property) or the attribute value of the value object linked to each grid row (i.e. a dynamic text or an image)
  • "enableInReadOnlyMode", define if the button is enabled (according to GridController.isCellEditable method) also when the grid is in readonly mode; default value: "false" i.e. the button is enabled only in INSERT/EDIT modes, according to "editableOnEdit" and "editableOnInsert" properties
  • "icon" - an Icon object or ImageIcon object that will be showed inside the button
  • "iconName" - a file name related to an image to show inside the button

In insert/edit grid mode, the button can be clicked; a programmer can listen click events by registering an ActionListener on the column, through the method addActionListener.

Note that it is required to bind the ButtonColumn to an attribute in the v.o.; this attribute usually is of type String (when used to show a text within the button) or of type byte[] or of type Icon/ImageIcon (when used to show an icon within the button).

 

Combo-box column

org.openswing.swing.table.column.client.ComboColumn – show a text when the cell is not edited and a combo-box when the cell is currently in edit.

This column provides additional properties:

  • "domain" – define the domain linked to this combo-box (list of combo items)
  • "domainId" – define the domain identifier, by which the combo-box automatically retrieves the domain from ClientSettings class
  • "nullAsDefaultValue" – define if the combo-box must be initialized with a null value (i.e. no selected item)

A programmer can listen combo-box item selection events by registering an ItemListener on the column, through the addItemListener method.

Image column

org.openswing.swing.table.column.client.ImageColumn – shows an image related to the attribute of byte[] type contained in the value object of the grid row; when the grid control is in insert/edit mode, then a button may be showed to allow the image selection from local file system.

This column provides additional properties:

  • "fileFilter" – allows to define the list of image formats supported in the window used to select an image from file system; the default setting is to allow the selection of images having file extension "gif" or "jpg"
  • "showButton" – define if the button for image selection is (in)visible; default value: "true"

ImageControl provides a utility method that can be used to listen ActionEvents fired by the selection button:

public void addActionListener(ActionListener listener)

by means of this method it is possible to capture the event of image selection: the property ActionCommand of ActionEvent argument contains the selected image path.

When using an image column, there could be useful to define two properties of grid control, that allow to change grid row heights, according to image heights (that could be fixed or variable):

  • "rowHeight" – define height of all rows of the grid: if all images have a fixed maximum dimension, then this property can be useful to set a maximum height, so that all images will be completely showed.
  • "rowHeightFixed" – this flag is set to "true" as default value: when it is set to "false", each grid row will have a specific height that depends on the image height showing inside it, so that each row is adapted to the image and the grid will be compacted according to images heights.

FormattedTextColumn

org.openswing.swing.table.column.client.FormattedTextColumn

A wrapper of javax.swing.JFormattedTextField. See Swing Javadoc about JFormattedTextField for more information.

Multi line text column

org.openswing.swing.table.column.client.MultiLineTextColumn – it allows to show/edit multi line text on the column.

This column provides an additional property: "maxCharacters" – maximum number of characters in insert/edit

Multiple type column

org.openswing.swing.table.column.client.MultipleTypeColumn – it allows to show in the same column data having several types, such as text, numeric, date, check-box, combo-box, etc. The attribute associated to this column must be of any type, but usually it should be of type Object, so it can host any data type. Through the column property "typeController" it is possible to define the exact type to use for each cell in the column. This is possible by overriding two methods:

  • "getCellType" - it requires to define the cell type, as a Column.TYPE_xxx value
  • "getAdditionalProperties"; this method can optionally be used to define additional properties for a specific cell editor , such as max chars for a text type cell editor, or the max numeric value for a numeric cell editor, a lookup controller for a lookup cell editor, the domain identifier for a combo-box editor, etc.

Progress bar column

org.openswing.swing.table.column.client.ProgressBarColumn

This column provides a read only progress bar; it has several additional properties:

  • "minValue" – minimum value allowed in the progress bar; default value = 0
  • "maxValue" – maximum value allowed in the progress bar; default value = 100
  • "color" - i.e. the current used color
  • "showAllBands" - flag used to determine how to color the progress bar: <code>true</code> to paint the bar with many colors, each band with its color, <code>false</code> to paint the bar with ony one color: the color related to the last matched band

The latter method is used when a programmer has defined some colored bands in the progress bar, through the method:

public final boolean addColoredBand(double minValue, double maxValue, Color color)

This method adds an interval [minValue,maxValue] and a color to use to paint that interval.

combo box multi-column

org.openswing.swing.table.column.client.ComboVOColumn


The content of a combo-box column is defined starting from a list of value objects, retrieved through an ItemsDataLocator. More than one v.o. attributes can be mapped as combo item and these attributes can also be mapped to the container v.o. (i.e. the v.o. of the grid or of the Form). This input field has several additional properties:

  • "nullAsDefaultValue" – define if combo-box must be initialized with a null value (i.e. no item is selected at the beginning)
  • "allColumnPreferredWidth" - the width of each column showed in the combo item
  • "allColumnVisible" - define if all attributes defined in the combo v.o. will be visible in the combo item

This input field provides some mandatory methods that a programmer must invoke:

  • "addCombo2ParentLink" - as for a lookup (see lookup section), define which combo attributes must be linked to container's v.o. attributes
  • "setComboValueObjectClassName" - define the v.o. type associated to each combo item
  • "setComboDataLocator"- define an ItemsDataLocator class that will be automatically invoked by the combo box to fetch items (i.e. the list of value objects)

Moreover, the input field allows to specify which combo's v.o. attributes to use to compose an item, through the following methods:

  • "setPreferredWidthColumn" - the column width, for a specified attribute
  • "setVisibleColumn"- define if the specified attribute must be mapped in the combo item.

File column

org.openswing.swing.table.column.client.FileColumn


This column can contain three widgets: the name of the file, an upload button and a download button. All these widgets are optional and can be hided/showed using the following properties:

  • "showUploadButton" – flag used to show/hide upload button; when pressing this button the user can select a file from local file system using standard file dialog, after that the file is read as byte[] and stored in the cell (cell must be of type byte[]); this button is disabled when the grid is in read only mode
  • "showDownloadButton" – flag used to show/hide download button; when pressing this button the user can save byte[] stored in the cell in the local file system: a file dialog is showed in order to select where to save the file
  • "fileNameAttributeNAme" – when this property is specified, the file name is showed on the left of the two buttons: when uploading a file from local file system, its name is showed in the label and stored in the value object attribute identified by this property

 

5.6.2 Popup menu

When a grid is in read only mode and the user clicks with the right mouse button on a grid's cell, a popup menu will be showed over the grid; this popup menu contains:

  • Quick filter applied to a grid colum – a quick filter is composed of a filter input field and a filter button; the filter field is filled with the cell content on which the user has clicked and user can modify that values; initial value can be replaced using getInitialQuickFilterValue() callback method available in GridController class. When user clicks on the filter button, the grid content will be filtered with an additional filter clause: "column equals to filter value". After filter button pressing, filter value can be replaced using beforeFilterGrid() callback method available in GridController class. User can apply filters on each grid column that has been defined as filterable (see "columnFilterable" property of a grid column).
    Filter value can include "%" symbol to enlarge search criteria or can be select one of the following criteria: field equals to filter value, field contains filter value (i.e. "like %filterValue%"), field starts with filter value (i.e. "like filterValue%"), field ends with filter value (i.e. "like %filterValue"). Moreover, "like" operator can be customized via ClientSettings.LIKE global property: for instance it can be replaced by "ilike" case insensitive operator for PosgreSQL database.
    It is possible to preset a default criteria, by setting the "defaultQuickFilterCriteria" property in GridControl component; this property has a default value defined as ClientSettings.DEFAULT_QUICK_FILTER_CRITERIA. This is pre-set to Consts.EQUALS. In this way you are able to define a default criteria valid for all grids in an application by defining ClientSettings.DEFAULT_QUICK_FILTER_CRITERIA property or define a default criteria for a specific grid component by defining the "defaultQuickFilterCriteria" property in GridControl.

    Optionally a search criteria can be defined as an interval, i.e. by specifying a lower and upper value (tipically for numeric or date values).

    In this way user can apply filters on the grid in a very quick way.
    It is possible to open the popup menu by pressing the combination CTRL+Q; to close it the ESC key can be pressed. To apply a filtering condition it is possible to press the ENTER button inside an input filter field.

  • List of selectable columns (i.e. grid column having "columnSelectable" property set to "true") – each selectable column reported in the popup menu acts a toggle button: by clicking on it user can switch column visibility state; so that, the user may change columns visibility by selecting columns from this list.

  • Grid profile management – in the same popup menu it could be showed a "Grid profile management" menu item. This item is visible only if ClientSettings.GRID_PROFILE_MANAGER is initialized with the object new FileGridProfileManager() and the grid control has defined a functionId; by means of this menu item, it is possible to store many grid profiles where a grid profile represents a snapshot of the grid, i.e. columns position, columns width, columns visibility state, columns sorting and columns filtering. All these properties are stored per user or per a specific "item", defined through the property username of FileGridProfileManager object. In this way it is possible to select a previously stored grid profile and apply it to the grid. You can create any number of grid profiles, change them or remove them simply by changing these properties on the grid (e.g. by applying a filtering condition or by sorting a column or by dragging a column to move it or reduce/extend it): these changes are automatically stored in the grid profile when the grid is closed (or when switching between two profiles).
    The "Restore default grid profile" menu item allows to restore the default grid settings, based on the source code.
    The description of the current applied grid profile is showed inside the status bar, on the right side.
    You can use a grid profile to represent a specific combination of grid properties, e.g. a combination of sorting and filterinf conditions, that can be applied simply by switch from a grid profile to another one.
    FileGridProfileManager class is the first implementation of the generic abstract class GridProfileManager: it stores grid profiles locally as files, inside the user home (e.g. "Documents and settings/<user>/profiles" folder in Windows O.S.). In the future other implementions of GridProfileManager will be available, for instance an implemention based on a database, that will store grid profiles inside ad hoc database tables.
    Another implementation of GridProfileManager is DbGridProfileManager that can be used with stand alone applications having a database. See "Demo28" as a sample application that uses three tables to manage grid profiles. This class requires 4 objects to correctly operate: a DbConnectionSource interface implementation to provide database Connection objects, an implementation of DbActiveProfileDescriptor to define the table name and columns used to store active profiles, an implementation of DbDigestDescriptor to define table name and columns used to store the grid "digest" and finally an implementation of DbProfileDescriptor to define table name and columns used to store grid profiles. There are available a default implementation of these 3 classes: DefaultDbActiveProfileDescriptor, DefaultDbDigestDescriptor and DefaultDbProfileDescriptor; see JavaDoc documentation about these classes to obtain more info. By means of these classes it is possible to define additional database fields managed directly by DbGridProfileManager class: these fields can be included to define complex primary keys for the profile tables and to manage additional database fields to fill in on insert/update operations, such as creation date or update date.

 

 

5.6.3 Supported operation modes in grid

A grid has three operation modes: inserting, editing, read only; this modes are identified by these constants: Consts.INSERT, Consts.EDIT and Consts.READONLY. By means of GridControl.setMode() method a programmer can switch between thse modes. To retrieve current grid mode a method is available: GridControl.getMode() .

When a grid is switched to INSERT mode, a new empty row is added to the grid, at the top of the grid, where cells are enabled if the related columns have "enabledOnInsert" property set to "true". When a new row is added to the grid, a new empty value object is added to the grid data model. As default behaviour, a grid allows to add only one row: the user can only save or reload (undo) that row before adding another one.

It is also possible to define when new rows must be inserted in the grid when it is in insert mode: "insertRowsOnTop" property defines whether new rows must be added at the top or at the bottom o f the grid.

It is possible to insert rows in edit mode too, when "allowInsertInEdit" property is set to "true" : in this case each time the user presses the down key on the last row of the grid, a new row is added at the bottom of the grid. When save button is pressed, GridControoller.updateRecords method is invoked: new rows and changed rows are added to "persistentObjects" argument, oldPersistentObjects list contains null elements for new rows and old value objects for changed rows. In this way a programmer is able to identify which rows must be inserted and which rows must be updated.

When a grid is in insert mode, editing operations are limited to the new row only: user is not able to move cursor to another row and clicking the mouse in another row cause the row selection to be re-set to the new row at the top of the grid. By means of " maxNumberOfRowsOnInsert " property, a grid allows to insert more than one row before saving data. If this property is set to a number greater than 1, then the user is able to move cursor or click with mouse in any new added row. To add new rows (until "maxNumberOfRowsOnInsert" number of rows) the user has to press the "down" key within the last new added row; the grid automatically adds a new row below the last one. To remove the last added row (not yet saved) the user has to press the "up" key: the grid removes the last added row only if it has not been changed yet.

When a grid is switched to EDIT mode, user can move cursor on any row of the grid and all cells related to columns having "enabledOnEdit" property set to "true" are editable. If "editOnSingleRow" grid property is set to "true" then only the current selected row will be editable.

A grid can retrieve data by reading the whole resultset or by reading only a block of data; in the second case, if a grid is in read only mode, when the user scrolls down the grid, the grid will retrieve the next block of data and when the user scrolls up a the grid, the grid will retrieve the previous block of data. If the grid is in insert or edit mode, data retrieval is disabled.

 

5.6.4 Data loading on grid

Through the property "autoLoadData" a programmer can define if the grid must automatically retrieve data when it is set to visible.

A grid automatically retrieves data when:

  • it is viewed (and "autoLoadData" property is set to "true)
  • the user applies a filter condition
  • the user applies a column sorting
  • the user scrolls the grid (and the grid is configured to load blocks of data)
  • a programmer calls "reloadData" method in the grid
  • the user presses "reload" button

In all these cases the grid control invokes the method:

public Response loadData(int action, int startIndex, Map filteredColumns, ArrayList currentSortedColumns, ArrayList currentSortedVersusColumns, Class valueObjectType, Map otherGridParams)

declared by the interface org.openswing.swing.table.java.GridDataLocator

While defining the grid, a programmer must define also an object of type GridDataLocator, through the grid's method setGridDataLocator .

To retrieve data the grid control invokes loadData method and pass to it some information:

  • "action" – i.e. the loading type: load next block of data, load previous block of data, load last block of data, according to user's actions; loading types are defined by these constants:

GridParams.PREVIOUS_BLOCK_ACTION, GridParams.NEXT_BLOCK_ACTION and GridParams. LAST_BLOCK_ACTION

  • "startPos" – i.e. the point in the resultset to reach before starting the data read
  • "filteredColumns" – filters currently applied to grid; each filter is composed of the FilterWhereClause[] array, where the object FilterWhereClause contains a triple <attribute name, operator, value> that has to be added to the WHERE clause of the query that retrieve grid's data
  • "currentSortedColumns" – list of attribute names that represent database fields to sort
  • "currentSortedVersusColumns" – list of sorting versus (ASC / DESC) to use in combination with the list of attribute names that represent database fields to sort
  • "valueObjectType" –value object type to set into the grid
  • "otherGridParams" – optional parameters to pass to the business logic dedicated to grid data retrieval; a programmer can access this collection of parameters throuth the getOtherGridParams() method of the grid control.

 

"loadData" method requires a return value of type Response; two subclasses of Response are allowed:

  • ErrorResponse – if an error occours during data retrieval
  • VOListResponse – if data retrieval was correctly completed. VOListResponse must contain a list of value objects that the grid control will store inside its data model and that use to show data within it. VOListResponse contains a "moreRows" flag indicating if there are other records next to the current block of records loaded: if data loading performs a full resultset fetching then this flag must be set to "false", so that the grid knows that there aren't any other records to fetch over the current ones and scrolling events don't generate other data loading requests.

OpenSwing provides some default implementations of GridDataLocator interface:

  • org.openswing.swing.table.java.ClientGridDataLocator – contains a void implementation of the loadData method; a programmer can use this implementation to create simple prototypes or it could override this implementation according to custom needs.
  • org.openswing.swing.table.java.ServerGridDataLocator – this implementation performs a call to ClientUtils.getData() method that will send a HTTP request to a java servlet; the generated request involves to pass an object of type org.openswing.swing.message.send.java.GridParams to the servlet; this object is a wrapper of all parameters described above and available as arguments of loadData method. The class ServerGridDataLocator includes an attribute "serverMethodName" that must be defined by the programmer: it represents the server-side service to contact that will phisically perfom the data retrieval for the grid.

This implementation of GridDataLocator has been created to work together with the server-side servlet org.openswing.swing.server.Controller (see "Server-side classes" chapter).

A programmer is free to define his own implementation of GridDataLocator interface, to contact server-side business logic according to specific requirements, such as via RMI or through SOAP protocol.

 

5.6.5 Buttons connected to a grid

E' possibile collegare i bottoni predefiniti (descritti nella sezione "Bottoni") alla griglia, tramite i metodi:

  • public final void setInsertButton(InsertButton insertButton) – by means of this method the insert button can be linked to the grid; in this way, when the insert button is pressed, the grid switches to insert mode, a new row is added to the grid those row's cells that are declared as enabled on insert will be enabled.
  • public final void setCopyButton(CopyButton copyButton) – by means of this method the copy button can be linked to the grid; in this way, when the copy button is pressed, the grid switches to insert mode, a new row is added to the grid and those row's cells that are declared as "duplicable" maintain the value of the previous selected row and those cells that are declared as enabled on insert will be enabled.
  • public final void setEditButton(EditButton editButton) – by means of this method the edit button can be linked to the grid; in this way, when the edit button is pressed, the grid switches to edit mode and those row's cells that are declared as enabled on edit will be enabled.
  • public final void setReloadButton(ReloadButton reloadButton) – by means of this method the reload button can be linked to the grid; in this way, when the reload button is pressed, the grid switches to read only mode, all rows will be disabled and data model linked to the grid will be reloaded.
  • public final void setSaveButton(SaveButton saveButton) – by means of this method the save button can be linked to the grid; in this way, when the save button is pressed, the grid will attempt to store data and, if saving operation will be correctly performed, the grid switches to read only mode and all rows will be disabled.
  • public final void setDeleteButton(DeleteButton deleteButton) – by means of this method the delete button can be linked to the grid; in this way, when the delete button is pressed, the grid will attempt to delete selected rows and, if deleting operation will be correctly performed, removes the selected rows on it.
  • public final void addGenericButton(GenericButton b) – by means of this method a generic button can be linked to the grid; in this way, the generic button will receive the same effects of the others buttons when operation mode is changed, that is, all generic buttons will be disabled on insert and edit modes and will be enabled in read only mode.
  • public final void setNavigationBar(NavigationBa navBar) – by means of this method a navigator bar can be linked to the grid; in this way, the selected row on grid can be move up or down, according to the navitator button pressed.
  • public final void setExportButton(ExportButton exportButton) – by means of this method an export button can be linked to the grid; in this way, when the export button is pressed, the grid will attempt to export data by reading all records in the resultset and creating a document (these formats are available: XLS, csv with ";" delimiter, csv with "," delimiter, XML, HTML, PDF, RTF) that will be viewed in the browser. To avoid excessive memory usage due to a large amount of records in the resultset, a programmer can restrict the records number to read from the resultset by setting the MAX_EXPORTABLE_ROWS attribute of ClientSettings singletono class.
  • public final void setFilterButton(FilterButton filterButton) – by means of this method the filter/sort button can be linked to the grid; in this way, when the filter/sort button is pressed, a dialog window will be showed: this window contains a list of filterable columns, showed through combo-boxes; for each column selected in the combo-box there exists another combo-box used to select the filter criteria (=, <, >, <=, >=, like, is null, is not null, in) to apply and an input field to specify the filter value; for numeric/date columns is available another combo criteria and another input field, used to apply a filtering condition expressed as an interval of values (min-max). For "in" operator, it is possible to specify more than one value by pressing TAB key to create another filter field next to the current one: all filter fields for the same column contain a single value of the "in" interval. Moreover, for a single column, it is possible to specify more conditions in OR each other, by pressing TAB key to create another filter value (for the same column/operator): this is allowed for each operator different from "in", "is null" and "is not null". The same window allows also to specify sorting conditions, through a second folder; sorting conditions are defined by selecting columns from combo-boxes and by selecting sorting versus (ASC/DESC).
    When the user presses the button inside this window, the grid will be reloaded, by applying filtering and sorting conditions just applied.

 

A required property that must be set in the grid control is " functionId "; this property defines an identifier associated to the grid that the grid exploits to decide if insert/edit/delete buttons must be enabled or not when the operation mode is changed: the setEnable method of these buttons always checks if the button must be enabled, by verifing authorizations defined in ClientSettings for the specified functionId. In OpenSwing buttons authorizations are defined as a collection of <functionId, related buttons authorizations> and are stored inside ClientSettings object (see buttons authorization section).

 

5.6.6 Grid Controller

A grid must be connected to a grid controller; a programmer must create a grid controller that extends org.openswing.swing.table.client.GridController class. Grid data model, grid and controller compose a tern in M-V-C pattern (Model-View-Controller), where the controller assumes the role of manager of events fired by the other two components, expecially for grid events. To connect the grid to a grid controller, a programmer has to invoke the grid method:

public final void setController(GridController gridController)

 

Grid controller provides many methods that can be overrided by the programmer::

•  public Response insertRecords(int[] rowNumbers, ArrayList newValueObjects) throws Exception – this method is automatically invoked when the grid is in insert mode and the user clicks on the save button, i.e. to save data inserted into the grid.

A programmer can override this method to store the list of new value objects passed as arguments to the method. Usually this method acts a data comunication layer, i.e. it does not contain insertion business logic: it contains instructions needed to contact the insertion business logic layer.

This method requires a return value of type Response (see "Response messages" paragraph); two type of Response subclasses are allowed: ErrorResponse if an error occours during saving data operation or a VOListResponse in case of saving correctly completed; VOListResponse object must contain the list of value object inserted; these object may be further filled with other data calculated inside the insertion business logic (such as progressives, creation date/time, etc). The grid control stores this list of v.o. into the data model and update its content.

Note that before calling this method, the grid has already checked all new row's cells to verify their validity state: this insure that the saving operation can be executed starting from a state where all mandatory cells are correctly filled. If validity check has no success, then insertRecords method is not called.

•  public Response updateRecords(int[] rowNumbers,ArrayList oldPersistentObjects,ArrayList persistentObjects) – this method is automatically invoked when the grid is in edit mode and the user clicks on the save button, i.e. to save data edited into the grid.

A programmer can override this method to store the list of changed value objects passed as arguments to the method. Usually this method acts a data comunication layer, i.e. it does not contain updating business logic: it contains instructions needed to contact the updating business logic layer.

By overriding this method, the programmer could carry on the saving operation by exploiting the list of value objects passed as argument and the same list of value objects not still changed, which were retrieved from the records's read from database before starting to edit the grid; the initial value objects can be useful for example with web applications that are concurrently accessed: before updating a changed record in the database, values from the initial value object will be used to check if the record has been already changed from another client; only if the record is not yet changed, the updating operation is performed.

The method requires as return value a Response object (see response messages paragraph): the programmer must return one of the following objects: ErrorResponse in case of error or a VOListResponse in case of saving correctly completed; VOListResponse object must contain the list of value objects updated; these objects may be further filled with other data calculated inside the updating business logic (such as update date/time, etc). The grid control stores this list of v.o. into the data model and update its content.

Note that before calling this method, the grid has already checked all changed cells to verify their validity state: this insure that the saving operation can be executed starting from a state where all mandatory cells are correctly filled. If validity check has no success, then updateRecors method is not called.

•  public Response deleteRecords(ArrayList persistentObjects) throws Exception – method automatically invoked by the grid to delete the selected rows (delete button has been pressed) when the grid is in read only mode; the list of value objects stored in data model related to the selected rows is passed as argument. By overriding this method, the programmer could carry on the deleting operation by exploiting the value objects passed as argument.

The method requires as return value a Response object (see response messages paragraph): the programmer must return one of the following objects: ErrorResponse in case of error or VOResponse in case of deleting operation correctly completed; VOResponse object must contain Boolean object, indicating the deleting result.

•  public void createValueObject(ValueObject valueObject) throws Exception – callback method automatically invoked by the grid when it is switched to insert mode data; the void value object just created and stored in the data model is passed as argument. By overriding this method, the programmer could fill some attribute values of the void value object to the purpose of setting default values in new row's cells.

•  public void loadDataCompleted(boolean error) – callback method automatically invoked by the grid when data model loading has been completed; data loading can be invoked by means of the reloadData method of the grid object. The reloadData method executes the loading in a separated thread, to the purpose of not blocking the application. By overriding this method, the programmer can intercept the data loading completed event.

A programmer can override this method to insert instructions that start data loading operations for other components, such as grids or panels detail Form/panel of the selected row in grid.

•  public void afterReloadGrid() – callback method automatically invoked by the grid when data model has been reloaded because the reload button has been pressed.

•  public void afterEditGrid(GridControl grid) - callback method automatically invoked by the grid when data updating operation has been correctly completed.

•  public void afterInsertGrid(GridControl grid) - callback method automatically invoked by the grid when data inserting operation has been correctly completed.

•  public void afterDeleteGrid() - callback method automatically invoked by the grid when data deleting operation has been correctly completed.

•  public void modeChanged(int currentMode) – callback method automatically invoked by the grid on changing the grid operation mode.

•  public boolean beforeEditGrid(GridControl grid) – callback method automatically invoked by the grid when the user has clicked on edit button. A programmer can override this method to stop operation mode switching according to custom policies, such as user authorization settings or other checks.

public boolean beforeInsertGrid(GridControl grid) - callback method automatically invoked by the grid when the user has clicked on insert button. A programmer can override this method to stop operation mode switching according to custom policies, such as user authorization settings or other checks.

public boolean beforeDeleteGrid(GridControl grid) - callback method automatically invoked by the grid when the user has clicked on delete button. A programmer can override this method to stop operation mode switching according to custom policies, such as user authorization settings or other checks.

public boolean beforeCopyGrid(GridControl grid) - callback method automatically invoked by the grid when the user has clicked on copy button. A programmer can override this method to stop operation mode switching according to custom policies, such as user authorization settings or other checks.

•  public boolean isCellEditable(GridControl grid,int row,String attributeName) – callback method automatically invoked for each grid's cell when the grid is in insert or edit mode to know whether the specified cell is editable or not. If this method is not overrided by the programmer, then the grid assumes that all cells of the same column are editable in insert or edit mode according to column properties "editableOnInsert" and "editableOnEdit".

A programmer could override this method to define a more finer custom editability policy, that can be establish editability state for each cell.

•  public void rowChanged(int rowNumber) - callback method automatically invoked by the grid when the user selects a row in the grid.

•  public void enterButton(int rowNumber,ValueObject persistentObject) – - callback method automatically invoked by the grid when the user has pressed the ENTER key. If this method is not overridden then if calles doubleClick() controller method.

public void doubleClick(int rowNumber,ValueObject persistentObject) – callback method automatically invoked by the grid when the user double clicks a grid's row. A programmer can override this methods to include instructions that open a window from the selected row, such as a detail window.

•  public void selectedCell(int rowNumber, int columnIndex, String attributedName, ValueObject persistentObject) - callback method automatically invoked by the grid when the user selects a cell in the grid.

•  public Color getBackgroundColor(int row,String attributedName,Object value) – callback method automatically invoked by the grid to retrieve the background color for each grid's cell. A programmer can override this method to specify distinct colors for grid's cells.

If the method is not overridden, then rows are colored alternatively with two different colors: one color is defined through ClientSettings.GRID_CELL_BACKGROUND attribute and the other color is slightly different from the first one, defined through getDeltaColor() method.

By means of setDetailRow() method a programmer can define the number of rows colored with the same value (default value: 1).

•  public Color getForegroundColor(int row,String attributedName,Object value) - callback method automatically invoked by the grid to retrieve the foreground color for each grid's cell. A programmer can override this method to specify distinct colors for grid's cells.

If the method is not overridden, then rows are colored with the same color, defined through ClientSettings. GRID_CELL_FOREGROUND attribute.

•  public boolean validateCell(int rowNumber,String attributeName,Object oldValue,Object newValue) – callback method automatically invoked by the grid when it is in insert or edit mode and a cell has been just changed by the user or from the program. This method requires a boolean return type that represents the validation exit code. A grid stores internally all non valid cells and uses this data to stop saving operation if there exist at least one non valid cell.

A programmer can override this method for two reasons: (i) to intercept a cell value change and perform a logic related to the change (e.g. cleaning out or filling other cells), (ii) validate the cell value, according to some validation logic.

•  public Font getFont(int row,String attributeName,Object value,Font defaultFont) – callback method automatically invoked by the grid for each cellof the grid to set the font for the text shoed inside the cell; ad default behaviour the method returns null, that means the default font has to be used for all cells.

•  public String getHeaderTooltip(String attributeName) – callback method automatically invoked by the grid for each column header: it allows to set a distinct tooltip text for a single column header

•  public String getCellTooltip(int row,String attributeName) - callback method automatically invoked by the grid for each cell: it allows to define a tooltip text for each grid's cell.

 

5.6.7 Locking rows

It is possible to lock (anchor) rows in grid:

  • by setting "lockedRowsAtTop" numeric property you are able to anchor N rows at the top of the grid
  • by setting "lockedRowsAtBottom" numeric property you are able to anchor N rows at the bottom of the grid

 

When setting one of these properties, you have to set setTopGridDataLocator or setBottomGridDataLocator method too.

These methods are automatically invoked when the grid model is loaded (i.e. when showing grid, when reloading, after applying filtering/sorting conditions). You have to return a list of value object (of the same type of the rest of the grid); these list must have the same length of the "lockedRowsAtTop" and "lockedRowsAtBottom" property values.

Optionally you could call setTopGridController of setBottomGridController to define other properties or intercept events related only to the top locked rows or bottom loked rows respectively.

Example:

      grid.setBottomGridDataLocator(new GridDataLocator() {

        public Response loadData(
            int action,
            int startIndex,
            Map filteredColumns,
            ArrayList currentSortedColumns,
            ArrayList currentSortedVersusColumns,
            Class valueObjectType,
            Map otherGridParams) {
          ArrayList rows = ...
          return new VOListResponse(rows,false,rows.size());
        }

      });

      grid.setBottomGridController(new GridController() {

        /**
         * Method used to define the background color for each cell of the grid.
         * @param rowNumber selected row index
         * @param attributedName attribute name related to the column currently selected
         * @param value object contained in the selected cell
         * @return background color of the selected cell
         */
        public Color getBackgroundColor(int row,String attributedName,Object value) {
          return new Color(220,220,220);
        }

      });

It is possible to update locked rows by accessing that rows throught the GridControl object: internally this object contains 3 "inner" grids: a top grid, the "standard" grid (i.e. the grid whose content is loaded through GriDataLocator std method) and a bottom grid.

The top grid is optional and is showed only if "lockedRowsAtTop" property has a value greater than 0: it shows the top locked rows and has a own data model, accessed through GridControl.getTopTable().getVoListTableModel()

The bottom grid is optional and is showed only if "lockedRowsAtBottom" property has a value greater than 0: it shows the bottom locked rows and has a own data model, accessed through GridControl.getBottomTable().getVoListTableModel()

In this way you are able to dinamically load rows in the "standard" grid and manually set locked rows, at the top or at the bottom of the grid, according to the needs.

 

5.6.8 Grid having nested components

GridControl component can include inside it a nested component, one for each row; a row can be expanded in two alternative ways: by showing nested component below it or within it, by replacing row default content.

It is possible to define which row are (not) expandable. Expandable rows contain a special "expansion symbol", the same showed near nodes in tree component; by clicking on this symbol a row can be expanded. An already expanded row can be collapsed by clicking on the same symbol. That symbol is always showed inside one of the visible columns of the grid: a programmer can define which column has to contain that symbol; nested component is showed starting from the expanded column until the right margin of the container grid.
A cell can be expanded/collapsed using key accelerators too: CTRL+P and CTRL+L to expand/collapse selected row. These key accelerators can be customized using ClientSettings properties EXPAND_CELL_KEY and COLLAPSE_CELL_KEY.

Nested component can be any graphical object (that derives from JComponent). For instance a hierarchy of grids can be created, composed of any number of nested grid components; for instance a main grid can be used to show orders and, by expanding one order, an inner grid can be included to show order rows; a specific order row can be expanded in order to show a third grid, reporting row discounts.

Grid editability is also supported for nested grids and also for nested Form panels.

To enable the usage of nested components inside a grid, there are some properties to set in GridControl component:

  • " expandableColumn " – define which column to use to show the "expansion symbol"
  • " singleExpandableRow " – this flag defines if only one row can be expanded per time
  • " overwriteRowWhenExpanding " – this flag defines whetherjust expanded row must be showed nested component below the current row or nested component must replace the current row
  • " expandableRowController " – row expansion feature is enabled only when this property has been filled; required argument is a class of type org.openswing.swing.client. ExpandableRow Controller . That class provides several callback methods:
    • public boolean isRowExpandable(VOListTableModel model, int rowNum) – this method is automatically invoked by grid component to check if the specified row is expandable
    • public JComponent getComponentToShow(VOListTableModel model, int rowNum) – this method is invoked by grid when user has just clicked on the "expansion symbol": return value is the nested component to show within the expanded row. It is important to specify a preferred size for nested component, through setPreferredSize() method,
    • public boolean removeShowedComponent(VOListTableModel model, int rowNum, JComponent showedComponent) – this method is automatically invoked by grid component when user collapses an expanded row: it can be used to dispose objects connected to the nested component.
    • public Component getFocusableComponent(JComponent showedComponent) - this method is automatically invoked by grid container to set focus when showing nested component

"Demo40" sample application shows how to create nested grids.

<< Previous Chapter | Next Chapter >>

Licence | Contacts | ©2007 Mauro Carniel SourceForge.net Logo