scrollentries.py (35430B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\scrollentries.py 2 import carbonui.const as uiconst 3 import localization 4 import log 5 import trinity 6 from carbon.client.script.environment.AudioUtil import PlaySound 7 from carbon.common.script.util.timerstuff import AutoTimer 8 from carbonui import uiconst 9 from carbonui.control.inlines import get_inline_deco_class 10 from carbonui.control.label import LabelCore 11 from carbonui.control.link import Link 12 from carbonui.fontconst import DEFAULT_FONTSIZE 13 from carbonui.primitives.container import Container 14 from carbonui.primitives.fill import Fill 15 from carbonui.primitives.sprite import Sprite 16 from carbonui.uicore import uicore 17 from carbonui.util.bunch import Bunch 18 from carbonui.util.stringManip import GetAsUnicode 19 from carbonui.util.various_unsorted import GetBrowser, MapIcon 20 from eve.client.script.ui.control.eveWindowUnderlay import ListEntryUnderlay 21 from menu import MenuLabel 22 from player_messaging.client.ui_message import prompt_player_fsd_dialog 23 24 class SE_BaseClassCore(Container): 25 labelLeftDefault = uiconst.LABELTABMARGIN 26 __guid__ = 'uicontrols.SE_BaseClassCore' 27 default_name = 'scrollentry' 28 default_align = uiconst.TOTOP 29 default_className = 'SE_Generic' 30 default_showHilite = True 31 default_highlightClass = ListEntryUnderlay 32 sound_hover = uiconst.SOUND_ENTRY_HOVER 33 sound_select = uiconst.SOUND_ENTRY_SELECT 34 35 def ApplyAttributes(self, attributes): 36 if 'className' not in attributes: 37 attributes.className = self.default_className 38 Container.ApplyAttributes(self, attributes) 39 self._hiliteFill = None 40 self._isSelected = False 41 self._showHilite = attributes.get('showHilite', self.default_showHilite) 42 self._highlightClass = attributes.get('highlightClass', self.default_highlightClass) 43 44 def GetTooltipPanelClassInfo(self): 45 if self.sr.node and self.sr.node.tooltipPanelClassInfo: 46 return self.sr.node.tooltipPanelClassInfo 47 48 def GetTooltipPointer(self): 49 if self.sr.node and self.sr.node.tooltipPanelClassInfo: 50 return getattr(self.sr.node.tooltipPanelClassInfo, 'tooltipPointer', None) 51 return uiconst.POINT_RIGHT_2 52 53 def ConstructHiliteFill(self): 54 if not self._hiliteFill: 55 self._hiliteFill = self._highlightClass(name='selectionHighlight', bgParent=self) 56 57 def ShowHilite(self, animate = True): 58 if not self._showHilite: 59 return 60 self.ConstructHiliteFill() 61 self._hiliteFill.set_hovered(True, animate) 62 63 def OnMouseEnter(self, *args): 64 if self.sound_hover and self._showHilite: 65 PlaySound(self.sound_hover) 66 self.ShowHilite() 67 68 def HideHilite(self, animate = True): 69 if self._hiliteFill: 70 self._hiliteFill.set_hovered(False, animate) 71 72 def OnMouseExit(self, *args): 73 self.HideHilite() 74 75 def Select(self, animate = True): 76 if self._isSelected: 77 return 78 self.ConstructHiliteFill() 79 self._isSelected = True 80 self._hiliteFill.Select(animate) 81 82 def Deselect(self, animate = True): 83 if not self._isSelected: 84 return 85 if self._hiliteFill: 86 self._hiliteFill.Deselect(animate) 87 self._isSelected = False 88 89 def IsMouseInsideEntry(self): 90 if uicore.uilib.mouseOver != self and not uicore.uilib.mouseOver.IsUnder(self): 91 return False 92 return True 93 94 @classmethod 95 def GetCopyData(cls, node): 96 return '' 97 98 99 class SE_SpaceCore(SE_BaseClassCore): 100 __params__ = ['height'] 101 default_showHilite = False 102 103 def Load(self, node): 104 self.sr.node = node 105 106 def GetDynamicHeight(node, width): 107 return node.height 108 109 110 class SE_GenericCore(SE_BaseClassCore): 111 __guid__ = 'uicontrols.SE_GenericCore' 112 __params__ = ['label'] 113 114 def ApplyAttributes(self, attributes): 115 SE_BaseClassCore.ApplyAttributes(self, attributes) 116 if uicore.fontHandler: 117 labelClass = uicore.fontHandler.defaultLabelClass 118 else: 119 labelClass = LabelCore 120 self.sr.label = labelClass(name='text', text='', parent=self, pos=(self.labelLeftDefault, 121 0, 122 0, 123 0), state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, maxLines=1) 124 125 def Load(self, node): 126 self.hint = node.get('hint', '') 127 self.confirmOnDblClick = node.get('confirmOnDblClick', 0) 128 if node.get('selected', 0): 129 self.Select() 130 else: 131 self.Deselect() 132 self.sr.label.busy = True 133 self.sr.label.left = 5 + 16 * node.get('sublevel', 0) 134 self.sr.label.maxLines = node.get('maxLines', 1) 135 self.sr.label.letterspace = node.get('letterspace', 0) 136 self.sr.label.shadow = node.get('letterspace', None) 137 if node.fontStyle: 138 self.sr.label.fontStyle = node.fontStyle 139 if node.fontsize: 140 self.sr.label.fontsize = node.fontsize 141 if node.fontcolor: 142 self.sr.label.SetRGBA(*node.fontcolor) 143 self.sr.label.busy = False 144 self.sr.label.text = node.label 145 if node.get('disabled', None): 146 self.opacity = 0.5 147 self.state = uiconst.UI_DISABLED 148 else: 149 self.opacity = 1.0 150 self.state = uiconst.UI_NORMAL 151 if node.get('OnDblClick', None) or getattr(self, 'confirmOnDblClick', None): 152 self.EnableDblClick() 153 else: 154 self.DisableDblClick() 155 156 def GetDynamicHeight(node, width): 157 height = uicore.font.GetTextHeight(node.label, width=width - 5 + 16 * node.get('sublevel', 0), fontStyle=node.get('fontStyle', None), fontsize=node.get('fontsize', DEFAULT_FONTSIZE), letterspace=node.get('letterspace', 0), maxLines=node.get('maxLines', 1)) + 4 158 return height 159 160 def OnMouseHover(self, *args): 161 if self.sr.get('node', None) and self.sr.node.get('OnMouseHover', None): 162 self.sr.node.OnMouseHover(self) 163 164 def OnMouseEnter(self, *args): 165 SE_BaseClassCore.OnMouseEnter(self, *args) 166 if self.sr.get('node', None) and self.sr.node.get('OnMouseEnter', None): 167 self.sr.node.OnMouseEnter(self) 168 169 def OnMouseExit(self, *args): 170 SE_BaseClassCore.OnMouseExit(self, *args) 171 if self.sr.get('node', None) and self.sr.node.get('OnMouseExit', None): 172 self.sr.node.OnMouseExit(self) 173 174 def OnClick(self, *args): 175 if self.sr.get('node', None): 176 if self.sr.node.get('OnClick', None): 177 self.sr.node.OnClick(self) 178 179 def EnableDblClick(self): 180 self.OnDblClick = self.DblClick 181 182 def DisableDblClick(self): 183 self.OnDblClick = None 184 185 def DblClick(self, *args): 186 if self.sr.node: 187 self.sr.node.scroll.SelectNode(self.sr.node) 188 if self.sr.node.get('OnDblClick', None): 189 self.sr.node.OnDblClick(self) 190 elif getattr(self, 'confirmOnDblClick', None): 191 uicore.registry.Confirm(self) 192 193 def OnMouseDown(self, *args): 194 SE_BaseClassCore.OnMouseDown(self, *args) 195 self.sr.node.scroll.SelectNode(self.sr.node) 196 prompt_player_fsd_dialog('ListEntryClick') 197 if self.sr.get('node', None) and self.sr.node.get('OnMouseDown', None): 198 self.sr.node.OnMouseDown(self) 199 200 def OnMouseUp(self, *args): 201 SE_BaseClassCore.OnMouseUp(self, *args) 202 if self.sr.get('node', None) and self.sr.node.get('OnMouseUp', None): 203 self.sr.node.OnMouseUp(self) 204 205 def GetMenu(self): 206 if self.sr.get('node', None) and self.sr.node.get('OnGetMenu', None): 207 return self.sr.node.OnGetMenu(self) 208 return [] 209 210 211 class SE_TextlineCore(SE_BaseClassCore, Link): 212 __guid__ = 'uicontrols.SE_TextlineCore' 213 default_showHilite = False 214 USECACHE = False 215 216 def ApplyAttributes(self, attributes): 217 SE_BaseClassCore.ApplyAttributes(self, attributes) 218 self.gotSurface = False 219 self.selectingtext = 0 220 self.sr.textcursor = None 221 self.sr.cursortimer = None 222 self.sr.textselection = None 223 self.Prepare_() 224 225 def Prepare_(self, *args): 226 self.sr.sprite = None 227 self.sr.inlines = Container(name='inlines', parent=self) 228 self.sr.links = Container(name='links', parent=self) 229 self.sr.textselection = None 230 231 def _OnClose(self): 232 if self.destroyed: 233 return 234 self.Unload() 235 if self.sr.node: 236 for inline, x in self.sr.node.Get('inlines', []): 237 control = inline.control 238 if control and getattr(control, '__guid__', '').startswith('uicls.SE_'): 239 inline.control = None 240 control.Close() 241 242 SE_BaseClassCore._OnClose(self) 243 244 def Load(self, node): 245 self.sr.links.Flush() 246 self.leftM = 0 247 self.sr.hiliteLinks = [] 248 self.RenderLine() 249 self.LoadInlines() 250 if not self or self.destroyed: 251 return 252 self.UpdateSelectionHilite() 253 self.UpdateCursor() 254 255 def OnChar(self, *args): 256 pass 257 258 def GetSprite(self): 259 if self.sr.sprite is None: 260 self.sr.sprite = Sprite(parent=self, state=uiconst.UI_PICKCHILDREN, spriteEffect=trinity.TR2_SFX_FONT, name='textSprite', idx=0) 261 self.sr.sprite.OnCreate = self.OnCreate 262 trinity.device.RegisterResource(self.sr.sprite) 263 uicore.textObjects.add(self) 264 return self.sr.sprite 265 266 def OnCreate(self, dev): 267 self.gotSurface = False 268 if not self.destroyed and self.sr.node: 269 self.Load(self.sr.node) 270 271 def Unload(self): 272 browser = GetBrowser(self) 273 if browser and self.sr.inlines: 274 for control in self.sr.inlines.children[:]: 275 if not control: 276 continue 277 if self.destroyed: 278 break 279 control.state = uiconst.UI_HIDDEN 280 control.SetParent(browser.sr.cacheContainer) 281 if hasattr(control, 'Unload') and control.loaded: 282 control.Unload() 283 284 def LoadInlines(self): 285 self.Unload() 286 if not self.sr.node.scroll: 287 return 288 scrollwidth = self.sr.node.scroll.GetContentWidth() 289 linewidth = self.sr.node.Get('lineWidth', 0) 290 lineHeight = self.sr.node.Get('maxBaseHeight', 12) 291 leftMargin = self.sr.node.Get('lpush', self.sr.node.scroll.xmargin) 292 rightMargin = self.sr.node.Get('rpush', self.sr.node.scroll.xmargin) 293 self.sr.inlines.left = max(0, self.leftM) 294 from carbonui.control.editutils import parser 295 for inline, x in self.sr.node.Get('inlines', []): 296 control = getattr(inline, 'control', None) 297 if control and not control.destroyed: 298 control.SetParent(self.sr.inlines) 299 else: 300 decoClass = get_inline_deco_class(inline.attrs.type) 301 if not decoClass: 302 continue 303 control = self.sr.node.scroll.GetInline(ScrollEntryNode(decoClass=decoClass, attrs=inline.attrs)) 304 if not self or self.destroyed: 305 return 306 control.SetParent(self.sr.inlines) 307 inline.control = control 308 control.top = 0 309 if inline.valign == parser.ALIGNMIDDLE: 310 control.top = (self.height - inline.inlineHeight) / 2 311 elif inline.valign in (parser.ALIGNBOTTOM, parser.ALIGNSUB): 312 control.top = self.height - inline.inlineHeight 313 elif inline.valign == parser.ALIGNBASELINE: 314 control.top = self.sr.node.Get('maxBaseLine', 12) - inline.inlineHeight 315 control.left = int(x) 316 control.height = inline.inlineHeight 317 control.width = inline.inlineWidth 318 if self.IsCentered: 319 control.SetAlign(uiconst.CENTER) 320 if hasattr(control, 'Load') and not control.loaded: 321 control.Load() 322 control.state = uiconst.UI_NORMAL 323 324 def RenderLine(self): 325 if not self.sr.node.scroll: 326 return 327 scrollwidth = self.sr.node.scroll.GetContentWidth() 328 if self.sr.node.glyphString: 329 linewidth = self.ReverseScaleDpi(self.sr.node.glyphString.width) 330 else: 331 linewidth = 0 332 self.IsCentered = False 333 lineHeight = self.sr.node.Get('maxBaseHeight', 12) 334 leftMargin = self.sr.node.Get('lpush', self.sr.node.scroll.xmargin) 335 rightMargin = self.sr.node.Get('rpush', self.sr.node.scroll.xmargin) 336 links = self.sr.node.Get('links', []) 337 sprite = self.GetSprite() 338 if self.sr.node.align == 'right': 339 sprite.left = int(scrollwidth - rightMargin - linewidth) 340 elif self.sr.node.align == 'center': 341 self.IsCentered = True 342 else: 343 sprite.left = int(leftMargin) 344 self.leftM = sprite.left 345 if self.sr.node.glyphString: 346 self.ApplyPixels(linewidth, lineHeight) 347 else: 348 sprite.state = uiconst.UI_HIDDEN 349 for linkAttrs in links: 350 self.StartLink(linkAttrs) 351 352 class TexResBuf(object): 353 __slots__ = ['width', 354 'height', 355 'data', 356 'pitch'] 357 358 def __init__(self, tuple): 359 self.data, self.width, self.height, self.pitch = tuple 360 361 def ApplyPixels(self, linewidth, lineHeight): 362 self.sr.xMin = 0 363 if not self.sr.node.glyphString: 364 return 365 node = self.sr.node 366 glyphstring = node.glyphString 367 bBox = node.bBox 368 sprite = self.GetSprite() 369 if not bBox or bBox.Width() <= 0 or bBox.Height() <= 0: 370 sprite.state = uiconst.UI_HIDDEN 371 return 372 surfaceWidth = bBox.Width() 373 surfaceHeight = glyphstring.baseHeight 374 sprite.left += bBox.xMin 375 if glyphstring.shadow: 376 sx, sy, scol = glyphstring.shadow[-1] 377 surfaceWidth += sx 378 surfaceHeight -= sy 379 sprite.texture = None 380 texturePrimary = trinity.Tr2Sprite2dTexture() 381 texturePrimary.atlasTexture = uicore.uilib.CreateTexture(surfaceWidth, surfaceHeight) 382 sprite.texture = texturePrimary 383 sprite.useSizeFromTexture = True 384 try: 385 bufferData = texturePrimary.atlasTexture.LockBuffer() 386 except AttributeError: 387 if texturePrimary and texturePrimary.atlasTexture: 388 texturePrimary.atlasTexture.UnlockBuffer() 389 bufferData = texturePrimary.atlasTexture.LockBuffer() 390 else: 391 self.display = False 392 return 393 394 try: 395 buf = SE_TextlineCore.TexResBuf(bufferData) 396 trinity.fontMan.ClearBuffer(buf.data, buf.width, buf.height, buf.pitch) 397 glyphstring.DrawToBuf(buf, -bBox.xMin, glyphstring.baseHeight - glyphstring.baseLine) 398 finally: 399 texturePrimary.atlasTexture.UnlockBuffer() 400 401 sprite.top = 0 402 self.sr.xMin = bBox.xMin 403 sprite.state = uiconst.UI_PICKCHILDREN 404 405 def StartLink(self, attrs): 406 link = Link(parent=self.sr.links) 407 link.left = self.GetSprite().left + attrs.left 408 link.top = self.GetSprite().top 409 link.height = self.height - self.GetSprite().top + 1 410 link.width = attrs.width 411 link.state = uiconst.UI_NORMAL 412 link.SetAlign(uiconst.RELATIVE) 413 link.hint = unicode(attrs.hint) 414 link.OnMouseMove = self.OnMouseMove 415 link.OnDblClick = self.OnDblClick 416 link.OnMouseEnter = (self.OnLinkMouseEnter, link) 417 link.OnMouseExit = (self.LinkExit, link) 418 link.OnMouseDown = (self.LinkDown, link) 419 link.OnMouseUp = (self.LinkUp, link) 420 link.cursor = uiconst.UICORSOR_FINGER 421 link.url = attrs.url 422 link.sr.attrs = attrs 423 link.name = 'textlink' 424 link.URLHandler = self.sr.node.Get('URLHandler', None) 425 link.linkText = attrs.linkText 426 if not attrs.Get('draggable', True): 427 link.DisableDrag() 428 return link 429 430 def OnLinkMouseEnter(self, link, *args): 431 PlaySound(uiconst.SOUND_BUTTON_HOVER) 432 return self.LinkEnter(link) 433 434 def LinkDown(self, link, *args): 435 for each in self.sr.hiliteLinks: 436 each.Flush() 437 438 def LinkUp(self, link, *args): 439 if uicore.uilib.mouseOver == link: 440 self.LinkEnter(link) 441 442 def LinkEnter(self, link, *args): 443 browser = GetBrowser(self) 444 if browser and browser.sr.window and hasattr(browser.sr.window, 'ShowHint'): 445 browser.sr.window.ShowHint(link.hint or link.url) 446 self.sr.hiliteLinks = [] 447 for entry in self.sr.node.scroll.GetNodes(): 448 if not entry.panel: 449 continue 450 if entry.panel.sr.Get('links', None): 451 for item in entry.panel.sr.links.children: 452 if item.name == 'textlink' and item.url == link.url: 453 self.HiliteLink(item) 454 self.sr.hiliteLinks.append(item) 455 456 def HiliteLink(self, link): 457 if link.sr.attrs.alink_color: 458 c = link.sr.attrs.alink_color 459 Fill(parent=link, color=(c[0], 460 c[1], 461 c[2], 462 c[3] * 0.5), pos=(-2, 0, -2, 0)) 463 464 def LinkExit(self, link, *args): 465 browser = GetBrowser(self) 466 if browser and browser.sr.window and hasattr(browser.sr.window, 'ShowHint'): 467 browser.sr.window.ShowHint('') 468 for each in self.sr.hiliteLinks: 469 each.Flush() 470 471 def SelectionHandlerDelegate(self, funcName, args): 472 handler = self.sr.node.Get('SelectionHandler', None) 473 if handler: 474 func = getattr(handler, funcName, None) 475 if func: 476 return func(*args) 477 478 def GetMenu(self): 479 self.sr.node.scroll.ShowHint('') 480 return self.SelectionHandlerDelegate('GetMenuDelegate', (self.sr.node,)) 481 482 def OnMouseMove(self, *args): 483 self.SelectionHandlerDelegate('OnMouseMoveDelegate', (self.sr.node,)) 484 485 def OnMouseDown(self, button, *args): 486 if button == 0: 487 self.SelectionHandlerDelegate('OnMouseDownDelegate', (self.sr.node,)) 488 489 def OnMouseUp(self, button, *args): 490 if button == 0: 491 self.SelectionHandlerDelegate('OnMouseUpDelegate', (self.sr.node,)) 492 493 def OnDropData(self, dragObj, nodes): 494 self.SelectionHandlerDelegate('OnDropDataDelegate', (self.sr.node, nodes)) 495 496 def OnDragMove(self, nodes, *args): 497 self.SelectionHandlerDelegate('OnDragMoveDelegate', (self.sr.node, nodes)) 498 499 def OnDragEnter(self, dragObj, nodes): 500 self.SelectionHandlerDelegate('OnDragEnterDelegate', (self.sr.node, nodes)) 501 502 def OnDragExit(self, dragObj, nodes): 503 self.SelectionHandlerDelegate('OnDragExitDelegate', (self.sr.node, nodes)) 504 505 def OnClick(self, *args): 506 pass 507 508 def OnDblClick(self, *args): 509 self.SelectionHandlerDelegate('SelectWordUnderCursor', ()) 510 511 def OnTripleClick(self, *args): 512 self.SelectionHandlerDelegate('SelectLineUnderCursor', ()) 513 514 def GetScrollAbove(self): 515 from carbonui.control.scroll import Scroll 516 item = self.parent 517 while item: 518 if isinstance(item, Scroll): 519 return item 520 item = item.parent 521 522 def UpdateSelectionHilite(self): 523 if not self.sr.node: 524 return 525 scrollAbove = self.GetScrollAbove() 526 f = uicore.registry.GetFocus() 527 if not scrollAbove or scrollAbove is not f or not trinity.app.IsActive(): 528 selectionAlpha = 0.125 529 else: 530 selectionAlpha = 0.25 531 if self.sr.node.selectionStartIndex is not None: 532 if self.sr.textselection is None: 533 self.sr.textselection = Fill(parent=self, align=uiconst.TOPLEFT, state=uiconst.UI_HIDDEN) 534 self.sr.textselection.SetAlpha(selectionAlpha) 535 if self.sr.node.inlines: 536 left = 0 537 width = 0 538 for inline, x in self.sr.node.inlines: 539 width = max(width, inline.width) 540 541 else: 542 left = uicore.font.GetWidthToIdx(self.sr.node, self.sr.node.selectionStartIndex) 543 right = uicore.font.GetWidthToIdx(self.sr.node, self.sr.node.selectionEndIndex) 544 width = uicore.ReverseScaleDpi(right - left) 545 left = uicore.ReverseScaleDpi(left) 546 self.sr.textselection.left = self.leftM + left 547 self.sr.textselection.width = width 548 self.sr.textselection.height = self.height 549 self.sr.textselection.top = 0 550 self.sr.textselection.state = uiconst.UI_DISABLED 551 elif self.sr.textselection: 552 self.sr.textselection.state = uiconst.UI_HIDDEN 553 554 def UpdateCursor(self): 555 if self.sr.node.cursorPos is not None: 556 sprite = self.GetSprite() 557 if self.sr.textcursor is None: 558 self.sr.textcursor = Fill(parent=self, align=uiconst.TOPLEFT, state=uiconst.UI_HIDDEN, color=(1.0, 1.0, 1.0, 1.0)) 559 self.sr.textcursor.top = 0 560 self.sr.textcursor.width = 1 561 left = uicore.font.GetWidthToIdx(self.sr.node, self.sr.node.cursorPos) 562 self.sr.textcursor.left = self.sr.inlines.left + uicore.ReverseScaleDpi(left) 563 self.sr.textcursor.height = self.height 564 if self.sr.cursortimer is None: 565 self.CursorBlink() 566 elif self.sr.textcursor: 567 self.sr.cursortimer = None 568 self.sr.textcursor.state = uiconst.UI_HIDDEN 569 570 def GetCursorOffset(self): 571 if self.sr.textcursor: 572 return self.sr.textcursor.left 573 574 def CursorBlink(self): 575 f = uicore.registry.GetFocus() 576 if f is uicore.desktop or not trinity.app.IsActive(): 577 if self.sr.textcursor: 578 self.sr.textcursor.state = uiconst.UI_HIDDEN 579 self.sr.cursortimer = None 580 return 581 if f and self.IsUnder(f) and self.sr.node.cursorPos is not None and self.sr.textcursor is not None: 582 self.sr.textcursor.state = [uiconst.UI_HIDDEN, uiconst.UI_DISABLED][self.sr.textcursor.state == uiconst.UI_HIDDEN] 583 if self.sr.cursortimer is None: 584 self.sr.cursortimer = AutoTimer(250, self.CursorBlink) 585 else: 586 self.sr.cursortimer = None 587 self.sr.textcursor.state = uiconst.UI_HIDDEN 588 589 def GetCopyData(self, fromIdx, toIdx): 590 return uicore.font.GetNodeCopyData(self.sr.node, fromIdx, toIdx) 591 592 def GetText(self, node): 593 if node.rawText: 594 return node.rawText 595 text = ''.join([ glyphData[4] for glyphData in self.sr.node.glyphString if glyphData[4] != None ]) 596 node.rawText = text 597 return text 598 599 def GetDynamicHeight(node, width): 600 return node.maxBaseHeight 601 602 603 class SE_ListGroupCore(SE_BaseClassCore): 604 __guid__ = 'uicontrols.SE_ListGroupCore' 605 ENTRYHEIGHT = 18 606 607 def ApplyAttributes(self, attributes): 608 SE_BaseClassCore.ApplyAttributes(self, attributes) 609 self.sr.entries = [] 610 self.dblclick = 0 611 self.sr.expander = None 612 self.sr.icon = None 613 614 def _OnClose(self): 615 SE_BaseClassCore._OnClose(self) 616 self.sr.entries = None 617 618 def Startup(self, *etc): 619 self.Prepare_ExpanderIcon_() 620 self.Prepare_Icon_() 621 self.Prepare_Label_() 622 self.Prepare_Selection_() 623 self.Prepare_Background_() 624 625 def Prepare_Label_(self): 626 self.sr.labelClipper = Container(parent=self, pos=(0, 0, 0, 0), clipChildren=1) 627 if uicore.fontHandler: 628 labelClass = uicore.fontHandler.defaultLabelClass 629 else: 630 labelClass = LabelCore 631 self.sr.label = labelClass(text='', parent=self.sr.labelClipper, pos=(self.labelLeftDefault, 632 0, 633 0, 634 0), state=uiconst.UI_DISABLED, maxLines=1, idx=0, align=uiconst.CENTERLEFT, fontsize=12) 635 636 def Prepare_Background_(self): 637 self.sr.background = Fill(parent=self, color=(0.0, 0.0, 0.0, 0.5), pos=(0, 1, 0, 1)) 638 639 def Prepare_ExpanderIcon_(self): 640 self.sr.expander = Sprite(align=uiconst.CENTERRIGHT, pos=(3, 0, 16, 16), parent=self, name='expander', idx=0) 641 self.sr.expander.LoadIcon('ui_1_16_97') 642 self.sr.expander.OnClick = self.Toggle 643 644 def Prepare_Icon_(self): 645 self.sr.icon = Sprite(align=uiconst.CENTERLEFT, pos=(0, 0, 16, 16), parent=self, idx=0, name='icon') 646 647 def Load(self, node): 648 self.sr.node = node 649 self.sr.id = node.id 650 self.sr.subitems = node.get('subitems', []) 651 self.UpdateLabel() 652 self.hint = node.get('hint', '') 653 sublevel = node.get('sublevel', 0) 654 self.sr.label.left = 20 + 16 * sublevel 655 if self.sr.icon: 656 self.sr.icon.left = 16 * sublevel 657 if node.get('selected', 0): 658 self.Select() 659 else: 660 self.Deselect() 661 if self.sr.expander: 662 self.sr.expander.state = [uiconst.UI_NORMAL, uiconst.UI_HIDDEN][node.get('hideExpander', 0)] 663 for k, v in node.get('labelstyle', {}).iteritems(): 664 setattr(self.sr.label, k, v) 665 666 if self.sr.icon: 667 icon = node.get('showicon', '') 668 graphicID = node.get('graphicID', None) 669 if graphicID: 670 self.sr.icon.LoadIconByIconID(graphicID) 671 self.sr.icon.SetSize(64, 64) 672 self.sr.icon.state = uiconst.UI_DISABLED 673 elif icon == 'hide': 674 if self.sr.icon: 675 self.sr.icon.state = uiconst.UI_HIDDEN 676 self.sr.label.left -= 12 677 else: 678 MapIcon(self.sr.icon, icon or 'ui_2_32_1') 679 self.sr.icon.state = uiconst.UI_DISABLED 680 self.sr.icon.width = self.sr.icon.height = 16 681 if node.panel is not self or self is None: 682 return 683 self.ShowOpenState(uicore.registry.GetListGroupOpenState(self.sr.id, default=node.get('openByDefault', False))) 684 685 def OnDropData(self, dragObj, nodes): 686 if self == dragObj: 687 return 688 if self.sr.node.get('DropData', None): 689 self.sr.node.DropData(self.sr.node.id, nodes) 690 return 691 ids = [] 692 myListGroupID = self.sr.node.id 693 for node in nodes: 694 guid = getattr(node, '__guid__', None) 695 if guid not in self.sr.node.get('allowGuids', []): 696 log.LogWarn('dropnode.__guid__ has to be listed in group.node.allowGuids', guid, self.sr.node.get('allowGuids', [])) 697 continue 698 if not node.get('itemID', None): 699 log.LogWarn('dropitem data has to have itemID') 700 continue 701 currentListGroupID = node.get('listGroupID', None) 702 ids.append((node.itemID, currentListGroupID, myListGroupID)) 703 704 for itemID, currentListGroupID, myListGroupID in ids: 705 if currentListGroupID and itemID: 706 uicore.registry.RemoveFromListGroup(currentListGroupID, itemID) 707 uicore.registry.AddToListGroup(myListGroupID, itemID) 708 709 if self.sr.node.get('RefreshScroll', None): 710 self.sr.node.RefreshScroll() 711 else: 712 self.RefreshScroll() 713 714 def Clear(self): 715 self.sr.node.panel = None 716 717 def OnClick(self, *args, **kwargs): 718 if not self.dblclick and not self.sr.node.get('disableToggle', 0): 719 self.Toggle() 720 if self.sr.node and self.sr.node.scroll and self.sr.node.selectGroup: 721 self.sr.node.scroll.SelectNode(self.sr.node) 722 if not self.destroyed and self.sr.get('node', None) and self.sr.node.get('OnClick', None): 723 self.sr.node.OnClick(self, *args, **kwargs) 724 725 def OnMouseDown(self, *args): 726 SE_BaseClassCore.OnMouseDown(self, *args) 727 if self.sr.get('node', None) and self.sr.node.get('OnMouseDown', None): 728 self.sr.node.OnMouseDown(self) 729 730 def RefreshScroll(self): 731 node = self.sr.node 732 if node.open: 733 if not node.get('GetContentIDList', None) or not node.get('CreateEntry', None): 734 return 735 entries = node.subEntries 736 if not entries: 737 self.LoadContent() 738 return 739 addlist = [] 740 rmlist = [] 741 entryIDs = [] 742 self.sr.subitems = newcontent = self.sr.node.GetContentIDList(node.id) 743 for entry in entries: 744 if not entry.get('id', None): 745 if len(newcontent): 746 rmlist.append(entry) 747 continue 748 if entry.id not in newcontent: 749 rmlist.append(entry) 750 else: 751 entryIDs.append(entry.id) 752 753 for id in newcontent: 754 if id not in entryIDs: 755 newEntry = node.CreateEntry(id, node.sublevel + 1) 756 if newEntry is not None: 757 addlist.append(newEntry) 758 759 if not len(newcontent) and len(node.subEntries) and node.subEntries[0].label != localization.GetByLabel('/Carbon/UI/Controls/Common/NoItem'): 760 noItem = self.GetNoItemEntry() 761 if noItem: 762 addlist.append(noItem) 763 if self.sr.node: 764 node.scroll.RemoveNodes(rmlist) 765 entries += node.scroll.AddNodes(node.idx + 1, addlist) 766 for entry in rmlist: 767 entries.remove(entry) 768 769 node.subEntries = entries 770 self.UpdateLabel() 771 772 def GetNoItemEntry(self): 773 return None 774 775 def GetMenu(self): 776 m = [] 777 node = self.sr.node 778 if not node.get('showmenu', True): 779 return m 780 if not node.open: 781 m += [(MenuLabel('/Carbon/UI/Common/Expand'), self.Toggle, ())] 782 else: 783 m += [(MenuLabel('/Carbon/UI/Common/Collapse'), self.Toggle, ())] 784 if node.get('state', None) != 'locked': 785 m += [(MenuLabel('/Carbon/UI/Controls/ScrollEntries/ChangeLabel'), self.ChangeLabel)] 786 m += [(MenuLabel('/Carbon/UI/Controls/ScrollEntries/DeleteFolder'), self.DeleteFolder)] 787 if node.get('MenuFunction', None): 788 cm = node.MenuFunction(node) 789 m += cm 790 return m 791 792 def ChangeLabel(self): 793 newgroupName = self.GetNewGroupName() 794 if not newgroupName or not self or self.destroyed: 795 return 796 if isinstance(newgroupName, dict): 797 newgroupName = newgroupName['name'] 798 self.sr.node.label = newgroupName 799 if self.sr.node.get('ChangeLabel', None): 800 self.sr.node.ChangeLabel(self.sr.node.id, newgroupName) 801 uicore.registry.ChangeListGroupLabel(self.sr.node.id, newgroupName) 802 wnd = uicore.registry.GetWindow(unicode(self.sr.node.id)) 803 if wnd: 804 wnd.SetCaption(' ' + newgroupName) 805 if self.sr.node.get('DropCallback', None): 806 self.sr.node.DropCallback(self.sr.node.id, None) 807 if self.sr.node.get('RefreshScroll', None): 808 self.sr.node.RefreshScroll() 809 else: 810 self.RefreshScroll() 811 812 def GetNewGroupName(self): 813 from eve.client.script.ui.util.utilWindows import NamePopup 814 return NamePopup(localization.GetByLabel('/Carbon/UI/Controls/ScrollEntries/TypeInNewName'), localization.GetByLabel('/Carbon/UI/Controls/ScrollEntries/TypeInNewFolderName')) 815 816 def DeleteFolder(self): 817 id = self.sr.id 818 if prompt_player_fsd_dialog('ConfirmDeleteFolder', {}, uiconst.YESNO, uiconst.ID_YES) == uiconst.ID_YES: 819 if self.sr.node.get('DeleteCallback', None): 820 self.sr.node.DeleteCallback(self.sr.subitems) 821 if self.sr.node.get('DeleteFolder', None): 822 self.sr.node.DeleteFolder(id) 823 uicore.registry.DeleteListGroup(id) 824 if not self or self.destroyed: 825 return 826 self.CloseWindow(unicode(id)) 827 if self.sr.node.get('DropCallback', None): 828 self.sr.node.DropCallback(id, None) 829 if self.sr.node.get('RefreshScroll', None): 830 self.sr.node.RefreshScroll() 831 832 def CloseWindow(self, windowID): 833 wnd = uicore.registry.GetWindow(windowID) 834 if wnd: 835 wnd.Close() 836 837 def OnDragEnter(self, dragObj, nodes): 838 if self.sr.node.get('DragEnterCallback', None): 839 self.sr.node.DragEnterCallback(self, dragObj) 840 elif getattr(nodes[0], '__guid__', None) in self.sr.node.get('allowGuids', []): 841 self.Select() 842 843 def OnDragExit(self, dragObj, nodes): 844 self.Deselect() 845 846 def Toggle(self, *args): 847 node = self.sr.node 848 if not node or node.get('toggling', 0): 849 return 850 node.toggling = 1 851 w = node.panel 852 if not w: 853 node.toggling = 0 854 return 855 node.open = not node.open 856 if node.open: 857 self.CloseWindow(unicode(node.id)) 858 if node.open: 859 PlaySound(uiconst.SOUND_EXPAND) 860 else: 861 PlaySound(uiconst.SOUND_COLLAPSE) 862 self.ShowOpenState(node.open) 863 self.UpdateLabel() 864 uicore.registry.SetListGroupOpenState(node.id, node.open) 865 node.scroll.PrepareSubContent(node) 866 if node.get('onToggle', None): 867 node.onToggle() 868 node.toggling = 0 869 870 def ShowOpenState(self, open_): 871 if self.sr.expander: 872 if open_: 873 MapIcon(self.sr.expander, 'ui_1_16_98') 874 else: 875 MapIcon(self.sr.expander, 'ui_1_16_97') 876 877 def UpdateLabel(self): 878 node = self.sr.node 879 if 'cleanLabel' not in node: 880 node.cleanLabel = node.label 881 text = node.cleanLabel 882 if self.sr.subitems is not None and node.get('showlen', 1): 883 text = localization.GetByLabel('/Carbon/UI/Controls/ScrollEntries/LabelWithLength', label=text, length=len(self.sr.subitems)) 884 posttext = node.get('posttext', '') 885 if posttext: 886 text = localization.GetByLabel('/Carbon/UI/Controls/ScrollEntries/LabelWithPostfix', label=text, postfix=posttext) 887 self.sr.label.text = text 888 node.label = text 889 890 891 def ScrollEntryNode(**kw): 892 data = Bunch(**kw) 893 decoClass = data.get('decoClass', SE_GenericCore) 894 data.decoClass = decoClass 895 data.GetHeightFunction = getattr(decoClass, 'GetHeight', None) 896 data.GetColumnWidthFunction = getattr(decoClass, 'GetColumnWidth', None) 897 data.PreLoadFunction = getattr(decoClass, 'PreLoad', None) 898 data.allowDynamicResize = getattr(decoClass, 'allowDynamicResize', False) 899 if data.GetHeightFunction: 900 data.GetHeightFunction = data.GetHeightFunction.__func__ 901 if data.PreLoadFunction: 902 data.PreLoadFunction = data.PreLoadFunction.__func__ 903 if data.GetColumnWidthFunction: 904 data.GetColumnWidthFunction = data.GetColumnWidthFunction.__func__ 905 if not data.charIndex and data.label: 906 data.charIndex = GetAsUnicode(data.label).split('<t>')[0] 907 if data.charIndex: 908 data.charIndex = data.charIndex.lower() 909 return data