示例#1
0
  def __getEntityList(self, selection):
    """
    If selection is empty, get all nodes on the canvas
    Else filter out links
    Returns semantic objects, subclasses of ASGNode rather than VisualObj
    """
    entityNodeList = []
    
    # Selection may contain a mixed bag of nodes and links
    if(selection):
      for node in selection:
        if(not isConnectionLink(node)):   
          semObj = node.semanticObject   
          semObj._treeVisit = False
          semObj._treeChildren = []    
          entityNodeList.append(semObj)
          
    # No selection? Grab all nodes in diagram
    else:
      if(not self.atom3i.ASGroot): 
        return []
      for nodetype in self.atom3i.ASGroot.nodeTypes:  
        for node in self.atom3i.ASGroot.listNodes[nodetype]:      
          if(not isConnectionLink(node.graphObject_)):  
            node._treeVisit = False
            node._treeChildren = []   
            entityNodeList.append(node)
 
    return entityNodeList
示例#2
0
    def __buildAbstractGraphSelectOnly(self, selectionList):
        """
    Generate abstraction of graph found in selection list
    NOTE: AToM3 dependent method
    """
        # Go through all the nodes
        #nodeList = filter(lambda x: not isConnectionLink(x), selectionList)
        nodeList = [
            node for node in selectionList if not isConnectionLink(node)
        ]
        for node in nodeList:
            self.__NodeList.append(Node(node.semanticObject))

        # Go through all the edges
        #edgeList = filter(isConnectionLink, selectionList)
        edgeList = [node for node in selectionList if isConnectionLink(node)]
        for edge in edgeList:
            semObj = edge.semanticObject

            # Directed edge (could be self-loop)
            if (len(semObj.in_connections_) == len(semObj.out_connections_) ==
                    1):
                self.__buildDirectedEdge(semObj)

            # Hyper-edge, multiple sources/targets
            else:
                self.__buildHyperEdge(semObj)
示例#3
0
    def __getEntityList(self, selection):
        """
    If selection is empty, get all nodes on the canvas
    Else filter out links
    Returns semantic objects, subclasses of ASGNode rather than VisualObj
    """
        entityNodeList = []

        # Selection may contain a mixed bag of nodes and links
        if (selection):
            for node in selection:
                if (not isConnectionLink(node)):
                    semObj = node.semanticObject
                    semObj._treeVisit = False
                    semObj._treeChildren = []
                    entityNodeList.append(semObj)

        # No selection? Grab all nodes in diagram
        else:
            if (not self.atom3i.ASGroot):
                return []
            for nodetype in self.atom3i.ASGroot.nodeTypes:
                for node in self.atom3i.ASGroot.listNodes[nodetype]:
                    if (not isConnectionLink(node.graphObject_)):
                        node._treeVisit = False
                        node._treeChildren = []
                        entityNodeList.append(node)

        return entityNodeList
示例#4
0
  def genLayoutConstraintsCode( self,file, myName, indent):
    """ Generates code related to graphical layout constraints """
    
      
    file.write(indent+myName+'.layConstraints = dict() # Graphical Layout Constraints \n')
    
    lcDict = self.graphObject_.layConstraints
    
    # Links will have their layout constraints tucked away in the center object...
    if( isConnectionLink( self.graphObject_ ) ):      
      if( self.graphObject_.centerObject ):
        centerConstraints = self.graphObject_.centerObject.layConstraints

        # Add in the center object constraints 
        for key in centerConstraints:
          if( not lcDict.has_key( key ) ):
            lcDict[ key ] = centerConstraints[ key ]
          
          # Scaling of the arrow width doesn't exist, so we must want the center object scale
          elif( key == 'scale' ):
            lcDict[ key ] = centerConstraints[ key ]
            
          # Uh oh, conflict... just use one of them...
          else:            
            ## print "WARNING: Constraint conflict, see ASGNode.py in genLayoutConstraintsCode() if this is a problem."
            ## print lcDict, "<-- Object constraints"
            ## print centerConstraints, "<-- Center object constraints"
            ## print centerConstraints[ key ], "<-- Saved constraint (other one dropped)"
            lcDict[ key ] = centerConstraints[ key ]
      
    # Write down all the constraints...
    for key in lcDict.keys():
      file.write(indent+myName+'.layConstraints[\''+str(key)+'\'] = '+str(lcDict[key])+'\n' )
示例#5
0
    def __buildAbstractGraphEntireCanvas(self, atom3i):
        """
    Generate abstraction of graph found on the whole atom3i canvas
    NOTE: AToM3 dependent method
    """
        if (not atom3i.ASGroot):
            return

        edgeList = []
        for nodetype in atom3i.ASGroot.nodeTypes:
            for node in atom3i.ASGroot.listNodes[nodetype]:

                # Regular node
                if (not isConnectionLink(node.graphObject_)):
                    self.__NodeList.append(Node(node))

                # Edge
                else:
                    edgeList.append(node)

        # Do edges in a 2nd phase, otherwise might try to lookup a Node object
        # that does not exist yet.
        for edge in edgeList:
            # Regular edge (could be self-loop)
            if (len(edge.in_connections_) == len(edge.out_connections_) == 1):
                self.__buildDirectedEdge(edge)

            # Hyper-edge
            else:
                self.__buildHyperEdge(edge)
示例#6
0
  def smoothSelected(self):
    """ Toggle smooths all links in the selection, toggles via majority vote """
    
    howManySmoothOnes = 0
    itemHandlers = []
    smoothFlag = True
    
    # Gather Statistics on what's smooth and what's not :D
    for tag in self.selectionDict:
      obj = self.selectionDict[tag][1]
      if(isConnectionLink(obj)):  
        for connObjTuple in obj.in_connections_ + obj.out_connections_:
          itemHandler = connObjTuple[0]
          itemHandlers.append(itemHandler)
          if(self.dc.itemcget(itemHandler, "smooth") != "0"):
            howManySmoothOnes += 1

    # Most of them are already smooth, so un-smooth them
    if(howManySmoothOnes != 0 
        and float(len(itemHandlers)) / float(howManySmoothOnes) > 0.5):
      smoothFlag = False
      
    # Apply the smoothness to the items...
    for itemHandler in itemHandlers:
      self.dc.itemconfigure(itemHandler, smooth = smoothFlag)
示例#7
0
def makeAllConnectionsVisible(self):
  """ """
  color = 'orange'
  
  print '\nVisual modification activated'
  print 'All invisible links have been re-colored to the color', color
  print 'NOTE:'
  print '    Effect is purely visual.'
  print '    Re-load model to restore invisibility of affected links.'
  print '    The', color, 'color is hard-coded in', __file__,
  print 'method makeAllConnectionsVisible\n'  
  
  from ModelSpecificCode import isConnectionLink
  dc = self.cb.getCanvas()
  
  for nodeList in self.ASGroot.listNodes.values():
    for node in nodeList:
      obj = node.graphObject_
      if isConnectionLink(obj):
        for connectionList in [obj.in_connections_ + obj.out_connections_]:
          for conInfoTuple in connectionList:
            itemHandler = conInfoTuple[0]
            #print 'itemHandler', itemHandler
            if(not self.cb.isItemVisible(itemHandler)):
              #print 'invisible'
              itemtype = dc.type(itemHandler)
              #print 'itemtype', itemtype
              if itemtype in ['line', 'text']:
                dc.itemconfigure(itemHandler, fill=color)
              else:
                dc.itemconfigure(itemHandler, outline=color)
示例#8
0
    def __getEntityList(self, selection):
        """
    If selection is empty, get all nodes on the canvas
    Else filter out links
    """
        entityNodeList = []

        # Selection may contain a mixed bag of nodes and links
        if (selection):
            for node in selection:
                if (not isConnectionLink(node)):
                    entityNodeList.append(node)

        # No selection? Grab all nodes in diagram
        else:
            if (not self.atom3i.ASGroot):
                return []
            for nodetype in self.atom3i.ASGroot.nodeTypes:
                for node in self.atom3i.ASGroot.listNodes[nodetype]:
                    if (not isConnectionLink(node.graphObject_)):
                        entityNodeList.append(node.graphObject_)

        return entityNodeList
示例#9
0
  def __getEntityList(self, selection):
    """
    If selection is empty, get all nodes on the canvas
    Else filter out links
    """
    entityNodeList = []
    
    # Selection may contain a mixed bag of nodes and links
    if(selection):
      for node in selection:
        if(not isConnectionLink(node)):          
          entityNodeList.append(node)
          
    # No selection? Grab all nodes in diagram
    else:
      if(not self.atom3i.ASGroot):
        return []
      for nodetype in self.atom3i.ASGroot.nodeTypes:  
        for node in self.atom3i.ASGroot.listNodes[nodetype]:      
          if(not isConnectionLink(node.graphObject_)):  
            entityNodeList.append(node.graphObject_)
 
    return entityNodeList
示例#10
0
  def __getEntityLinkTuple(self, selection):
    """
    If selection is empty, get all nodes & links on the canvas
    Else returns the entities and links in the selection
    Returns a tuple containing:
      entityList = List of entity ASG nodes
      linkNodeDict = Mapping of link ASG nodes to VisualObj graph objects
    """
    entityNodeList = []    # Non-edge entities
    linkNodeDict = dict()  # Regular and self-looping edges
    
    # Selection may contain a mixed bag of nodes and links
    if(selection):
      for node in selection:
        semObj = node.semanticObject  
        if(isConnectionLink(node)):   
          #linkNodeList.append(semObj)
          linkNodeDict[semObj] = node
        else:           
          entityNodeList.append(semObj)
          
    # No selection? Grab all nodes in diagram
    else:
      if(not self.atom3i.ASGroot): 
        return ([], [])
      for nodetype in self.atom3i.ASGroot.nodeTypes:  
        for node in self.atom3i.ASGroot.listNodes[nodetype]:      
          if(isConnectionLink(node.graphObject_)):  
            #linkNodeList.append(node)
            linkNodeDict[node] = node.graphObject_
          else:            
            entityNodeList.append(node)

   
    if(selection):
      return (entityNodeList, linkNodeDict)    
    return (entityNodeList, linkNodeDict)    
示例#11
0
    def __getEntityLinkTuple(self, selection):
        """
    If selection is empty, get all nodes & links on the canvas
    Else returns the entities and links in the selection
    Returns a tuple containing:
      entityList = List of entity ASG nodes
      linkNodeDict = Mapping of link ASG nodes to VisualObj graph objects
    """
        entityNodeList = []  # Non-edge entities
        linkNodeDict = dict()  # Regular and self-looping edges

        # Selection may contain a mixed bag of nodes and links
        if (selection):
            for node in selection:
                semObj = node.semanticObject
                if (isConnectionLink(node)):
                    #linkNodeList.append(semObj)
                    linkNodeDict[semObj] = node
                else:
                    entityNodeList.append(semObj)

        # No selection? Grab all nodes in diagram
        else:
            if (not self.atom3i.ASGroot):
                return ([], [])
            for nodetype in self.atom3i.ASGroot.nodeTypes:
                for node in self.atom3i.ASGroot.listNodes[nodetype]:
                    if (isConnectionLink(node.graphObject_)):
                        #linkNodeList.append(node)
                        linkNodeDict[node] = node.graphObject_
                    else:
                        entityNodeList.append(node)

        if (selection):
            return (entityNodeList, linkNodeDict)
        return (entityNodeList, linkNodeDict)
示例#12
0
    def __grabInfoFromGraphicalObject(self, obj):
        """ Takes a graphical object and stores relevent info in a data structure """

        # This be a node/entity object
        if (not isConnectionLink(obj)):

            try:
                x0, y0, x1, y1 = obj.getbbox()
                width = abs((x0 - x1))
                height = abs((y0 - y1))
                center = [x0 + width / 2, y0 + height / 2]
            except:
                print "ERROR caught and handled in ForceTransfer.py in __grabInfoFromGraphicalObject"
                width = 4
                height = 4
                center = [obj.x, obj.y]
                x0 = obj.x - 2
                y0 = obj.y - 2

            NodeObject(obj,
                       center, [width, height],
                       self.__minNodeDist,
                       topLeftPos=[x0, y0])

        # This be a link/edge object
        elif (self.__minLinkDist > 0):

            # Treat the link center as a repulsive object
            EdgeObject(obj, obj.getCenterCoord(), self.__minLinkDist)

            # Treat each control point as a repulsive object
            if (self.__minControlDist > 0):

                if (not self.dc): return
                for connTuple in obj.connections:
                    itemHandler = connTuple[0]
                    c = self.dc.coords(itemHandler)
                    for i in range(2, len(c) - 2, 2):
                        ControlPoint(c[i:i + 2], self.__minControlDist,
                                     itemHandler, i, self.dc)
示例#13
0
def createDynamicMenu(self, event):
  """ Create a dynamic context sensitive popup menu system  """

  cb = self.cb  
  selectionIsEmpty = cb.isLastSelectionEmpty()
  
  # Item under cursor?
  itemTuple = cb.getItemUnderCursor(self, event)
  if(itemTuple and cb.isItemVisible(itemTuple[0])):
    obj = itemTuple[2]
        
    # Graph Entity Object Selected
    if(isEntityNode(obj)):
      if(selectionIsEmpty):
        self.popupMenuCreator.EntityAtCursorNoSelectPopup(event)
      else:
        self.popupMenuCreator.EntityAtCursorMultiSelectPopup(event)

    # Graph Link Object Selected
    elif(isConnectionLink(obj)): 
      if(selectionIsEmpty):
        self.popupMenuCreator.LinkAtCursorNoSelectPopup(event)
      else:
        self.popupMenuCreator.LinkAtCursorMultiSelectPopup(event)
    
    # Uknown Object Selected
    else:
      raise Exception, \
        "Not an entity, not a link, what is it? Superman? " + str(obj) 
  
  # No item under cursor, no items selected
  elif(selectionIsEmpty):   
    self.popupMenuCreator.NoCursorNoSelectPopup(event)
    
  # No item under cursor, but multiple items selected
  else:   
    self.popupMenuCreator.NoCursorMultiSelectPopup(event)
示例#14
0
def createDynamicMenu(self, event):
    """ Create a dynamic context sensitive popup menu system  """

    cb = self.cb
    selectionIsEmpty = cb.isLastSelectionEmpty()

    # Item under cursor?
    itemTuple = cb.getItemUnderCursor(self, event)
    if (itemTuple and cb.isItemVisible(itemTuple[0])):
        obj = itemTuple[2]

        # Graph Entity Object Selected
        if (isEntityNode(obj)):
            if (selectionIsEmpty):
                self.popupMenuCreator.EntityAtCursorNoSelectPopup(event)
            else:
                self.popupMenuCreator.EntityAtCursorMultiSelectPopup(event)

        # Graph Link Object Selected
        elif (isConnectionLink(obj)):
            if (selectionIsEmpty):
                self.popupMenuCreator.LinkAtCursorNoSelectPopup(event)
            else:
                self.popupMenuCreator.LinkAtCursorMultiSelectPopup(event)

        # Uknown Object Selected
        else:
            raise Exception, \
              "Not an entity, not a link, what is it? Superman? " + str(obj)

    # No item under cursor, no items selected
    elif (selectionIsEmpty):
        self.popupMenuCreator.NoCursorNoSelectPopup(event)

    # No item under cursor, but multiple items selected
    else:
        self.popupMenuCreator.NoCursorMultiSelectPopup(event)
示例#15
0
 def __grabInfoFromGraphicalObject( self, obj ):
         """ Takes a graphical object and stores relevent info in a data structure """
     
         # This be a node/entity object
         if( not isConnectionLink( obj ) ):
           
           try: 
             x0,y0,x1,y1 = obj.getbbox()  
             width  = abs( (x0 - x1) )
             height = abs( (y0 - y1) )
             center = [ x0 + width/2, y0 + height/2 ]
           except:
             print "ERROR caught and handled in ForceTransfer.py in __grabInfoFromGraphicalObject"
             width = 4
             height = 4
             center = [obj.x, obj.y]
             x0 = obj.x - 2
             y0 = obj.y - 2
                         
           NodeObject( obj, center, [width,height], self.__minNodeDist, topLeftPos = [x0,y0] )
                   
         # This be a link/edge object
         elif( self.__minLinkDist > 0 ) :
         
           # Treat the link center as a repulsive object
           EdgeObject( obj, obj.getCenterCoord(), self.__minLinkDist )
         
           # Treat each control point as a repulsive object
           if( self.__minControlDist > 0 ):
             
             if( not self.dc ): return
             for connTuple in obj.connections:
               itemHandler = connTuple[0]
               c = self.dc.coords( itemHandler )    
               for i in range(2,len(c)-2,2): 
                 ControlPoint( c[i:i+2], self.__minControlDist, itemHandler, i, self.dc )
示例#16
0
def writeExportCode(self,
                    fileName,
                    exportFormat,
                    graphicDict,
                    labelingMode=False):
    """
    Generates GML code for creating this graph. 
    self = ASGroot
    """

    file = open(fileName, "w+t")
    dir, fil = os.path.split(fileName)
    funcName = string.split(fil, ".")  # Compose class name

    # Header code
    if (exportFormat == Exporter.GML_LABELED
            or exportFormat == Exporter.GML_CLASSIC):
        # GML
        file.write('Creator	\"Atom3 GML Exporter\"\n')
        file.write('Version	\"0.2.2\"\n')
        file.write('graph\n')
        file.write('[\n')
        file.write('  hierarchic	1\n')
        file.write('  label	\"' + funcName[0] + '\"\n')
        file.write('  directed	1\n')
    elif (exportFormat == Exporter.GXL_LABELED
          or exportFormat == Exporter.GXL_CLASSIC):
        # GXL
        file.write('<gxl><graph>\n')
    elif (exportFormat == Exporter.DOT_LABELED):
        # DOT
        file.write('digraph g {\n')
    else:
        raise Exception

    # Body Code, Version 1: generates a graph with nodes in between nodes (as labels)
    if (labelingMode):

        for nodetype in self.nodeTypes:  # Iterate on all the node types...
            for node in self.listNodes[
                    nodetype]:  # Iterate on all the nodes of each type
                if (isConnectionLink(node.graphObject_)): whiteLabel = True
                else: whiteLabel = False

                shape, color, label = getShapeColorLabel(
                    node, nodetype, graphicDict)
                position = [node.graphObject_.x, node.graphObject_.y]

                # Label with no border
                if (whiteLabel and exportFormat == Exporter.GML_CLASSIC):
                    file.write(  genGMLNodeCode(node.objectNumber,label,position, \
                                                    fill="#FFFFFF", outline= "#FFFFFF" ) )
                else:
                    if (exportFormat == Exporter.GML_CLASSIC):
                        file.write(
                            genGMLNodeCode(node.objectNumber,
                                           label,
                                           position,
                                           fill=color,
                                           type=shape))
                    elif (exportFormat == Exporter.GXL_CLASSIC):
                        file.write(genGXLNodeCode(node.objectNumber, label))

        # Generate code for the connections...
        edgeID = 0
        for nodetype in self.nodeTypes:
            for node in self.listNodes[nodetype]:
                # Looping over the output connections is sufficient
                for obj in node.out_connections_:
                    if (exportFormat == Exporter.GML_CLASSIC):
                        file.write(
                            genGMLConnectionCode(node.objectNumber,
                                                 obj.objectNumber))
                    elif (exportFormat == Exporter.GXL_CLASSIC):
                        file.write(
                            genGXLConnectionCode(node.objectNumber,
                                                 obj.objectNumber, edgeID))
                        edgeID += 1

    # Body Code, Version 2: no intermediate nodes, labels directly on the edges
    else:

        for nodetype in self.nodeTypes:  # Iterate on all the node types...
            for node in self.listNodes[
                    nodetype]:  # Iterate on all the nodes of each type
                if (isConnectionLink(node.graphObject_)): continue

                shape, color, label = getShapeColorLabel(
                    node, nodetype, graphicDict)
                position = [node.graphObject_.x, node.graphObject_.y]

                # Generate code for the nodes...
                if (exportFormat == Exporter.GML_LABELED):
                    file.write(
                        genGMLNodeCode(node.objectNumber,
                                       label,
                                       position,
                                       fill=color,
                                       type=shape))
                elif (exportFormat == Exporter.GXL_LABELED):
                    file.write(genGXLNodeCode(node.objectNumber, label))
                elif (exportFormat == Exporter.DOT_LABELED):
                    file.write(genDOTNodeCode(node.objectNumber, label))

        # Generate code for the connections...
        edgeID = 0
        for nodetype in self.nodeTypes:
            for node in self.listNodes[nodetype]:
                if (not isConnectionLink(node.graphObject_)): continue

                label = getShapeColorLabel(node, nodetype, graphicDict)[2]

                target = node.out_connections_[0].objectNumber
                source = node.in_connections_[0].objectNumber
                if (exportFormat == Exporter.GML_LABELED):
                    file.write(genGMLConnectionCode(source, target, label))
                elif (exportFormat == Exporter.GXL_LABELED):
                    file.write(
                        genGXLConnectionCode(source, target, edgeID, label))
                    edgeID += 1
                elif (exportFormat == Exporter.DOT_LABELED):
                    file.write(genDOTConnectionCode(source, target, label))

    # Footer code
    if (exportFormat == Exporter.GML_LABELED
            or exportFormat == Exporter.GML_CLASSIC):
        # GML
        file.write(']\n')
    elif (exportFormat == Exporter.GXL_LABELED
          or exportFormat == Exporter.GXL_CLASSIC):
        # GXL
        file.write('</graph></gxl>\n')
    elif (exportFormat == Exporter.DOT_LABELED):
        #DOT
        file.write('}\n')
    else:
        raise Exception

    file.close()
    return funcName[0]  # This indicates that we've done something
示例#17
0
    def edit(self, event=None):
        """ Edit window for setting up the graphical appearence of a given node type """

        nodeType = self.listbox.get(self.listbox.curselection()[0])
        shape, color, attrList = self.EXPORT_GRAPHIC_DICT[nodeType]
        node = self.atom3i.ASGroot.listNodes[nodeType][0]
        allAttrList = node.generatedAttributes.keys()
        useShape, useColor, useLabels = self.getExportTypeTuple(
            getExportableAttributes=True)

        # New toplevel window
        self.editWindow = Tkinter.Toplevel(self.Tkroot)
        self.editWindow.geometry("+%d+%d" % (150, 150))
        self.editWindow.title("Export Appearence: " + nodeType)
        self.editWindow.transient(self.Tkroot)
        try:
            self.editWindow.grab_set()
        except:
            pass
        self.editWindow.focus_set()
        self.editWindow.tk_focusFollowsMouse()

        # Frame Creation Area
        self.superEditFrame = Tkinter.Frame(self.editWindow)
        self.editFrame = Tkinter.Frame(self.superEditFrame)

        self.shapeColorFrame = Tkinter.Frame(self.editFrame)
        self.labelFrame = Tkinter.Frame(self.shapeColorFrame)
        self.shapeFrame = Tkinter.Frame(self.shapeColorFrame)
        self.colorFrame = Tkinter.Frame(self.shapeColorFrame)

        self.activeFrame = Tkinter.Frame(self.editFrame)
        self.av_labelFrame = Tkinter.Frame(self.activeFrame)
        self.av_listFrame = Tkinter.Frame(self.activeFrame)
        self.av_remFrame = Tkinter.Frame(self.activeFrame)

        self.allAttributesFrame = Tkinter.Frame(self.editFrame)
        self.all_labelFrame = Tkinter.Frame(self.allAttributesFrame)
        self.all_listFrame = Tkinter.Frame(self.allAttributesFrame)
        self.all_addFrame = Tkinter.Frame(self.allAttributesFrame)

        # Shape & Color Panel
        self.shapeColorl = Tkinter.Label(self.labelFrame,
                                         height=2,
                                         text='Shape & Color',
                                         relief=Tkinter.GROOVE,
                                         bg='white')
        self.shapeListBox = self.createListBox(self.shapeFrame,
                                               self.GML_SHAPE_LIST)

        # Set the active shape
        for i in range(0, len(self.GML_SHAPE_LIST)):
            if (shape == self.GML_SHAPE_LIST[i]):
                self.shapeListBox[0].selection_set(i)

        self.colorb = Tkinter.Button(self.colorFrame,
                                     text="Choose Color",
                                     command=self.chooseColor)
        self.colorl = Tkinter.Label(self.colorFrame,
                                    height=2,
                                    relief=Tkinter.RIDGE,
                                    bg=color)

        self.shapeColorl.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
        self.shapeListBox[0].pack(side=Tkinter.LEFT,
                                  fill=Tkinter.BOTH,
                                  expand=1)
        self.shapeListBox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
        self.colorb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH)
        self.colorl.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)

        # Active Attributes Panel
        self.av_activel = Tkinter.Label(self.av_labelFrame,
                                        height=2,
                                        text='Export Attributes',
                                        relief=Tkinter.GROOVE,
                                        bg='white')
        self.av_activeListbox = self.createListBox(
            self.av_listFrame,
            attrList,
            doubleclickCallback=self.removeActiveAttribute)
        self.av_orderb = Tkinter.Button(self.av_remFrame,
                                        text="Remove Attribute",
                                        command=self.removeActiveAttribute)

        self.av_activel.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
        self.av_activeListbox[0].pack(side=Tkinter.LEFT,
                                      fill=Tkinter.BOTH,
                                      expand=1)
        self.av_activeListbox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
        self.av_orderb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)

        # All Attributes Panel
        self.all_activel = Tkinter.Label(self.all_labelFrame,
                                         height=2,
                                         text='All Attributes',
                                         relief=Tkinter.GROOVE,
                                         bg='white')
        self.all_attributesListbox = self.createListBox(
            self.all_listFrame,
            allAttrList,
            doubleclickCallback=self.addAttribute)
        self.all_orderb = Tkinter.Button(self.all_addFrame,
                                         text="Add Attribute",
                                         command=self.addAttribute)

        self.all_activel.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
        self.all_attributesListbox[0].pack(side=Tkinter.LEFT,
                                           fill=Tkinter.BOTH,
                                           expand=1)
        self.all_attributesListbox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
        self.all_orderb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)

        # Done & Ready Panel
        self.editDoneb = Tkinter.Button(self.superEditFrame,
                                        text="Done",
                                        command=self.editDone)
        self.editDoneb.pack(side=Tkinter.BOTTOM, fill=Tkinter.BOTH, expand=1)

        # Frame Packaging Area
        if (not isConnectionLink(node.graphObject_)
                and (useShape or useColor)):
            self.labelFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
            if (useShape):
                self.shapeFrame.pack(side=Tkinter.TOP,
                                     fill=Tkinter.BOTH,
                                     expand=1)
            if (useColor):
                self.colorFrame.pack(side=Tkinter.TOP,
                                     fill=Tkinter.BOTH,
                                     expand=1)
            self.shapeColorFrame.pack(side=Tkinter.LEFT,
                                      fill=Tkinter.BOTH,
                                      expand=1)

        if (useLabels):
            self.av_labelFrame.pack(side=Tkinter.TOP,
                                    fill=Tkinter.BOTH,
                                    expand=1)
            self.av_listFrame.pack(side=Tkinter.TOP,
                                   fill=Tkinter.BOTH,
                                   expand=1)
            self.av_remFrame.pack(side=Tkinter.TOP,
                                  fill=Tkinter.BOTH,
                                  expand=1)
            self.activeFrame.pack(side=Tkinter.LEFT,
                                  fill=Tkinter.BOTH,
                                  expand=1)

            self.all_labelFrame.pack(side=Tkinter.TOP,
                                     fill=Tkinter.BOTH,
                                     expand=1)
            self.all_listFrame.pack(side=Tkinter.TOP,
                                    fill=Tkinter.BOTH,
                                    expand=1)
            self.all_addFrame.pack(side=Tkinter.TOP,
                                   fill=Tkinter.BOTH,
                                   expand=1)
            self.allAttributesFrame.pack(side=Tkinter.LEFT,
                                         fill=Tkinter.BOTH,
                                         expand=1)

        self.superEditFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
        self.editFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
示例#18
0
def writeExportCode(self, fileName,exportFormat, graphicDict, labelingMode = False ):
    """
    Generates GML code for creating this graph. 
    self = ASGroot
    """
        
    file = open(fileName, "w+t" )
    dir, fil   = os.path.split(fileName)
    funcName   = string.split (fil, ".")	# Compose class name

    # Header code
    if( exportFormat == Exporter.GML_LABELED or exportFormat == Exporter.GML_CLASSIC ):
      # GML 
      file.write('Creator	\"Atom3 GML Exporter\"\n')
      file.write('Version	\"0.2.2\"\n')
      file.write('graph\n')
      file.write('[\n')
      file.write('  hierarchic	1\n')
      file.write('  label	\"' + funcName[0] + '\"\n')
      file.write('  directed	1\n')
    elif( exportFormat == Exporter.GXL_LABELED or exportFormat == Exporter.GXL_CLASSIC ):
      # GXL
      file.write('<gxl><graph>\n')
    elif(exportFormat == Exporter.DOT_LABELED ):
      # DOT
      file.write('digraph g {\n')         
    else:
      raise Exception
      
    # Body Code, Version 1: generates a graph with nodes in between nodes (as labels)
    if( labelingMode ):  
      
      for nodetype in self.nodeTypes:		# Iterate on all the node types...
        for node in self.listNodes[nodetype]:	# Iterate on all the nodes of each type                
          if( isConnectionLink( node.graphObject_ ) ):  whiteLabel = True
          else:                                         whiteLabel = False
          
          shape, color, label = getShapeColorLabel( node, nodetype, graphicDict )
          position = [node.graphObject_.x, node.graphObject_.y]
   
          # Label with no border
          if( whiteLabel and exportFormat == Exporter.GML_CLASSIC ):            
            file.write(  genGMLNodeCode(node.objectNumber,label,position, \
                                            fill="#FFFFFF", outline= "#FFFFFF" ) )
          else:
            if( exportFormat == Exporter.GML_CLASSIC ):               
              file.write(  genGMLNodeCode(node.objectNumber,label,position, 
                                          fill = color, type = shape ) )
            elif( exportFormat == Exporter.GXL_CLASSIC ): 
              file.write(  genGXLNodeCode(node.objectNumber,label ) )
              
      # Generate code for the connections...
      edgeID = 0
      for nodetype in self.nodeTypes:
        for node in self.listNodes[nodetype]:
          # Looping over the output connections is sufficient
          for obj in node.out_connections_:
            if( exportFormat == Exporter.GML_CLASSIC ):             
              file.write( genGMLConnectionCode(node.objectNumber,obj.objectNumber)) 
            elif( exportFormat == Exporter.GXL_CLASSIC ): 
              file.write( genGXLConnectionCode(node.objectNumber,obj.objectNumber,edgeID)) 
              edgeID += 1
    
    
    # Body Code, Version 2: no intermediate nodes, labels directly on the edges
    else:      
      
      for nodetype in self.nodeTypes:		# Iterate on all the node types...
        for node in self.listNodes[nodetype]:	# Iterate on all the nodes of each type               
          if( isConnectionLink( node.graphObject_ ) ):  continue
              
          shape, color, label = getShapeColorLabel( node, nodetype, graphicDict )
          position = [ node.graphObject_.x, node.graphObject_.y]
        
          # Generate code for the nodes...
          if( exportFormat == Exporter.GML_LABELED ):
            file.write(  genGMLNodeCode(node.objectNumber,label,position, fill=color, type=shape) )
          elif( exportFormat == Exporter.GXL_LABELED ):
            file.write(  genGXLNodeCode(node.objectNumber,label) )
          elif(exportFormat == Exporter.DOT_LABELED ):
            file.write(  genDOTNodeCode(node.objectNumber,label) )
      
      # Generate code for the connections...
      edgeID = 0
      for nodetype in self.nodeTypes:
        for node in self.listNodes[nodetype]:
          if( not isConnectionLink( node.graphObject_ ) ):  continue
      
          label = getShapeColorLabel( node, nodetype, graphicDict )[ 2 ]
                  
          target = node.out_connections_[0].objectNumber
          source = node.in_connections_[0].objectNumber     
          if( exportFormat == Exporter.GML_LABELED ):                                                
            file.write( genGMLConnectionCode(source,target,label)  )
          elif( exportFormat == Exporter.GXL_LABELED ):
            file.write( genGXLConnectionCode(source,target,edgeID,label)  )
            edgeID += 1
          elif(exportFormat == Exporter.DOT_LABELED ):
            file.write( genDOTConnectionCode(source,target,label)  )
          
    # Footer code
    if( exportFormat == Exporter.GML_LABELED or exportFormat == Exporter.GML_CLASSIC ):
      # GML
      file.write(']\n')
    elif( exportFormat == Exporter.GXL_LABELED or exportFormat == Exporter.GXL_CLASSIC ):
      # GXL
      file.write('</graph></gxl>\n')
    elif(exportFormat == Exporter.DOT_LABELED ):
      #DOT
      file.write('}\n')
    else:
      raise Exception
  
    file.close()
    return funcName[0] # This indicates that we've done something
示例#19
0
 def edit( self, event=None ):
   """ Edit window for setting up the graphical appearence of a given node type """
   
   nodeType = self.listbox.get(self.listbox.curselection()[0])
   shape, color, attrList = self.EXPORT_GRAPHIC_DICT[ nodeType ]
   node = self.atom3i.ASGroot.listNodes[ nodeType ][ 0 ]
   allAttrList = node.generatedAttributes.keys()
   useShape, useColor, useLabels = self.getExportTypeTuple( getExportableAttributes = True )
     
   # New toplevel window
   self.editWindow = Tkinter.Toplevel(self.Tkroot)
   self.editWindow.geometry("+%d+%d" % (150,150))
   self.editWindow.title("Export Appearence: " + nodeType  )
   self.editWindow.transient(self.Tkroot)        
   try:    self.editWindow.grab_set() 
   except: pass
   self.editWindow.focus_set()  
   self.editWindow.tk_focusFollowsMouse()
   
   # Frame Creation Area
   self.superEditFrame = Tkinter.Frame(self.editWindow) 
   self.editFrame = Tkinter.Frame(self.superEditFrame) 
   
   self.shapeColorFrame = Tkinter.Frame(self.editFrame)
   self.labelFrame = Tkinter.Frame(self.shapeColorFrame)   
   self.shapeFrame = Tkinter.Frame(self.shapeColorFrame)   
   self.colorFrame = Tkinter.Frame(self.shapeColorFrame)   
      
   self.activeFrame = Tkinter.Frame(self.editFrame)
   self.av_labelFrame = Tkinter.Frame(self.activeFrame)
   self.av_listFrame = Tkinter.Frame(self.activeFrame)
   self.av_remFrame = Tkinter.Frame(self.activeFrame)
         
   self.allAttributesFrame = Tkinter.Frame(self.editFrame) 
   self.all_labelFrame = Tkinter.Frame(self.allAttributesFrame) 
   self.all_listFrame = Tkinter.Frame(self.allAttributesFrame) 
   self.all_addFrame = Tkinter.Frame(self.allAttributesFrame) 
   
   
   # Shape & Color Panel 
   self.shapeColorl = Tkinter.Label(self.labelFrame, height=2, text='Shape & Color',                               
                               relief=Tkinter.GROOVE, bg='white' )
   self.shapeListBox = self.createListBox( self.shapeFrame, self.GML_SHAPE_LIST ) 
   
   # Set the active shape
   for i in range( 0, len( self.GML_SHAPE_LIST ) ):
     if( shape == self.GML_SHAPE_LIST[ i ] ):
       self.shapeListBox[0].selection_set( i )
       
   self.colorb = Tkinter.Button(self.colorFrame, text="Choose Color",
                                command=self.chooseColor )
   self.colorl = Tkinter.Label(self.colorFrame, height=2,                               
                               relief=Tkinter.RIDGE, bg=color )                                        
       
   self.shapeColorl.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   self.shapeListBox[0].pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) 
   self.shapeListBox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
   self.colorb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH ) 
   self.colorl.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   
   # Active Attributes Panel
   self.av_activel = Tkinter.Label(self.av_labelFrame, height=2, text='Export Attributes',                               
                                   relief=Tkinter.GROOVE, bg='white' )
   self.av_activeListbox = self.createListBox( self.av_listFrame, attrList, 
                                              doubleclickCallback = self.removeActiveAttribute  ) 
   self.av_orderb = Tkinter.Button(self.av_remFrame, text="Remove Attribute",
                                command=self.removeActiveAttribute ) 
                                                                       
   self.av_activel.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   self.av_activeListbox[0].pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) 
   self.av_activeListbox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
   self.av_orderb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   
   # All Attributes Panel
   self.all_activel = Tkinter.Label(self.all_labelFrame, height=2, text='All Attributes',                               
                                   relief=Tkinter.GROOVE, bg='white' )
   self.all_attributesListbox = self.createListBox( self.all_listFrame, allAttrList,
                                                   doubleclickCallback = self.addAttribute) 
   self.all_orderb = Tkinter.Button(self.all_addFrame, text="Add Attribute",
                                command=self.addAttribute ) 
                                                                       
   self.all_activel.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   self.all_attributesListbox[0].pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) 
   self.all_attributesListbox[1].pack(side=Tkinter.LEFT, fill=Tkinter.Y)
   self.all_orderb.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) 
   
   # Done & Ready Panel 
   self.editDoneb = Tkinter.Button(self.superEditFrame, text="Done",
                                command=self.editDone )
   self.editDoneb.pack(side=Tkinter.BOTTOM, fill=Tkinter.BOTH, expand=1 )     
       
   # Frame Packaging Area
   if( not isConnectionLink( node.graphObject_ ) and (useShape or useColor) ):
     self.labelFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     if( useShape ):
       self.shapeFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     if( useColor ):
       self.colorFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.shapeColorFrame.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
   
   if( useLabels ):
     self.av_labelFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.av_listFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.av_remFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.activeFrame.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
             
     self.all_labelFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.all_listFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.all_addFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
     self.allAttributesFrame.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1)
   
   self.superEditFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
   self.editFrame.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
示例#20
0
  def main(self, selection):

    if( not selection ): return
    
    atom3i = self.atom3i
    nodeObject.nodeList = []
    edgeObject.edgeList = []
    edgeObject.dc       = self.dc   
       
    #------------------------- INFORMATION GATHERING -------------------------
       
    # Generate a datastructure for the Nodes and Edges in the diagram, containing
    # only the information needed by this algorithm.
    edgeList   = []
    nodeDict   = dict()
    self.sourceTargetDict = dict()
    for obj in selection:
        
        if( isConnectionLink( obj ) ):  
          # Edge!
          edgeList.append( obj.getSemanticObject() )                    
        else:
          # Node
          pos = obj.getCenterCoord()
          boundBox = obj.getbbox()
          if( self.__stickyBoundary ):
            boundary = self.atom3i.CANVAS_SIZE_TUPLE
          else:
            boundary = None
          n = nodeObject( obj, pos, boundBox, self.__chargeStrength, boundary )
          nodeDict.update( { obj : n } )
           
    # Now lets go through the "node" edges...
    for node in edgeList:
      # Source object
      key = node.in_connections_[0].graphObject_
      if( not nodeDict.has_key( key ) ): continue
      source = nodeDict[ key ]
      
      # Target object
      key = node.out_connections_[0].graphObject_
      if( not nodeDict.has_key( key ) ): continue
      target = nodeDict[ key ]
      
      # Make the edge object with the info...         
      edgeObject(node, source, target)
      self.sourceTargetDict[ source ] = target
      
      # These nodes have edges...
      source.setHasEdgeTrue()
      target.setHasEdgeTrue()
      
    # Count the beans...
    self.__totalNodes = len( nodeObject.nodeList )
    if( self.__totalNodes <= 1 ):  return                          
                              
    #-------------------------- MAIN SIMULATION LOOP -------------------------
    
    # Initial card shuffling :D
    if( self.__randomness ):
      self.__shakeThingsUp( self.__randomness )

    i = 0
    while( i < self.__maxIterations ):
      
      # Calculate the powers that be
      self.__calculateRepulsiveForces()
      self.__calculateAttractiveForces()
        
      # Move move move!
      for node in nodeObject.nodeList:
        node.commitMove()  
          
      # Force a screen update every x calculation
      if( i % self.__animationUpdates == 0 ):
        self.dc.update_idletasks()

      i+=1
          
    #--------------------------- FINAL OPTIMIZATIONS -------------------------

    # Optimize the arrows to use the nearest connectors
    optimizeLinks( self.atom3i.cb, self.__splineArrows, self.__arrowCurvature )
    
    # Make sure the canvas is updated
    self.dc.update_idletasks()
示例#21
0
def getSelectedItemsForDelete(self, entityOnlyFlag=False):
    """ 
  Use:
    Finds all the selected nodes and links, then creates a custom event, 
    DeleteEvent, which it sends to the UI_scope that then sends the event
    to whichever scoped statechart will handle it. The DeleteEvent uses the
    x, y coordinates of the node/link to be deleted, so potentially, each
    node/link's deletion could be handled by a different scoped statechart. 
  Parameters:
    self, ATOM3 instance
    entityOnlyFlag, if this boolean flag is True, then deleting an entity will
                    NOT automatically delete arrows that connect to that entity
  """
    class DeleteEvent:
        """
    A special event that mimics the x, y coordinates of a Tkinter binding
    generated event, but lacks many of the normal attributes, and includes
    tag and itemHandler attributes not normally found there...
    """
        def __init__(self,
                     obj,
                     tag=None,
                     itemHandlerTagList=None,
                     entityOnlyFlag=False):
            self.x = obj.x
            self.y = obj.y
            self.tag = tag
            self.semanticObject = obj.semanticObject
            self.atom3i = obj.semanticObject.parent
            self.itemHandlerTagList = itemHandlerTagList
            self.entityOnlyFlag = entityOnlyFlag

        def destroy(self):
            """ Deletes the associated ATOM3 node or link """
            if (self.itemHandlerTagList):
                tag2objMap = self.atom3i.cb.getTag2ObjMap()
                for itemHandler, tag in self.itemHandlerTagList:
                    # Deleting one segment of an arrow, can delete the other, so careful!
                    if (tag2objMap.has_key(tag)):
                        self.atom3i.deleteConnection(itemHandler, tag)
            else:
                self.atom3i.deleteRealEntity(self.tag,
                                             entityOnly=self.entityOnlyFlag)

        def getSemanticObject(self):
            """ Returns the ASGNode instance being deleted """
            return self.semanticObject

    selectionDict = self.cb.getSelectionDict()  # Dict of selected items
    objTagDict = dict()

    self.fromClass = None
    self.toClass = None

    # This little dictionary gymnastic is being used to prevent duplicate objects
    for tag in selectionDict:
        obj = selectionDict[tag][1]
        objTagDict.update({obj: tag})

    # Now do the connections first, since if entities disappear,
    # connections might too. And we DO NOT want that to happen... crash crash :p
    for obj in objTagDict:
        tag = objTagDict[obj]

        # Connection
        if (isConnectionLink(obj)):
            #print "Now deleting connection: ", tag, obj, selectionDict[tag][0]
            # This may seem like overkill, but it's necessary for hyper-edges
            connList = []
            for connTuple in obj.in_connections_:
                connList.append(connTuple)
            for connTuple in obj.out_connections_:
                connList.append(connTuple)

            itemHandlerTagList = []
            for connTuple in connList:
                itemHandlerTagList.append(connTuple[:2])
            event = DeleteEvent(obj, itemHandlerTagList=itemHandlerTagList)
            self.UI_scope('<serviceLinkDeleteRequest>', event)

        # Entity
        else:
            event = DeleteEvent(obj, tag=tag, entityOnlyFlag=entityOnlyFlag)
            self.UI_scope('<serviceNodeDeleteRequest>', event)

    # Model changed!
    modelChange(self)

    # No more selected objects :-(
    self.cb.clearSelectionDict()
示例#22
0
def optimizeConnectionPorts(self,
                            entityList=None,
                            linkObjectList=None,
                            doAllLinks=False,
                            cb=None):
    """ 
  Ensures that the endpoints of the arrows use the optimal connectors 
  Applied only to selected arrows and to the arrows attached to selected nodes
  Does not move arrows attached to named ports :D
  
  4 Modes of operation:
  i) Given entityList, a list of nodes, the links between them will be optimized
  ii) Given linkObjectList, a list of edge graph objects, the links are optimized
  iii) Given doAllLinks, a boolean and self=atom3i, optimizes all links on the canvas
  iv) Given self=atom3i or cb=cb, will optimize everything currently selected on the canvas
  
  NOTES:
  a) self argument should be atom3 instance, required if doAllLinks=True, otherwise, cb=cb is acceptable
  b) cb is an instance of CallbackState
  """

    if (not cb):
        cb = self.cb
    dc = cb.getCanvas()

    # Step 1A: Given entities, not a selection dict, so get all affected links
    if (entityList):

        augmentedSelection = dict()

        # List of node/entity objects
        for obj in entityList:
            # Any one of its links may need optimization
            augmentTheSelection(dc, obj, augmentedSelection)

    # Step 1B: Given list of link objects
    elif (linkObjectList):

        augmentedSelection = dict()

        for linkObject in linkObjectList:

            linkTag = linkObject.tag + "1stSeg0"
            itemHandler = dc.find_withtag(linkTag)
            if (not itemHandler):
                print "WARNING: Utilities.optimizeConnectionPorts() cannot find item with tag", linkTag
                continue


#        raise Exception, "optimizeConnectionPorts() having trouble playing " \
#                         + "tag, Step 1B (Try save & load)"

# Add to the selection, {tag : [itemHandler, Object] }
            augmentedSelection[linkTag] = [itemHandler[0], linkObject]

    # Step 1C: Find all the links!
    elif (doAllLinks):

        augmentedSelection = dict()

        nodeTypes = self.ASGroot.nodeTypes
        listNodes = self.ASGroot.listNodes
        for nodetype in nodeTypes:
            if (listNodes[nodetype]):
                if (isConnectionLink(listNodes[nodetype][0].graphObject_)):

                    # Iterate over all the links only
                    for node in listNodes[nodetype]:

                        linkTag = node.graphObject_.tag + "1stSeg0"
                        itemHandler = dc.find_withtag(linkTag)
                        if (not itemHandler):
                            print "WARNING: itemhandler not found! Utilities.py --> " \
                                  + "optimizeConnectionPorts() fails (Try save & load)"
                            continue

                        # Add to the selection, {tag : [itemHandler, Object] }
                        augmentedSelection[linkTag] = [
                            itemHandler[0], node.graphObject_
                        ]

    # Step 1D: Augment the selection with links affected by the node movement
    #          & remove nodes
    else:

        selection = cb.getSelectionDict()
        augmentedSelection = selection.copy(
        )  # <--- This copy() is soooo important

        for tag in selection:
            itemHandler, obj = selection[tag]

            # This is a NODE
            if (isEntityNode(obj)):

                # Any one of its links may need optimization
                augmentTheSelection(dc, obj, augmentedSelection)

                # We don't need to optimize nodes, just links... so... bye bye node
                del augmentedSelection[tag]

    # Step 2: Optimize all the selected links
    for tag in augmentedSelection:

        obj = augmentedSelection[tag][1]
        baseTag = obj.tag  # Ex: Obj3 , the tag of the intermediate link object

        # Some links have center objects (labels/drawings) that look way better
        # if they are above the arrow
        centerObj = obj.getCenterObject()
        if (centerObj):
            dc.tag_raise(centerObj.tag)

        # Find all the entities that the edge is linking to
        # (general enough to handle hyperedges)
        objectsFrom = []
        objectsTo = []
        semObject = obj.getSemanticObject()
        arrowArrowCase = False
        for semObj in semObject.in_connections_:
            if (isConnectionLink(semObj.graphObject_)):
                arrowArrowCase = True
            objectsFrom.append(semObj.graphObject_)
        for semObj in semObject.out_connections_:
            if (isConnectionLink(semObj.graphObject_)):
                arrowArrowCase = True
            objectsTo.append(semObj.graphObject_)

        # Arrow connected to another arrow, this isn't handled!!!
        if (arrowArrowCase):
            continue

        # Initial point/s in the connection ---> Object/s From
        for i in range(0, len(objectsFrom)):

            # Get the tag & itemhandler for each from segement
            segTag = baseTag + "1stSeg" + str(i)
            itemHandler = dc.find_withtag(segTag)
            if (not itemHandler):
                print "WARNING: Having problems looking up canvas tags!", segTag
                continue
                #raise Exception, "Having problems looking up canvas tags!"

            coords = dc.coords(itemHandler)
            objFrom = objectsFrom[i]

            # If the object has connectors and they are not NAMED connectors
            if (objFrom.hasConnectors() and
                    not objFrom.isConnectedByNamedPort(obj.semanticObject)):

                # Snap to the nearest connection port if not already there
                # NOTE: the [obj.x,obj.y] part makes sure we connect directly
                #       to the intermediate object
                x, y = objFrom.getClosestConnector2Point(
                    objFrom, coords[2], coords[3])
                if (x != coords[0] or y != coords[1]):
                    dc.coords(*[itemHandler] + [x, y] + coords[2:-2] +
                              [obj.x, obj.y])

                    # Check if a link drawing needs moving...
                    obj.updateDrawingsTo(x, y, itemHandler[0])

        # Final point/s in the connection ---> Object/s To
        for i in range(0, len(objectsTo)):

            # Get the tag & itemhandler for each to segement
            segTag = baseTag + "2ndSeg" + str(i)
            itemHandler = dc.find_withtag(segTag)
            if (not itemHandler):
                print "WARNING: Having problems looking up canvas tags!", segTag
                continue
                #raise Exception, "Having problems looking up canvas tags!"
            itemHandler = itemHandler[0]

            coords = dc.coords(itemHandler)
            objTo = objectsTo[i]

            if (objTo.hasConnectors()
                    and not objTo.isConnectedByNamedPort(obj.semanticObject)):

                # Snap to the nearest connection port if not already there
                # NOTE: the [obj.x,obj.y] part makes sure we connect directly to the
                #       intermediate object
                x, y = objTo.getClosestConnector2Point(objTo, coords[2],
                                                       coords[3])
                if (x != coords[0] or y != coords[1]):
                    dc.coords(*[itemHandler] + [x, y] + coords[2:-2] +
                              [obj.x, obj.y])

                    # Check if a link drawing needs moving...
                    obj.updateDrawingsTo(x, y, itemHandler, segmentNumber=2)
示例#23
0
def optimizeLinks( cb, setSmooth = True, setCurved = 10, selectedLinks=list(), 
                  curveDirection=-1 ):
  """
  Optimizes the links associated with the nodes in entityList or all the nodes
  in the graph if entityList is not provided.
  The links are set straight, with the endpoints at the nearest connectors of
  the nodes they connect.
  Optionally, additional control points can be added to make a smooth arrow,
  and give it some curvature (setCurved is a pixel distance perpendicular to 
  what would have been a straight arrow ). 
  It is possible to pass a list of link objects directly, and optimize those.
  It is also possible to specify the direction of the curve, Random=-1, Right=0, Left=1
  
  Created July 25, 2004 by Denis Dube
  """
  
  dc = cb.getCanvas() 
  
  # Step 1: Find the selected links 
  if( not selectedLinks ):
    selection = cb.getSelectionDict()
    selectedLinks = []
  
    for tag in selection:
      itemHandler, obj = selection[tag]    
      
      # This is a Link
      if( isConnectionLink( obj ) ):
        if( obj not in selectedLinks ):
          selectedLinks.append(  obj )
              
        
  # Step 2: Optimize all the selected links
  for obj in selectedLinks:
          
    # Optimize the end point connection ports
    optimizeConnectionPorts( None, linkObjectList=selectedLinks, cb=cb ) 
    
    # Find all the entities that the edge is linking to 
    # (general enough to handle hyperedges)
    objectsFrom = []
    objectsTo = []    
    semObject = obj.semanticObject #obj.getSemanticObject()
    if(not semObject):
      continue
    arrowArrowCase = False
    for semObj in semObject.in_connections_: 
      if(isConnectionLink(semObj.graphObject_)):
        arrowArrowCase = True
      objectsFrom.append( semObj.graphObject_ )
    for semObj in semObject.out_connections_: 
      if(isConnectionLink(semObj.graphObject_)):
        arrowArrowCase = True
      objectsTo.append( semObj.graphObject_ )
      
    # Arrow connected to another arrow, this isn't handled!!!
    if(arrowArrowCase):
      continue
    
    # Edge with 2 endpoints
    if( len( objectsFrom ) == 1 and len( objectsTo ) == 1  ):
       
      # Edge with both endpoints on one object
      if( objectsFrom[0] == objectsTo[0] ):
        optimizeSelfLink(dc, obj, objectsFrom[0], setSmooth, setCurved)
      
      # Regular edge
      else:
        optimizeRegularLink( dc, obj, objectsFrom[0], objectsTo[0], 
                              setSmooth, setCurved, curveDirection  )
            
    # Hyper-edge with multiple endpoints
    else:
      optimizerHyperLink( dc, obj, objectsFrom, objectsTo, setSmooth, 
                         setCurved, curveDirection  )
示例#24
0
def optimizeLinks(cb,
                  setSmooth=True,
                  setCurved=10,
                  selectedLinks=list(),
                  curveDirection=-1):
    """
  Optimizes the links associated with the nodes in entityList or all the nodes
  in the graph if entityList is not provided.
  The links are set straight, with the endpoints at the nearest connectors of
  the nodes they connect.
  Optionally, additional control points can be added to make a smooth arrow,
  and give it some curvature (setCurved is a pixel distance perpendicular to 
  what would have been a straight arrow ). 
  It is possible to pass a list of link objects directly, and optimize those.
  It is also possible to specify the direction of the curve, Random=-1, Right=0, Left=1
  
  Created July 25, 2004 by Denis Dube
  """

    dc = cb.getCanvas()

    # Step 1: Find the selected links
    if (not selectedLinks):
        selection = cb.getSelectionDict()
        selectedLinks = []

        for tag in selection:
            itemHandler, obj = selection[tag]

            # This is a Link
            if (isConnectionLink(obj)):
                if (obj not in selectedLinks):
                    selectedLinks.append(obj)

    # Step 2: Optimize all the selected links
    for obj in selectedLinks:

        # Optimize the end point connection ports
        optimizeConnectionPorts(None, linkObjectList=selectedLinks, cb=cb)

        # Find all the entities that the edge is linking to
        # (general enough to handle hyperedges)
        objectsFrom = []
        objectsTo = []
        semObject = obj.semanticObject  #obj.getSemanticObject()
        if (not semObject):
            continue
        arrowArrowCase = False
        for semObj in semObject.in_connections_:
            if (isConnectionLink(semObj.graphObject_)):
                arrowArrowCase = True
            objectsFrom.append(semObj.graphObject_)
        for semObj in semObject.out_connections_:
            if (isConnectionLink(semObj.graphObject_)):
                arrowArrowCase = True
            objectsTo.append(semObj.graphObject_)

        # Arrow connected to another arrow, this isn't handled!!!
        if (arrowArrowCase):
            continue

        # Edge with 2 endpoints
        if (len(objectsFrom) == 1 and len(objectsTo) == 1):

            # Edge with both endpoints on one object
            if (objectsFrom[0] == objectsTo[0]):
                optimizeSelfLink(dc, obj, objectsFrom[0], setSmooth, setCurved)

            # Regular edge
            else:
                optimizeRegularLink(dc, obj, objectsFrom[0], objectsTo[0],
                                    setSmooth, setCurved, curveDirection)

        # Hyper-edge with multiple endpoints
        else:
            optimizerHyperLink(dc, obj, objectsFrom, objectsTo, setSmooth,
                               setCurved, curveDirection)
示例#25
0
    def main(self, selection):

        if (not selection): return

        atom3i = self.atom3i
        nodeObject.nodeList = []
        edgeObject.edgeList = []
        edgeObject.dc = self.dc

        #------------------------- INFORMATION GATHERING -------------------------

        # Generate a datastructure for the Nodes and Edges in the diagram, containing
        # only the information needed by this algorithm.
        edgeList = []
        nodeDict = dict()
        self.sourceTargetDict = dict()
        for obj in selection:

            if (isConnectionLink(obj)):
                # Edge!
                edgeList.append(obj.getSemanticObject())
            else:
                # Node
                pos = obj.getCenterCoord()
                boundBox = obj.getbbox()
                if (self.__stickyBoundary):
                    boundary = self.atom3i.CANVAS_SIZE_TUPLE
                else:
                    boundary = None
                n = nodeObject(obj, pos, boundBox, self.__chargeStrength,
                               boundary)
                nodeDict.update({obj: n})

        # Now lets go through the "node" edges...
        for node in edgeList:
            # Source object
            key = node.in_connections_[0].graphObject_
            if (not nodeDict.has_key(key)): continue
            source = nodeDict[key]

            # Target object
            key = node.out_connections_[0].graphObject_
            if (not nodeDict.has_key(key)): continue
            target = nodeDict[key]

            # Make the edge object with the info...
            edgeObject(node, source, target)
            self.sourceTargetDict[source] = target

            # These nodes have edges...
            source.setHasEdgeTrue()
            target.setHasEdgeTrue()

        # Count the beans...
        self.__totalNodes = len(nodeObject.nodeList)
        if (self.__totalNodes <= 1): return

        #-------------------------- MAIN SIMULATION LOOP -------------------------

        # Initial card shuffling :D
        if (self.__randomness):
            self.__shakeThingsUp(self.__randomness)

        i = 0
        while (i < self.__maxIterations):

            # Calculate the powers that be
            self.__calculateRepulsiveForces()
            self.__calculateAttractiveForces()

            # Move move move!
            for node in nodeObject.nodeList:
                node.commitMove()

            # Force a screen update every x calculation
            if (i % self.__animationUpdates == 0):
                self.dc.update_idletasks()

            i += 1

        #--------------------------- FINAL OPTIMIZATIONS -------------------------

        # Optimize the arrows to use the nearest connectors
        optimizeLinks(self.atom3i.cb, self.__splineArrows,
                      self.__arrowCurvature)

        # Make sure the canvas is updated
        self.dc.update_idletasks()
示例#26
0
def startArrowEditorMode(self, event):
  """ 
  Checks that the selected object is a link, then starts the editor 
  Return True if editor is started
  """
  
  cb = self.cb
  dc = cb.getCanvas()
  
  itemTuple = cb.getItemUnderCursor(self, event)
  if(itemTuple):
    itemHandler, tag, obj = itemTuple
    
    # This is a link --> Proceed
    if(isConnectionLink(obj)): 
      
      # Get information from the tag, segment type and segmenet number
      segTuple = cb.getSegmentTagInfoTuple(tag)
      if(not segTuple): 
        return self.arrowEditor.setArrowEditorAbort()
      
      objNum, segType, segNum = segTuple
      
      # This is the 1st segment, so get the 2nd part
      if(segType == 1):
        nextSegmentTag = "Obj" + str(objNum) + "2ndSeg0"
        nextItemHandler = cb.findItemHandlerWithTag(nextSegmentTag)
        
      # This is the 2nd segment, so get the 1st part
      elif(segType == 2):
        nextSegmentTag = tag
        nextItemHandler = itemHandler
        tag = "Obj" + str(objNum) + "1stSeg0"
        itemHandler = cb.findItemHandlerWithTag(tag)
        
      # Never!
      else:  
        raise Exception, \
          "This will never happen... setType must be 1 or 2!" + str(segType)
          
      seg1coords = dc.coords(itemHandler)
      # Reverse the 2nd segments coords 
      # (so that they are in same direction as the 1st )
      seg2coords = obj.reverseList2by2(dc.coords(nextItemHandler))
      
      # Get the connected objects: objFrom and objTo
      semObject = obj.getSemanticObject()
      if(not semObject.in_connections_ or not semObject.out_connections_): 
        return self.arrowEditor.setArrowEditorAbort()
      
      if(segType == 1):
        connectedObjects = (semObject.in_connections_[segNum].graphObject_, 
                           semObject.out_connections_[0].graphObject_) 
      else:
        connectedObjects = (semObject.in_connections_[0].graphObject_, 
                           semObject.out_connections_[segNum].graphObject_) 
           
      # Now construct the interactive editor arrow
      self.arrowEditor.constructEditorArrow(seg1coords, seg2coords, 
                              (itemHandler, nextItemHandler), 
                               connectedObjects, obj, self.snapGridInfoTuple)
      return
  
  # Things didn't work out... abort!
  self.arrowEditor.setArrowEditorAbort()
示例#27
0
def startArrowEditorMode(self, event):
    """ 
  Checks that the selected object is a link, then starts the editor 
  Return True if editor is started
  """

    cb = self.cb
    dc = cb.getCanvas()

    itemTuple = cb.getItemUnderCursor(self, event)
    if (itemTuple):
        itemHandler, tag, obj = itemTuple

        # This is a link --> Proceed
        if (isConnectionLink(obj)):

            # Get information from the tag, segment type and segmenet number
            segTuple = cb.getSegmentTagInfoTuple(tag)
            if (not segTuple):
                return self.arrowEditor.setArrowEditorAbort()

            objNum, segType, segNum = segTuple

            # This is the 1st segment, so get the 2nd part
            if (segType == 1):
                nextSegmentTag = "Obj" + str(objNum) + "2ndSeg0"
                nextItemHandler = cb.findItemHandlerWithTag(nextSegmentTag)

            # This is the 2nd segment, so get the 1st part
            elif (segType == 2):
                nextSegmentTag = tag
                nextItemHandler = itemHandler
                tag = "Obj" + str(objNum) + "1stSeg0"
                itemHandler = cb.findItemHandlerWithTag(tag)

            # Never!
            else:
                raise Exception, \
                  "This will never happen... setType must be 1 or 2!" + str(segType)

            seg1coords = dc.coords(itemHandler)
            # Reverse the 2nd segments coords
            # (so that they are in same direction as the 1st )
            seg2coords = obj.reverseList2by2(dc.coords(nextItemHandler))

            # Get the connected objects: objFrom and objTo
            semObject = obj.getSemanticObject()
            if (not semObject.in_connections_
                    or not semObject.out_connections_):
                return self.arrowEditor.setArrowEditorAbort()

            if (segType == 1):
                connectedObjects = (
                    semObject.in_connections_[segNum].graphObject_,
                    semObject.out_connections_[0].graphObject_)
            else:
                connectedObjects = (
                    semObject.in_connections_[0].graphObject_,
                    semObject.out_connections_[segNum].graphObject_)

            # Now construct the interactive editor arrow
            self.arrowEditor.constructEditorArrow(
                seg1coords, seg2coords, (itemHandler, nextItemHandler),
                connectedObjects, obj, self.snapGridInfoTuple)
            return

    # Things didn't work out... abort!
    self.arrowEditor.setArrowEditorAbort()
示例#28
0
def getSelectedItemsForDelete(self, entityOnlyFlag=False):
  """ 
  Use:
    Finds all the selected nodes and links, then creates a custom event, 
    DeleteEvent, which it sends to the UI_scope that then sends the event
    to whichever scoped statechart will handle it. The DeleteEvent uses the
    x, y coordinates of the node/link to be deleted, so potentially, each
    node/link's deletion could be handled by a different scoped statechart. 
  Parameters:
    self, ATOM3 instance
    entityOnlyFlag, if this boolean flag is True, then deleting an entity will
                    NOT automatically delete arrows that connect to that entity
  """
  
  class DeleteEvent:
    """
    A special event that mimics the x, y coordinates of a Tkinter binding
    generated event, but lacks many of the normal attributes, and includes
    tag and itemHandler attributes not normally found there...
    """
    def __init__(self, obj, tag=None,
                itemHandlerTagList=None, entityOnlyFlag=False):
      self.x = obj.x
      self.y = obj.y
      self.tag = tag
      self.semanticObject = obj.semanticObject
      self.atom3i = obj.semanticObject.parent
      self.itemHandlerTagList = itemHandlerTagList
      self.entityOnlyFlag = entityOnlyFlag
      
    def destroy(self):
      """ Deletes the associated ATOM3 node or link """
      if(self.itemHandlerTagList):
        tag2objMap = self.atom3i.cb.getTag2ObjMap()
        for itemHandler, tag in self.itemHandlerTagList:
          # Deleting one segment of an arrow, can delete the other, so careful!
          if(tag2objMap.has_key(tag)):
            self.atom3i.deleteConnection(itemHandler, tag)
      else:
        self.atom3i.deleteRealEntity(self.tag, entityOnly=self.entityOnlyFlag)
    
    def getSemanticObject(self):
      """ Returns the ASGNode instance being deleted """
      return self.semanticObject
  
  selectionDict = self.cb.getSelectionDict() # Dict of selected items
  objTagDict = dict()
  
  self.fromClass = None
  self.toClass = None
  
  # This little dictionary gymnastic is being used to prevent duplicate objects
  for tag in selectionDict:
    obj = selectionDict[tag][1]
    objTagDict.update({obj:tag})

  # Now do the connections first, since if entities disappear, 
  # connections might too. And we DO NOT want that to happen... crash crash :p
  for obj in objTagDict:
    tag = objTagDict[obj]
    
    # Connection
    if(isConnectionLink(obj)):  
      #print "Now deleting connection: ", tag, obj, selectionDict[tag][0]
      # This may seem like overkill, but it's necessary for hyper-edges
      connList = []
      for connTuple in obj.in_connections_:  
        connList.append(connTuple)
      for connTuple in obj.out_connections_: 
        connList.append(connTuple)
        
      itemHandlerTagList = []
      for connTuple in connList:
        itemHandlerTagList.append(connTuple[:2])          
      event = DeleteEvent(obj, itemHandlerTagList=itemHandlerTagList)
      self.UI_scope('<serviceLinkDeleteRequest>', event)
      
    # Entity
    else:  
      event = DeleteEvent(obj, tag=tag, entityOnlyFlag=entityOnlyFlag)
      self.UI_scope('<serviceNodeDeleteRequest>', event)
      
  # Model changed!
  modelChange(self)
    
  # No more selected objects :-(
  self.cb.clearSelectionDict()
示例#29
0
def optimizeConnectionPorts(self, entityList = None, linkObjectList=None, 
                            doAllLinks = False, cb=None ):
  """ 
  Ensures that the endpoints of the arrows use the optimal connectors 
  Applied only to selected arrows and to the arrows attached to selected nodes
  Does not move arrows attached to named ports :D
  
  4 Modes of operation:
  i) Given entityList, a list of nodes, the links between them will be optimized
  ii) Given linkObjectList, a list of edge graph objects, the links are optimized
  iii) Given doAllLinks, a boolean and self=atom3i, optimizes all links on the canvas
  iv) Given self=atom3i or cb=cb, will optimize everything currently selected on the canvas
  
  NOTES:
  a) self argument should be atom3 instance, required if doAllLinks=True, otherwise, cb=cb is acceptable
  b) cb is an instance of CallbackState
  """
    
  if( not cb ):
    cb = self.cb
  dc = cb.getCanvas() 
  
  # Step 1A: Given entities, not a selection dict, so get all affected links
  if( entityList ): 
    
    augmentedSelection = dict()
    
    # List of node/entity objects
    for obj in entityList:      
      # Any one of its links may need optimization
      augmentTheSelection( dc, obj, augmentedSelection )
        
  # Step 1B: Given list of link objects
  elif( linkObjectList ):
      
    augmentedSelection = dict()  
      
    for linkObject in linkObjectList:	  
      
      linkTag = linkObject.tag + "1stSeg0"        
      itemHandler = dc.find_withtag( linkTag ) 
      if( not itemHandler ):
        print "WARNING: Utilities.optimizeConnectionPorts() cannot find item with tag", linkTag
        continue
#        raise Exception, "optimizeConnectionPorts() having trouble playing " \
#                         + "tag, Step 1B (Try save & load)"

      # Add to the selection, {tag : [itemHandler, Object] }
      augmentedSelection[ linkTag ] = [ itemHandler[0], linkObject ]
        
  # Step 1C: Find all the links!
  elif( doAllLinks ):
    
    augmentedSelection = dict()
    
    nodeTypes = self.ASGroot.nodeTypes
    listNodes = self.ASGroot.listNodes 
    for nodetype in nodeTypes:	
      if( listNodes[nodetype] ):
        if( isConnectionLink( listNodes[nodetype][0].graphObject_ ) ):  
            
          # Iterate over all the links only
          for node in listNodes[nodetype]:	  
      
            linkTag = node.graphObject_.tag + "1stSeg0"        
            itemHandler = dc.find_withtag( linkTag ) 
            if( not itemHandler ):
              print "WARNING: itemhandler not found! Utilities.py --> " \
                    + "optimizeConnectionPorts() fails (Try save & load)"
              continue
              
            # Add to the selection, {tag : [itemHandler, Object] }
            augmentedSelection[ linkTag ] = [ itemHandler[0], node.graphObject_ ]
    
    
  # Step 1D: Augment the selection with links affected by the node movement 
  #          & remove nodes 
  else: 
     
    selection = cb.getSelectionDict()
    augmentedSelection = selection.copy() # <--- This copy() is soooo important
  
    for tag in selection:
      itemHandler, obj = selection[tag]    
      
      # This is a NODE
      if( isEntityNode( obj ) ):
        
        # Any one of its links may need optimization
        augmentTheSelection( dc, obj, augmentedSelection )
       
        # We don't need to optimize nodes, just links... so... bye bye node
        del augmentedSelection[tag]    

  # Step 2: Optimize all the selected links
  for tag in augmentedSelection:
    
    obj = augmentedSelection[tag][1]
    baseTag = obj.tag # Ex: Obj3 , the tag of the intermediate link object
  
    
    # Some links have center objects (labels/drawings) that look way better
    # if they are above the arrow
    centerObj = obj.getCenterObject()
    if( centerObj ):
      dc.tag_raise(centerObj.tag )
    
    
    # Find all the entities that the edge is linking to 
    # (general enough to handle hyperedges)
    objectsFrom = []
    objectsTo = []    
    semObject = obj.getSemanticObject()
    arrowArrowCase = False
    for semObj in semObject.in_connections_: 
      if(isConnectionLink(semObj.graphObject_)):
        arrowArrowCase = True
      objectsFrom.append( semObj.graphObject_ )
    for semObj in semObject.out_connections_: 
      if(isConnectionLink(semObj.graphObject_)):
        arrowArrowCase = True
      objectsTo.append( semObj.graphObject_ )
      
    # Arrow connected to another arrow, this isn't handled!!!
    if(arrowArrowCase):
      continue
  
    # Initial point/s in the connection ---> Object/s From
    for i in range(0, len(objectsFrom) ):
      
      # Get the tag & itemhandler for each from segement
      segTag = baseTag + "1stSeg" + str(i)
      itemHandler = dc.find_withtag( segTag )
      if( not itemHandler ): 
        print "WARNING: Having problems looking up canvas tags!", segTag
        continue
        #raise Exception, "Having problems looking up canvas tags!"
            
      coords = dc.coords( itemHandler )
      objFrom = objectsFrom[i]
      
      # If the object has connectors and they are not NAMED connectors
      if( objFrom.hasConnectors() and 
          not objFrom.isConnectedByNamedPort( obj.semanticObject ) ):
          
        # Snap to the nearest connection port if not already there
        # NOTE: the [obj.x,obj.y] part makes sure we connect directly 
        #       to the intermediate object
        x, y = objFrom.getClosestConnector2Point(objFrom, coords[2],
                                                 coords[3])    
        if( x != coords[0] or y != coords[1]  ):        
          dc.coords(* [itemHandler] + [x, y] + coords[2:-2] + [obj.x, obj.y])
          
          # Check if a link drawing needs moving...
          obj.updateDrawingsTo( x, y, itemHandler[0] )
  
      
    # Final point/s in the connection ---> Object/s To
    for i in range(0, len(objectsTo) ):
      
      # Get the tag & itemhandler for each to segement
      segTag = baseTag + "2ndSeg" + str(i)
      itemHandler = dc.find_withtag( segTag )
      if( not itemHandler ): 
        print "WARNING: Having problems looking up canvas tags!", segTag
        continue
        #raise Exception, "Having problems looking up canvas tags!"
      itemHandler = itemHandler[0]
            
      coords = dc.coords( itemHandler )
      objTo = objectsTo[i]
        
      if( objTo.hasConnectors() and 
          not objTo.isConnectedByNamedPort( obj.semanticObject ) ):
          
        # Snap to the nearest connection port if not already there
        # NOTE: the [obj.x,obj.y] part makes sure we connect directly to the 
        #       intermediate object
        x, y = objTo.getClosestConnector2Point(objTo, coords[2], coords[3])   
        if( x != coords[0] or y != coords[1]  ): 
          dc.coords(* [itemHandler] + [x, y] + coords[2:-2] + [obj.x, obj.y])
          
          
          # Check if a link drawing needs moving...
          obj.updateDrawingsTo( x, y, itemHandler, segmentNumber=2 )