loadingContainer.py (8114B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\loadingContainer.py 2 import uthread2 3 import trinity 4 import eveicon 5 import logging 6 from carbonui import ButtonVariant, Density, TextAlign, uiconst 7 from carbonui.control.button import Button 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.childrenlist import PyChildrenList 10 from carbonui.primitives.containerAutoSize import ContainerAutoSize 11 from carbonui.primitives.sprite import StreamingVideoSprite 12 from carbonui.uianimations import animations 13 from eve.client.script.ui.control.eveLabel import EveCaptionSmall, EveLabelLarge 14 from eve.client.script.ui import eveColor 15 from itertoolsext.Enum import Enum 16 from sovereignty.mercenaryden.common.errors import ServiceUnavailable 17 logger = logging.getLogger(__name__) 18 19 @Enum 20 21 class LoadingSpriteSize(object): 22 SMALL = 16 23 MEDIUM = 32 24 LARGE = 64 25 26 27 @Enum 28 29 class LoadingContainerState(object): 30 LOADING = 'loading' 31 LOADED = 'loaded' 32 FAILED = 'failure' 33 34 35 class LoadingContainer(Container): 36 _loadingSpriteFadeDuration = 0.1 37 _contentsFadeDuration = 0.2 38 _failureStateFadeDuration = 0.2 39 loadingSpriteFadeDelay = 0.0 40 failureContPadding = 16 41 42 def __init__(self, loadCallback = None, failedCallback = None, loadingSpriteSize = LoadingSpriteSize.MEDIUM, failureStateMessage = '', failureStateMessageColor = eveColor.WARNING_ORANGE, failureStateSubtext = '', retryBtnLabel = '', errorLoggingEnabled = True, **kw): 43 self._state = None 44 self._loadingThread = None 45 self._contentsCont = None 46 self._failureStateCont = None 47 self._failureStateMessageColor = failureStateMessageColor 48 self._loadCallback = loadCallback 49 self._failedCallback = failedCallback 50 self._loadingSpriteSize = loadingSpriteSize 51 self._errorLoggingEnabled = errorLoggingEnabled 52 super(LoadingContainer, self).__init__(**kw) 53 self._ConstructLayout(failureStateMessage, failureStateSubtext, retryBtnLabel) 54 self.children = LoadingGroupChildrenList(self) 55 56 def Close(self): 57 if self._loadingThread: 58 self._loadingThread.kill() 59 self._loadingThread = None 60 super(LoadingContainer, self).Close() 61 62 @property 63 def contents(self): 64 return self._contentsCont 65 66 @property 67 def state(self): 68 return self._state 69 70 @state.setter 71 def state(self, value): 72 if value != self._state: 73 self._state = value 74 if self._state == LoadingContainerState.LOADING: 75 self._HideFailureCont() 76 self._HideContents() 77 self._ShowLoadingSprite() 78 elif self._state == LoadingContainerState.LOADED: 79 self._HideFailureCont() 80 self._HideLoadingSprite() 81 self._ShowContents() 82 elif self._state == LoadingContainerState.FAILED: 83 self._HideLoadingSprite() 84 self._HideContents() 85 self._ShowFailureCont() 86 87 def _ConstructLayout(self, failureStateMessage, failureStateSubtext, retryBtnLabel): 88 self._failureStateCont = Container(parent=self, name='failureStateCont', opacity=0.0) 89 self._contentsCont = Container(parent=self, name='contentsCont', opacity=0.0) 90 self._ConstructFailureState(failureStateMessage, failureStateSubtext, retryBtnLabel) 91 self._ConstructLoadingSprite() 92 93 def _ConstructFailureState(self, failureStateMessage, failureStateSubtext, retryBtnLabel): 94 self._failureCentralCont = ContainerAutoSize(name='failureCentralCont', parent=self._failureStateCont, align=uiconst.CENTER, padding=(self.failureContPadding, 95 self.failureContPadding, 96 self.failureContPadding, 97 self.failureContPadding)) 98 if len(failureStateMessage) > 0: 99 errorMessage = EveCaptionSmall(name='errorMessage', parent=self._failureCentralCont, align=uiconst.TOTOP, textAlign=TextAlign.CENTER, text=failureStateMessage, color=self._failureStateMessageColor) 100 errorMessage.uppercase = True 101 if len(failureStateSubtext) > 0: 102 EveLabelLarge(name='errorSubtext', parent=self._failureCentralCont, align=uiconst.TOTOP, textAlign=TextAlign.CENTER, text=failureStateSubtext, top=8 if len(failureStateMessage) > 0 else 0) 103 if len(retryBtnLabel) > 0: 104 btnCont = ContainerAutoSize(name='btnCont', parent=self._failureCentralCont, align=uiconst.TOTOP, height=32, top=16 if len(failureStateMessage) + len(failureStateSubtext) > 0 else 0) 105 Button(name='retryBtn', parent=btnCont, align=uiconst.CENTER, density=Density.NORMAL, label=retryBtnLabel, texturePath=eveicon.refresh, variant=ButtonVariant.GHOST, func=lambda *args: self.LoadContent(self._loadCallback, self._failedCallback)) 106 107 def _ConstructLoadingSprite(self): 108 self._loadingSprite = StreamingVideoSprite(parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=self._loadingSpriteSize, height=self._loadingSpriteSize, videoPath='res:/video/shared/loading_sprite_%s.webm' % self._loadingSpriteSize, videoLoop=True, blendMode=trinity.TR2_SBM_ADD, spriteEffect=trinity.TR2_SFX_COPY, opacity=0.0) 109 110 def LoadContent(self, loadCallback = None, failedCallback = None): 111 self._loadCallback = loadCallback 112 self._failedCallback = failedCallback 113 if self._loadingThread is None: 114 self._loadingThread = uthread2.StartTasklet(self._LoadContentThread) 115 116 def _LoadContentThread(self): 117 try: 118 self.state = LoadingContainerState.LOADING 119 self._loadCallback() 120 self.state = LoadingContainerState.LOADED 121 except ServiceUnavailable as e: 122 self.state = LoadingContainerState.FAILED 123 if self._errorLoggingEnabled: 124 logger.warning('LoadingContainer: timeout in _LoadContentThread: %s', e) 125 except Exception as e: 126 self.state = LoadingContainerState.FAILED 127 if self._errorLoggingEnabled: 128 logger.exception('LoadingContainer: exception in _LoadContentThread: %s', e) 129 if self._failedCallback: 130 self._failedCallback(e) 131 else: 132 raise 133 finally: 134 self._loadingThread = None 135 136 def _HideContents(self): 137 animations.FadeTo(self._contentsCont, self._contentsCont.opacity, 0.0, duration=self._contentsFadeDuration) 138 139 def _ShowContents(self): 140 animations.FadeTo(self._contentsCont, self._contentsCont.opacity, 1.0, duration=self._contentsFadeDuration) 141 142 def _HideLoadingSprite(self): 143 animations.FadeTo(self._loadingSprite, self._loadingSprite.opacity, 0.0, duration=self._loadingSpriteFadeDuration) 144 145 def _ShowLoadingSprite(self): 146 animations.FadeTo(self._loadingSprite, self._loadingSprite.opacity, 1.0, duration=self._loadingSpriteFadeDuration, timeOffset=self.loadingSpriteFadeDelay) 147 148 def _ShowFailureCont(self): 149 self._failureStateCont.Enable() 150 animations.FadeTo(self._failureStateCont, self._failureStateCont.opacity, 1.0, duration=self._failureStateFadeDuration) 151 152 def _HideFailureCont(self): 153 animations.FadeTo(self._failureStateCont, self._failureStateCont.opacity, 0.0, duration=self._failureStateFadeDuration) 154 self._failureStateCont.Disable() 155 156 def Flush(self): 157 self._contentsCont.Flush() 158 159 def _OnSizeChange_NoBlock(self, width, height): 160 super(LoadingContainer, self)._OnSizeChange_NoBlock(width, height) 161 if hasattr(self, '_failureCentralCont'): 162 self._failureCentralCont.width = width 163 164 165 class LoadingGroupChildrenList(PyChildrenList): 166 167 def __init__(self, parentCont): 168 super(LoadingGroupChildrenList, self).__init__(owner=parentCont, children=parentCont.children) 169 170 def append(self, obj): 171 return self.insert(-1, obj) 172 173 def insert(self, idx, obj): 174 parentCont = self.GetOwner() 175 if parentCont: 176 parentCont.contents.children.insert(idx, obj) 177 return self