Пример #1
0
def realtimeArrowMotion(self, event, snap=True):
    """ 
  Animated arrow that has no semantic meaning, but aids interactive drawing 
  """

    cb = self.cb
    dc = cb.getCanvas()
    arrow = self.pilotArrow.getArrow(create=False)
    if (not arrow):
        print 'arrow motion'
        return

    coords = dc.coords(arrow)
    x, y = cb.getCanvasCoords(event)

    # Snap Grid
    if (self.snapGridInfoTuple and self.snapGridInfoTuple[2]):
        gridSize = self.snapGridInfoTuple[0]
        x, y = [snapIt(x, x, gridSize), snapIt(y, y, gridSize)]

    # If still have 2 points, do object Snapping on first point
    # Don't snap if we have a lock in effect (useful for Named Ports)
    if (snap and len(coords) == 4 and not self.pilotArrow.getSnapLock()):
        fromObj = self.pilotArrow.getFromObject()
        if (fromObj):
            # Regular entity
            if (fromObj.hasConnectors()):
                x0, y0 = fromObj.getMinDistance_Connectors2Fixed(fromObj, x, y)
                coords = [x0, y0, x, y]
                dc.coords(*[arrow] + coords)

    # Look under the mouse pointer for treasures :D
    itemTuple = cb.getItemUnderCursor(self, event, ignore=arrow)
    if (not itemTuple):
        return dc.coords(*[arrow] + coords[:-2] + [x, y])
    obj = itemTuple[2]

    # Snap the final point to the nearest object connector (Avoid snapping to self)
    if (snap and obj != self.pilotArrow.getFromObject()):

        # Regular Entity
        if (obj.hasConnectors()):
            # Calc distance from before last point to the nearest connector
            x, y = obj.getMinDistance_Connectors2Fixed(obj, coords[-4],
                                                       coords[-3])

        # Hyperedge! Snap to the center point of the edge
        elif (isHyperEdge(obj)):
            x, y = obj.getCenterCoord()

    dc.coords(*[arrow] + coords[:-2] + [x, y])
Пример #2
0
def realtimeArrowMotion(self, event, snap = True):
  """ 
  Animated arrow that has no semantic meaning, but aids interactive drawing 
  """

  cb = self.cb
  dc = cb.getCanvas()
  arrow = self.pilotArrow.getArrow(create=False)
  if(not arrow):
    print 'arrow motion'
    return
  
  coords = dc.coords(arrow)
  x, y = cb.getCanvasCoords(event)

  # Snap Grid
  if(self.snapGridInfoTuple and self.snapGridInfoTuple[2]):
    gridSize = self.snapGridInfoTuple[0]
    x, y = [ snapIt(x, x, gridSize), snapIt(y, y, gridSize) ]

  # If still have 2 points, do object Snapping on first point 
  # Don't snap if we have a lock in effect (useful for Named Ports) 
  if(snap and len(coords) == 4 and not self.pilotArrow.getSnapLock()):
    fromObj = self.pilotArrow.getFromObject()
    if(fromObj):
      # Regular entity
      if(fromObj.hasConnectors()):
        x0, y0 = fromObj.getMinDistance_Connectors2Fixed(fromObj, x, y)
        coords = [x0, y0, x, y] 
        dc.coords(* [arrow] + coords)
        
  # Look under the mouse pointer for treasures :D
  itemTuple = cb.getItemUnderCursor(self, event, ignore=arrow)
  if(not itemTuple): 
    return dc.coords(* [ arrow ] + coords[:-2] + [x, y])
  obj = itemTuple[2]

  # Snap the final point to the nearest object connector (Avoid snapping to self)
  if(snap and obj != self.pilotArrow.getFromObject()):

    # Regular Entity
    if(obj.hasConnectors()):
      # Calc distance from before last point to the nearest connector
      x, y = obj.getMinDistance_Connectors2Fixed(obj, coords[-4], coords[-3])

    # Hyperedge! Snap to the center point of the edge
    elif(isHyperEdge(obj)): 
      x, y = obj.getCenterCoord()
           
  dc.coords(* [ arrow ] + coords[:-2] + [x, y])
Пример #3
0
def dragInMotion(self, event):
  """ 
  Dragged objects follow mouse motion 
  If snap mode, snaps the top-left of the object. 
  Replaced object.x, object.y with the x,y = object.getCenterCoord() , for 
  a center snap. Do the same to the snapNewEntity method in Utilities. 
  NOTE: Center snap causes problems when saving/loading models because it is 
  applied to new nodes created by loading a model. See ASG.py, addNode()
  """
  
  cb = self.cb
  
  x0, y0 = cb.getLastClickCoord() 
  x1, y1 = cb.getCanvasCoords(event)
  dx, dy = [x1-x0, y1-y0]
  selectionSet = cb.getSelectionObjectSet()
  
  # Many entities, try to make dragging more responsive (faster)
  if(len(selectionSet) > 1):
    dragMotion(self, [x0, y0], [x1, y1], selectionSet)
    
  
  elif(self.snapGridInfoTuple):
    
    gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple
    
    # Apply Snap only to entities, exclude arrows
    if(not snapArrowNode):    
      for object in selectionSet:      
        if(isEntityNode(object)):      
          #x,y = object.getCenterCoord() 
          x1 = snapIt(object.x + dx, x1, gridSize)
          y1 = snapIt(object.y + dy, y1, gridSize)        
          cb.setLastClickCoords([x1, y1])
          break
          
    # Snap Entities or Arrows
    else:
      for object in selectionSet:      
        #x,y = object.getCenterCoord() 
        x1 = snapIt(object.x + dx, x1, gridSize)
        y1 = snapIt(object.y + dy, y1, gridSize)               
        cb.setLastClickCoords([x1, y1])
        break
    
    dragMotion(self, [x0, y0], [x1, y1], selectionSet)
    optimizeConnectionPorts(self)
Пример #4
0
def dragInMotion(self, event):
    """ 
  Dragged objects follow mouse motion 
  If snap mode, snaps the top-left of the object. 
  Replaced object.x, object.y with the x,y = object.getCenterCoord() , for 
  a center snap. Do the same to the snapNewEntity method in Utilities. 
  NOTE: Center snap causes problems when saving/loading models because it is 
  applied to new nodes created by loading a model. See ASG.py, addNode()
  """

    cb = self.cb

    x0, y0 = cb.getLastClickCoord()
    x1, y1 = cb.getCanvasCoords(event)
    dx, dy = [x1 - x0, y1 - y0]
    selectionSet = cb.getSelectionObjectSet()

    # Many entities, try to make dragging more responsive (faster)
    if (len(selectionSet) > 1):
        dragMotion(self, [x0, y0], [x1, y1], selectionSet)

    elif (self.snapGridInfoTuple):

        gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple

        # Apply Snap only to entities, exclude arrows
        if (not snapArrowNode):
            for object in selectionSet:
                if (isEntityNode(object)):
                    #x,y = object.getCenterCoord()
                    x1 = snapIt(object.x + dx, x1, gridSize)
                    y1 = snapIt(object.y + dy, y1, gridSize)
                    cb.setLastClickCoords([x1, y1])
                    break

        # Snap Entities or Arrows
        else:
            for object in selectionSet:
                #x,y = object.getCenterCoord()
                x1 = snapIt(object.x + dx, x1, gridSize)
                y1 = snapIt(object.y + dy, y1, gridSize)
                cb.setLastClickCoords([x1, y1])
                break

        dragMotion(self, [x0, y0], [x1, y1], selectionSet)
        optimizeConnectionPorts(self)
Пример #5
0
  def onGFButtonMotion(self, gf, event):
      """translate the selected GFs and keep track of the total translation since the handler started"""
 
      # Using the snap grid
      if( self.editor.snapGridInfoTuple and len( self.gfList ) > 0 ):
        gridSize = self.editor.snapGridInfoTuple[0] / self.zoom
        x0 = self.previousX
        y0 = self.previousY
        ex = event.x / self.zoom
        ey = event.y / self.zoom
        
        # Snapping to the top left corner of the first object encountered
        x,y = self.gfList[0].getCoords()[:2] 
        x1 = snapIt( x + ex - x0, ex, gridSize)
        y1 = snapIt( y + ey - y0, ey, gridSize)     
        self.previousX = x1
        self.previousY = y1        
        dx = x1 - x0
        dy = y1 - y0 
        self.totalTranslationX += dx
        self.totalTranslationY += dy
        
        for g in self.gfList:
            g.translate(dx, dy)
        
            
      # No snap grid
      else:          
        ex = event.x / self.zoom 
        ey = event.y / self.zoom 
        dx = ex - self.previousX
        dy = ey - self.previousY
        for g in self.gfList:
            g.translate(dx, dy)
        self.totalTranslationX += dx
        self.totalTranslationY += dy
        self.previousX = ex
        self.previousY = ey
Пример #6
0
 def onHandleButtonMotion(self, handleNumber, event):
     newXY = self.poly.getCoords()
     
     
     # Using the snap grid
     if( self.editor.snapGridInfoTuple ):
       gridSize = self.editor.snapGridInfoTuple[0]
       x0 = self.previousHX
       y0 = self.previousHY
                 
       # Snapping to the top left corner of the first object encountered
       x = newXY[handleNumber * 2]
       y = newXY[handleNumber * 2 + 1] 
       x1 = snapIt( x + event.x - x0,event.x,gridSize)
       y1 = snapIt( y + event.y - y0,event.y,gridSize)  
                         
       dx = x1 - x0
       dy = y1 - y0
       
       newXY[handleNumber * 2] += dx/self.zoom
       newXY[handleNumber * 2 + 1] += dy/self.zoom
       self.poly.setCoords(newXY)
       self.handles[handleNumber].translate(dx, dy)
       
       self.previousHX = x1
       self.previousHY = y1
       
     # No snaps
     else:
       dx = (event.x - self.previousHX)
       dy = (event.y - self.previousHY)
       newXY[handleNumber * 2] += dx/self.zoom
       newXY[handleNumber * 2 + 1] += dy/self.zoom
       self.poly.setCoords(newXY)
       self.handles[handleNumber].translate(dx, dy)
       self.previousHX = event.x
       self.previousHY = event.y
Пример #7
0
    def dragOps(self, x0, y0, x1, y1, mouseMove=True):
        """ Drag operation on a control point knob """

        deltaX, deltaY = (x1 - x0, y1 - y0)
        knob, color, type, index = self.activeControlPointTuple

        knobTag = self.dc.gettags(knob)
        if (not knobTag): raise Exception, "No tag, no game!"

        # Move the "real" arrow.
        # Step 1: If the knob is the center object of the link
        if (knobTag[0] == self.INTERMEIDATE_OBJ_TAG):

            obj = self.intermediateObject
            # Move the label/drawing attached to the node
            if (self.moveLabelDrawingMode):
                if (obj.centerObject):
                    obj.centerObject.Move(deltaX, deltaY, 0)

                    # Save the offest as a graphical layout constraint for model save/load
                    if (not obj.layConstraints.has_key('Label Offset')):
                        obj.layConstraints['Label Offset'] = [deltaX, deltaY]
                    else:
                        dx, dy = obj.layConstraints['Label Offset']
                        obj.layConstraints['Label Offset'] = [
                            dx + deltaX, dy + deltaY
                        ]

                    return

            # Move the actual node & dependencies using the obj.Move method
            else:

                # Snap grid: snap the intermediate object
                if (self.snapGridInfoTuple and mouseMove):
                    gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple
                    if (snapControlPoints):
                        cpX, cpY = obj.getCenterCoord()
                        x1 = snapIt(cpX + deltaX, x1, gridSize)
                        y1 = snapIt(cpY + deltaY, y1, gridSize)
                        self.lastMousePosition = [x1, y1]
                        deltaX, deltaY = (x1 - x0, y1 - y0)

                obj.setCenterSelect()
                obj.Move(deltaX, deltaY)

        # Step 2: If the knob is a regular control point, use the hacky method
        elif (knobTag[0][:3] == "Seg"):
            controlPointCoords = self.dc.coords(knob)
            cpX = controlPointCoords[0] + self.CONTROL_POINT_SIZE
            cpY = controlPointCoords[1] + self.CONTROL_POINT_SIZE

            # Snap grid: snap the dragged control points
            if (self.snapGridInfoTuple and mouseMove):
                gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple
                if (snapControlPoints):
                    x1 = snapIt(cpX + deltaX, x1, gridSize)
                    y1 = snapIt(cpY + deltaY, y1, gridSize)
                    self.lastMousePosition = [x1, y1]
                    deltaX, deltaY = (x1 - x0, y1 - y0)

            # Segment 1 coordinates
            seg1Coords = self.dc.coords(self.itemsTuple[0])
            # Segment 1 length minus the starting point and the intermediate object
            seg1Len = len(seg1Coords[2:-2])

            # Segment 1
            if (knobTag[0][-1:] == "1"):

                # Failure case that will never happen... really... it won't...
                if (index * 2 > seg1Len):
                    raise Exception, "Noooooo! Don't do it Bun-Bun!"

                seg1Coords[index * 2 + 2] += deltaX
                seg1Coords[index * 2 + 3] += deltaY
                self.dc.coords(*[self.itemsTuple[0]] + seg1Coords)

            # Segment 2
            elif (knobTag[0][-1:] == "2"):
                seg2Coords = self.dc.coords(self.itemsTuple[1])

                # Segment 2 coordinates minus the starting point and the intermediate object
                seg2Len = len(seg2Coords[2:-2])
                normalizedIndex = index * 2 - seg1Len - 2  # Subtract seg1  & inter. object

                # Failure cases that should *never* happen
                if (normalizedIndex > seg2Len):
                    raise Exception, "Noooooo! Don't do it Bun-Bun."
                elif (normalizedIndex < 0):
                    raise Exception, "Beware the kitten..."

                # Flip the index because of some really freaky reversal
                normalizedIndex = seg2Len - normalizedIndex

                seg2Coords[normalizedIndex] += deltaX
                seg2Coords[normalizedIndex + 1] += deltaY
                self.dc.coords(*[self.itemsTuple[1]] + seg2Coords)

            # It will always be segment 1 or 2... or I'm gonna get embarassed here...
            else:
                raise Exception, "Game called on account of naked chick (see www.sluggy.com)."

        # Since all knobs are given a tag, this won't happen...
        else:
            raise Exception, "No tag, no game!"

        # Move the Control Point Knob
        controlPointCoords = self.dc.coords(knob)
        self.dc.move(knob, deltaX, deltaY)

        # Move the colorful arrows...
        coords = self.dc.coords(self.innerArrowItem)
        coords[(index + 1) * 2] += deltaX
        coords[(index + 1) * 2 + 1] += deltaY
        self.dc.coords(*[self.innerArrowItem] + coords)
        self.dc.coords(*[self.outerArrowItem] + coords)

        # Make sure connections are nice (snap the end points to closest connector)
        self.optimalConnectionCheck()
Пример #8
0
  def dragOps(self, x0,y0, x1,y1, mouseMove = True ):
    """ Drag operation on a control point knob """
    
    deltaX, deltaY = (x1-x0,y1-y0)   
    knob, color, type, index = self.activeControlPointTuple

    knobTag = self.dc.gettags( knob )
    if( not knobTag ): raise Exception, "No tag, no game!"
    
    # Move the "real" arrow. 
    # Step 1: If the knob is the center object of the link
    if( knobTag[0] == self.INTERMEIDATE_OBJ_TAG ):
      
      obj = self.intermediateObject
      # Move the label/drawing attached to the node
      if( self.moveLabelDrawingMode ):
        if( obj.centerObject ):
          obj.centerObject.Move(deltaX, deltaY, 0)	
          
          # Save the offest as a graphical layout constraint for model save/load
          if( not obj.layConstraints.has_key( 'Label Offset' ) ):
            obj.layConstraints['Label Offset'] = [deltaX,deltaY]
          else:
            dx,dy = obj.layConstraints['Label Offset']
            obj.layConstraints['Label Offset'] = [dx+deltaX,dy+deltaY]
            
          return
        
      # Move the actual node & dependencies using the obj.Move method
      else: 
        
        # Snap grid: snap the intermediate object
        if( self.snapGridInfoTuple and mouseMove ):
          gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple
          if( snapControlPoints ):
            cpX,cpY = obj.getCenterCoord()
            x1 = snapIt( cpX+deltaX,x1,gridSize)
            y1 = snapIt( cpY+deltaY,y1,gridSize)         
            self.lastMousePosition = [x1,y1]
            deltaX, deltaY = (x1-x0,y1-y0) 
              
        obj.setCenterSelect()
        obj.Move( deltaX, deltaY  )
    
    # Step 2: If the knob is a regular control point, use the hacky method
    elif( knobTag[0][:3] == "Seg" ):
      controlPointCoords = self.dc.coords(knob)
      cpX = controlPointCoords[0] + self.CONTROL_POINT_SIZE 
      cpY = controlPointCoords[1] + self.CONTROL_POINT_SIZE 
      
      # Snap grid: snap the dragged control points
      if( self.snapGridInfoTuple and mouseMove ):
        gridSize, snapArrowNode, snapControlPoints = self.snapGridInfoTuple
        if( snapControlPoints ):
          x1 = snapIt( cpX+deltaX,x1,gridSize)
          y1 = snapIt( cpY+deltaY,y1,gridSize)         
          self.lastMousePosition = [x1,y1]
          deltaX, deltaY = (x1-x0,y1-y0) 
          
      # Segment 1 coordinates 
      seg1Coords = self.dc.coords( self.itemsTuple[0] )
      # Segment 1 length minus the starting point and the intermediate object
      seg1Len = len( seg1Coords[2:-2] )      
      
      # Segment 1
      if( knobTag[0][-1:] == "1" ):
             
        # Failure case that will never happen... really... it won't... 
        if( index*2 > seg1Len ): raise Exception, "Noooooo! Don't do it Bun-Bun!"
        
        seg1Coords[index*2+2]   += deltaX
        seg1Coords[index*2+3]   += deltaY
        self.dc.coords( * [self.itemsTuple[0]] + seg1Coords )   
        
      # Segment 2
      elif( knobTag[0][-1:] == "2" ): 
        seg2Coords = self.dc.coords( self.itemsTuple[1] )
 
               
        # Segment 2 coordinates minus the starting point and the intermediate object
        seg2Len = len( seg2Coords[2:-2] ) 
        normalizedIndex = index * 2 - seg1Len - 2  # Subtract seg1  & inter. object   
        
        # Failure cases that should *never* happen
        if( normalizedIndex > seg2Len ): raise Exception, "Noooooo! Don't do it Bun-Bun."
        elif( normalizedIndex < 0 ): raise Exception, "Beware the kitten..."
        
        # Flip the index because of some really freaky reversal
        normalizedIndex = seg2Len - normalizedIndex
        
        seg2Coords[normalizedIndex]     += deltaX
        seg2Coords[normalizedIndex+1]   += deltaY
        self.dc.coords( * [self.itemsTuple[1]] + seg2Coords )  
       
      # It will always be segment 1 or 2... or I'm gonna get embarassed here...
      else:
        raise Exception, "Game called on account of naked chick (see www.sluggy.com)."
Пример #9
0
def dropArrowPoints(self, event, snap = True, filterLinkTypeList=None):
  """ 
  Drops intermediate points in the arrow or connects the arrow to the final
  object. If connection is not possible due to the final object not having 
  connectors, the arrow will be rolled back 1 connection point, or destroyed
  """
  
  cb = self.cb                        # User-interface callback object
  dc = cb.getCanvas()
  x, y = cb.getCanvasCoords(event)   # Event coordinates     
  
  arrow = self.pilotArrow.getArrow()
  coords = dc.coords(arrow)
    
  # Find the closest item to the arrow
  itemTuple = cb.getItemUnderCursor(self, event, ignore=arrow, allTags=True)
  if(itemTuple and snap):
    itemHandler, tags, obj = itemTuple
    
    # Embedded model  ---> WARNING: Not tested, original AToM3 code
    if(len(tags) >= 2 and tags[1][:4] == 'ASG_'):
      self.toClass = tags[0]   
      # Open to select the entity inside the model
      ATOM3TypeDialog(self, obj.semanticObject, ATOM3TypeDialog.OPEN, 
                      (None, self.setConnectMode))	
      # Check if we have both sides...
      if self.sem_objFrom and self.sem_objTo:	# we have both sides...
        drawConnection(self)
      
    # Object
    elif(tags[0][:3] == 'Obj'):
    
      # Get the actual connector point that we are going to connect to
      # coords[-4],coords[-3] are the before last point, so the min distance 
      # that point to the connector yields the optimal final point.
      # Some objects may not have connectors, in this case gracefully rollback 
      # the arrow
      if(obj.hasConnectors()): 
        coords[-2], coords[-1] = obj.getMinDistance_Connectors2Fixed(obj, 
                                                         coords[-4], coords[-3])
        if(obj.hasNamedPorts() and self.showNamedPortMessage):
          name = obj.guesstimateNamedConnAtPoint(coords[-2], coords[-1])
          if(name):
            text = 'Arrow ended on named port: '  \
                    + name \
                    + '\n\nThis message is shown only when you end an arrow' \
                    + ' directly on a named port' \
                    + '\n\nIf you choose the 2nd option and want to see these '\
                    + 'messages again, restart AToM3'
            dialog = Dialog.Dialog(None, {'title': 'Lock Current Named Port', 
                        'text': text, 
                        'bitmap': '', 
                        'default': 0, 
                        'strings': (name, 'Rollback arrow', 
                                    'Never show this message')})         
            if(dialog.num == 1):
              return
            if(dialog.num == 2):
              self.showNamedPortMessage = False
      
      # Edge just happens to have a connector
      elif(obj.hasCenterObjectConnector()):
        coords[-2], coords[-1] = obj.getCenterCoord()
      
      # Hyperedge! This means that links can connect to links
      elif(isHyperEdge(obj)): 
        coords[-2], coords[-1] = obj.getCenterCoord()
        
      else:
        # Failure! The object had no connectors. Oooops.
        if(self.pilotArrow.rollbackArrow([x, y])):
#          self.UI_scope.event("Reset")
          self.UI_scope("Reset", None)
        return
      
      
      # Get the semantic object
      self.sem_objTo = obj.semanticObject	        
      self.sem_objFrom = self.pilotArrow.getFromObject().semanticObject 
      self.toClass = tags[0]
      self.fromClass = self.pilotArrow.getFromTag()
      
      # Arrow is connecting the object to itself with just 2 points! BAD
      if(self.sem_objTo == self.sem_objFrom and len(coords) <= 4):
        pass
      
      # Draw the connection, turn off simpleConnect, since using intermediate 
      # points
      else:             
        smooth = self.pilotArrow.getSmoothness()
        self.inter_connect_points = coords
        drawConnection(self, smooth, simpleConnect = False, 
                         filterLinkTypeList=filterLinkTypeList)
                
    # Unknown something...
    else:
      raise Exception, tags
      
                  
    # Empty variables
    self.fromClass   = None				
    self.toClass     = None
    self.sem_objFrom = None
    self.sem_objTo   = None

    # Model changed!
    modelChange(self)
    
    # Pilot arrow is no longer needed, GOODBYE!      
    self.pilotArrow.removeArrow(False)
    self.UI_scope("<Arrow Created>", None) # Tell UI we succeeded!
    
  # Nope, keep adding intermediate points
  else:

    # Snap Grid
    if(self.snapGridInfoTuple and self.snapGridInfoTuple[2]):
      gridSize = self.snapGridInfoTuple[0]
      coords[-2:] = [ snapIt(x, x, gridSize), snapIt(y, y, gridSize) ]
    
    # No grid snapping
    else:
      coords[-2:] = [ x, y ]
      
    # Apply coords & add a duplicate point
    dc.coords(* [arrow] + coords + coords[-2:])
Пример #10
0
def dropArrowPoints(self, event, snap=True, filterLinkTypeList=None):
    """ 
  Drops intermediate points in the arrow or connects the arrow to the final
  object. If connection is not possible due to the final object not having 
  connectors, the arrow will be rolled back 1 connection point, or destroyed
  """

    cb = self.cb  # User-interface callback object
    dc = cb.getCanvas()
    x, y = cb.getCanvasCoords(event)  # Event coordinates

    arrow = self.pilotArrow.getArrow()
    coords = dc.coords(arrow)

    # Find the closest item to the arrow
    itemTuple = cb.getItemUnderCursor(self, event, ignore=arrow, allTags=True)
    if (itemTuple and snap):
        itemHandler, tags, obj = itemTuple

        # Embedded model  ---> WARNING: Not tested, original AToM3 code
        if (len(tags) >= 2 and tags[1][:4] == 'ASG_'):
            self.toClass = tags[0]
            # Open to select the entity inside the model
            ATOM3TypeDialog(self, obj.semanticObject, ATOM3TypeDialog.OPEN,
                            (None, self.setConnectMode))
            # Check if we have both sides...
            if self.sem_objFrom and self.sem_objTo:  # we have both sides...
                drawConnection(self)

        # Object
        elif (tags[0][:3] == 'Obj'):

            # Get the actual connector point that we are going to connect to
            # coords[-4],coords[-3] are the before last point, so the min distance
            # that point to the connector yields the optimal final point.
            # Some objects may not have connectors, in this case gracefully rollback
            # the arrow
            if (obj.hasConnectors()):
                coords[-2], coords[-1] = obj.getMinDistance_Connectors2Fixed(
                    obj, coords[-4], coords[-3])
                if (obj.hasNamedPorts() and self.showNamedPortMessage):
                    name = obj.guesstimateNamedConnAtPoint(
                        coords[-2], coords[-1])
                    if (name):
                        text = 'Arrow ended on named port: '  \
                                + name \
                                + '\n\nThis message is shown only when you end an arrow' \
                                + ' directly on a named port' \
                                + '\n\nIf you choose the 2nd option and want to see these '\
                                + 'messages again, restart AToM3'
                        dialog = Dialog.Dialog(
                            None, {
                                'title':
                                'Lock Current Named Port',
                                'text':
                                text,
                                'bitmap':
                                '',
                                'default':
                                0,
                                'strings': (name, 'Rollback arrow',
                                            'Never show this message')
                            })
                        if (dialog.num == 1):
                            return
                        if (dialog.num == 2):
                            self.showNamedPortMessage = False

            # Edge just happens to have a connector
            elif (obj.hasCenterObjectConnector()):
                coords[-2], coords[-1] = obj.getCenterCoord()

            # Hyperedge! This means that links can connect to links
            elif (isHyperEdge(obj)):
                coords[-2], coords[-1] = obj.getCenterCoord()

            else:
                # Failure! The object had no connectors. Oooops.
                if (self.pilotArrow.rollbackArrow([x, y])):
                    #          self.UI_scope.event("Reset")
                    self.UI_scope("Reset", None)
                return

            # Get the semantic object
            self.sem_objTo = obj.semanticObject
            self.sem_objFrom = self.pilotArrow.getFromObject().semanticObject
            self.toClass = tags[0]
            self.fromClass = self.pilotArrow.getFromTag()

            # Arrow is connecting the object to itself with just 2 points! BAD
            if (self.sem_objTo == self.sem_objFrom and len(coords) <= 4):
                pass

            # Draw the connection, turn off simpleConnect, since using intermediate
            # points
            else:
                smooth = self.pilotArrow.getSmoothness()
                self.inter_connect_points = coords
                drawConnection(self,
                               smooth,
                               simpleConnect=False,
                               filterLinkTypeList=filterLinkTypeList)

        # Unknown something...
        else:
            raise Exception, tags

        # Empty variables
        self.fromClass = None
        self.toClass = None
        self.sem_objFrom = None
        self.sem_objTo = None

        # Model changed!
        modelChange(self)

        # Pilot arrow is no longer needed, GOODBYE!
        self.pilotArrow.removeArrow(False)
        self.UI_scope("<Arrow Created>", None)  # Tell UI we succeeded!

    # Nope, keep adding intermediate points
    else:

        # Snap Grid
        if (self.snapGridInfoTuple and self.snapGridInfoTuple[2]):
            gridSize = self.snapGridInfoTuple[0]
            coords[-2:] = [snapIt(x, x, gridSize), snapIt(y, y, gridSize)]

        # No grid snapping
        else:
            coords[-2:] = [x, y]

        # Apply coords & add a duplicate point
        dc.coords(*[arrow] + coords + coords[-2:])