NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

infoPanelJobBoard.py (9676B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\infoPanels\infoPanelJobBoard.py
      2 import logging
      3 import blue
      4 import eveui
      5 import eveicon
      6 from eve.client.script.ui.shared.infoPanels.InfoPanelBase import InfoPanelBase
      7 from eve.client.script.ui.shared.infoPanels.const.infoPanelConst import PANEL_JOB_BOARD, MODE_NORMAL
      8 from carbonui.control.buttonIcon import ButtonIcon
      9 import uthread2
     10 from jobboard.client import get_job_board_service, job_board_signals
     11 import localization
     12 from clientsettings.setting import SessionSettingNumeric
     13 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst
     14 logger = logging.getLogger('job_board')
     15 SCROLL_CONTAINER_HEIGHT_MAX = 450
     16 
     17 class InfoPanelJobBoard(InfoPanelBase):
     18     default_name = 'InfoPanelJobBoard'
     19     panelTypeID = PANEL_JOB_BOARD
     20     hasSettings = False
     21     uniqueUiName = pConst.UNIQUE_NAME_AGENT_MISSION_INFO_PANEL
     22     label = 'UI/Opportunities/WindowTitle'
     23     default_iconTexturePath = eveicon.opportunities_board
     24     expandedJobSettingsName = 'expanded_job'
     25     featureID = 'opportunities'
     26     __notifyevents__ = InfoPanelBase.__notifyevents__ + ['OnExpandedMissionChanged']
     27     _scroll_fraction = SessionSettingNumeric(0, 0.0, 1.0)
     28 
     29     @staticmethod
     30     def IsAvailable():
     31         service = get_job_board_service()
     32         if service is None:
     33             return False
     34         return service.is_available and bool(service.get_tracked_jobs())
     35 
     36     def __init__(self, **kwargs):
     37         self._expanded_job_id = None
     38         self._job_entries = {}
     39         self._scroll_initialized = False
     40         self._constructing = True
     41         super(InfoPanelJobBoard, self).__init__(**kwargs)
     42         self._layout()
     43         self._refresh_entries()
     44         self._update_content_container_scroll_position()
     45         job_board_signals.on_job_state_changed.connect(self._on_job_state_changed)
     46         job_board_signals.on_job_added.connect(self._on_job_added)
     47 
     48     def Close(self):
     49         for entry in self._job_entries.values():
     50             entry.Close()
     51 
     52         self._job_entries.clear()
     53         job_board_signals.on_job_state_changed.disconnect(self._on_job_state_changed)
     54         job_board_signals.on_job_added.disconnect(self._on_job_added)
     55         super(InfoPanelJobBoard, self).Close()
     56 
     57     def ConstructNormal(self):
     58         if self._constructing or self.destroyed:
     59             return
     60         self._debounced_refresh()
     61 
     62     @property
     63     def service(self):
     64         return get_job_board_service()
     65 
     66     def _on_tracked_jobs_changed(self):
     67         if self.destroyed:
     68             return
     69         self._debounced_refresh()
     70 
     71     @uthread2.debounce(0.1)
     72     def _debounced_refresh(self):
     73         if not self.destroyed:
     74             self._refresh_entries()
     75 
     76     def _on_job_state_changed(self, job):
     77         if self.destroyed:
     78             return
     79         if job.job_id in self._job_entries:
     80             self._job_entries[job.job_id].update_state()
     81 
     82     def _on_job_added(self, job):
     83         if self.destroyed:
     84             return
     85         if job.is_tracked and job.job_id not in self._job_entries:
     86             self._debounced_refresh()
     87 
     88     @eveui.skip_if_destroyed
     89     def _refresh_entries(self):
     90         jobs = self.service.get_tracked_jobs()
     91         job_ids = [ job.job_id for job in jobs ]
     92         previous_job_ids = [ job_id for job_id in self._job_entries.keys() ]
     93         obsolete_job_ids = list(set(previous_job_ids) - set(job_ids))
     94         for job_id in obsolete_job_ids:
     95             job_entry = self._job_entries[job_id]
     96             job_entry.Close()
     97             self._job_entries[job_id] = None
     98             self._job_entries.pop(job_id)
     99 
    100         for index, job in enumerate(jobs):
    101             if job.job_id not in previous_job_ids:
    102                 self._construct_job_entry(job, index)
    103             else:
    104                 self._job_entries[job.job_id].SetOrder(index)
    105 
    106         if not self._job_entries:
    107             self._save_expanded(-1)
    108         else:
    109             self._check_update_expanded()
    110         self._update_content_container_height()
    111 
    112     @eveui.skip_if_destroyed
    113     def _construct_job_entry(self, job, index):
    114         try:
    115             entry = job.INFO_PANEL_ENTRY_CLASS(parent=self._content_container, job=job, padBottom=4, padTop=4, on_click=self._on_entry_clicked, idx=index, callback=self._update_content_container_height)
    116             self._job_entries[job.job_id] = entry
    117         except:
    118             logger.exception('Failed to construct info panel entry %s', job.job_id)
    119 
    120     def _layout(self):
    121         self._constructing = True
    122         self._title = eveui.EveCaptionSmall(name='title', parent=self.headerCont, align=eveui.Align.center_left, text=localization.GetByLabel(self.label))
    123         self._content_container = eveui.ScrollContainer(name='missions_scroll_container', parent=self.mainCont, align=eveui.Align.to_top, height=0)
    124         self._content_container.OnScrolledVertical = self._on_scroll
    125         self._constructing = False
    126 
    127     def ConstructHeaderButton(self):
    128         container = eveui.Container(parent=self.headerBtnCont, align=eveui.Align.center_right, width=28, height=28)
    129         return ButtonIcon(parent=container, align=eveui.Align.center, iconSize=18, width=18, height=18, texturePath=self.default_iconTexturePath, func=self._open_job_board)
    130 
    131     def _open_job_board(self, *args, **kwargs):
    132         self.service.open_active_page()
    133 
    134     def _on_entry_clicked(self, job_id):
    135         if job_id == self._expanded_job_id:
    136             self._expand_job(None, save=True)
    137         else:
    138             self._expand_job(job_id, save=True)
    139 
    140     def _expand_job(self, job_id, save = False):
    141         self._update_expanded_job_id_settings(job_id)
    142         self._update_expanded_entries()
    143         self._scroll_to_expanded()
    144         if save:
    145             self._save_expanded(job_id)
    146 
    147     def _update_expanded_entries(self):
    148         for job_id, entry in self._job_entries.items():
    149             if job_id == self._expanded_job_id:
    150                 try:
    151                     entry.expand()
    152                 except:
    153                     logger.exception('Failed to expand info panel entry %s', entry.name)
    154 
    155             else:
    156                 entry.collapse()
    157 
    158     def _scroll_to_expanded(self):
    159         blue.synchro.Yield()
    160         job_id = self._expanded_job_id
    161         if not job_id or job_id not in self._job_entries:
    162             return
    163         self._content_container.ScrollToRevealChildVertical(self._job_entries[job_id])
    164 
    165     def OnStartModeChanged(self, oldMode):
    166         if not oldMode:
    167             return
    168         self._check_update_expanded()
    169 
    170     def OnExpandedMissionChanged(self, featureID = None, missionID = None):
    171         if not featureID or featureID == self.featureID:
    172             return
    173         self._expanded_job_id = -1
    174         self._update_expanded_entries()
    175         if self._expanded_job_id != -1:
    176             self._scroll_to_expanded()
    177 
    178     def _get_expanded_job_id_from_settings(self):
    179         return settings.char.ui.Get(self.expandedJobSettingsName, self._get_default_expanded_job_id())
    180 
    181     def _get_default_expanded_job_id(self):
    182         jobs = self.service.get_tracked_jobs()
    183         for job in jobs:
    184             if job.job_id in self._job_entries:
    185                 return job.job_id
    186 
    187     def _update_expanded_job_id_settings(self, job_id):
    188         settings.char.ui.Set(self.expandedJobSettingsName, job_id)
    189         self._expanded_job_id = job_id
    190 
    191     def _check_update_expanded(self):
    192         if self.mode == MODE_NORMAL:
    193             expanded_mission = sm.GetService('infoPanel').GetExpandedMission()
    194             expanded_id = None
    195             save = True
    196             if not expanded_mission or expanded_mission['missionID'] == -1:
    197                 expanded_id = self._get_expanded_job_id_from_settings()
    198                 if expanded_id in (None, -1) or expanded_id not in self._job_entries:
    199                     expanded_id = self._get_default_expanded_job_id()
    200             elif expanded_mission['featureID'] == self.featureID:
    201                 expanded_id = expanded_mission['missionID']
    202                 save = settings.char.ui.Get(self.expandedJobSettingsName) != expanded_id
    203             if expanded_id is not None:
    204                 self._expand_job(expanded_id, save=save)
    205         else:
    206             self._save_expanded(-1)
    207 
    208     def _save_expanded(self, expanded_id):
    209         if expanded_id == -1:
    210             expanded_mission = sm.GetService('infoPanel').GetExpandedMission()
    211             if expanded_mission.get('featureID') != self.featureID:
    212                 return
    213         sm.GetService('infoPanel').SetExpandedMission(self.featureID, expanded_id)
    214 
    215     def _update_content_container_height(self):
    216         if not self._content_container or self._content_container.destroyed:
    217             return
    218         totalHeight = self._content_container.mainCont.height
    219         self._content_container.height = min(totalHeight, SCROLL_CONTAINER_HEIGHT_MAX)
    220         self._content_container.clipCont.clipChildren = totalHeight > SCROLL_CONTAINER_HEIGHT_MAX
    221 
    222     def _update_content_container_scroll_position(self):
    223         blue.synchro.Yield()
    224         if not self._content_container or self._content_container.destroyed:
    225             return
    226         self._scroll_initialized = True
    227         self._content_container.ScrollToVertical(self._scroll_fraction.get())
    228 
    229     def _on_scroll(self, pos_fraction):
    230         if self._scroll_initialized:
    231             self._scroll_fraction.set(self._content_container.GetPositionVertical())
    232 
    233     def get_visible_jobs(self, job_ids):
    234         visible_job_ids = [ entry.name for entry in self._job_entries.values() if entry.name in job_ids and self._content_container.IsChildVisible(entry) ]
    235         return visible_job_ids