containerAutoSize.py (9548B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\primitives\containerAutoSize.py 2 import telemetry 3 from carbonui import uiconst, Align 4 from carbonui.primitives.container import Container 5 from carbonui.primitives.childrenlist import PyChildrenList as UIChildrenList 6 from carbonui.uianimations import animations 7 ALLOWED_ALIGNMENTS = (uiconst.TOLEFT, 8 uiconst.TORIGHT, 9 uiconst.TOTOP, 10 uiconst.TOBOTTOM, 11 uiconst.TOPLEFT, 12 uiconst.TOPRIGHT, 13 uiconst.CENTER, 14 uiconst.CENTERTOP, 15 uiconst.CENTERBOTTOM, 16 uiconst.CENTERLEFT, 17 uiconst.CENTERRIGHT, 18 uiconst.BOTTOMLEFT, 19 uiconst.BOTTOMRIGHT, 20 uiconst.NOALIGN, 21 uiconst.TOLEFT_NOPUSH, 22 uiconst.TOTOP_NOPUSH, 23 uiconst.TORIGHT_NOPUSH, 24 uiconst.TOBOTTOM_NOPUSH, 25 uiconst.TOTOP_STICKY, 26 uiconst.VERTICALLY_CENTERED) 27 ALIGNMENT_MAPPING = {Align.TOTOP_STICKY: Align.TOTOP} 28 29 def GetMappedAlignment(align): 30 return ALIGNMENT_MAPPING.get(align, align) 31 32 33 class ContainerAutoSize(Container): 34 default_align = uiconst.TOPLEFT 35 default_alignMode = None 36 _childrenAlign = None 37 isAutoSizeEnabled = True 38 alignMode = None 39 callback = None 40 41 def ApplyAttributes(self, attributes): 42 self.alignMode = attributes.Get('alignMode', self.default_alignMode) 43 self.callback = attributes.Get('callback', None) 44 self._only_use_callback_when_size_changes = attributes.Get('only_use_callback_when_size_changes', False) 45 self._isCollapsed = False 46 Container.ApplyAttributes(self, attributes) 47 48 @property 49 def minWidth(self): 50 return self._minWidth 51 52 @minWidth.setter 53 def minWidth(self, minWidth): 54 if minWidth != self._minWidth: 55 self._minWidth = minWidth 56 if self.width < minWidth: 57 self.FlagAlignmentDirty() 58 59 @property 60 def minHeight(self): 61 return self._minHeight 62 63 @minHeight.setter 64 def minHeight(self, minHeight): 65 if minHeight != self._minHeight: 66 self._minHeight = minHeight 67 if self.height < minHeight: 68 self.FlagAlignmentDirty() 69 70 @property 71 def maxWidth(self): 72 return self._maxWidth 73 74 @maxWidth.setter 75 def maxWidth(self, maxWidth): 76 if maxWidth != self._maxWidth: 77 self._maxWidth = maxWidth 78 if self.width > maxWidth: 79 self.FlagAlignmentDirty() 80 81 @property 82 def maxHeight(self): 83 return self._maxHeight 84 85 @maxHeight.setter 86 def maxHeight(self, maxHeight): 87 if maxHeight != self._maxHeight: 88 self._maxHeight = maxHeight 89 if self.height != maxHeight: 90 self.FlagAlignmentDirty() 91 92 @property 93 def isCollapsed(self): 94 return self._isCollapsed 95 96 @telemetry.ZONE_METHOD 97 def SetSizeAutomatically(self): 98 if self.align == uiconst.TOALL: 99 self.DisableAutoSize() 100 if not self.isAutoSizeEnabled: 101 return 102 size_changed = False 103 width, height = self.GetAutoSize() 104 if width is not None: 105 width_before = self.width 106 if self.minWidth is not None: 107 self.width = max(width, self.minWidth) 108 elif self.maxWidth is not None: 109 self.width = min(width, self.maxWidth) 110 else: 111 self.width = width 112 if self.width != width_before: 113 size_changed = True 114 if height is not None: 115 height_before = self.height 116 if self.minHeight is not None: 117 self.height = max(height, self.minHeight) 118 elif self.maxHeight is not None: 119 self.height = min(height, self.maxHeight) 120 else: 121 self.height = height 122 if self.height != height_before: 123 size_changed = True 124 if self.callback and (not self._only_use_callback_when_size_changes or self._only_use_callback_when_size_changes and size_changed): 125 self.callback() 126 127 @telemetry.ZONE_METHOD 128 def GetAutoSize(self): 129 horizontal_padding = 0 130 vertical_padding = 0 131 if self.align in uiconst.ALIGNMENTS_WITH_INCLUDED_VERTICAL_PADDING: 132 vertical_padding = self.padTop + self.padBottom 133 if self.align in uiconst.ALIGNMENTS_WITH_INCLUDED_HORIZONTAL_PADDING: 134 horizontal_padding = self.padLeft + self.padRight 135 if self._childrenAlign in (uiconst.TOLEFT, uiconst.TORIGHT): 136 width = 0 137 for child in self.children: 138 if self._IgnoreChild(child): 139 continue 140 width += child.width + child.left + child.padLeft + child.padRight 141 142 width += horizontal_padding 143 return (width, None) 144 elif self._childrenAlign in (uiconst.TOTOP, 145 uiconst.TOBOTTOM, 146 uiconst.TOTOP_NOPUSH, 147 uiconst.TOBOTTOM_NOPUSH): 148 height = 0 149 for child in self.children: 150 if self._IgnoreChild(child): 151 continue 152 height += child.height + child.top + child.padTop + child.padBottom 153 154 height += vertical_padding 155 return (None, height) 156 elif self._childrenAlign in ALLOWED_ALIGNMENTS: 157 width = height = 0 158 for child in self.children: 159 if self._IgnoreChild(child): 160 continue 161 x = child.left + child.width 162 if x > width: 163 width = x 164 y = child.top + child.height 165 if y > height: 166 height = y 167 168 width += horizontal_padding 169 height += vertical_padding 170 return (width, height) 171 else: 172 return (vertical_padding, horizontal_padding) 173 174 def _IgnoreChild(self, child): 175 if not child.display: 176 return True 177 if self.alignMode is not None and child.align != self._childrenAlign: 178 return True 179 return False 180 181 @telemetry.ZONE_METHOD 182 def _VerifyNewChild(self, child): 183 if self.alignMode is not None: 184 self._childrenAlign = GetMappedAlignment(self.alignMode) 185 return 186 if child.align not in ALLOWED_ALIGNMENTS: 187 raise ValueError('ContainerAutoSize only supports TOLEFT, TORIGHT, TOTOP, TOBOTTOM, TOPLEFT, TOPRIGHT or CENTER aligned children') 188 if self.children and GetMappedAlignment(child.align) != self._childrenAlign: 189 raise ValueError('All children of ContainerAutoSize must have the same alignment (Got %s, expecting %s)' % (child.align, self._childrenAlign)) 190 if not self.children: 191 self._childrenAlign = GetMappedAlignment(child.align) 192 193 def GetChildrenList(self): 194 return UIChildrenListAutoSize(self) 195 196 def DisableAutoSize(self): 197 self.isAutoSizeEnabled = False 198 199 def EnableAutoSize(self): 200 if not self.isAutoSizeEnabled: 201 self.isAutoSizeEnabled = True 202 self.SetSizeAutomatically() 203 204 def UpdateAlignment(self, *args, **kwds): 205 budget = Container.UpdateAlignment(self, *args, **kwds) 206 if self._childrenAlign is not None: 207 self.SetSizeAutomatically() 208 if self._alignmentDirty: 209 budget = Container.UpdateAlignment(self, *args, **kwds) 210 return budget 211 212 def CollapseHeight(self, duration = 0.2, time_offset = 0.0, callback = None): 213 _, height = self.GetAutoSize() 214 self._CollapseSize(attribute='height', value=height, duration=duration, time_offset=time_offset, callback=callback) 215 216 def ExpandHeight(self, duration = 0.2, time_offset = 0.0, callback = None): 217 _, height = self.GetAutoSize() 218 self._ExpandSize(attribute='height', value=height, duration=duration, callback=callback, time_offset=time_offset) 219 220 def CollapseWidth(self, duration = 0.2, time_offset = 0.0, callback = None): 221 width, _ = self.GetAutoSize() 222 self._CollapseSize(attribute='width', value=width, duration=duration, time_offset=time_offset, callback=callback) 223 224 def ExpandWidth(self, duration = 0.2, time_offset = 0.0, callback = None): 225 width, _ = self.GetAutoSize() 226 self._ExpandSize(attribute='width', value=width, duration=duration, callback=callback, time_offset=time_offset) 227 228 def _CollapseSize(self, attribute, value, duration, time_offset, callback): 229 self._isCollapsed = True 230 self.DisableAutoSize() 231 animations.MorphScalar(self, attribute, startVal=value, endVal=0, duration=duration, timeOffset=time_offset, callback=callback) 232 233 def _ExpandSize(self, attribute, value, duration, time_offset, callback): 234 self._isCollapsed = False 235 self.DisableAutoSize() 236 237 def after_animation(): 238 self.EnableAutoSize() 239 if callback: 240 callback() 241 242 animations.MorphScalar(self, attribute, startVal=getattr(self, attribute, 0.0), endVal=value, duration=duration, timeOffset=time_offset, callback=after_animation) 243 244 245 class UIChildrenListAutoSize(UIChildrenList): 246 247 def append(self, obj): 248 owner = self.GetOwner() 249 if owner: 250 owner._VerifyNewChild(obj) 251 UIChildrenList.append(self, obj) 252 253 def insert(self, idx, obj): 254 owner = self.GetOwner() 255 if owner: 256 owner._VerifyNewChild(obj) 257 UIChildrenList.insert(self, idx, obj) 258 259 def remove(self, obj): 260 owner = self.GetOwner() 261 if owner: 262 UIChildrenList.remove(self, obj) 263 owner.FlagAlignmentDirty()