Michael L Brereton - 03
October 2008, http://www.ewesoft.com/
<< Previous:
Starting Your Application
>>
Next: Event Handling
One of the most important uses of a
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.