/**
   * Incrementally builds the menu from the contribution items. This method leaves out double
   * separators and separators in the first or last position.
   *
   * @param force <code>true</code> means update even if not dirty, and <code>false</code> for
   *     normal incremental updating
   * @param recursive <code>true</code> means recursively update all submenus, and <code>false
   *     </code> means just this menu
   */
  protected void update(boolean force, boolean recursive) {
    if (isDirty() || force) {
      if (menuExist()) {
        // clean contains all active items without double separators
        IContributionItem[] items = getItems();
        List clean = new ArrayList(items.length);
        IContributionItem separator = null;
        for (int i = 0; i < items.length; ++i) {
          IContributionItem ci = items[i];
          if (!isChildVisible(ci)) {
            continue;
          }
          if (ci.isSeparator()) {
            // delay creation until necessary
            // (handles both adjacent separators, and separator at end)
            separator = ci;
          } else {
            if (separator != null) {
              if (clean.size() > 0) {
                clean.add(separator);
              }
              separator = null;
            }
            clean.add(ci);
          }
        }

        // remove obsolete (removed or non active)
        Item[] mi = getMenuItems();

        for (int i = 0; i < mi.length; i++) {
          Object data = mi[i].getData();

          if (data == null || !clean.contains(data)) {
            mi[i].dispose();
          } else if (data instanceof IContributionItem
              && ((IContributionItem) data).isDynamic()
              && ((IContributionItem) data).isDirty()) {
            mi[i].dispose();
          }
        }

        // add new
        mi = getMenuItems();
        int srcIx = 0;
        int destIx = 0;

        for (Iterator e = clean.iterator(); e.hasNext(); ) {
          IContributionItem src = (IContributionItem) e.next();
          IContributionItem dest;

          // get corresponding item in SWT widget
          if (srcIx < mi.length) {
            dest = (IContributionItem) mi[srcIx].getData();
          } else {
            dest = null;
          }

          if (dest != null && src.equals(dest)) {
            srcIx++;
            destIx++;
          } else if (dest != null && dest.isSeparator() && src.isSeparator()) {
            mi[srcIx].setData(src);
            srcIx++;
            destIx++;
          } else {
            int start = getMenuItemCount();
            doItemFill(src, destIx);
            int newItems = getMenuItemCount() - start;
            for (int i = 0; i < newItems; i++) {
              Item item = getMenuItem(destIx++);
              item.setData(src);
            }
          }

          // May be we can optimize this call. If the menu has just
          // been created via the call src.fill(fMenuBar, destIx) then
          // the menu has already been updated with update(true)
          // (see MenuManager). So if force is true we do it again. But
          // we can't set force to false since then information for the
          // sub sub menus is lost.
          if (recursive) {
            IContributionItem item = src;
            if (item instanceof SubContributionItem) {
              item = ((SubContributionItem) item).getInnerItem();
            }
            if (item instanceof IMenuManager) {
              ((IMenuManager) item).updateAll(force);
            }
          }
        }

        // remove any old menu items not accounted for
        for (; srcIx < mi.length; srcIx++) {
          mi[srcIx].dispose();
        }

        setDirty(false);
      }
    } else {
      // I am not dirty. Check if I must recursivly walk down the hierarchy.
      if (recursive) {
        IContributionItem[] items = getItems();
        for (int i = 0; i < items.length; ++i) {
          IContributionItem ci = items[i];
          if (ci instanceof IMenuManager) {
            IMenuManager mm = (IMenuManager) ci;
            if (isChildVisible(mm)) {
              mm.updateAll(force);
            }
          }
        }
      }
    }
    updateMenuItem();
  }
 /* (non-Javadoc)
  * @see org.eclipse.jface.action.IContributionItem#update()
  */
 public void update() {
   updateMenuItem();
 }