Custom functionality may also be included in the shadow classes. For
example, the window shadow will resize the window to its preferred size
and map the window when its visible
attribute is set to true.
Rules for writing a shadow:
getOnBody
and
setOnBody
methods
in the shadow class where they are declared (attributes flagged with
NONBODY
are the exception to this rule).
getOnBody
and setOnBody
should invoke
super for all attributes that aren't handled in that particular
shadow 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.
From an external viewpoint, a group is a single component that has a set of attributes, public methods, and messages:
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.
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.
Messages
A group will create messages and post them to their parent groups. By
posting messages, 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.
addComponentAttributes
, addFrameAttributes
,
and addDialogAttributes
should be called in the constructor
to add a set of forwarded attributes to the group.
getOnGroup
and setOnGroup
.
Any attributes that are not handled should be passed up using a call to super.
You may call super.setOnGroup
with an attribute, even if
the attribute is already being handled by your setOnGroup
method. This will cause
the attribute value to be stored in the group's list of attributes.
Then, the getOnGroup
method will automatically look
up this attribute's value from the list.
So make sure that any attributes that are handled in
setOnGroup
without
calling super are also handled in the getOnGroup
method.
initRoot
must be overridden to initialize the root of
the application. The root contains all the children that are contained
by the group. The default generated group contains an
initRoot
method that does the right thing.
startGroup
and stopGroup
methods can
be overridden to get notification
when the applet starts and stops. Also, startGroup
will
be called
when standalone applications are completely done initializing. This
can be useful if, for example, you want to do something that may
cause an error, and you want to immediately pop up an error dialog box.
handleMessage
and handleEvent
methods
should be overridden to
receive AWT events from the root children. For AWT events, the
target of the message is the shadow corresponding to the AWT
component that sent the event. The target of the AWT event is
(of course) the AWT component itself.
For AWT components that do not have a shadow, the target of the message will be set to the AWT component itself.
setOnGroup
and getOnGroup
methods will not be invoked until the group has
been initialized. When the group is initialized, setOnGroup
will be invoked for all the attributes.
However, any custom methods you write need to handle the case of
the group not being initialized or created. This isn't a problem
if the user of the group is careful not to call the group's methods
until it is initialized, but better safe than sorry. Dealing with
the group not being initialized almost always consists of doing
a null check on the gui
instance variable.
Main
// Construct the group Group group = new MyFancyGroup(); // Set the group environment. The "args" are command // line arguments. group.setEnvironmentInfo(null, args); // Initialize the group group.initialize(); // Set the top level on the group WindowShadow win = (WindowShadow)group.getWindow(); if (win instanceof FrameShadow) { win.createBody(); group.setTopLevel((Frame)win.getBody()); } else { group.setTopLevel(/* Pass in an existing frame window from your application */); } // Create the group group.create(); // If the group is a panel group, add it in the // hierarchy somewhere if (group.getPanel() != null) { myApplicationFrame.add((Panel)group.getPanel().getBody()); } // Start the group group.start();
Applet
// Construct the group Group group = new MyFancyGroup(); // Set the group environment. The "applet" must be available here. group.setEnvironmentInfo(myApplet, null); // Initialize the group group.initialize(); // Set the top level on the group WindowShadow win = (WindowShadow)group.getWindow(); if (win instanceof FrameShadow) { win.createBody(); group.setTopLevel((Frame)win.getBody()); } else { // Figure out the applet's frame Component comp = applet; while (comp != null && !(comp instanceof Frame)) comp = comp.getParent(); group.setTopLevel((Frame)comp); } // Create the group group.create(); // If the group is a panel group, add it in the // hierarchy somewhere if (group.getPanel() != null) { myApplet.add((Panel)group.getPanel().getBody()); }
The start, stop, and destroy methods should be forwarded from the applet to the group:
group.start(); group.stop(); group.destroy();
See also: