code: /*--------------------------------------------------------------*
    Copyright (C) 2006-2015 OpenSim Ltd.
  
    This file is distributed WITHOUT ANY WARRANTY. See the file
    'License' for details on this and other legal matters.
  *--------------------------------------------------------------*/
  
  package org.omnetpp.ned.editor.graph.parts;
  
  import org.eclipse.draw2d.ConnectionAnchor;
  import org.eclipse.draw2d.geometry.Point;
  import org.eclipse.gef.ConnectionEditPart;
  import org.eclipse.gef.EditPolicy;
  import org.eclipse.gef.NodeEditPart;
  import org.eclipse.gef.Request;
  import org.eclipse.gef.requests.DropRequest;
  import org.omnetpp.figures.anchors.GateAnchor;
  import org.omnetpp.ned.editor.graph.parts.policies.NedGraphicalNodeEditPolicy;
  import org.omnetpp.ned.model.ex.ConnectionElementEx;
  
  /**
   * Provides support for connection handling and common display attributes.
   * Both compound and submodules share this as a super type.
   *
   * @author rhornig
   */
  abstract public class ModuleEditPart extends NedEditPart implements NodeEditPart {
  
      @Override
      protected void createEditPolicies() {
          super.createEditPolicies();
          installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new NedGraphicalNodeEditPolicy());
      }
  
      /**
       * Compute the source connection anchor to be assigned based on the current mouse
       * location and available gates.
       * @param p current mouse coordinates
       * @return The selected connection anchor
       */
      public abstract ConnectionAnchor getConnectionAnchorAt(Point p);
  
      /**
       * Returns a connection anchor registered for the given gate
       */
      public abstract GateAnchor getConnectionAnchor(ConnectionElementEx connection, String gate);
  
      public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connEditPart) {
          ConnectionElementEx connection = (ConnectionElementEx) connEditPart.getModel();
          return getConnectionAnchor(connection, connection.getSrcGateWithIndex());
      }
  
      public ConnectionAnchor getSourceConnectionAnchor(Request request) {
          Point pt = new Point(((DropRequest) request).getLocation());
          return getConnectionAnchorAt(pt);
      }
  
      public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connEditPart) {
          ConnectionElementEx connection = (ConnectionElementEx) connEditPart.getModel();
          return getConnectionAnchor(connection, connection.getDestGateWithIndex());
      }
  
      public ConnectionAnchor getTargetConnectionAnchor(Request request) {
          Point pt = new Point(((DropRequest) request).getLocation());
          return getConnectionAnchorAt(pt);
      }
  
      /**
       * Returns the scale factor of the module
       */
      public abstract float getScale();
  
      /**
       * Returns the icon scale factor of the module
       */
      public abstract float getIconScale();
  
      /**
       * Returns the compound module itself, or the compound module editpart
       * which contains this editpart
       */
      public abstract CompoundModuleEditPart getCompoundModulePart();
  
      /**
       * Re-implemented because the original implementation has a global (per viewer) MAP
       * to store MODEL - PART associations. This is a problem if we want to display a compound module which
       * inherits some submodules and connections from an other one (that is also displayed in this viewer)
       * In those cases the original implementation would not create a new PART for the connection in the
       * derived module but would return the editpart from the base module (which is of course wrong)
       * and leads to very strange bugs.
       */
      @Override
      protected ConnectionEditPart createOrFindConnection(Object model) {
          // get the model - controller cache from the containing compound module
          ConnectionEditPart conx = getCompoundModulePart().getModelToConnectionPartsRegistry().get(model);
          if (conx != null)
              return conx;
          return createConnection(model);
      }
  }
  