Eve Application Development

Michael L Brereton - 03 October 2008, http://www.ewesoft.com/

 

Beginners Guide - Contents

<< Previous: Starting Your Application

>> Next: Event Handling

Data Objects

 

One of the most important uses of a

GUI Data Transfer

The Eve environment provides an easy way to transfer data between a GUI control (e.g. an Input text control, or a CheckBox control) and a Field (member variable) of an object. This is done via an eve.ui.data.Editor control, which inherits from Form.

The Editor Control

Being a type of Form control, an Editor is a container for controls. However it does have an important extra capability: it can automatically transfer data from an UI control to a Field of an Object that is being edited. This works as follows:

 

 

Each call to addField() will prompt the Editor to look at the class specification for the edited Object to locate the matching field variable (using the Reflection API). Then an eve.sys.FieldTransfer object is associated with that control. This FieldTransfer will then be used to transfer data between the Object field and the associated control in the way most appropriate for the data type.

 

Calling setObject(Object object) on the Editor will then associate an instance of the data object with the Editor. This causes all data from the edited object to be transferred to the controls in the Editor in a manner that is compatible with the GUI control. For example if the control is an Input (single line text input) or TextPad (multi-line text input) and the field variable is of type String, it will set the text of the control to be the same text as the member variable. This eliminates the need to explicitly set each control value via calls such as setText() or setState().

 

Additionally, once the data has been displayed on screen, any changes made to the data by the user via the on-screen controls will be transferred automatically to the object being edited. This eliminates the need to explicitly fetch each control value via calls such as getText() or getState().

 

In order for the Editor to work correctly the Class of the object being edited must be public and each field being edited must also be public. This is because of standard security restrictions in the Reflection API.

 

To summarize, you must do the following steps to be able to edit an object via an Editor:

 

  1. Create a new Editor and set the objectClass field to be a Class object that represents the class of the object to be edited.

  2. Add controls to the Editor. If a control should represent data in the object to be edited, associate the field name with the control by calling: addField(Control control, String fieldname).

  3. Set the object to be edited by calling setObject(Object obj) on the Editor. If the Editor is currently on screen, the controls will be immediately updated. You can call setObject() multiple times to edit multiple objects if you need to. Each time it is called, the controls are updated to reflect the data in the new object. You can call setObject(null) if necessary and all controls will be set to an empty value.

  4. All user changes to the data will automatically change the data in the object being edited, but programmatic changes to the object fields will not be automatically updated in the Editor controls. If your program changes data in the object while it is being edited you must call toControls(String fieldnames), where fieldnames is a comma separated list of fields that you want the Editor to update on screen. You can also call toControls() with no arguments to update all of the Editor controls.

 

You should use the following controls to represent different data:

Input

Single lines of text and any numeric values (int, float, double, long).

TextPad

Multiple lines of text.

CheckBox

Boolean (true/false) values.

Choice/ComboBox

Text values and integer values.

DateTimeInput

Time/TimeOfDay/DayOfYear values.

 

Using a DataConverter object it is possible to edit more complex data values using more controls, but that will be covered in an advanced section.

The InputStack Control

An InputStack is a type of container that makes it easy to add a series of inputs with associated prompts. The InputStack takes care of aligning the controls and prompts. You simply add a control to the InputStack and specify a string prompt. It will create a label to represent the prompt and add it to itself in addition to adding the control. You do this by calling: add(Control control, String prompt). This method returns the control that was added. This allows you add a field to the Editor at the same time as you add it to the input stack by doing something like:

 

editor.addField(inputStack.add(new Input(),”Name:”),”name”);

 

Just remember to add the input stack itself to the Editor using addLast() or addNext().

Field Change and Action Events

It is frequently desirable to detect when a field value has been changed by the user, in order to begin some action or to validate the input. Additionally, there may be action events (e.g. a button press) that you would like to trap and act upon, even though no particular data is associated with the action (e.g. a button to clear the fields of an object).

 

These are both facilitated by the Editor object through the FieldListener interface. You can add FieldListener objects to the Editor by adding them to the Editor’s fieldListeners variable (which is a Vector). However, if the object which is being edited (the one sent to setObject()) itself implements the FieldListener interface, then it will automatically be added to the Editor’s fieldListeners Vector. This is the preferred way of doing things as it allows you to group together in one class both the data to be edited and code used to validate the object data during entry.

The fieldChanged() method

A FieldListener has two methods that will be called during entry. The first is fieldChanged(FieldTransfer ft, Editor ed). This is called after the Editor has updated the member variables in the object being edited. If you explicitly change any data in the object within this method you must call ed.toControls(<fieldnames>) in order for those changes to be reflected on screen. The FieldTransfer parameter sent to the method is the object which actually does the work of the GUI-object data transfer. You can tell which field has been modified by checking the fieldName variable in the FieldTransfer object. The control which is being used to represent the field is given by the dataInterface variable in the FieldTransfer object.

 

Note that if the type of a field in an object is eve.ui.MenuItem then this can be used to detect when a menu item has been selected in the menu which is associated with the Control assigned to field. For example if the Control is a PullDownMenu then when the user selects an item within the PullDownMenu the fieldChanged() method is invoked and the new value of the field will be the MenuItem object which was just selected.  See the Editor Example to see how this is used.

The action() method

The second method that can be called during entry is action(FieldTransfer ft, Editor ed). This is called when a control that is associated with a field name generates a ControlEvent.PRESSED event. When assigning field names to controls which are to be used for generating action() events only (e.g. a Button) the field name which is assigned should NOT correspond to an actual Field name in the object being edited. Again, if you explicitly change any data in the object within this method you must call ed.toControls(<fieldnames>) in order for those changes to be reflected on screen.

 

You will be surprised to discover that using these two methods is enough to handle the great majority of your user interface forms. You will probably never have to deal with control events again.

 

There is also another FieldListener method void fieldEvent(FieldTransfer xfer,Editor editor,Object event). This gets called when an event is fired by a control and the event is not a PRESSED event and the event is not a Pen/Mouse/Focus event. You can use this to trap events from other complex or custom GUI controls.

Editor Example

To see an example of using an Editor go to the classes\samples\editor directory in the development environment and look at the file: PersonInfo.java and EditPerson.java.

Editor Notes

An important thing to note about the Editor class is that it implements the FieldListener interface itself. This means you can extend the Editor class and create an Editor object which can edit itself! In fact, this is the default behavior for the Editor. When you first create an Editor, the constructor sets the objectClass variable to be a Reflect object representing its own class, and it calls setObject() passing itself as the object to be edited. Here is the source code for the Editor constructor:

 

//================================

public Editor()

//================================

{

            objectClass = Reflect.getForObject(this);

            setObject(this);

}

 

Here is an example of this is in the file: LoginScreen.java in the classes\samples\editor directory. It shows an Editor editing itself. This also demonstrates a button which has an associated menu that pops-up when the button is held down or if the right mouse button is pressed on it. It shows how to determine which action has been taken by the user.