/** have a look at the supplied editors, find which properties are common */
  protected static MethodDescriptor[] getCommonMethodsFor(final Editable[] editables) {
    MethodDescriptor[] res = null;
    final MethodDescriptor[] demo = new MethodDescriptor[] {};

    // right, get the first set of properties
    if (editables.length > 0) {
      final Editable first = editables[0];
      final EditorType firstInfo = first.getInfo();
      if (firstInfo != null) {
        res = firstInfo.getMethodDescriptors();

        // only continue if there are any methods to compare against
        if (res != null) {
          // right, are there any more?
          if (editables.length > 1) {
            // pass through the others, finding the common ground
            for (int cnt = 1; cnt < editables.length; cnt++) {
              final Editable thisE = editables[cnt];

              // get its props
              final EditorType thisEditor = thisE.getInfo();

              // do we have an editor?
              if (thisEditor != null) {
                final MethodDescriptor[] newSet = thisEditor.getMethodDescriptors();

                // find the common ones
                res = (MethodDescriptor[]) getIntersectionFor(res, newSet, demo);
              } else {
                // handle instance where editable doesn't have anything editable
                res = null;
                break;
              }
            }
          }
        } else {
          // handle instance where editable doesn't have anything editable
          res = null;
        }
      }
    }

    return res;
  }
  /** have a look at the supplied editors, find which properties are common */
  protected static MWC.GUI.Tools.SubjectAction[] getUndoableActionsFor(final Editable[] editables) {
    MWC.GUI.Tools.SubjectAction[] res = null;
    final MWC.GUI.Tools.SubjectAction[] demo = new MWC.GUI.Tools.SubjectAction[] {};

    // right, get the first set of properties
    if (editables.length > 0) {
      final Editable first = editables[0];
      final EditorType firstInfo = first.getInfo();
      if (firstInfo != null) {
        res = firstInfo.getUndoableActions();

        // only continue if there are any methods to compare against
        if (res != null) {
          // right, are there any more?
          if (editables.length > 1) {
            // pass through the others, finding the common ground
            for (int cnt = 1; cnt < editables.length; cnt++) {
              final Editable thisE = editables[cnt];

              // get its props
              final EditorType thisEditor = thisE.getInfo();

              // do we have an editor?
              if (thisEditor != null) {
                final MWC.GUI.Tools.SubjectAction[] newSet = thisEditor.getUndoableActions();

                // find the common ones
                res = (MWC.GUI.Tools.SubjectAction[]) getIntersectionFor(res, newSet, demo);
              }
            }
          }
        }
      }
    }
    return res;
  }
  /**
   * @param manager where we add our items to
   * @param editables the selected items
   * @param topLevelLayers the top-level layers that contain our elements (it's these that get
   *     updated)
   * @param parentLayers the immediate parents of our items
   * @param theLayers the overall layers object
   * @param hideClipboardOperations
   */
  public static void getDropdownListFor(
      final IMenuManager manager,
      final Editable[] editables,
      final Layer[] topLevelLayers,
      final Layer[] parentLayers,
      final Layers theLayers,
      final boolean hideClipboardOperations) {

    // sort out the top level layer, if we have one
    Layer theTopLayer = null;
    if (topLevelLayers != null) if (topLevelLayers.length > 0) theTopLayer = topLevelLayers[0];

    // and now the edit-able bits
    if (editables.length > 0) {
      // first the parameters
      MenuManager subMenu = null;
      final PropertyDescriptor[] commonProps = getCommonPropertiesFor(editables);
      if (commonProps != null) {
        for (int i = 0; i < commonProps.length; i++) {
          final PropertyDescriptor thisP = commonProps[i];

          // start off with the booleans
          if (supportsBooleanEditor(thisP)) {
            // generate boolean editors in the sub-menu
            subMenu =
                generateBooleanEditorFor(
                    manager, subMenu, thisP, editables, theLayers, theTopLayer);
          } else {
            // now the drop-down lists
            if (supportsListEditor(thisP)) {
              // generate boolean editors in the sub-menu
              subMenu =
                  generateListEditorFor(manager, subMenu, thisP, editables, theLayers, theTopLayer);
            }
          }
        }
      }

      // special case: if only one item is selected, try adding any additional
      // methods
      if (editables.length == 1) {
        // any additional ones?
        Editable theE = editables[0];

        // ok, get the editor
        EditorType info = theE.getInfo();

        if (info != null) {
          BeanInfo[] additional = info.getAdditionalBeanInfo();

          // any there?
          if (additional != null) {
            // ok, loop through the beans
            for (int i = 0; i < additional.length; i++) {
              BeanInfo thisB = additional[i];
              if (thisB instanceof EditorType) {
                EditorType editor = (EditorType) thisB;
                Editable subject = (Editable) editor.getData();

                // and the properties
                PropertyDescriptor[] theseProps = thisB.getPropertyDescriptors();

                for (int j = 0; j < theseProps.length; j++) {

                  PropertyDescriptor thisP = theseProps[j];

                  // and wrap the object
                  Editable[] holder = new Editable[] {subject};
                  if (supportsBooleanEditor(thisP)) {

                    // generate boolean editors in the sub-menu
                    subMenu =
                        generateBooleanEditorFor(
                            manager, subMenu, thisP, holder, theLayers, theTopLayer);
                  } else {
                    // now the drop-down lists
                    if (supportsListEditor(thisP)) {
                      // generate boolean editors in the sub-menu
                      subMenu =
                          generateListEditorFor(
                              manager, subMenu, thisP, holder, theLayers, theTopLayer);
                    }
                  }
                }
              }
            }
          }
        }
      }

      // hmm, have a go at methods for this item
      // ok, try the methods
      final MethodDescriptor[] meths = getCommonMethodsFor(editables);
      if (meths != null) {
        for (int i = 0; i < meths.length; i++) {
          final Layer myTopLayer = theTopLayer;

          final MethodDescriptor thisMethD = meths[i];

          if (thisMethD == null) {
            CorePlugin.logError(
                Status.ERROR, "Failed to create method, props may be wrongly named", null);
          } else {
            // create button for this method
            final Action doThisAction =
                new SubjectMethod(
                    thisMethD.getDisplayName(),
                    editables,
                    thisMethD.getMethod(),
                    myTopLayer,
                    theLayers);

            // ok - add to the list.
            manager.add(doThisAction);
          }
        }
      }

      // hmm, now do the same for the undoable methods
      final MWC.GUI.Tools.SubjectAction[] actions = getUndoableActionsFor(editables);
      if (actions != null) {
        for (int i = 0; i < actions.length; i++) {
          final MWC.GUI.Tools.SubjectAction thisMethD = actions[i];

          // create button for this method
          final IAction doThisAction =
              generateUndoableActionFor(thisMethD, editables, theLayers, theTopLayer);

          // ok - add to the list.
          manager.add(doThisAction);
        }
      }
    }

    // see if we're still looking at the parent element (we only show
    // clipboard
    // operations for item clicked on)
    if (!hideClipboardOperations) {
      final Clipboard theClipboard = CorePlugin.getDefault().getClipboard();

      // hey, also see if we're going to do a cut/paste
      RightClickCutCopyAdaptor.getDropdownListFor(
          manager, editables, topLevelLayers, parentLayers, theLayers, theClipboard);

      // what about paste?
      Editable selectedItem = null;
      if (editables.length == 1) {
        selectedItem = editables[0];
      }
      RightClickPasteAdaptor.getDropdownListFor(
          manager, selectedItem, topLevelLayers, parentLayers, theLayers, theClipboard);

      manager.add(new Separator());
    }

    if (!_rightClickExtensionsChecked) {
      loadLoaderExtensions();

      // ok, done
      _rightClickExtensionsChecked = true;
    }

    // hmm, do we have any right-click generators?
    if (_additionalRightClickItems != null) {
      for (final Iterator<RightClickContextItemGenerator> thisItem =
              _additionalRightClickItems.iterator();
          thisItem.hasNext(); ) {
        final RightClickContextItemGenerator thisGen =
            (RightClickContextItemGenerator) thisItem.next();

        try {
          thisGen.generate(manager, theLayers, topLevelLayers, editables);
        } catch (final Exception e) {
          // and log the error
          CorePlugin.logError(Status.ERROR, "failed whilst creating context menu", e);
        }
      }
    }
  }