GUI Commands 2.0 has arrived! Find out what's new and improved.
Custom Groups and Widgets

A typical example of customization is to subclass either CommandGroup or ToggleCommandGroup to provide specialized widgets. The following example is taken from the webstart demo, and shows two key methods of PageSelectorGroup that create the button bar on the left of the demo window.

Creating the widget

   /**
    * Creates a new JButtonBar with the specified orientation using the specified face.
    * @param orientation the orientation of the bar, either {@link JButtonBar#VERTICAL} or
    * {@link JButtonBar#HORIZONTAL}.
    * @param faceName the face for button bar and its members to use.
    *
    * @return a new JButtonBar for this group.
    */
   public JButtonBar createButtonBar(int orientation, String faceName)
   {
      JButtonBar buttonBar = new JButtonBar(orientation);
      bindMembers(buttonBar, buttonBar, getButtonFactory(), faceName);
      return buttonBar;
   }

The most important line in the method is the call to bindMembers. This method binds the group to an instance of java.awt.Container and ensures that the container is kept in sync with the group's members. There are two flavours of this method, one ensures the container is populated with buttons, the other with menu items. There are four arguments to the method, which are as follows.

  • owner - the owner provides the garbage collection information for the group. If the owner goes out of scope, all the resources used to manage this particular container will be also be freed for garbage collection. In many cases, the owner will be the container the holds the members of the group.
  • container - the instance of java.awt.Container that will hold the group members. Members are added using the generic Container.add(Component) method (i.e. no layout information is provided).
  • factory - the factory may be either an instance of ButtonFactory or MenuFactory. The container will be populated with either buttons or menu items accordingly.
  • faceName - the face that will be used when creating the members of the group.

Points worth noting:

  1. The group will remove all non group members from the container.
  2. The group may add separators and glue components if they have been specified in the groups member list.

Adding a custom face name

While there are no special requirements for adding a custom face name, there are a couple of things that make the behaviour more consistent for other developers. These are as follows:

  1. Provide create<Widget> methods that use the custom face name by default. In this example, a default createButtonBar() method is provided that uses the custom "page-selector" face.
  2. Override getAlternativeFaceNames to provide sensible defaults if the user hasn't defined the face in the groups configuration. This allows the methods described in point 1 to work reliably.

When overriding getAlternativeFaceNames you should always invoke the super class for face names you don't care about. In the above example, the method ensures the "page-selector" face will default first to the button and then to the default face.

   /**
    * Overrides the default implementation to provide defaults for the page-selector face if
    * it hasn't been specified.
    * @param face the desired face name
    * @return a String array with the alternate faces in preferred order.
    */
   public String[]
   getAlternativeFaceNames(String face)
   {
      if (PAGE_SELECTOR_FACE.equals(face))
         return new String[] {Face.BUTTON, Face.DEFAULT};

      return super.getAlternativeFaceNames(face);
   }