How it worksThe main idea is to split the task is two components that comunicate with each other. The first one, the Attributes, handle the communication with the objects, and the second one, the GUI, uses the Attributes to create the widgets and interact with the user. AttributesThe attributes are a kind of hight level reflection. They know how to get/set itself, how to add/remove listeners to changes and a few more tricks. They are the Model component, or a Model wrapper, if you prefer. The interface of an attribute is: public interface Attribute
{
String getName();
Object getType();
AttributeValueRange getValueRange();
boolean canWrite();
Object getValue();
void setValue(Object obj);
boolean canListen();
void addListener(AttributeListener listener);
void removeListener(AttributeListener listener);
AttributeGroup asGroup();
}getNameThe full name of the Attribute. In the ReflectionAttribute, it returns something like "com.package.ClassName.attributeName". It has to be an unique id to an attribute, and provides a good key for i18n issues. (Do not dare to return null :-P ) getTypeThe type of the attribute. It can really be anything (not just a Class). This is the only thing that identifies the attribute and it is how the GUI know which widget to use. The SWT GUI, for example, accepts primitive classes, String.class and strings like "combo", "scale", "number", etc. getValueRangeReturns an object that lists the constraints on this attribute. This, too, is used by the GUI to select the widget and to change how they interact. It will be explained latter. canWriteTells if the attribute is read-only or not. If it returns false the method setValue can't be called. getValueGet the value of the attribue. setValueSet the value of the attribute. canListenReturns if this attribute can receive listeners. If it is false, addListener and removeListener should not be called. addListenerAdds a listener to the attribute. The attribute implementation is reponsible to convert the AttributeListener to the correct listener and back removeListenerRemove a listener from the attribute asGroupReturns a representation of this attribute as a group. If it can't be represented as an attribute, return null. It is used because sometimes the GUI don't know how to handle a type, but knows how to handle its sub-attributes. In the reflection case, if an attribute is not a primitive type, it returns a ReflectionGroup representing its value. GroupsA group represents an entity that have list of attributes and a name. The ReflectionGroup is really an Object representation, but it does not have to have a 1 to 1 representation with an Object. The interface of a group is: public interface AttributeGroup
{
String getName();
Collection<Object> getAttributes();
boolean canListen();
void addListener(AttributeListener listener);
void removeListener(AttributeListener listener);
}getNameThe full name of the Group. In the ReflectionGroup, it returns something like "com.package.ClassName" or "com.package.ClassName.fieldName" (if it was retrieved by a call to Attribute.asGroup). It is also a good key for i18n issues. (Do not dare to return null :-P ) getAttributesRetrieves the list of attributes that this group have. canListenReturns if this group can receive listeners. If it is false, addListener and removeListener should not be called. A listener to a group means that some (0, 1 or more) of its attributes has changed. addListenerAdds a listener to the group. The attribute implementation is reponsible to convert the AttributeListener to the correct listener and back. removeListenerRemove a listener from the group.
|