17.1. Customizing a menu or a toolBar without redefining it from scratch

The insert child element, the insert, replace, replaceEnd attributes may be used to customize to the previous definition of a menu or a toolBar. In this section, we'll use menus in the examples, but it works exactly the same with tool bars.

Extending a menu

There are two ways to extend previously defined menu:

  1. by using the insert child element;

  2. by using the insert attribute.

Only one method for customizing a menu or a toolBar: insert child element OR insert attribute OR replace and replaceEnd attributes (see below) may be used at a time.

  1. Using the insert child element. Example:

    <!-- ==============================================
    Let's suppose this menu is initially defined as follows:
    
    <menu label="Insert">
      <item label="Insert..." command="insert" parameter="into" />
    </menu>
    =============================================== -->
    
    <menu label="Insert">
      <item label="Insert Before..." command="insert"
         parameter="before[implicitElement]" />
      <insert />
      <item label="Insert After..." command="insert" 
        parameter="after[implicitElement]" />
    </menu>

    The insert child element is a directive which means: insert all the items of the previous definition of the same menu here.

    About the label attribute

    When you extend a previously defined menu, the label attribute specifies the title of the extended menu. This means that you can change the title of a menu at the same time you extend it.

    If you don't want to do that, which is often the case, simply specify label="-" in the menu extension. This is simpler and safer than repeating the original label of the menu. In such case, the above example becomes:

    <menu label="-">
      <item label="Insert Before..." command="insert"
         parameter="before[implicitElement]" />
      <insert />
      <item label="Insert After..." command="insert" 
        parameter="after[implicitElement]" />
    </menu>
  2. Using the insert attribute. Example:

    <!-- ==============================================
    Let's suppose this menu is initially defined as follows:
    
    <menu label="Insert">
      <item name="insertBeforeItem" label="Insert Before..." 
        command="insert" parameter="before[implicitElement]" />
      <item name="insertAfterItem" label="Insert After..." 
        command="insert" parameter="after[implicitElement]" />
    </menu>
    =============================================== -->
    
    <menu label="-" insert="insertAfterItem">
      <item label="Insert..." command="insert" parameter="into" />
    </menu>

    The insert attribute is a directive which means: insert all the items found in this menu into the previous definition of the same menu, and this, at specified position.

    The value of the insert attribute is the name of an item found in the previous definition of the same menu. This name may be preceded by modifier "before " , modifier "after " or modifier "into ". Modifier "before " is the implicit one.

    In the above example, extending menu "Insert" could have also been achieved by using:

    <menu label="-" insert="before insertAfterItem">
      <item label="Insert..." command="insert" parameter="into" />
    </menu>

    or by using:

    <menu label="-" insert="after insertBeforeItem">
      <item label="Insert..." command="insert" parameter="into" />
    </menu>

    About modifier "into "

    Modifier "into " means: append to container having specified name. In the case of a menu, this container is necessarily a sub-menu. Example:

    <!-- ==============================================
    Let's suppose this menu is initially defined as follows:
    
    <menu label="XHTML">
      <menu name="pasteAsMenu" label="Paste _As">
        <item label="_p" command="pasteAs"
          parameter="toOrAdd #template(...)"/>
        ...
      </menu>
      <separator />
      ...
    </menu>
    =============================================== -->
    
    <menu label="-" insert="into pasteAsMenu">
      <separator />
      <item label="Paste from _Word" 
        command="pasteFromWord" parameter="..." />
    </menu>

    Alternatively, the value of the insert attribute may be ##first or ##last. Value ##first specifies the first item of the previous definition of the same menu. Value ##last specifies the last item of the previous definition of the same menu. Example:

    <menu label="-" insert="before ##last">
      <item label="Insert..." command="insert" parameter="into" />
    </menu>

    The value of the insert attribute may start with ifDefined(system_property_name). In such case, the previously defined menu is extended if and only if a system property called system_property_name has been defined (no matter its value). Example:

    <menu label="-" 
          insert="ifDefined(HAS_CONVERT_SUBMENU)after ##last">
      <separator />
      <menu label="_Convert Document">
      ...
      </menu>
    </menu>

    In addition to ifDefined(system_property_name), the following conditional processing constructs are also supported:

    • In ifDefined(test), the test is not limited to testing the existence of a system property. It is also possible to specify:

      system_property_name=value

      The test evaluates to true when specified system property exists and is equal to specified value.

      system_property_name^=value

      The test evaluates to true when specified system property exists and starts with specified value.

      system_property_name$=value

      The test evaluates to true when specified system property exists and ends with specified value.

      system_property_name*=value

      The test evaluates to true when specified system property exists and contains specified value.

    • It's also possible to specify ifNotDefined(test). Example (a customization which is applied on Windows and on the Mac, but not on Linux):

      <menu label="-" 
            insert="ifNotDefined(os.name*=Linux)after ##last">
        <separator />
        <menu label="_Convert Document">
        ...
        </menu>
      </menu>

Removing or replacing items inside a menu

Removing or replacing some items inside a menu is done by the means of the replace attribute and, optionally, also the replaceEnd attribute. The replaceEnd attribute is needed to specify a range of sibling items.

Only one method for customizing a menu or a toolBar: insert child element OR insert attribute (see above) OR replace and replaceEnd attributes may be used at a time.

Remove items example:

<!-- ==============================================
Let's suppose this menu is initially defined as follows:

<menu label="XHTML">
  <item name="moveUpItem" label="Move _Up"
        command="moveElement" parameter="up" />
  <item name="moveDownItem" label="Move _Down"
        command="moveElement" parameter="down" />
</menu>
=============================================== -->

<menu label="-" replace="moveUpItem" />

results in the following menu:

<menu label="XHTML">
  <item name="moveDownItem" label="Move _Down"
        command="moveElement" parameter="down" />
</menu>

This could have been specified as follows:

<menu label="-" replace="before moveDownItem" />

or as follows:

<menu label="-" replace="##first" />

In fact, the replace and replaceEnd attributes support the same values as the insert attribute (except modifier "into "). See above. However, there is a pitfall. While attributes insert="before moveDownItem" and insert="moveDownItem" are equivalent, attributes replace="before moveDownItem" and replace="moveDownItem" are not equivalent.

Example of replacing items:

<!-- ==============================================
Let's suppose this menu is initially defined as follows:

<menu label="XHTML">
  <item label="Move _Up"
        command="moveElement" parameter="up" />
  <separator />
  <item name="previewItem" label="Pre_view"
        command="xhtml.preview" />
</menu>
=============================================== -->

<menu label="-" replace="before previewItem" replaceEnd="previewItem">
  <item label="Move _Down"
        command="moveElement" parameter="down" />
</menu>

results in the following menu:

<menu label="XHTML">
  <item label="Move _Up"
        command="moveElement" parameter="up" />
  <item label="Move _Down"
        command="moveElement" parameter="down" />
</menu>