![]() |
![]() |
||||||
|
|||||||
This section shows how the spinner model and controller classes are implemented. It is intended for Java™ developers, and requires a good understanding of Java interfaces. A spinner and its supporting objects are shown in the following illustration:![]() Action Listener The spinner is controlled by an action listener that is loosely coupled to a model that maintains the spinner’s value. The controller has no direct association with any view. Loose coupling is achieved by making the controller refer to the model, not through the text model’s class, but through the com.enode.xalt.Sequence interface described next. The com.enode.xalt.Sequence interface captures the essential properties of a spinner’s model, and the operations that may be performed on it. The interface also declares methods required to support event listeners for user-defined event notifications. You may use this interface as-is, or treat this as a model for defining your own interface. Note that this interface works for sequences of any type, not just numbers. The action listener is implemented as a JavaBean™ class called com.enode.xalt.Sequencer. The bean class defines a single property called sequence, as evidenced by the presence of conforming bean property methods setSequence() and getSequence(). As usual, you can use this class as an example for defining your own action listener, or you may choose to use it as-is. The increment() and decrement() methods have the same return type and argument list as the actionPerformed() method declared by the java.awt.event.ActionListener interface. If you associate either of these methods with a trampoline using the method attribute of an action element, eNode Object Realizer will invoke the named method in lieu of the generic actionPerformed() method. This allows us to use a single action listener object to handle action events from multiple sources, without having to decode the source of the action event inside the action listener. That is all there is to the definition of the action listener class. Because of its design, this class can easily be reused in other unrelated situations, such as cycling through items in a combo box. Spinner Text Model As previously mentioned, the spinner and the text field share the same model — Rather than use a separate object for the spinner’s model, we adapt the text field’s model to implement the spinner’s model. That way, whenever the value maintained by the spinner’s model changes, the text field’s model also shows an identical change — after all, they are the same object! The com.enode.xalt.Sequence interface declares methods that define one read-write property called value and two read-only properties called previousValue and nextValue. We want our spinner model to support a bounded sequence where the “step” size as well as the maximum and minimum for the sequence can be specified. So, we extend the existing interface by adding three new read-write properties, as follows: We define our text model class by extending javax.swing.text.PlainDocument (which is the default model class for a text field), and implementing the com.enode.BoundedSequence interface. We call this class com.enode.xalt.IntegerTextModel because we envision that it will be used to store integer values only. The properties maximum and minimum define the range within which the spinner’s value is bounded. If either or both of these are not set, the corresponding end of the range is unbounded. The default value of the stepSize property is one, but it can be set to any integer value that indicates the amount by which the spinner’s value should change during a single increment or decrement. A negative value will cause increment() to decrease the value of the spinner by the absolute value of the stepSize property. The listing for com.enode.xalt.IntegerTextModel is shown below. The code is straightforward and should be self-explanatory. Notice that our spinner model implements com.enode.BoundedSequence, but the action listener does not need to know about the additional properties. So, com.enode.xalt.Sequencer continues to refer to the model through the more general interface com.enode.xalt.Sequence. Whenever the value of the spinner is changed, the spinner model fires a user-defined event called com.enode.xalt.SequenceChangeEvent. Event firing is a straightforward process that requires stereotypical code for setting up the necessary infrastructure. Refer to the documentation of javax.swing.event.EventListenerList for details. Here, the events infrastructure depends on the com.enode.xalt.SequenceChangeListener interface, which declares a single method called sequenceChanged(), as shown below. .The listsing for com.enode.xalt.SequenceChangeEvent is shown below. Whenever the spinner’s value changes, it fires a SequenceChangeEvent that can be intercepted by an object that implements the SequenceChangeListener interface. Upon notification, the listener can query the event to determine how the sequence changed. It can also query the event source, which, in this case, is the spinner model, to determine the current value of the sequence. In this example, however, we do not use the sequenceChanged() notification, relying instead on the trampoline mechanism to invoke increment() or decrement(), as appropriate. |
|||||||
|
Copyright © 2002 eNode, Inc. All Rights Reserved. |