| # GUI Commands User Guide ## Version 2.1 |
| # Expansion Points Expansion points define growth points for groups at runtime. A typical example would be a plugin that provides its own menu, or one that adds additional content to an existing menu. Expansion points ensure the new content is inserted at the correct point. The expansion point location is defined by the `expand` member. Expansion points can be configured to place separators before, after and around any members it contains. The separators are only shown when the expansion point contains one or more members. This is covered in more detail in the Group Configuration section. The following is an example of specifying an expansion point that places a separator before its content:
       group!file-menu@members=\
          new, \
          open, \
          save, \
          save-as, \
          expand(separatorBefore), \
          separator, \
          exit
The content of expansion points is managed using `ExpansionPointBuilders`. The following is a typical example:
       CommandGroup group = new CommandGroup("file-menu");
       // get the builder
       ExpansionPointBuilder builder = group.getExpansionPointBuilder();

       // remove any existing members from the expansion point.
       builder.clear();

       // add a command.
       builder.add(anotherCommand);
       builder.addSeparator();
       // and an inline group.
       builder.addInline(anotherGroup);

       // apply the changes
       builder.applyChanges();
Unlike Group Builders expansion point builders only let you add actual command instances. You can't add commands or groups using just the command Id. # Embedding Expansion point builders allow you to embed new members within an existing group structure. Embedded groups are automatically added inline to existing group members that have matching text. If no match is found the group is added normally to the main group's expansion point. ## Example The following is the main menu definition from the online demo.
       group!main-menu@members=\
          file-menu, \
          view-menu, \
          edit-menu, \
          download-menu, \
          expand, \
          help-menu

       group!help-menu@face.text=_Help
       group!help-menu@members=help-about, expand(separatorBefore)
This produces the standard menu as shown below: Standard Menu Each example withing the demo can provide one or more contributions for the main menu. The face example provides two menus, `face.menu` and `face.help-menu` defined as follows:
       group!face.menu@face.text=Face Menu
       group!face.menu@members=\
         face.basic-command,\
         face.text-leading,\
         face.text-bottom,\
         face.icon-factory-example,\
         face.rollover-example,\
         face.selected-icon-example,\
         face.disabled-icon-example,\
         face.client-property-example

       group!face.help-menu@face.text=_Help
       group!face.help-menu@members=face.help-about
When ever you select a new example, the main frame retrieves its menu contributions and embedds them into the main menu. This is achieved as follows:
       CommandGroup mainMenuGroup = ...;

       // get the builder
       ExpansionPointBuilder builder = mainMenuGroup.getExpansionPointBuilder();

       // clear any previous contributions from the menu, returning
       // it to its original state
       builder.clear();

       // Now add all the contributions. The face demo returns the
       // fac.menu and face.help-menu defined above.
       CommandGroup[] contributions = demoPanel.getMenuContributions();
       for (CommandGroup group : contributions)
       {
          // embed each contribution, matching on the menu face.
          builder.addEmbedded(group, Face.MENU);
       }
       builder.applyChanges();
The following shows the before and after menu structure after selecting the face examples: Before: After: Notice how `face.menu` (text="Face Menu") has been inserted into the main menu bar between the Download and Help menus. The `face.help-menu` (text="Help") however has been added as an inline member of the top level "Help" menu since their text values matched. ## Using Custom Comparators The builder also supports embedding using an arbitrary Comparator if you'd prefer no to match based on the text properties of the groups. The following is an example.
       ExpansionPointBuilder builder = group.getExpansionPointBuilder();

       // use a custom comparator when embedding groups.
       builder.addEmbedded(contribution, new CustomComparator());

       builder.applyChanges();