src/reportlab/graphics/charts/axes.py
author robin <robin@reportlab.com>
Tue, 07 Mar 2017 10:00:34 +0000
changeset 4330 617ffa6bbdc8
parent 4320 1b0c1ba5d716
child 4360 823a45c95ed8
permissions -rw-r--r--
changes for release 3.4.0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4330
617ffa6bbdc8 changes for release 3.4.0
robin <robin@reportlab.com>
parents: 4320
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2017
817
8c3a399effda License text changes
rgbecker
parents: 746
diff changeset
     2
#see license.txt for license details
4252
fe660f227cac changes for release 3.3.0
robin
parents: 4182
diff changeset
     3
__version__='3.3.0'
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     4
__doc__="""Collection of axes for charts.
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
     5
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
     6
The current collection comprises axes for charts using cartesian
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
     7
coordinate systems. All axes might have tick marks and labels.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
     8
There are two dichotomies for axes: one of X and Y flavours and
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
     9
another of category and value flavours.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    10
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    11
Category axes have an ordering but no metric. They are divided
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    12
into a number of equal-sized buckets. Their tick marks or labels,
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    13
if available, go BETWEEN the buckets, and the labels are placed
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    14
below to/left of the X/Y-axis, respectively.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    15
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    16
  Value axes have an ordering AND metric. They correspond to a nu-
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    17
  meric quantity. Value axis have a real number quantity associated
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    18
  with it. The chart tells it where to go.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    19
  The most basic axis divides the number line into equal spaces
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    20
  and has tickmarks and labels associated with each; later we
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    21
  will add variants where you can specify the sampling
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    22
  interval.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    23
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    24
The charts using axis tell them where the labels should be placed.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    25
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    26
Axes of complementary X/Y flavours can be connected to each other
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    27
in various ways, i.e. with a specific reference point, like an
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    28
x/value axis to a y/value (or category) axis. In this case the
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    29
connection can be either at the top or bottom of the former or
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    30
at any absolute value (specified in points) or at some value of
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    31
the former axes in its own coordinate system.
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    32
"""
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    33
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
    34
from reportlab.lib.validators import    isNumber, isNumberOrNone, isListOfStringsOrNone, isListOfNumbers, \
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
    35
                                        isListOfNumbersOrNone, isColorOrNone, OneOf, isBoolean, SequenceOf, \
3762
4817e577522d some fixes to typeing etc etc
robin
parents: 3754
diff changeset
    36
                                        isString, EitherOr, Validator, NoneOr, isInstanceOf, \
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
    37
                                        isNormalDate, isNoneOrCallable
948
2531b35adf85 New AttrMap emplacement
rgbecker
parents: 947
diff changeset
    38
from reportlab.lib.attrmap import *
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
    39
from reportlab.lib import normalDate
3531
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
    40
from reportlab.graphics.shapes import Drawing, Line, PolyLine, Rect, Group, STATE_DEFAULTS, _textBoxLimits, _rotatedBoxLimits
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    41
from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
    42
from reportlab.graphics.charts.textlabels import Label, PMVLabel
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents: 826
diff changeset
    43
from reportlab.graphics.charts.utils import nextRoundNumber
3531
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
    44
from reportlab.graphics.widgets.grids import ShadedRect
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
    45
from reportlab.lib.colors import Color
3762
4817e577522d some fixes to typeing etc etc
robin
parents: 3754
diff changeset
    46
from reportlab.lib.utils import isSeq
3406
16f8bd304539 axes.py: eliinate import string, fix Andy's auto bounds label dx
rgbecker
parents: 3404
diff changeset
    47
import copy
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
    48
try:
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
    49
    reduce  # Python 2.x
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
    50
except NameError:
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
    51
    from functools import reduce
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
    52
907
7693d30d2746 Various minor changes.
dinu_gherman
parents: 893
diff changeset
    53
# Helpers.
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    54
def _findMinMaxValue(V, x, default, func, special=None):
3762
4817e577522d some fixes to typeing etc etc
robin
parents: 3754
diff changeset
    55
    if isSeq(V[0][0]):
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    56
        if special:
2029
f2b34413aefe Fix up 2.2ism
rgbecker
parents: 1998
diff changeset
    57
            f=lambda T,x=x,special=special,func=func: special(T,x,func)
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    58
        else:
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    59
            f=lambda T,x=x: T[x]
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
    60
        V=list(map(lambda e,f=f: list(map(f,e)),V))
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
    61
    V = list(filter(len,[[x for x in x if x is not None] for x in V]))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
    62
    if len(V)==0: return default
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
    63
    return func(list(map(func,V)))
1269
94ff82adc95b Added None handling & ValueAxis._adjustAxisTicks
rgbecker
parents: 1256
diff changeset
    64
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    65
def _findMin(V, x, default,special=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
    66
    '''find minimum over V[i][x]'''
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    67
    return _findMinMaxValue(V,x,default,min,special=special)
907
7693d30d2746 Various minor changes.
dinu_gherman
parents: 893
diff changeset
    68
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    69
def _findMax(V, x, default,special=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
    70
    '''find maximum over V[i][x]'''
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
    71
    return _findMinMaxValue(V,x,default,max,special=special)
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
    72
2538
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    73
def _allInt(values):
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    74
    '''true if all values are int'''
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    75
    for v in values:
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    76
        try:
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    77
            if int(v)!=v: return 0
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    78
        except:
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    79
            return 0
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    80
    return 1
6a2c2612e67c axes.py: factor out _allInt
rgbecker
parents: 2522
diff changeset
    81
4320
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    82
class AxisLabelAnnotation:
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    83
    '''Create a grid like line using the given user value to draw the line
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    84
    v       value to use
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    85
    kwds may contain
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    86
    scaleValue  True/not given --> scale the value
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    87
                otherwise use the absolute value
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    88
    labelClass  the label class to use default Label
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    89
    all Label keywords are acceptable (including say _text)
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    90
    '''
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    91
    def __init__(self,v,**kwds):
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    92
        self._v = v
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    93
        self._kwds = kwds
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    94
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    95
    def __call__(self,axis):
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    96
        kwds = self._kwds.copy()
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    97
        labelClass = kwds.pop('labelClass',Label)
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    98
        scaleValue = kwds.pop('scaleValue',True)
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
    99
        if not hasattr(axis,'_tickValues'):
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   100
            axis._pseudo_configure()
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   101
        sv = (axis.scale if scaleValue else lambda x: x)(self._v)
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   102
        if axis.isYAxis:
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   103
            y = axis._x
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   104
            x = sv
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   105
        else:
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   106
            x = sv
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   107
            y = axis._y
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   108
        kwds['x'] = x
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   109
        kwds['y'] = y
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   110
        return labelClass(**kwds)
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   111
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   112
class AxisLineAnnotation:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   113
    '''Create a grid like line using the given user value to draw the line
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   114
    kwds may contain
3548
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   115
    startOffset if true v is offset from the default grid start position
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   116
    endOffset   if true v is offset from the default grid end position
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   117
    scaleValue  True/not given --> scale the value
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   118
                otherwise use the absolute value
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   119
    lo          lowest coordinate to draw default 0
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   120
    hi          highest coordinate to draw at default = length
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   121
    drawAtLimit True draw line at appropriate limit if its coordinate exceeds the lo, hi range
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   122
                False ignore if it's outside the range
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   123
    all Line keywords are acceptable
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   124
    '''
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   125
    def __init__(self,v,**kwds):
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   126
        self._v = v
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   127
        self._kwds = kwds
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   128
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   129
    def __call__(self,axis):
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   130
        kwds = self._kwds.copy()
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   131
        scaleValue = kwds.pop('scaleValue',True)
3548
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   132
        endOffset = kwds.pop('endOffset',False)
4320
1b0c1ba5d716 fix bug in NormalDateXValueAxis, add AxisLabelAnnotation
robin <robin@reportlab.com>
parents: 4319
diff changeset
   133
        startOffset = kwds.pop('startOffset',False)
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   134
        if axis.isYAxis:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   135
            offs = axis._x
3530
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   136
            d0 = axis._y
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   137
        else:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   138
            offs = axis._y
3530
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   139
            d0 = axis._x
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   140
        s = kwds.pop('start',None)
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   141
        e = kwds.pop('end',None)
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   142
        if s is None or e is None:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   143
            dim = getattr(getattr(axis,'joinAxis',None),'getGridDims',None)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3276
diff changeset
   144
            if dim and hasattr(dim,'__call__'):
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   145
                dim = dim()
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   146
            if dim:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   147
                if s is None: s = dim[0]
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   148
                if e is None: e = dim[1]
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   149
            else:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   150
                if s is None: s = 0
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   151
                if e is None: e = 0
3530
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   152
        hi = kwds.pop('hi',axis._length)+d0
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   153
        lo = kwds.pop('lo',0)+d0
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   154
        lo,hi=min(lo,hi),max(lo,hi)
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   155
        drawAtLimit = kwds.pop('drawAtLimit',False)
3530
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   156
        oaglp = axis._get_line_pos
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   157
        if not scaleValue:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   158
            axis._get_line_pos = lambda x: x
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   159
        try:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   160
            v = self._v
3548
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   161
            if endOffset:
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   162
                v = v + hi
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   163
            elif startOffset:
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   164
                v = v + lo
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   165
            func = axis._getLineFunc(s-offs,e-offs,kwds.pop('parent',None))
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   166
            if not hasattr(axis,'_tickValues'):
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   167
                axis._pseudo_configure()
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   168
            d = axis._get_line_pos(v)
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   169
            if d<lo or d>hi:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   170
                if not drawAtLimit: return None
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   171
                if d<lo:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   172
                    d = lo
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   173
                else:
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   174
                    d = hi
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   175
                axis._get_line_pos = lambda x: d
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   176
            L = func(v)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   177
            for k,v in kwds.items():
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   178
                setattr(L,k,v)
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   179
        finally:
3530
f49b949af4a9 axes.py:minor fix to AxisLineAnnotation
rgbecker
parents: 3414
diff changeset
   180
            axis._get_line_pos = oaglp
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   181
        return L
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   182
3531
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   183
class AxisBackgroundAnnotation:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   184
    '''Create a set of coloured bars on the background of a chart using axis ticks as the bar borders
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   185
    colors is a set of colors to use for the background bars. A colour of None is just a skip.
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   186
    Special effects if you pass a rect or Shaded rect instead.
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   187
    '''
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   188
    def __init__(self,colors,**kwds):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   189
        self._colors = colors
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   190
        self._kwds = kwds
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   191
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   192
    def __call__(self,axis):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   193
        colors = self._colors
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   194
        if not colors: return
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   195
        kwds = self._kwds.copy()
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   196
        isYAxis = axis.isYAxis
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   197
        if isYAxis:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   198
            offs = axis._x
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   199
            d0 = axis._y
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   200
        else:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   201
            offs = axis._y
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   202
            d0 = axis._x
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   203
        s = kwds.pop('start',None)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   204
        e = kwds.pop('end',None)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   205
        if s is None or e is None:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   206
            dim = getattr(getattr(axis,'joinAxis',None),'getGridDims',None)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   207
            if dim and hasattr(dim,'__call__'):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   208
                dim = dim()
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   209
            if dim:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   210
                if s is None: s = dim[0]
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   211
                if e is None: e = dim[1]
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   212
            else:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   213
                if s is None: s = 0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   214
                if e is None: e = 0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   215
        if not hasattr(axis,'_tickValues'):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   216
            axis._pseudo_configure()
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   217
        tv = getattr(axis,'_tickValues',None)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   218
        if not tv: return
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   219
        G = Group()
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   220
        ncolors = len(colors)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   221
        v0 = axis._get_line_pos(tv[0])
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   222
        for i in range(1,len(tv)):
3531
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   223
            v1 = axis._get_line_pos(tv[i])
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   224
            c = colors[(i-1)%ncolors]
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   225
            if c:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   226
                if isYAxis:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   227
                    y = v0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   228
                    x = s
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   229
                    height = v1-v0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   230
                    width = e-s
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   231
                else:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   232
                    x = v0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   233
                    y = s
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   234
                    width = v1-v0
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   235
                    height = e-s
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   236
                if isinstance(c,Color):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   237
                    r = Rect(x,y,width,height,fillColor=c,strokeColor=None)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   238
                elif isinstance(c,Rect):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   239
                    r = Rect(x,y,width,height)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   240
                    for k in c.__dict__:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   241
                        if k not in ('x','y','width','height'):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   242
                            setattr(r,k,getattr(c,k))
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   243
                elif isinstance(c,ShadedRect):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   244
                    r = ShadedRect(x=x,y=y,width=width,height=height)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   245
                    for k in c.__dict__:
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   246
                        if k not in ('x','y','width','height'):
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   247
                            setattr(r,k,getattr(c,k))
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   248
                G.add(r)
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   249
            v0 = v1
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   250
        return G
1f1572a6a841 axes.py: added AxisBackgroundAnnotation
rgbecker
parents: 3530
diff changeset
   251
3413
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   252
class TickLU:
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   253
    '''lookup special cases for tick values'''
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   254
    def __init__(self,*T,**kwds):
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   255
        self.accuracy = kwds.pop('accuracy',1e-8)
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   256
        self.T = T
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   257
    def __contains__(self,t):
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   258
        accuracy = self.accuracy
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   259
        for x,v in self.T:
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   260
            if abs(x-t)<accuracy:
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   261
                return True
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   262
        return False
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   263
    def __getitem__(self,t):
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   264
        accuracy = self.accuracy
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   265
        for x,v in self.T:
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   266
            if abs(x-t)<self.accuracy:
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   267
                return v
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   268
        raise IndexError('cannot locate index %r' % t)
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   269
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   270
class _AxisG(Widget):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   271
    def _get_line_pos(self,v):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   272
        v = self.scale(v)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   273
        try:
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   274
            v = v[0]
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   275
        except:
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   276
            pass
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   277
        return v
907
7693d30d2746 Various minor changes.
dinu_gherman
parents: 893
diff changeset
   278
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   279
    def _cxLine(self,x,start,end):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   280
        x = self._get_line_pos(x)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   281
        return Line(x, self._y + start, x, self._y + end)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   282
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   283
    def _cyLine(self,y,start,end):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   284
        y = self._get_line_pos(y)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   285
        return Line(self._x + start, y, self._x + end, y)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   286
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   287
    def _cxLine3d(self,x,start,end,_3d_dx,_3d_dy):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   288
        x = self._get_line_pos(x)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   289
        y0 = self._y + start
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   290
        y1 = self._y + end
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   291
        y0, y1 = min(y0,y1),max(y0,y1)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   292
        x1 = x + _3d_dx
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   293
        return PolyLine([x,y0,x1,y0+_3d_dy,x1,y1+_3d_dy],strokeLineJoin=1)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   294
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   295
    def _cyLine3d(self,y,start,end,_3d_dx,_3d_dy):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   296
        y = self._get_line_pos(y)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   297
        x0 = self._x + start
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   298
        x1 = self._x + end
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   299
        x0, x1 = min(x0,x1),max(x0,x1)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   300
        y1 = y + _3d_dy
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   301
        return PolyLine([x0,y,x0+_3d_dx,y1,x1+_3d_dx,y1],strokeLineJoin=1)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   302
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   303
    def _getLineFunc(self, start, end, parent=None):
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   304
        _3d_dx = getattr(parent,'_3d_dx',None)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   305
        if _3d_dx is not None:
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   306
            _3d_dy = getattr(parent,'_3d_dy',None)
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   307
            f = self.isYAxis and self._cyLine3d or self._cxLine3d
2082
07bb9b9da8d9 Attempt to fix 2.2ism
rgbecker
parents: 2068
diff changeset
   308
            return lambda v, s=start, e=end, f=f,_3d_dx=_3d_dx,_3d_dy=_3d_dy: f(v,s,e,_3d_dx=_3d_dx,_3d_dy=_3d_dy)
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   309
        else:
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   310
            f = self.isYAxis and self._cyLine or self._cxLine
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   311
            return lambda v, s=start, e=end, f=f: f(v,s,e)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   312
3413
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   313
    def _makeLines(self,g,start,end,strokeColor,strokeWidth,strokeDashArray,strokeLineJoin,strokeLineCap,strokeMiterLimit,parent=None,exclude=[],specials={}):
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   314
        func = self._getLineFunc(start,end,parent)
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
   315
        if not hasattr(self,'_tickValues'):
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
   316
            self._pseudo_configure()
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   317
        if exclude:
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   318
            exf = self.isYAxis and (lambda l: l.y1 in exclude) or (lambda l: l.x1 in exclude)
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   319
        else:
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   320
            exf = None
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   321
        for t in self._tickValues:
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   322
                L = func(t)
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   323
                if exf and exf(L): continue
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   324
                L.strokeColor = strokeColor
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   325
                L.strokeWidth = strokeWidth
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   326
                L.strokeDashArray = strokeDashArray
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   327
                L.strokeLineJoin = strokeLineJoin
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   328
                L.strokeLineCap = strokeLineCap
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   329
                L.strokeMiterLimit = strokeMiterLimit
3413
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   330
                if t in specials:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   331
                    for a,v in specials[t].items():
3413
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   332
                        setattr(L,a,v)
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   333
                g.add(L)
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   334
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   335
    def makeGrid(self,g,dim=None,parent=None,exclude=[]):
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   336
        '''this is only called by a container object'''
2714
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   337
        c = self.gridStrokeColor
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   338
        w = self.gridStrokeWidth or 0
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   339
        if w and c and self.visibleGrid:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   340
            s = self.gridStart
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   341
            e = self.gridEnd
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   342
            if s is None or e is None:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3276
diff changeset
   343
                if dim and hasattr(dim,'__call__'):
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   344
                    dim = dim()
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   345
                if dim:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   346
                    if s is None: s = dim[0]
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   347
                    if e is None: e = dim[1]
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   348
                else:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   349
                    if s is None: s = 0
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   350
                    if e is None: e = 0
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   351
            if s or e:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   352
                if self.isYAxis: offs = self._x
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   353
                else: offs = self._y
3413
8e6e6e276f09 legends.py: beginning of support for special grid styling
rgbecker
parents: 3412
diff changeset
   354
                self._makeLines(g,s-offs,e-offs,c,w,self.gridStrokeDashArray,self.gridStrokeLineJoin,self.gridStrokeLineCap,self.gridStrokeMiterLimit,parent=parent,exclude=exclude,specials=getattr(self,'_gridSpecials',{}))
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   355
        self._makeSubGrid(g,dim,parent,exclude=[])
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   356
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   357
    def _makeSubGrid(self,g,dim=None,parent=None,exclude=[]):
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   358
        '''this is only called by a container object'''
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   359
        if not (getattr(self,'visibleSubGrid',0) and self.subTickNum>0): return
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   360
        c = self.subGridStrokeColor
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   361
        w = self.subGridStrokeWidth or 0
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   362
        if not(w and c): return
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   363
        s = self.subGridStart
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   364
        e = self.subGridEnd
2714
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   365
        if s is None or e is None:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3276
diff changeset
   366
            if dim and hasattr(dim,'__call__'):
2714
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   367
                dim = dim()
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   368
            if dim:
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   369
                if s is None: s = dim[0]
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   370
                if e is None: e = dim[1]
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   371
            else:
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   372
                if s is None: s = 0
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   373
                if e is None: e = 0
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   374
        if s or e:
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   375
            if self.isYAxis: offs = self._x
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   376
            else: offs = self._y
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   377
            otv = self._calcSubTicks()
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   378
            try:
3398
ac8ff8482dae lineplots.py, axes.py: start support for excluding grid lines
rgbecker
parents: 3392
diff changeset
   379
                self._makeLines(g,s-offs,e-offs,c,w,self.subGridStrokeDashArray,self.subGridStrokeLineJoin,self.subGridStrokeLineCap,self.subGridStrokeMiterLimit,parent=parent,exclude=exclude)
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   380
            finally:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   381
                self._tickValues = otv
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   382
2714
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   383
    def getGridDims(self,start=None,end=None):
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   384
        if start is None: start = (self._x,self._y)[self.isYAxis]
6b27a3362cff charts: fix axis gridding
rgbecker
parents: 2700
diff changeset
   385
        if end is None: end = start+self._length
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   386
        return start,end
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   387
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   388
    def isYAxis(self):
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   389
        if getattr(self,'_dataIndex',None)==1: return True
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   390
        acn = self.__class__.__name__
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   391
        return acn[0]=='Y' or acn[:4]=='AdjY'
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   392
    isYAxis = property(isYAxis)
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   393
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   394
    def isXAxis(self):
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   395
        if getattr(self,'_dataIndex',None)==0: return True
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   396
        acn = self.__class__.__name__
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   397
        return acn[0]=='X' or acn[:11]=='NormalDateX'
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   398
    isXAxis = property(isXAxis)
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   399
3402
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   400
    def addAnnotations(self,g,A=None):
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   401
        if A is None: getattr(self,'annotations',[])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   402
        for x in A:
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   403
            g.add(x(self))
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   404
3402
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   405
    def _splitAnnotations(self):
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   406
        A = getattr(self,'annotations',[])[:]
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   407
        D = {}
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   408
        for v in ('early','beforeAxis','afterAxis','beforeTicks',
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   409
                'afterTicks','beforeTickLabels',
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   410
                'afterTickLabels','late'):
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   411
            R = [].append
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   412
            P = [].append
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   413
            for a in A:
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   414
                if getattr(a,v,0):
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   415
                    R(a)
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   416
                else:
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   417
                    P(a)
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   418
            D[v] = R.__self__
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   419
            A[:] = P.__self__
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   420
        D['late'] += A
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   421
        return D
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   422
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   423
    def draw(self):
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   424
        g = Group()
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   425
        A = self._splitAnnotations()
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   426
        self.addAnnotations(g,A['early'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   427
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   428
        if self.visible:
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   429
            self.addAnnotations(g,A['beforeAxis'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   430
            g.add(self.makeAxis())
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   431
            self.addAnnotations(g,A['afterAxis'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   432
            self.addAnnotations(g,A['beforeTicks'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   433
            g.add(self.makeTicks())
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   434
            self.addAnnotations(g,A['afterTicks'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   435
            self.addAnnotations(g,A['beforeTickLabels'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   436
            g.add(self.makeTickLabels())
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   437
            self.addAnnotations(g,A['afterTickLabels'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   438
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   439
        self.addAnnotations(g,A['late'])
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   440
        return g
4a5a0dc6a531 axes.py: order axis annotations
rgbecker
parents: 3398
diff changeset
   441
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   442
class CALabel(PMVLabel):
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   443
    _attrMap = AttrMap(BASE=PMVLabel,
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   444
        labelPosFrac = AttrMapValue(isNumber, desc='where in the category range [0,1] the labels should be anchored'),
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   445
        )
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   446
    def __init__(self,**kw):
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   447
        PMVLabel.__init__(self,**kw)
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   448
        self._setKeywords(
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   449
                labelPosFrac = 0.5,
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   450
                )
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   451
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   452
# Category axes.
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   453
class CategoryAxis(_AxisG):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   454
    "Abstract category axis, unusable in itself."
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   455
    _nodoc = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   456
    _attrMap = AttrMap(
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   457
        visible = AttrMapValue(isBoolean, desc='Display entire object, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   458
        visibleAxis = AttrMapValue(isBoolean, desc='Display axis line, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   459
        visibleTicks = AttrMapValue(isBoolean, desc='Display axis ticks, if true.'),
1960
2269ab0089fe Added visibleLabels
andy_robinson
parents: 1959
diff changeset
   460
        visibleLabels = AttrMapValue(isBoolean, desc='Display axis labels, if true.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   461
        visibleGrid = AttrMapValue(isBoolean, desc='Display axis grid, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   462
        strokeWidth = AttrMapValue(isNumber, desc='Width of axis line and ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   463
        strokeColor = AttrMapValue(isColorOrNone, desc='Color of axis line and ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   464
        strokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array used for axis line.'),
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   465
        strokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Line cap 0=butt, 1=round & 2=square"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   466
        strokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Line join 0=miter, 1=round & 2=bevel"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   467
        strokeMiterLimit = AttrMapValue(isNumber,desc="miter limit control miter line joins"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   468
        gridStrokeWidth = AttrMapValue(isNumber, desc='Width of grid lines.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   469
        gridStrokeColor = AttrMapValue(isColorOrNone, desc='Color of grid lines.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   470
        gridStrokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array used for grid lines.'),
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   471
        gridStrokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Grid Line cap 0=butt, 1=round & 2=square"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   472
        gridStrokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Grid Line join 0=miter, 1=round & 2=bevel"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   473
        gridStrokeMiterLimit = AttrMapValue(isNumber,desc="Grid miter limit control miter line joins"),
1934
104a813e8402 Attempt at getting SplitLinePlot & allow for inFill
rgbecker
parents: 1933
diff changeset
   474
        gridStart = AttrMapValue(isNumberOrNone, desc='Start of grid lines wrt axis origin'),
104a813e8402 Attempt at getting SplitLinePlot & allow for inFill
rgbecker
parents: 1933
diff changeset
   475
        gridEnd = AttrMapValue(isNumberOrNone, desc='End of grid lines wrt axis origin'),
3206
25606c688529 charts: silly attempt at getting the grid to draw last
rgbecker
parents: 3032
diff changeset
   476
        drawGridLast = AttrMapValue(isBoolean, desc='if true draw gridlines after everything else.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   477
        labels = AttrMapValue(None, desc='Handle of the axis labels.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   478
        categoryNames = AttrMapValue(isListOfStringsOrNone, desc='List of category names.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   479
        joinAxis = AttrMapValue(None, desc='Join both axes if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   480
        joinAxisPos = AttrMapValue(isNumberOrNone, desc='Position at which to join with other axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   481
        reverseDirection = AttrMapValue(isBoolean, desc='If true reverse category direction.'),
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   482
        style = AttrMapValue(OneOf('parallel','stacked','parallel_3d'),"How common category bars are plotted"),
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   483
        labelAxisMode = AttrMapValue(OneOf('high','low','axis', 'axispmv'), desc="Like joinAxisMode, but for the axis labels"),
2428
afc1df476143 axes.py: added categegorAxis tickShift
rgbecker
parents: 2426
diff changeset
   484
        tickShift = AttrMapValue(isBoolean, desc='Tick shift typically'),
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   485
        loPad = AttrMapValue(isNumber, desc='extra inner space before start of the axis'),
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   486
        hiPad = AttrMapValue(isNumber, desc='extra inner space after end of the axis'),
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   487
        annotations = AttrMapValue(None,desc='list of annotations'),
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   488
        loLLen = AttrMapValue(isNumber, desc='extra line length before start of the axis'),
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   489
        hiLLen = AttrMapValue(isNumber, desc='extra line length after end of the axis'),
3548
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   490
        skipGrid = AttrMapValue(OneOf('none','top','both','bottom'),"grid lines to skip top bottom both none"),
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   491
        innerTickDraw = AttrMapValue(isNoneOrCallable, desc="Callable to replace _drawInnerTicks"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   492
        )
830
670015a99a24 Factorized some more methods into abstract base classes.
dinu_gherman
parents: 829
diff changeset
   493
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   494
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   495
        assert self.__class__.__name__!='CategoryAxis', "Abstract Class CategoryAxis Instantiated"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   496
        # private properties set by methods.  The initial values
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   497
        # here are to make demos easy; they would always be
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   498
        # overridden in real life.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   499
        self._x = 50
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   500
        self._y = 50
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   501
        self._length = 100
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   502
        self._catCount = 0
1234
069de083d1c2 Added reverseDirection, reversePlotOrder and style attributes
rgbecker
parents: 1216
diff changeset
   503
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   504
        # public properties
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   505
        self.visible = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   506
        self.visibleAxis = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   507
        self.visibleTicks = 1
1960
2269ab0089fe Added visibleLabels
andy_robinson
parents: 1959
diff changeset
   508
        self.visibleLabels = 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   509
        self.visibleGrid = 0
3206
25606c688529 charts: silly attempt at getting the grid to draw last
rgbecker
parents: 3032
diff changeset
   510
        self.drawGridLast = False
1234
069de083d1c2 Added reverseDirection, reversePlotOrder and style attributes
rgbecker
parents: 1216
diff changeset
   511
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   512
        self.strokeWidth = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   513
        self.strokeColor = STATE_DEFAULTS['strokeColor']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   514
        self.strokeDashArray = STATE_DEFAULTS['strokeDashArray']
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   515
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   516
        self.gridStrokeLineJoin = self.strokeLineJoin = STATE_DEFAULTS['strokeLineJoin']
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   517
        self.gridStrokeLineCap = self.strokeLineCap = STATE_DEFAULTS['strokeLineCap']
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   518
        self.gridStrokeMiterLimit = self.strokeMiterLimit = STATE_DEFAULTS['strokeMiterLimit']
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   519
        self.gridStrokeWidth = 0.25
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   520
        self.gridStrokeColor = STATE_DEFAULTS['strokeColor']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   521
        self.gridStrokeDashArray = STATE_DEFAULTS['strokeDashArray']
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   522
        self.gridStart = self.gridEnd = None
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   523
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   524
        self.strokeLineJoin = STATE_DEFAULTS['strokeLineJoin']
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   525
        self.strokeLineCap = STATE_DEFAULTS['strokeLineCap']
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   526
        self.strokeMiterLimit = STATE_DEFAULTS['strokeMiterLimit']
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   527
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   528
        self.labels = TypedPropertyCollection(CALabel)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   529
        # if None, they don't get labels. If provided,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   530
        # you need one name per data point and they are
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   531
        # used for label text.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   532
        self.categoryNames = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   533
        self.joinAxis = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   534
        self.joinAxisPos = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   535
        self.joinAxisMode = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   536
        self.labelAxisMode = 'axis'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   537
        self.reverseDirection = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   538
        self.style = 'parallel'
1234
069de083d1c2 Added reverseDirection, reversePlotOrder and style attributes
rgbecker
parents: 1216
diff changeset
   539
1930
5b571c08428e Fixed unitialized parameter in axes (broken in last checkin?)
andy_robinson
parents: 1928
diff changeset
   540
        #various private things which need to be initialized
5b571c08428e Fixed unitialized parameter in axes (broken in last checkin?)
andy_robinson
parents: 1928
diff changeset
   541
        self._labelTextFormat = None
2428
afc1df476143 axes.py: added categegorAxis tickShift
rgbecker
parents: 2426
diff changeset
   542
        self.tickShift = 0
3229
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   543
        self.loPad = 0
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   544
        self.hiPad = 0
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   545
        self.loLLen = 0
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   546
        self.hiLLen = 0
1930
5b571c08428e Fixed unitialized parameter in axes (broken in last checkin?)
andy_robinson
parents: 1928
diff changeset
   547
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   548
    def setPosition(self, x, y, length):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   549
        # ensure floating point
3229
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   550
        self._x = float(x)
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   551
        self._y = float(y)
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   552
        self._length = float(length)
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   553
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   554
    def configure(self, multiSeries,barWidth=None):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   555
        self._catCount = max(list(map(len,multiSeries)))
3229
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   556
        self._barWidth = barWidth or ((self._length-self.loPad-self.hiPad)/float(self._catCount or 1))
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   557
        self._calcTickmarkPositions()
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   558
        if self.labelAxisMode == 'axispmv':
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   559
            self._pmv = [sum([series[i] for series in multiSeries]) for i in xrange(self._catCount)]
2054
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   560
08302f68d88e Factorise axes a bit and make them more 3d aware
rgbecker
parents: 2036
diff changeset
   561
    def _calcTickmarkPositions(self):
2428
afc1df476143 axes.py: added categegorAxis tickShift
rgbecker
parents: 2426
diff changeset
   562
        n = self._catCount
afc1df476143 axes.py: added categegorAxis tickShift
rgbecker
parents: 2426
diff changeset
   563
        if self.tickShift:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   564
            self._tickValues = [t+0.5 for t in range(n)]
2428
afc1df476143 axes.py: added categegorAxis tickShift
rgbecker
parents: 2426
diff changeset
   565
        else:
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   566
            if self.reverseDirection:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   567
                self._tickValues = list(range(-1,n))
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   568
            else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   569
                self._tickValues = list(range(n+1))
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   570
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   571
    def _scale(self,idx):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   572
        if self.reverseDirection: idx = self._catCount-idx-1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   573
        return idx
1234
069de083d1c2 Added reverseDirection, reversePlotOrder and style attributes
rgbecker
parents: 1216
diff changeset
   574
1803
1f02a9cb6f48 Fix up bugs in joinAxisMode handling
rgbecker
parents: 1801
diff changeset
   575
def _assertYAxis(axis):
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   576
    assert axis.isYAxis, "Cannot connect to other axes (%s), but Y- ones." % axis.__class__.__name__
1803
1f02a9cb6f48 Fix up bugs in joinAxisMode handling
rgbecker
parents: 1801
diff changeset
   577
def _assertXAxis(axis):
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
   578
    assert axis.isXAxis, "Cannot connect to other axes (%s), but X- ones." % axis.__class__.__name__
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   579
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   580
class _XTicks:
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   581
    _tickTweaks = 0 #try 0.25-0.5
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   582
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   583
    def _drawTicksInner(self,tU,tD,g):
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   584
        itd = getattr(self,'innerTickDraw',None)
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   585
        if itd:
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   586
            itd(self,tU,tD,g)
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   587
        elif tU or tD:
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   588
            sW = self.strokeWidth
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   589
            tW = self._tickTweaks
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   590
            if tW:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   591
                if tU and not tD:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   592
                    tD = tW*sW
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   593
                elif tD and not tU:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   594
                    tU = tW*sW
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   595
            self._makeLines(g,tU,-tD,self.strokeColor,sW,self.strokeDashArray,self.strokeLineJoin,self.strokeLineCap,self.strokeMiterLimit)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   596
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   597
    def _drawTicks(self,tU,tD,g=None):
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   598
        g = g or Group()
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   599
        if self.visibleTicks:
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   600
            self._drawTicksInner(tU,tD,g)
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   601
        return g
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   602
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   603
    def _calcSubTicks(self):
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   604
        if not hasattr(self,'_tickValues'):
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   605
            self._pseudo_configure()
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   606
        otv = self._tickValues
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   607
        if not hasattr(self,'_subTickValues'):
3276
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   608
            acn = self.__class__.__name__
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   609
            if acn[:11]=='NormalDateX':
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   610
                iFuzz = 0
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   611
                dCnv = int
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   612
            else:
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   613
                iFuzz = 1e-8
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   614
                dCnv = lambda x:x
3354
98a92942e3a0 axes.py: add support for force end/first date and control of subticking
rgbecker
parents: 3341
diff changeset
   615
98a92942e3a0 axes.py: add support for force end/first date and control of subticking
rgbecker
parents: 3341
diff changeset
   616
            OTV = [tv for tv in otv if getattr(tv,'_doSubTicks',1)]
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   617
            T = [].append
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   618
            nst = int(self.subTickNum)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   619
            i = len(OTV)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   620
            if i<2:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   621
                self._subTickValues = []
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   622
            else:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   623
                if i==2:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   624
                    dst = OTV[1]-OTV[0]
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   625
                elif i==3:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   626
                    dst = max(OTV[1]-OTV[0],OTV[2]-OTV[1])
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   627
                else:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   628
                    i >>= 1
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   629
                    dst = OTV[i+1] - OTV[i]
3276
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   630
                fuzz = dst*iFuzz
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   631
                vn = self._valueMin+fuzz
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   632
                vx = self._valueMax-fuzz
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   633
                if OTV[0]>vn: OTV.insert(0,OTV[0]-dst)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   634
                if OTV[-1]<vx: OTV.append(OTV[-1]+dst)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   635
                dst /= float(nst+1)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   636
                for i,x in enumerate(OTV[:-1]):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   637
                    for j in range(nst):
3276
95872cdbeabc subticks & subgrid fixed for data axis
meitham
parents: 3274
diff changeset
   638
                        t = x+dCnv((j+1)*dst)
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   639
                        if t<=vn or t>=vx: continue
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   640
                        T(t)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   641
                self._subTickValues = T.__self__
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   642
        self._tickValues = self._subTickValues
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   643
        return otv
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   644
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   645
    def _drawSubTicks(self,tU,tD,g):
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   646
        if getattr(self,'visibleSubTicks',0) and self.subTickNum>0:
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   647
            otv = self._calcSubTicks()
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   648
            try:
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   649
                self._subTicking = 1
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   650
                self._drawTicksInner(tU,tD,g)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   651
            finally:
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
   652
                del self._subTicking
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   653
                self._tickValues = otv
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   654
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   655
    def makeTicks(self):
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   656
        yold=self._y
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   657
        try:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   658
            self._y = self._labelAxisPos(getattr(self,'tickAxisMode','axis'))
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   659
            g = self._drawTicks(self.tickUp,self.tickDown)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   660
            self._drawSubTicks(getattr(self,'subTickHi',0),getattr(self,'subTickLo',0),g)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   661
            return g
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   662
        finally:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   663
            self._y = yold
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   664
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   665
    def _labelAxisPos(self,mode=None):
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   666
        axis = self.joinAxis
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   667
        if axis:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   668
            mode = mode or self.labelAxisMode
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   669
            if mode == 'low':
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   670
                return axis._y
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   671
            elif mode == 'high':
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   672
                return axis._y + axis._length
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   673
        return self._y
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   674
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   675
class _YTicks(_XTicks):
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   676
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   677
    def _labelAxisPos(self,mode=None):
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   678
        axis = self.joinAxis
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   679
        if axis:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   680
            mode = mode or self.labelAxisMode
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   681
            if mode == 'low':
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   682
                return axis._x
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   683
            elif mode == 'high':
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   684
                return axis._x + axis._length
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   685
        return self._x
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   686
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   687
    def makeTicks(self):
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   688
        xold=self._x
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   689
        try:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   690
            self._x = self._labelAxisPos(getattr(self,'tickAxisMode','axis'))
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   691
            g = self._drawTicks(self.tickRight,self.tickLeft)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   692
            self._drawSubTicks(getattr(self,'subTickHi',0),getattr(self,'subTickLo',0),g)
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   693
            return g
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   694
        finally:
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   695
            self._x = xold
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   696
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   697
class XCategoryAxis(_XTicks,CategoryAxis):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   698
    "X/category axis"
830
670015a99a24 Factorized some more methods into abstract base classes.
dinu_gherman
parents: 829
diff changeset
   699
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   700
    _attrMap = AttrMap(BASE=CategoryAxis,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   701
        tickUp = AttrMapValue(isNumber,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   702
            desc='Tick length up the axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   703
        tickDown = AttrMapValue(isNumber,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   704
            desc='Tick length down the axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   705
        joinAxisMode = AttrMapValue(OneOf('bottom', 'top', 'value', 'points', None),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   706
            desc="Mode used for connecting axis ('bottom', 'top', 'value', 'points', None)."),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   707
        )
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   708
1974
5c8594a4f856 Fixes to makeGrids etc
rgbecker
parents: 1972
diff changeset
   709
    _dataIndex = 0
5c8594a4f856 Fixes to makeGrids etc
rgbecker
parents: 1972
diff changeset
   710
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   711
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   712
        CategoryAxis.__init__(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   713
        self.labels.boxAnchor = 'n' #north - top edge
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   714
        self.labels.dy = -5
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   715
        # ultra-simple tick marks for now go between categories
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   716
        # and have same line style as axis - need more
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   717
        self.tickUp = 0  # how far into chart does tick go?
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   718
        self.tickDown = 5  # how far below axis does tick go?
882
b5cec3c4c9d3 Made joining of axes possible via axes attributes.
dinu_gherman
parents: 854
diff changeset
   719
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   720
    def demo(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   721
        self.setPosition(30, 70, 140)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   722
        self.configure([(10,20,30,40,50)])
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   723
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   724
        self.categoryNames = ['One','Two','Three','Four','Five']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   725
        # all labels top-centre aligned apart from the last
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   726
        self.labels.boxAnchor = 'n'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   727
        self.labels[4].boxAnchor = 'e'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   728
        self.labels[4].angle = 90
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   729
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   730
        d = Drawing(200, 100)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   731
        d.add(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   732
        return d
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   733
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   734
    def joinToAxis(self, yAxis, mode='bottom', pos=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   735
        "Join with y-axis using some mode."
1803
1f02a9cb6f48 Fix up bugs in joinAxisMode handling
rgbecker
parents: 1801
diff changeset
   736
        _assertYAxis(yAxis)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   737
        if mode == 'bottom':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   738
            self._y = yAxis._y
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   739
        elif mode == 'top':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   740
            self._y = yAxis._y + yAxis._length
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   741
        elif mode == 'value':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   742
            self._y = yAxis.scale(pos)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   743
        elif mode == 'points':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   744
            self._y = pos
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   745
2516
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   746
    def _joinToAxis(self):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   747
        ja = self.joinAxis
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   748
        if ja:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   749
            jam = self.joinAxisMode
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   750
            if jam in ('bottom', 'top'):
3589
adbc6aafc51c axes.py: complete _joinToAxis cleanup
rgbecker
parents: 3584
diff changeset
   751
                self.joinToAxis(ja, mode=jam)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   752
            elif jam in ('value', 'points'):
3589
adbc6aafc51c axes.py: complete _joinToAxis cleanup
rgbecker
parents: 3584
diff changeset
   753
                self.joinToAxis(ja, mode=jam, pos=self.joinAxisPos)
882
b5cec3c4c9d3 Made joining of axes possible via axes attributes.
dinu_gherman
parents: 854
diff changeset
   754
2516
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   755
    def scale(self, idx):
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   756
        """returns the x position and width in drawing units of the slice"""
3229
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
   757
        return (self._x + self.loPad + self._scale(idx)*self._barWidth, self._barWidth)
2516
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   758
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   759
    def makeAxis(self):
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   760
        g = Group()
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   761
        self._joinToAxis()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   762
        if not self.visibleAxis: return g
1242
4c036db6ca81 Allow categoryAxis to be positioned even if not visible
rgbecker
parents: 1234
diff changeset
   763
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   764
        axis = Line(self._x-self.loLLen, self._y, self._x + self._length+self.hiLLen, self._y)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   765
        axis.strokeColor = self.strokeColor
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   766
        axis.strokeWidth = self.strokeWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   767
        axis.strokeDashArray = self.strokeDashArray
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   768
        g.add(axis)
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   769
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   770
        return g
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   771
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   772
    def makeTickLabels(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   773
        g = Group()
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   774
2116
fbcc73b25408 Add visibleLabels to value Axes
rgbecker
parents: 2082
diff changeset
   775
        if not self.visibleLabels: return g
923
4f15a54e6fac Added visibleAxis/visibleTicks attributes.
dinu_gherman
parents: 910
diff changeset
   776
2426
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   777
        categoryNames = self.categoryNames
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   778
        if categoryNames is not None:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   779
            catCount = self._catCount
2426
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   780
            n = len(categoryNames)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   781
            reverseDirection = self.reverseDirection
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   782
            barWidth = self._barWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   783
            _y = self._labelAxisPos()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   784
            _x = self._x
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   785
            pmv = self._pmv if self.labelAxisMode=='axispmv' else None
1234
069de083d1c2 Added reverseDirection, reversePlotOrder and style attributes
rgbecker
parents: 1216
diff changeset
   786
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   787
            for i in range(catCount):
2426
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   788
                if reverseDirection: ic = catCount-i-1
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   789
                else: ic = i
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   790
                if ic>=n: continue
3391
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   791
                label=i-catCount
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   792
                if label in self.labels:
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   793
                    label = self.labels[label]
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   794
                else:
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   795
                    label = self.labels[i]
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   796
                if pmv:
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   797
                    _dy = label.dy
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   798
                    v = label._pmv = pmv[ic]
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   799
                    if v<0: _dy *= -2
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   800
                else:
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   801
                    _dy = 0
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   802
                lpf = label.labelPosFrac
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   803
                x = _x + (i+lpf) * barWidth
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   804
                label.setOrigin(x,_y+_dy)
2426
fac927fa6f7c Auto Legends
rgbecker
parents: 2370
diff changeset
   805
                label.setText(categoryNames[ic] or '')
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   806
                g.add(label)
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   807
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   808
        return g
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   809
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   810
class YCategoryAxis(_YTicks,CategoryAxis):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   811
    "Y/category axis"
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   812
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   813
    _attrMap = AttrMap(BASE=CategoryAxis,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   814
        tickLeft = AttrMapValue(isNumber,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   815
            desc='Tick length left of the axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   816
        tickRight = AttrMapValue(isNumber,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   817
            desc='Tick length right of the axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   818
        joinAxisMode = AttrMapValue(OneOf(('left', 'right', 'value', 'points', None)),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   819
            desc="Mode used for connecting axis ('left', 'right', 'value', 'points', None)."),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   820
        )
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   821
1974
5c8594a4f856 Fixes to makeGrids etc
rgbecker
parents: 1972
diff changeset
   822
    _dataIndex = 1
5c8594a4f856 Fixes to makeGrids etc
rgbecker
parents: 1972
diff changeset
   823
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   824
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   825
        CategoryAxis.__init__(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   826
        self.labels.boxAnchor = 'e' #east - right edge
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   827
        self.labels.dx = -5
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   828
        # ultra-simple tick marks for now go between categories
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   829
        # and have same line style as axis - need more
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   830
        self.tickLeft = 5  # how far left of axis does tick go?
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   831
        self.tickRight = 0  # how far right of axis does tick go?
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   832
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   833
    def demo(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   834
        self.setPosition(50, 10, 80)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   835
        self.configure([(10,20,30)])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   836
        self.categoryNames = ['One','Two','Three']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   837
        # all labels top-centre aligned apart from the last
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   838
        self.labels.boxAnchor = 'e'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   839
        self.labels[2].boxAnchor = 's'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   840
        self.labels[2].angle = 90
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   841
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   842
        d = Drawing(200, 100)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   843
        d.add(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   844
        return d
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   845
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   846
    def joinToAxis(self, xAxis, mode='left', pos=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   847
        "Join with x-axis using some mode."
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   848
1803
1f02a9cb6f48 Fix up bugs in joinAxisMode handling
rgbecker
parents: 1801
diff changeset
   849
        _assertXAxis(xAxis)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   850
        if mode == 'left':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   851
            self._x = xAxis._x * 1.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   852
        elif mode == 'right':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   853
            self._x = (xAxis._x + xAxis._length) * 1.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   854
        elif mode == 'value':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   855
            self._x = xAxis.scale(pos) * 1.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   856
        elif mode == 'points':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   857
            self._x = pos * 1.0
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   858
2516
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   859
    def _joinToAxis(self):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   860
        ja = self.joinAxis
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   861
        if ja:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   862
            jam = self.joinAxisMode
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   863
            if jam in ('left', 'right'):
3589
adbc6aafc51c axes.py: complete _joinToAxis cleanup
rgbecker
parents: 3584
diff changeset
   864
                self.joinToAxis(ja, mode=jam)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   865
            elif jam in ('value', 'points'):
3589
adbc6aafc51c axes.py: complete _joinToAxis cleanup
rgbecker
parents: 3584
diff changeset
   866
                self.joinToAxis(ja, mode=jam, pos=self.joinAxisPos)
882
b5cec3c4c9d3 Made joining of axes possible via axes attributes.
dinu_gherman
parents: 854
diff changeset
   867
2516
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   868
    def scale(self, idx):
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   869
        "Returns the y position and width in drawing units of the slice."
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   870
        return (self._y + self._scale(idx)*self._barWidth, self._barWidth)
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   871
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   872
    def makeAxis(self):
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   873
        g = Group()
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   874
        self._joinToAxis()
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   875
        if not self.visibleAxis: return g
cdfd0126c655 merge stable 2657:2658 axes/lineplots.py: fix inFill behaviour
rgbecker
parents: 2441
diff changeset
   876
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   877
        axis = Line(self._x, self._y-self.loLLen, self._x, self._y + self._length+self.hiLLen)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   878
        axis.strokeColor = self.strokeColor
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   879
        axis.strokeWidth = self.strokeWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   880
        axis.strokeDashArray = self.strokeDashArray
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   881
        g.add(axis)
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
   882
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   883
        return g
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   884
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   885
    def makeTickLabels(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   886
        g = Group()
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   887
3245
24391f33f6b1 axes.py: YCategoryAxis makeTickLabels fix contributed by Mike Folwell <mjf@pearson.co.uk>
rgbecker
parents: 3236
diff changeset
   888
        if not self.visibleLabels: return g
923
4f15a54e6fac Added visibleAxis/visibleTicks attributes.
dinu_gherman
parents: 910
diff changeset
   889
2522
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   890
        categoryNames = self.categoryNames
2580
318552322f36 reportlab: minor fix to axes.py
rgbecker
parents: 2538
diff changeset
   891
        if categoryNames is not None:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   892
            catCount = self._catCount
2522
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   893
            n = len(categoryNames)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   894
            reverseDirection = self.reverseDirection
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   895
            barWidth = self._barWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   896
            labels = self.labels
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   897
            _x = self._labelAxisPos()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   898
            _y = self._y
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   899
            pmv = self._pmv if self.labelAxisMode=='axispmv' else None
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   900
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3683
diff changeset
   901
            for i in range(catCount):
2522
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   902
                if reverseDirection: ic = catCount-i-1
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   903
                else: ic = i
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   904
                if ic>=n: continue
3391
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   905
                label=i-catCount
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   906
                if label in self.labels:
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   907
                    label = self.labels[label]
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   908
                else:
45b63c8586ee axes.py: allow for negative labels indeces so we can modify labels[-1] etc etc
rgbecker
parents: 3381
diff changeset
   909
                    label = self.labels[i]
3381
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   910
                lpf = label.labelPosFrac
37bc971ef029 barcharts.py/axes.py: support for bar like category labels
rgbecker
parents: 3378
diff changeset
   911
                y = _y + (i+lpf) * barWidth
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   912
                if pmv:
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   913
                    _dx = label.dx
3647
8bfe7cd78f43 axes.py: make category name placing a bit more intelligent
robin
parents: 3617
diff changeset
   914
                    v = label._pmv = pmv[ic]
3754
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   915
                    if v<0: _dx *= -2
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   916
                else:
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   917
                    _dx = 0
7c3fb137ead7 apply 3696 axes.py: fix bug in tick label positioning & fix reduce import
robin
parents: 3721
diff changeset
   918
                label.setOrigin(_x+_dx, y)
2522
c662297eb109 axes.py: make YCategoryAxis accept less than n labels
rgbecker
parents: 2516
diff changeset
   919
                label.setText(categoryNames[ic] or '')
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   920
                g.add(label)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   921
        return g
737
8f0e58918da9 Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff changeset
   922
2793
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   923
class TickLabeller:
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   924
    '''Abstract base class which may be used to indicate a change
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   925
    in the call signature for callable label formats
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   926
    '''
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   927
    def __call__(self,axis,value):
875b4de7e1ae axes.py: added TickLabeller class
rgbecker
parents: 2714
diff changeset
   928
        return 'Abstract class instance called'
882
b5cec3c4c9d3 Made joining of axes possible via axes attributes.
dinu_gherman
parents: 854
diff changeset
   929
4273
c75089f14f46 fix python>=3.2 default axis labelling to match python2.x; bugfix contributed by Robin Westin bitbucket issue #82
robin
parents: 4271
diff changeset
   930
#this matches the old python str behaviour
c75089f14f46 fix python>=3.2 default axis labelling to match python2.x; bugfix contributed by Robin Westin bitbucket issue #82
robin
parents: 4271
diff changeset
   931
_defaultLabelFormatter = lambda x: '%.12g' % x
c75089f14f46 fix python>=3.2 default axis labelling to match python2.x; bugfix contributed by Robin Westin bitbucket issue #82
robin
parents: 4271
diff changeset
   932
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   933
# Value axes.
2036
d0905af12237 First changes needed for 3d bars
rgbecker
parents: 2029
diff changeset
   934
class ValueAxis(_AxisG):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   935
    "Abstract value axis, unusable in itself."
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
   936
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   937
    _attrMap = AttrMap(
1957
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
   938
        forceZero = AttrMapValue(EitherOr((isBoolean,OneOf('near'))), desc='Ensure zero in range if true.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   939
        visible = AttrMapValue(isBoolean, desc='Display entire object, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   940
        visibleAxis = AttrMapValue(isBoolean, desc='Display axis line, if true.'),
2116
fbcc73b25408 Add visibleLabels to value Axes
rgbecker
parents: 2082
diff changeset
   941
        visibleLabels = AttrMapValue(isBoolean, desc='Display axis labels, if true.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   942
        visibleTicks = AttrMapValue(isBoolean, desc='Display axis ticks, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   943
        visibleGrid = AttrMapValue(isBoolean, desc='Display axis grid, if true.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   944
        strokeWidth = AttrMapValue(isNumber, desc='Width of axis line and ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   945
        strokeColor = AttrMapValue(isColorOrNone, desc='Color of axis line and ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   946
        strokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array used for axis line.'),
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   947
        strokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Line cap 0=butt, 1=round & 2=square"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   948
        strokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Line join 0=miter, 1=round & 2=bevel"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   949
        strokeMiterLimit = AttrMapValue(isNumber,desc="miter limit control miter line joins"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   950
        gridStrokeWidth = AttrMapValue(isNumber, desc='Width of grid lines.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   951
        gridStrokeColor = AttrMapValue(isColorOrNone, desc='Color of grid lines.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   952
        gridStrokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array used for grid lines.'),
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   953
        gridStrokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Grid Line cap 0=butt, 1=round & 2=square"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   954
        gridStrokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Grid Line join 0=miter, 1=round & 2=bevel"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
   955
        gridStrokeMiterLimit = AttrMapValue(isNumber,desc="Grid miter limit control miter line joins"),
1934
104a813e8402 Attempt at getting SplitLinePlot & allow for inFill
rgbecker
parents: 1933
diff changeset
   956
        gridStart = AttrMapValue(isNumberOrNone, desc='Start of grid lines wrt axis origin'),
104a813e8402 Attempt at getting SplitLinePlot & allow for inFill
rgbecker
parents: 1933
diff changeset
   957
        gridEnd = AttrMapValue(isNumberOrNone, desc='End of grid lines wrt axis origin'),
3206
25606c688529 charts: silly attempt at getting the grid to draw last
rgbecker
parents: 3032
diff changeset
   958
        drawGridLast = AttrMapValue(isBoolean, desc='if true draw gridlines after everything else.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   959
        minimumTickSpacing = AttrMapValue(isNumber, desc='Minimum value for distance between ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   960
        maximumTicks = AttrMapValue(isNumber, desc='Maximum number of ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   961
        labels = AttrMapValue(None, desc='Handle of the axis labels.'),
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   962
        labelAxisMode = AttrMapValue(OneOf('high','low','axis'), desc="Like joinAxisMode, but for the axis labels"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   963
        labelTextFormat = AttrMapValue(None, desc='Formatting string or function used for axis labels.'),
1996
0150666f5022 dded in stuff for area plots, fixes to axis formatting etc
rgbecker
parents: 1974
diff changeset
   964
        labelTextPostFormat = AttrMapValue(None, desc='Extra Formatting string.'),
0150666f5022 dded in stuff for area plots, fixes to axis formatting etc
rgbecker
parents: 1974
diff changeset
   965
        labelTextScale = AttrMapValue(isNumberOrNone, desc='Scaling for label tick values.'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   966
        valueMin = AttrMapValue(isNumberOrNone, desc='Minimum value on axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   967
        valueMax = AttrMapValue(isNumberOrNone, desc='Maximum value on axis.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   968
        valueStep = AttrMapValue(isNumberOrNone, desc='Step size used between ticks.'),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   969
        valueSteps = AttrMapValue(isListOfNumbersOrNone, desc='List of step sizes used between ticks.'),
1946
a5a348e2df9d Allow avoidBoundFrac to be a tuple
rgbecker
parents: 1942
diff changeset
   970
        avoidBoundFrac = AttrMapValue(EitherOr((isNumberOrNone,SequenceOf(isNumber,emptyOK=0,lo=2,hi=2))), desc='Fraction of interval to allow above and below.'),
3392
7be660ffcae3 axes.py: add avoidBoundSpace
rgbecker
parents: 3391
diff changeset
   971
        avoidBoundSpace = AttrMapValue(EitherOr((isNumberOrNone,SequenceOf(isNumber,emptyOK=0,lo=2,hi=2))), desc='Space to allow above and below.'),
3378
1f4d656fb22f axes.py: added abf_ignore_zero, fixed force zero bug
rgbecker
parents: 3368
diff changeset
   972
        abf_ignore_zero = AttrMapValue(EitherOr((NoneOr(isBoolean),SequenceOf(isBoolean,emptyOK=0,lo=2,hi=2))), desc='Set to True to make the avoidBoundFrac calculations treat zero as non-special'),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
   973
        rangeRound=AttrMapValue(OneOf('none','both','ceiling','floor'),'How to round the axis limits'),
1967
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
   974
        zrangePref = AttrMapValue(isNumberOrNone, desc='Zero range axis limit preference.'),
2068
6a398064dd55 Working HorizontalLineCharts3D
rgbecker
parents: 2054
diff changeset
   975
        style = AttrMapValue(OneOf('normal','stacked','parallel_3d'),"How values are plotted!"),
2848
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
   976
        skipEndL = AttrMapValue(OneOf('none','start','end','both'), desc='Skip high/low tick labels'),
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
   977
        origShiftIPC = AttrMapValue(isNumberOrNone, desc='Lowest label shift interval ratio.'),
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
   978
        origShiftMin = AttrMapValue(isNumberOrNone, desc='Minimum amount to shift.'),
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
   979
        origShiftSpecialValue = AttrMapValue(isNumberOrNone, desc='special value for shift'),
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
   980
        tickAxisMode = AttrMapValue(OneOf('high','low','axis'), desc="Like joinAxisMode, but for the ticks"),
3208
0b16634a87f9 axes.py: allow value axes to be reversible
rgbecker
parents: 3206
diff changeset
   981
        reverseDirection = AttrMapValue(isBoolean, desc='If true reverse category direction.'),
3235
ea83d033ad7d axes.py: added AxisLineAnnotation
rgbecker
parents: 3234
diff changeset
   982
        annotations = AttrMapValue(None,desc='list of annotations'),
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   983
        loLLen = AttrMapValue(isNumber, desc='extra line length before start of the axis'),
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
   984
        hiLLen = AttrMapValue(isNumber, desc='extra line length after end of the axis'),
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   985
        subTickNum = AttrMapValue(isNumber, desc='Number of axis sub ticks, if >0'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   986
        subTickLo = AttrMapValue(isNumber, desc='sub tick down or left'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   987
        subTickHi = AttrMapValue(isNumber, desc='sub tick up or right'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   988
        visibleSubTicks = AttrMapValue(isBoolean, desc='Display axis sub ticks, if true.'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   989
        visibleSubGrid = AttrMapValue(isBoolean, desc='Display axis sub grid, if true.'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   990
        subGridStrokeWidth = AttrMapValue(isNumber, desc='Width of grid lines.'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   991
        subGridStrokeColor = AttrMapValue(isColorOrNone, desc='Color of grid lines.'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   992
        subGridStrokeDashArray = AttrMapValue(isListOfNumbersOrNone, desc='Dash array used for grid lines.'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   993
        subGridStrokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Grid Line cap 0=butt, 1=round & 2=square"),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   994
        subGridStrokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Grid Line join 0=miter, 1=round & 2=bevel"),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   995
        subGridStrokeMiterLimit = AttrMapValue(isNumber,desc="Grid miter limit control miter line joins"),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   996
        subGridStart = AttrMapValue(isNumberOrNone, desc='Start of grid lines wrt axis origin'),
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
   997
        subGridEnd = AttrMapValue(isNumberOrNone, desc='End of grid lines wrt axis origin'),
3403
ff270718579d added forceTickLabelsInside
andy
parents: 3402
diff changeset
   998
        keepTickLabelsInside = AttrMapValue(isBoolean, desc='Ensure tick labels do not project beyond bounds of axis if true'),
3548
dfb3110087ad axes.py, lineplots.py: added some features for lines/grids on charts
rgbecker
parents: 3531
diff changeset
   999
        skipGrid = AttrMapValue(OneOf('none','top','both','bottom'),"grid lines to skip top bottom both none"),
3683
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1000
        requiredRange = AttrMapValue(isNumberOrNone, desc='Minimum required value range.'),
4182
2d2580fd00c6 axes.py add innerTickDraw callback option, version-->3.1.53
robin
parents: 4150
diff changeset
  1001
        innerTickDraw = AttrMapValue(isNoneOrCallable, desc="Callable to replace _drawInnerTicks"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1002
        )
852
6f2543f14d9b Moved some common stuff into ValueAxis, added maximumTicks
rgbecker
parents: 850
diff changeset
  1003
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1004
    def __init__(self,**kw):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1005
        assert self.__class__.__name__!='ValueAxis', 'Abstract Class ValueAxis Instantiated'
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1006
        self._setKeywords(**kw)
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1007
        self._setKeywords(
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1008
                        _configured = 0,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1009
                        # private properties set by methods.  The initial values
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1010
                        # here are to make demos easy; they would always be
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1011
                        # overridden in real life.
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1012
                        _x = 50,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1013
                        _y = 50,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1014
                        _length = 100,
854
8a98bd0ac7d8 Move common value axis bits into base class
rgbecker
parents: 853
diff changeset
  1015
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1016
                        # public properties
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1017
                        visible = 1,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1018
                        visibleAxis = 1,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1019
                        visibleLabels = 1,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1020
                        visibleTicks = 1,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1021
                        visibleGrid = 0,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1022
                        forceZero = 0,
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
  1023
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1024
                        strokeWidth = 1,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1025
                        strokeColor = STATE_DEFAULTS['strokeColor'],
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1026
                        strokeDashArray = STATE_DEFAULTS['strokeDashArray'],
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1027
                        strokeLineJoin =  STATE_DEFAULTS['strokeLineJoin'],
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1028
                        strokeLineCap = STATE_DEFAULTS['strokeLineCap'],
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1029
                        strokeMiterLimit = STATE_DEFAULTS['strokeMiterLimit'],
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1030
                        gridStrokeWidth = 0.25,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1031
                        gridStrokeColor = STATE_DEFAULTS['strokeColor'],
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1032
                        gridStrokeDashArray = STATE_DEFAULTS['strokeDashArray'],
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1033
                        gridStrokeLineJoin =  STATE_DEFAULTS['strokeLineJoin'],
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1034
                        gridStrokeLineCap = STATE_DEFAULTS['strokeLineCap'],
070271955526 graphics: add in some line properties
rgbecker
parents: 3229
diff changeset
  1035
                        gridStrokeMiterLimit = STATE_DEFAULTS['strokeMiterLimit'],
2700
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
  1036
                        gridStart = None,
1fa1f6a89e52 charts: improvements to Axes
rgbecker
parents: 2690
diff changeset
  1037
                        gridEnd = None,
3206
25606c688529 charts: silly attempt at getting the grid to draw last
rgbecker
parents: 3032
diff changeset
  1038
                        drawGridLast = False,
3252
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1039
                        visibleSubGrid = 0,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1040
                        visibleSubTicks = 0,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1041
                        subTickNum = 0,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1042
                        subTickLo = 0,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1043
                        subTickHi = 0,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1044
                        subGridStrokeLineJoin = STATE_DEFAULTS['strokeLineJoin'],
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1045
                        subGridStrokeLineCap = STATE_DEFAULTS['strokeLineCap'],
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1046
                        subGridStrokeMiterLimit = STATE_DEFAULTS['strokeMiterLimit'],
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1047
                        subGridStrokeWidth = 0.25,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1048
                        subGridStrokeColor = STATE_DEFAULTS['strokeColor'],
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1049
                        subGridStrokeDashArray = STATE_DEFAULTS['strokeDashArray'],
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1050
                        subGridStart = None,
94fdd5f8f031 axes.py: add support for 'sub' ticks and grids
rgbecker
parents: 3245
diff changeset
  1051
                        subGridEnd = None,
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1052
                        labels = TypedPropertyCollection(Label),
3403
ff270718579d added forceTickLabelsInside
andy
parents: 3402
diff changeset
  1053
                        keepTickLabelsInside = 0,
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
  1054
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1055
                        # how close can the ticks be?
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1056
                        minimumTickSpacing = 10,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1057
                        maximumTicks = 7,
907
7693d30d2746 Various minor changes.
dinu_gherman
parents: 893
diff changeset
  1058
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1059
                        # a format string like '%0.2f'
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1060
                        # or a function which takes the value as an argument and returns a string
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1061
                        _labelTextFormat = None,
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
  1062
                        labelAxisMode = 'axis',
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1063
                        labelTextFormat = None,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1064
                        labelTextPostFormat = None,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1065
                        labelTextScale = None,
830
670015a99a24 Factorized some more methods into abstract base classes.
dinu_gherman
parents: 829
diff changeset
  1066
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1067
                        # if set to None, these will be worked out for you.
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1068
                        # if you override any or all of them, your values
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1069
                        # will be used.
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1070
                        valueMin = None,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1071
                        valueMax = None,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1072
                        valueStep = None,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1073
                        avoidBoundFrac = None,
3392
7be660ffcae3 axes.py: add avoidBoundSpace
rgbecker
parents: 3391
diff changeset
  1074
                        avoidBoundSpace = None,
3378
1f4d656fb22f axes.py: added abf_ignore_zero, fixed force zero bug
rgbecker
parents: 3368
diff changeset
  1075
                        abf_ignore_zero = False,
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1076
                        rangeRound = 'none',
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1077
                        zrangePref = 0,
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1078
                        style = 'normal',
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2829
diff changeset
  1079
                        skipEndL='none',
2848
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
  1080
                        origShiftIPC = None,
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
  1081
                        origShiftMin = None,
62db2318e9fa charts: more changes to axes and lineplots
rgbecker
parents: 2847
diff changeset
  1082
                        origShiftSpecialValue = None,
2920
4a59381425d1 charts: add labelAxisMode,tickAxisMode to valueAxes
rgbecker
parents: 2864
diff changeset
  1083
                        tickAxisMode = 'axis',
3208
0b16634a87f9 axes.py: allow value axes to be reversible
rgbecker
parents: 3206
diff changeset
  1084
                        reverseDirection=0,
3236
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
  1085
                        loLLen=0,
1563446a1bed axes.py: added in loLLen and hiLLen for axis extension
rgbecker
parents: 3235
diff changeset
  1086
                        hiLLen=0,
3683
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1087
                        requiredRange=0,
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1088
                        )
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1089
        self.labels.angle = 0
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
  1090
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1091
    def setPosition(self, x, y, length):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1092
        # ensure floating point
3229
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
  1093
        self._x = float(x)
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
  1094
        self._y = float(y)
366fafbe1fef axes.py: add support for category axis lo & hi Pad
rgbecker
parents: 3208
diff changeset
  1095
        self._length = float(length)
1195
3e620ee48f0a Moved from fidlineplot
rgbecker
parents: 1178
diff changeset
  1096
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1097
    def configure(self, dataSeries):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1098
        """Let the axis configure its scale and range based on the data.
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
  1099
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1100
        Called after setPosition. Let it look at a list of lists of
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1101
        numbers determine the tick mark intervals.  If valueMin,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1102
        valueMax and valueStep are configured then it
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1103
        will use them; if any of them are set to None it
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1104
        will look at the data and make some sensible decision.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1105
        You may override this to build custom axes with
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1106
        irregular intervals.  It creates an internal
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1107
        variable self._values, which is a list of numbers
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1108
        to use in plotting.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1109
        """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1110
        self._setRange(dataSeries)
2673
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1111
        self._configure_end()
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1112
fb2289f033a9 axes.py: allow value axes to be more standalone
rgbecker
parents: 2652
diff changeset
  1113
    def _configure_end(self):
1957
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1114
        self._calcTickmarkPositions()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1115
        self._calcScaleFactor()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1116
        self._configured = 1
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
  1117
1957
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1118
    def _getValueStepAndTicks(self, valueMin, valueMax,cache={}):
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1119
        try:
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1120
            K = (valueMin,valueMax)
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1121
            r = cache[K]
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1122
        except:
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1123
            self._valueMin = valueMin
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1124
            self._valueMax = valueMax
2829
4019b82d26b4 axes.py: try to stamp out another buglet
rgbecker
parents: 2826
diff changeset
  1125
            valueStep,T = self._calcStepAndTickPositions()
1957
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1126
            r = cache[K] = valueStep, T, valueStep*1e-8
1c7a9e4d8e7a Move avoidBoundFrac etc into base class
rgbecker
parents: 1956
diff changeset
  1127
        return r
829
fa534b71604e Added new abstract base classes CategoryAxis and ValueAxis.
dinu_gherman
parents: 827
diff changeset
  1128
3683
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1129
    def _preRangeAdjust(self,valueMin,valueMax):
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1130
        rr = self.requiredRange
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1131
        if rr>0:
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1132
            r = valueMax - valueMin
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1133
            if r<rr:
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1134
                m = 0.5*(valueMax+valueMin)
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1135
                rr *= 0.5
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1136
                y1 = min(m-rr,valueMin)
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1137
                y2 = max(m+rr,valueMax)
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1138
                if valueMin>=100 and y1<100:
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1139
                    y2 = y2 + 100 - y1
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1140
                    y1 = 100
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1141
                elif valueMin>=0 and y1<0:
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1142
                    y2 = y2 - y1
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1143
                    y1 = 0
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1144
                valueMin = self._cValueMin = y1
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1145
                valueMax = self._cValueMax = y2
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1146
        return valueMin,valueMax
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1147
261502a485a2 reportlab\graphics\charts\axes.py: move requireRange and check in _preRangeAdjust
robin
parents: 3647
diff changeset
  1148
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1149
    def _setRange(self, dataSeries):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1150
        """Set minimum and maximum axis values.
830
670015a99a24 Factorized some more methods into abstract base classes.
dinu_gherman
parents: 829
diff changeset
  1151
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1152
        The dataSeries argument is assumed to be a list of data
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1153
        vectors. Each vector is itself a list or tuple of numbers.
830
670015a99a24 Factorized some more methods into abstract base classes.
dinu_gherman
parents: 829
diff changeset
  1154
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1155
        Returns a min, max tuple.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1156
        """
907
7693d30d2746 Various minor changes.
dinu_gherman
parents: 893
diff changeset
  1157
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
  1158
        oMin = valueMin = self.valueMin
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
  1159
        oMax = valueMax = self.valueMax
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
  1160
        if valueMin is None: valueMin = self._cValueMin = _findMin(dataSeries,self._dataIndex,0)
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
  1161
        if valueMax is None: valueMax = self._cValueMax = _findMax(dataSeries,self._dataIndex,0)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1162
        if valueMin == valueMax:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1649
diff changeset
  1163
            if valueMax==0:
1998
bac8395354d1 Fixup for bubble charts
rgbecker
parents: 1996
diff changeset
  1164
                if oMin is None and oMax is None:
1967
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1165
                    zrp = getattr(self,'zrangePref',0)
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1166
                    if zrp>0:
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1167
                        valueMax = zrp
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1168
                        valueMin = 0
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1169
                    elif zrp<0:
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1170
                        valueMax = 0
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1171
                        valueMin = zrp
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1172
                    else:
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1173
                        valueMax = 0.01
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1174
                        valueMin = -0.01
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1175
                elif self.valueMin is None:
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff changeset
  1176
                    valueMin = -0.01
86fb6441ee17 Added zrangePref
rgbecker
parents: 1964
diff