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

from qt import *
import math
import coral
coral.lang.UML14.__import__(globals())
L = coral.lang.UML14
DI = coral.lang.XMIDI20
from coral.modeler.diagram.presentation import *

from coral.modeler.diagram import presentation

from util import *

import coral.modeler.diagram.di_support as DISUPP
import coral.modeler.diagram.di_support_gfx as DISUPPGFX

class ActorGER(DiagramElementRenderer):

    def drawShape( self, painter ):

        if self.ge.semanticModel and self.ge.semanticModel.presentation == "Classifier":
            # Draw it as a classifier
            painter.drawRect(0,0,self.widget.width(),self.widget.height())
        else:

            w = h = min(self.widget.width(),self.widget.height())
            x,y = (self.widget.width()-w)/2,(self.widget.height()-h)/2
            actor_width = max(10,w-10)


            painter.drawEllipse(x+w/2-actor_width/4+1,y+2,actor_width/2,h/3)
            painter.drawLine(x+w/2,y+2+h/3,x+w/2,y+2*h/3)#body
            painter.drawLine(x+w/2-actor_width/2,y+h/2,x+w/2+actor_width/2,y+h/2)#arms
            painter.drawLine(x+w/2,y+2*h/3,x+w/2-actor_width/2,y+h-2)#left leg
            painter.drawLine(x+w/2,y+2*h/3,x+w/2+actor_width/2,y+h-2)#right leg


class UseCaseGER(DiagramElementRenderer):
    def drawShape( self, painter ):
	painter.drawEllipse(0, 0,
			    self.widget.width(),self.widget.height())
		

        
class PackageGED(DiagramElementRenderer):

    def drawShape( self, painter ):

        if self.isref:
            return
        
        # Draw the "handle" on the package
        handleGE = DISUPP.findSimpleElementOfType(self.ge,"NameCompartment")[0]
        if handleGE:
             painter.drawRect(QRect(int(handleGE.position.x),
                                    int(handleGE.position.y),
                                    int(handleGE.size.width),
                                    int(handleGE.size.height)))

        # Draw the box container
        bodyGE = DISUPP.findSimpleElementOfType(self.ge,"BodyCompartment")[0]
        if bodyGE:
            painter.drawRect(QRect(int(bodyGE.position.x),
                                   int(bodyGE.position.y),
                                   int(bodyGE.size.width),
                                   int(bodyGE.size.height)))

class ClassGED(DiagramElementRenderer):
    
    def drawShape( self, painter ):

        modelcontainer = DISUPP.findUpwardsModelElement(self.ge.container)
        # Only draw class box in these special cases:
        if (not modelcontainer
            or modelcontainer.oclIsKindOf(Package)
            or modelcontainer.oclIsKindOf(Component)):

            painter.drawRect(0,0,self.widget.width(),self.widget.height())
            tmpstr = ""
            p = self.ge.semanticModel.element.templateParameter
            
            if p:
                tmpstr = ", ".join([str(t.parameter.name) for t in p])
                DISUPPGFX.setPenStyle(painter, Qt.DashLine)
                f = painter.fontMetrics()
                h = f.height() + 3
                painter.drawRect(3,3, f.width(tmpstr)+6, h)
                painter.drawText(6, h, tmpstr)

	    
class BoxGER(DiagramElementRenderer):
    def drawShape( self, painter ):
        painter.drawRect(0,0,self.widget.width(),self.widget.height())


class StereotypeGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        cnt = self.ge.container
        if cnt and cnt.semanticModel and cnt.semanticModel.oclIsKindOf(DI.SimpleSemanticModelElement) and cnt.semanticModel.typeInfo=="StereotypeCompartment":
            pass ## Make up these cases later
        else:
            painter.drawRect(0,0,self.widget.width(),self.widget.height())


class StateGER(DiagramElementRenderer):

    def drawShape( self, painter ):

        cnt = self.ge.container
        hasRgnCmp =  cnt and cnt.semanticModel and cnt.semanticModel.oclIsKindOf(DI.SimpleSemanticModelElement) and cnt.semanticModel.typeInfo=="RegionCompartment"
        if self.element.container and not self.element.container.isConcurrent and not hasRgnCmp:
            rness = 15 # Set the roundness in pixel here
            w = self.widget.width()
            h = self.widget.height()
            if w and h:
                painter.drawRoundRect(0, 0, w, h, (100.0*rness)/w,(100.0*rness)/h)
            else:
                painter.drawRoundRect(0, 0, w, h, 5, 5)

class RelationGER(DiagramElementRenderer):

    # This is the base class for relationship renderers: Association,
    # Generalization, Dependency and Realization

    ARROWHEAD_ANGLE = math.radians(20.0)
    ARROWHEAD_LENGTH = 12.0
    ARROWHEAD_PROJ = ARROWHEAD_LENGTH*math.cos(ARROWHEAD_ANGLE)
    ARROWHEAD_RISE = ARROWHEAD_LENGTH*math.sin(ARROWHEAD_ANGLE)

    DIAMOND_SIDE_LENGTH = 11.0
    DIAMOND_STRUT = (DIAMOND_SIDE_LENGTH**2/2.0)**0.5

    def _drawArrow(self,painter,s):
        self._preparePainter(painter)
        painter.drawLine(0,0,0+s*self.ARROWHEAD_PROJ,0+self.ARROWHEAD_RISE)
        # The -PEN_THICKNESS makes the arrow look good in e.g. Postscript.
        # Weird but true.
        painter.drawLine(0,
                         -presentation.PEN_THICKNESS,
                         0 + s*self.ARROWHEAD_PROJ,
                         -presentation.PEN_THICKNESS - self.ARROWHEAD_RISE)

    def _drawDiamond(self,painter,fillDiamond,isBeginConnector):
	"""_drawDiamond draws a Diamond on the AssociationEnd which can represent an Composition(black diamond) or an Aggregation(white diamond) 
           fillDiamond=0(white diamond),fillDiamond=1(black diamond),isBeginConnector=1(beginConnector),isBeginConnector=0(endConnector)
        """
        if not fillDiamond:
            painter.setBrush(Qt.white)
        else:
            painter.setBrush(Qt.black)
        
        if isBeginConnector:
            k = 1
        else:
            k = -1

        diamond = QPointArray([0,0,
                               0+k*self.DIAMOND_STRUT,self.DIAMOND_STRUT,
                               # The -k makes stuff look better. Weird but
                               # true...
                               0+k*2.0*self.DIAMOND_STRUT - k, 0,
                               0+k*self.DIAMOND_STRUT,-self.DIAMOND_STRUT])
        painter.drawPolygon(diamond)

class CommentLinkSGER( RelationGER ):
    def _preparePainter(self,painter):
        RelationGER._preparePainter(self,painter)
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)
            
class AssociationGER(RelationGER):
    def drawBeginConnector(self,painter):
        RelationGER.drawBeginConnector(self,painter)
        
        associationEnd=self.element
        agg = associationEnd.connection[0].aggregation
        if agg == AggregationKind.ak_composite: 
            self._drawDiamond(painter,1,1)
        elif agg == AggregationKind.ak_aggregate:
            self._drawDiamond(painter,0,1)
        elif not associationEnd.connection[1].isNavigable and associationEnd.connection[0].isNavigable:
	    self._drawArrow(painter,1)            
        

    def drawEndConnector(self,painter):
        RelationGER.drawEndConnector(self,painter)

        associationEnd=self.element
        agg = associationEnd.connection[1].aggregation
        if agg ==AggregationKind.ak_composite: 
	    self._drawDiamond(painter,1,0)
        elif agg == AggregationKind.ak_aggregate:
            self._drawDiamond(painter,0,0)    
        elif not associationEnd.connection[0].isNavigable and associationEnd.connection[1].isNavigable:
	    self._drawArrow(painter,-1)

            
class LinkGER(RelationGER):
    #
    # Our Links between objects are drawn in a special way.
    # They show composition/aggregation just like associations, which
    # is not according to common UML usage. But then again, who cares,
    # this makes object diagrams actually easier to read. And if you don't
    # care about composition/aggregation in object diagrams, why do you care
    # about them in the class diagram?-)
    #
    # Note that Links should be nice and directed in SequenceDiagrams, but
    # follow the corresponding Association in Object/Deployment Diagrams
    #
    def drawBeginConnector(self,painter):
        RelationGER.drawBeginConnector(self,painter)
        
        try:
            conn = self.element.connection[0]
            associationEnd0 = conn.associationEnd # DeploymentDiagrams
            if associationEnd0:
                agg = associationEnd0.aggregation
                if agg == AggregationKind.ak_composite: 
                    self._drawDiamond(painter,1,1)
                elif agg == AggregationKind.ak_aggregate:
                    self._drawDiamond(painter,0,1)
                else:
                    associationEnd1=self.element.connection[1].associationEnd
                    if not associationEnd1.isNavigable and associationEnd0.isNavigable:
                        self._drawArrow(painter,1)

        except AttributeError:
            # BUG rmeove this try..catch?
            pass
        

    def drawEndConnector(self,painter):
        RelationGER.drawEndConnector(self,painter)

        try:
            conn = self.element.connection[1]
            associationEnd1 = conn.associationEnd # DeploymentDiagrams
            if associationEnd1:
                agg = associationEnd1.aggregation
                if agg ==AggregationKind.ak_composite: 
                    self._drawDiamond(painter,1,0)
                elif agg == AggregationKind.ak_aggregate:
                    self._drawDiamond(painter,0,0)    
                else:
                    associationEnd0=self.element.connection[0].associationEnd
                    if not associationEnd0.isNavigable and associationEnd1.isNavigable:
                        self._drawArrow(painter,-1)
            else:
                inst = conn.instance # SequenceDiagrams
                if inst:
                    rs = self.graphElement.__getRoot__().semanticModel
                    if rs and hasattr(rs, "typeInfo") and str(rs.typeInfo) in ["DeploymentDiagram","CollaborationDiagram"]:
                        pass ## BUG Come up later with better
                    else:
                        self._drawArrow(painter,-1)
        except AttributeError:
            # BUG rmeove this try..catch?
            pass

            
class TransitionGER(RelationGER):

    def drawBeginConnector(self,painter):
        RelationGER.drawBeginConnector(self,painter)

    def drawEndConnector(self,painter):
        RelationGER.drawEndConnector(self,painter)
        self._drawArrow(painter,-1)
        

class DependencyGER( RelationGER ):

    def _preparePainter( self, painter ):
        RelationGER._preparePainter(self,painter)
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)

    def drawEndConnector( self, painter ):
        RelationGER.drawEndConnector(self,painter)
        self._drawArrow(painter,-1)



class GeneralizationGER( RelationGER ):

    GEN_ARROWHEAD_ANGLE = math.radians(25.0)
    GEN_ARROWHEAD_LENGTH = 15.0
    GEN_ARROWHEAD_PROJ = GEN_ARROWHEAD_LENGTH*math.cos(GEN_ARROWHEAD_ANGLE)
    GEN_ARROWHEAD_RISE = GEN_ARROWHEAD_LENGTH*math.sin(GEN_ARROWHEAD_ANGLE)

    def drawEndConnector( self, painter ):
        painter.setBrush(Qt.white)
        arrow = QPointArray([0,0,
                             0-self.GEN_ARROWHEAD_PROJ,0+self.GEN_ARROWHEAD_RISE,
                             0-self.GEN_ARROWHEAD_PROJ,0-self.GEN_ARROWHEAD_RISE])                             
        painter.drawPolygon(arrow)
        


class AbstractionGER( GeneralizationGER ):

    def _preparePainter( self, painter ):
        RelationGER._preparePainter(self,painter)
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)


class FinalStateGER(DiagramElementRenderer):
    
    def drawShape( self, painter ):
        DISUPPGFX.setPenColor(painter, Qt.black)
        painter.setBrush(Qt.white)

        w = self.widget.width()
        h = self.widget.height()
        painter.drawEllipse(0, 0, w, h)
        
        painter.setBrush(Qt.black)

        x = int(0.15 * w)
        y = int(0.15 * h)
        innerw = int(0.7 * w)
        innerh = int(0.7 * h)

        painter.drawEllipse(x,y,innerw, innerh)

class PseudostateGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        DISUPPGFX.setPenColor(painter, Qt.black)
        w = self.widget.width()
        h = self.widget.height()
        
        if (self.element.kind == "fork" or self.element.kind == "join"):
            painter.setBrush(Qt.black)
            painter.drawRect(0, 0, w, h)
        elif self.element.kind == "junction":
            e = self.element.container
            b = None
            while e:
                s = e.stateMachine
                if s:
                    if s.oclIsKindOf(ActivityGraph):
                        painter.setBrush(QBrush.SolidPattern)
                    break
                e = e.container

            painter.setBrush(Qt.black)
            diamond = QPointArray( [ int(w/2),0,
                                     w, int(h/2),
                                     int(w/2), h,
                                     0,int(w/2) ] )
            painter.drawPolygon(diamond)
        elif self.element.kind == "initial":
            painter.setBrush(Qt.black)
            painter.drawEllipse(0, 0, w, h)
        else:
            painter.setBrush(Qt.white)
            painter.drawEllipse(0, 0, w, h)
            if (self.element.kind == "deepHistory"):
                painter.drawText(0, 0, w, h, Qt.AlignCenter, "H*")
            elif (self.element.kind == "shallowHistory"):
                painter.drawText(0, 0, w, h, Qt.AlignCenter, "H")

class SynchStateGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        painter.setBrush(Qt.white)
        w = self.widget.width()
        h = self.widget.height()
        painter.drawEllipse(0, 0, w, h)
        mx = w/2
        my = h/2
        length = min(w, h) * 0.3
        for i in range(3):
            r = math.radians(i * 60)
            dy = math.cos(r) * length
            dx = math.sin(r) * length
            painter.drawLine(mx + dx, my + dy, mx - dx, my - dy)

class ObjectGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        d = DISUPP.findDiagramOfElement(self.ge)
        w = self.widget.width()
        h = self.widget.height()
        if d and d.semanticModel.typeInfo == "SequenceDiagram":
            painter.drawLine(w/2, 0, w/2, h)
            return
        painter.drawRect(0, 0, w, h)


class CommentGER(DiagramElementRenderer):

    def drawShape( self, painter ):

        w = self.widget.width()
        h = self.widget.height()
        mainpoly = QPointArray([0,0,
                                w-11,0,
                                w-1,11,
                                w-1,h-1,
                                0,h-1,
                                0,0])

        flippoly = QPointArray([w-11,0,
                                w-1,11,
                                w-11,11])

        painter.drawPolygon(mainpoly)
        painter.drawPolygon(flippoly)

        if self.element.body:
            txt = unicode(self.element.body)
            fontcolor = DISUPPGFX.getFontColor(self.ge)
            DISUPPGFX.setPenColor(painter, fontcolor)
            painter.drawText(10, 10,
                             w-10, h-10,
                             Qt.AlignLeft | Qt.WordBreak,
                             txt)
        


class ArrowGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        """Draws an arrow. The arrow direction is the same as the direction of the closest
        segment."""
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        gc = self.ge.container.container.anchor


        rcv = self.element.receiver
        snd = self.element.sender

        points = None
        if self.ge.container and self.ge.container.container and self.ge.container.container.oclIsKindOf(DI.GraphEdge):
            if len(self.ge.container.container.waypoints) >= 2:
                points = self.ge.container.container.waypoints
                segment = 0
                segments = xrange(0, len(points)-1)
                mindist = 1000
                for s in segments:
                    _,_,d = DISUPP.calcDistFromPoint2Line(points[s], points[s+1], self.ge.container.position)
                    if d != -1 and d < mindist:
                        mindist = d
                        segment = s

        if points and len(points) >= segment+1:
            # Arrow angle will adjust according to angle of closest segment
            point1 = points[segment]
            point2 = points[segment+1]
            x1,y1 = point1.x,point1.y
            x2,y2 = point2.x,point2.y
        else: # If no waypoints exist, use graphconnector positions
            point1 = gc[0].position
            point2 = gc[1].position
            
            x1,y1 = DISUPP.localToGlobalPosition(gc[0].graphElement, point1.x, point1.y )
            x2,y2 = DISUPP.localToGlobalPosition(gc[1].graphElement, point2.x, point2.y )
        
        if snd == gc[0].graphElement.semanticModel.element:
            angle = math.atan2(y2-y1, x2-x1)
        else:
            angle = math.atan2(y1-y2, x1-x2)
        
        painter.save()
        try:
            painter.translate(10,10)
            painter.rotate(math.degrees(angle))
            painter.translate(-10,-10)
            
            self.drawStimuliArrow(painter)
        
        finally:
            painter.restore()


    def drawStimuliArrow(self,painter):
        
        if self.element.dispatchAction and self.element.dispatchAction.oclIsKindOf(SendAction):
            painter.drawLine(0,10,20,10)
            painter.drawLine(14,5,20,10)
            painter.drawLine(14,15,20,10)
        elif self.element.dispatchAction and self.element.dispatchAction.oclIsKindOf(ReturnAction):
            painter.drawLine(14,5,20,10)
            painter.drawLine(14,15,20,10)
            DISUPPGFX.setPenStyle(painter, Qt.DotLine)
            painter.drawLine(0,10,20,10)
        else:
            arrowpts = QPointArray([12,5,
                                18,10,
                                12,15,
                                12,5])

            painter.setBrush(painter.pen().color())
            
            painter.drawPolygon(arrowpts)
            painter.drawLine(0,10,12,10)
        

class CollaborationGER(DiagramElementRenderer):
    
    def drawShape( self, painter ):
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)
        painter.drawEllipse(0,0,self.widget.width(),self.widget.height())

class ClassifierRoleGER(RelationGER):
    def _preparePainter( self, painter ):
        RelationGER._preparePainter(self,painter)
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)

class ActionStateGER(DiagramElementRenderer):
    def drawShape( self, painter ):
        name = unicode(self.element.name)
        w = self.widget.width()
        h = self.widget.height()
        if self.isref:
            t = ""
            if self.element.entry.script:
                t = unicode(self.element.entry.script.body)

            painter.drawText(0, 0, w, h, Qt.AlignCenter,"["+t+"]")
        else:
            rness = 25
            if w:
                painter.drawRoundRect(0, 0, w, h, (100*rness) / w, 99)

class Box3DGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        w = self.widget.width()
        h = self.widget.height()

        top3dr = QPointArray([20,0,
                              w-1,0,
                              w-21,20,
                              0,20,
                              20,0])
        right3dr = QPointArray([w-21, 20,
                                w-21, h,
                                w-1, h-20,
                                w-1, 0,
                                w-21, 20])

        painter.drawPolygon(top3dr)
        painter.drawPolygon(right3dr)
        painter.drawRect(0, 20, w-20, h-20)

class NodeGER(Box3DGER):
    
    def drawShape( self, painter ):
        Box3DGER.drawShape( self, painter )


class NodeInstanceGER(Box3DGER):
    
    def drawShape( self, painter ):
        Box3DGER.drawShape( self, painter )


class ComponentGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        painter.drawRect(15,0,self.widget.width()-15,self.widget.height())
        cystart = 20 # offset from top-left
        cwidth = 30  # width of one "notch" in the component
        cheight = 10 # height of one "notch"
        cseparation = 7 # separation between the two notches
        painter.drawRect(0, cystart, cwidth, cheight)
        painter.drawRect(0, cystart + cheight + cseparation, cwidth, cheight)

############################################################################


class SimpleDiagramElementGER( DiagramElementRenderer ):

    pass

class ActivationSGER( SimpleDiagramElementGER ):

    def drawShape( self, painter ):
        painter.drawRect(0,0,self.widget.width()-1,self.widget.height()-1)

class CompartmentSeparatorSGER( SimpleDiagramElementGER ):

    def drawShape( self, painter ):
        if self.widget.height()<=1:
            painter.drawLine(0,0,self.widget.width()-1,0)


class RegionSeparatorSGER( SimpleDiagramElementGER ):

    def drawShape( self, painter ):
        DISUPPGFX.setPenStyle(painter, Qt.DashLine)
        painter.drawLine(0, 0, self.widget.width()-1, 0)

        
class StringSGER( SimpleDiagramElementGER ):

    def getString( self ):
        return ""
    
    def getAlignmentFlags( self ):
        return Qt.AlignAuto|Qt.AlignVCenter

    def isItalic(self):
        return False
    
    def drawShape( self, painter ):
        oldsize = None
        v = DISUPP.get_XMIDI_Property_FontSize(self.ge)
        if v:
            oldsize = painter.font().pointSizeFloat()
            painter.font().setPointSizeFloat(v)

        oldfont = None
        if self.isItalic():
            oldfont = painter.font()
            f = QFont(oldfont)
            f.setItalic(True)
            painter.setFont(f)
        try:
            c = DISUPPGFX.getFontColor(self.ge)
            DISUPPGFX.setPenColor(painter, c)
            
            painter.drawText(0,0,self.widget.width(),self.widget.height(),
                             self.getAlignmentFlags(),self.getString())
        finally:
            if oldfont:
                painter.setFont(oldfont)
            if oldsize:
                painter.font().setPointSizeFloat(oldsize)

class NameAndTypeSGER( DiagramElementRenderer ):

    def drawShape( self, painter ):
        painter.drawLine(0,self.widget.height()-1,
                         self.widget.width()-1,self.widget.height()-1)

class KeywordMetaclassSGER( StringSGER ):

    def getString( self ):
        element = DISUPP.findUpwardsModelElement(self.ge)
        if element.oclIsKindOf(L.Interface):
            return "interface"
        return "component" # We'll do this for now, low-priority
        
class CommaSGER( StringSGER ):
    def getString( self ):
        return ", "

class ExpressionSGER( StringSGER ):
    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element and self.element.oclIsKindOf(CallAction):
            if self.element.script:
                return unicode(self.element.script.body)
        elif self.element and self.element.oclIsKindOf(Guard):
            if self.element.expression:
                return unicode(self.element.expression.body)
        elif self.element and self.element.oclIsKindOf(Constraint):
            if self.element.body:
                return unicode(self.element.body.body)    
        else:
            if self.element and hasattr(self.element, "body") and self.element.body:
                return unicode(self.element.body)

        return ""

class InitialValueSeparatorSGER( StringSGER ):
    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element and self.element.initialValue and self.element.initialValue.body:
            return "="
        else:
            return ""
        

class InitialValueSGER( StringSGER ):
    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element and self.element.initialValue:
            return unicode(self.element.initialValue.body)
        else:
            return ""

class StereotypeStartSGER( StringSGER ):
    def getString( self ):
        return u" \xab"


class StereotypeEndSGER( StringSGER ):
    def getString( self ):
        return u"\xbb "


class ParameterStartSGER( StringSGER ):
    def getString( self ):
        return "("


class ParameterEndSGER( StringSGER ):
    def getString( self ):
        return ")"

class EffectStartSGER( StringSGER ):
    def getString( self ):
        return "/"

class ArgumentSGER( StringSGER ):
    def getString( self ):
        
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)

        if self.element and self.element.value:
            txt = unicode(self.element.value.body)
        else:
            txt = ""
        return txt

class AssignmentSGER( StringSGER ):
    def getString( self ):
        return ":="

class LabelSGER( StringSGER ):
    def getString( self ):
        t = ""
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if not self.element:
            return t
        e = self.element
        if e.oclIsKindOf(CallAction):
            if e.state and e.state.entry is e:
                t = "entry"
            elif e.stateDoActivity and e.stateDoActivity.doActivity is e:
                t = "do"
            elif e.stateExit and e.stateExit.exit is e:
                t = "exit"
        elif e.oclIsKindOf(UseCase) and e.extensionPoint:
            t = "Extension Point"

        return t


class ExpressionStartSGER( StringSGER ):
    def getString( self ):
        return " {"

class ExpressionEndSGER( StringSGER ):
    def getString( self ):
        return "} "

class NamespaceStartSGER( StringSGER ):
    def getString( self ):
        return "(from "

class NamespaceEndSGER( StringSGER ):
    def getString( self ):
        return ")"
    
class TypeSeparatorSGER( StringSGER ):
    def getString( self ):
        return ": "

class NameLocationSeparatorSGER( StringSGER ):
    def getString( self ):
        return "."

class MultiplicityStartSGER( StringSGER ):
    def getString( self ):
        return "["

class MultiplicityEndSGER( StringSGER ):
    def getString( self ):
        return "]"


class NameSGER( StringSGER ):
    def isItalic(self):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element and self.element.oclIsKindOf(L.Class) and self.element.isAbstract:
            return True
        return False

    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element:
            return unicode(self.element.name)
        else:
            return ""

    def drawShape(self, painter):
        StringSGER.drawShape(self, painter)
        if not self.element:
            return
        if not self.element.oclIsKindOf(L.AssociationEnd):
            return
        if self.element.targetScope != "classifier":
            return
        h = self.widget.height()-2
        painter.drawLine(0, h, self.widget.width(), h)
                

class OrderingSGER(StringSGER):
    def getString(self):
        return "ordered"

class LocationSGER( StringSGER ):

    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element:
            return unicode(self.element.location)
        else:
            return ""

class DiscriminatorSGER( StringSGER ):
    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element:
            return unicode(self.element.discriminator)
        else:
            return ""

class VisibilitySGER( StringSGER ):

    viskind= { "public": "+",
               "protected": "#",
               "private": " -", # Better alignment than "-"
               "package": "~" }
    
    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        return self.__class__.viskind[unicode(self.element.visibility)]



class MultiplicitySGER( StringSGER ):

    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        return fromMultiplicityToString(self.element.multiplicity)
