NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

axis.py (13331B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\graphs\axis.py
      2 import math
      3 import blue
      4 import localization
      5 from carbon.common.script.util.commonutils import StripTags
      6 from signals import Signal
      7 AXIS_TIGHT = 0
      8 AXIS_FROM_ZERO = 1
      9 AXIS_CUSTOM = 2
     10 AXIS_FILTERED = 3
     11 
     12 class AxisOrientation(object):
     13     HORIZONTAL = 0
     14     VERTICAL = 1
     15 
     16 
     17 class InteractionLimit(object):
     18     NONE = 0
     19     DATA_RANGE = 1
     20     DATA_AND_VIEWPORT_RANGE = 2
     21 
     22 
     23 def GetStrippedLabel(path, **kwargs):
     24     label = localization.GetByLabel(path, **kwargs)
     25     if isinstance(label, basestring):
     26         label = StripTags(label, stripOnly=['localized'])
     27     return label
     28 
     29 
     30 def GetRangeFromSequences(*sequences):
     31     minv = None
     32     maxv = None
     33     for sequence in sequences:
     34         if sequence:
     35             v = min(sequence)
     36             if minv is None:
     37                 minv = v
     38             else:
     39                 minv = min(minv, v)
     40             v = max(sequence)
     41             if maxv is None:
     42                 maxv = v
     43             else:
     44                 maxv = max(maxv, v)
     45 
     46     return (minv, maxv)
     47 
     48 
     49 def FixupRange(dataRange):
     50     dataRange = (float(dataRange[0]), float(dataRange[1]))
     51     if dataRange[0] > dataRange[1]:
     52         dataRange = (dataRange[1], dataRange[0])
     53     if dataRange[0] == dataRange[1]:
     54         dataRange = (dataRange[0], dataRange[0] + 0.1)
     55     return dataRange
     56 
     57 
     58 class BaseAxis(object):
     59 
     60     def __init__(self, dataRange, viewportRange = (0.0, 1.0), visibleRange = None, behavior = AXIS_TIGHT, margins = (0.0, 0.0), interactionLimit = InteractionLimit.DATA_AND_VIEWPORT_RANGE, labelFormat = str):
     61         self._dataRange = FixupRange(dataRange)
     62         self._viewportRange = viewportRange
     63         self._visibleRange = FixupRange(visibleRange or dataRange)
     64         self._margins = margins
     65         self._behavior = behavior
     66         self._interactionLimit = interactionLimit
     67         self._labelFormat = labelFormat
     68         self.onChange = Signal(signalName='onChange')
     69         self._UpdateVisibleRange()
     70 
     71     def MapToView(self, value):
     72         return (value - self._visibleRange[0]) / (self._visibleRange[1] - self._visibleRange[0])
     73 
     74     def MapFromView(self, value):
     75         return self._visibleRange[0] + value * (self._visibleRange[1] - self._visibleRange[0])
     76 
     77     def MapToViewport(self, value):
     78         v = self.MapToView(value)
     79         return self._viewportRange[0] * (1 - v) + self._viewportRange[1] * v
     80 
     81     def MapFromViewport(self, value):
     82         v = (value - self._viewportRange[0]) / (self._viewportRange[1] - self._viewportRange[0])
     83         return self.MapFromView(v)
     84 
     85     def MapSequenceToViewport(self, sequence):
     86         visible = (self._viewportRange[1] - self._viewportRange[0]) / (self._visibleRange[1] - self._visibleRange[0])
     87         offset = self._viewportRange[0] - self._visibleRange[0] * visible
     88         return (offset + value * visible for value in sequence)
     89 
     90     def UpdateToViewportTransform(self, transform, column, dpiScaling = 1):
     91         visible = (self._viewportRange[1] - self._viewportRange[0]) / (self._visibleRange[1] - self._visibleRange[0])
     92         offset = (self._viewportRange[0] - self._visibleRange[0] * visible) * dpiScaling
     93         scale = visible * dpiScaling
     94         if column == 0:
     95             row0 = list(transform[0])
     96             row0[0] = scale
     97             row2 = list(transform[2])
     98             row2[0] = offset
     99             return (tuple(row0), transform[1], tuple(row2))
    100         else:
    101             row1 = list(transform[1])
    102             row1[1] = scale
    103             row2 = list(transform[2])
    104             row2[1] = offset
    105             return (transform[0], tuple(row1), tuple(row2))
    106 
    107     def SetViewportRange(self, viewport):
    108         if self._viewportRange == viewport:
    109             return
    110         self._viewportRange = viewport
    111         self._OnChange()
    112 
    113     def GetViewportRange(self):
    114         return self._viewportRange
    115 
    116     def GetViewportSize(self):
    117         return self._viewportRange[1] - self._viewportRange[0]
    118 
    119     def SetDataRange(self, dataRange):
    120         self._dataRange = dataRange
    121         self._UpdateVisibleRange()
    122         self._OnChange()
    123 
    124     def ZoomOn(self, visibleRange):
    125         if visibleRange is None:
    126             self._UpdateVisibleRange()
    127             self._OnChange()
    128             return
    129         scope = self._dataRange[1] - self._dataRange[0]
    130         if self._behavior == AXIS_FROM_ZERO:
    131             self._visibleRange = (self._visibleRange[0], visibleRange[1] + scope * self._margins[1])
    132         elif self._behavior == AXIS_TIGHT:
    133             self._visibleRange = (visibleRange[0] - scope * self._margins[0], visibleRange[1] + scope * self._margins[1])
    134         else:
    135             self._visibleRange = visibleRange
    136         self._visibleRange = FixupRange(self._visibleRange)
    137         self._OnChange()
    138 
    139     def GetDataRange(self):
    140         return self._dataRange
    141 
    142     def GetVisibleRange(self):
    143         return self._visibleRange
    144 
    145     def SetVisibleRange(self, visibleRange):
    146         if self._visibleRange != visibleRange:
    147             self._visibleRange = visibleRange
    148             self._OnChange()
    149 
    150     def GetBehavior(self):
    151         return self._behavior
    152 
    153     def SetBehavior(self, behavior):
    154         if self._behavior == behavior:
    155             return
    156         self._behavior = behavior
    157         self._UpdateVisibleRange()
    158         self._OnChange()
    159 
    160     def _UpdateVisibleRange(self):
    161         scope = self._dataRange[1] - self._dataRange[0]
    162         if self._behavior == AXIS_FROM_ZERO:
    163             self._visibleRange = (min(self._dataRange[0], 0), self._dataRange[1] + scope * self._margins[1])
    164         elif self._behavior == AXIS_TIGHT:
    165             self._visibleRange = (self._dataRange[0] - scope * self._margins[0], self._dataRange[1] + scope * self._margins[1])
    166         self._visibleRange = FixupRange(self._visibleRange)
    167 
    168     def Zoom(self, amount, ratio = 0.5):
    169         self._behavior = AXIS_CUSTOM
    170         scope = self._visibleRange[1] - self._visibleRange[0]
    171         amount *= scope
    172         if not amount:
    173             return
    174         oldVisibleRange = self._visibleRange
    175         self._visibleRange = (self._visibleRange[0] + amount * ratio, self._visibleRange[1] - amount * (1.0 - ratio))
    176         dataRange = abs(self.MapToView(self._dataRange[0]) - self.MapToView(self._dataRange[1]))
    177         if dataRange > 200 and amount > 0 or dataRange < 0.01 and amount < 0:
    178             self._visibleRange = oldVisibleRange
    179             return
    180         if self._visibleRange[1] <= self._visibleRange[0] or math.isinf(self._visibleRange[0]) or math.isinf(self._visibleRange[1]):
    181             self._visibleRange = oldVisibleRange
    182             return
    183         if abs(self.MapToViewport(self._dataRange[0]) - self.MapToViewport(self._dataRange[1])) < 1:
    184             self._visibleRange = oldVisibleRange
    185             return
    186         self._OnChange()
    187 
    188     def Pan(self, amount):
    189         scope = self._visibleRange[1] - self._visibleRange[0]
    190         delta = amount * scope
    191         if not delta:
    192             return
    193         self._behavior = AXIS_CUSTOM
    194         if self._interactionLimit == InteractionLimit.DATA_AND_VIEWPORT_RANGE:
    195             if self._visibleRange[1] + delta < self._dataRange[0]:
    196                 delta = self._dataRange[0] - self._visibleRange[1]
    197             if self._visibleRange[0] + delta > self._dataRange[1]:
    198                 delta = self._dataRange[1] - self._visibleRange[0]
    199         elif self._interactionLimit == InteractionLimit.DATA_RANGE:
    200             if self._visibleRange[0] + delta < self._dataRange[0]:
    201                 delta = self._dataRange[0] - self._visibleRange[0]
    202             if self._visibleRange[1] + delta > self._dataRange[1]:
    203                 delta = self._dataRange[1] - self._visibleRange[1]
    204         self._visibleRange = (self._visibleRange[0] + delta, self._visibleRange[1] + delta)
    205         self._OnChange()
    206 
    207     def GetTicks(self):
    208         return ()
    209 
    210     def GetTickLabel(self, tickValue):
    211         return self._labelFormat(tickValue)
    212 
    213     def _OnChange(self):
    214         self.onChange(self)
    215 
    216     def GetRangeText(self, start, end):
    217         return str(end - start)
    218 
    219 
    220 class CategoryAxis(BaseAxis):
    221 
    222     def __init__(self, dataPoints, *args, **kwargs):
    223         super(CategoryAxis, self).__init__((-0.5, len(dataPoints) - 0.5), *args, **kwargs)
    224         self._dataPoints = dataPoints
    225 
    226     def GetDataPoints(self):
    227         return self._dataPoints
    228 
    229     def SetDataPoints(self, dataPoints, updateRange = True):
    230         self._dataPoints = dataPoints
    231         if updateRange:
    232             dataRange = FixupRange((-0.5, len(dataPoints) - 0.5))
    233             self.SetDataRange(dataRange)
    234 
    235     def MapDataPointsToViewport(self):
    236         return self.MapSequenceToViewport(xrange(len(self._dataPoints)))
    237 
    238     def GetTicks(self):
    239         return range(len(self._dataPoints))
    240 
    241     def GetTickLabel(self, tickValue):
    242         return self._labelFormat(self._dataPoints[tickValue])
    243 
    244     def GetRangeText(self, start, end):
    245         return ''
    246 
    247 
    248 class AutoTicksAxis(BaseAxis):
    249 
    250     def __init__(self, dataRange, tickCount = 0, tickFilter = None, tickBase = 10, *args, **kwargs):
    251         super(AutoTicksAxis, self).__init__(dataRange, *args, **kwargs)
    252         self._tickCount = tickCount
    253         self._tickFilter = tickFilter
    254         self._ticks = []
    255         self._tickBase = tickBase
    256         self._UpdateTicks()
    257 
    258     def SetTickCount(self, tickCount):
    259         self._tickCount = tickCount
    260         self._OnChange()
    261 
    262     def GetTicks(self):
    263         return self._ticks
    264 
    265     def _UpdateTicks(self):
    266         if not self._tickCount:
    267             self._ticks = []
    268             return
    269         delta = (self._visibleRange[1] - self._visibleRange[0]) / self._tickCount
    270         delta = self._tickBase ** math.ceil(math.log(delta, self._tickBase))
    271         start = math.floor(self._visibleRange[0] / delta) * delta
    272         cnt = int((self._visibleRange[1] - self._visibleRange[0]) / delta)
    273         while cnt * 2 < self._tickCount:
    274             delta /= 2
    275             cnt = int((self._visibleRange[1] - self._visibleRange[0]) / delta)
    276 
    277         incr = 0
    278         result = []
    279         while start + incr <= self._visibleRange[1]:
    280             if not self._tickFilter or self._tickFilter(start + incr):
    281                 if not result or result[-1] != start + incr:
    282                     result.append(start + incr)
    283             incr += delta
    284 
    285         self._ticks = result
    286 
    287     def _OnChange(self):
    288         self._UpdateTicks()
    289         super(AutoTicksAxis, self)._OnChange()
    290 
    291 
    292 class AutoTicksCategoryAxis(CategoryAxis):
    293 
    294     def __init__(self, dataRange, tickCount = 0, tickFilter = None, tickBase = 10, *args, **kwargs):
    295         super(AutoTicksCategoryAxis, self).__init__(dataRange, *args, **kwargs)
    296         self._tickCount = tickCount
    297         self._tickFilter = tickFilter
    298         self._tickBase = tickBase
    299         self._ticks = []
    300         self._UpdateTicks()
    301 
    302     def SetTickCount(self, tickCount):
    303         self._tickCount = tickCount
    304         self._OnChange()
    305 
    306     def GetTicks(self):
    307         return self._ticks
    308 
    309     def _UpdateTicks(self):
    310         if not self._tickCount:
    311             self._ticks = []
    312             return
    313         delta = (self._visibleRange[1] - self._visibleRange[0]) / self._tickCount
    314         delta = self._tickBase ** math.ceil(math.log(delta, self._tickBase))
    315         a = math.floor(self._visibleRange[0] / delta) * delta
    316         cnt = int((self._visibleRange[1] - self._visibleRange[0]) / delta)
    317         while cnt * 2 < self._tickCount and delta > 1:
    318             delta /= 2
    319             cnt = int((self._visibleRange[1] - self._visibleRange[0]) / delta)
    320 
    321         result = []
    322         while a <= self._visibleRange[1]:
    323             if not self._tickFilter or self._tickFilter(a):
    324                 result.append(int(a))
    325             a += delta
    326 
    327         self._ticks = result
    328 
    329     def _OnChange(self):
    330         self._UpdateTicks()
    331         super(AutoTicksCategoryAxis, self)._OnChange()
    332 
    333 
    334 class MonthlyTimeAxis(CategoryAxis):
    335 
    336     def __init__(self, timestamps, *args, **kwargs):
    337         super(MonthlyTimeAxis, self).__init__(timestamps, *args, **kwargs)
    338         self._months = [GetStrippedLabel('/Carbon/UI/Common/Months/JanuaryShort'),
    339          GetStrippedLabel('/Carbon/UI/Common/Months/FebruaryShort'),
    340          GetStrippedLabel('/Carbon/UI/Common/Months/MarchShort'),
    341          GetStrippedLabel('/Carbon/UI/Common/Months/AprilShort'),
    342          GetStrippedLabel('/Carbon/UI/Common/Months/MayShort'),
    343          GetStrippedLabel('/Carbon/UI/Common/Months/JuneShort'),
    344          GetStrippedLabel('/Carbon/UI/Common/Months/JulyShort'),
    345          GetStrippedLabel('/Carbon/UI/Common/Months/AugustShort'),
    346          GetStrippedLabel('/Carbon/UI/Common/Months/SeptemberShort'),
    347          GetStrippedLabel('/Carbon/UI/Common/Months/OctoberShort'),
    348          GetStrippedLabel('/Carbon/UI/Common/Months/NovemberShort'),
    349          GetStrippedLabel('/Carbon/UI/Common/Months/DecemberShort')]
    350 
    351     def GetTicks(self):
    352         months = []
    353         for i, t in enumerate(self._dataPoints):
    354             if self._visibleRange[0] <= i <= self._visibleRange[1] and blue.os.GetTimeParts(t)[3] == 1:
    355                 months.append(i)
    356 
    357         return months
    358 
    359     def GetTickLabel(self, tickValue):
    360         month = blue.os.GetTimeParts(self._dataPoints[tickValue])[1]
    361         return self._months[month - 1]
    362 
    363     def GetRangeText(self, start, end):
    364         return str(int(round(end - start)))