overViewLabel.py (19395B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\overViewLabel.py 2 import blue 3 import telemetry 4 import carbonui.const as uiconst 5 import eveicon 6 import trinity 7 import uthread 8 from carbon.client.script.environment.AudioUtil import PlaySound 9 from carbonui import TextColor 10 from carbonui.primitives.base import Base 11 from carbonui.primitives.container import Container 12 from carbonui.primitives.sprite import VisibleBase 13 from carbonui.text.settings import check_convert_font_size 14 from carbonui.uicore import uicore 15 from eve.client.script.ui.control import eveIcon, eveLabel 16 from eve.client.script.ui.inflight.overview import overviewColumns, overviewConst 17 from eve.client.script.ui.inflight.overview.overviewConst import * 18 from localization import GetByLabel 19 from signals import Signal 20 FONT_COLOR_INT = trinity.TriColor(*TextColor.HIGHLIGHT).AsInt() 21 22 class OverviewLabel(VisibleBase): 23 __renderObject__ = trinity.Tr2Sprite2dTextObject 24 default_name = 'OverviewLabel' 25 default_color = None 26 _text = None 27 _columnWidth = None 28 _columnPosition = 0 29 _globalMaxWidth = None 30 _columnWidthDirty = False 31 32 def ApplyAttributes(self, attributes): 33 VisibleBase.ApplyAttributes(self, attributes) 34 self.typeID = attributes.get('typeID', None) 35 self.fadeSize = self.ScaleDpi(COLUMNFADESIZE) 36 self.rightAligned = False 37 measurer = trinity.Tr2FontMeasurer() 38 measurer.limit = 0 39 measurer.fontSize = uicore.ScaleDpi(check_convert_font_size(attributes.fontSize)) 40 measurer.font = str(uicore.font.GetFontDefault()) 41 measurer.letterSpace = 0 42 self.renderObject.fontMeasurer = measurer 43 self.renderObject.shadowOffset = eveLabel.Label.get_default_shadow_offset() 44 self.renderObject.shadowColor = eveLabel.Label.default_shadowColor 45 self.measurer = measurer 46 47 def OnGlobalFontShadowChanged(self): 48 self.renderObject.shadowOffset = eveLabel.Label.get_default_shadow_offset() 49 50 def UpdateFade(self): 51 measurer = self.measurer 52 columnWidth = self.columnWidth 53 if columnWidth: 54 globalFade = False 55 globalMaxWidth = self.globalMaxWidth 56 if globalMaxWidth and globalMaxWidth - self.left < columnWidth: 57 scaledMaxWidth = max(0, self.ScaleDpi(globalMaxWidth - self.left)) 58 globalFade = True 59 elif self.rightAligned: 60 scaledMaxWidth = measurer.cursorX 61 else: 62 scaledMaxWidth = self.ScaleDpi(columnWidth) 63 if measurer.cursorX > scaledMaxWidth: 64 maxFade = max(2, measurer.cursorX - scaledMaxWidth) 65 if globalFade: 66 measurer.fadeRightStart = max(0, scaledMaxWidth - min(maxFade, self.fadeSize)) 67 measurer.fadeRightEnd = scaledMaxWidth 68 else: 69 measurer.fadeRightStart = measurer.cursorX + 1 70 measurer.fadeRightEnd = measurer.cursorX + 1 71 else: 72 measurer.fadeRightStart = measurer.cursorX + 1 73 measurer.fadeRightEnd = measurer.cursorX + 1 74 75 @apply 76 def left(): 77 78 def fget(self): 79 return self._left 80 81 def fset(self, value): 82 if value < 1.0: 83 adjustedValue = value 84 else: 85 adjustedValue = int(round(value)) 86 if adjustedValue != self._left: 87 self._left = adjustedValue 88 self.FlagAlignmentDirty() 89 self.UpdateFade() 90 91 return property(**locals()) 92 93 @apply 94 def width(): 95 96 def fget(self): 97 return self._width 98 99 def fset(self, value): 100 if value < 1.0: 101 adjustedValue = value 102 else: 103 adjustedValue = int(round(value)) 104 if adjustedValue != self._width: 105 self._width = adjustedValue 106 if self.rightAligned: 107 self.left = self.columnPosition + self.columnWidth - adjustedValue 108 self.FlagAlignmentDirty() 109 self.UpdateFade() 110 111 return property(**locals()) 112 113 @apply 114 def text(): 115 116 def fget(self): 117 return self._text 118 119 def fset(self, value): 120 if self._text != value or self._columnWidthDirty: 121 self._columnWidthDirty = False 122 self._text = value 123 if not value: 124 self.texture = None 125 self.spriteEffect = trinity.TR2_SFX_NONE 126 return 127 measurer = self.measurer 128 measurer.Reset() 129 measurer.color = FONT_COLOR_INT 130 if self.columnWidth: 131 measurer.limit = self.ScaleDpi(self.columnWidth) 132 added = measurer.AddText(unicode(value)) 133 measurer.CommitText(0, measurer.ascender) 134 if self.columnWidth: 135 self.width = min(self.columnWidth, self.ReverseScaleDpi(measurer.cursorX + 0.5)) 136 self.renderObject.textWidth = min(self.ScaleDpi(self.columnWidth), measurer.cursorX) 137 else: 138 self.width = self.ReverseScaleDpi(measurer.cursorX + 0.5) 139 self.renderObject.textWidth = measurer.cursorX 140 self.height = self.ReverseScaleDpi(measurer.ascender - measurer.descender) 141 self.renderObject.textHeight = measurer.ascender - measurer.descender 142 143 return property(**locals()) 144 145 @apply 146 def columnWidth(): 147 148 def fget(self): 149 return self._columnWidth 150 151 def fset(self, value): 152 if self._columnWidth != value: 153 self._columnWidth = value 154 self._columnWidthDirty = True 155 measurer = self.measurer 156 self.width = min(value, self.ReverseScaleDpi(measurer.cursorX + 0.5)) 157 self.renderObject.textWidth = min(self.ScaleDpi(value), measurer.cursorX) 158 if self.rightAligned: 159 self.left = self.columnPosition + value - self.width 160 161 return property(**locals()) 162 163 @apply 164 def columnPosition(): 165 166 def fget(self): 167 return self._columnPosition 168 169 def fset(self, value): 170 if self._columnPosition != value: 171 self._columnPosition = value 172 if self.rightAligned: 173 self.left = value + self.columnWidth - self.width 174 else: 175 self.left = value 176 177 return property(**locals()) 178 179 @apply 180 def globalMaxWidth(): 181 182 def fget(self): 183 return self._globalMaxWidth 184 185 def fset(self, value): 186 if self._globalMaxWidth != value: 187 self._globalMaxWidth = value 188 self.UpdateFade() 189 190 return property(**locals()) 191 192 @classmethod 193 def MeasureTextSize(cls, text, **customAttributes): 194 customAttributes['parent'] = None 195 customAttributes['align'] = uiconst.TOPLEFT 196 label = cls(**customAttributes) 197 label.text = text 198 return (label.width, label.height) 199 200 def GetMenu(self): 201 parent = self.parent 202 if parent and hasattr(parent, 'GetMenu'): 203 return parent.GetMenu() 204 205 def OnMouseDown(self, *args, **kwds): 206 parent = self.parent 207 if parent and parent.OnMouseDown.__func__ != Base.OnMouseDown.__func__: 208 return parent.OnMouseDown(*args, **kwds) 209 210 def OnMouseUp(self, *args, **kwds): 211 parent = self.parent 212 if parent and parent.OnMouseUp.__func__ != Base.OnMouseUp.__func__: 213 return parent.OnMouseUp(*args, **kwds) 214 215 def OnClick(self, *args, **kwds): 216 parent = self.parent 217 if parent and parent.OnClick.__func__ != Base.OnClick.__func__: 218 return parent.OnClick(*args, **kwds) 219 220 def OnDblClick(self, *args, **kwds): 221 parent = self.parent 222 if parent and hasattr(parent, 'OnDblClick'): 223 return parent.OnDblClick(*args, **kwds) 224 225 226 class Header(Container): 227 228 def ApplyAttributes(self, attributes): 229 super(Header, self).ApplyAttributes(attributes) 230 showScaler = attributes.showScaler 231 self.columnID = attributes.columnID 232 self.sortTriangle = None 233 self._hovered = False 234 self.on_scaler_mouse_down = Signal('on_scaler_mouse_down') 235 self.get_menu_func = attributes.get_menu_func 236 if showScaler: 237 scaler = Container(name='scaler', parent=self, align=uiconst.TORIGHT_NOPUSH, width=4, state=uiconst.UI_NORMAL, cursor=uiconst.UICURSOR_LEFT_RIGHT_DRAG) 238 scaler.OnMouseDown = self.OnScalerMouseDown 239 self.label = eveLabel.EveLabelSmall(parent=self, text=self.GetLabelText(), align=uiconst.CENTERLEFT, left=uiconst.LABELTABMARGIN, state=uiconst.UI_DISABLED, maxLines=1) 240 self._update() 241 242 def GetLabelText(self): 243 return overviewColumns.GetColumnLabel(self.columnID, addFormatUnit=True) 244 245 def OnScalerMouseDown(self, *args): 246 self.on_scaler_mouse_down(self, *args) 247 248 def OnMouseEnter(self, *args): 249 self._hovered = True 250 PlaySound(uiconst.SOUND_BUTTON_HOVER) 251 self._update() 252 253 def OnMouseExit(self, *args): 254 self._hovered = False 255 self._update() 256 257 def _update(self): 258 self.label.rgba = self._GetLabelColor() 259 if self.sortTriangle: 260 self.sortTriangle.rgba = self._GetTriangleColor() 261 262 def _GetTriangleColor(self): 263 if self._hovered: 264 return TextColor.HIGHLIGHT 265 else: 266 return TextColor.NORMAL 267 268 def _GetLabelColor(self): 269 if self._hovered: 270 return TextColor.HIGHLIGHT 271 else: 272 return TextColor.SECONDARY 273 274 def ConstructSortTriangle(self): 275 if not self.sortTriangle: 276 self.sortTriangle = eveIcon.Icon(align=uiconst.CENTERRIGHT, pos=(3, -1, 16, 16), parent=self, name='directionIcon', shadowOffset=(1, 1), idx=0) 277 self._update() 278 279 def GetMenu(self): 280 return self.get_menu_func() 281 282 def LoadTooltipPanel(self, tooltipPanel, owner): 283 tooltipPanel.LoadStandardSpacing() 284 tooltipPanel.columns = 1 285 tooltipPanel.AddMediumHeader(text=self.GetLabelText()) 286 description = self.GetDescription() 287 if description: 288 tooltipPanel.AddLabelMedium(text=description, wrapWidth=300) 289 290 def GetDescription(self): 291 description = overviewConst.COLUMN_DESCRIPTIONS.get(self.columnID, None) 292 if description: 293 return GetByLabel(description) 294 295 296 class SortHeaders(Container): 297 default_name = 'SortHeaders' 298 default_align = uiconst.TOTOP 299 default_height = 24 300 default_state = uiconst.UI_PICKCHILDREN 301 default_clipChildren = True 302 default_padBottom = 0 303 304 def ApplyAttributes(self, attributes): 305 super(SortHeaders, self).ApplyAttributes(attributes) 306 self.headerContainer = Container(parent=self) 307 self.settingsID = attributes.settingsID 308 self.get_menu_func = attributes.get_menu_func 309 self.subSettingID = None 310 self.customSortIcon = None 311 self.columnIDs = [] 312 self.fixedColumns = None 313 self.defaultColumn = None 314 self.minSizeByColumnID = {} 315 316 def SetSubSettingID(self, subSettingID): 317 self.subSettingID = subSettingID 318 319 def GetSettingKey(self): 320 return (self.settingsID, self.subSettingID) 321 322 def SetDefaultColumn(self, columnID, direction): 323 self.defaultColumn = (columnID, direction) 324 325 def SetMinSizeByColumnID(self, minSizes): 326 self.minSizeByColumnID = minSizes 327 328 def CreateColumns(self, columns, fixedColumns = None): 329 self.headerContainer.Flush() 330 self.columnIDs = columns 331 self.fixedColumns = fixedColumns 332 if columns: 333 sizes = self.GetCurrentSizes() 334 for columnID in columns: 335 header = Header(parent=self.headerContainer, align=uiconst.TOLEFT, state=uiconst.UI_NORMAL, showScaler=columnID not in fixedColumns, columnID=columnID, get_menu_func=self.get_menu_func) 336 header.OnClick = (self.ClickHeader, header) 337 header.OnDblClick = (self.DblClickHeader, header) 338 header.on_scaler_mouse_down.connect(self.StartHeaderScale) 339 minWidth = self.minSizeByColumnID.get(columnID, COLUMNMINSIZE) 340 if fixedColumns and columnID in fixedColumns: 341 header.width = fixedColumns[columnID] 342 if header.width <= 32: 343 header.label.Hide() 344 elif columnID in sizes: 345 header.width = max(minWidth, sizes[columnID]) 346 else: 347 defaultWidth = COLUMN_DEFAULTSIZE.get(columnID, COLUMNMINDEFAULTSIZE) 348 if columnID in COLUMN_DO_NOT_EXPAND_FOR_LABEL: 349 header.width = max(minWidth, defaultWidth) 350 else: 351 requiredWidthForLabel = header.label.textwidth + 24 352 header.width = max(minWidth, max(defaultWidth, requiredWidthForLabel)) 353 354 self.UpdateActiveState() 355 356 def SetSortIcon(self, texturePath): 357 if self.customSortIcon != texturePath: 358 self.customSortIcon = texturePath 359 self.UpdateActiveState() 360 361 def UpdateActiveState(self): 362 currentActive, currentDirection = self.GetCurrentActive() 363 for header in self.headerContainer.children: 364 if hasattr(header, 'columnID'): 365 if header.columnID == currentActive: 366 if not header.sortTriangle: 367 header.ConstructSortTriangle() 368 if self.customSortIcon: 369 header.sortTriangle.LoadTexture(self.customSortIcon) 370 else: 371 texturePath = eveicon.caret_up if currentDirection else eveicon.caret_down 372 header.sortTriangle.LoadIcon(texturePath) 373 header.sortTriangle.state = uiconst.UI_DISABLED 374 rightMargin = 20 375 else: 376 if header.sortTriangle: 377 header.sortTriangle.Hide() 378 rightMargin = 6 379 header.label.width = header.width - header.label.left - 4 380 if header.sortTriangle and header.sortTriangle.display: 381 header.label.SetRightAlphaFade(header.width - rightMargin - header.label.left, uiconst.SCROLL_COLUMN_FADEWIDTH) 382 else: 383 header.label.SetRightAlphaFade() 384 if header.width <= 32 or header.width - header.label.left - rightMargin - 6 < header.label.textwidth: 385 header.hint = header.label.text 386 else: 387 header.hint = None 388 389 def GetCurrentColumns(self): 390 return self.columnIDs 391 392 @telemetry.ZONE_METHOD 393 def GetCurrentActive(self): 394 all = settings.char.ui.Get('SortHeadersSettings2', {}) 395 currentActive, currentDirection = None, True 396 settingTuple = self.GetSettingKey() 397 if settingTuple in all: 398 currentActive, currentDirection = all[settingTuple] 399 if currentActive not in self.columnIDs: 400 return (None, True) 401 return (currentActive, currentDirection) 402 if self.defaultColumn is not None: 403 columnID, direction = self.defaultColumn 404 if columnID in self.columnIDs: 405 return self.defaultColumn 406 if self.columnIDs: 407 currentActive, currentDirection = self.columnIDs[0], True 408 return (currentActive, currentDirection) 409 410 def SetCurrentActive(self, columnID, doCallback = True): 411 currentActive, currentDirection = self.GetCurrentActive() 412 if currentActive == columnID: 413 sortDirection = not currentDirection 414 else: 415 sortDirection = currentDirection 416 settingTuple = self.GetSettingKey() 417 all = settings.char.ui.Get('SortHeadersSettings2', {}) 418 all[settingTuple] = (columnID, sortDirection) 419 settings.char.ui.Set('SortHeadersSettings2', all) 420 self.UpdateActiveState() 421 if doCallback: 422 self.OnSortingChange(currentActive, columnID, currentDirection, sortDirection) 423 424 def DblClickHeader(self, header): 425 if not self.ColumnIsFixed(header.columnID): 426 self.SetCurrentActive(header.columnID, doCallback=False) 427 self.OnColumnSizeReset(header.columnID) 428 429 def ClickHeader(self, header): 430 self.SetCurrentActive(header.columnID) 431 432 def StartHeaderScale(self, header, mouseButton, *args): 433 if mouseButton == uiconst.MOUSELEFT: 434 self.startScaleX = uicore.uilib.x 435 self.startScaleWidth = header.width 436 uthread.new(self.ScaleHeader, header) 437 438 def ScaleHeader(self, header): 439 while not self.destroyed and uicore.uilib.leftbtn: 440 diff = self._GetColumnWidthDiff() 441 header.width = max(self.minSizeByColumnID.get(header.columnID, COLUMNMINSIZE), self.startScaleWidth + diff) 442 self.UpdateActiveState() 443 blue.pyos.synchro.Yield() 444 445 currentSizes = self.RegisterCurrentSizes() 446 self.UpdateActiveState() 447 self.OnColumnSizeChange(header.columnID, header.width, currentSizes) 448 449 def _GetColumnWidthDiff(self): 450 diff = uicore.uilib.x - self.startScaleX 451 l, t, w, h = self.GetAbsolute() 452 maxDiff = w - (self.startScaleX - l) - 2 453 return min(diff, maxDiff) 454 455 def GetCurrentSizes(self): 456 settingsID = self.GetSettingKey() 457 current = settings.char.ui.Get('SortHeadersSizes', {}).get(settingsID, {}) 458 if self.fixedColumns: 459 current.update(self.fixedColumns) 460 for each in self.headerContainer.children: 461 if hasattr(each, 'columnID') and each.columnID not in current: 462 current[each.columnID] = each.width 463 464 return current 465 466 def ColumnIsFixed(self, columnID): 467 return columnID in self.fixedColumns 468 469 def SetColumnSize(self, columnID, size): 470 if columnID in self.fixedColumns: 471 return 472 columnSize = max(self.minSizeByColumnID.get(columnID, COLUMNMINSIZE), size) 473 for each in self.headerContainer.children: 474 if hasattr(each, 'columnID') and each.columnID == columnID: 475 each.width = columnSize 476 break 477 478 self.UpdateActiveState() 479 currentSizes = self.RegisterCurrentSizes() 480 self.OnColumnSizeChange(columnID, columnSize, currentSizes) 481 482 def RegisterCurrentSizes(self): 483 sizes = {} 484 for each in self.headerContainer.children: 485 if hasattr(each, 'columnID'): 486 sizes[each.columnID] = each.width 487 488 all = settings.char.ui.Get('SortHeadersSizes', {}) 489 settingsID = self.GetSettingKey() 490 all[settingsID] = sizes 491 settings.char.ui.Set('SortHeadersSizes', all) 492 return sizes 493 494 def OnSortingChange(self, oldColumnID, columnID, oldSortDirection, sortDirection): 495 pass 496 497 def OnColumnSizeChange(self, columnID, newSize, currentSizes): 498 pass 499 500 def OnColumnSizeReset(self, columnID): 501 pass