Logo Search packages:      
Sourcecode: kayali version File versions  Download package

nodesubclasses.py

#***************************************************************************
# *   Copyright (C) 2003-2006 by A Lynch                                    *
# *   aalynch@users.sourceforge.net                                         *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License version 2 as published by  *
# *   the Free Software Foundation;                                         *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU General Public License for more details.                          *
# *                                                                         *
# *   You should have received a copy of the GNU General Public License     *
# *   along with this program; if not, write to the                         *
# *   Free Software Foundation, Inc.,                                       *
# *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
# ***************************************************************************/

import copy
import constants
import node as nodemodule
from maximaparsertokens import tokenValues
from configuration import config

import logging
l = logging.getLogger(__name__)


class BRACKETNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        # brackets could have multiple nodes if the input expression had commas in it

        self.w = 0
        nodeNum = 0
        for node in self.nodes:
            if nodeNum > 0:
                self.w += self.spacewidth
            self.w += node.w
            nodeNum += 1

        h, operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
        self.scaledBracketWidth = nodemodule.getScaledBracketWidth(self.spacewidth, h)

        if h <= self.Xheight+2:
            self.w += self.bracketwidth * 2 + self.thirdspacewidth*2
            self.h = h #self.Xheight
            self.bracketSpacing = 0
            self.noScale = True
        else:            
            self.w += self.scaledBracketWidth * 2 + self.thirdspacewidth*2
            self.h = h * ( 1 + config["bracketincreaseratio"])
            self.bracketSpacing = (self.h - h)/2.0
            self.noScale = False

        if self.followBodyCentreLine():
            self.operatorcentreline = operatorcentreline
            # increase height to double max of upper/lower above centre line
            aboveLineHeight = h - operatorcentreline
            if aboveLineHeight > operatorcentreline:
                self.h = aboveLineHeight * 2
            else:
                self.h = operatorcentreline * 2
        
        self.operatorcentreline = self.h / 2.0

    def followBodyCentreLine(self):
        """ should the brackets observe the centre line of what they enclose?"""
        return True
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

        if self.noScale:
            X = X + self.bracketwidth + self.thirdspacewidth
        else:
            X = X + self.scaledBracketWidth + self.thirdspacewidth
        Y = Y - self.bracketSpacing
        nodeNum = 0
        for node in self.nodes:
            node.setTextPosition(X,Y)
            if nodeNum > 0:
                X += self.spacewidth
            X += node.w
            nodeNum += 1
            
    def subClassDrawNodeText(self,painter, metrics):

        if self.getType() == tokenValues.BRACKET:
            lbracket = '('
            rbracket = ')'
        else:
            lbracket = '['
            rbracket = ']'
        bracketY = self.y + self.operatorcentreline - self.h

        if self.noScale:
            self.drawString(painter,lbracket,self.x,self.y)
        else:
            painter.drawCharacterToFit(metrics, lbracket, self.x, bracketY, self.scaledBracketWidth, self.h)

        if self.noScale:
            X = self.x + self.w - self.bracketwidth
        else:
            X = self.x + self.w - self.scaledBracketWidth

        if self.noScale:
            self.drawString(painter,rbracket,X,self.y)
        else:
            painter.drawCharacterToFit(metrics, rbracket, X, bracketY, self.scaledBracketWidth, self.h)

        
class SQRTNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w + config["rootsignwidth"] + config["roottickwidth"]
        self.h = max(self.nodes[0].h,self.trueXheight) + config["rootsignextraheight"]
        self.operatorcentreline = self.nodes[0].operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        X = X + config["roottickwidth"] + config["rootsignwidth"]
        self.nodes[0].setTextPosition(X,Y)

    def subClassDrawNodeText(self,painter, metrics):
        barY = self.y + self.operatorcentreline - self.h
        painter.drawLine(self.x + config["roottickwidth"]+config["rootsignwidth"],barY,self.x + self.w,barY)
        baseY = self.y + self.operatorcentreline
        tickY = (baseY - barY)/2.0 + barY
        painter.drawLine(self.x + config["roottickwidth"], tickY,
                          self.x + config["roottickwidth"]+config["rootsignwidth"]/2.0, baseY)
        painter.drawLine(self.x + config["roottickwidth"] + config["rootsignwidth"]/2.0,
                         baseY, self.x+config["roottickwidth"]+config["rootsignwidth"], barY)
        painter.drawLine(self.x, tickY +config["roottickheight"],
                          self.x+config["roottickwidth"], tickY)
      
class FUNCTIONNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def postParse(self):
        nodemodule.Node.postParse(self)
        # rewrite function name and convert to lower case first
        self.setText(self.nodes[0].getText().lower())
        self.bodyNode = self.nodes[1]
        self.nodes[0].dontDraw = True
        
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        self.w = self.bodyNode.w + self.operatorsize.width() + self.thirdspacewidth
        self.h = max(self.bodyNode.h,self.operatorsize.height())
        #if self.bodyNode.containsDivides():
        #    self.operatorcentreline = max(self.bodyNode.operatorcentreline,self.getTextCentreLine(self.font,self.getText()))
        #else:
        #    self.operatorcentreline = self.getTextCentreLine(self.font,self.getText())
        self.operatorcentreline = max(self.bodyNode.operatorcentreline,self.getTextCentreLine(self.font,self.getText()))
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        X = X + self.operatorsize.width() + self.thirdspacewidth
        self.bodyNode.setTextPosition(X,Y)

    def subClassDrawNodeText(self,painter, metrics):
        self.drawString(painter,self.getText(),self.x,self.y)

class DIFFERENTIATENode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setFont(self, name, size):
        nodemodule.Node.setFont(self, name, size)
        for node in self.nodes[2:]:
            node.setFont(name, size/2.0)

    def setTextSize(self):
        if len(self.nodes) > 3:
            # there are many parameters so display like a normal function
            raise Exception("too many params to DIFF")
            FUNCTIONNode.setTextSize(self)
            return
        nodemodule.Node.setTextSize(self)

        dSize = self.metrics.charBoundingRect('d')
        self.delwidth = dSize.width()
        self.delheight = dSize.height()
        self.delcentreline = self.getTextCentreLine(self.font,'d')
        #l.debug("del w %d h %d c %d" % (self.delwidth,self.delheight,self.delcentreline))

        self.diffOrder = "1"
        self.orderWidth = 0
        self.orderHeight = 0
        self.fromWidth = 0
        if len(self.nodes) == 3:
            self.diffOrder = self.nodes[2].getText()
            if self.diffOrder == "1":
                self.nodes[2].dontDraw = True
            self.orderWidth = self.nodes[2].w
            self.orderHeight = self.nodes[2].h
            self.orderCentre = self.getTextCentreLine(self.font,self.nodes[2].getText())

        # we are putting d/dx in front of terms[0]
        self.ddxwidth = self.delwidth + self.nodes[1].w
        self.w = self.ddxwidth + self.nodes[0].w + self.thirdspacewidth
        if self.diffOrder != "1":
            # we must display the order as it is not 1
            self.w += self.orderWidth + self.thirdspacewidth
        # height must make allowances for the d/dx
        self.h = max(self.nodes[0].h,self.delheight + max(self.delheight, self.nodes[1].h) + config["dividerlinespace"])
        self.operatorcentreline = max(self.nodes[0].operatorcentreline,
                                       max(self.delheight, self.nodes[1].h) + config["dividerlinespace"]/2.0)
    
    def setTextPosition(self,X,Y):
        if len(self.nodes) > 3:
            # there are many parameters so display like a normal function
            FUNCTIONNode.setTextPosition(self)
            return
        nodemodule.Node.setTextPosition(self,X,Y)
        
        # draw divider line

        self.term2Y = Y + self.delheight - self.delcentreline + config["dividerlinespace"]/2.0

        self.nodes[1].setTextPosition(X + self.delwidth, self.term2Y)

        if self.diffOrder != "1":
            self.nodes[2].setTextPosition(X+self.ddxwidth/2.0+self.delwidth/2.0 + self.thirdspacewidth,\
                                          Y - self.delheight + self.orderHeight
                                           - self.orderCentre - config["dividerlinespace"]/2.0)
            self.otherOrderPosition = (X+self.ddxwidth + self.thirdspacewidth,
                                        Y + config["dividerlinespace"]/2.0 + self.orderHeight
                                         - self.orderCentre)

        X = X + self.ddxwidth + self.thirdspacewidth
        if self.diffOrder != "1":
            X += self.orderWidth + self.thirdspacewidth
        self.nodes[0].setTextPosition(X,Y)


    def subClassDrawNodeText(self,painter, metrics):
        if len(self.nodes) > 3:
            # there are many parameters so display like a normal function
            FUNCTIONNode.subClassDrawNodeText(self)
            return
        # draw divider line
        X = self.x
        Y = self.y
        painter.drawLine(X,Y,X + self.ddxwidth,Y)
        self.drawString(painter,'d',
                        X + self.ddxwidth/2.0 - self.delwidth/2.0,Y - config["dividerlinespace"]/2.0
                         - self.delcentreline)
        self.drawString(painter,'d',X,self.term2Y )
        if self.diffOrder != "1":
            # redraw node[2] at the other position
            x, y = self.otherOrderPosition
            self.nodes[2].setTextPosition(x,y)
            self.nodes[2].drawNodeText(painter)

            
class FACTORIALNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        
        self.w = self.nodes[0].w + self.operatorsize.width() + self.thirdspacewidth * 2.0
        self.h = max(self.nodes[0].h,self.operatorsize.height())
        self.operatorcentreline = self.nodes[0].operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        
        self.nodes[0].setTextPosition(X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        X = self.x + self.nodes[0].w + self.thirdspacewidth * 2.0
        self.drawString(painter,self.getText(),X,self.y)

class MATRIXNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def postParse(self):
        nodemodule.Node.postParse(self)
        self.numRows = len(self.nodes)
        self.numColumns = 0
        for node in self.nodes:
            if len(node.nodes) > self.numColumns:
                self.numColumns = len(node.nodes)

    def getNode(self, r, c):
        try:
            row = self.nodes[r]
        except:
            return None
        try:
            node = row.nodes[c]
        except:
            return None
        return node

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        # node sizes indexed by (row,column) tuple
        self.nodeSizes = {}
        for r in range(self.numRows):
            for c in range(self.numColumns):
                node = self.getNode(r, c)
                if node:
                    #l.debug("set node size for %s,%s to %s,%s" % (r,c,node.w,node.h))
                    self.nodeSizes[(r,c)] = (node.w, node.h)
                else:
                    self.nodeSizes[(r,c)] = (0, 0)
                    
        # now for each row get maximum height
        self.rowHeights = []
        for r in range(self.numRows):
            rowHeight = 0
            for c in range(self.numColumns):
                if self.nodeSizes[(r,c)][1] > rowHeight:
                    rowHeight =  self.nodeSizes[(r,c)][1]
            rowHeight += self.spacewidth*5
            #l.debug("row height for row %s is %s" % (r,rowHeight))
            self.rowHeights.append(rowHeight)
        # now same for column widths
        self.columnWidths = []
        for c in range(self.numColumns):
            columnWidth = 0
            for r in range(self.numRows):
                if self.nodeSizes[(r,c)][0] > columnWidth:
                    columnWidth =  self.nodeSizes[(r,c)][0]
            columnWidth += self.spacewidth * 5
            #l.debug("column width for column %s is %s" % (c,columnWidth))
            self.columnWidths.append(columnWidth)

        self.w = sum(self.columnWidths)
        self.h = sum(self.rowHeights)
            
        self.operatorcentreline = self.h/2.0

    def getCentreCoordinateOffset(self, r, c):
        xCoord = 0
        yCoord = 0
        if r > 0:
            precedingRows = self.rowHeights[:r]
            yCoord += sum(precedingRows)
            #l.debug("preceding rows is %s and height is %s" % (precedingRows, yCoord))
        yCoord += self.rowHeights[r]/2.0
        if c > 0:
            precedingColumns = self.columnWidths[:c]
            xCoord += sum(precedingColumns)
        xCoord += self.columnWidths[c]/2.0
        #l.debug("coordinate offset for %s %s is %s %s" % (r,c,xCoord,yCoord))
        return (xCoord, yCoord)
    
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        for r in range(self.numRows):
            for c in range(self.numColumns):
                node = self.getNode(r,c)
                if node:
                    x,y = self.getCentreCoordinateOffset(r,c)
                    x += X - node.w/2.0
                    y += Y - self.h/2.0
                    #l.debug("set text position for %s %s to %s %s" % (r,c,x,y))
                    node.setTextPosition(x,y)

    def subClassDrawNodeText(self, painter, metrics):
        pass  

class NEGNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def postParse(self):
        nodemodule.Node.postParse(self)
        if isinstance(self.nodes[0], BRACKETNode):
            self.nodes[0] = self.nodes[0].nodes[0]
        
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w + self.operatorsize.width() + self.thirdspacewidth
        self.h = self.nodes[0].h
        self.operatorcentreline = max(self.nodes[0].operatorcentreline,self.getTextCentreLine(self.font, self.getText()))
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        X = X + self.operatorsize.width() + self.thirdspacewidth
        self.nodes[0].setTextPosition(X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,self.getText(),self.x,self.y) 
        
        
class PLUSMINUSNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w + self.operatorsize.width() + self.nodes[1].w + 2*self.spacewidth
        self.h, self.operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
            
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        term1X = X
        term1Y = Y

        term2X = X + self.nodes[0].w + 2*self.spacewidth + self.operatorsize.width()
        term2Y = Y

        self.nodes[0].setTextPosition(term1X, term1Y)
        self.nodes[1].setTextPosition(term2X, term2Y)

    def subClassDrawNodeText(self, painter, metrics):
        operatorX = self.x + self.nodes[0].w + self.spacewidth
        operatorY = self.y

        self.drawString(painter,self.getText(),operatorX,operatorY)
        
class INTEGRATENode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setFont(self, name, size):
        nodemodule.Node.setFont(self, name, size)
        for node in self.nodes[2:]:
            node.setFont(name, size/2.0)

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.delwidth = self.metrics.charBoundingRect('d').width()
        self.delheight = self.metrics.charBoundingRect('d').height()
        self.delcentreline = self.getTextCentreLine(self.font,'d')
        integralsize = self.metrics.charBoundingRect(constants.INTEGRALSIGN)
        self.integralheight = integralsize.height()
        self.fromWidth = 0
        self.toWidth = 0
        self.fromHeight = 0
        self.toHeight = 0
        if len(self.nodes) == 4:
            self.fromWidth = self.nodes[2].w
            self.fromHeight = self.nodes[2].h
            self.fromCentreLine = self.nodes[2].getTextCentreLine(self.nodes[2].font, self.getText())
            self.toWidth = self.nodes[3].w
            self.toHeight = self.nodes[3].h
            self.toCentreLine = self.nodes[3].getTextCentreLine(self.nodes[2].font, self.getText())
        
        # increase height to take account of the integrate sign
        bodyNodeBelowCentre = self.nodes[0].operatorcentreline
        bodyNodeAboveCentre = self.nodes[0].h - self.nodes[0].operatorcentreline
        maxHalf = max(bodyNodeBelowCentre, bodyNodeAboveCentre)
        self.h = max(maxHalf * 2, self.integralheight)
        self.operatorcentreline = self.h/2.0
        
        self.integralwidth = nodemodule.getIntegralWidth(integralsize.width(),self.h)
        self.w = self.nodes[0].w + self.integralwidth + self.spacewidth + self.thirdspacewidth + self.nodes[1].w + self.delwidth + self.thirdspacewidth + max(self.fromWidth, self.toWidth)


        #self.integralwidth += self.h**0.5/3
        #self.w += self.h**0.5/3

        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        
        X = X + self.integralwidth + self.spacewidth + max(self.fromWidth,self.toWidth) + self.thirdspacewidth
        self.nodes[0].setTextPosition(X,Y)

        X = X + self.nodes[0].w + self.thirdspacewidth
        self.delXPosition = X
        X = X + self.delwidth
        self.nodes[1].setTextPosition(X,Y)

        if len(self.nodes) == 4:
            self.nodes[2].setTextPosition(self.x + self.integralwidth - self.thirdspacewidth*2,
                                           self.y + self.operatorcentreline - self.fromCentreLine)
            self.nodes[3].setTextPosition(self.x + self.integralwidth + self.thirdspacewidth,
                                           self.y + self.operatorcentreline - self.h + self.toHeight)

    def subClassDrawNodeText(self, painter, metrics):
        X = self.x
        Y = self.y

        painter.drawCharacterToFit(metrics, constants.INTEGRALSIGN, self.x,
                                    self.y + self.operatorcentreline - self.h, self.integralwidth, self.h)
        self.drawString(painter,'d',self.delXPosition,Y)
        
class POWERNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)

    def postParse(self):
        nodemodule.Node.postParse(self)
        if isinstance(self.nodes[1], BRACKETNode):
            self.nodes[1] = self.nodes[1].nodes[0]
        self.nodes[1].requestReduceVerticalHeight = True
        
    def setFont(self, name, size):
        nodemodule.Node.setFont(self, name, size)
        try:
            depth = self.getPowerDepth()
            self.nodes[1].setFont(name, size * (config["fontreductionratio"]**(depth* 1.0)))
        except:
            l.exception("setting font size for " + repr(self))
            raise
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w + self.nodes[1].w + self.thirdspacewidth
        self.h = self.nodes[0].h + self.nodes[1].h
#         if self.containsDivides():
#             self.operatorcentreline = self.nodes[0].operatorcentreline
#         else:
#             self.operatorcentreline = self.getTextCentreLine(self.font, "a")
        # the question is, do we elevate the operator centre line or not?
        # this depends on how big the power is relative to the base text
        # or not?
        self.operatorcentreline = self.nodes[0].operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        term1X = X
        term1Y = Y

        term2X = X + self.nodes[0].w
        term2Y = Y - self.nodes[0].h + self.nodes[0].operatorcentreline - self.nodes[1].operatorcentreline

        self.nodes[0].setTextPosition(term1X, term1Y)
        self.nodes[1].setTextPosition(term2X, term2Y)

    def subClassDrawNodeText(self, painter, metrics):
        pass
 
class TIMESNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        
        if self.getRightmostTerm().getType != tokenValues.NUM:
            """ we have a term abutting a non-number so we can lose the * sign """
            self.w = self.nodes[0].w + self.nodes[1].w + self.spacewidth
            self.noMultiplyOperator = True
        else:
            self.noMultiplyOperator = False
            self.w = self.nodes[0].w + self.operatorsize.width() + self.nodes[1].w + 2*self.spacewidth
            
        self.h, self.operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        term1X = X
        term1Y = Y

        term2X = X + self.nodes[0].w + 2*self.spacewidth + self.operatorsize.width()
        term2Y = Y

        if self.noMultiplyOperator == True:
            term2X -= self.spacewidth + self.operatorsize.width()

        self.nodes[0].setTextPosition(term1X, term1Y)
        self.nodes[1].setTextPosition(term2X, term2Y)

    def subClassDrawNodeText(self, painter, metrics):
        X = self.x
        Y = self.y
        operatorX = X + self.nodes[0].w + self.spacewidth
        operatorY = Y

        if self.noMultiplyOperator == False:
            self.drawString(painter,self.getText(),operatorX,operatorY)
    
class EQUALSNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w + self.operatorsize.width() + self.nodes[1].w + 2*self.spacewidth
        self.h, self.operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        term1X = X
        term1Y = Y

        term2X = X + self.nodes[0].w + 2*self.spacewidth + self.operatorsize.width()
        term2Y = Y

        self.nodes[0].setTextPosition(term1X, term1Y)
        self.nodes[1].setTextPosition(term2X, term2Y)

    def subClassDrawNodeText(self, painter, metrics):
        operatorX = self.x + self.nodes[0].w + self.spacewidth
        operatorY = self.y

        self.drawString(painter,self.getText(),operatorX,operatorY)
        
class COMMANode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        self.w = self.nodes[0].w + self.operatorsize.width() + self.nodes[1].w + 2*self.spacewidth
        self.h, self.operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        term1X = X
        term1Y = Y

        term2X = X + self.nodes[0].w + 2*self.spacewidth + self.operatorsize.width()
        term2Y = Y

        self.nodes[0].setTextPosition(term1X, term1Y)
        self.nodes[1].setTextPosition(term2X, term2Y)

    def subClassDrawNodeText(self, painter, metrics):
        operatorX = self.x + self.nodes[0].w + self.spacewidth
        operatorY = self.y
        self.drawString(painter,self.getText(),operatorX,operatorY) 

class DIVIDENode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def postParse(self):
        nodemodule.Node.postParse(self)
        # if a child term is a BRACKET (and not a square bracket) then change it to a noop as it's not required (visually)
        if isinstance(self.nodes[0],BRACKETNode) and self.nodes[0].getText() == "(":
            noopNode = NOOPNode()
            self.nodes[0].clone(noopNode)
            self.nodes[0] = noopNode
            #noopNode.parent = self
        if isinstance(self.nodes[1],BRACKETNode) and self.nodes[1].getText() == "(":
            noopNode = NOOPNode()
            self.nodes[1].clone(noopNode)
            self.nodes[1] = noopNode
            #noopNode.parent = self

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        if self.requestReduceVerticalHeight:
            self.h, self.operatorcentreline =  self.getHeightHorizontalTerms(self.nodes)
            self.dividerWidth = self.h / 4.0
            self.w = self.nodes[0].w + self.dividerWidth + self.spacewidth*2 + self.nodes[1].w
        else:
            self.w = max(self.nodes[0].w,self.nodes[1].w)
            self.h = self.nodes[0].h + self.nodes[1].h + config["dividerlinespace"]
            self.operatorcentreline = self.nodes[1].h + config["dividerlinespace"]/2.0

        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        originalX = X
        originalY = Y
        if self.requestReduceVerticalHeight:
            self.nodes[0].setTextPosition(X,Y)
            self.nodes[1].setTextPosition(X + self.nodes[0].w + self.dividerWidth + self.spacewidth*2, Y)
        else:
            # draw terms[1] under the line
            X = originalX + self.w/2 - self.nodes[1].w/2
            Y = Y + self.nodes[1].h - self.nodes[1].operatorcentreline + config["dividerlinespace"]/2.0
            self.nodes[1].setTextPosition(X,Y)

            # draw terms[0] over the line
            X = originalX + self.w/2 - self.nodes[0].w/2
            Y = originalY - self.nodes[0].operatorcentreline - config["dividerlinespace"]/2.0
            self.nodes[0].setTextPosition(X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        # draw divider line
        if self.requestReduceVerticalHeight:
            painter.drawLine(self.x + self.nodes[0].w + self.spacewidth,self.y + self.operatorcentreline,
                             self.x + self.nodes[0].w + self.dividerWidth + self.spacewidth,
                             self.y + self.operatorcentreline - self.h) 
        else:
            painter.drawLine(self.x,self.y,self.x + self.w,self.y) 
        
class VARNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)

    def postParse(self):
        nodemodule.Node.postParse(self)
        # rewrite function name and convert to lower case first
        self.plainVar = self.getText()
        textUpper = self.getText().upper()
        replacements = {}
        replacements["%PI"] = u'\u03C0'
        replacements["%E"] = 'e'
        replacements["%I"] = 'i'
        replacements["%ALPHA"] = u'\u03B1'
        replacements["%BETA"] = u'\u03B2'
        replacements["%GAMMA"] = u'\u03B3'
        replacements["%DELTA"] = u'\u03B4'
        replacements["%EPSILON"] = u'\u03B5'
        replacements["%ZETA"] = u'\u03B6'
        replacements["%ETA"] = u'\u03B7'
        replacements["%THETA"] = u'\u03B8'
        replacements["%IOTA"] = u'\u03B9'
        replacements["%KAPPA"] = u'\u03BA'
        replacements["%LAMBDA"] = u'\u03BB'
        replacements["%MU"] = u'\u03BC'
        replacements["%NU"] = u'\u03BD'
        replacements["%XI"] = u'\u03BE'
        replacements["%SIGMA"] = u'\u03A3'

        replacements["INF"] = u'\u221E'
        replacements["inf"] = u'\u221E'

        if textUpper in replacements:
            self.setText(replacements[textUpper])

        if self.getText() == "%C":
            self.setText("C")
            self.italic = True
        elif self.getText() == "%c":
            self.setText("c")
            self.italic = True
        elif self.getText() == "%k":
            self.setText("k")
            self.italic = True
        elif self.getText() == "%K1":
            self.setText("K1")
            self.italic = True
        elif self.getText() == "%K2":
            self.setText("K2")
            self.italic = True
        elif self.getText() == "%k1":
            self.setText("k1")
            self.italic = True
        elif self.getText() == "%k2":
            self.setText("k2")
            self.italic = True

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.colour = constants.blue
        text = self.getText()
        if len(text) == 1:
            size = self.metrics.charBoundingRect(unicode(text))
        else:
            size = self.metrics.boundingRect(unicode(text))
        self.w = size.width()
        self.h = size.height()
        self.operatorcentreline = self.getTextCentreLine(self.font, self.getText())
        self.xOffset = size.x()
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X - self.xOffset,Y)

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,unicode(self.getText()),self.x,self.y)
        
class NUMNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        text = self.getText()
        if len(text) == 1:
            size = self.metrics.charBoundingRect(unicode(text))
        else:
            size = self.metrics.boundingRect(unicode(text))
        self.w = size.width()
        self.h = size.height()
        self.operatorcentreline = self.getTextCentreLine(self.font, self.getText())
        self.xOffset = size.x()
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X - self.xOffset,Y)

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,unicode(self.getText()),self.x,self.y)
        
class LABELNode(nodemodule.Node):

    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.id = self.nodes[0].getText()
        l.debug("id set to " + repr(self.id))
        self.nodes[0].dontDraw = True
        
        self.w = self.nodes[1].w
        self.h = self.nodes[1].h
        self.operatorcentreline = self.nodes[1].operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        
        self.nodes[1].setTextPosition(X,Y)
        
    def subClassDrawNodeText(self, painter, metrics):
        pass
        
00831 class NOOPNode(nodemodule.Node):
    """ does nothing and can only have one child """
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
        self.setText("NOOP")
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        self.w = self.nodes[0].w
        self.h = self.nodes[0].h
        self.operatorcentreline = self.nodes[0].operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)
        self.nodes[0].setTextPosition(X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        pass  

00851 class EMPTYNode(nodemodule.Node):
    """ a node that is just a blank space and has no children """
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
        self.dontDraw = True
        self.setText("EMPTY")
    
    def setTextSize(self):
        #nodemodule.Node.setTextSize(self)
        self.w = 0
        self.h = 0
        self.operatorcentreline = 0
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        pass  

class PROGCONTROLNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        self.colour = constants.red
        w = 0
        commandSize = self.metrics.boundingRect(self.getText())
        w += commandSize.width()
        for node in self.nodes:
            w += node.w + self.spacewidth*2
        self.w = w
        h = 0
        operatorcentreline = 0
        if self.nodes:
            h, operatorcentreline = self.getHeightHorizontalTerms(self.nodes)
        if commandSize.height() > h:
            h = commandSize.height()
        if self.getTextCentreLine(self.font, self.getText()) > operatorcentreline:
            operatorcentreline = self.getTextCentreLine(self.font, self.getText())
        self.h = h
        self.operatorcentreline = operatorcentreline
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

        x = X + self.metrics.boundingRect(self.getText()).width()
        for node in self.nodes:
            x += self.spacewidth*2
            node.setTextPosition(x, Y)
            x += node.w

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,unicode(self.getText()),self.x,self.y)


class LIMITNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setFont(self, name, size):
        nodemodule.Node.setFont(self, name, size)
        for node in self.nodes[1:]:
            node.setFont(name, size/2.0)

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        self.setText("lim")
        self.size = self.metrics.boundingRect(self.getText())
        self.textCentreLine = self.getTextCentreLine(self.font, self.getText())
        
        self.limDetailsMinArrowWidth = self.size.width()/2.0
        self.limDetailsMinWidth = self.nodes[1].w + self.nodes[2].w + self.limDetailsMinArrowWidth + self.spacewidth*2
        if self.limDetailsMinWidth > self.size.width():
            w = self.limDetailsMinWidth
        else:
            w = self.size.width()
        self.limWidth = w
        w += self.spacewidth
        w += self.nodes[0].w
        self.w = w
        self.h = max(self.size.height() + max(self.nodes[1].h,self.nodes[2].h) + self.spacewidth,
                      self.nodes[0].h)
        operatorcentreline = self.textCentreLine + max(self.nodes[1].h,self.nodes[2].h) + self.spacewidth
        self.operatorcentreline = max(operatorcentreline, self.nodes[0].operatorcentreline)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

        self.nodes[0].setTextPosition(X + self.limWidth + self.spacewidth,Y)
        self.limDetailsHeight = max(self.nodes[1].h - self.nodes[1].operatorcentreline,
                                    self.nodes[1].h - self.nodes[1].operatorcentreline)
        self.nodes[1].setTextPosition(X, Y + self.textCentreLine + self.limDetailsHeight + self.spacewidth)
        self.nodes[2].setTextPosition(X + self.limWidth - self.nodes[2].w,
                                       Y + self.textCentreLine + self.limDetailsHeight + self.spacewidth)

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,unicode(self.getText()),
                        self.x + self.limWidth/2.0 - self.size.width()/2.0,self.y)
        # draw arrow
        arrowStartX = self.nodes[1].x + self.nodes[1].w + self.thirdspacewidth*2
        arrowEndX = self.nodes[2].x - self.thirdspacewidth*2
        arrowY = self.y + self.textCentreLine + self.limDetailsHeight + self.spacewidth
        arrowY = self.y + self.textCentreLine + self.spacewidth + self.nodes[1].h/2.0
        painter.drawLine(arrowStartX,arrowY,arrowEndX,arrowY)
        painter.drawLine(arrowEndX,arrowY,arrowEndX-self.spacewidth,arrowY-self.spacewidth/2.0)
        painter.drawLine(arrowEndX,arrowY,arrowEndX-self.spacewidth,arrowY+self.spacewidth/2.0)

class SUMNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setFont(self, name, size):
        nodemodule.Node.setFont(self, name, size)
        for node in self.nodes[1:]:
            node.setFont(name, size/2.0)

    def setTextSize(self):
        nodemodule.Node.setTextSize(self)

        self.setText(constants.SUMSIGN)
        self.size = self.metrics.boundingRect(self.getText())
        self.textCentreLine = self.getTextCentreLine(self.font, self.getText())
        
        self.limDetailsMinArrowWidth = self.size.width()/2.0
        self.limDetailsMinWidth = self.nodes[1].w + self.nodes[2].w + self.limDetailsMinArrowWidth + self.spacewidth*2
        if self.limDetailsMinWidth > self.size.width():
            w = self.limDetailsMinWidth
        else:
            w = self.size.width()
        self.limWidth = w
        w += self.spacewidth
        w += self.nodes[0].w
        self.w = w
        self.h = max(self.size.height() + max(self.nodes[1].h,self.nodes[2].h)
                      + self.spacewidth + self.nodes[3].h + self.spacewidth, self.nodes[0].h)
        operatorcentreline = self.textCentreLine + max(self.nodes[1].h,self.nodes[2].h) + self.spacewidth
        self.operatorcentreline = max(operatorcentreline, self.nodes[0].operatorcentreline)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

        self.nodes[0].setTextPosition(X + self.limWidth + self.spacewidth,Y)
        self.limDetailsHeight = max(self.nodes[1].h - self.nodes[1].operatorcentreline,
                                    self.nodes[1].h - self.nodes[1].operatorcentreline)
        self.nodes[1].setTextPosition(X, Y + self.textCentreLine + self.limDetailsHeight + self.spacewidth)
        self.nodes[2].setTextPosition(X + self.limWidth - self.nodes[2].w,
                                       Y + self.textCentreLine + self.limDetailsHeight + self.spacewidth)
        self.nodes[3].setTextPosition(X + self.limWidth/2.0 - self.nodes[3].w/2.0,
                                       Y +self.operatorcentreline - self.h + self.nodes[3].h
                                        - self.nodes[3].operatorcentreline)

    def subClassDrawNodeText(self, painter, metrics):
        self.drawString(painter,unicode(self.getText()),
                        self.x + self.limWidth/2.0 - self.size.width()/2.0,self.y)
        # draw arrow
        arrowStartX = self.nodes[1].x + self.nodes[1].w + self.thirdspacewidth*2
        arrowEndX = self.nodes[2].x - self.thirdspacewidth*2
        arrowY = self.y + self.textCentreLine + self.limDetailsHeight + self.spacewidth
        arrowY = self.y + self.textCentreLine + self.spacewidth + self.nodes[1].h/2.0
        painter.drawLine(arrowStartX,arrowY,arrowEndX,arrowY)
        painter.drawLine(arrowEndX,arrowY,arrowEndX-self.spacewidth,arrowY-self.spacewidth/2.0)
        painter.drawLine(arrowEndX,arrowY,arrowEndX-self.spacewidth,arrowY+self.spacewidth/2.0)

class TemplateNode(nodemodule.Node):
    
    def __init__(self, *args):
        nodemodule.Node.__init__(self, *args)
    
    def setTextSize(self):
        nodemodule.Node.setTextSize(self)
        
    def setTextPosition(self,X,Y):
        nodemodule.Node.setTextPosition(self,X,Y)

    def subClassDrawNodeText(self, painter, metrics):
        pass  


Generated by  Doxygen 1.6.0   Back to index