What Are Groups and Shadows?

GUI builder introduces two new concepts: groups and shadows. A shadow is a wrapper class for an AWT component. A group is a collection of shadows and other groups.

Shadows

Shadows are wrapper classes for AWT components. Shadows do several things for you:

Custom functionality may also be included in the shadow classes. For example, the window shadow resizes the window to its preferred size and maps the window when its visible attribute is set to true.

Groups

A group encapsulates a set of shadows and subgroups. GUI builder is used to create new groups out of existing shadows and groups. When a new group is created, it can be imported into the GUI builder palette and can then be incorporated into other groups. New groups must be subclasses of the Group class.

Groups that are included inside other groups are called subgroups. The top-level group is called the base group. A tree of groups exists while the application is running. Messages sent by subgroups propagate up toward the top of the tree until they are handled or they reach the base group.

The interface to a group consists of a set of attributes and methods. The class Group defines a set of attributes and methods. Specific subclasses of the Group class add their own customized attributes and methods. The attributes and methods of the shadows and subgroups contained by a group are not automatically inherited.

Applications created using GUI builder are actually groups. A large application typically consists of a base group that contains many other shadows and subgroups.

Attributes, Methods, and Messages

From an external viewpoint, a group is a single component that has a set of attributes, public methods, and messages.

Attributes

Every shadow and group class has a set of attributes. Attributes for a group are defined in the constructor and are handled using the getOnGroup and setOnGroup methods. Support is provided for forwarding a set of attributes to one or more children of the group--a child being either a shadow or a subgroup.

When writing a group, many of your tasks involve setting and getting the attributes of the shadows contained by the group. Two methods are used to manipulate attributes:

	public void set(String key, Object value);
	public Object get(String key);

Example:

Every AWT component shadow inherits the following attributes:
   NAME		TYPE			DEFAULT VALUE
   ----		----			-------------
   name		java.lang.String	null
   visible	java.lang.Boolean	TRUE
   enabled	java.lang.Boolean	TRUE
   foreground	java.awt.Color		null
   background	java.awt.Color		null
   font		java.awt.Font		null

The button shadow defines an additional attribute:

   text		java.lang.String	button


In future releases the list of attributes will automatically be extracted from a shadow or group. This will make it possible to create a document listing all the attributes for each shadow class.

The visible attribute has a special behavior. When visible is set to true on a window for the first time, the window changes to its preferred size before display. Subsequent setting of the visible attribute to true or false will cause the window to be shown or hidden, but will cause no further resizing of the window.

Methods

Most methods are custom methods written by the author of the group. There are some useful methods defined in the Group class itself, such as the get/set attribute methods.

Message

A group will create messages and post them to their parent groups. A group does not need to have any knowledge of its parent. Instead, the parent can listen for a particular message from its subgroup and perform an action based on the message. A message can be sent by a subgroup, or it can be sent as a result of the delivery of an AWT event.


AWT stands for Abstract Windowing Toolkit. AWT is the GUI toolkit that is included with the JDK. This document assumes some familiarity with AWT, especially in the area of AWT events. For information on AWT, please refer to the JDK documentation.

A message has the following fields:

String name
Name of the event; this is "AWT" for AWT events
Object arg
Same as the arg field in the AWT event
Object target
The shadow corresponding to the target field in the AWT event
long when
Time of event creation.
String type
Null for AWT events
String targetName
Null for AWT events
boolean isAWT
True for AWT events

Message Handling (Operations)

Operations are defined in the group. When an AWT event is generated by an AWT component, it is translated into a message and then sent to the group that contains the component. (Actually, the group contains the shadow corresponding to the AWT component.) To intercept messages in the group, one or more of the following methods should be overridden (these are referred to as "message-handling methods"):
  public boolean handleMessage(Message msg);
  public boolean handleEvent(Message msg, Event evt);

  public boolean action(Message msg, Event evt, Object what);

  public boolean mouseDown(Message msg, Event evt, int x, int y);
  public boolean mouseDrag(Message msg, Event evt, int x, int y);
  public boolean mouseUp(Message msg, Event evt, int x, int y);
  public boolean mouseMove(Message msg, Event evt, int x, int y);
  public boolean mouseEnter(Message msg, Event evt, int x, int y);
  public boolean mouseExit(Message msg, Event evt, int x, int y);
  public boolean keyDown(Message msg, Event evt, int key);
  public boolean keyUp(Message msg, Event evt, int key);
  public boolean gotFocus(Message msg, Event evt, Object what);
  public boolean lostFocus(Message msg, Event evt, Object what);

handleMessage is invoked for all messages, whether the message is from a subgroup or is the result of an AWT event. The implementation of handleMessage in the Group class invokes handleEvent for all AWT events.

Code excerpt from "Group.java":

  public boolean handleMessage(Message msg) {
    if (msg.isAWT)
      return handleEvent(msg, (Event)msg.arg);
    else
      return true;
  }

handleEvent is only invoked for messages that come from AWT events. The implementation of handleEvent in the Group class invokes other methods depending on the type of the event. For example, MOUSE_DOWN events cause the mouseDown method to be invoked. By overridding the mouseDown method, all MOUSE_DOWN events originating inside the group will be caught.

Code excerpt from Group.java:

  public boolean handleEvent(Message msg, Event evt) {
    switch (evt.id) {
    case Event.MOUSE_ENTER:
      return mouseEnter(msg, evt, evt.x, evt.y);
    case Event.MOUSE_EXIT:
      return mouseExit(msg, evt, evt.x, evt.y);
    case Event.MOUSE_MOVE:
      return mouseMove(msg, evt, evt.x, evt.y);
    case Event.MOUSE_DOWN:
      return mouseDown(msg, evt, evt.x, evt.y);
    case Event.MOUSE_DRAG:
      return mouseDrag(msg, evt, evt.x, evt.y);
    case Event.MOUSE_UP:
      return mouseUp(msg, evt, evt.x, evt.y);

    case Event.KEY_PRESS:
    case Event.KEY_ACTION:
      return keyDown(msg, evt, evt.key);
    case Event.KEY_RELEASE:
    case Event.KEY_ACTION_RELEASE:
      return keyUp(msg, evt, evt.key);
	    
    case Event.ACTION_EVENT:
      return action(msg, evt, evt.arg);
    case Event.GOT_FOCUS:
      return gotFocus(msg, evt, evt.arg);
    case Event.LOST_FOCUS:
      return lostFocus(msg, evt, evt.arg);

    default:
      return false;
    }
  }

The next example demonstrates action event handling. Action events are generated by AWT components and translated by handleEvent() into calls on the action method. The example assumes the creation of a GUI description containing a button named "OK" and a button named "Cancel." If an action event originates from the "OK" button or the "Cancel" button, a message is printed.


The AWT button component generates an action event when it is clicked.

public boolean action(Message msg, Event evt, Object what) {
  boolean handled = false;

  if (msg.target == gui.ok) {
    System.out.println("OK");
    handled = true;
  }
  else if (msg.target == gui.cancel) {
    System.out.println("Cancel");
    handled = true;
  }

  // All message handling methods should be true if the message
  // was handled, and false otherwise.
  //
  // The return value determines if the message should be passed
  // on to the operation classes, and subsequently on up the
  // group tree. AWT messages are never propagated up the group
  // tree regardless of the return value, but they are forwarded
  // to the operations classes depending on the return value.
  // [ operation classes are currently not implemented ]

  return handled;
}

See also:

More On Groups and Shadows
Generating Java Source Code
What Is a Component Operation?
Adding Operations to Components
GUI Builder Runtime Classes
Adding Operations to Menus
Importing Components

Visual Java GUI Builder API Documentation
Visual Java GUI Builder Runtime Packages
Class Hierarchy
Index of All Fields and Methods