container.py (16095B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\primitives\container.py 2 import weakref 3 import trinity 4 from carbonui.util.autonaming import apply_auto_naming 5 from carbonui import uiconst 6 from carbonui.primitives.backgroundList import BackgroundList 7 from carbonui.primitives.base import Base 8 from carbonui.primitives.childrenlist import PyChildrenList 9 from carbonui.primitives.fill import Fill 10 from carbonui.primitives.sprite import Sprite 11 from carbonui.uiconst import PickState 12 from carbonui.uicore import uicore 13 import logging 14 log = logging.getLogger(__name__) 15 16 class Container(Base): 17 __guid__ = 'uiprimitives.Container' 18 __renderObject__ = trinity.Tr2Sprite2dContainer 19 isDropLocation = True 20 default_clipChildren = False 21 default_pickRadius = 0 22 default_opacity = 1.0 23 default_align = uiconst.TOALL 24 default_state = uiconst.UI_PICKCHILDREN 25 default_pickState = PickState.CHILDREN 26 default_depthMin = 0.0 27 default_depthMax = 0.0 28 default_bgColor = None 29 default_bgTexturePath = None 30 default_bgRotation = 0.0 31 default_bgBlendMode = trinity.TR2_SBM_BLEND 32 default_bgSpriteEffect = Sprite.default_spriteEffect 33 default_bgOutputMode = Sprite.default_outputMode 34 _cacheContents = False 35 _containerClosing = False 36 _childrenAlignmentDirty = False 37 _backgroundlist = None 38 _opacity = None 39 40 def ApplyAttributes(self, attributes): 41 self.children = self.GetChildrenList() 42 Base.ApplyAttributes(self, attributes) 43 self.depthMin = attributes.get('depthMin', self.default_depthMin) 44 self.depthMax = attributes.get('depthMax', self.default_depthMax) 45 self.pickRadius = attributes.get('pickRadius', self.default_pickRadius) 46 self.opacity = attributes.get('opacity', self.default_opacity) 47 self.clipChildren = attributes.get('clipChildren', self.default_clipChildren) 48 self._bgColor = attributes.get('bgColor', self.default_bgColor) 49 self._bgTexturePath = attributes.get('bgTexturePath', self.default_bgTexturePath) 50 self._bgRotation = attributes.get('bgRotation', self.default_bgRotation) 51 self._bgBlendMode = attributes.get('bgBlendMode', self.default_bgBlendMode) 52 self._bgSpriteEffect = attributes.get('bgSpriteEffect', self.default_bgSpriteEffect) 53 self._bgSpriteOutputMode = attributes.get('bgOutputMode', self.default_bgOutputMode) 54 self._bgSprite = None 55 self.bgFill = None 56 self._SetupBackground() 57 try: 58 self._ApplyAutonaming(attributes) 59 except Exception as exc: 60 log.exception('Failed to autoname container: %s', exc) 61 62 def _SetupBackground(self): 63 if self._bgSprite is not None: 64 self._bgSprite.Close() 65 if self.bgFill is not None: 66 self.bgFill.Close() 67 if self._bgTexturePath: 68 self._bgSprite = Sprite(bgParent=self, texturePath=self._bgTexturePath, color=self._bgColor or (1.0, 1.0, 1.0, 1.0), rotation=self._bgRotation, blendMode=self._bgBlendMode, outputMode=self._bgSpriteOutputMode, spriteEffect=self._bgSpriteEffect) 69 elif self._bgColor: 70 self.bgFill = Fill(bgParent=self, color=self._bgColor, rotation=self._bgRotation, blendMode=self._bgBlendMode) 71 72 def _ApplyAutonaming(self, attributes): 73 apply_auto_naming(self, attributes) 74 75 def Close(self): 76 if getattr(self, 'destroyed', False): 77 return 78 self._containerClosing = True 79 for child in self.children: 80 child.Close() 81 82 self.children = [] 83 if self._backgroundlist: 84 for child in self.background[:]: 85 child.Close() 86 87 Base.Close(self) 88 89 def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False): 90 forceUpdate = self._forceUpdateAlignment 91 if updateChildrenOnly: 92 childrenDirty = True 93 sizeChange = False 94 else: 95 budgetLeft, budgetTop, budgetWidth, budgetHeight, sizeChange = Base.UpdateAlignment(self, budgetLeft, budgetTop, budgetWidth, budgetHeight) 96 childrenDirty = self._childrenAlignmentDirty 97 self._childrenAlignmentDirty = False 98 if childrenDirty or forceUpdate or sizeChange: 99 self._update_children_alignment(sizeChange, forceUpdate) 100 return (budgetLeft, 101 budgetTop, 102 budgetWidth, 103 budgetHeight, 104 sizeChange) 105 106 def _update_children_alignment(self, sizeChange, forceUpdate): 107 flagNextChild = False 108 cbLeft, cbTop, cbWidth, cbHeight = (0, 109 0, 110 self.displayWidth, 111 self.displayHeight) 112 for each in self.children: 113 if each.destroyed: 114 continue 115 if each.display and forceUpdate: 116 each._forceUpdateAlignment = True 117 isPushAligned = each.isPushAligned 118 if isPushAligned and each._forceUpdateAlignment: 119 flagNextChild = True 120 if each.display: 121 if not each._alignmentDirty and (sizeChange or flagNextChild and each.isAffectedByPushAlignment): 122 each._alignmentDirty = True 123 if getattr(each, '_childrenAlignmentDirty', False) or each._alignmentDirty or each._forceUpdateAlignment or isPushAligned: 124 preDisplayX = each.displayX 125 preDisplayY = each.displayY 126 cbLeft, cbTop, cbWidth, cbHeight, changedSize = each.UpdateAlignment(cbLeft, cbTop, cbWidth, cbHeight) 127 if not flagNextChild and isPushAligned: 128 flagNextChild = changedSize or preDisplayX != each.displayX or preDisplayY != each.displayY 129 130 def GetChildrenList(self): 131 return PyChildrenList(self) 132 133 def GetOpacity(self): 134 return self.opacity 135 136 def SetOpacity(self, opacity): 137 self.opacity = opacity 138 139 def IsVisibleAndClickable(self): 140 if not hasattr(self, 'opacity'): 141 return False 142 if self.opacity <= 0.5: 143 return False 144 return super(Container, self).IsVisibleAndClickable() 145 146 def AutoFitToContent(self): 147 if self.isAffectedByPushAlignment: 148 raise RuntimeError('AutoFitToContent: invalid alignment') 149 minWidth = 0 150 minHeight = 0 151 totalAutoVertical = 0 152 totalAutoHorizontal = 0 153 for each in self.children: 154 if not each.isAffectedByPushAlignment: 155 minWidth = max(minWidth, each.left + each.width) 156 minHeight = max(minHeight, each.top + each.height) 157 elif each.align in (uiconst.TOTOP, uiconst.TOBOTTOM): 158 totalAutoVertical += each.padTop + each.height + each.padBottom 159 elif each.align in (uiconst.TOLEFT, uiconst.TORIGHT): 160 totalAutoHorizontal += each.padLeft + each.width + each.padRight 161 162 self.width = max(minWidth, totalAutoHorizontal) 163 self.height = max(minHeight, totalAutoVertical) 164 165 def Flush(self): 166 for child in self.children[:]: 167 child.Close() 168 169 def FindChild(self, *names, **kwds): 170 if self.destroyed: 171 return 172 ret = None 173 searchFrom = self 174 for name in names: 175 ret = searchFrom._FindChildByName(name) 176 if hasattr(ret, 'children'): 177 searchFrom = ret 178 179 if not ret or ret.name != names[-1]: 180 if kwds.get('raiseError', False): 181 raise RuntimeError('ChildNotFound', (self.name, names)) 182 return 183 return ret 184 185 def _FindChildByName(self, name, lvl = 0): 186 for child in self.children: 187 if child.name == name: 188 return child 189 190 for child in self.children: 191 if hasattr(child, 'children'): 192 ret = child._FindChildByName(name, lvl + 1) 193 if ret is not None: 194 return ret 195 196 def iter_children(self): 197 for child in self.children: 198 yield child 199 200 def iter_descendants_breadth_first(self): 201 remaining = list((weakref.ref(child) for child in self.children)) 202 while remaining: 203 element_ref = remaining.pop(0) 204 element = element_ref() 205 if element is None: 206 continue 207 yield element 208 if hasattr(element, 'children'): 209 remaining.extend((weakref.ref(child) for child in element.children)) 210 211 def iter_descendants_depth_first(self): 212 remaining = list((weakref.ref(child) for child in reversed(self.children))) 213 while remaining: 214 element_ref = remaining.pop() 215 element = element_ref() 216 if element is None: 217 continue 218 yield element 219 remaining.extend((weakref.ref(child) for child in reversed(getattr(element, 'children', [])))) 220 221 def Find(self, triTypeName): 222 return list(filter(lambda element: getattr(element, '__bluetype__', None) == triTypeName, self.iter_descendants_depth_first())) 223 224 def FindByInstance(self, classTypeOrTypeTuple): 225 return set(filter(lambda element: isinstance(element, classTypeOrTypeTuple), self.iter_descendants_depth_first())) 226 227 def GetChild(self, *names): 228 return self.FindChild(*names, **{'raiseError': True}) 229 230 def IsChildClipped(self, child): 231 if not self.clipChildren: 232 return False 233 cdx = child.displayX 234 cdw = child.displayWidth 235 sdx = self.displayX 236 sdw = self.displayWidth 237 if cdx >= sdx and cdx <= sdx + sdw or cdx + cdw >= sdx and cdx + cdw <= sdx + sdw: 238 cdy = child.displayY 239 cdh = child.displayHeight 240 sdy = self.displayY 241 sdh = self.displayHeight 242 if cdy >= sdy and cdy <= sdy + sdh or cdy + cdh >= sdy and cdy + cdh <= sdy + sdh: 243 return False 244 return True 245 246 @property 247 def background(self): 248 if not self._backgroundlist: 249 self._backgroundlist = BackgroundList(self) 250 return self._backgroundlist 251 252 @property 253 def depthMin(self): 254 return self._depthMin 255 256 @depthMin.setter 257 def depthMin(self, value): 258 self._depthMin = value 259 ro = self.renderObject 260 if ro and hasattr(ro, 'depthMin'): 261 ro.depthMin = value or 0.0 262 263 @property 264 def depthMax(self): 265 return self._depthMax 266 267 @depthMax.setter 268 def depthMax(self, value): 269 self._depthMax = value 270 ro = self.renderObject 271 if ro and hasattr(ro, 'depthMax'): 272 ro.depthMax = value or 0.0 273 274 @property 275 def clipChildren(self): 276 return self._clipChildren 277 278 @clipChildren.setter 279 def clipChildren(self, value): 280 self._clipChildren = value 281 ro = self.renderObject 282 if ro and hasattr(ro, 'clip'): 283 ro.clip = value 284 285 @property 286 def opacity(self): 287 return self._opacity 288 289 @opacity.setter 290 def opacity(self, value): 291 self._SetOpacity(value) 292 293 def _SetOpacity(self, value): 294 if value != self._opacity: 295 self._opacity = value 296 ro = self.renderObject 297 if ro and hasattr(ro, 'opacity'): 298 ro.opacity = value or 0.0 299 for child in self.children: 300 childRenderObject = child.renderObject 301 if childRenderObject: 302 childRenderObject.isDirty = True 303 304 @property 305 def pickRadius(self): 306 return self._pickRadius 307 308 @pickRadius.setter 309 def pickRadius(self, value): 310 self._pickRadius = value 311 ro = self.renderObject 312 if ro and hasattr(ro, 'pickRadius'): 313 if value < 0: 314 ro.pickRadius = value 315 else: 316 ro.pickRadius = uicore.ScaleDpi(value) or 0.0 317 318 @Base.displayWidth.setter 319 def displayWidth(self, value): 320 Base.displayWidth.fset(self, value) 321 if self._backgroundlist and len(self.background): 322 self.UpdateBackgrounds() 323 324 @Base.displayHeight.setter 325 def displayHeight(self, value): 326 Base.displayHeight.fset(self, value) 327 if self._backgroundlist and len(self.background): 328 self.UpdateBackgrounds() 329 330 @Base.displayRect.setter 331 def displayRect(self, value): 332 Base.displayRect.fset(self, value) 333 if self._backgroundlist and len(self.background): 334 self.UpdateBackgrounds() 335 336 def UpdateBackgrounds(self): 337 for each in self.background: 338 pl, pt, pr, pb = each.padding 339 each.displayRect = (uicore.ScaleDpi(pl), 340 uicore.ScaleDpi(pt), 341 self._displayWidth - uicore.ScaleDpi(pl + pr), 342 self._displayHeight - uicore.ScaleDpi(pt + pb)) 343 344 @property 345 def cacheContents(self): 346 return self._cacheContents 347 348 @cacheContents.setter 349 def cacheContents(self, value): 350 self._cacheContents = value 351 if self.renderObject: 352 self.renderObject.cacheContents = value 353 354 def _AppendChildRO(self, child): 355 try: 356 self.renderObject.children.append(child.renderObject) 357 except (AttributeError, TypeError): 358 pass 359 360 def _InsertChildRO(self, idx, child): 361 try: 362 self.renderObject.children.insert(idx, child.renderObject) 363 except IndexError: 364 self.renderObject.children.append(child.renderObject) 365 except (AttributeError, TypeError): 366 pass 367 368 def _RemoveChildRO(self, child): 369 try: 370 self.renderObject.children.remove(child.renderObject) 371 except (AttributeError, 372 ValueError, 373 RuntimeError, 374 TypeError): 375 pass 376 377 def AppendBackgroundObject(self, child): 378 try: 379 self.renderObject.background.append(child.renderObject) 380 except AttributeError: 381 pass 382 383 def InsertBackgroundObject(self, idx, child): 384 try: 385 self.renderObject.background.insert(idx, child.renderObject) 386 except AttributeError: 387 pass 388 389 def RemoveBackgroundObject(self, child): 390 try: 391 self.renderObject.background.remove(child.renderObject) 392 except (AttributeError, 393 ValueError, 394 RuntimeError, 395 TypeError): 396 pass 397 398 @property 399 def background_color(self): 400 return self._bgColor 401 402 @background_color.setter 403 def background_color(self, value): 404 self._bgColor = value 405 self._SetupBackground() 406 407 @property 408 def background_texture_path(self): 409 return self._bgTexturePath 410 411 @background_texture_path.setter 412 def background_texture_path(self, value): 413 self._bgTexturePath = value 414 self._SetupBackground() 415 416 def UpdateUIScaling(self, value, oldValue): 417 for child in self.children: 418 child.UpdateUIScaling(value, oldValue) 419 420 for bgChild in self.background: 421 bgChild.UpdateUIScaling(value, oldValue) 422 423 def OnColorThemeChanged(self): 424 for child in self.children: 425 child.OnColorThemeChanged() 426 427 for bgChild in self.background: 428 bgChild.OnColorThemeChanged() 429 430 def OnWindowAboveSetActive(self): 431 for child in self.children: 432 child.OnWindowAboveSetActive() 433 434 for bgChild in self.background: 435 bgChild.OnWindowAboveSetActive() 436 437 def OnWindowAboveSetInactive(self): 438 for child in self.children: 439 child.OnWindowAboveSetInactive() 440 441 for bgChild in self.background: 442 bgChild.OnWindowAboveSetInactive() 443 444 def OnGlobalFontSizeChanged(self): 445 for child in self.children: 446 child.OnGlobalFontSizeChanged() 447 448 for bgChild in self.background: 449 bgChild.OnGlobalFontSizeChanged() 450 451 def OnGlobalFontShadowChanged(self): 452 for child in self.children: 453 child.OnGlobalFontShadowChanged() 454 455 for bgChild in self.background: 456 bgChild.OnGlobalFontShadowChanged()