sideNavigation.py (17356B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\control\sideNavigation.py 2 import carbonui 3 import carbonui.text.styles 4 import eveicon 5 import eveui 6 import signals 7 import uthread2 8 from carbonui import Align, TextColor, uiconst, PickState 9 from carbonui.control.button import Button 10 from carbonui.control.buttonIcon import ButtonIcon 11 from carbonui.control.scrollContainer import ScrollContainer 12 from carbonui.decorative.blurredSceneUnderlay import BlurredSceneUnderlay 13 from carbonui.decorative.panelUnderlay import PanelUnderlay 14 from carbonui.decorative.selectionIndicatorLine import SelectionIndicatorLine 15 from carbonui.primitives.container import Container 16 from carbonui.primitives.containerAutoSize import ContainerAutoSize 17 from carbonui.primitives.fill import Fill 18 from carbonui.primitives.split_view import SplitView, PanelMode 19 from carbonui.primitives.sprite import Sprite 20 from eve.client.script.ui import eveThemeColor 21 22 class SideNavigationSplitView(SplitView): 23 24 def __init__(self, is_always_expanded_setting, compact_panel_width = 58, panel_mode = PanelMode.COMPACT_OVERLAY, static_panel_inner_width = False, force_compact = False, **kwargs): 25 super(SideNavigationSplitView, self).__init__(compact_panel_width=compact_panel_width, panel_mode=panel_mode, static_panel_inner_width=static_panel_inner_width, **kwargs) 26 self._minimized = False 27 self._force_compact = force_compact 28 self.original_compact_panel_width = compact_panel_width 29 self.is_always_expanded_setting = is_always_expanded_setting 30 self.panel.pickState = PickState.ON 31 self.panel.OnMouseEnter = self._panel_mouse_enter 32 self.panel.OnMouseExit = self._panel_mouse_exit 33 self.is_always_expanded_setting.on_change.connect(self._apply_always_expanded_setting) 34 self._apply_always_expanded_setting() 35 self._expand_button = Button(parent=self.content, align=Align.TOPLEFT, padTop=8, texturePath=eveicon.list_view, func=self._on_expand_button) 36 self._expand_button.Hide() 37 38 def _apply_always_expanded_setting(self, *args, **kwargs): 39 if self.is_always_expanded_setting.is_enabled(): 40 self._enable_always_expanded() 41 else: 42 self._disable_always_expanded() 43 44 def _disable_always_expanded(self): 45 self.panel_mode = PanelMode.COMPACT_OVERLAY 46 self.content.padLeft = self.compact_panel_width 47 self.collapse(animate=False) 48 49 def _enable_always_expanded(self): 50 self.panel_mode = PanelMode.INLINE 51 self.content.padLeft = 0 52 self.expand(animate=False) 53 54 def _panel_mouse_enter(self, *args, **kwargs): 55 self.expand_panel(True) 56 57 def _panel_mouse_exit(self, *args, **kwargs): 58 self.expand_panel(False) 59 60 def expand_panel(self, expanded): 61 if self.is_always_expanded_setting.is_enabled(): 62 return 63 if self._force_compact: 64 return 65 self.expanded = expanded 66 67 def _on_expand_button(self, *args): 68 self.expand(True) 69 70 def set_content_padLeft(self, padLeft): 71 self.content.padLeft = padLeft 72 73 def set_minimized(self, minimized): 74 if minimized and not self._minimized: 75 self.compact_panel_width = 0 76 self.set_content_padLeft(0) 77 self.panel_mode = PanelMode.OVERLAY 78 self._expand_button.Show() 79 elif not minimized and self._minimized: 80 self.compact_panel_width = self.original_compact_panel_width 81 self.set_content_padLeft(self.original_compact_panel_width) 82 self.panel_mode = PanelMode.COMPACT_OVERLAY 83 self._expand_button.Hide() 84 self._minimized = minimized 85 86 def set_force_compact(self, force_compact): 87 if force_compact: 88 self.expanded = False 89 self._force_compact = force_compact 90 91 92 class SideNavigation(Container): 93 default_state = uiconst.UI_NORMAL 94 95 def __init__(self, is_expanded_func, expand_func = None, is_always_expanded_setting = None, force_compact = False, **kwargs): 96 super(SideNavigation, self).__init__(**kwargs) 97 self._entries = {} 98 self._force_compact = force_compact 99 self.is_expanded_func = is_expanded_func 100 self.expand_func = expand_func 101 self.is_always_expanded_setting = is_always_expanded_setting 102 self._on_expand_signal = signals.Signal('on_expand_signal') 103 self._layout() 104 self.on_expanded_changed(self.is_expanded_func(), animate=False) 105 106 def on_expanded_changed(self, expanded, animate = True): 107 if expanded: 108 if self._body.scrollbarsDisabled: 109 eveui.Sound.expand.play() 110 self._body.EnableScrollbars() 111 else: 112 if not self._body.scrollbarsDisabled: 113 eveui.Sound.collapse.play() 114 self._body.DisableScrollbars() 115 self._on_expand_signal(expanded, animate) 116 117 def set_force_compact(self, force_compact): 118 self._force_compact = force_compact 119 for entry in self._body.mainCont.children: 120 if isinstance(entry, SideNavigationEntryInterface): 121 entry.set_force_compact(force_compact) 122 123 def set_entry_selected(self, entry_id): 124 for _entry_id, entry in self._entries.items(): 125 entry.selected = _entry_id == entry_id 126 127 if self.is_expanded_func() and self.expand_func is not None: 128 self.expand_func(False) 129 130 def _layout(self): 131 main = Container(name='main', parent=self, padding=(8, 8, 0, 8)) 132 self._layout_header(main) 133 self._layout_footer(main) 134 self._body = ScrollContainer(name='body', parent=main) 135 self._body.DisableScrollbars() 136 self._construct_header() 137 self._construct_footer() 138 self._construct_body() 139 self._construct_background() 140 141 def _layout_header(self, main): 142 self._header = ContainerAutoSize(name='header', parent=main, align=Align.TOTOP, alignMode=Align.TOTOP) 143 144 def _layout_footer(self, main): 145 self._footer = ContainerAutoSize(name='footer', parent=main, align=Align.TOBOTTOM, alignMode=Align.TOTOP) 146 147 def Flush(self): 148 self._body.Flush() 149 150 def _construct_background(self): 151 PanelUnderlay(bgParent=self) 152 BlurredSceneUnderlay(bgParent=self) 153 154 def _construct_header(self): 155 pass 156 157 def _construct_body(self): 158 pass 159 160 def _construct_footer(self): 161 if self.is_always_expanded_setting: 162 entry = SideNavigationSettingsEntry(parent=self._footer, padTop=8, is_always_expanded_setting=self.is_always_expanded_setting, on_hover=self._on_entry_hover) 163 self._connect_to_expand(entry) 164 165 def _connect_to_expand(self, entry): 166 self._on_expand_signal.connect(entry.on_expanded_changed) 167 168 def add_entry(self, entry_id, text, on_click, icon, hide_empty = False, force_hidden = False, entry_cls = None, data = None, **kwargs): 169 entry_cls = entry_cls or SideNavigationEntry 170 entry = entry_cls(name='{}_entry'.format(entry_id), parent=self._body, icon=icon, text=text, hide_empty=hide_empty, force_hidden=force_hidden, force_compact=self._force_compact, on_click=on_click, entry_id=entry_id, on_hover=self._on_entry_hover, data=data, **kwargs) 171 entry.on_expanded_changed(self.is_expanded_func(), animate=False) 172 self._entries[entry_id] = entry 173 self._connect_to_expand(entry) 174 175 def add_header(self, label, **kwargs): 176 padTop = 12 if not len(self._body.mainCont.children) else 16 177 entry = SideNavigationHeaderEntry(parent=self._body, text=label, **kwargs) 178 entry.padTop = padTop 179 entry.on_expanded_changed(self.is_expanded_func(), animate=False) 180 self._connect_to_expand(entry) 181 182 def _on_entry_hover(self, entry): 183 if not self.is_expanded_func() and self.expand_func is not None: 184 self.expand_func(True) 185 186 187 class SideNavigationEntryInterface(object): 188 189 def on_expanded_changed(self, expanded, animate = True): 190 raise NotImplementedError 191 192 def set_expanded(self, animate = True): 193 raise NotImplementedError 194 195 def set_collapsed(self, animate = True): 196 raise NotImplementedError 197 198 def set_force_compact(self, force_compact): 199 raise NotImplementedError 200 201 202 class SideNavigationSettingsEntry(Container, SideNavigationEntryInterface): 203 default_align = Align.TOTOP 204 default_height = 32 205 default_padLeft = 8 206 default_padRight = 8 207 208 def __init__(self, is_always_expanded_setting, on_hover = None, **kwargs): 209 super(SideNavigationSettingsEntry, self).__init__(**kwargs) 210 self._on_hover = on_hover 211 self.is_always_expanded_setting = is_always_expanded_setting 212 self._layout() 213 self._update_expand_icon() 214 215 def _layout(self): 216 self._expand_button = ButtonIcon(parent=self, align=Align.TORIGHT, func=self._expand_clicked, opacity=0) 217 218 def on_expanded_changed(self, expanded, animate = True): 219 if expanded: 220 self.set_expanded(animate) 221 else: 222 self.set_collapsed(animate) 223 224 def set_expanded(self, animate = True): 225 if animate: 226 eveui.animation.fade_in(self._expand_button, end_value=TextColor.NORMAL.opacity, duration=0.2, time_offset=0.3) 227 else: 228 self._expand_button.opacity = TextColor.NORMAL.opacity 229 230 def set_collapsed(self, animate = True): 231 if animate: 232 eveui.animation.fade_out(self._expand_button, duration=0.2) 233 else: 234 self._expand_button.opacity = 0.0 235 236 def _expand_clicked(self): 237 self.is_always_expanded_setting.toggle() 238 self._update_expand_icon() 239 240 def _update_expand_icon(self): 241 self._expand_button.SetTexturePath(eveicon.chevron_left if self.is_always_expanded_setting.is_enabled() else eveicon.chevron_right) 242 243 def set_force_compact(self, force_compact): 244 pass 245 246 def OnMouseEnter(self, *args): 247 super(SideNavigationSettingsEntry, self).OnMouseEnter(*args) 248 if self._on_hover: 249 self._on_hover(self) 250 251 252 class SideNavigationHeaderEntry(ContainerAutoSize, SideNavigationEntryInterface): 253 default_align = Align.TOTOP 254 default_alignMode = Align.TOPLEFT 255 default_padding = (8, 16, 8, 4) 256 257 def __init__(self, text, **kwargs): 258 super(SideNavigationHeaderEntry, self).__init__(**kwargs) 259 self._text = text 260 self._text_label = carbonui.text.styles.TextDetail(parent=self, align=Align.TOPLEFT, text=text, opacity=0) 261 self._text_label.autoFadeSides = 12 262 263 def on_expanded_changed(self, expanded, animate = True): 264 if expanded: 265 self.set_expanded(animate) 266 else: 267 self.set_collapsed(animate) 268 269 def set_collapsed(self, animate = True): 270 if animate: 271 eveui.animation.fade_out(self._text_label, duration=0.2) 272 else: 273 self._text_label.opacity = 0.0 274 275 def set_expanded(self, animate = True): 276 if animate: 277 eveui.animation.fade_in(self._text_label, end_value=TextColor.SECONDARY.opacity, duration=0.2) 278 else: 279 self._text_label.opacity = TextColor.SECONDARY.opacity 280 281 def set_force_compact(self, force_compact): 282 pass 283 284 285 class SideNavigationEntry(Container, SideNavigationEntryInterface): 286 default_state = uiconst.UI_NORMAL 287 default_align = Align.TOTOP 288 default_height = 32 289 default_bgColor = eveThemeColor.THEME_FOCUSDARK 290 291 def __init__(self, icon, text, on_click, hide_empty = False, value = '', force_hidden = False, force_compact = False, entry_id = None, icon_size = 16, icon_color = TextColor.NORMAL, on_hover = None, data = None, **kwargs): 292 super(SideNavigationEntry, self).__init__(**kwargs) 293 self._on_click = on_click 294 self._on_hover = on_hover 295 self._selected = False 296 self._value = value 297 self.entry_id = entry_id 298 self._hide_empty = hide_empty 299 self._force_hidden = force_hidden 300 self._force_compact = force_compact 301 self.bgFill.opacity = 0 302 self._icon_size = icon_size 303 self._icon_color = icon_color 304 self._text = text 305 self._data = data 306 self._selected_fill = Fill(bgParent=self, color=eveThemeColor.THEME_FOCUSDARK, opacity=0) 307 self.selection_indicator = SelectionIndicatorLine(parent=self, align=Align.TOLEFT_NOPUSH, selected=False) 308 self.content = Container(parent=self, pickState=PickState.OFF, padding=(8, 4, 16, 4)) 309 self._icon_container = Container(parent=self.content, align=Align.TOLEFT, width=24) 310 self._icon = Sprite(parent=self._icon_container, align=Align.CENTER, height=self._icon_size, width=self._icon_size, texturePath=icon, color=TextColor.NORMAL) 311 if not icon: 312 self._icon_container.Hide() 313 self.construct_right_aligned_content() 314 self._text_container = Container(parent=self.content, padLeft=8, padRight=8, clipChildren=True, opacity=0) 315 self._text_label = carbonui.text.styles.TextBody(parent=self._text_container, align=Align.CENTERLEFT, text=text, maxLines=1) 316 self._text_label.autoFadeSides = 16 317 self.set_value(value) 318 319 def construct_right_aligned_content(self): 320 self.construct_value_container() 321 322 def construct_value_container(self): 323 self._value_container = ContainerAutoSize(parent=self.content, align=Align.TORIGHT, opacity=0) 324 self._value_label = carbonui.text.styles.TextBody(parent=self._value_container, align=Align.CENTERLEFT, color=TextColor.SECONDARY) 325 326 def on_expanded_changed(self, expanded, animate = True): 327 if expanded: 328 self.set_expanded(animate) 329 else: 330 self.set_collapsed(animate) 331 332 def set_expanded(self, animate = True): 333 if animate: 334 eveui.animation.fade_in(self._value_container, duration=0.2) 335 eveui.animation.fade_in(self._text_container, duration=0.2) 336 else: 337 self._value_container.opacity = 1.0 338 self._text_container.opacity = 1.0 339 340 def set_collapsed(self, animate = True): 341 if animate: 342 eveui.animation.fade_out(self._value_container, duration=0.1) 343 eveui.animation.fade_out(self._text_container, duration=0.2) 344 else: 345 self._value_container.opacity = 0.0 346 self._text_container.opacity = 0.0 347 348 def set_value(self, value): 349 self._value = value 350 self._update_display_state() 351 self._value_label.text = unicode(value) if value else '' 352 self._update_colors() 353 354 def force_hidden(self, hidden): 355 self._force_hidden = hidden 356 self._update_display_state() 357 358 def set_force_compact(self, force_compact): 359 self._force_compact = force_compact 360 361 def OnColorThemeChanged(self): 362 super(SideNavigationEntry, self).OnColorThemeChanged() 363 self.bgFill.rgb = eveThemeColor.THEME_FOCUSDARK[:3] 364 self._selected_fill.rgb = eveThemeColor.THEME_FOCUSDARK[:3] 365 366 def OnMouseEnter(self, *args): 367 super(SideNavigationEntry, self).OnMouseEnter(*args) 368 eveui.Sound.button_hover.play() 369 eveui.animation.fade_in(self.bgFill, end_value=0.15, duration=0.05) 370 if self._on_hover: 371 self._on_hover(self) 372 373 def OnMouseExit(self, *args): 374 super(SideNavigationEntry, self).OnMouseExit(*args) 375 eveui.animation.fade_out(self.bgFill, duration=0.2) 376 377 def OnClick(self, *args): 378 eveui.Sound.button_click.play() 379 self._on_click(self) 380 381 @property 382 def selected(self): 383 return self._selected 384 385 @selected.setter 386 def selected(self, value): 387 if self._selected == value: 388 return 389 self._selected = value 390 self._update_display_state() 391 self._update_colors() 392 if self.selected: 393 eveui.fade_in(self._selected_fill, end_value=0.2, duration=0.2) 394 self.selection_indicator.Select() 395 else: 396 eveui.fade_out(self._selected_fill, duration=0.2) 397 self.selection_indicator.Deselect() 398 399 def _update_colors(self): 400 if self._value == 0: 401 color = TextColor.DISABLED 402 self._text_label.rgba = color 403 self._icon.rgba = color 404 self._value_label.rgba = color 405 elif self._selected: 406 color = TextColor.HIGHLIGHT 407 self._icon.rgba = color 408 self._text_label.rgba = color 409 self._value_label.rgba = color 410 else: 411 self._text_label.rgba = TextColor.NORMAL 412 self._icon.rgba = self._icon_color 413 self._value_label.rgba = TextColor.SECONDARY 414 415 def _update_display_state(self): 416 display = True 417 if not self.selected: 418 if self._force_hidden: 419 display = False 420 elif self._hide_empty: 421 display = bool(self._value) 422 self.display = display 423 424 def GetHint(self): 425 if self._force_compact: 426 hint = self.hint 427 if hint: 428 return u'<b>{}</b>\n{}'.format(self._text, self.hint) 429 else: 430 return self._text 431 return self.hint 432 433 def GetTooltipDelay(self): 434 if self._force_compact: 435 return 0 436 437 def GetTooltipPointer(self): 438 return uiconst.POINT_RIGHT_2