Developing Control Beans



This chapter is a guide for those who wish to develop their own Control Beans. It explains the fundamentals of the components and AbstractCommunicator, the class from which all communicators should be inherited.

Introduction/Dictionary

Before we start there are a few concepts we would like you to familiarize yourself with.
  • Java beans. Beans are Java classes written in according to a certain design pattern. By doing so, a visual programming environment such as NetBeans Developer can perform a so called introspection of the class and find out what attributes can be manipulated and which events the class can send. These design patterns stipulate that you must provide the following:
  • To the top


    How to develop new components.

    In order for a new component to function properly with the existing set, it should implement ComponentInterface. This interface provides each component with the methods it needs to be able to be stored within a communicator and receive values from it. Normally a component would be inherited from some kind of existing AWT or Swing component, such as a button or a slider. We recommend that you try to use Swing components rather than AWT components as the older AWT package is not fully compatible with Swing.
    We will now go through each step in the process of creating a new component.

    Package declaration.

    If you wish for your new component to be a part of the original Control Beans package, you should set the package declaration to:
    package ControlBeans;
    If not just set it to whatever you wish to name your package. Just don't forget to import the Control beans package... like this:
    import ControlBeans.*;

    Declaration.

    As mentioned above, each new component should implement ComponentInterface.

    Class attributes/variables.

    Your component should have (at least) these attributes:

    private int myID;

    Used to store the ID provided when the communicator registers with your component. More on that later.
     


    private AbstractCommunicator myCommunicator;

    Used to keep a reference to the communicator when it registers with your component. More on that later.
     


    private ComponentListener myListener;

    Used to store a reference to the object to which you will send a registerComponentEvent.
     


    private boolean isSender;

    Used to store whether or not your component should send values to the communicator or not.
     


    private boolean isReceiver;

    Used to store whether or not your component should receive values from the communicator or not.
     


    private int tag;  or   private int[] tags;

    Used to store this components tag(s).

    Constructor.

    A few special considerations should be taken in order for it to function as a Control Bean:

    Implementing the methods of ComponentInterface.

    There are quite a few of them, but most of them are very simple. In fact, many of them can be copied from existing components within the Control Beans package.
    public boolean getIsReceiver();
    public void setIsReceiver(boolean value);
    public boolean getIsSender();
    public void setIsSender(boolean value);

    These methods are used for getting and setting the isSender and isReceiver attributes. The methods are needed in order for your component to pass as a Java bean.
     


    public void addComponentListener(ComponentListener l);
    public void removeComponentListener(ComponentListener l);

    These methods must be implemented so that your component can keep track of which object(s) should receive events from it. Normally, you don't need to keep track of more than one listener. At present, none of the components within the Control Beans package can keep track of multiple listeners.
    addComponentListener should when invoked send a registerComponentEvent to the listener. This event will eventually end up within the communicator which will then invoke registerCommunicator. (See myListener).
     

    public void registerCommunicator(AbstractCommunicator c, int ID);

    When the communicator receives a registerComponentEvent it will invoke this method at the source of the event (which is your component in this case (just in case you hadn't figured)). c will then be a reference to the communicator itself and ID will be a unique ID number for your component. Both of these parameters should be stored. (See myCommunicator, myID).
     

    public int[] getTags();

    This method must be implemented to return an array containing all tags that your components subscribe to, even if your component only has one tag. The communicator invokes this method upon registering.
     

    public void putValue(int value, int aTag, double time, int ID);
    public void putValue(double value, int aTag, double time, int ID);
    public void putValue(String value, int aTag, double time, int ID);

    When the communicator wishes to pass a value to your component it will invoke one of these methods. This is what these methods should do:

    Methods for value types that are not supposed to be received by your component can be left with empty bodies. You may wish to provide conversion between the different types. For instance: even if your component is only supposed to receive integer values you should also implement the method which receives double values and cast value from double to integer before processing it.
     

    public void requestValues();

    When invoked, your component should send its value(s) to the communicator. This is used to provide the application your GUI is supposed to be controlling with initial parameter values. Don't forget to check whether or not isSender is set to true. If your component is not of such a kind that it contains a certain value (ordinary buttons for instance don't), this method can be left with an empty body. Please note if you are constructing your own communicator that AbstractCommunicator does not automatically invoke this method. See the next chapter for more information.

    Event handling.

    Finally, you should implement methods that process events triggered when the someone uses your component. Most commonly, this is done by implementing actionPerformed which is the method to handle ActionEvent which in turn is the standard event to be sent by a component when used. Please check with the documentation for the component you inherited from to see which event will be sent. This is what the event handling method should do: For more information, please look at the source code and the Java documentation of the Control Beans components. CButton is a good place to start.

    To the top



    How to develop new communicators.

    All new communicators that are developed should be inherited from the class AbstractCommunicator.  This is because of a number of reasons:
    1. All components interact with that class.
    2. There is already an established protocol of communication between that class and the components.
    3. It saves you tonnes of work.
    AbstractCommunicator is a class designed to : AbstractCommunicator already contains all the methods and mechanisms needed to contain the components that register with it. It also makes sure that all components that subscribe to the same tag gets the same values. Please note that AbstractCommunicator is inherited from com.sun.java.swing.JPanel which make all communicators inherited from it visual components. This is to allow you to place AWT/Swing controls on it to add user friendliness.
    A communicator is  - as said before - a class which is supposed to send and receive values to and from a control application in order to control it. AbstractCommunicator doesn't have that ability and that part must therefore be implemented by you.

    Sending values to the application.

    What you need to do is simply to implement three methods that are declared abstract in AbstractCommunicator to make your new communicator work. These methods are... sendValue, sendValue and sendValue. Here are the declarations of the three methods in AbstractCommunicator:
    protected abstract void sendValue(int value, int aTag, double time);
    protected abstract void sendValue(double value, int aTag, double time);
    protected abstract void sendValue(String value, int aTag, double time);
    These methods are called by the communicator itself when it has received a value from one of the components that have registered with it (i.e. when someone has invoked putValue on the communicator). sendValue is where you are supposed to supply the means for your communicator to pass this value on to the application that your GUI is supposed to be controlling. How you do this is completely up to you. After you have implemented the three sendValue methods (and the methods and possible inner classes needed to support them) there is only one more thing to do...

    Receiving values from the application.

    When values are sent to your communicator from the control application, you must pass these values on to the components. This is done by invoking one of the communicators own putValue methods. This is how it should be done:
    putValue(value, tag, time, myID);
    where value is the value received from the application, tag is the tag that came with the value and time is the time stamp. myID is the communicators own ID number and must be sent along to prevent the value from "bouncing back" to any of the sendValue methods.
    If you don't wish to use the time stamp that came with the value, you can instead call putValue like this:
    putValue(value, tag, CURRENT_TIME, myID);
    By doing so, the communicator will insert the time stamp itself.

    And that - as they say - is it.



    To the topBack