Example #1
0
class BarcodeUSPS_4State(_BarcodeWidget):
    codeName = "USPS_4State"
    _attrMap = AttrMap(
        BASE=_BarcodeWidget,
        widthSize=AttrMapValue(
            isNumber,
            '''(float, default 1): the bar width size adjustment between 0 and 1.'''
        ),
        heightSize=AttrMapValue(
            isNumber,
            '''(float, default 1): the bar height size adjustment between 0 and 1.'''
        ),
        fontName=AttrMapValue(isString, desc='human readable font'),
        fontSize=AttrMapValue(isNumber, desc='human readable font size'),
        tracking=AttrMapValue(isString, desc='tracking data'),
        routing=AttrMapValue(isString, desc='routing data'),
        humanReadable=AttrMapValue(isBoolean, desc='if human readable'),
    )

    def __init__(self, **kw):
        from reportlab.graphics.barcode.usps4s import USPS_4State
        kw.setdefault('routing', '01234567891')
        _BarcodeWidget.__init__(self, USPS_4State, '01234567094987654321',
                                **kw)

    def annotate(self, x, y, text, fontName, fontSize, anchor='middle'):
        _BarcodeWidget.annotate(self,
                                x,
                                y,
                                text,
                                fontName,
                                fontSize,
                                anchor='start')
Example #2
0
class AddedPlot(LinePlot, object):

    _attrMap = AttrMap(BASE=LinePlot, g=AttrMapValue(None, desc='Groups.'))

    def __init__(self):
        super(AddedPlot, self).__init__()
        self.g = Group()

    def draw(self):
        g = super(AddedPlot, self).draw()
        for i in self.g.contents:
            if isinstance(i, Rect):
                x = self.xValueAxis.scale(i.x)
                width = self.xValueAxis.scale(
                    i.width) - self.xValueAxis.scale(0)
                y = self.yValueAxis.scale(i.y)
                height = self.yValueAxis.scale(
                    i.height) - self.yValueAxis.scale(0)
                g.add(
                    Rect(x,
                         y,
                         width,
                         height,
                         strokeColor=i.strokeColor,
                         strokeWidth=i.strokeWidth,
                         fillColor=i.fillColor))
            else:
                g.add(i)
        return g
Example #3
0
class BarcodeFIM(_BarcodeWidget):
    """
    FIM was developed as part of the POSTNET barcoding system. FIM (Face Identification Marking) is used by the cancelling machines to sort mail according to whether or not they have bar code and their postage requirements. There are four types of FIM called FIM A, FIM B, FIM C, and FIM D.

    The four FIM types have the following meanings:
        FIM A- Postage required pre-barcoded
        FIM B - Postage pre-paid, no bar code exists
        FIM C- Postage prepaid prebarcoded
        FIM D- Postage required, no bar code exists
    """
    codeName = "FIM"
    _attrMap = AttrMap(BASE=_BarcodeWidget,
        barWidth = AttrMapValue(isNumber,'''(float, default 1/32in): the bar width.'''),
        spaceWidth = AttrMapValue(isNumber,'''(float or None, default 1/16in):
            width of intercharacter gap. None means "use barWidth".'''),
        barHeight = AttrMapValue(isNumber,'''(float, default 5/8in): The bar height.'''),
        quiet = AttrMapValue(isBoolean,'''(bool, default 0):
            Whether to include quiet zones in the symbol.'''),
        lquiet = AttrMapValue(isNumber,'''(float, default: 15/32in):
            Quiet zone size to left of code, if quiet is true.'''),
        rquiet = AttrMapValue(isNumber,'''(float, default 1/4in):
            Quiet zone size to right left of code, if quiet is true.'''),
        fontName = AttrMapValue(isString, desc='human readable font'),
        fontSize = AttrMapValue(isNumber, desc='human readable font size'),
        humanReadable = AttrMapValue(isBoolean, desc='if human readable'),
        )
    def __init__(self,**kw):
        from reportlab.graphics.barcode.usps import FIM
        _BarcodeWidget.__init__(self,FIM,"A",**kw)
Example #4
0
class BarcodeI2of5(_BarcodeWidget):
    """Interleaved 2 of 5 is used in distribution and warehouse industries.

    It encodes an even-numbered sequence of numeric digits. There is an optional
    module 10 check digit; if including this, the total length must be odd so that
    it becomes even after including the check digit.  Otherwise the length must be
    even. Since the check digit is optional, our library does not check it.
    """

    _tests = [
        '12',
        '1234',
        '123456',
        '12345678',
        '1234567890'
        ]
    codeName = "I2of5"
    _attrMap = AttrMap(BASE=_BarcodeWidget,
        barWidth = AttrMapValue(isNumber,'''(float, default .0075):
            X-Dimension, or width of the smallest element
            Minumum is .0075 inch (7.5 mils).'''),
        ratio = AttrMapValue(isNumber,'''(float, default 2.2):
            The ratio of wide elements to narrow elements.
            Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
            barWidth is greater than 20 mils (.02 inch))'''),
        gap = AttrMapValue(isNumberOrNone,'''(float or None, default None):
            width of intercharacter gap. None means "use barWidth".'''),
        barHeight = AttrMapValue(isNumber,'''(float, see default below):
            Height of the symbol.  Default is the height of the two
            bearer bars (if they exist) plus the greater of .25 inch
            or .15 times the symbol's length.'''),
        checksum = AttrMapValue(isBoolean,'''(bool, default 1):
            Whether to compute and include the check digit'''),
        bearers = AttrMapValue(isNumber,'''(float, in units of barWidth. default 3.0):
            Height of bearer bars (horizontal bars along the top and
            bottom of the barcode). Default is 3 x-dimensions.
            Set to zero for no bearer bars. (Bearer bars help detect
            misscans, so it is suggested to leave them on).'''),
        quiet = AttrMapValue(isBoolean,'''(bool, default 1):
            Whether to include quiet zones in the symbol.'''),

        lquiet = AttrMapValue(isNumber,'''(float, see default below):
            Quiet zone size to left of code, if quiet is true.
            Default is the greater of .25 inch, or .15 times the symbol's
            length.'''),

        rquiet = AttrMapValue(isNumber,'''(float, defaults as above):
            Quiet zone size to right left of code, if quiet is true.'''),
        fontName = AttrMapValue(isString, desc='human readable font'),
        fontSize = AttrMapValue(isNumber, desc='human readable font size'),
        humanReadable = AttrMapValue(isBoolean, desc='if human readable'),
        stop = AttrMapValue(isBoolean, desc='if we use start/stop symbols (default 1)'),
        )
    _bcTransMap = {}

    def __init__(self,**kw):
        from reportlab.graphics.barcode.common import I2of5
        _BarcodeWidget.__init__(self,I2of5,1234,**kw)
Example #5
0
class BarcodeStandard93(BarcodeCode128):
    """This is a compressed form of Code 39"""
    codeName = "Standard93"
    _attrMap = AttrMap(BASE=BarcodeCode128,
        stop = AttrMapValue(isBoolean, desc='if we use start/stop symbols (default 1)'),
        )
    def __init__(self,**kw):
        from reportlab.graphics.barcode.code93 import Standard93
        _BarcodeWidget.__init__(self,Standard93,"CODE 93",**kw)
Example #6
0
class DataMatrixWidget(Widget, _DMTXCheck):
    codeName = "DataMatrix"
    _attrMap = AttrMap(
        BASE=Widget,
        value=AttrMapValue(isString, desc='Datamatrix data'),
        x=AttrMapValue(isNumber, desc='x-coord'),
        y=AttrMapValue(isNumber, desc='y-coord'),
        color=AttrMapValue(isColor, desc='foreground color'),
        bgColor=AttrMapValue(isColorOrNone, desc='background color'),
        encoding=AttrMapValue(isString, desc='encoding'),
        size=AttrMapValue(isString, desc='size'),
        cellSize=AttrMapValue(isString, desc='cellSize'),
        anchor=AttrMapValue(isBoxAnchor, desc='anchor pooint for x,y'),
    )

    _defaults = dict(
        x=('0', _numConv),
        y=('0', _numConv),
        color=('black', toColor),
        bgColor=(None, lambda _: toColor(_) if _ is not None else _),
        encoding=('Ascii', None),
        size=('SquareAuto', None),
        cellSize=('5x5', None),
        anchor=('sw', None),
    )

    def __init__(self, value='Hello Cruel World!', **kwds):
        self.pylibdmtx_check()
        self.value = value
        for k, (d, c) in self._defaults.items():
            v = kwds.pop(k, d)
            if c: v = c(v)
            setattr(self, k, v)

    def rect(self, x, y, w, h, fill=1, stroke=0):
        self._gadd(
            Rect(x, y, w, h, strokeColor=None, fillColor=self._fillColor))

    def saveState(self, *args, **kwds):
        pass

    restoreState = setStrokeColor = saveState

    def setFillColor(self, c):
        self._fillColor = c

    def draw(self):
        m = DataMatrix(value=self.value,
                       **{k: getattr(self, k)
                          for k in self._defaults})
        m.canv = self
        m.y += m.height
        g = Group()
        self._gadd = g.add
        m.draw()
        return g
Example #7
0
class BarcodeCode128(BarcodeI2of5):
    """Code 128 encodes any number of characters in the ASCII character set.
    """
    _tests = [
        'ReportLab Rocks!'
        ]
    codeName = "Code128"
    _attrMap = AttrMap(BASE=BarcodeI2of5,UNWANTED=('bearers','checksum','ratio','checksum','stop'))
    def __init__(self,**kw):
        from reportlab.graphics.barcode.code128 import Code128
        _BarcodeWidget.__init__(self,Code128,"AB-12345678",**kw)
Example #8
0
class ShadedPolygon(Widget, LineShape):
    _attrMap = AttrMap(
        BASE=LineShape,
        angle=AttrMapValue(isNumber, desc="Shading angle"),
        fillColorStart=AttrMapValue(isColorOrNone),
        fillColorEnd=AttrMapValue(isColorOrNone),
        numShades=AttrMapValue(isNumber,
                               desc='The number of interpolating colors.'),
        cylinderMode=AttrMapValue(isBoolean,
                                  desc='True if shading reverses in middle.'),
        points=AttrMapValue(isListOfNumbers),
    )

    def __init__(self, **kw):
        self.angle = 90
        self.fillColorStart = colors.red
        self.fillColorEnd = colors.green
        self.cylinderMode = 0
        self.numShades = 50
        self.points = [-1, -1, 2, 2, 3, -1]
        LineShape.__init__(self, kw)

    def draw(self):
        P = self.points
        P = map(lambda i, P=P: (P[i], P[i + 1]), xrange(0, len(P), 2))
        path = definePath([('moveTo', ) + P[0]] +
                          map(lambda x:
                              ('lineTo', ) + x, P[1:]) + ['closePath'],
                          fillColor=None,
                          strokeColor=None)
        path.isClipPath = 1
        g = Group()
        g.add(path)
        angle = self.angle
        orientation = 'vertical'
        if angle == 180:
            angle = 0
        elif angle in (90, 270):
            orientation = 'horizontal'
            angle = 0
        rect = ShadedRect(strokeWidth=0,
                          strokeColor=None,
                          orientation=orientation)
        for k in 'fillColorStart', 'fillColorEnd', 'numShades', 'cylinderMode':
            setattr(rect, k, getattr(self, k))
        g.add(rotatedEnclosingRect(P, angle, rect))
        g.add(EmptyClipPath)
        path = path.copy()
        path.isClipPath = 0
        path.strokeColor = self.strokeColor
        path.strokeWidth = self.strokeWidth
        g.add(path)
        return g
Example #9
0
class BarcodePOSTNET(_BarcodeWidget):
    codeName = "POSTNET"
    _attrMap = AttrMap(BASE=_BarcodeWidget,
        barWidth = AttrMapValue(isNumber,'''(float, default 0.018*in): the bar width.'''),
        spaceWidth = AttrMapValue(isNumber,'''(float or None, default 0.0275in): width of intercharacter gap.'''),
        shortHeight = AttrMapValue(isNumber,'''(float, default 0.05in): The short bar height.'''),
        barHeight = AttrMapValue(isNumber,'''(float, default 0.125in): The full bar height.'''),
        fontName = AttrMapValue(isString, desc='human readable font'),
        fontSize = AttrMapValue(isNumber, desc='human readable font size'),
        humanReadable = AttrMapValue(isBoolean, desc='if human readable'),
        )
    def __init__(self,**kw):
        from reportlab.graphics.barcode.usps import POSTNET
        _BarcodeWidget.__init__(self,POSTNET,"78247-1043",**kw)
Example #10
0
class BarcodeCode11(BarcodeI2of5):
    """Used mostly for labelling telecommunications equipment.
    It encodes numeric digits.
    """
    codeName = "Code11"
    _attrMap = AttrMap(BASE=BarcodeI2of5,
        checksum = AttrMapValue(isInt,'''(integer, default 2):
            Whether to compute and include the check digit(s).
            (0 none, 1 1-digit, 2 2-digit, -1 auto, default -1):
            How many checksum digits to include. -1 ("auto") means
            1 if the number of digits is 10 or less, else 2.'''),
            )
    def __init__(self,**kw):
        from reportlab.graphics.barcode.common import Code11
        _BarcodeWidget.__init__(self,Code11,"01234545634563",**kw)
Example #11
0
class _BarcodeWidget(PlotArea):
    _attrMap = AttrMap(BASE=PlotArea,
        barStrokeColor = AttrMapValue(isColorOrNone, desc='Color of bar borders.'),
        barFillColor = AttrMapValue(isColorOrNone, desc='Color of bar interior areas.'),
        barStrokeWidth = AttrMapValue(isNumber, desc='Width of bar borders.'),
        value = AttrMapValue(EitherOr((isString,isNumber)), desc='Value.'),
        textColor = AttrMapValue(isColorOrNone, desc='Color of human readable text.'),
        valid = AttrMapValue(isBoolean),
        validated = AttrMapValue(isString,desc="validated form of input"),
        encoded = AttrMapValue(None,desc="encoded form of input"),
        decomposed = AttrMapValue(isString,desc="decomposed form of input"),
        canv = AttrMapValue(None,desc="temporarily used for internal methods"),
        gap = AttrMapValue(isNumberOrNone, desc='Width of inter character gaps.'),
        )

    textColor = barFillColor = black
    barStrokeColor = None
    barStrokeWidth = 0
    _BCC = None
    def __init__(self,BCC=None,_value='',**kw):
        self._BCC = BCC
        class Combiner(self.__class__,BCC):
            __name__ = self.__class__.__name__
        self.__class__ = Combiner
        PlotArea.__init__(self)
        del self.width, self.height
        self.x = self.y = 0
        kw.setdefault('value',_value)
        BCC.__init__(self,**kw)

    def rect(self,x,y,w,h,**kw):
        self._Gadd(Rect(self.x+x,self.y+y,w,h,
                    strokeColor=self.barStrokeColor,strokeWidth=self.barStrokeWidth, fillColor=self.barFillColor))

    def draw(self):
        if not self._BCC: raise NotImplementedError("Abstract class %s cannot be drawn" % self.__class__.__name__)
        self.canv = self
        G = Group()
        self._Gadd = G.add
        self._Gadd(Rect(self.x,self.y,self.width,self.height,fillColor=None,strokeColor=None,strokeWidth=0.0001))
        self._BCC.draw(self)
        del self.canv, self._Gadd
        return G

    def annotate(self,x,y,text,fontName,fontSize,anchor='middle'):
        self._Gadd(String(self.x+x,self.y+y,text,fontName=fontName,fontSize=fontSize,
                            textAnchor=anchor,fillColor=self.textColor))
Example #12
0
class YValueAxisWithDesc(YValueAxis):

    _attrMap = AttrMap(BASE=YValueAxis,
                       desc=AttrMapValue(
                           None, desc="The description of the Y axis."))

    def __init__(self, desc=None):
        YValueAxis.__init__(self)

        self.desc = None
        if isString(desc) is True:
            self.desc = desc

    def makeTickLabels(self):
        g = YValueAxis.makeTickLabels(self)

        desc_text = make_desc_test(self, "Y")
        if desc_text is not None:
            g.add(desc_text)

        return g
Example #13
0
class XCategoryAxisWithDesc(XCategoryAxis):

    _attrMap = AttrMap(BASE=XCategoryAxis,
                       desc=AttrMapValue(
                           None, desc="The description of the X axis."))

    def __init__(self, desc=None):
        XCategoryAxis.__init__(self)

        self.desc = None
        if isString(desc) is True:
            self.desc = desc

        self.labels.fontName = DefaultFontName

    def makeTickLabels(self):
        g = XCategoryAxis.makeTickLabels(self)

        desc_text = make_desc_test(self, "X")
        if desc_text is not None:
            g.add(desc_text)

        return g
Example #14
0
class Marker(Widget):
    '''A polymorphic class of markers'''
    _attrMap = AttrMap(BASE=Widget,
                    kind = AttrMapValue(
                            OneOf(None, 'Square', 'Diamond', 'Circle', 'Cross', 'Triangle', 'StarSix',
                                'Pentagon', 'Hexagon', 'Heptagon', 'Octagon', 'StarFive',
                                'FilledSquare', 'FilledCircle', 'FilledDiamond', 'FilledCross',
                                'FilledTriangle','FilledStarSix', 'FilledPentagon', 'FilledHexagon',
                                'FilledHeptagon', 'FilledOctagon', 'FilledStarFive',
                                'Smiley','ArrowHead', 'FilledArrowHead'),
                            desc='marker type name'),
                    size = AttrMapValue(isNumber,desc='marker size'),
                    x = AttrMapValue(isNumber,desc='marker x coordinate'),
                    y = AttrMapValue(isNumber,desc='marker y coordinate'),
                    dx = AttrMapValue(isNumber,desc='marker x coordinate adjustment'),
                    dy = AttrMapValue(isNumber,desc='marker y coordinate adjustment'),
                    angle = AttrMapValue(isNumber,desc='marker rotation'),
                    fillColor = AttrMapValue(isColorOrNone, desc='marker fill colour'),
                    strokeColor = AttrMapValue(isColorOrNone, desc='marker stroke colour'),
                    strokeWidth = AttrMapValue(isNumber, desc='marker stroke width'),
                    arrowBarbDx = AttrMapValue(isNumber, desc='arrow only the delta x for the barbs'),
                    arrowHeight = AttrMapValue(isNumber, desc='arrow only height'),
                    )

    def __init__(self,*args,**kw):
        self.setProperties(kw)
        self._setKeywords(
            kind = None,
            strokeColor = black,
            strokeWidth = 0.1,
            fillColor = None,
            size = 5,
            x = 0,
            y = 0,
            dx = 0,
            dy = 0,
            angle = 0,
            arrowBarbDx = -1.25,
            arrowHeight = 1.875,
            )

    def clone(self):
        return new.instance(self.__class__,self.__dict__.copy())

    def _Smiley(self):
        x, y = self.x+self.dx, self.y+self.dy
        d = self.size/2.0
        s = SmileyFace()
        s.fillColor = self.fillColor
        s.strokeWidth = self.strokeWidth
        s.strokeColor = self.strokeColor
        s.x = x-d
        s.y = y-d
        s.size = d*2
        return s

    def _Square(self):
        x, y = self.x+self.dx, self.y+self.dy
        d = self.size/2.0
        s = Rect(x-d,y-d,2*d,2*d,fillColor=self.fillColor,strokeColor=self.strokeColor,strokeWidth=self.strokeWidth)
        return s

    def _Diamond(self):
        d = self.size/2.0
        return self._doPolygon((-d,0,0,d,d,0,0,-d))

    def _Circle(self):
        x, y = self.x+self.dx, self.y+self.dy
        s = Circle(x,y,self.size/2.0,fillColor=self.fillColor,strokeColor=self.strokeColor,strokeWidth=self.strokeWidth)
        return s

    def _Cross(self):
        x, y = self.x+self.dx, self.y+self.dy
        s = float(self.size)
        h, s = s/2, s/6
        return self._doPolygon((-s,-h,-s,-s,-h,-s,-h,s,-s,s,-s,h,s,h,s,s,h,s,h,-s,s,-s,s,-h))

    def _Triangle(self):
        x, y = self.x+self.dx, self.y+self.dy
        r = float(self.size)/2
        c = 30*_toradians
        s = sin(30*_toradians)*r
        c = cos(c)*r
        return self._doPolygon((0,r,-c,-s,c,-s))

    def _StarSix(self):
        r = float(self.size)/2
        c = 30*_toradians
        s = sin(c)*r
        c = cos(c)*r
        z = s/2
        g = c/2
        return self._doPolygon((0,r,-z,s,-c,s,-s,0,-c,-s,-z,-s,0,-r,z,-s,c,-s,s,0,c,s,z,s))

    def _StarFive(self):
        R = float(self.size)/2
        r = R*sin(18*_toradians)/cos(36*_toradians)
        P = []
        angle = 90
        for i in xrange(5):
            for radius in R, r:
                theta = angle*_toradians
                P.append(radius*cos(theta))
                P.append(radius*sin(theta))
                angle = angle + 36
        return self._doPolygon(P)

    def _Pentagon(self):
        return self._doNgon(5)

    def _Hexagon(self):
        return self._doNgon(6)

    def _Heptagon(self):
        return self._doNgon(7)

    def _Octagon(self):
        return self._doNgon(8)

    def _ArrowHead(self):
        s = self.size
        h = self.arrowHeight
        b = self.arrowBarbDx
        return self._doPolygon((0,0,b,-h,s,0,b,h))

    def _doPolygon(self,P):
        x, y = self.x+self.dx, self.y+self.dy
        if x or y: P = map(lambda i,P=P,A=[x,y]: P[i] + A[i&1], range(len(P)))
        return Polygon(P, strokeWidth =self.strokeWidth, strokeColor=self.strokeColor, fillColor=self.fillColor)

    def _doFill(self):
        old = self.fillColor
        if old is None:
            self.fillColor = self.strokeColor
        r = (self.kind and getattr(self,'_'+self.kind[6:]) or Group)()
        self.fillColor = old
        return r

    def _doNgon(self,n):
        P = []
        size = float(self.size)/2
        for i in xrange(n):
            r = (2.*i/n+0.5)*pi
            P.append(size*cos(r))
            P.append(size*sin(r))
        return self._doPolygon(P)

    _FilledCircle = _doFill
    _FilledSquare = _doFill
    _FilledDiamond = _doFill
    _FilledCross = _doFill
    _FilledTriangle = _doFill
    _FilledStarSix = _doFill
    _FilledPentagon = _doFill
    _FilledHexagon = _doFill
    _FilledHeptagon = _doFill
    _FilledOctagon = _doFill
    _FilledStarFive = _doFill
    _FilledArrowHead = _doFill

    def draw(self):
        if self.kind:
            m = getattr(self,'_'+self.kind)
            if self.angle:
                _x, _dx, _y, _dy = self.x, self.dx, self.y, self.dy
                self.x, self.dx, self.y, self.dy = 0,0,0,0
                try:
                    m = m()
                finally:
                    self.x, self.dx, self.y, self.dy = _x, _dx, _y, _dy
                if not isinstance(m,Group):
                    _m, m = m, Group()
                    m.add(_m)
                if self.angle: m.rotate(self.angle)
                x, y = _x+_dx, _y+_dy
                if x or y: m.shift(x,y)
            else:
                m = m()
        else:
            m = Group()
        return m
class PH(PropHolder):
    _attrMap = AttrMap(a=AttrMapValue(isNumber), b=AttrMapValue(isNumber))
Example #16
0
 AttrMap(
     BASE=_BarcodeWidget,
     barWidth=AttrMapValue(
         isNumber, '''(float, default .0075):
         X-Dimension, or width of the smallest element
         Minumum is .0075 inch (7.5 mils).'''),
     ratio=AttrMapValue(
         isNumber, '''(float, default 2.2):
         The ratio of wide elements to narrow elements.
         Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
         barWidth is greater than 20 mils (.02 inch))'''),
     gap=AttrMapValue(
         isNumberOrNone, '''(float or None, default None):
         width of intercharacter gap. None means "use barWidth".'''),
     barHeight=AttrMapValue(
         isNumber, '''(float, see default below):
         Height of the symbol.  Default is the height of the two
         bearer bars (if they exist) plus the greater of .25 inch
         or .15 times the symbol's length.'''),
     checksum=AttrMapValue(
         isBoolean, '''(bool, default 1):
         Whether to compute and include the check digit'''),
     bearers=AttrMapValue(
         isNumber, '''(float, in units of barWidth. default 3.0):
         Height of bearer bars (horizontal bars along the top and
         bottom of the barcode). Default is 3 x-dimensions.
         Set to zero for no bearer bars. (Bearer bars help detect
         misscans, so it is suggested to leave them on).'''),
     quiet=AttrMapValue(
         isBoolean, '''(bool, default 1):
         Whether to include quiet zones in the symbol.'''),
     lquiet=AttrMapValue(
         isNumber, '''(float, see default below):
         Quiet zone size to left of code, if quiet is true.
         Default is the greater of .25 inch, or .15 times the symbol's
         length.'''),
     rquiet=AttrMapValue(
         isNumber, '''(float, defaults as above):
         Quiet zone size to right left of code, if quiet is true.'''),
     fontName=AttrMapValue(isString, desc='human readable font'),
     fontSize=AttrMapValue(isNumber, desc='human readable font size'),
     humanReadable=AttrMapValue(isBoolean, desc='if human readable'),
     stop=AttrMapValue(isBoolean,
                       desc='if we use start/stop symbols (default 1)'),
 ),
class ReportLabBarChart(BarChart):

    _flipXY = 0

    _attrMap = AttrMap(
        BASE=BarChart,
        drawLegend=AttrMapValue(isBoolean,
                                desc='If true draw legend.',
                                advancedUsage=1),
        legendPositionType=AttrMapValue(OneOf("null", "top-left", "top-mid",
                                              "top-right", "bottom-left",
                                              "bottom-mid", "bottom-right"),
                                        desc="The position of LinLegend."),
        legendAdjustX=AttrMapValue(isNumber, desc='xxx.'),
        legendAdjustY=AttrMapValue(isNumber, desc='xxx.'),
        legendCategoryNames=AttrMapValue(
            isListOfStringsOrNone, desc='List of legend category names.'),
        titleMain=AttrMapValue(isString, desc='main title text.'),
        titleMainFontName=AttrMapValue(isString, desc='main title font name.'),
        titleMainFontSize=AttrMapValue(isNumberInRange(0, 100),
                                       desc='main title font size.'),
        titleMainFontColor=AttrMapValue(isColor,
                                        desc='main title font color.'),
        legendFontSize=AttrMapValue(isNumberInRange(0, 100),
                                    desc='legend text font size.'),
        x_labels_height=AttrMapValue(isNumberInRange(0, 100),
                                     desc='the max height in x-labels.'),
        y_labels_height=AttrMapValue(isNumberInRange(0, 50),
                                     desc='the max height in y-labels.'))

    def __init__(self,
                 x,
                 y,
                 width,
                 height,
                 cat_names,
                 data,
                 step_count=4,
                 style="parallel",
                 label_format=None,
                 label_sum=False,
                 legend_names=None,
                 legend_position="top-right",
                 legend_adjust_x=0,
                 legend_adjust_y=0,
                 main_title="",
                 main_title_font_name=None,
                 main_title_font_size=None,
                 main_title_font_color=None,
                 x_desc=None,
                 y_desc=None,
                 cat_label_angle=30,
                 cat_label_all=False):
        BarChart.__init__(self)

        if self._flipXY:
            self.categoryAxis = YCategoryAxisWithDesc(desc=y_desc)
            self.valueAxis = XValueAxisWithDesc(desc=x_desc)
        else:
            self.categoryAxis = XCategoryAxisWithDesc(desc=x_desc)
            self.valueAxis = YValueAxisWithDesc(desc=y_desc)

        if style not in ["stacked", "parallel"]:
            style = "parallel"
        self.categoryAxis.style = style

        self.valueAxis.visibleGrid = 1
        self.valueAxis.gridStrokeColor = colors.Color(0.5, 0.5, 0.5, 0.5)
        self.valueAxis.gridStrokeWidth = 1

        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.data = data
        self.strokeColor = colors.black
        self.categoryAxis.labels.boxAnchor = 'ne'
        # self.categoryAxis.labels.dx = 0
        # self.categoryAxis.labels.dy = 0
        self.categoryAxis.labels.angle = cat_label_angle
        # self.categoryAxis.labels.boxFillColor = colors.Color(1, 0, 0, 1)

        if cat_label_all is False:
            cat_names_num = len(cat_names)
            show_cat_num = 4
            if cat_names_num > show_cat_num:
                gap_num = int(cat_names_num / show_cat_num)
                for i in range(cat_names_num):
                    if i % gap_num != 0:
                        cat_names[i] = ""
        self.categoryAxis.categoryNames = cat_names

        self._lable_sum = []
        if label_format is not None:
            self.barLabelFormat = label_format
            if len(data) > 1 and style == "stacked":
                if label_sum:
                    self._cal_col_sum()

                    self.barLabels.boxTarget = "hi"
                    self.barLabels.nudge = 15
                else:
                    self.barLabels.boxTarget = "mid"
            else:
                self.barLabels.boxTarget = "hi"
                self.barLabels.nudge = 15

        min_value, max_value, step = self.get_limit_value(step_count)

        self.valueAxis.valueMin = min_value
        self.valueAxis.valueMax = max_value
        self.valueAxis.valueStep = step

        self.drawLegend = False
        self.legendCategoryNames = None
        if legend_names is not None and isListOfStrings(legend_names) is True:
            self.drawLegend = True
            self.legendCategoryNames = legend_names
        self.legendPositionType = legend_position
        self.legendAdjustX = legend_adjust_x
        self.legendAdjustY = legend_adjust_y
        self.legendFontSize = 7

        self.titleMain = main_title
        self.titleMainFontName = DefaultFontName
        self.titleMainFontSize = STATE_DEFAULTS['fontSize']
        self.titleMainFontColor = colors.black
        if main_title_font_name is not None:
            self.titleMainFontName = main_title_font_name
        if main_title_font_size is not None:
            self.titleMainFontSize = main_title_font_size
        if main_title_font_color is not None:
            self.titleMainFontColor = main_title_font_color

        self.x_labels_height = 0
        self.y_labels_height = 0

    def _cal_col_sum(self):
        for i in range(len(self.data[0])):
            self._lable_sum.append(0)
        for d in self.data:
            idx = 0
            for i in d:
                self._lable_sum[idx] += i
                idx += 1

    def get_limit_value(self, step_count):
        min_value = 0xffffffff
        max_value = 0 - min_value

        _data = []
        if self.categoryAxis.style == "stacked":
            flag = True
            for d in self.data:
                idx = 0
                for i in d:
                    if flag:
                        _data.append(i)
                    else:
                        _data[idx] += i
                    idx += 1
                flag = False

            for d in _data:
                if d > max_value:
                    max_value = d
            for d in self.data:
                for i in d:
                    if i < min_value:
                        min_value = i
        else:
            _data = self.data[:]

            for d in _data:
                for i in d:
                    if i > max_value:
                        max_value = i
                    if i < min_value:
                        min_value = i

        max_value += int(max_value / 10)
        max_value = int(max_value / 5) * 5
        min_value -= int(min_value / 10)
        min_value = int(min_value / 5) * 5

        step = int((max_value - min_value) / step_count)
        step = int(step / 5 + 1) * 5

        max_value = min_value + (step * step_count)

        return min_value, max_value, step

    def set_bar_color(self):
        if self.legendCategoryNames is None:
            self.legendCategoryNames = []
        legend_num = len(self.legendCategoryNames)
        data_num = len(self.data)
        for i in range(data_num):
            bar = self.bars[i]
            bar.strokeColor = ALL_COLORS[i]
            bar.fillColor = ALL_COLORS[i]
            if i >= legend_num:
                self.legendCategoryNames.append("unknown")

        legend_num = len(self.legendCategoryNames)
        temp_category_names = self.legendCategoryNames[:]
        if legend_num >= 1:
            self.legendCategoryNames = []
            color_name_pairs = [(0, name) for name in temp_category_names]

            legend_width = ChartsLegend.calc_legend_width(
                color_name_pairs, 10, 10, DefaultFontName, self.legendFontSize)
            per_legend_width = int(legend_width / legend_num)
            legend_num_per_row = int(self.width / per_legend_width)
            index = 0
            row_names = []
            for name in temp_category_names:
                row_names.append(name)
                index += 1
                if index == legend_num_per_row:
                    index = 0
                    self.legendCategoryNames.append(row_names)
                    row_names = []
            if len(row_names) > 0:
                self.legendCategoryNames.append(row_names)
        else:
            self.legendCategoryNames = temp_category_names

    def _draw_legend(self, g):
        legend_count = 0
        for i in range(len(self.legendCategoryNames)):
            legend = ChartsLegend()

            legend.positionType = self.legendPositionType
            if self.legendPositionType != "null":
                if self.legendPositionType in [
                        "bottom-left", "bottom-mid", "bottom-right"
                ]:
                    legend.backgroundRect = \
                        Rect(self.x,
                             self.y + legend.bottom_gap - self.x_labels_height - 15 - ((i + 1) * legend.fontSize),
                             self.width, self.height)
                else:
                    legend.backgroundRect = Rect(
                        self.x, self.y + (i * legend.fontSize * 1.2),
                        self.width, self.height)

            legend.adjustX = self.legendAdjustX
            legend.adjustY = self.legendAdjustY

            legend.fontSize = self.legendFontSize

            legend.colorNamePairs = []
            for j in range(len(self.legendCategoryNames[i])):
                legend.colorNamePairs.append((ALL_COLORS[legend_count + j],
                                              self.legendCategoryNames[i][j]))
            legend_count += len(self.legendCategoryNames[i])

            g.add(legend)

    def _get_label_sum_text(self, row_no, col_no):
        """
        return formatted label text
        :param row_no:
        :param col_no:
        :return:
        """
        len_row = len(self.data)
        if row_no != len_row - 1:
            return None

        text = self._lable_sum[col_no]

        label_fmt = self.barLabelFormat
        if isinstance(label_fmt, (list, tuple)):
            label_fmt = label_fmt[row_no]
            if isinstance(label_fmt, (list, tuple)):
                label_fmt = label_fmt[col_no]

        if label_fmt is None:
            label_text = None
        elif label_fmt == 'values':
            label_text = text
        elif isStr(label_fmt):
            label_text = label_fmt % text
        elif hasattr(label_fmt, '__call__'):
            label_text = label_fmt(text)
        else:
            msg = "Unknown formatter type %s, expected string or function" % label_fmt
            raise Exception(msg)
        return label_text

    def _addBarLabel(self, g, row_no, col_no, x, y, width, height):
        if self._lable_sum:
            text = self._get_label_sum_text(row_no, col_no)
        else:
            text = self._getLabelText(row_no, col_no)
        if text:
            self._addLabel(text, self.barLabels[(row_no, col_no)], g, row_no,
                           col_no, x, y, width, height)

    def draw(self):
        self.set_bar_color()
        if self.drawLegend is True:
            if self.legendPositionType in [
                    "bottom-left", "bottom-mid", "bottom-right"
            ]:
                row_count = len(self.legendCategoryNames) + 1
                self.height -= row_count * self.legendFontSize
                self.y += row_count * self.legendFontSize

        g = BarChart.draw(self)

        if self.drawLegend is True:
            self._draw_legend(g)

        if self.titleMain != "":
            title = String(0, 0, self.titleMain)
            title.fontSize = self.titleMainFontSize
            title.fontName = self.titleMainFontName
            title.fillColor = self.titleMainFontColor
            title.textAnchor = 'start'
            # title.x = self.x - 20
            # title.y = self.y + self.height + 20
            title.x = 0
            title.y = self.y + self.height + 20

            g.add(title)

        return g
Example #18
0
class QrCodeWidget(Widget):
    codeName = "QR"
    _attrMap = AttrMap(
        BASE=Widget,
        value=AttrMapValue(isUnicodeOrQRList, desc='QRCode data'),
        x=AttrMapValue(isNumber, desc='x-coord'),
        y=AttrMapValue(isNumber, desc='y-coord'),
        barFillColor=AttrMapValue(isColor, desc='bar color'),
        barWidth=AttrMapValue(
            isNumber,
            desc='Width of bars.'),  # maybe should be named just width?
        barHeight=AttrMapValue(
            isNumber,
            desc='Height of bars.'),  # maybe should be named just height?
        barBorder=AttrMapValue(
            isNumber,
            desc='Width of QR border.'),  # maybe should be named qrBorder?
        barLevel=AttrMapValue(
            isLevel, desc='QR Code level.'),  # maybe should be named qrLevel
        qrVersion=AttrMapValue(isNumberOrNone,
                               desc='QR Code version. None for auto'),
        # Below are ignored, they make no sense
        barStrokeWidth=AttrMapValue(isNumber, desc='Width of bar borders.'),
        barStrokeColor=AttrMapValue(isColor, desc='Color of bar borders.'),
    )
    x = 0
    y = 0
    barFillColor = colors.black
    barStrokeColor = None
    barStrokeWidth = 0
    barHeight = 32 * mm
    barWidth = 32 * mm
    barBorder = 4
    barLevel = 'L'
    qrVersion = None
    value = None

    def __init__(self, value='Hello World', **kw):
        self.value = isUnicodeOrQRList.normalize(value)
        for k, v in kw.items():
            setattr(self, k, v)

        ec_level = getattr(qrencoder.QRErrorCorrectLevel, self.barLevel)

        self.__dict__['qr'] = qrencoder.QRCode(self.qrVersion, ec_level)

        if isUnicode(self.value):
            self.addData(self.value)
        elif self.value:
            for v in self.value:
                self.addData(v)

    def addData(self, value):
        self.qr.addData(value)

    def draw(self):
        self.qr.make()

        g = Group()

        color = self.barFillColor
        border = self.barBorder
        width = self.barWidth
        height = self.barHeight
        x = self.x
        y = self.y

        g.add(SRect(x, y, width, height, fillColor=None))

        moduleCount = self.qr.getModuleCount()
        minwh = float(min(width, height))
        boxsize = minwh / (moduleCount + border * 2.0)
        offsetX = x + (width - minwh) / 2.0
        offsetY = y + (minwh - height) / 2.0

        for r, row in enumerate(self.qr.modules):
            row = map(bool, row)
            c = 0
            for t, tt in itertools.groupby(row):
                isDark = t
                count = len(list(tt))
                if isDark:
                    x = (c + border) * boxsize
                    y = (r + border + 1) * boxsize
                    s = SRect(offsetX + x,
                              offsetY + height - y,
                              count * boxsize,
                              boxsize,
                              fillColor=color)
                    g.add(s)
                c += count

        return g
Example #19
0
class PlotArea(Widget):
    "Abstract base class representing a chart's plot area, pretty unusable by itself."
    _attrMap = AttrMap(
        x = AttrMapValue(isNumber, desc='X position of the lower-left corner of the chart.'),
        y = AttrMapValue(isNumber, desc='Y position of the lower-left corner of the chart.'),
        width = AttrMapValue(isNumber, desc='Width of the chart.'),
        height = AttrMapValue(isNumber, desc='Height of the chart.'),
        strokeColor = AttrMapValue(isColorOrNone, desc='Color of the plot area border.'),
        strokeWidth = AttrMapValue(isNumber, desc='Width plot area border.'),
        fillColor = AttrMapValue(isColorOrNone, desc='Color of the plot area interior.'),
        background = AttrMapValue(isNoneOrShape, desc='Handle to background object e.g. Rect(0,0,width,height).'),
        debug = AttrMapValue(isNumber, desc='Used only for debugging.'),
        )

    def __init__(self):
        self.x = 20
        self.y = 10
        self.height = 85
        self.width = 180
        self.strokeColor = None
        self.strokeWidth = 1
        self.fillColor = None
        self.background = None
        self.debug = 0

    def makeBackground(self):
        if self.background is not None:
            BG = self.background
            if isinstance(BG,Group):
                g = BG
                for bg in g.contents:
                    bg.x = self.x
                    bg.y = self.y
                    bg.width = self.width
                    bg.height = self.height
            else:
                g = Group()
                if type(BG) not in (type(()),type([])): BG=(BG,)
                for bg in BG:
                    bg.x = self.x
                    bg.y = self.y
                    bg.width = self.width
                    bg.height = self.height
                    g.add(bg)
            return g
        else:
            strokeColor,strokeWidth,fillColor=self.strokeColor, self.strokeWidth, self.fillColor
            if (strokeWidth and strokeColor) or fillColor:
                g = Group()
                _3d_dy = getattr(self,'_3d_dy',None)
                x = self.x
                y = self.y
                h = self.height
                w = self.width
                if _3d_dy is not None:
                    _3d_dx = self._3d_dx
                    if fillColor and not strokeColor:
                        from reportlab.lib.colors import Blacker
                        c = Blacker(fillColor, getattr(self,'_3d_blacken',0.7))
                    else:
                        c = strokeColor
                    if not strokeWidth: strokeWidth = 0.5
                    if fillColor or strokeColor or c:
                        bg = Polygon([x,y,x,y+h,x+_3d_dx,y+h+_3d_dy,x+w+_3d_dx,y+h+_3d_dy,x+w+_3d_dx,y+_3d_dy,x+w,y],
                            strokeColor=strokeColor or c or grey, strokeWidth=strokeWidth, fillColor=fillColor)
                        g.add(bg)
                        g.add(Line(x,y,x+_3d_dx,y+_3d_dy, strokeWidth=0.5, strokeColor=c))
                        g.add(Line(x+_3d_dx,y+_3d_dy, x+_3d_dx,y+h+_3d_dy,strokeWidth=0.5, strokeColor=c))
                        fc = Blacker(c, getattr(self,'_3d_blacken',0.8))
                        g.add(Polygon([x,y,x+_3d_dx,y+_3d_dy,x+w+_3d_dx,y+_3d_dy,x+w,y],
                            strokeColor=strokeColor or c or grey, strokeWidth=strokeWidth, fillColor=fc))
                        bg = Line(x+_3d_dx,y+_3d_dy, x+w+_3d_dx,y+_3d_dy,strokeWidth=0.5, strokeColor=c)
                    else:
                        bg = None
                else:
                    bg = Rect(x, y, w, h,
                        strokeColor=strokeColor, strokeWidth=strokeWidth, fillColor=fillColor)
                if bg: g.add(bg)
                return g
            else:
                return None
Example #20
0
class LegendedHorizontalLineChart(HorizontalLineChart):
    """A subclass of Legend for drawing legends with lines as the
    swatches rather than rectangles. Useful for lineCharts and
    linePlots. Should be similar in all other ways the the standard
    Legend class.
    """

    _attrMap = AttrMap(
        BASE=HorizontalLineChart,
        drawLegend=AttrMapValue(isBoolean, desc='If true draw legend.', advancedUsage=1),
        legendPositionType=AttrMapValue(
            OneOf(
                "null",
                "top-left", "top-mid", "top-right",
                "bottom-left", "bottom-mid", "bottom-right"
            ),
            desc="The position of LinLegend."),
        legendAdjustX=AttrMapValue(isNumber, desc='xxx.'),
        legendAdjustY=AttrMapValue(isNumber, desc='xxx.'),
        legendCategoryNames=AttrMapValue(isListOfStringsOrNone, desc='List of legend category names.'),
        titleMain=AttrMapValue(isString, desc='main title text.'),
        titleMainFontName=AttrMapValue(isString, desc='main title font name.'),
        titleMainFontSize=AttrMapValue(isNumberInRange(0, 100), desc='main title font size.'),
        titleMainFontColor=AttrMapValue(isColor, desc='main title font color.'),
        legendFontSize=AttrMapValue(isNumberInRange(0, 100), desc='legend text font size.'),
        labels_height=AttrMapValue(isNumberInRange(0, 100), desc='the max height of x-labels.')
    )

    def __init__(self):
        HorizontalLineChart.__init__(self)

        self.drawLegend = False
        self.legendPositionType = "null"
        self.legendCategoryNames = None
        self.legendAdjustX = 0
        self.legendAdjustY = 0
        self.titleMain = ""
        self.titleMainFontColor = colors.gray
        self.titleMainFontName = DefaultFontName
        self.titleMainFontSize = STATE_DEFAULTS['fontSize']

        self.legendFontSize = 7

        self.labels_height = 0

    def set_line_color(self):
        if self.legendCategoryNames is None:
            self.legendCategoryNames = []
        legend_num = len(self.legendCategoryNames)
        data_num = len(self.data)
        for i in range(data_num):
            line = self.lines[i]
            line.strokeColor = ALL_COLORS[i]
            if i >= legend_num:
                self.legendCategoryNames.append("unknown")

        legend_num = len(self.legendCategoryNames)
        temp_category_names = self.legendCategoryNames[:]
        if legend_num >= 1:
            self.legendCategoryNames = []
            color_name_pairs = [(0, name) for name in temp_category_names]

            legend_width = ChartsLegend.calc_legend_width(
                color_name_pairs, 10, 10, DefaultFontName, self.legendFontSize)
            per_legend_width = int(legend_width / legend_num)
            legend_num_per_row = int(self.width / per_legend_width)
            index = 0
            row_names = []
            for name in temp_category_names:
                row_names.append(name)
                index += 1
                if index == legend_num_per_row:
                    index = 0
                    self.legendCategoryNames.append(row_names)
                    row_names = []
            if len(row_names) > 0:
                self.legendCategoryNames.append(row_names)
        else:
            self.legendCategoryNames = temp_category_names

    def _calc_labels_size(self):
        max_width = 0
        index = 0
        for label_text in self.categoryAxis.categoryNames:
            tmp_width = get_string_width(label_text, self.categoryAxis.labels.fontName,
                                         self.categoryAxis.labels.fontSize)
            if tmp_width > max_width:
                max_width = tmp_width

            if self.categoryAxis.labels[index].angle % 90 == 0:
                self.categoryAxis.labels[index].dx = \
                    int(tmp_width * math.cos(self.categoryAxis.labels[index].angle / 180 * math.pi) / 2) - \
                    int(self.categoryAxis.labels.fontSize *
                        math.sin(self.categoryAxis.labels[index].angle / 180 * math.pi)
                        / 2)
            index += 1

        self.labels_height = \
            int(max_width * math.sin(self.categoryAxis.labels.angle / 180 * math.pi)) + \
            int(self.categoryAxis.labels.fontSize * math.cos(self.categoryAxis.labels.angle / 180 * math.pi))

        return self.labels_height

    def _adjust_positon(self):
        self.x = 30
        if self.labels_height > 20:
            self.y = self.labels_height + 10
        else:
            self.y = 30
        self.width -= self.x + 30
        self.height -= self.y + self.titleMainFontSize + 20

    def draw(self):
        self._calc_labels_size()
        self._adjust_positon()

        self.set_line_color()
        if self.drawLegend is True:
            if self.legendPositionType in ["bottom-left", "bottom-mid", "bottom-right"]:
                row_count = len(self.legendCategoryNames) + 1
                self.height -= row_count * self.legendFontSize
                self.y += row_count * self.legendFontSize

        g = HorizontalLineChart.draw(self)

        if self.drawLegend:
            legend_count = 0
            for i in range(len(self.legendCategoryNames)):
                legend = ChartsLegend()

                legend.positionType = self.legendPositionType
                if self.legendPositionType != "null":
                    if self.legendPositionType in ["bottom-left", "bottom-mid", "bottom-right"]:
                        legend.backgroundRect = \
                            Rect(self.x,
                                 self.y + legend.bottom_gap - self.labels_height - 15 - ((i+1) * legend.fontSize),
                                 self.width, self.height)
                    else:
                        legend.backgroundRect = Rect(self.x, self.y - (i * legend.fontSize * 1.2),
                                                     self.width, self.height)

                legend.adjustX = self.legendAdjustX
                legend.adjustY = self.legendAdjustY

                legend.fontSize = self.legendFontSize

                legend.colorNamePairs = []
                for j in range(len(self.legendCategoryNames[i])):
                    legend.colorNamePairs.append((ALL_COLORS[legend_count + j],
                                                  self.legendCategoryNames[i][j]))
                legend_count += len(self.legendCategoryNames[i])

                g.add(legend)

        if self.titleMain != "":
            title = String(0, 0, self.titleMain)
            title.fontSize = self.titleMainFontSize
            title.fontName = self.titleMainFontName
            title.fillColor = self.titleMainFontColor
            title.textAnchor = 'start'
            # title.x = self.x - 20
            title.x = 0
            title.y = self.y + self.height + 20

            g.add(title)

        return g
Example #21
0
class Grid(Widget):
    """This makes a rectangular grid of equidistant stripes.

    The grid contains an outer border rectangle, and stripes
    inside which can be drawn with lines and/or as solid tiles.
    The drawing order is: outer rectangle, then lines and tiles.

    The stripes' width is indicated as 'delta'. The sequence of
    stripes can have an offset named 'delta0'. Both values need
    to be positive!
    """

    _attrMap = AttrMap(
        x=AttrMapValue(isNumber, desc="The grid's lower-left x position."),
        y=AttrMapValue(isNumber, desc="The grid's lower-left y position."),
        width=AttrMapValue(isNumber, desc="The grid's width."),
        height=AttrMapValue(isNumber, desc="The grid's height."),
        orientation=AttrMapValue(
            OneOf(('vertical', 'horizontal')),
            desc='Determines if stripes are vertical or horizontal.'),
        useLines=AttrMapValue(
            OneOf((0, 1)), desc='Determines if stripes are drawn with lines.'),
        useRects=AttrMapValue(
            OneOf((0, 1)),
            desc='Determines if stripes are drawn with solid rectangles.'),
        delta=AttrMapValue(isNumber,
                           desc='Determines the width/height of the stripes.'),
        delta0=AttrMapValue(
            isNumber,
            desc='Determines the stripes initial width/height offset.'),
        deltaSteps=AttrMapValue(isListOfNumbers,
                                desc='List of deltas to be used cyclically.'),
        stripeColors=AttrMapValue(
            isListOfColors,
            desc='Colors applied cyclically in the right or upper direction.'),
        fillColor=AttrMapValue(isColorOrNone,
                               desc='Background color for entire rectangle.'),
        strokeColor=AttrMapValue(isColorOrNone, desc='Color used for lines.'),
        strokeWidth=AttrMapValue(isNumber, desc='Width used for lines.'),
        rectStrokeColor=AttrMapValue(isColorOrNone,
                                     desc='Color for outer rect stroke.'),
        rectStrokeWidth=AttrMapValue(isNumberOrNone,
                                     desc='Width for outer rect stroke.'),
    )

    def __init__(self):
        self.x = 0
        self.y = 0
        self.width = 100
        self.height = 100
        self.orientation = 'vertical'
        self.useLines = 0
        self.useRects = 1
        self.delta = 20
        self.delta0 = 0
        self.deltaSteps = []
        self.fillColor = colors.white
        self.stripeColors = [colors.red, colors.green, colors.blue]
        self.strokeColor = colors.black
        self.strokeWidth = 2

    def demo(self):
        D = Drawing(100, 100)

        g = Grid()
        D.add(g)

        return D

    def makeOuterRect(self):
        strokeColor = getattr(self, 'rectStrokeColor', self.strokeColor)
        strokeWidth = getattr(self, 'rectStrokeWidth', self.strokeWidth)
        if self.fillColor or (strokeColor and strokeWidth):
            rect = Rect(self.x, self.y, self.width, self.height)
            rect.fillColor = self.fillColor
            rect.strokeColor = strokeColor
            rect.strokeWidth = strokeWidth
            return rect
        else:
            return None

    def makeLinePosList(self, start, isX=0):
        "Returns a list of positions where to place lines."

        w, h = self.width, self.height
        if isX:
            length = w
        else:
            length = h
        if self.deltaSteps:
            r = [start + self.delta0]
            i = 0
            while 1:
                if r[-1] > start + length:
                    del r[-1]
                    break
                r.append(r[-1] + self.deltaSteps[i % len(self.deltaSteps)])
                i = i + 1
        else:
            r = frange(start + self.delta0, start + length, self.delta)

        r.append(start + length)
        if self.delta0 != 0:
            r.insert(0, start)
        #print 'Grid.makeLinePosList() -> %s' % r
        return r

    def makeInnerLines(self):
        # inner grid lines
        group = Group()

        w, h = self.width, self.height

        if self.useLines == 1:
            if self.orientation == 'vertical':
                r = self.makeLinePosList(self.x, isX=1)
                for x in r:
                    line = Line(x, self.y, x, self.y + h)
                    line.strokeColor = self.strokeColor
                    line.strokeWidth = self.strokeWidth
                    group.add(line)
            elif self.orientation == 'horizontal':
                r = self.makeLinePosList(self.y, isX=0)
                for y in r:
                    line = Line(self.x, y, self.x + w, y)
                    line.strokeColor = self.strokeColor
                    line.strokeWidth = self.strokeWidth
                    group.add(line)

        return group

    def makeInnerTiles(self):
        # inner grid lines
        group = Group()

        w, h = self.width, self.height

        # inner grid stripes (solid rectangles)
        if self.useRects == 1:
            cols = self.stripeColors

            if self.orientation == 'vertical':
                r = self.makeLinePosList(self.x, isX=1)
            elif self.orientation == 'horizontal':
                r = self.makeLinePosList(self.y, isX=0)

            dist = makeDistancesList(r)

            i = 0
            for j in range(len(dist)):
                if self.orientation == 'vertical':
                    x = r[j]
                    stripe = Rect(x, self.y, dist[j], h)
                elif self.orientation == 'horizontal':
                    y = r[j]
                    stripe = Rect(self.x, y, w, dist[j])
                stripe.fillColor = cols[i % len(cols)]
                stripe.strokeColor = None
                group.add(stripe)
                i = i + 1

        return group

    def draw(self):
        # general widget bits
        group = Group()

        group.add(self.makeOuterRect())
        group.add(self.makeInnerTiles())
        group.add(self.makeInnerLines(), name='_gridLines')

        return group
Example #22
0
class ShadedRect(Widget):
    """This makes a rectangle with shaded colors between two colors.

    Colors are interpolated linearly between 'fillColorStart'
    and 'fillColorEnd', both of which appear at the margins.
    If 'numShades' is set to one, though, only 'fillColorStart'
    is used.
    """

    _attrMap = AttrMap(
        x=AttrMapValue(isNumber, desc="The grid's lower-left x position."),
        y=AttrMapValue(isNumber, desc="The grid's lower-left y position."),
        width=AttrMapValue(isNumber, desc="The grid's width."),
        height=AttrMapValue(isNumber, desc="The grid's height."),
        orientation=AttrMapValue(
            OneOf(('vertical', 'horizontal')),
            desc='Determines if stripes are vertical or horizontal.'),
        numShades=AttrMapValue(isNumber,
                               desc='The number of interpolating colors.'),
        fillColorStart=AttrMapValue(isColorOrNone,
                                    desc='Start value of the color shade.'),
        fillColorEnd=AttrMapValue(isColorOrNone,
                                  desc='End value of the color shade.'),
        strokeColor=AttrMapValue(isColorOrNone,
                                 desc='Color used for border line.'),
        strokeWidth=AttrMapValue(isNumber, desc='Width used for lines.'),
        cylinderMode=AttrMapValue(isBoolean,
                                  desc='True if shading reverses in middle.'),
    )

    def __init__(self, **kw):
        self.x = 0
        self.y = 0
        self.width = 100
        self.height = 100
        self.orientation = 'vertical'
        self.numShades = 20
        self.fillColorStart = colors.pink
        self.fillColorEnd = colors.black
        self.strokeColor = colors.black
        self.strokeWidth = 2
        self.cylinderMode = 0
        self.setProperties(kw)

    def demo(self):
        D = Drawing(100, 100)
        g = ShadedRect()
        D.add(g)

        return D

    def _flipRectCorners(self):
        "Flip rectangle's corners if width or height is negative."
        x, y, width, height, fillColorStart, fillColorEnd = self.x, self.y, self.width, self.height, self.fillColorStart, self.fillColorEnd
        if width < 0 and height > 0:
            x = x + width
            width = -width
            if self.orientation == 'vertical':
                fillColorStart, fillColorEnd = fillColorEnd, fillColorStart
        elif height < 0 and width > 0:
            y = y + height
            height = -height
            if self.orientation == 'horizontal':
                fillColorStart, fillColorEnd = fillColorEnd, fillColorStart
        elif height < 0 and height < 0:
            x = x + width
            width = -width
            y = y + height
            height = -height
        return x, y, width, height, fillColorStart, fillColorEnd

    def draw(self):
        # general widget bits
        group = Group()
        x, y, w, h, c0, c1 = self._flipRectCorners()
        numShades = self.numShades
        if self.cylinderMode:
            if not numShades % 2: numShades = numShades + 1
            halfNumShades = (numShades - 1) / 2 + 1
        num = float(numShades)  # must make it float!
        vertical = self.orientation == 'vertical'
        if vertical:
            if numShades == 1:
                V = [x]
            else:
                V = frange(x, x + w, w / num)
        else:
            if numShades == 1:
                V = [y]
            else:
                V = frange(y, y + h, h / num)

        for v in V:
            stripe = vertical and Rect(v, y, w / num, h) or Rect(
                x, v, w, h / num)
            if self.cylinderMode:
                if V.index(v) >= halfNumShades:
                    col = colors.linearlyInterpolatedColor(
                        c1, c0, V[halfNumShades], V[-1], v)
                else:
                    col = colors.linearlyInterpolatedColor(
                        c0, c1, V[0], V[halfNumShades], v)
            else:
                col = colors.linearlyInterpolatedColor(c0, c1, V[0], V[-1], v)
            stripe.fillColor = col
            stripe.strokeColor = col
            stripe.strokeWidth = 1
            group.add(stripe)
        if self.strokeColor and self.strokeWidth >= 0:
            rect = Rect(x, y, w, h)
            rect.strokeColor = self.strokeColor
            rect.strokeWidth = self.strokeWidth
            rect.fillColor = None
            group.add(rect)
        return group
Example #23
0
class DoubleGrid(Widget):
    """This combines two ordinary Grid objects orthogonal to each other.
    """

    _attrMap = AttrMap(
        x=AttrMapValue(isNumber, desc="The grid's lower-left x position."),
        y=AttrMapValue(isNumber, desc="The grid's lower-left y position."),
        width=AttrMapValue(isNumber, desc="The grid's width."),
        height=AttrMapValue(isNumber, desc="The grid's height."),
        grid0=AttrMapValue(None, desc="The first grid component."),
        grid1=AttrMapValue(None, desc="The second grid component."),
    )

    def __init__(self):
        self.x = 0
        self.y = 0
        self.width = 100
        self.height = 100

        g0 = Grid()
        g0.x = self.x
        g0.y = self.y
        g0.width = self.width
        g0.height = self.height
        g0.orientation = 'vertical'
        g0.useLines = 1
        g0.useRects = 0
        g0.delta = 20
        g0.delta0 = 0
        g0.deltaSteps = []
        g0.fillColor = colors.white
        g0.stripeColors = [colors.red, colors.green, colors.blue]
        g0.strokeColor = colors.black
        g0.strokeWidth = 1

        g1 = Grid()
        g1.x = self.x
        g1.y = self.y
        g1.width = self.width
        g1.height = self.height
        g1.orientation = 'horizontal'
        g1.useLines = 1
        g1.useRects = 0
        g1.delta = 20
        g1.delta0 = 0
        g1.deltaSteps = []
        g1.fillColor = colors.white
        g1.stripeColors = [colors.red, colors.green, colors.blue]
        g1.strokeColor = colors.black
        g1.strokeWidth = 1

        self.grid0 = g0
        self.grid1 = g1


##    # This gives an AttributeError:
##    #   DoubleGrid instance has no attribute 'grid0'
##    def __setattr__(self, name, value):
##        if name in ('x', 'y', 'width', 'height'):
##            setattr(self.grid0, name, value)
##            setattr(self.grid1, name, value)

    def demo(self):
        D = Drawing(100, 100)
        g = DoubleGrid()
        D.add(g)
        return D

    def draw(self):
        group = Group()
        g0, g1 = self.grid0, self.grid1
        # Order groups to make sure both v and h lines
        # are visible (works only when there is only
        # one kind of stripes, v or h).
        G = g0.useRects == 1 and g1.useRects == 0 and (g0, g1) or (g1, g0)
        for g in G:
            group.add(g.makeOuterRect())
        for g in G:
            group.add(g.makeInnerTiles())
            group.add(g.makeInnerLines(), name='_gridLines')

        return group
Example #24
0
class ChartsLegend(LineLegend):
    """A subclass of Legend for drawing legends with lines as the
    swatches rather than rectangles. Useful for lineCharts and
    linePlots. Should be similar in all other ways the the standard
    Legend class.
    """

    _attrMap = AttrMap(
        BASE=LineLegend,
        positionType=AttrMapValue(OneOf("null", "top-left", "top-mid",
                                        "top-right", "bottom-left",
                                        "bottom-mid", "bottom-right", "right"),
                                  desc="The position of LinLegend."),
        backgroundRect=AttrMapValue(None, desc="The position of LinLegend."),
        adjustX=AttrMapValue(isNumber, desc='xxx.'),
        adjustY=AttrMapValue(isNumber, desc='xxx.'),
        bottom_gap=AttrMapValue(isNumber, desc='xxx.'))

    def __init__(self):
        LineLegend.__init__(self)

        self.positionType = "null"
        self.backgroundRect = None
        self.adjustX = 0
        self.adjustY = 0
        self.fontName = DefaultFontName
        self.deltax = 10
        self.deltay = 0
        self.boxAnchor = 'w'
        self.columnMaximum = 1
        self.yGap = 0
        self.fontSize = 7
        self.alignment = 'right'
        self.dxTextSpace = 5

        self.bottom_gap = 40

    @staticmethod
    def calc_legend_width(color_name_pairs,
                          dx,
                          deltax,
                          font_name,
                          font_size,
                          sub_cols=None):
        pairs_num = len(color_name_pairs)

        max_text_width = 0
        x_width = 0
        for x in color_name_pairs:
            if type(x[1]) is tuple:
                for str_i in x[1]:
                    tmp_width = stringWidth(str(str_i), font_name, font_size)
                    if sub_cols is not None and tmp_width < sub_cols[
                            0].minWidth:
                        tmp_width = sub_cols[0].minWidth
                    x_width += tmp_width
            else:
                str_x = x[1]
                x_width = stringWidth(str_x, font_name, font_size)
            if x_width > max_text_width:
                max_text_width = x_width
        total_text_width = (pairs_num - 1) * max_text_width + x_width

        legend_width = total_text_width + (dx * pairs_num) + (deltax *
                                                              pairs_num)

        return legend_width

    def draw(self):
        legend_width = self.calc_legend_width(self.colorNamePairs, self.dx,
                                              self.deltax, self.fontName,
                                              self.fontSize, self.subCols)

        if self.positionType != "null" and self.backgroundRect is not None:
            if self.positionType == "top-left":
                self.x = self.backgroundRect.x
                self.y = self.backgroundRect.y + self.backgroundRect.height
            elif self.positionType == "top-mid":
                self.x = self.backgroundRect.x + int(
                    self.backgroundRect.width / 2) - int(legend_width / 2)
                self.y = self.backgroundRect.y + self.backgroundRect.height
            elif self.positionType == "top-right":
                self.x = self.backgroundRect.x + self.backgroundRect.width - legend_width
                self.y = self.backgroundRect.y + self.backgroundRect.height
            elif self.positionType == "bottom-left":
                self.x = self.backgroundRect.x
                self.y = self.backgroundRect.y - self.bottom_gap
            elif self.positionType == "bottom-mid":
                self.x = self.backgroundRect.x + int(
                    self.backgroundRect.width / 2) - int(legend_width / 2)
                self.y = self.backgroundRect.y - self.bottom_gap
            elif self.positionType == "bottom-right":
                self.x = self.backgroundRect.x + self.backgroundRect.width - legend_width
                self.y = self.backgroundRect.y - self.bottom_gap
            elif self.positionType == "right":
                self.x = self.backgroundRect.x + self.backgroundRect.width + 10
                self.y = self.backgroundRect.y + self.backgroundRect.height

            self.x += self.adjustX
            self.y += self.adjustY

        return LineLegend.draw(self)