Once again, I would like to welcome guest blogger Levente Hunyadi.
Non-standard property renderers and editors
Last week, I discussed JIDE’s property table and showed how we can add custom properties and present this table in our Matlab GUI. Today, I will extend the previous week’s example to include more sophisticated renderers and editors.
Cell renderers and editors are the backbone of JTable implementations, JIDE’s property grid included. Each property is associated with a type, and a renderer and an editor may be registered for a type. The cell renderer controls how the property value is displayed, while the editor determines how it is edited. For example, flags (Java Booleans) are often both rendered and edited using a checkbox, but can also use a text renderer with a combo-box editor. PropertyTable automatically assigns a default renderer and editor to each property, based on its type: Flags are assigned a combo-box editor of true/false values, and similarly for other types.
Let us now modify the preassigned editor. First, let’s set a checkbox editor (BooleanCheckBoxCellEditor) for flags and a spinner for numbers:
% Initialize JIDE's usage within Matlab com.mathworks.mwswing.MJUtilities.initJIDE; % Prepare the properties list: % First two logical values (flags) list = java.util.ArrayList(); prop1 = com.jidesoft.grid.DefaultProperty(); prop1.setName('mylogical'); prop1.setType(javaclass('logical')); prop1.setValue(true); list.add(prop1); prop2 = com.jidesoft.grid.DefaultProperty(); prop2.setName('mycheckbox'); prop2.setType(javaclass('logical')); prop2.setValue(true); prop2.setEditorContext(com.jidesoft.grid.BooleanCheckBoxCellEditor.CONTEXT); list.add(prop2); % Now integers (note the different way to set property values): prop3 = com.jidesoft.grid.DefaultProperty(); javatype = javaclass('int32'); set(prop3,'Name','myinteger','Type',javatype,'Value',int32(1)); list.add(prop3); prop4 = com.jidesoft.grid.DefaultProperty(); set(prop4,'Name','myspinner','Type',javatype,'Value',int32(1)); set(prop4,'EditorContext',com.jidesoft.grid.SpinnerCellEditor.CONTEXT); list.add(prop4); % Prepare a properties table containing the list model = com.jidesoft.grid.PropertyTableModel(list); model.expandAll(); grid = com.jidesoft.grid.PropertyTable(model); pane = com.jidesoft.grid.PropertyPane(grid); % Display the properties pane onscreen hFig = figure; panel = uipanel(hFig); javacomponent(pane, [0 0 200 200], panel);

A property grid with checkbox and spinner controls
Notice how the EditorContext is used to specify a non-standard renderer/editor for myspinner and mycheckbox: The mylogical flag displays as a string label, while mycheckbox displays as a checkbox; myinteger uses a regular integer editor that accepts whole numbers, while myspinner uses a spinner control to modify the value.
Note that instead of creating an entirely new properties list and table, we could have run last week’s example, modified list and then simply called model.refresh() to update the display.
Also note that Matlab types are automatically converted to Java types, but we must be careful that the results of the conversion should match our setType declaration. The logical value true converts to java.lang.Boolean, but 1 by default would be a double, which is the standard numeric type in Matlab. The int32 wrapper is needed to force a conversion to a java.lang.Integer.
Spinners with indefinite value bounds are seldom useful. The following shows how to register a new editor to restrict values to a fixed range. Remember to unregister the editor when it is no longer used:
javatype = javaclass('int32'); value = int32(0); minVal = int32(-2); maxVal = int32(5); step = int32(1); spinner = javax.swing.SpinnerNumberModel(value, minVal, maxVal, step); editor = com.jidesoft.grid.SpinnerCellEditor(spinner); context = com.jidesoft.grid.EditorContext('spinnereditor'); com.jidesoft.grid.CellEditorManager.registerEditor(javatype, editor, context); prop = com.jidesoft.grid.DefaultProperty(); set(prop, 'Name','myspinner', 'Type',javatype, ... 'Value',int32(1), 'EditorContext',context); % [do something useful here...] com.jidesoft.grid.CellEditorManager.unregisterEditor(javatype, context);
The principle is the same for combo-boxes:
javatype = javaclass('char', 1); options = {'spring', 'summer', 'fall', 'winter'}; editor = com.jidesoft.grid.ListComboBoxCellEditor(options); context = com.jidesoft.grid.EditorContext('comboboxeditor'); com.jidesoft.grid.CellEditorManager.registerEditor(javatype, editor, context); prop = com.jidesoft.grid.DefaultProperty(); set(prop, 'Name','season', 'Type',javatype, ... 'Value','spring', 'EditorContext',context); % [do something useful here...] com.jidesoft.grid.CellEditorManager.unregisterEditor(javatype, context);

A property grid with a combobox control
Nested properties
Properties can act as a parent node for other properties. A typical example is an object’s dimensions: a parent node value may be edited as a 2-by-1 matrix, but width and height may also be exposed individually. Nested properties are created as regular properties. However, rather than adding them directly to a PropertyTableModel, they are added under a Property instance using its addChild method:
propdimensions = com.jidesoft.grid.DefaultProperty(); propdimensions.setName('dimensions'); propdimensions.setEditable(false); propwidth = com.jidesoft.grid.DefaultProperty(); propwidth.setName('width'); propwidth.setType(javaclass('int32')); propwidth.setValue(int32(100)); propdimensions.addChild(propwidth); propheight = com.jidesoft.grid.DefaultProperty(); propheight.setName('height'); propheight.setType(javaclass('int32')); propheight.setValue(int32(100)); propdimensions.addChild(propheight);

A property grid with nested property
PropertyTableModel accesses properties in a hierarchical naming scheme. This means that the parts of nested properties are separated with a dot (.). In the above example, these two fully-qualified names are dimensions.width and dimensions.height.
Trapping property change events
Sometimes it is desirable to subscribe to the PropertyChange event. This event is fired by PropertyTableModel whenever any property value is updated. To expose Java events to Matlab, we use the two-parameter form of the handle function with the optional CallbackProperties parameter.
hModel = handle(model, 'CallbackProperties'); set(hModel, 'PropertyChangeCallback', @callback_onPropertyChange);
The callback function receives two input arguments: The first is the PropertyTableModel object that fired the event, the second is a PropertyChangeEvent object with properties PropertyName, OldValue and NewValue. The PropertyTableModel’s getProperty(PropertyName) method may be used to fetch the Property instance that has changed.
Callbacks enable property value validation: OldValue can be used to restore the original property value, if NewValue fails to meet some criteria that cannot be programmed into the cell editor. We may, for instance, set the property type to a string; then, in our callback function, use str2num as a validator to try to convert NewValue to a numeric matrix. If the conversion fails, we restore the OldValue:
function callback_onPropertyChange(model, event) string = event.getNewValue(); [value, isvalid] = str2num(string); %#ok prop = model.getProperty(event.getPropertyName()); if isvalid % standardize value entered string = mat2str(value); else % restore previous value string = event.getOldValue(); end prop.setValue(string); model.refresh(); % refresh value onscreen
The JIDE packages that are pre-bundled in Matlab contain numerous other useful classes. Some of these will be described in future articles.




















