bargraph.py (11573B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\bargraph.py 2 import math 3 import blue 4 import localization 5 import uthread 6 from carbon.common.script.util.format import FmtAmt 7 from carbonui import uiconst 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.fill import Fill 10 from carbonui.primitives.frame import Frame 11 from carbonui.primitives.line import Line 12 from carbonui.primitives.sprite import Sprite 13 from carbonui.uicore import uicore 14 from carbonui.uianimations import animations 15 from carbonui.util.color import Color 16 from eve.client.script.ui.control import eveLabel 17 COLOR_FRAME = (1.0, 18 1.0, 19 1.0, 20 0.5) 21 22 class BarGraph(Container): 23 default_name = 'barGraph' 24 default_maxValue = 1.0 25 default_barUpdateDelayMs = 10 26 default_backgroundColor = (0.0, 0.0, 0.0, 0.9) 27 default_timeIndicatorColor = (1.0, 1.0, 1.0, 0.6) 28 UPDATEINTERVAL_NORMAL = 100 29 UPDATEINTERVAL_NEWBARS = 1500 30 31 def ApplyAttributes(self, attributes): 32 Container.ApplyAttributes(self, attributes) 33 self.barUpdateDelayMs = attributes.get('barUpdateDelayMs', self.default_barUpdateDelayMs) 34 backgroundColor = attributes.get('backgroundColor', self.default_backgroundColor) 35 timeIndicatorColor = attributes.get('timeIndicatorColor', self.default_timeIndicatorColor) 36 self.barHintFunc = attributes.get('barHintFunc', None) 37 self.bars = [] 38 self.busy = None 39 self.queuedValues = None 40 self.numBars = None 41 self.setValuesThread = None 42 self.timeIndicatorValue = 0.0 43 self.maxValue = None 44 self.xLabels = None 45 self.timeIndicatorThread = None 46 self.barWidth = None 47 XAXISHEIGHT = 15 48 YAXISWIDTH = 40 49 self.yAxisCont = Container(parent=self, name='yAxisCont', align=uiconst.TOLEFT, width=YAXISWIDTH, padBottom=XAXISHEIGHT + 1) 50 self.xAxisCont = Container(parent=self, name='xAxisCont', align=uiconst.TOBOTTOM, height=XAXISHEIGHT) 51 self.graphCont = Container(parent=self, name='graphCont', align=uiconst.TOALL) 52 self.timeIndicator = Line(parent=self.graphCont, name='timeIndicator', state=uiconst.UI_HIDDEN, align=uiconst.TOPLEFT, color=timeIndicatorColor, padding=(0, 1, 0, 1), width=1) 53 self.backgroundCont = Container(parent=self, name='backgroundCont', align=uiconst.TOALL, padding=(1, 2, 1, 1), clipChildren=True) 54 Frame(parent=self, color=COLOR_FRAME) 55 Sprite(parent=self.backgroundCont, name='backgroundStripes', align=uiconst.TOTOP, height=500, texturePath='res:/UI/Texture/Bargraph/background_stripes.dds', ignoreSize=True, color=backgroundColor) 56 self.barCont = Container(parent=self.graphCont, name='barCont', align=uiconst.TOALL, padding=(2, 2, 1, 1), clipChildren=True) 57 58 def _CreateBars(self, numBars): 59 self.barCont.Flush() 60 self.bars = [] 61 self.numBars = numBars 62 l, t, w, h = self.barCont.GetAbsolute() 63 self.barWidth = max(1, (w - 2) / self.numBars) 64 for i in xrange(self.numBars): 65 bar = Bar(parent=self.barCont, name='bar%s' % i, align=uiconst.TOLEFT, width=self.barWidth, height=h, barNum=i + 1) 66 if self.barHintFunc: 67 bar._GetBarHint = self.barHintFunc 68 self.bars.append(bar) 69 70 self.xAxisCont.padRight = w - self.barWidth * self.numBars - 2 71 if self.xLabels: 72 self.SetXLabels(self.xLabels) 73 self.ShowTimeIndicator(self.timeIndicatorValue) 74 75 def SetXLabels(self, labels): 76 self.xAxisCont.Flush() 77 self.xLabels = labels 78 for i, label in enumerate(labels): 79 if i == len(labels) - 1: 80 align = uiconst.TOPRIGHT 81 else: 82 align = uiconst.TOPLEFT 83 XLabel(parent=self.xAxisCont, value=float(i) / (len(labels) - 1), text=label, align=align) 84 85 def _CreateYAxis(self): 86 self.yAxisCont.Flush() 87 NUMYAXISLABELS = 5 88 if self.maxValue == 0: 89 return 90 for i in xrange(NUMYAXISLABELS): 91 value = float(i) / (NUMYAXISLABELS - 1) 92 YLabel(parent=self.yAxisCont, width=self.yAxisCont.width, value=value, text=FmtAmt(value * self.maxValue)) 93 94 yAxisFill = Fill(parent=self.yAxisCont, color=Color.WHITE) 95 animations.FadeTo(yAxisFill, startVal=0.2, endVal=0.0, duration=0.3) 96 97 def SetValues(self, values): 98 if self.busy: 99 self.queuedValues = values 100 return 101 self.queuedValues = None 102 self.busy = True 103 updateInterval = self.UPDATEINTERVAL_NORMAL 104 maxValue = max(values) 105 lenValues = len(values) 106 if self.numBars != lenValues: 107 if self.setValuesThread: 108 self.setValuesThread.kill() 109 self._CreateBars(lenValues) 110 updateInterval = self.UPDATEINTERVAL_NEWBARS 111 YAXISRESCALEVALUE = 1 112 while YAXISRESCALEVALUE < maxValue: 113 YAXISRESCALEVALUE *= 10 114 115 YAXISRESCALEVALUE *= 0.1 116 if maxValue > self.maxValue or maxValue < self.maxValue - 1.3 * YAXISRESCALEVALUE: 117 self.maxValue = int(math.ceil(float(maxValue) / YAXISRESCALEVALUE)) * YAXISRESCALEVALUE 118 self._CreateYAxis() 119 self.setValuesThread = uthread.new(self._SetValues, values) 120 uthread.new(self._EnforceUpdateInterval, updateInterval) 121 122 def _EnforceUpdateInterval(self, updateInterval): 123 blue.pyos.synchro.SleepWallclock(updateInterval) 124 if not self or self.destroyed: 125 return 126 self.busy = False 127 if self.queuedValues: 128 self.SetValues(self.queuedValues) 129 130 def _SetValues(self, values): 131 for i, val in enumerate(values): 132 if i >= self.numBars: 133 continue 134 bar = self.bars[i] 135 if self.maxValue == 0: 136 bar.SetValue(rawValue=0.0, maxRawValue=1.0) 137 else: 138 bar.SetValue(rawValue=val, maxRawValue=self.maxValue) 139 if self.barUpdateDelayMs: 140 blue.pyos.synchro.SleepWallclock(self.barUpdateDelayMs) 141 if not self or self.destroyed: 142 return 143 144 def ShowTimeIndicator(self, value, animate = True): 145 if value is None: 146 return 147 if self.barWidth is None: 148 return 149 self.timeIndicatorValue = value 150 l, t, w, h = self.graphCont.GetAbsolute() 151 self.timeIndicator.state = uiconst.UI_DISABLED 152 self.timeIndicator.SetAlpha(1.0) 153 p = self.barCont.padLeft 154 self.timeIndicator.left = p + int(value * self.barWidth * self.numBars) 155 self.timeIndicator.height = h 156 if animate and self.timeIndicatorThread is None: 157 self.timeIndicatorThread = uthread.new(self._AnimateTimeIndicator) 158 159 def _AnimateTimeIndicator(self): 160 x = 0.0 161 CYCLETIME = 3.0 162 k = 2 * math.pi / CYCLETIME 163 while self and not self.destroyed: 164 x = (x + 1.0 / blue.os.fps) % CYCLETIME 165 self.timeIndicator.SetAlpha(0.3 * math.sin(k * x) + 0.7) 166 blue.pyos.synchro.Yield() 167 168 def HideTimeIndicator(self): 169 self.timeIndicatorValue = None 170 self.timeIndicator.state = uiconst.UI_HIDDEN 171 if self.timeIndicatorThread is not None: 172 self.timeIndicatorThread.kill() 173 self.timeIndicatorThread = None 174 175 176 class Bar(Container): 177 default_frequency = 14.0 178 default_dampRatio = 1.41 179 default_color = COLOR_FRAME 180 default_disturbance = 0.5 181 default_state = uiconst.UI_NORMAL 182 BARHEIGHT = 150 183 184 def ApplyAttributes(self, attributes): 185 Container.ApplyAttributes(self, attributes) 186 self.frequency = attributes.Get('frequency', self.default_frequency) 187 self.dampRatio = attributes.Get('dampRatio', self.default_dampRatio) 188 self.color = attributes.Get('color', self.default_color) 189 self.disturbance = attributes.Get('disturbance', self.default_disturbance) 190 self.barNum = attributes.Get('barNum', 0) 191 self.value = 0.0 192 self.rawValue = 0.0 193 self.maxRawValue = 1.0 194 self.morphThread = None 195 self.graphHeight = None 196 self.backgroundFill = Fill(parent=self, color=Color.GetGrayRGBA(0.0, 0.5), state=uiconst.UI_HIDDEN) 197 self.bar = Sprite(parent=self, align=uiconst.BOTTOMLEFT, color=self.color, texturePath='res:/UI/Texture/Bargraph/%s.dds' % self.BARHEIGHT, pos=(0, 198 -self.BARHEIGHT, 199 self.width, 200 self.BARHEIGHT), state=uiconst.UI_DISABLED, padLeft=1) 201 202 def SetValue(self, rawValue, maxRawValue, *args): 203 if self.morphThread: 204 self.morphThread.kill() 205 initVal = self.value 206 self.rawValue = rawValue 207 self.maxRawValue = maxRawValue 208 self.value = float(rawValue) / maxRawValue 209 if not self.graphHeight: 210 l, t, w, h = self.GetAbsolute() 211 self.graphHeight = h 212 diffInPixels = math.fabs(self.GetTopFromValue(initVal) - self.GetTopFromValue(self.value)) 213 if diffInPixels > 2: 214 self.morphThread = uicore.effect.MorphUIMassSpringDamper(self.bar, newVal=self.value, initVal=initVal, newthread=1, float=1, minVal=-1.0, maxVal=1.0, dampRatio=self.dampRatio, frequency=self.frequency, maxTime=3.0, callback=self.OnValueChanged) 215 else: 216 self.OnValueChanged(self, self.value) 217 218 def OnValueChanged(self, bar, value, *args): 219 if not self or self.destroyed: 220 return 221 HUEMAX = 0.6 222 hue = HUEMAX * max(0.0, 1.0 - value) 223 color = Color().SetHSB(hue, 0.7, 0.8, 1.0).GetRGBA() 224 self.bar.SetRGBA(*color) 225 self.bar.top = self.GetTopFromValue(value) 226 self.value = value 227 228 def GetTopFromValue(self, value): 229 top = int(value * self.graphHeight - self.BARHEIGHT) 230 top -= top % 2 231 return top 232 233 def GetHint(self): 234 return self._GetBarHint(self.barNum, self.rawValue, self.maxRawValue) 235 236 def _GetBarHint(self, num, rawValue, maxRawValue): 237 return localization.GetByLabel('UI/BarGraph/DefaultBarHint', num=num, rawValue=rawValue, maxRawValue=maxRawValue) 238 239 def OnMouseEnter(self, *args): 240 if hasattr(self, 'background'): 241 self.backgroundFill.state = uiconst.UI_DISABLED 242 243 def OnMouseExit(self, *args): 244 if hasattr(self, 'background'): 245 self.backgroundFill.state = uiconst.UI_HIDDEN 246 247 248 class LabelText(eveLabel.EveLabelSmall): 249 default_color = (1.0, 1.0, 1.0, 0.6) 250 251 252 class YLabel(Container): 253 default_align = uiconst.BOTTOMRIGHT 254 default_height = 20 255 256 def ApplyAttributes(self, attributes): 257 Container.ApplyAttributes(self, attributes) 258 value = attributes.Get('value') 259 text = attributes.Get('text', '%s' % value) 260 l, t, w, h = self.parent.GetAbsolute() 261 self.top = int(h * value) 262 LabelText(parent=self, text=text, align=uiconst.BOTTOMRIGHT, top=-5, left=5) 263 Line(parent=self, color=COLOR_FRAME, align=uiconst.BOTTOMRIGHT, width=4, height=1, top=-1) 264 265 266 class XLabel(Container): 267 default_align = uiconst.TOPLEFT 268 default_width = 100 269 default_height = 20 270 271 def ApplyAttributes(self, attributes): 272 Container.ApplyAttributes(self, attributes) 273 value = attributes.Get('value') 274 text = attributes.Get('text', '%s' % value) 275 l, t, w, h = self.parent.GetAbsolute() 276 LabelText(parent=self, text=text, align=self.align, top=5) 277 Line(parent=self, color=COLOR_FRAME, align=self.align, width=1, height=4)