Michael L Brereton - 08 February 2008, http://www.ewesoft.com/
<< Previous:
Starting Your Application
>>
Next: Event Handling
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.
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:
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.
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().
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.
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 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.
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.
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.