public final Image addDecoration(
     IPapyrusDecoration pDecoration, int percentageFromSource, int margin, boolean isVolatile) {
   // use image registry, see bug 401056
   Image image = Activator.getPluginIconImage(Activator.ID, pDecoration.getDecorationImageForGE());
   IDecoration decoration =
       createDecorationImage(decoratorTarget, image, percentageFromSource, margin, isVolatile);
   if (decoration != null) {
     decorations.add(decoration);
     String message = pDecoration.getMessage();
     Label toolTip = getToolTip(message);
     if (decoration instanceof Decoration) {
       ((Decoration) decoration).setToolTip(toolTip);
     }
     return image;
   } else {
     return null;
   }
 }
Exemplo n.º 2
0
/**
 * The decorator to represent inherited element This decorator adds a small image ( the
 * generalization icon) next to the UML Element which are inherited. 3 positions are defined for the
 * decoration :
 *
 * <ul>
 *   <li>if the UML Element is represented like an affixed child node : in {@link
 *       PositionConstants#NORTH_WEST} or {@link PositionConstants#SOUTH_EAST} following its
 *       position/parent and margin =1
 *   <li>else if the element is in a compartment list : {@link PositionConstants#EAST} and margin
 *       =-1
 *   <li>else {@link PositionConstants#SOUTH_EAST} and margin = -1
 * </ul>
 */
public class InheritedDecorator implements IDecorator {

  /** the object to be decorated */
  private IDecoratorTarget decoratorTarget;

  /** the decoration being displayed */
  private IDecoration decoration;

  /** the plugin where owning the icons for the UML Element */
  public static final String pluginID = "org.eclipse.papyrus.uml.diagram.common"; // $NON-NLS-1$

  /** the image path */
  public static final String imagePath = "/icons/hyperlink_13x13.gif"; // $NON-NLS-1$

  /** the image used added to represent an inherited element */
  private static final Image ICON_HYPERLINK = Activator.getPluginIconImage(pluginID, imagePath);

  /**
   * Creates a new <code>AbstractDecorator</code> for the decorator target passed in.
   *
   * @param decoratorTarget the object to be decorated
   */
  public InheritedDecorator(IDecoratorTarget decoratorTarget) {
    this.decoratorTarget = decoratorTarget;
  }

  /**
   * Gets the object to be decorated.
   *
   * @return Returns the object to be decorated
   */
  protected IDecoratorTarget getDecoratorTarget() {
    return decoratorTarget;
  }

  /** @return Returns the decoration. */
  public IDecoration getDecoration() {
    return decoration;
  }

  /** @param decoration The decoration to set. */
  public void setDecoration(IDecoration decoration) {
    this.decoration = decoration;
  }

  /** Removes the decoration if it exists and sets it to null. */
  protected void removeDecoration() {
    if (decoration != null) {
      decoratorTarget.removeDecoration(decoration);
      decoration = null;
    }
  }

  /**
   * getDecoratorTargetClassifier Utility method to determine if the decoratorTarget is a supported
   * type for this decorator and return the associated Classifier element.
   *
   * @param decoratorTarget IDecoratorTarget to check and return valid Classifier target.
   * @return node Node if IDecoratorTarget can be supported, null otherwise.
   */
  public static Node getDecoratorTargetNode(IDecoratorTarget decoratorTarget) {
    DescriptionStyle descStyle = null;
    View node = (View) decoratorTarget.getAdapter(View.class);
    if (node != null && !(node instanceof Diagram)) {
      descStyle = (DescriptionStyle) node.getStyle(NotationPackage.eINSTANCE.getDescriptionStyle());

      if (descStyle != null) {
        return (Node) node;
      }
    }
    return null;
  }

  /**
   * Creates the appropriate review decoration if all the criteria is satisfied by the view passed
   * in.
   */
  public void refresh() {
    removeDecoration();

    Node node = getDecoratorTargetNode(getDecoratorTarget());
    IGraphicalEditPart gep =
        (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);

    if (node != null) {
      DescriptionStyle descStyle = getDescriptionStyle(node);

      if (descStyle != null) {
        if (isInherited(node)) {
          // if(Util.isAffixedChildNode(gep)) {

          // setDecoration(getDecoratorTarget().addDecoration(figure,
          // locator, false));
          // } else {
          // setDecoration(getDecoratorTarget().addShapeDecoration(figure,
          // getDirection(node), -1, false));
          // }

          if (gep != null && gep.getRoot() != null) { // if the gep has
            // no parent, we
            // can't test if
            // the container
            // is a
            // compartment
            // list
            // (because, we
            // call the
            // method
            // DiagramEditPartsUtil.getEditPartFromView((View)container,
            // gep);
            IFigure figure = getFigure(ICON_HYPERLINK);
            if (isInCompartmentList(node) && !Util.isAffixedChildNode(gep)) {
              setDecoration(
                  getDecoratorTarget().addShapeDecoration(figure, getDirection(node), -1, false));
            } else {
              Locator locator = new OverlayLocator(gep.getFigure(), getDirection(node));
              setDecoration(getDecoratorTarget().addDecoration(figure, locator, false));
            }
          }
        }
      }
    }
  }

  /**
   * Returns a figure corresponding to this image
   *
   * @param image a image
   * @return a figure corresponding to this image
   */
  public IFigure getFigure(Image image) {
    IMapMode mm =
        MapModeUtil.getMapMode(
            ((IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class))
                .getFigure());
    ImageFigure fig = new ImageFigure();
    fig.setImage(image);
    fig.setSize(mm.DPtoLP(image.getBounds().width), mm.DPtoLP(image.getBounds().height));
    return fig;
  }

  /**
   * Returns the direction to set the decorator for the node
   *
   * @param node the node
   * @return the direction to set the decorator for the node direction can be :
   *     <ul>
   *       <li>{@link PositionConstants#NORTH_WEST} or {@link PositionConstants#SOUTH_EAST} if the
   *           node is an Affixed Child Node
   *       <li>{@link PositionConstants#EAST} if the node is in a compartment list
   *       <li>{@link PositionConstants#SOUTH_EAST} in other cases
   *     </ul>
   */
  protected Direction getDirection(Node node) {
    IGraphicalEditPart gep =
        (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
    assert gep != null;
    // test if its an affixed ChildNode
    // if(Util.isAffixedChildNode(gep)) {
    //
    // IBorderItemLocator loc =
    // ((BorderNamedElementEditPart)gep).getBorderItemLocator();
    // int location = loc.getCurrentSideOfParent();
    // if(PositionConstants.NONE == location) { //sometimes
    // getBorderItemLocator doesn't work correctly!
    // location = PositionConstants.NORTH_WEST;
    // }
    // switch(location) {
    // case PositionConstants.NORTH:
    // case PositionConstants.NORTH_WEST:
    // case PositionConstants.WEST:
    // case PositionConstants.SOUTH_WEST:
    // // return IDecoratorTarget.Direction.NORTH_WEST;
    // default:
    // return IDecoratorTarget.Direction.SOUTH_EAST;
    // }
    // }
    if (gep.getParent() != null) {
      if (isInCompartmentList(node) && !Util.isAffixedChildNode(gep)) {
        return IDecoratorTarget.Direction.EAST;
      }
    }
    return IDecoratorTarget.Direction.SOUTH_WEST;
  }

  /**
   * Tests if the compartment is a compartment list
   *
   * @param node the node on which we want add an Overlay
   * @return <code>true</code> if the compartment is managed by an {@link XYLayoutEditPolicy}
   */
  protected boolean isInCompartmentList(Node node) {
    IGraphicalEditPart gep =
        (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
    if (gep != null && gep.getRoot() != null) {
      EObject container = node.eContainer();
      if (container instanceof View) {
        EditPart EP = DiagramEditPartsUtil.getEditPartFromView((View) container, gep);
        EditPolicy editPolicy = EP.getEditPolicy(EditPolicy.LAYOUT_ROLE);
        if (!(editPolicy instanceof XYLayoutEditPolicy)) { // we are in a
          // compartment
          // list
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Tests if the node is an inherited element
   *
   * @param node a node
   * @return <code>true</code> if the node is an inherited element <code>false</code> if not
   */
  protected boolean isInherited(Node node) {
    EObject element = node.getElement();
    if (element instanceof Element) {
      EObject container = node.eContainer();
      EObject graphicalParent = null;
      if (container instanceof DecorationNode) {
        graphicalParent = ((DecorationNode) container).getElement();
      } else if (container instanceof View) {
        graphicalParent = ((View) container).getElement();
      }
      if (graphicalParent instanceof Property || graphicalParent instanceof Classifier) {
        Classifier classifier = null;
        if (graphicalParent instanceof Property) {
          Type type = ((Property) graphicalParent).getType();
          if (type instanceof Classifier) {
            classifier = (Classifier) type;
          }
        } else {
          classifier = (Classifier) graphicalParent;
        }
        if (classifier != null) {
          EList<NamedElement> inheritedMembers = classifier.getInheritedMembers();
          return inheritedMembers.contains(element);
        }
      }
    }
    return false;
  }

  /**
   * getDescriptionStyle Accessor to retrieve the description style from a Node.
   *
   * @param node Node to retrieve the description style from.
   * @return DescriptionStyle style object
   */
  protected DescriptionStyle getDescriptionStyle(Node node) {
    return (DescriptionStyle) node.getStyle(NotationPackage.eINSTANCE.getDescriptionStyle());
  }

  /** A listener used to listen the change of location and type (for Property) */
  private NotificationListener notificationListener =
      new NotificationListener() {

        /**
         * @see
         *     org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener#notifyChanged(org.eclipse.emf.common.notify.Notification)
         * @param notification
         */
        public void notifyChanged(Notification notification) {

          if (notification.getEventType() == Notification.REMOVE) {
            if (notification.getNotifier() instanceof Classifier) {
              IGraphicalEditPart gep =
                  (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
              assert gep != null;
              // we remove the listener on the container (because it's
              // changing
              DiagramEventBroker.getInstance(gep.getEditingDomain())
                  .removeNotificationListener(
                      (EObject) notification.getNotifier(), notificationListener);
            }
          }
          // we update the listeners It's useful when an Element with overlay
          // changes of parent
          deactivate();
          activate();
          refresh();
        }
      };

  /**
   * Adds listeners on
   *
   * <ul>
   *   <li>Affixed Child Node
   *   <li>graphical parent, when its a {@link Property} (we add the listener on its Type)
   * </ul>
   */
  public void activate() {

    IGraphicalEditPart gep =
        (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
    assert gep != null;
    View view = ((View) gep.getModel());

    if (view instanceof Node) {
      // the location of the decorator can change if it's an Affixed Child
      // Node
      if (isInherited((Node) view) && Util.isAffixedChildNode(gep)) {
        DiagramEventBroker.getInstance(gep.getEditingDomain())
            .addNotificationListener(gep.getNotationView(), notificationListener);
      }
    }

    // if the graphical parent is a Property, we add a listener on the type
    // of the property, to refresh the decoration
    EObject parent = view.eContainer();
    if (parent instanceof DecorationNode) {
      parent = parent.eContainer();
    }
    if (parent instanceof View) {
      EObject el = ((View) parent).getElement();
      if (el instanceof Property) {
        DiagramEventBroker.getInstance(gep.getEditingDomain())
            .addNotificationListener(
                el, UMLPackage.eINSTANCE.getTypedElement_Type(), notificationListener);
      }
    }

    /*
     * We listen the changes on the UML parent, in order to know if the
     * element is changing of parent Adding a listener using the following
     * EReference doesn't work UMLPackage.eINSTANCE.getElement_Owner();
     * UMLPackage.eINSTANCE.getProperty_Class();
     * UMLPackage.eINSTANCE.getNamedElement_Namespace(); that's why we
     * listen the parent
     */
    if (view.getElement() instanceof Element) {
      Element semanticElement = (Element) view.getElement();

      /*
       * We need add a listener only if the element is an element which
       * can be inherited, like Property, Operation, Signal, Classifier...
       */
      if (semanticElement != null && canBeInherited(semanticElement)) {
        // we listen if the container of the element changes!
        if (semanticElement.eContainer() != null) {
          DiagramEventBroker.getInstance(gep.getEditingDomain())
              .addNotificationListener(semanticElement.eContainer(), notificationListener);
        }
      }
    }
  }

  /**
   * Tests if the element can be inherited
   *
   * @param semanticElement the element to test
   * @return <code>true</code> if the element can be inherited
   */
  protected boolean canBeInherited(Element semanticElement) {
    /*
     * maybe we could replace these tests by RedefinableElement? or not?
     */

    if (semanticElement instanceof Classifier) {
      return true;
    } else if (semanticElement instanceof Property) {
      return true;
    } else if (semanticElement instanceof Operation) {
      return true;
    }
    return false;
  }

  /** Removes the listeners and the decorations */
  public void deactivate() {
    removeDecoration();

    IGraphicalEditPart gep =
        (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
    assert gep != null;
    DiagramEventBroker.getInstance(gep.getEditingDomain())
        .removeNotificationListener(gep.getNotationView(), notificationListener);
    View view = ((View) gep.getModel());

    if (view instanceof Node) {
      // the location of the decorator can change if it's an Affixed Child
      // Node
      if (isInherited((Node) view) && Util.isAffixedChildNode(gep)) {
        DiagramEventBroker.getInstance(gep.getEditingDomain())
            .removeNotificationListener(gep.getNotationView(), notificationListener);
      }
    }
    EObject parent = view.eContainer();
    if (parent instanceof View) {
      EObject el = ((View) parent).getElement();
      if (el instanceof Property) {
        DiagramEventBroker.getInstance(gep.getEditingDomain())
            .removeNotificationListener(
                el, UMLPackage.eINSTANCE.getTypedElement_Type(), notificationListener);
      }
    }

    if (view.getElement() instanceof Element) {
      Element semanticElement = (Element) view.getElement();
      if (semanticElement != null) {
        if (semanticElement.eContainer() != null) {
          DiagramEventBroker.getInstance(gep.getEditingDomain())
              .addNotificationListener(semanticElement.eContainer(), notificationListener);
        }
      }
    }
  }
}