bargraph.py (8584B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\graphs\bargraph.py 2 from carbonui.primitives.fill import Fill 3 from carbonui.primitives.polygon import Polygon 4 import carbonui.const as uiconst 5 from carbonui.graphs import animations 6 from carbonui.graphs.axis import AxisOrientation 7 from carbonui.uicore import uicore 8 from carbonui.util import colorblind 9 from carbonui.util.color import Color 10 11 class DynamicHint(object): 12 13 def __init__(self, callback): 14 self._callback = callback 15 16 def __getitem__(self, item): 17 return self._callback(item) 18 19 20 class BarGraph(Polygon): 21 default_name = 'BarGraph' 22 default_state = uiconst.UI_NORMAL 23 default_barSize = 7 24 25 def ApplyAttributes(self, attributes): 26 Polygon.ApplyAttributes(self, attributes) 27 self._categoryAxis = attributes['categoryAxis'] 28 self._valueAxis = attributes['valueAxis'] 29 self._orientation = attributes.get('orientation', AxisOrientation.VERTICAL) 30 self._categoryAxis.onChange.connect(self._AxisChanged) 31 self._valueAxis.onChange.connect(self._AxisChanged) 32 self._values = attributes['values'] 33 self._barColors = attributes.get('barColors', None) 34 self._vertices = None 35 self.barColor = self.GetRGBA() 36 self.hoverColor = attributes.get('hoverColor', self.barColor) 37 self.negativeColor = attributes.get('negativeColor', self.barColor) 38 self.negativeHoverColor = attributes.get('negativeHoverColor', self.negativeColor) 39 self.barSize = attributes.get('barSize', self.default_barSize) 40 self.barSizeMinMax = attributes.get('barSizeMinMax', (self.barSize, self.barSize)) 41 self.color = (1, 1, 1, 1) 42 self._locked = False 43 self._dirty = False 44 self._originalColor = self.color 45 self._animation = None 46 self._hoverIndex = None 47 self._tooltipRect = None 48 self._Build() 49 50 def GetLegendItem(self): 51 return Fill(name='legendVolume', color=self.barColor, align=uiconst.TOLEFT) 52 53 @property 54 def hint(self): 55 h = getattr(self, '_hint', None) 56 if not isinstance(h, basestring) and hasattr(h, '__getitem__'): 57 return h[self._hoverIndex] 58 return h 59 60 @hint.setter 61 def hint(self, value): 62 Polygon.hint.fset(self, value) 63 64 def GetTooltipPosition(self): 65 return self._tooltipRect 66 67 def Animate(self, animationType, animationDynamics, duration): 68 self.CancelAnimation() 69 self._animation = animations.CreateAnimation(self, self._categoryAxis, self._valueAxis, self._orientation, animationType, animationDynamics, duration, 4) 70 71 def CancelAnimation(self, applyLastFrame = True): 72 self.StopAnimations() 73 self.opacity = 1.0 74 if self._animation: 75 self._animation.Cancel(applyLastFrame) 76 self._animation = None 77 78 def Close(self): 79 self.CancelAnimation(False) 80 super(BarGraph, self).Close() 81 self._categoryAxis.onChange.disconnect(self._AxisChanged) 82 self._valueAxis.onChange.disconnect(self._AxisChanged) 83 84 def _Build(self): 85 dpiScaling = uicore.desktop.dpiScaling 86 barWidth = self._GetBarWidth() 87 barWidth *= dpiScaling 88 axisZero = self._valueAxis.MapToViewport(0) * dpiScaling 89 positions = [] 90 colors = [] 91 triangles = [] 92 for i, (x, y, value) in enumerate(zip(self._categoryAxis.MapDataPointsToViewport(), self._valueAxis.MapSequenceToViewport(self._values), self._values)): 93 x *= dpiScaling 94 y *= dpiScaling 95 color = self.GetBarColor(i, value) 96 if self._orientation == AxisOrientation.VERTICAL: 97 positions.append((x - barWidth, y)) 98 positions.append((x + barWidth, y)) 99 positions.append((x + barWidth, axisZero)) 100 positions.append((x - barWidth, axisZero)) 101 else: 102 positions.append((y, x - barWidth)) 103 positions.append((y, x + barWidth)) 104 positions.append((axisZero, x + barWidth)) 105 positions.append((axisZero, x - barWidth)) 106 colors.append(color) 107 colors.append(color) 108 colors.append(color) 109 colors.append(color) 110 triangles.append((4 * i, 4 * i + 1, 4 * i + 2)) 111 triangles.append((4 * i + 2, 4 * i + 3, 4 * i)) 112 113 self.AppendVertices(positions, None, colors) 114 self.renderObject.AppendTriangles(triangles) 115 self.width = max((x[0] for x in positions)) 116 self.height = max((x[1] for x in positions)) 117 118 def _Rescale(self): 119 dpiScaling = uicore.desktop.dpiScaling 120 barWidth = self._GetBarWidth() 121 barWidth *= dpiScaling 122 axisZero = self._valueAxis.MapToViewport(0) * dpiScaling 123 positions = [] 124 for i, (x, y) in enumerate(zip(self._categoryAxis.MapDataPointsToViewport(), self._valueAxis.MapSequenceToViewport(self._values))): 125 x *= dpiScaling 126 y *= dpiScaling 127 if self._orientation == AxisOrientation.VERTICAL: 128 positions.append((x - barWidth, y)) 129 positions.append((x + barWidth, y)) 130 positions.append((x + barWidth, axisZero)) 131 positions.append((x - barWidth, axisZero)) 132 else: 133 positions.append((y, x - barWidth)) 134 positions.append((y, x + barWidth)) 135 positions.append((axisZero, x + barWidth)) 136 positions.append((axisZero, x - barWidth)) 137 138 self.renderObject.SetVertices(positions) 139 140 def _GetBarWidth(self): 141 barWidth = abs(self._categoryAxis.MapToViewport(0) - self._categoryAxis.MapToViewport(1)) - 1 142 barWidth = min(max(barWidth, self.barSizeMinMax[0]), self.barSizeMinMax[1]) / 2.0 143 return barWidth 144 145 def _AxisChanged(self, _): 146 if self._locked: 147 self._dirty = True 148 else: 149 self._Rescale() 150 151 def AddBarHighlight(self, barIndex): 152 self._hoverIndex = barIndex 153 color = self.GetBarHoverColor(barIndex, self._values[self._hoverIndex]) 154 self._SetBarColor(color) 155 156 def _RemoveBarHighlight(self): 157 if self._hoverIndex is None: 158 return 159 color = self.GetBarColor(self._hoverIndex, self._values[self._hoverIndex]) 160 self._SetBarColor(color) 161 self._hoverIndex = None 162 163 def _SetBarColor(self, color): 164 color = colorblind.CheckReplaceColor(color) 165 offset = self._hoverIndex * 4 166 for each in range(4): 167 self.renderObject.vertices[offset + each].color = color 168 169 self.renderObject.SetDirty() 170 171 def GetBarColor(self, barIdx, value): 172 if self._barColors is None: 173 if value < 0: 174 return self.negativeColor 175 return self.barColor 176 return self._barColors[barIdx] 177 178 def GetBarHoverColor(self, barIdx, value): 179 if self._barColors is None: 180 if value < 0: 181 return self.negativeHoverColor 182 return self.hoverColor 183 else: 184 barColor = self._barColors[barIdx] 185 c = Color(*barColor) 186 sat = c.GetSaturation() 187 newSat = min(1.0, max(0.0, sat - 0.3)) 188 hoverColor = c.SetSaturation(newSat).GetRGBA() 189 return hoverColor 190 191 def OnMouseEnter(self, *args): 192 index = self.FindMouseoverIndex() 193 self._RemoveBarHighlight() 194 self.AddBarHighlight(index) 195 dpiScaling = uicore.desktop.dpiScaling 196 offset = index * 4 197 tl = self.renderObject.vertices[offset].position 198 br = self.renderObject.vertices[offset + 2].position 199 pos = self.GetAbsolutePosition() 200 self._tooltipRect = (tl[0] / dpiScaling + pos[0], 201 tl[1] / dpiScaling + pos[1], 202 br[0] / dpiScaling - tl[0] / dpiScaling, 203 br[1] / dpiScaling - tl[1] / dpiScaling) 204 205 def FindMouseoverIndex(self): 206 if self._orientation == AxisOrientation.VERTICAL: 207 x = uicore.uilib.x - self.GetAbsoluteLeft() 208 else: 209 x = uicore.uilib.y - self.GetAbsoluteTop() 210 x = self._categoryAxis.MapFromViewport(x) 211 index = int(round(x)) 212 return index 213 214 def OnMouseExit(self, *args): 215 self._RemoveBarHighlight() 216 217 def LockGraphUpdates(self): 218 self._locked = True 219 220 def UnlockGraphUpdates(self): 221 if self._locked: 222 self._locked = False 223 if self._dirty: 224 self._Rescale()