Пример #1
0
def _errorBarsCurve(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                    painter, clip):
    """Draw curve around error region."""
    if None not in (xmin, xmax, ymin, ymax):
        # non-filling brush
        painter.setBrush(qt4.QBrush())

        for xp, yp, xmn, ymn, xmx, ymx in itertools.izip(
                xplotter, yplotter, xmin, ymin, xmax, ymax):

            # break up curve into four arcs (for asym error bars)
            # qt geometry means we have to calculate lots
            # the big numbers are in 1/16 degrees
            painter.drawArc(
                qt4.QRectF(xp - (xmx - xp), yp - (yp - ymx), (xmx - xp) * 2,
                           (yp - ymx) * 2), 0, 1440)
            painter.drawArc(
                qt4.QRectF(xp - (xp - xmn), yp - (yp - ymx), (xp - xmn) * 2,
                           (yp - ymx) * 2), 1440, 1440)
            painter.drawArc(
                qt4.QRectF(xp - (xp - xmn), yp - (ymn - yp), (xp - xmn) * 2,
                           (ymn - yp) * 2), 2880, 1440)
            painter.drawArc(
                qt4.QRectF(xp - (xmx - xp), yp - (ymn - yp), (xmx - xp) * 2,
                           (ymn - yp) * 2), 4320, 1440)
Пример #2
0
    def drawShape(self, painter, rect):
        """Draw image."""
        s = self.settings

        # draw border and fill
        painter.drawRect(rect)

        # check to see whether image needs reloading
        image = None
        if s.filename != '' and os.path.isfile(s.filename):
            if (self.cachefilename != s.filename
                    or os.stat(s.filename) != self.cachestat):
                # update the image cache
                self.updateCachedImage()
                # clear any embedded image data
                self.settings.get('embeddedImageData').set('')
            image = self.cacheimage

        # or needs recreating from embedded data
        if s.filename == '{embedded}':
            if s.embeddedImageData is not self.cacheembeddata:
                self.updateCachedEmbedded()
            image = self.cacheimage

        # if no image, then use default image
        if (not image or image.isNull() or image.width() == 0
                or image.height() == 0):
            # load replacement image
            fname = os.path.join(utils.imagedir, 'button_imagefile.svg')
            r = qt4.QSvgRenderer(fname)
            r.render(painter, rect)

        else:
            # image rectangle
            irect = qt4.QRectF(image.rect())

            # preserve aspect ratio
            if s.aspect:
                xr = rect.width() / irect.width()
                yr = rect.height() / irect.height()

                if xr > yr:
                    rect = qt4.QRectF(
                        rect.left() +
                        (rect.width() - irect.width() * yr) * 0.5, rect.top(),
                        irect.width() * yr, rect.height())
                else:
                    rect = qt4.QRectF(
                        rect.left(),
                        rect.top() +
                        (rect.height() - irect.height() * xr) * 0.5,
                        rect.width(),
                        irect.height() * xr)

            # finally draw image
            painter.drawImage(rect, image, irect)
Пример #3
0
    def render(self):
        """Render the text."""

        if self.calcbounds is None:
            self.getBounds()

        p = self.painter
        p.save()
        if self.mmldoc is not None:
            p.translate(self.xi, self.yi)
            p.rotate(self.angle)
            # is drawn from bottom of box, not top
            p.translate(0, -self.size.height())
            p.scale(self.drawscale, self.drawscale)
            self.record.play(p)
        else:
            # display an error - must be a better way to do this
            p.setFont(qt4.QFont())
            p.setPen(qt4.QPen(qt4.QColor("red")))
            p.drawText(
                qt4.QRectF(self.xi, self.yi, 200, 200),
                qt4.Qt.AlignLeft | qt4.Qt.AlignTop | qt4.Qt.TextWordWrap,
                self.error)
        p.restore()

        return self.calcbounds
Пример #4
0
    def drawKeySymbol(self, number, painter, x, y, width, height):
        """Draw the plot symbol and/or line."""
        painter.save()
        cliprect = qt4.QRectF(qt4.QPointF(x, y),
                              qt4.QPointF(x + width, y + height))
        painter.setClipRect(cliprect)

        # draw sample error bar
        s = self.settings
        size = s.get('markerSize').convert(painter)
        style = s.errorStyle

        # make some fake error bar data to plot
        xv = s.get('xData').getData(self.document)
        yv = s.get('yData').getData(self.document)
        yp = y + height / 2
        xpts = N.array([x - width, x + width / 2, x + 2 * width])
        ypts = N.array([yp, yp, yp])

        # size of error bars in key
        errorsize = height * 0.4

        # make points for error bars (if any)
        if xv and xv.hasErrors():
            xneg = N.array(
                [x - width, x + width / 2 - errorsize, x + 2 * width])
            xpos = N.array(
                [x - width, x + width / 2 + errorsize, x + 2 * width])
        else:
            xneg = xpos = xpts
        if yv and yv.hasErrors():
            yneg = N.array([yp - errorsize, yp - errorsize, yp - errorsize])
            ypos = N.array([yp + errorsize, yp + errorsize, yp + errorsize])
        else:
            yneg = ypos = ypts

        # plot error bar
        painter.setPen(s.ErrorBarLine.makeQPenWHide(painter))
        for function in _errorBarFunctionMap[style]:
            function(style, xneg, xpos, yneg, ypos, xpts, ypts, s, painter,
                     cliprect)

        # draw line
        if not s.PlotLine.hide:
            painter.setPen(s.PlotLine.makeQPen(painter))
            painter.drawLine(qt4.QPointF(x, yp), qt4.QPointF(x + width, yp))

        # draw marker
        if not s.MarkerLine.hide or not s.MarkerFill.hide:
            if not s.MarkerFill.hide:
                painter.setBrush(s.MarkerFill.makeQBrush())

            if not s.MarkerLine.hide:
                painter.setPen(s.MarkerLine.makeQPen(painter))
            else:
                painter.setPen(qt4.QPen(qt4.Qt.NoPen))

            utils.plotMarker(painter, x + width / 2, yp, s.marker, size)

        painter.restore()
Пример #5
0
 def setClip(self, painter, bounds):
     '''Set clipping for graph.'''
     p = qt4.QPainterPath()
     p.addEllipse(
         qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                    qt4.QPointF(bounds[2], bounds[3])))
     painter.setClipPath(p)
Пример #6
0
    def draw(self, parentposn, painthelper, outerbounds=None):
        '''Update the margins before drawing.'''

        s = self.settings

        margins = (s.get('leftMargin').convert(painthelper),
                   s.get('topMargin').convert(painthelper),
                   s.get('rightMargin').convert(painthelper),
                   s.get('bottomMargin').convert(painthelper))

        bounds = self.computeBounds(parentposn, painthelper, margins=margins)
        maxbounds = self.computeBounds(parentposn, painthelper)

        # controls for adjusting graph margins
        painter = painthelper.painter(self, bounds)
        painthelper.setControlGraph(self, [
            controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper)
        ])

        # do no painting if hidden
        if s.hide:
            return bounds

        # set graph rectangle attributes
        path = qt4.QPainterPath()
        path.addRect(
            qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                       qt4.QPointF(bounds[2], bounds[3])))
        utils.brushExtFillPath(painter,
                               s.Background,
                               path,
                               stroke=s.Border.makeQPenWHide(painter))

        # do normal drawing of children
        # iterate over children in reverse order
        for c in reversed(self.children):
            c.draw(bounds, painthelper, outerbounds=outerbounds)

        # now need to find axes which aren't children, and draw those again
        axestodraw = set()
        childrennames = set()
        for c in self.children:
            childrennames.add(c.name)
            try:
                for axis in c.getAxesNames():
                    axestodraw.add(axis)
            except AttributeError:
                pass

        axestodraw = axestodraw - childrennames
        if axestodraw:
            # now redraw all these axes if they aren't children of us
            axeswidgets = self.getAxes(axestodraw)
            for w in axeswidgets:
                if w is not None:
                    w.draw(bounds, painthelper, outerbounds=outerbounds)

        return bounds
Пример #7
0
 def renderPage(self, size, dpi, painter):
     """Render page using paint helper to painter.
     This first renders to the helper, then to the painter
     """
     helper = painthelper.PaintHelper(size, dpi=dpi, directpaint=painter)
     painter.setClipRect(qt4.QRectF(qt4.QPointF(0, 0), qt4.QPointF(*size)))
     self.doc.paintTo(helper, self.pagenumber)
     painter.restore()
     painter.end()
Пример #8
0
    def draw(self, parentposn, painthelper, outerbounds=None):
        """Draw the function."""

        posn = GenericPlotter.draw(self,
                                   parentposn,
                                   painthelper,
                                   outerbounds=outerbounds)
        x1, y1, x2, y2 = posn
        s = self.settings

        # exit if hidden or function blank
        if s.hide or s.function.strip() == '':
            return

        # get axes widgets
        axes = self.parent.getAxes((s.xAxis, s.yAxis))

        # return if there's no proper axes
        if (None in axes or axes[0].settings.direction != 'horizontal'
                or axes[1].settings.direction != 'vertical'):
            return

        # clip data within bounds of plotter
        cliprect = self.clipAxesBounds(axes, posn)
        painter = painthelper.painter(self, posn, clip=cliprect)

        # get the points to plot by evaluating the function
        (xpts, ypts), (pxpts, pypts) = self.calcFunctionPoints(axes, posn)

        # draw the function line
        if pxpts is None or pypts is None:
            # not sure how to deal with errors here
            painter.setPen(setting.settingdb.color('error'))
            f = qt4.QFont()
            f.setPointSize(20)
            painter.setFont(f)
            painter.drawText(qt4.QRectF(x1, y1, x2 - x1,
                                        y2 - y1), qt4.Qt.AlignCenter,
                             "Cannot evaluate '%s'" % s.function)
        else:
            if not s.FillBelow.hide:
                self._fillRegion(painter, pxpts, pypts, posn, True, cliprect,
                                 s.FillBelow)

            if not s.FillAbove.hide:
                self._fillRegion(painter, pxpts, pypts, posn, False, cliprect,
                                 s.FillAbove)

            if not s.Line.hide:
                painter.setBrush(qt4.QBrush())
                painter.setPen(s.Line.makeQPen(painter))
                self._plotLine(painter, pxpts, pypts, posn, cliprect)
Пример #9
0
    def draw(self, posn, phelper, outerbounds=None):
        """Draw the text label."""

        s = self.settings
        d = self.document

        # exit if hidden
        if s.hide or s.Text.hide:
            return

        text = s.get('label').getData(d)

        xp, yp = self._getPlotterCoords(posn)
        if xp is None or yp is None:
            # we can't calculate coordinates
            return

        clip = None
        if s.clip:
            clip = qt4.QRectF(qt4.QPointF(posn[0], posn[1]),
                              qt4.QPointF(posn[2], posn[3]))
        painter = phelper.painter(self, posn, clip=clip)
        textpen = s.get('Text').makeQPen()
        painter.setPen(textpen)
        font = s.get('Text').makeQFont(painter)

        # we should only be able to move non-dataset labels
        isnotdataset = (not s.get('xPos').isDataset(d)
                        and not s.get('yPos').isDataset(d))

        controlgraphitems = []
        for index, (x, y, t) in enumerate(
                itertools.izip(xp, yp, itertools.cycle(text))):
            # render the text
            tbounds = utils.Renderer(painter, font, x, y, t,
                                     TextLabel.cnvtalignhorz[s.alignHorz],
                                     TextLabel.cnvtalignvert[s.alignVert],
                                     s.angle).render()

            # add cgi for adjustable positions
            if isnotdataset:
                cgi = controlgraph.ControlMovableBox(self,
                                                     tbounds,
                                                     phelper,
                                                     crosspos=(x, y))
                cgi.labelpt = (x, y)
                cgi.widgetposn = posn
                cgi.index = index
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Пример #10
0
    def checkHighlight(self):
        """Check to see whether box is over hightlight area.
        Returns (x, y) name or None if not."""

        rect = self.rect()
        rect.translate(self.pos())

        highlight = None
        highlightrect = qt4.QRectF(rect.left()-10, rect.top()-10, 20, 20)
        for name, point in self.highlightpoints.iteritems():
            if highlightrect.contains(point):
                highlight = name
                break
        return highlight
Пример #11
0
    def draw(self, posn, phelper, outerbounds=None):
        """Plot the data on a plotter."""

        s = self.settings

        # exit if hidden
        if s.hide:
            return

        # get points in plotter coordinates
        xp, yp = self._getPlotterCoords(posn)
        if xp is None or yp is None:
            # we can't calculate coordinates
            return

        x1, y1, x2, y2 = posn
        cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
        painter = phelper.painter(self, posn, clip=cliprect)

        pen = s.Line.makeQPenWHide(painter)
        pw = pen.widthF() * 2
        lineclip = qt4.QRectF(qt4.QPointF(x1 - pw, y1 - pw),
                              qt4.QPointF(x2 + pw, y2 + pw))

        # this is a hack as we generate temporary fake datasets
        path = qt4.QPainterPath()
        for xvals, yvals in document.generateValidDatasetParts(
                document.Dataset(xp), document.Dataset(yp)):

            poly = qt4.QPolygonF()
            utils.addNumpyToPolygonF(poly, xvals.data, yvals.data)
            clippedpoly = qt4.QPolygonF()
            utils.polygonClip(poly, lineclip, clippedpoly)
            path.addPolygon(clippedpoly)
            path.closeSubpath()

        utils.brushExtFillPath(painter, s.Fill, path, stroke=pen)
Пример #12
0
def _errorBarsDiamond(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                      painter, clip):
    """Draw diamond around error region."""
    if None not in (xmin, xmax, ymin, ymax):

        # expand clip by pen width (urgh)
        pw = painter.pen().widthF() * 2
        clip = qt4.QRectF(qt4.QPointF(clip.left() - pw,
                                      clip.top() - pw),
                          qt4.QPointF(clip.right() + pw,
                                      clip.bottom() + pw))

        path = qt4.QPainterPath()
        utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax,
                                    xmax, yplotter, xplotter, ymin)
        painter.setBrush(qt4.QBrush())
        painter.drawPath(path)
Пример #13
0
    def clipAxesBounds(self, axes, bounds):
        """Returns clipping rectange for start and stop values of axis."""

        # update cached coordinates of axes
        axes[0].plotterToDataCoords(bounds, N.array([]))
        axes[1].plotterToDataCoords(bounds, N.array([]))

        # get range
        x1, x2 = axes[0].coordParr1, axes[0].coordParr2
        if x1 > x2:
            x1, x2 = x2, x1
        y1, y2 = axes[1].coordParr2, axes[1].coordParr1
        if y1 > y2:
            y1, y2 = y2, y1

        # actually clip the data
        cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
        return cliprect
Пример #14
0
    def plotBars(self, painter, s, dsnum, clip, corners):
        """Plot a set of boxes."""
        # get style
        brush = s.BarFill.get('fills').returnBrushExtended(dsnum)
        pen = s.BarLine.get('lines').makePen(painter, dsnum)
        lw = pen.widthF() * 2

        # make clip box bigger to avoid lines showing
        extclip = qt4.QRectF(
            qt4.QPointF(clip.left() - lw,
                        clip.top() - lw),
            qt4.QPointF(clip.right() + lw,
                        clip.bottom() + lw))

        # plot bars
        path = qt4.QPainterPath()
        utils.addNumpyPolygonToPath(path, extclip, corners[0], corners[1],
                                    corners[2], corners[1], corners[2],
                                    corners[3], corners[0], corners[3])
        utils.brushExtFillPath(painter, brush, path, stroke=pen)
Пример #15
0
    def render(self, state):
        initx = state.x

        # draw material under bar
        Part.render(self, state)

        # draw circle over text with 1pt radius
        painter = state.painter
        height = state.fontMetrics().ascent()

        painter.save()
        circsize = state.getPixelsPerPt()
        painter.setBrush(qt4.QBrush(painter.pen().color()))
        painter.setPen(qt4.QPen(qt4.Qt.NoPen))

        x = 0.5 * (initx + state.x)
        y = state.y - height + circsize
        painter.drawEllipse(
            qt4.QRectF(qt4.QPointF(x - circsize, y - circsize),
                       qt4.QPointF(x + circsize, y + circsize)))
        painter.restore()
Пример #16
0
    def drawGraph(self, painter, bounds, datarange, outerbounds=None):
        '''Plot graph area and axes.'''

        s = self.settings
        if s.maxradius == 'Auto':
            self._maxradius = datarange[1]
        else:
            self._maxradius = s.maxradius

        self._xscale = (bounds[2] - bounds[0]) * 0.5
        self._yscale = (bounds[3] - bounds[1]) * 0.5
        self._xc = 0.5 * (bounds[0] + bounds[2])
        self._yc = 0.5 * (bounds[3] + bounds[1])

        path = qt4.QPainterPath()
        path.addEllipse(
            qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]),
                       qt4.QPointF(bounds[2], bounds[3])))
        utils.brushExtFillPath(painter,
                               s.Background,
                               path,
                               stroke=s.Border.makeQPenWHide(painter))
Пример #17
0
    def draw(self, parentposn, painthelper, outerbounds=None):
        """Draw the plotter. Clip graph inside bounds."""

        # document should pass us the page bounds
        x1, y1, x2, y2 = parentposn

        # find ranges of axes
        axisdependhelper = _AxisDependHelper(self)
        axisdependhelper.findPlotters()
        axisdependhelper.findAxisRanges()

        # store axis->plotter mappings in painter too (is this nasty?)
        painthelper.axisplottermap.update(axisdependhelper.axis_plotter_map)

        if self.settings.hide:
            bounds = self.computeBounds(parentposn, painthelper)
            return bounds

        clip = qt4.QRectF(qt4.QPointF(parentposn[0], parentposn[1]),
                          qt4.QPointF(parentposn[2], parentposn[3]))
        painter = painthelper.painter(self, parentposn, clip=clip)

        # clip to page
        bounds = widget.Widget.draw(self, parentposn, painthelper, parentposn)

        # w and h are non integer
        w = self.settings.get('width').convert(painter)
        h = self.settings.get('height').convert(painter)
        painthelper.setControlGraph(self, [
            controlgraph.ControlMarginBox(self, [0, 0, w, h],
                                          [-10000, -10000, 10000, 10000],
                                          painthelper,
                                          ismovable=False)
        ])

        return bounds
Пример #18
0
 def boundingRect(self):
     return qt4.QRectF(0, 0, 0, 0)
Пример #19
0
 def boundingRectChar(self, c):
     return qt4.QRectF(0, 0, self.height() * 0.5, self.height())
Пример #20
0
    def draw(self, posn, phelper, outerbounds=None):
        """Plot the key on a plotter."""

        s = self.settings
        d = self.document
        if s.hide:
            return

        # get positions of shapes
        width = s.get('width').getFloatArray(d)
        height = s.get('height').getFloatArray(d)
        rotate = s.get('rotate').getFloatArray(d)
        if width is None or height is None or rotate is None:
            return

        # translate coordinates from axes or relative values
        xpos, ypos = self._getPlotterCoords(posn)
        if xpos is None or ypos is None:
            # we can't calculate coordinates
            return

        # if a dataset is used, we can't use control items
        isnotdataset = (not s.get('xPos').isDataset(d)
                        and not s.get('yPos').isDataset(d)
                        and not s.get('width').isDataset(d)
                        and not s.get('height').isDataset(d)
                        and not s.get('rotate').isDataset(d))
        controlgraphitems = []

        clip = None
        if s.clip:
            clip = qt4.QRectF(qt4.QPointF(posn[0], posn[1]),
                              qt4.QPointF(posn[2], posn[3]))
        painter = phelper.painter(self, posn, clip=clip)

        # drawing settings for shape
        if not s.Border.hide:
            painter.setPen(s.get('Border').makeQPen(painter))
        else:
            painter.setPen(qt4.QPen(qt4.Qt.NoPen))

        # iterate over positions
        index = 0
        dx, dy = posn[2] - posn[0], posn[3] - posn[1]
        for x, y, w, h, r in itertools.izip(xpos, ypos, itertools.cycle(width),
                                            itertools.cycle(height),
                                            itertools.cycle(rotate)):
            wp, hp = dx * w, dy * h
            painter.save()
            painter.translate(x, y)
            if r != 0:
                painter.rotate(r)
            self.drawShape(painter, qt4.QRectF(-wp * 0.5, -hp * 0.5, wp, hp))
            painter.restore()

            if isnotdataset:
                cgi = controlgraph.ControlResizableBox(self, [x, y], [wp, hp],
                                                       r,
                                                       allowrotate=True)
                cgi.index = index
                cgi.widgetposn = posn
                index += 1
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Пример #21
0
 def boundingRect(self):
     """Intentionally zero bounding rect."""
     return qt4.QRectF(0, 0, 0, 0)
Пример #22
0
    def draw(self, parentposn, phelper, outerbounds=None,
             useexistingpainter=None):
        """Plot the axis on the painter.

        useexistingpainter is a hack so that a colorbar can reuse the
        drawing code here. If set to a painter, it will use this rather
        than opening a new one.
        """

        s = self.settings

        # recompute if document modified
        if self.docchangeset != self.document.changeset:
            self._computePlottedRange()

        posn = widget.Widget.draw(self, parentposn, phelper, outerbounds)
        self._updatePlotRange(posn)

        # get ready to draw
        if useexistingpainter is not None:
            painter = useexistingpainter
        else:
            painter = phelper.painter(self, posn)

        # make control item for axis
        phelper.setControlGraph(self, [ controlgraph.ControlAxisLine(
                    self, s.direction, self.coordParr1,
                    self.coordParr2, self.coordPerp, posn) ])

        # get tick vals
        coordticks = self._graphToPlotter(self.majortickscalc)
        coordminorticks = self._graphToPlotter(self.minortickscalc)

        # exit if axis is hidden
        if s.hide:
            return

        texttorender = []

        # multiplication factor if reflection on the axis is requested
        sign = 1
        if s.direction == 'vertical':
            sign *= -1
        if self.coordReflected:
            sign *= -1

        # plot gridlines
        if not s.MinorGridLines.hide:
            self._drawGridLines('MinorGridLines', painter, coordminorticks,
                                parentposn)
        if not s.GridLines.hide:
            self._drawGridLines('GridLines', painter, coordticks,
                                parentposn)

        # plot the line along the axis
        if not s.Line.hide:
            self._drawAxisLine(painter)

        # plot minor ticks
        if not s.MinorTicks.hide:
            self._drawMinorTicks(painter, coordminorticks)

        # keep track of distance from axis
        self._delta_axis = 0

        # plot major ticks
        if not s.MajorTicks.hide:
            self._drawMajorTicks(painter, coordticks)

        # plot tick labels
        suppresstext = self._suppressText(painter, parentposn, outerbounds)
        if not s.TickLabels.hide and not suppresstext:
            self._drawTickLabels(phelper, painter, coordticks, sign,
                                 outerbounds, texttorender)

        # draw an axis label
        if not s.Label.hide and not suppresstext:
            self._drawAxisLabel(painter, sign, outerbounds, texttorender)

        # mirror axis at other side of plot
        if s.autoMirror:
            self._autoMirrorDraw(posn, painter, coordticks, coordminorticks)

        # all the text is drawn at the end so that
        # we can check it doesn't overlap
        drawntext = qt4.QPainterPath()
        for r, pen in texttorender:
            bounds = r.getBounds()
            rect = qt4.QRectF(bounds[0], bounds[1], bounds[2]-bounds[0],
                              bounds[3]-bounds[1])

            if not drawntext.intersects(rect):
                painter.setPen(pen)
                r.render()
                drawntext.addRect(rect)
Пример #23
0
    def draw(self, parentposn, phelper, outerbounds = None):
        '''Update the margins before drawing.'''

        s = self.settings

        # exit if hidden
        if s.hide:
            return

        # get height of label font
        bounds = self.computeBounds(parentposn, phelper)
        painter = phelper.painter(self, parentposn)

        font = s.get('Label').makeQFont(phelper)
        painter.setFont(font)
        fontheight = utils.FontMetrics(font, painter.device()).height()

        horz = s.direction == 'horizontal'

        # use above to estimate width and height if necessary
        w = s.get('width')
        if w.isAuto():
            if horz:
                totalwidth = bounds[2] - bounds[0] - 2*fontheight
            else:
                totalwidth = fontheight
        else:
            totalwidth = w.convert(painter)

        h = s.get('height')
        if h.isAuto():
            if horz:
                totalheight = fontheight
            else:
                totalheight = bounds[3] - bounds[1] - 2*fontheight
        else:
            totalheight = h.convert(painter)

        # work out horizontal position
        h = s.horzPosn
        if h == 'left':
            bounds[0] += fontheight
            bounds[2] = bounds[0] + totalwidth
        elif h == 'right':
            bounds[2] -= fontheight
            bounds[0] = bounds[2] - totalwidth
        elif h == 'centre':
            delta = (bounds[2]-bounds[0]-totalwidth)/2.
            bounds[0] += delta
            bounds[2] -= delta
        elif h == 'manual':
            bounds[0] += (bounds[2]-bounds[0])*s.horzManual
            bounds[2] = bounds[0] + totalwidth

        # work out vertical position
        v = s.vertPosn
        if v == 'top':
            bounds[1] += fontheight
            bounds[3] = bounds[1] + totalheight 
        elif v == 'bottom':
            bounds[3] -= fontheight
            bounds[1] = bounds[3] - totalheight 
        elif v == 'centre':
            delta = (bounds[3]-bounds[1]-totalheight)/2.
            bounds[1] += delta
            bounds[3] -= delta
        elif v == 'manual':
            bounds[1] += (bounds[3]-bounds[1])*s.vertManual
            bounds[3] = bounds[1] + totalheight

        # this is ugly - update bounds in helper state
        phelper.states[self].bounds = bounds

        # do no painting if hidden or no image
        imgwidget = s.get('widgetName').findWidget()
        if s.hide:
            return bounds

        # update image if necessary with new settings
        if imgwidget is not None:
            # could find widget
            (minval, maxval,
             axisscale, img) = imgwidget.makeColorbarImage(s.direction)
        else:
            # couldn't find widget
            minval, maxval, axisscale = 0., 1., 'linear'
            img = None

        self.setAutoRange([minval, maxval])

        s.get('log').setSilent(axisscale == 'log')            

        # now draw image on axis...
        minpix, maxpix = self.graphToPlotterCoords(
            bounds, N.array([minval, maxval]) )

        if s.direction == 'horizontal':
            c = [ minpix, bounds[1], maxpix, bounds[3] ]
        else:
            c = [ bounds[0], maxpix, bounds[2], minpix ]
        r = qt4.QRectF(c[0], c[1], c[2]-c[0], c[3]-c[1])

        # really draw the img
        if img is not None:
            painter.drawImage(r, img)

        # if there's a border
        if not s.Border.hide:
            painter.setPen( s.get('Border').makeQPen(painter) )
            painter.setBrush( qt4.QBrush() )
            painter.drawRect( qt4.QRectF(bounds[0], bounds[1],
                                         bounds[2]-bounds[0],
                                         bounds[3]-bounds[1]) )

        # actually draw axis
        # we have to force position to full, as otherwise computeBounds
        # will mess up range if called twice
        savedposition = self.position
        self.position = (0., 0., 1., 1.)

        axis.Axis.draw(self, bounds, phelper, outerbounds=outerbounds,
                       useexistingpainter=painter)
        self.position = savedposition
Пример #24
0
        s = self.settings

        # exit if hidden
        if s.hide:
            return

        # ignore if function isn't sensible
        try:
            self.checker.check(s.function, s.variable)
        except RuntimeError, e:
            self.logEvalError(e)
            return

        x1, y1, x2, y2 = posn
        cliprect = qt4.QRectF( qt4.QPointF(x1, y1), qt4.QPointF(x2, y2) )
        painter = phelper.painter(self, posn)
        self.parent.setClip(painter, posn)

        apts, bpts = self.getFunctionPoints()
        px, py = self.parent.graphToPlotCoords(apts, bpts)

        # plot line
        painter.setBrush(qt4.QBrush())
        painter.setPen( s.PlotLine.makeQPenWHide(painter) )
        for x, y in utils.validLinePoints(px, py):
            if not s.Fill1.hide:
                self.parent.drawFillPts(painter, s.Fill1, cliprect, x, y)
            if not s.Fill2.hide:
                self.parent.drawFillPts(painter, s.Fill2, cliprect, x, y)
            if not s.PlotLine.hide:
Пример #25
0
    def drawAxes(self, painter, bounds, datarange, outerbounds=None):
        '''Plot axes.'''

        s = self.settings
        t = s.Tick

        if self._maxradius <= 0.:
            self._maxradius = 1.

        atick = AxisTicks(0,
                          self._maxradius,
                          t.number,
                          t.number * 4,
                          extendmin=False,
                          extendmax=False)
        atick.getTicks()
        majtick = atick.tickvals

        # draw ticks as circles
        if not t.hideannuli:
            painter.setPen(s.Tick.makeQPenWHide(painter))
            painter.setBrush(qt4.QBrush())
            for tick in majtick[1:]:
                radius = tick / self._maxradius

                painter.drawEllipse(
                    qt4.QRectF(
                        qt4.QPointF(self._xc - radius * self._xscale,
                                    self._yc - radius * self._yscale),
                        qt4.QPointF(self._xc + radius * self._xscale,
                                    self._yc + radius * self._yscale)))

        # setup axes plot
        tl = s.TickLabels
        scale, format = tl.scale, tl.format
        if format == 'Auto':
            format = atick.autoformat
        painter.setPen(tl.makeQPen())
        font = tl.makeQFont(painter)

        # draw radial axis
        if not s.TickLabels.hideradial:
            for tick in majtick[1:]:
                num = utils.formatNumber(tick * scale,
                                         format,
                                         locale=self.document.locale)
                x = tick / self._maxradius * self._xscale + self._xc
                r = utils.Renderer(painter,
                                   font,
                                   x,
                                   self._yc,
                                   num,
                                   alignhorz=-1,
                                   alignvert=-1,
                                   usefullheight=True)
                r.render()

        if s.units == 'degrees':
            angles = [
                u'0°', u'30°', u'60°', u'90°', u'120°', u'150°', u'180°',
                u'210°', u'240°', u'270°', u'300°', u'330°'
            ]
        else:
            angles = [
                '0', u'π/6', u'π/3', u'π/2', u'2π/3', u'5π/6', u'π', u'7π/6',
                u'4π/3', u'3π/2', u'5π/3', u'11π/6'
            ]

        align = [(-1, 1), (-1, 1), (-1, 1), (0, 1), (1, 1), (1, 1), (1, 0),
                 (1, -1), (1, -1), (0, -1), (-1, -1), (-1, -1)]

        if s.direction == 'anticlockwise':
            angles = angles[0:1] + angles[1:][::-1]

        # rotate labels if zero not at right
        if s.position0 == 'top':
            angles = angles[3:] + angles[:4]
        elif s.position0 == 'left':
            angles = angles[6:] + angles[:7]
        elif s.position0 == 'bottom':
            angles = angles[9:] + angles[:10]

        # draw labels around plot
        if not s.TickLabels.hidetangential:
            for i in xrange(12):
                angle = 2 * N.pi / 12
                x = self._xc + N.cos(angle * i) * self._xscale
                y = self._yc + N.sin(angle * i) * self._yscale
                r = utils.Renderer(painter,
                                   font,
                                   x,
                                   y,
                                   angles[i],
                                   alignhorz=align[i][0],
                                   alignvert=align[i][1],
                                   usefullheight=True)
                r.render()

        # draw spokes
        if not t.hidespokes:
            painter.setPen(s.Tick.makeQPenWHide(painter))
            painter.setBrush(qt4.QBrush())
            angle = 2 * N.pi / 12
            lines = []
            for i in xrange(12):
                x = self._xc + N.cos(angle * i) * self._xscale
                y = self._yc + N.sin(angle * i) * self._yscale
                lines.append(
                    qt4.QLineF(qt4.QPointF(self._xc, self._yc),
                               qt4.QPointF(x, y)))
            painter.drawLines(lines)
Пример #26
0
    def draw(self, parentposn, phelper, outerbounds = None):
        """Plot the key on a plotter."""

        s = self.settings
        if s.hide:
            return

        painter = phelper.painter(self, parentposn)

        font = s.get('Text').makeQFont(painter)
        painter.setFont(font)
        height = utils.FontMetrics(font, painter.device()).height()
        margin = s.marginSize * height

        showtext = not s.Text.hide

        # maximum width of text required
        maxwidth = 1
        # total number of layout lines required
        totallines = 0

        # reserve space for the title
        titlewidth, titleheight = 0, 0
        if s.title != '':
            titlefont = qt4.QFont(font)
            titlefont.setPointSize(max(font.pointSize() * 1.2, font.pointSize() + 2))
            titlewidth, titleheight = utils.Renderer(painter, titlefont,
                                            0, 0, s.title).getDimensions()
            titleheight += 0.5*margin
            maxwidth = titlewidth

        entries = []
        # iterate over children and find widgets which are suitable
        for c in self.parent.children:
            try:
                num = c.getNumberKeys()
            except AttributeError:
                continue
            if not c.settings.hide:
                # add an entry for each key entry for each widget
                for i in xrange(num):
                    lines = 1
                    if showtext:
                        w, h = utils.Renderer(painter, font, 0, 0,
                                              c.getKeyText(i)).getDimensions()
                        maxwidth = max(maxwidth, w)
                        lines = max(1, math.ceil(float(h)/float(height)))
                    
                    totallines += lines
                    entries.append( (c, i, lines) )

        # layout the box
        layout, (numrows, numcols) = self._layout(entries, totallines)

        # total size of box
        symbolwidth = s.get('keyLength').convert(painter)
        totalwidth = ( (maxwidth + height + symbolwidth)*numcols +
                       height*(numcols-1) )
        totalheight = numrows * height + titleheight
        if not s.Border.hide:
            totalwidth += 2*margin
            totalheight += margin

        # work out horizontal position
        h = s.horzPosn
        if h == 'left':
            x = parentposn[0] + height
        elif h == 'right':
            x = parentposn[2] - height - totalwidth
        elif h == 'centre':
            x = ( parentposn[0] +
                  0.5*(parentposn[2] - parentposn[0] - totalwidth) )
        elif h == 'manual':
            x = parentposn[0] + (parentposn[2]-parentposn[0])*s.horzManual

        # work out vertical position
        v = s.vertPosn
        if v == 'top':
            y = parentposn[1] + height
        elif v == 'bottom':
            y = parentposn[3] - totalheight - height
        elif v == 'centre':
            y = ( parentposn[1] +
                  0.5*(parentposn[3] - parentposn[1] - totalheight) )
        elif v == 'manual':
            y = ( parentposn[3] -
                  (parentposn[3]-parentposn[1])*s.vertManual - totalheight )

        # for controlgraph
        boxposn = (x, y)
        boxdims = (totalwidth, totalheight)

        # draw surrounding box
        boxpath = qt4.QPainterPath()
        boxpath.addRect(qt4.QRectF(x, y, totalwidth, totalheight))
        if not s.Background.hide:
            utils.brushExtFillPath(painter, s.Background, boxpath)
        if not s.Border.hide:
            painter.strokePath(boxpath, s.get('Border').makeQPen(painter) )
            x += margin
            y += margin*0.5

        # center and draw the title
        if s.title:
            xpos = x + 0.5*(totalwidth - (0 if s.Border.hide else 2*margin) - titlewidth)
            utils.Renderer(painter, titlefont, xpos, y, s.title, alignvert=1).render()
            y += titleheight

        textpen = s.get('Text').makeQPen()

        # plot dataset entries
        for (plotter, num, xp, yp, lines) in layout:
            xpos = x + xp*(maxwidth+2*height+symbolwidth)
            ypos = y + yp*height

            # plot key symbol
            painter.save()
            keyoffset = 0
            if s.keyAlign == 'centre':
                keyoffset = (lines-1)*height/2.0
            elif s.keyAlign == 'bottom':
                keyoffset = (lines-1)*height
            
            plotter.drawKeySymbol(num, painter, xpos, ypos+keyoffset,
                                  symbolwidth, height)
            painter.restore()

            # write key text
            if showtext:
                painter.setPen(textpen)
                utils.Renderer(painter, font,
                               xpos + height + symbolwidth, ypos,
                               plotter.getKeyText(num),
                               -1, 1).render()

        phelper.setControlGraph(
            self, [ControlKey(self, parentposn, boxposn, boxdims, height)] )
Пример #27
0
def swapbox(painter, x1, y1, x2, y2, swap):
    """Return box, swapping x and y coordinates if swap is True."""
    if swap:
        return qt4.QRectF(qt4.QPointF(y1, x1), qt4.QPointF(y2, x2))
    else:
        return qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
Пример #28
0
    def draw(self, parentposn, phelper, outerbounds=None):
        """Draw the image."""

        posn = plotters.GenericPlotter.draw(self,
                                            parentposn,
                                            phelper,
                                            outerbounds=outerbounds)
        x1, y1, x2, y2 = posn
        s = self.settings

        # get axes widgets
        axes = self.parent.getAxes((s.xAxis, s.yAxis))

        # return if there's no proper axes
        if (None in axes or axes[0].settings.direction != 'horizontal'
                or axes[1].settings.direction != 'vertical'):
            return

        # get data and update internal computations
        data = self.recomputeInternals()
        if not data or s.hide:
            return

        # find coordinates of image coordinate bounds
        rangex, rangey = data.getDataRanges()

        # translate coordinates to plotter coordinates
        coordsx = axes[0].dataToPlotterCoords(posn, N.array(rangex))
        coordsy = axes[1].dataToPlotterCoords(posn, N.array(rangey))

        # truncate image down if necessary
        # This assumes linear pixels!
        if (coordsx[0] < x1 or coordsx[1] > x2 or coordsy[0] < y1
                or coordsy[1] > y2):

            coordsx, coordsy, image = self.cutImageToFit(
                coordsx, coordsy, posn)
        else:
            image = self.image

        # clip data within bounds of plotter
        clip = self.clipAxesBounds(axes, posn)
        painter = phelper.painter(self, posn, clip=clip)

        # optionally smooth images before displaying
        if s.smooth:
            image = image.scaled(coordsx[1] - coordsx[0],
                                 coordsy[0] - coordsy[1],
                                 qt4.Qt.IgnoreAspectRatio,
                                 qt4.Qt.SmoothTransformation)

        # get position and size of output image
        xp, yp = coordsx[0], coordsy[1]
        xw = coordsx[1] - coordsx[0]
        yw = coordsy[0] - coordsy[1]

        # invert output drawing if axes go from positive->negative
        # we only translate the coordinate system if this is the case
        xscale = yscale = 1
        if xw < 0:
            xscale = -1
        if yw < 0:
            yscale = -1
        if xscale != 1 or yscale != 1:
            painter.save()
            painter.translate(xp, yp)
            xp = yp = 0
            painter.scale(xscale, yscale)

        # draw image
        painter.drawImage(qt4.QRectF(xp, yp, abs(xw), abs(yw)), image)

        # restore painter if image was inverted
        if xscale != 1 or yscale != 1:
            painter.restore()
Пример #29
0
    def draw(self, posn, phelper, outerbounds = None):
        """Plot the key on a plotter."""

        s = self.settings
        d = self.document
        if s.hide:
            return

        # if a dataset is used, we can't use control items
        isnotdataset = ( not s.get('xPos').isDataset(d) and 
                         not s.get('yPos').isDataset(d) )

        if s.mode == 'length-angle':
            isnotdataset = ( isnotdataset and
                             not s.get('length').isDataset(d) and
                             not s.get('angle').isDataset(d) )
        else:
            isnotdataset = ( isnotdataset and
                             not s.get('xPos2').isDataset(d) and
                             not s.get('yPos2').isDataset(d) )

        # now do the drawing
        clip = None
        if s.clip:
            clip = qt4.QRectF( qt4.QPointF(posn[0], posn[1]),
                               qt4.QPointF(posn[2], posn[3]) )
        painter = phelper.painter(self, posn, clip=clip)

        # adjustable positions for the lines
        arrowsize = s.get('arrowSize').convert(painter)

        # drawing settings for line
        if not s.Line.hide:
            painter.setPen( s.get('Line').makeQPen(painter) )
        else:
            painter.setPen( qt4.QPen(qt4.Qt.NoPen) )

        # settings for fill
        if not s.Fill.hide:
            painter.setBrush( s.get('Fill').makeQBrush() )
        else:
            painter.setBrush( qt4.QBrush() )

        # iterate over positions
        scaling = posn[2]-posn[0]
        if s.mode == 'length-angle':
            lines = self._computeLinesLengthAngle(posn, scaling)
        else:
            lines = self._computeLinesPointToPoint(posn)

        if lines is None:
            return

        controlgraphitems = []
        for index, (x, y, l, a) in enumerate(lines):

            utils.plotLineArrow(painter, x, y, l, a,
                                arrowsize=arrowsize,
                                arrowleft=s.arrowleft,
                                arrowright=s.arrowright)

            if isnotdataset:
                cgi = controlgraph.ControlLine(
                    self, x, y,
                    x + l*math.cos(a/180.*math.pi),
                    y + l*math.sin(a/180.*math.pi))
                cgi.index = index
                cgi.widgetposn = posn
                controlgraphitems.append(cgi)

        phelper.setControlGraph(self, controlgraphitems)
Пример #30
0
    def drawKeySymbol(self, number, painter, x, y, width, height):
        """Draw a fill rectangle for key entry."""

        self.plotBars(
            painter, self.settings, number, qt4.QRectF(0, 0, 32767, 32767),
            ([x], [y + height * 0.1], [x + width], [y + height * 0.8]))