infoPanelWorldEvents.py (12199B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\infoPanels\infoPanelWorldEvents.py 2 import blue 3 import eveicon 4 import eveui 5 from carbonui import Align, TextColor 6 from eve.client.script.ui.shared.infoPanels.InfoPanelBase import InfoPanelBase 7 from eve.client.script.ui.shared.infoPanels.const.infoPanelConst import PANEL_WORLD_EVENTS 8 from objectives.client.ui.objective_chain import ObjectiveChainEntry 9 import eveformat 10 import localization 11 from clientsettings.setting import SessionSettingNumeric 12 from eve.client.script.ui import eveColor, eveThemeColor 13 from metadata.common.content_tags import get_content_tag_as_object, ContentTags 14 from carbonui.control.buttonIcon import ButtonIcon 15 from jobboard.client import get_job_board_service, get_world_event_job, open_world_event 16 SCROLL_CONTAINER_HEIGHT_MAX = 450 17 HEADER_BG_COLOR = (0, 0, 0, 0.35) 18 19 class InfoPanelWorldEvents(InfoPanelBase): 20 default_name = 'InfoPanelWorldEvents' 21 panelTypeID = PANEL_WORLD_EVENTS 22 hasSettings = False 23 label = 'UI/Metadata/ContentTags/WorldEvents' 24 _scroll_fraction = SessionSettingNumeric(0, 0.0, 1.0) 25 26 @staticmethod 27 def IsAvailable(): 28 return bool(sm.GetService('tale').get_active_world_event_tales_in_system()) 29 30 @classmethod 31 def GetTexturePath(cls): 32 return get_content_tag_as_object(ContentTags.feature_world_events).icon 33 34 def __init__(self, **kwargs): 35 self._entries = {} 36 self._scroll_initialized = False 37 self._constructing = True 38 super(InfoPanelWorldEvents, self).__init__(**kwargs) 39 self._layout() 40 self._refresh_entries() 41 self._update_content_container_scroll_position() 42 43 def ConstructNormal(self): 44 if self._constructing or self.destroyed: 45 return 46 self._refresh_entries() 47 48 @property 49 def service(self): 50 return sm.GetService('tale') 51 52 @eveui.skip_if_destroyed 53 def _refresh_entries(self): 54 tales = self.service.get_active_world_event_tales_in_system() 55 tale_ids = set([ tale.tale_id for tale in tales ]) 56 previous_entry_ids = self._entries.keys() 57 obsolete_entry_ids = list(set(previous_entry_ids) - tale_ids) 58 for entry_id in obsolete_entry_ids: 59 if entry_id not in self._entries: 60 continue 61 entry = self._entries[entry_id] 62 entry.Close() 63 self._entries[entry_id] = None 64 self._entries.pop(entry_id) 65 66 for index, tale in enumerate(tales): 67 if tale.tale_id not in previous_entry_ids: 68 self._construct_tale_entry(tale, index) 69 else: 70 self._entries[tale.tale_id].SetOrder(index) 71 72 self._update_content_container_height() 73 74 @eveui.skip_if_destroyed 75 def _construct_tale_entry(self, tale, index): 76 entry = TaleInfoPanelEntry(parent=self._content_container, tale=tale, padBottom=4, padTop=4, idx=index, callback=self._update_content_container_height) 77 self._entries[tale.tale_id] = entry 78 79 def _layout(self): 80 self._constructing = True 81 self._title = eveui.EveCaptionSmall(name='title', parent=self.headerCont, align=eveui.Align.center_left, text=localization.GetByLabel(self.label)) 82 self._content_container = eveui.ScrollContainer(name='content_scroll_container', parent=self.mainCont, align=Align.TOTOP, height=0) 83 self._content_container.OnScrolledVertical = self._on_scroll 84 self._constructing = False 85 86 def ConstructHeaderButton(self): 87 container = eveui.Container(parent=self.headerBtnCont, align=eveui.Align.center_right, width=28, height=28) 88 return ButtonIcon(parent=container, align=eveui.Align.center, iconSize=18, width=18, height=18, texturePath=self.GetTexturePath(), func=self._open_job_board) 89 90 def _open_job_board(self, *args, **kwargs): 91 get_job_board_service().open_browse_page(content_tag_id=ContentTags.feature_world_events) 92 93 def _update_content_container_height(self): 94 if not self._content_container or self._content_container.destroyed: 95 return 96 totalHeight = self._content_container.mainCont.height 97 self._content_container.height = min(totalHeight, SCROLL_CONTAINER_HEIGHT_MAX) 98 self._content_container.clipCont.clipChildren = totalHeight > SCROLL_CONTAINER_HEIGHT_MAX 99 100 def _update_content_container_scroll_position(self): 101 blue.synchro.Yield() 102 if not self._content_container or self._content_container.destroyed: 103 return 104 self._scroll_initialized = True 105 self._content_container.ScrollToVertical(self._scroll_fraction.get()) 106 107 def _on_scroll(self, pos_fraction): 108 if self._scroll_initialized: 109 self._scroll_fraction.set(self._content_container.GetPositionVertical()) 110 111 112 class TaleInfoPanelEntry(eveui.ContainerAutoSize): 113 default_align = Align.TOTOP 114 default_alignMode = Align.TOTOP 115 default_clipChildren = True 116 117 def __init__(self, tale, *args, **kwargs): 118 kwargs.setdefault('name', str(tale.tale_id)) 119 super(TaleInfoPanelEntry, self).__init__(*args, **kwargs) 120 self._tale = tale 121 self._is_hovered = False 122 self._objective_chain_entry = None 123 self._layout() 124 if self._expanded: 125 self._expand() 126 self._update_hover_state() 127 self._register() 128 self._on_progress() 129 130 def Close(self): 131 self._unregister() 132 if self._objective_chain_entry: 133 self._objective_chain_entry.Close() 134 self._objective_chain_entry = None 135 super(TaleInfoPanelEntry, self).Close() 136 self.callback = None 137 self._tale = None 138 139 def _register(self): 140 self._tale.context.subscribe_to_value('current_progress', self._on_progress) 141 142 def _unregister(self): 143 self._tale.context.unsubscribe_from_value('current_progress', self._on_progress) 144 145 @property 146 def _expanded(self): 147 return self._tale.context.get_value('is_expanded') 148 149 @_expanded.setter 150 def _expanded(self, value): 151 self._tale.context.update_value('is_expanded', value) 152 153 @property 154 def _current_progress(self): 155 return self._tale.context.get_value('current_progress', 0) 156 157 @property 158 def _target_progress(self): 159 return self._tale.context.get_value('target_progress', 0) 160 161 @property 162 def _progress_percentage(self): 163 target = self._target_progress 164 if not target: 165 return 0 166 return float(self._current_progress) / target 167 168 @property 169 def _has_progress(self): 170 return bool(self._target_progress) 171 172 @property 173 def _progress_text(self): 174 target_progress = self._target_progress 175 if not target_progress: 176 return '' 177 elif target_progress >= 100: 178 return u'{value}%'.format(value=int(self._progress_percentage * 100)) 179 else: 180 return u'{}/{}'.format(eveformat.number(self._current_progress, 0), eveformat.number(self._target_progress, 0)) 181 182 def _on_progress(self, *args, **kwargs): 183 if not self._tale: 184 return 185 text = self._progress_text 186 if not text: 187 return 188 self._progress_label.text = text 189 eveui.animate(self._progress_fill, 'width', end_value=self._progress_percentage, duration=1) 190 self._update_progress_color() 191 192 def _layout(self): 193 self._construct_header() 194 self._content_container = eveui.ContainerAutoSize(name='content_container', parent=self, align=Align.TOTOP, alignMode=Align.TOTOP) 195 196 def _construct_header(self): 197 self._header_container = header_container = eveui.ContainerAutoSize(name='header_container', parent=self, state=eveui.State.normal, align=Align.TOTOP, alignMode=Align.TOTOP_NOPUSH, bgColor=HEADER_BG_COLOR) 198 header_container.OnClick = self.OnClick 199 header_container.GetMenu = self.GetMenu 200 wrapper = eveui.ContainerAutoSize(parent=header_container, align=Align.TOTOP_NOPUSH, alignMode=Align.TOTOP, padding=8) 201 job = get_world_event_job(self._tale.tale_id) 202 if job: 203 icon_container = eveui.ContainerAutoSize(parent=wrapper, align=eveui.Align.to_left, padRight=8, width=16) 204 view_details_button = ButtonIcon(name='view_details_button', parent=icon_container, align=eveui.Align.center, texturePath=job.feature_tag.icon, iconSize=16, width=16, height=16, color=TextColor.NORMAL, func=self._open_tale_details, hint=localization.GetByLabel('UI/Opportunities/ViewOpportunity')) 205 view_details_button.isDragObject = True 206 view_details_button.GetDragData = job.get_drag_data 207 progress_text_container = eveui.ContainerAutoSize(parent=wrapper, state=eveui.State.disabled, align=eveui.Align.to_right, clipChildren=True) 208 self._progress_label = eveui.EveLabelLarge(parent=progress_text_container, align=eveui.Align.center_right, text=self._progress_text, maxLines=1, padLeft=4) 209 title_container = eveui.ContainerAutoSize(parent=wrapper, state=eveui.State.disabled, align=Align.TOTOP, clipChildren=True) 210 self._title = eveui.EveLabelLarge(parent=title_container, align=Align.TOTOP, text=self._tale.title, maxLines=1, showEllipsis=True, color=TextColor.HIGHLIGHT) 211 progress_fill_container = eveui.Container(name='progress_fill_container', parent=header_container, align=eveui.Align.to_all, clipChildren=True, opacity=0.15) 212 self._progress_fill = eveui.StretchSpriteHorizontal(parent=progress_fill_container, align=eveui.Align.to_left_prop, texturePath='res:/UI/Texture/classes/InfoPanels/progress_bar_solid.png', color=self._get_progress_color(), leftEdgeSize=2, rightEdgeSize=10, padLeft=-2, padRight=-10, width=self._progress_percentage) 213 214 @eveui.skip_if_destroyed 215 def _construct_body(self): 216 if self._objective_chain_entry: 217 self._objective_chain_entry.Close() 218 self._objective_chain_entry = None 219 objective_chain = self._tale.objective_chain 220 if objective_chain: 221 self._objective_chain_entry = ObjectiveChainEntry(parent=self._content_container, objective_chain=objective_chain) 222 223 def _reconstruct_body(self): 224 self._content_container.Flush() 225 self._construct_body() 226 227 def _expand(self): 228 self._expanded = True 229 self._reconstruct_body() 230 self._update_hover_state() 231 232 def _collapse(self): 233 self._expanded = False 234 self._content_container.Flush() 235 self._update_hover_state() 236 237 def OnClick(self): 238 if self._expanded: 239 eveui.Sound.collapse.play() 240 else: 241 eveui.Sound.expand.play() 242 if self._expanded: 243 self._collapse() 244 else: 245 self._expand() 246 247 def GetMenu(self): 248 return self._tale.get_menu() 249 250 def OnMouseEnter(self, *args): 251 super(TaleInfoPanelEntry, self).OnMouseEnter(*args) 252 self._is_hovered = True 253 self._update_hover_state() 254 255 def OnMouseExit(self, *args): 256 super(TaleInfoPanelEntry, self).OnMouseEnter(*args) 257 self._is_hovered = False 258 self._update_hover_state() 259 260 def _update_hover_state(self): 261 has_progress = self._has_progress 262 self._progress_fill.display = has_progress and not self._expanded 263 self._progress_label.display = has_progress and not self._expanded and not self._is_hovered 264 if self._expanded or self._is_hovered: 265 eveui.fade(self._header_container.bgFill, end_value=0.5, duration=0.2) 266 else: 267 eveui.fade(self._header_container.bgFill, end_value=HEADER_BG_COLOR[3], duration=0.2) 268 269 def _get_progress_color(self): 270 if self._progress_percentage < 1: 271 return eveThemeColor.THEME_FOCUS 272 else: 273 return eveColor.SUCCESS_GREEN 274 275 def _update_progress_color(self): 276 self._progress_fill.color = self._get_progress_color() 277 278 def OnColorThemeChanged(self): 279 super(TaleInfoPanelEntry, self).OnColorThemeChanged() 280 self._update_progress_color() 281 282 def _open_tale_details(self, *args, **kwargs): 283 open_world_event(self._tale.tale_id)