Whiteboard Example


TOC

  1. Introduction
  2. How to compile
    1. On Unix
    2. On Windows/NT
  3. How to run
    1. On Unix
    2. On Windows/NT
  4. User Interface
  5. Software Design
    1. Interfaces
    2. Classes
    3. How remote objects are created and rendered?
  6. Changes

1. Introduction

Whiteboard example uses the shared objects. This example is different from the Chat and HelloWorld examples because each whiteboard user joins the execution when the program starts and each user can define number of objects (be the owner of number of objects). Therefore, Whiteboard federate simulates number of objects by creating, deleting, updating object's attributes.

User interface contains two action buttons:

Select: selects the object on the whiteboard if the user is the owner of this object, and
Rect: introduces a new rectangle object on the whiteboard. When a new rectangle object is defined, its color is selected from the bottom right window and its size is adjusted with mouse drag. First click fixes the one corner and the drag operation changes its size and mouse release finishes the declaration of a new object.

User can select an object on the whiteboard provided that this object defined by him/her and drag the object on the whiteboard.

Whiteboard assumes that the whole world is looking at the same whiteboard and each joining federate sees the same whiteboard. If there are already other users in the federate and they defined objects, the joining federate sees all this objects. (RTI sends a discoverObject, the federate decides whether it wants to know this object or not. If the federate wants to know more about this object, it asks RTI to give more information, then RTI sends a provideAttributeValues message to the owner(s) of this object. Owner federates publish the required attribute values and the initiating federate receives reflect messages belonging to this object's attributes.)

Whiteboard.xml in $(OWRTI_HOME)/xml directory contains the federation definition. It only defines a Rectangle object that has x,y,transx,transy, width, and height attributes.

2. How to compile

JDK 1.2 or later release.

2.1. On Unix

  1. Makefile contains necessary compile parameters. It includes $(OWRTI_HOME)/mk/config.mk configuration file. This file contains variables for:

    1. Java installation directory (J_HOME),
    2. OWRTI installation directory (OWRTI_HOME), and
    3. JWORB installation directory (JWORB_HOME).

    These variables should be set to the proper directories.

  2. make

    compiles the codes.

2.1. On Windows/NT

  1. Makefile.win contains necessary compile parameters. It includes $(OWRTI_HOME)/mk/config.win configuration file. This file contains variables for:

    1. Java installation directory (J_HOME),
    2. OWRTI installation directory (OWRTI_HOME), and
    3. JWORB installation directory (JWORB_HOME).

    These variables should be set to the proper directories.

  2. nmake /f Makefile.win

    compiles the codes.

3. How to run

JDK 1.2 or later release.

3.1. On Unix

  1. Makefile contains necessary compile parameters. It includes $(OWRTI_HOME)/mk/config.mk configuration file. This file contains variables for:

    1. Java installation directory (J_HOME),
    2. OWRTI installation directory (OWRTI_HOME), and
    3. JWORB installation directory (JWORB_HOME).

    These variables should be set to the proper directories.

  2. Whiteboard.xml file is stored in $(OWRTI_HOME)/xml directory. This file should be placed in $(JWORB_HOME)/config directory since the JWORB actually starts up the OWRTI.

  3. kernel.srv file contains machine name and port number pairs. These pairs are used to find a running JWORB server. Therefore, you should add your running JWORB's machine name and port number information into this file. Assume that your JWORB is running on herman.arl.mil port number 3142, then kernel.srv should contain

    herman.arl.mil 3142
    osprey2.npac.syr.edu 4004

    During the runtime, system goes through the entries in order and uses the first JWORB that runs the OWRTI.

  4. run

    script starts up the GUI.

3.2. On Windows/NT

  1. Makefile.win contains necessary compile parameters. It includes $(OWRTI_HOME)/mk/config.win configuration file. This file contains variables for:

    1. Java installation directory (J_HOME),
    2. OWRTI installation directory (OWRTI_HOME), and
    3. JWORB installation directory (JWORB_HOME).

    These variables should be set to the proper directories.

  2. Whiteboard.xml file is stored in $(OWRTI_HOME)/xml directory. This file should be placed in $(JWORB_HOME)/config directory since the JWORB actually starts up the OWRTI.

  3. kernel.srv file contains machine name and port number pairs. These pairs are used to find a running JWORB server. Therefore, you should add your running JWORB's machine name and port number information into this file. Assume that your JWORB is running on herman.arl.mil port number 3142, then kernel.srv should contain

    herman.arl.mil 3142
    osprey2.npac.syr.edu 4004

    During the runtime, system goes through the entries in order and uses the first JWORB that runs the OWRTI.

  4. run

    script starts up the GUI. (This is a .BAT file).

4. User Interface

User interface contains two shapes and select button. Select button is used to move the locally defined object (Figure 1). Shape buttons (Rect and Circle) are used to draw a shape on the whiteboard (Figure 2,3,4,5).

Figure 1. Select button.

Figure 2. Rect button.

Figure 3. Circle button.

Figure 4. Rectangle is drawn by clicking on the Rect button, then left mouse
click denotes the left upper left corner. The right mouse button
marks the other corner.

Figure 5. Circle is drawn by clicking on the Circle button, then left mouse
click denotes the left upper left corner. The right mouse button
marks the other corner.

Figure 6. Two whiteboards can see each other. The remote objects are drawn with red color.

5. Software Design

Package has the following subdirectories:

edu:source files.
gif:images.
jdocs:Javadoc outputs.
Figure . UML diagram for the objects in edu.dmi package.
Figure . UML diagram for the objects in edu.rti package.
Figure . UML diagram for the objects in edu package.

"config.txt" file is used to import Visual components that can be used on the Whiteboard. The format of this file is:

sel,gif/sel.gif,edu.Select
rect,gif/rect.gif,edu.Rect
circle,gif/858x2.gif,edu.Circle

The first component is the name, the second component is the Image file name and the third one if the Java class implementing edu.Tool interface.

5.1. Interfaces

AppletProps
URL getCodeBase() : returns the base url.
Image getImage(URL base, String fName) : loads the image from the base url.

UpdateListener extends java.util.EventListener
UpdateEvent
void updateOccurred (UpdateEvent e) : a event call.

UpdateListenersRegistry
A registry pattern for UpdateListener objects.
void addUpdateListener(UpdateListener ele) : adds an UpdateListener object.
void removeUpdateListener(UpdateListener ele) : removes an UpdateListener object.

Element
Represents objects to be rendered on the screen.
Rectangle getBounds() : returns enclosing rectangle of this object.
void paint (Graphics g) : asks object to render itself on the Graphics object.
void commitTranslation(int dX, int dY) : tells object that drag operation is finished and it can updates itself.
void updateTranslation(int dX, int dY) : updates the translation parameter of the object during mouse drag.
void setUpdateListener(UpdateListener lis) : sets the UpdateListener object for this Element. It fires an UpdateEvent to inform this observer.
boolean isSelectable() : Is this Element dragged by a mouse?.(We do not want the networked objects to be dragged by the local client)

ElementsContainer extends UpdateListenersRegistry
Container for Element objects.
Enumeration getElements() : returns all the registered Element objects.
void addElement(Element ele) : adds one Element object.
void removeElement(Element ele) : removes one Element object.

Tool
Tool object is used for authoring an Element object.
Component getControls() : returns Component object which has a GUI for the Element authoring.
void processEvent (AWTEvent e) : a paint area forwards the AWTEvent s to the Tool.

5.2. Classes

WBContainer extends JPanel implements UpdateListener
  1. keeps a reference to ElementsContainer.
  2. forwards mouse events to the currentTool (Tool)
  3. when it receives an updateOccured() message, then it sends paint() message to all the Element objects in the ElementsContainer object.

BaseFedAmb
A utility object to give empty implementation of FederateAmbassador methods.

EntityManager extends UpdateBroadcaster implements UpdateListener, RTIObjectsContainer, ElementsContainer
It has a reference to RTIAmbassador. Keeps the mapping from RTI object instance id to the local RTIObject representing this networked object.

RTIObjectsContainer view is used by the WBFedAmb object to add/remove object instances to the EntityManager.

Any change in the container causes a firing of UpdateEvent, this event is delivered to the listeners. (UpdateBroadcaster)

ElementsContainer view is used by renderer and Tool objects to add a new Element. EntityManager automatically gets an RTI object instance id for this object. If it is remove operation, then it also sends a message to remove this object from the federation.

It contains a factory pattern registration for object types.
void registerObjectFactory(String rtiClassName, ObjFactory oFactory)
ObjFactory getObjectFactoryForRtiObjectClass(String rtiClassName)

UpdateBroadcaster extends GenericMessageBroadcaster implements UpdateListenersRegistry
For each fireUpdate() method, it broadcasts the GenericMessage to all the UpdateListener objects.

WBFedAmb extends BaseFedAmb
It has a reference to RTIObjectsContainer
  1. discoverObjectInstance() : invokes addObjectInstance() on RTIObjectsContainer.
  2. reflectAttributeValues() : finds the RTIObject from RTIObjectsContainer via getObjectInstance() method and invokes addAttributes() on this RTIObject.
  3. removeObjectInstanceWithTime() : invokes removeObjectInstance() on RTIObjectsContainer.
  4. removeObjectInstance() : invokes removeObjectInstance() on RTIObjectsContainer.
  5. provideAttributeValueUpdate() : finds the RTIObject from RTIObjectsContainer via getObjectInstance() method and invokes reflectAttributes() on this RTIObject.
  6. turnUpdatesOnForObjectInstance() : finds the RTIObject from RTIObjectsContainer via getObjectInstance() method and invokes reflectAttributes() on this RTIObject.

edu.rti.RTIObject (Abstract Class)

Object which has RTI Object definition extends from this object and gives an implementation of some methods for attribute updates. Single inheritance in Java might cause some ad hoc solutions if the object can not be naturally extended from RTIObject. RTIObject handles publish/nonpublish options, hides the RTI instance id, hides the RTI attribute ids and presents an attribute name based communication pattern with its concrete class. The concrete class should provide the implementation of the following methods:

  1. Properties getAttributes(boolean state) : asks the current value of the attributes. state is connected with turnUpdatesOn/Off in the FederationAmbassador interface. The concrete class is supposed to return a <attribute_name,attribute_value> pairs in the Properties object. The network representation of these values are left to the concrete class implementation. CDRCoderEncoder might be useful for basic common network representation.

  2. void setAttributes(Properties props) : attribute updates are carried to the concrete class with this method. The Properties object stores <attribute_name,attribute_value> pairs. The network representation of these values are left to the concrete class implementation. CDRCoderEncoder might be useful for basic common network representation.

  3. void reflectAttributes(Vector props) : asks the object to produce an update for the given attributes.

RectElement extends RTIObject implements Element
Denotes a Rectangle object.
  1. commitTranslation() : updates its left-upper corner and sets its translation values to zero.
  2. updateTranslation() : updates its translation values and fires an UpdateEvent.
  3. paint() : draws a rectangle.
  4. setUpdateListener() : sets its UpdateListener.
  5. getAttributes() : an RTIObject hook, to ask the object to encode its attributes into a Properties object where the <attribute_name,attribute_value> pairs are stored.
  6. setAttributes() : an RTIObject hook, to informs this object about the attribute value updates this information is passed with Properties object that stores <attribute_name,attribute_value> pairs.
  7. reflectAttributes() : an RTIObject hook, to push this object to publish the required attributes (which is passed in Vector object containing the attribute names).

Rect extends Component implements Tool, ItemListener

A Tool implementation for RectElement object. This object is responsible for providing GUI for the rectangle authoring such as its color. It brings up a pull-down list. This object is also responsible for handling mouse events coming from the paint area. The WBContainer object controls the input in the paint area and forwards the mouse events to the current Tool object. Tool implementations creates the object, drags it and resizes it.

In processEvent(), if the Mouse is pressed, it defines a new RectElement object and adds this object to the ElementsContainer object. If the Mouse is dragged while an object is already defined, this means that the user click on the first corner and tries to determine the second corner of the rectangle. Therefore, it sets the new coorinate values for the RectElement object. If the Mouse is released during the object definition, it updates the current coordinate values and prepares for the next object definition.

edu.rti.NWRTI implments UpdateListener

It has a reference to RTIAmbassador object. It receives the UpdateEvent through UpdateListener interface (updateOccured). It extracts the source object from the UpdateEvent (getSource) and if it is RTIObject and its is publishable then it extracts the RTIObject instance id and updated attribute values and sends them through the RTI (updateAttributeValues).

edu.dmi.ObjFactory

Contains a constructor definition for an Object definition. getNewInstance() method creates the instance of the object class by using the constructor definition.

edu.rti.RTIObjFactory extends ObjFactory

Contains a constructor definition for an RTI Object definition.

edu.WB extends JFrame

A main Frame object.

  1. getRtiIds() : gets the RTI id for object classes, attributes, interaction classes, and parameters.
  2. publishSubscribe() : defines a publish/subscribe object and attributes. It also registers the RTIObjFactory implementation for the RTI Object definitions.
  3. joinFederationExecution() : creates and joins the federation.
  4. deleteObjects() : goes through the local objects in ElementsContainer and removes them from the RTI.
  5. leaveFederationExecution() : resigns from the Federation and deletes the Federation.
  6. doRealyConnect() : defines an EntityManager. defines an WBContainer object. defines WBFedAmb object.
  7. constructor() : It reads the config.txt file to get the name of button, image of button, and the class name which implements the Tool interface. These buttons are placed on the left panel. The button name and class pairs are stored in a hashtable. actionPerformed() method access the Tool implementation name through the hashtable. It instantiate the Tool implementation. makes it the currentTool. Passes the EntityManager and WBContainer reference to the Tool implementation. Informs WBContainer about the currentTool.

5.3. How remote objects are created and rendered?

  1. receives discoverObjectInstance method (WBFedAmb)
  2. WBFedAmb -> adds this object to the EntityManager (since it implements the RTIObjectsContainer)
  3. EntityManager fires an UpdateEvent (in addElement) to announce that its state have been changed.
  4. WBContainer is registered to EntityManager (in WB.doRealyConnect()) for UpdateEvent therefore event fired by EntityManager is also received by WBContainer.
  5. WBContainer receives updateOccured() message. It calls repaint()
  6. repaint()->paint()->update() (all in WBContainer)
  7. update() method goes through all the elements in ElementsContainer (these are actually comes from EntityManager object since it implements ElementsContainer interface), and invokes paint() method on each Element object.
  8. 7.PS: If you look WB.doRealyConnect() method, you'll see that when WBContainer is defined the first parameter is the EntityManager itself. EntityManager keeps track of entities created by the user and discovered from the network.

6. Changes

  1. Circle is added. (6.29.1999)
===================================================================The End.
Prepared by H. Timucin Ozdemir, August 8, 1999.
E-mail : timucin@npac.syr.edu
===========================================================================