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

from qt import *
import math
import coral
L = coral.lang.DIML10
SMD = coral.lang.SMD01
DI = coral.lang.XMIDI20
from coral.modeler.diagram.presentation import DiagramElementRenderer, PEN_THICKNESS
import coral.modeler.diagram.di_support as DISUPP
import coral.modeler.diagram.di_support_gfx as DISUPPGFX

class EmptyGER(DiagramElementRenderer):

    def drawShape( self, painter ):
        pass

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

class RoundedBoxGER(DiagramElementRenderer):
    def drawShape( self, painter ):
        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,
                         -PEN_THICKNESS,
                         0 + s*self.ARROWHEAD_PROJ,
                         -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 ContainedGER( RelationGER ):

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

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

class MappingGER( RelationGER ):

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

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

class SeparatorGER( 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 StringSGER( DiagramElementRenderer ):

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

    def drawShape( self, painter ):
        painter.setPen(DISUPPGFX.getFontColor(self.ge))
	painter.drawText(0,0,self.widget.width(),self.widget.height(),
                         self.getAlignmentFlags(),self.getString())

class TypeInfoSGER( StringSGER ):

    def getString( self ):
        if not self.element:
            self.element = DISUPP.findUpwardsModelElement(self.ge)
        if self.element and self.element.typeInfo:
            return "typeInfo: "+unicode(self.element.typeInfo)
        else:
            return ""
        
class GuardGER( StringSGER ):

    def getString( self ):
        if self.element:
            return " [ "+unicode(self.element.expression)+" ] "
        else:
            return ""

class ConnectorGER( StringSGER ):

    def getString( self ):
        container_element = DISUPP.findUpwardsModelElement(self.ge.container)
        if container_element and container_element.oclIsKindOf(L.GraphNodePart):
            if self.element:
                return "proxyConnector: {self."+unicode(self.element.nextProperty.name)+"}"
            else:
                return ""
        else:
            if self.element:
                conn = ""
                if self.element.property:
                    conn += "property: {self."+unicode(self.element.property.name)+"}"
                if self.element.nextProperty:
                    conn += "\nnextProperty: "+unicode(self.element.nextProperty.name)
                return conn
            else:
                return ""            

class ClassificationGER( StringSGER ):

    def getAlignmentFlags( self ):
        return Qt.AlignCenter|Qt.AlignVCenter

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

class SelectionGER( StringSGER ):

    def getString( self ):
        sel = ""
        el = self.element
        if el:
            if el.property:
                sel += "self."+unicode(el.property.name)
            if el.type or (el.parameterValue and el.parameterType and el.operation):
                if el.type and not (el.parameterValue and el.parameterType and el.operation):
                    sel += "->select(x | x.oclIsKindOf("+unicode(el.type.name)+"))"
                elif el.type and (el.parameterValue and el.parameterType and el.operation):
                    sel += "->select(x | x.oclIsKindOf("+unicode(el.type.name)+") and x."+unicode(el.parameterType.name)+" "+unicode(el.operation)+" "+unicode(el.parameterValue)+")"
            return sel
        else:
            return ""


class ConnectorStartGER( StringSGER ):

    def getString( self ):
        return " {"

class ConnectorEndGER( StringSGER ):

    def getString( self ):
        return "} "

class ConnectorSeparatorGER( StringSGER ):

    def getString( self ):
        return ", "
