# This file is part of the Coral project.
# Please read the copyright notice in the LICENSE file.

import coral
DI = coral.lang.XMIDI20
from coral.modeler.extension import *
from coral.modeler import iconcache
from coral.modeler.diagram.degen import DiagramElementGenerator, DiagramElementCreatorExt
from coral import log
logger=log.getLogger("UML14DiagramActions")
import coral

import coral.modeler.diagram.di_support as DISUPP

L = coral.lang.UML14
# The below import hack is not useful, use L instead
coral.lang.UML14.__import__(globals())

n = 0
def perpetualEnumerator():
    global n
    n += 1
    return n


class CreateAction( DiagramEditorToolbarEntry ):


    def prepare(self, diagram):
        self.__diagram = diagram

    def __call__(self, hints, parentge):
        return self.doIt(self.__diagram, self.__diagram, hints, parentge)

    def doIt( self, diagram, parent, hints=None, parentge=None ):
        if hints:
            hint1 = hints[0]
            if hint1:
                px = hint1[0]
                py = hint1[1]
            else:
                px = 50
                py = 50


        if parentge:
            model = parentge.semanticModel.element
        else:
            model = diagram.owner.element
        assert model
        
        coral.getTransactionManager().beginModifyCmd()
        try:
            element = self.createModelElement(model,parent)
            if not element:
                return
            deg = DiagramElementGenerator.getExtension(element.__type__())
            if not deg:
                return
            
            if model.oclIsKindOf(Package) and not model.oclIsKindOf(Model) and parentge:
                bc = None
                for cmp in parentge.contained:
                    if str(cmp.semanticModel.typeInfo) == "BodyCompartment":
                        bc = cmp
                        break
                if bc:
                    _x,_y = DISUPP.globalToLocalPosition(bc, px, py)
                    de = deg.createDiagramElement(element, xparent=bc, size=self.getDimension())
                    de.position.x = _x
                    de.position.y = _y
                    bc.contained.append(de)
            else:
                de = deg.createDiagramElement(element, xparent=parent, size=self.getDimension())
                if not de:
                    return
                de.position = DI.Point(x=px,y=py)
                parent.contained.append(de)
        finally:
            coral.getTransactionManager().endModifyCmd()

    def createModelElement( self, model, parent ):
        raise NotImplemented

    def createEdgeOrNot(self):
        return False

    def getDimension(self):
        raise NotImplemented

class CreateEdgeAction( CreateAction ):
    def firstType(self):
        raise NotImplemented

    def secondType(self):
        raise NotImplemented
    
    def createEdgeOrNot(self):
        return True

    def doIt(  self, diagram, parent, hints=None, parentge=None ):
        if not hints or not len(hints)==3:
            return
        model = diagram.owner.element
        assert model

        node1 = hints[0]
        node2 = hints[1]
        waypoints = hints[2]
        waypoints2 = []
        
        if ((node1.semanticModel and node1.semanticModel.element) and
            (node2.semanticModel and node2.semanticModel.element)):
            clsf1 = node1.semanticModel.element
            clsf2 = node2.semanticModel.element
            # BUG this checking should be more generic
            if not (clsf1.oclIsKindOf(self.firstType()) and clsf2.oclIsKindOf(self.secondType())):
                logger.debug("Attempt to make illegal edge")
                return
        else:
            logger.debug("Attempt to make illegal edge")
            return

        coral.getTransactionManager().beginModifyCmd()
        try:
            element = self.createModelElement(model,parent, node1, node2)
            if not element:
                return
            deg = DiagramElementGenerator.getExtension(element.__type__())
            if not deg:
                return
            anchor0 = DI.GraphConnector(graphElement=node1)
            anchor1 = DI.GraphConnector(graphElement=node2)
            ## Create the GraphEdge
            di_parent = DISUPP.getCommonParent(node1, node2)
            for wp in waypoints:
                ps_x, ps_y = coral.XMIDI_GlobalToLocalPosition(di_parent, wp.x, wp.y)
                waypoints2.append(DI.Point(x=ps_x, y=ps_y))
            de = deg.createDiagramElement(element, xparent = di_parent, waypoints=waypoints2 )
            assert de
            de.anchor.append(anchor0)
            de.anchor.append(anchor1)
            de.container = di_parent
            if waypoints:
                self.positionEdgeLabels(de, waypoints2)
        finally:
            coral.getTransactionManager().endModifyCmd()

    def createModelElement(self, model, parent, ge1, ge2):
        raise NotImplemented

    def positionEdgeLabels(self, graphEdge, waypoints):
        """Positions possible graphNodes below the @graphEdge, using the
        information in @waypoints. May be overriden by subclasses"""
        return

class CreateClassAction( CreateAction ):
    def getIcon( cls ):
        return iconcache.getIcon("icons/classtb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = Class(name="NewClass_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "Class"
    
    def getDimension(self):
        return DI.Dimension(width=100, height=100)

class CreatePackageAction( CreateAction ):
    def getIcon( cls ):
        return iconcache.getIcon("icons/packagetb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = Package(name="NewPackage_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "Package"
    
    def getDimension(self):
        return DI.Dimension(width=250, height=200)

class CreateInterfaceAction( CreateAction ):
    def createModelElement( self, model, parent ):
        c = Interface(name="NewInterface_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getIcon( cls ):
        return iconcache.getIcon("icons/interfacetb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Interface"
    
    def getDimension(self):
        return DI.Dimension(width=100, height=100)

class CreateAssociationAction( CreateEdgeAction ):
    def firstType(self):
        return L.Classifier

    def secondType(self):
        return L.Classifier

    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[2].position = DISUPP.calcGENameDIPoints(waypoints)
        de0p = graphEdge.contained[0]
        de1p = graphEdge.contained[1]
        wp1=waypoints[0]
        wp2=waypoints[-1]
        de0p.position.x, de0p.position.y = wp1.x, wp1.y
        de1p.position.x, de1p.position.y = wp2.x, wp2.y

    def createModelElement(self, model, parent, ge1, ge2):
        ass = Association(name="NewAssociation_%d"%perpetualEnumerator())
        assend1 = AssociationEnd(association=ass, participant = ge1.semanticModel.element, isNavigable="true")
        assend2 = AssociationEnd(association=ass, participant = ge2.semanticModel.element, isNavigable="true")
        ass.connection.append(assend1)
        ass.connection.append(assend2)
        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(ass)
        return ass

    def getLabel(self):
        return "Association"
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/associationtb","UML14")
    getIcon = classmethod(getIcon)

        
class CreateGeneralizationAction( CreateEdgeAction ):
    def firstType(self):
        return L.GeneralizableElement

    def secondType(self):
        return L.GeneralizableElement

    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[0].position = DISUPP.calcGENameDIPoints(waypoints)

    def createModelElement(self, model, parent, ge1, ge2):
        me1 = ge1.semanticModel.element
        me2 = ge2.semanticModel.element

        if me1 == me2:
            # Don't allow self-inheritance
            # We can't prevent it totally, but this is one way less to do it
            logger.debug("Attempt to make illegal self inheritance")
            return

        gen = Generalization(name="NewGeneralization_%d"%perpetualEnumerator())
        gen.child = me1
        gen.parent = me2

        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(gen)
        return gen

    def getLabel(self):
        return "Generalization"
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/generalizationtb","UML14")
    getIcon = classmethod(getIcon)



class CreateDependencyAction( CreateEdgeAction ):
    def firstType(self):
        return L.ModelElement

    def secondType(self):
        return L.ModelElement

    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[0].position = DISUPP.calcGENameDIPoints(waypoints)

    def createModelElement(self, model, parent, ge1, ge2):
        dep = Dependency(name="NewDependency_%d"%perpetualEnumerator())
        dep.client.append(ge1.semanticModel.element)
        dep.supplier.append(ge2.semanticModel.element)
        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(dep)
        return dep

    def getLabel(self):
        return "Dependency"
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/dependencytb","UML14")
    getIcon = classmethod(getIcon)

class CreateCommentLinkAction( CreateAction ):
    def doIt(  self, diagram, parent, hints=None, parentge=None ):
        if hints and len(hints)==3:
            model = diagram.owner.element
            assert model
        node1 = hints[0]
        node2 = hints[1]
        waypoints = hints[2]
        waypoints2 = []
        if ((node1.semanticModel and node1.semanticModel.element) and
            (node2.semanticModel and node2.semanticModel.element)):
            me1 = node1.semanticModel.element
            me2 = node2.semanticModel.element
            if not (me1.oclIsKindOf(Comment) ^ me2.oclIsKindOf(Comment)):
                logger.debug("Attempt to make illegal comment link")
                return
        else:
            logger.debug("Attempt to make illegal comment link")
            return

        if me1.oclIsKindOf(Comment):
            me2.comment.append(me1)
        else:
            me1.comment.append(me2) 

        coral.getTransactionManager().beginModifyCmd()
        try:
            di_parent = DISUPP.getCommonParent(node1, node2)
            for wp in waypoints:
                ps_x, ps_y = coral.XMIDI_GlobalToLocalPosition(di_parent, wp.x, wp.y)
                waypoints2.append(DI.Point(x=ps_x, y=ps_y))            
            de = DiagramElementCreatorExt().createSimpleGraphEdge("CommentLink", waypoints=waypoints2)
            if de:
                anchor0 = DI.GraphConnector(graphElement=node1, position=DI.Point())
                anchor1 = DI.GraphConnector(graphElement=node2, position=DI.Point())
                de.anchor.append(anchor0)
                de.anchor.append(anchor1)
                de.container = di_parent
        finally:
            coral.getTransactionManager().endModifyCmd()

    def getLabel(self):
        return "Comment Link"
        

    def createModelElement( self, model, parent ):
        pass

    def getIcon( cls ):
        return iconcache.getIcon("icons/commentlinktb","UML14")
    getIcon = classmethod(getIcon)

    def createEdgeOrNot(self):
        return True


class CreateActorAction( CreateAction ):

    def createModelElement( self, model, parent ):
        a = Actor(name="NewActor_%d"%perpetualEnumerator())
        model.ownedElement.insert(a)
        return a

    def getIcon( cls ):
        return iconcache.getIcon("icons/actortb","UML14")
    getIcon = classmethod(getIcon)


    def getLabel(self):
        return "Actor"
    
    def getDimension(self):
        return DI.Dimension(width=70, height=120)


class CreateSubsystemAction( CreateAction ):

    def getIcon( cls ):
        return iconcache.getIcon("icons/subsystemtb","UML14")
    getIcon = classmethod(getIcon)


    def getLabel(self):
        return "Subsystem"
    

class CreateComponentAction( CreateAction ):

    def createModelElement( self, model, parent ):
        c = Component(name="NewComponent_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/componenttb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Component"
    
    def getDimension(self):
        return DI.Dimension(width=100, height=100)

class CreateCommentAction( CreateAction ):

    def createModelElement( self, model, parent ):
        c = L.Comment(name="NewComment_%d"%perpetualEnumerator())
        from coral import configuration
        import time
        user = configuration.getUserName()
        gmt = time.gmtime()
        c.body.__setString__(
            "\nComment made by %s on %d-%02d-%02d at %02d:%02d:%02d (UTC)"
            % (user, gmt[0], gmt[1], gmt[2],
               gmt[3], gmt[4], gmt[5]))
        # Don't set .comment for model, because
        # that's not really what we want. When the user places
        # a CommentLink, we know what to connect
        
        # Add the comment to the first .ownedElement we can
        while not model.__type__().getPropertyByName("ownedElement"):
            model = model.__parent__()
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "Comment"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/commenttb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=100, height=100)


##=========================================
##=========================================
##=========State=Diagrams==================
##=========================================
##=========================================
class CreateStateAction( CreateAction ):
    def doIt( self, diagram, parent, hints=None, parentge=None ):
        if hints:
            hint1 = hints[0]
            if hint1:
                px = hint1[0]
                py = hint1[1]
            else:
                px = 50
                py = 50

        if parentge and parentge.semanticModel.element.oclIsKindOf(CompositeState):
            model = parentge.semanticModel.element
        else:
            model = diagram.owner.element        

        assert model
        
        coral.getTransactionManager().beginModifyCmd()
        try:
            element = self.createModelElement(model,parent)
            if not element:
                return
            deg = DiagramElementGenerator.getExtension(element.__type__())
            if not deg:
                return
            
            if model.oclIsKindOf(StateMachine):
                de = deg.createDiagramElement(element, xparent=parent, size=self.getDimension())
                if not de:
                    return
                de.position = DI.Point(x=px,y=py)
                parent.contained.append(de)
            else:
                ssc = None
                for cmp in parentge.contained:
                    if not cmp.semanticModel.oclIsKindOf(DI.Uml1SemanticModelBridge) and str(cmp.semanticModel.typeInfo) == "SubStateCompartment":
                        ssc = cmp
                        break
                if ssc:
                    _x,_y = DISUPP.globalToLocalPosition(ssc, px, py)
                    de = deg.createDiagramElement(element, xparent=ssc, size=self.getDimension())
                    if not de:
                        return
                    de.position = DI.Point(x=_x, y=_y)
                    ssc.contained.append(de)
                elif not ssc and model.oclIsKindOf(CompositeState):
                    _x,_y = DISUPP.globalToLocalPosition(parentge, px, py)
                    de = deg.createDiagramElement(element, xparent=parentge, size=self.getDimension())
                    if not de:
                        return
                    de.position = DI.Point(x=_x, y=_y)
                    parentge.contained.append(de)
        finally:
            coral.getTransactionManager().endModifyCmd()



class CreateSimpleStateAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = SimpleState(name="NewSimpleState_%d"%perpetualEnumerator())
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "SimpleState"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/statetb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=100, height=100)


class CreateCompositeStateAction( CreateStateAction ):
    def createModelElement( self, model, parent ):
        c = CompositeState(name="NewCompositeState_%d"%perpetualEnumerator())
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "CompositeState"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/compstatetb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=100, height=100)


class CreateConcurrentStateAction( CreateStateAction ):
    def createModelElement( self, model, parent ):
        c = CompositeState(name="NewConcurrentState_%d"%perpetualEnumerator(), isConcurrent=True)
        is1 =CompositeState(name="Region_1", container=c)
        is2 =CompositeState(name="Region_2", container=c)
        c.subvertex.insert(is1)
        c.subvertex.insert(is2)
        
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "Concurrent CompositeState"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/cncstatetb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=100, height=150)


class CreateSynchStateAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = SynchState(name="NewSynchState_%d"%perpetualEnumerator())
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/synchtb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=20, height=20)

    def getLabel(self):
        return "SynchState"
    

class CreateFinalStateAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = FinalState(name="NewFinalState_%d"%perpetualEnumerator())
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/finalstatetb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=20, height=20)

    def getLabel(self):
        return "FinalState"
    

class CreateTransitionAction( CreateEdgeAction ):
    def firstType(self):
        return L.StateVertex

    def secondType(self):
        return L.StateVertex

    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[1].position = DISUPP.calcGENameDIPoints(waypoints)

    def createModelElement( self, model, parent, ge1, ge2 ):
        c = Transition(name="NewTransition_%d"%perpetualEnumerator())
        c.source = ge1.semanticModel.element
        c.target = ge2.semanticModel.element
        model.transitions.insert(c)
        return c

    def getLabel(self):
        return "Transition"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/transitiontb","UML14")
    getIcon = classmethod(getIcon)

class CreateForkAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewFork_%d"%perpetualEnumerator(), kind="fork")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "Fork"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/forktb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=50, height=10)

class CreateInitialStateAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewInitialState_%d"%perpetualEnumerator(), kind="initial")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/initialstatetb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Initial State"
    
    def getDimension(self):
        return DI.Dimension(width=20, height=20)
    
class CreateJoinAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewJoin_%d"%perpetualEnumerator(), kind="join")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/jointb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Join"
    
    def getDimension(self):
        return DI.Dimension(width=50, height=10)

class CreateJunctionAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewJunction_%d"%perpetualEnumerator(), kind="junction")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "Junction"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/junctiontb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=20, height=20)


class CreateChoiceAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewChoice_%d"%perpetualEnumerator(), kind="choice")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/choicetb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Choice"
    
    def getDimension(self):
        return DI.Dimension(width=20, height=20)

class CreateDeepHistoryAction( CreateStateAction ):

    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewDeepHistory_%d"%perpetualEnumerator(), kind="deepHistory")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/deephistorytb","UML14")
    getIcon = classmethod(getIcon)

    def getLabel(self):
        return "Deep History"
    
    def getDimension(self):
        return DI.Dimension(width=20, height=20)


class CreateShallowHistoryAction( CreateStateAction ):

    
    def createModelElement( self, model, parent ):
        c = Pseudostate(name="NewShallowHistory_%d"%perpetualEnumerator(), kind="shallowHistory")
        if model.oclIsKindOf(StateMachine):
            model.top.subvertex.insert(c)
        elif model.oclIsKindOf(CompositeState):
            model.subvertex.insert(c)
        return c

    def getLabel(self):
        return "Shallow History"
        
    def getIcon( cls ):
        return iconcache.getIcon("icons/historytb","UML14")
    getIcon = classmethod(getIcon)

    def getDimension(self):
        return DI.Dimension(width=20, height=20)

## Object Diagrams and Collaboration Diagrams


class CreateObjectAction( CreateAction ):

    def getIcon( cls ):
        return iconcache.getIcon("icons/objecttb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = Object(name="NewObject_%d"%perpetualEnumerator())

        if model.oclIsKindOf(CollaborationInstanceSet):
            model.collaboration.ownedElement.insert(c)
            model.participatingInstance.insert(c)
        else:
            model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "Object"
    
    def getDimension(self):
        return DI.Dimension(width=120, height=80)


class CreateLinkAction( CreateEdgeAction ):
    def firstType(self):
        return L.Instance

    def secondType(self):
        return L.Instance

    def createModelElement(self, model, parent, ge1, ge2):
         lnk = Link(name="NewLink_%d"%perpetualEnumerator())
         lnkend1 = LinkEnd(link=lnk, instance = ge1.semanticModel.element)
         lnkend2 = LinkEnd(link=lnk, instance = ge2.semanticModel.element)
         lnk.connection.append(lnkend1)
         lnk.connection.append(lnkend2)
         lnk.owner_at_Link = ge1.semanticModel.element
         if model.oclIsKindOf(CollaborationInstanceSet):
             model.participatingLink.insert(lnk)
         return lnk

    def getLabel(self):
        return "Link"
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/linktb","UML14")
    getIcon = classmethod(getIcon)

# Deployment and Component Diagrams

class CreateNodeAction( CreateAction ):

    def getIcon( cls ):
        return iconcache.getIcon("icons/nodetb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = Node(name="NewNode_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getDimension(self):
        return DI.Dimension(width=120, height=120)

    def getLabel(self):
        return "Node"
    

class CreateNodeInstanceAction( CreateAction ):

    def getIcon( cls ):
        return iconcache.getIcon("icons/nodeinstancetb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = NodeInstance(name="NewNodeInstance_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getDimension(self):
        return DI.Dimension(width=120, height=120)

    def getLabel(self):
        return "NodeInstance"
    
class CreateComponentInstanceAction( CreateAction ):

    def getIcon( cls ):
        return iconcache.getIcon("icons/componentinstancetb","UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = ComponentInstance(name="NewComponentInstance_%d"%perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "ComponentInstance"
    
    def getDimension(self):
        return DI.Dimension(width=120, height=120)

class CreateAbstractionAction( CreateEdgeAction ):
    def firstType(self):
        return L.ModelElement

    def secondType(self):
        return L.ModelElement

    def createModelElement(self, model, parent, ge1, ge2):
        abs = Abstraction(name="NewAbstraction_%d"%perpetualEnumerator())
        abs.client.append(ge1.semanticModel.element)
        abs.supplier.append(ge2.semanticModel.element)
        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(abs)
        return abs

    def getLabel(self):
        return "Abstraction"
    
    def getIcon( cls ):
        return iconcache.getIcon("icons/abstractiontb","UML14")
    getIcon = classmethod(getIcon)

    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[0].position = DISUPP.calcGENameDIPoints(waypoints)


#
#
# USE CASE DIAGRAMS
#
#

class CreateUseCaseAction(CreateAction):
    def getIcon( cls ):
        return iconcache.getIcon("icons/usecasetb", "UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = L.UseCase(name="New Use Case %d" % perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "UseCase"
    
    def getDimension(self):
        return DI.Dimension(width=120, height=80)

class CreateCollaborationAction(CreateAction):
    def getIcon( cls ):
        return iconcache.getIcon("icons/collaborationtb", "UML14")
    getIcon = classmethod(getIcon)

    def createModelElement( self, model, parent ):
        c = L.Collaboration(name="New Collaboration %d" % perpetualEnumerator())
        model.ownedElement.insert(c)
        return c

    def getLabel(self):
        return "Collaboration"
    
    def getDimension(self):
        return DI.Dimension(width=120, height=80)

class CreateExtendAction( CreateEdgeAction ):
    def firstType(self):
        return L.UseCase

    def secondType(self):
        return L.UseCase

    def createModelElement(self, model, parent, ge1, ge2):
        extend = L.Extend(name="Extend %d"%perpetualEnumerator())
        extend.base = ge1.semanticModel.element
        extend.extension = ge2.semanticModel.element
        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(extend)         
        return extend

    def getLabel(self):
        return "Extend"
    
    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[0].position = DISUPP.calcGENameDIPoints(waypoints)

    def getIcon( cls ):
        return iconcache.getIcon("icons/extendtb","UML14")
    getIcon = classmethod(getIcon)

class CreateIncludeAction( CreateEdgeAction ):
    def firstType(self):
        return L.UseCase

    def secondType(self):
        return L.UseCase

    def createModelElement(self, model, parent, ge1, ge2):
        include = L.Include(name="Include %d" % perpetualEnumerator())
        include.base = ge1.semanticModel.element
        include.addition = ge2.semanticModel.element
        abs_parent = DISUPP.getCommonParent(ge1.semanticModel.element, ge2.semanticModel.element)
        if not abs_parent:
            di_parent = DISUPP.getCommonParent(ge1, ge2)
            abs_parent = DISUPP.findUpwardsModelElement(di_parent)
        abs_parent.ownedElement.add(include)         
        return include

    def getLabel(self):
        return "Include"
    
    def positionEdgeLabels(self, graphEdge, waypoints):
        graphEdge.contained[0].position = DISUPP.calcGENameDIPoints(waypoints)

    def getIcon( cls ):
        return iconcache.getIcon("icons/includetb","UML14")
    getIcon = classmethod(getIcon)
