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

edit_window.py (16579B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\systemMenu\theme\edit_window.py
      2 import carbonui
      3 import carbonui.text.styles
      4 import eveicon
      5 import localization
      6 import signals
      7 import trinity
      8 from carbonui import Align, ButtonVariant, uiconst
      9 from carbonui.button.group import ButtonGroup, ButtonSizeMode
     10 from carbonui.control.button import Button
     11 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     12 from carbonui.control.window import Window
     13 from carbonui.primitives.container import Container
     14 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     15 from carbonui.primitives.frame import Frame
     16 from carbonui.primitives.layoutGrid import LayoutGrid
     17 from carbonui.primitives.sprite import Sprite
     18 from carbonui.uianimations import animations
     19 from carbonui.uicore import uicore
     20 from eve.client.script.ui import eveColor
     21 from eve.client.script.ui.control import eveLabel
     22 from eve.client.script.ui.control.infoIcon import InfoGlyphIcon
     23 from eve.client.script.ui.shared.colorThemes import ColorTheme
     24 from eve.client.script.ui.shared.systemMenu.theme import theme_const
     25 from carbonui.control.color_picker import ColorField
     26 from eve.client.script.ui.shared.systemMenu.theme.confirm import confirm_discard_unsaved_color_theme_changes
     27 from eve.client.script.ui.shared.systemMenu.theme.model import focus_dark_from_focus
     28 from eve.client.script.ui.shared.systemMenu.theme.share import copy_theme_slug_to_clipboard, format_theme_slug, InvalidThemeSlug, parse_theme_slug
     29 
     30 class ThemeEditState(object):
     31 
     32     def __init__(self, theme):
     33         self._initial_theme = theme
     34         self._theme_id = theme.id
     35         self._name = theme.name
     36         self._focus = theme.focus
     37         self._accent = theme.accent
     38         self._alert = theme.alert
     39         self._tint = theme.tint
     40         self.on_theme_changed = signals.Signal()
     41         self.on_name_changed = signals.Signal()
     42         self.on_focus_color_changed = signals.Signal()
     43         self.on_focus_dark_color_changed = signals.Signal()
     44         self.on_accent_color_changed = signals.Signal()
     45         self.on_tint_color_changed = signals.Signal()
     46         self.on_alert_color_changed = signals.Signal()
     47         self.on_theme_slug_changed = signals.Signal()
     48 
     49     @property
     50     def has_unsaved_changes(self):
     51         return self._initial_theme != self.theme
     52 
     53     @property
     54     def theme(self):
     55         return ColorTheme(theme_id=self._theme_id, name=self._name, focus=self._focus, focus_dark=self.focus_dark_color, accent=self._accent, alert=self._alert, tint=self._tint)
     56 
     57     @property
     58     def name(self):
     59         return self._name
     60 
     61     @name.setter
     62     def name(self, value):
     63         if self._name != value:
     64             self._name = value
     65             self.on_name_changed(self)
     66 
     67     @property
     68     def focus_color(self):
     69         return self._focus
     70 
     71     @focus_color.setter
     72     def focus_color(self, value):
     73         if self._focus != value:
     74             self._focus = value
     75             self.on_focus_color_changed(self)
     76             self.on_focus_dark_color_changed(self)
     77             self.on_theme_slug_changed(self)
     78             self.on_theme_changed(self)
     79 
     80     @property
     81     def focus_dark_color(self):
     82         return focus_dark_from_focus(self._focus)
     83 
     84     @property
     85     def accent_color(self):
     86         return self._accent
     87 
     88     @accent_color.setter
     89     def accent_color(self, value):
     90         if self._accent != value:
     91             self._accent = value
     92             self.on_accent_color_changed(self)
     93             self.on_theme_slug_changed(self)
     94             self.on_theme_changed(self)
     95 
     96     @property
     97     def tint_color(self):
     98         return self._tint
     99 
    100     @tint_color.setter
    101     def tint_color(self, value):
    102         if self._tint != value:
    103             self._tint = value
    104             self.on_tint_color_changed(self)
    105             self.on_theme_slug_changed(self)
    106             self.on_theme_changed(self)
    107 
    108     @property
    109     def alert_color(self):
    110         return self._alert
    111 
    112     @alert_color.setter
    113     def alert_color(self, value):
    114         if self._alert != value:
    115             self._alert = value
    116             self.on_alert_color_changed(self)
    117             self.on_theme_slug_changed(self)
    118             self.on_theme_changed(self)
    119 
    120     @property
    121     def theme_slug(self):
    122         return format_theme_slug(focus=self.focus_color, accent=self.accent_color, tint=self.tint_color, alert=self.alert_color)
    123 
    124     def apply_theme_slug(self, slug):
    125         focus, accent, tint, alert = parse_theme_slug(slug)
    126         self.focus_color = focus
    127         self.accent_color = accent
    128         self.tint_color = tint
    129         self.alert_color = alert
    130 
    131 
    132 class ThemeEditWindow(Window):
    133     default_windowID = 'theme_edit_window'
    134     default_isLightBackgroundConfigurable = False
    135     default_isLockable = False
    136     default_isMinimizable = False
    137     default_isOverlayable = False
    138     default_isCollapseable = False
    139     default_captionLabelPath = 'UI/SystemMenu/GeneralSettings/ColorTheme/ThemeEditWindowCaption'
    140     default_iconNum = 'res:/UI/Texture/WindowIcons/color_picker.png'
    141     _content_wrap = None
    142     _theme_slug_input = None
    143 
    144     def __init__(self, theme, on_theme_changed = None, **kwargs):
    145         self.on_theme_changed = signals.Signal()
    146         self._theme_edit_state = ThemeEditState(theme)
    147         super(ThemeEditWindow, self).__init__(**kwargs)
    148         self.MakeUnResizeable()
    149         self._layout()
    150         self._theme_edit_state.on_focus_color_changed.connect(self._on_focus_color_changed)
    151         self._theme_edit_state.on_accent_color_changed.connect(self._on_accent_color_changed)
    152         self._theme_edit_state.on_tint_color_changed.connect(self._on_tint_color_changed)
    153         self._theme_edit_state.on_alert_color_changed.connect(self._on_alert_color_changed)
    154         self._theme_edit_state.on_theme_changed.connect(self._on_theme_changed)
    155         self._theme_edit_state.on_theme_slug_changed.connect(self._on_theme_slug_changed)
    156         if on_theme_changed is not None:
    157             self.on_theme_changed.connect(on_theme_changed)
    158 
    159     @property
    160     def theme(self):
    161         return self._theme_edit_state.theme
    162 
    163     def _on_theme_changed(self, theme_edit_state):
    164         self.on_theme_changed(self)
    165 
    166     def _layout(self):
    167         self._content_wrap = ContainerAutoSize(parent=self.content, callback=self._on_content_wrap_size_changed, only_use_callback_when_size_changes=True)
    168         self._content_wrap.DisableAutoSize()
    169         grid = LayoutGrid(parent=self._content_wrap, align=Align.TOPLEFT, columns=2, cellSpacing=(16, 16))
    170         name_cont = ContainerAutoSize(align=Align.TOTOP)
    171         grid.AddCell(name_cont, colSpan=2)
    172         eveLabel.EveLabelMedium(parent=name_cont, align=Align.TOTOP, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/ThemeNameFieldLabel'))
    173         SingleLineEditText(parent=name_cont, align=Align.TOTOP, top=4, maxLength=64, setvalue=self._theme_edit_state.name, OnChange=self._on_name_input_changed)
    174         primary_grid = LayoutGrid(parent=grid, align=Align.TOPLEFT, columns=1, cellSpacing=(0, 4))
    175         eveLabel.EveLabelMedium(parent=primary_grid, align=Align.TOPLEFT, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/PrimaryColorFieldLabel'))
    176         self._focus_color_picker = ColorField(parent=primary_grid, align=Align.TOPLEFT, color=self._theme_edit_state.focus_color, on_color_changed=self._on_focus_color_picked, brightness_range=(theme_const.FOREGROUND_MIN_BRIGHTNESS, 1.0))
    177         accent_grid = LayoutGrid(parent=grid, align=Align.TOPLEFT, columns=1, cellSpacing=(0, 4))
    178         eveLabel.EveLabelMedium(parent=accent_grid, align=Align.TOPLEFT, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/AccentColorFieldLabel'))
    179         self._accent_color_picker = ColorField(parent=accent_grid, align=Align.TOPLEFT, color=self._theme_edit_state.accent_color, on_color_changed=self._on_accent_color_picked, brightness_range=(theme_const.FOREGROUND_MIN_BRIGHTNESS, 1.0))
    180         tint_grid = LayoutGrid(parent=grid, align=Align.TOPLEFT, columns=1, cellSpacing=(0, 4))
    181         eveLabel.EveLabelMedium(parent=tint_grid, align=Align.TOPLEFT, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/TintColorFieldLabel'))
    182         self._tint_color_picker = ColorField(parent=tint_grid, align=Align.TOPLEFT, color=self._theme_edit_state.tint_color, on_color_changed=self._on_tint_color_picked, brightness_range=(0.0, theme_const.BACKGROUND_MAX_BRIGHTNESS), ignore_color_blind_mode=True)
    183         alert_grid = LayoutGrid(parent=grid, align=Align.TOPLEFT, columns=1, cellSpacing=(0, 4))
    184         eveLabel.EveLabelMedium(parent=alert_grid, align=Align.TOPLEFT, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/AlertColorFieldLabel'))
    185         self._alert_color_picker = ColorField(parent=alert_grid, align=Align.TOPLEFT, color=self._theme_edit_state.alert_color, on_color_changed=self._on_alert_color_picked, brightness_range=(theme_const.FOREGROUND_MIN_BRIGHTNESS, 1.0))
    186         share_cont = ContainerAutoSize(align=Align.TOTOP, alignMode=Align.TOTOP, top=16)
    187         grid.AddCell(share_cont, colSpan=2)
    188         Button(parent=ContainerAutoSize(parent=share_cont, align=Align.TORIGHT, padLeft=8), align=Align.TOPLEFT, hint=localization.GetByLabel('UI/Common/Copy'), texturePath=eveicon.copy, func=self._on_copy_theme_slug, args=())
    189         self._theme_slug_input = SingleLineEditText(parent=share_cont, align=Align.TOTOP, setvalue=self._theme_edit_state.theme_slug, autoselect=True, OnChange=self._on_theme_slug_edited, OnFocusLost=self._on_theme_slug_focus_lost)
    190         self._theme_slug_input.SetHistoryVisibility(False)
    191         InfoGlyphIcon(parent=ContainerAutoSize(parent=self._theme_slug_input, align=Align.TORIGHT, left=8, idx=0), align=Align.CENTER, state=uiconst.UI_NORMAL, hint=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/ShareHint'))
    192         group = ButtonGroup(align=Align.TOTOP, button_size_mode=ButtonSizeMode.STRETCH, top=16)
    193         grid.AddCell(group, colSpan=2)
    194         Button(parent=group, label=localization.GetByLabel('UI/Common/Buttons/Apply'), func=self._on_apply, args=(), variant=ButtonVariant.PRIMARY)
    195         Button(parent=group, label=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/Save'), func=self._on_save, args=())
    196         Button(parent=group, label=localization.GetByLabel('UI/Common/Cancel'), func=self._on_cancel, args=())
    197         self._content_wrap.EnableAutoSize()
    198 
    199     def _on_apply(self):
    200         self.SetModalResult(uiconst.ID_APPLY)
    201 
    202     def _on_save(self):
    203         self.SetModalResult(uiconst.ID_OK)
    204 
    205     def _on_cancel(self):
    206         if self._confirm_discard_changes_if_any():
    207             self.SetModalResult(uiconst.ID_CANCEL)
    208 
    209     def _on_copy_theme_slug(self):
    210         copy_theme_slug_to_clipboard(self._theme_edit_state.theme_slug)
    211 
    212     def CloseByUser(self, *args):
    213         if self._confirm_discard_changes_if_any():
    214             super(ThemeEditWindow, self).CloseByUser()
    215 
    216     def DeactivateUnderlay(self):
    217         pass
    218 
    219     def OnWindowAboveSetInactive(self):
    220         pass
    221 
    222     def _confirm_discard_changes_if_any(self):
    223         if self._theme_edit_state.has_unsaved_changes:
    224             return confirm_discard_unsaved_color_theme_changes()
    225         else:
    226             return True
    227 
    228     def _on_name_input_changed(self, text):
    229         self._theme_edit_state.name = text
    230 
    231     def _on_focus_color_changed(self, theme_edit_state):
    232         self._focus_color_picker.color = theme_edit_state.focus_color
    233 
    234     def _on_focus_color_picked(self, color_picker):
    235         self._theme_edit_state.focus_color = color_picker.color
    236 
    237     def _on_accent_color_changed(self, theme_edit_state):
    238         self._accent_color_picker.color = theme_edit_state.accent_color
    239 
    240     def _on_accent_color_picked(self, color_picker):
    241         self._theme_edit_state.accent_color = color_picker.color
    242 
    243     def _on_tint_color_changed(self, theme_edit_state):
    244         self._tint_color_picker.color = theme_edit_state.tint_color
    245 
    246     def _on_tint_color_picked(self, color_picker):
    247         self._theme_edit_state.tint_color = color_picker.color
    248 
    249     def _on_alert_color_changed(self, theme_edit_state):
    250         self._alert_color_picker.color = theme_edit_state.alert_color
    251 
    252     def _on_alert_color_picked(self, color_picker):
    253         self._theme_edit_state.alert_color = color_picker.color
    254 
    255     def _on_theme_slug_changed(self, theme_edit_state):
    256         focused = uicore.registry.GetFocus() == self._theme_slug_input
    257         if not focused:
    258             self._theme_slug_input.SetText(theme_edit_state.theme_slug)
    259 
    260     def _on_theme_slug_edited(self, text):
    261         try:
    262             self._theme_edit_state.apply_theme_slug(text)
    263         except InvalidThemeSlug:
    264             pass
    265 
    266     def _on_theme_slug_focus_lost(self, input):
    267         try:
    268             self._theme_edit_state.apply_theme_slug(input.GetValue())
    269         except InvalidThemeSlug:
    270             pass
    271 
    272         self._theme_slug_input.SetText(self._theme_edit_state.theme_slug)
    273 
    274     def _on_content_wrap_size_changed(self):
    275         self.width, self.height = self.GetWindowSizeForContentSize(width=self._content_wrap.width, height=self._content_wrap.height)
    276 
    277     def _create_modal_layer(self, name, close_when_clicked = False):
    278         return ModalLayer(name=name, parent=uicore.layer.modal)
    279 
    280 
    281 def edit_custom_color_theme(theme, ui_color_service):
    282     if theme.is_preset:
    283         raise ValueError("Can't edit preset themes")
    284 
    285     def on_theme_changed(theme_edit_window):
    286         ui_color_service.SetThemeOverride(theme_edit_window.theme)
    287 
    288     ui_color_service.SetThemeOverride(theme)
    289     try:
    290         window = ThemeEditWindow.Open(theme=theme, on_theme_changed=on_theme_changed)
    291         result = window.ShowDialog(modal=True, fillOpacity=0.0, sceneSaturation=1.0)
    292         if result == uiconst.ID_APPLY:
    293             ui_color_service.SaveCustomTheme(window.theme)
    294             ui_color_service.SetThemeID(window.theme.id)
    295         elif result == uiconst.ID_OK:
    296             ui_color_service.SaveCustomTheme(window.theme)
    297     finally:
    298         ui_color_service.ClearThemeOverride()
    299 
    300 
    301 class ModalLayer(Container):
    302     _frame = None
    303     _header = None
    304     _hatch = None
    305     HATCH_SIZE = 264
    306     HATCH_SIZE_HALF = HATCH_SIZE / 2.0
    307 
    308     def __init__(self, name, parent):
    309         super(ModalLayer, self).__init__(name=name, parent=parent, align=Align.TOALL, state=uiconst.UI_NORMAL, idx=0)
    310         self._frame = Frame(parent=self, align=Align.TOALL, frameConst=uiconst.FRAME_BORDER2_CORNER0, color=eveColor.WARNING_ORANGE)
    311         self._header = carbonui.text.styles.TextHeadline(parent=self, align=Align.CENTERTOP, top=16, text=localization.GetByLabel('UI/SystemMenu/GeneralSettings/ColorTheme/ColorThemePreviewModeCaption'), color=eveColor.WARNING_ORANGE)
    312         self._hatch = Sprite(parent=self, align=Align.TOPLEFT, state=uiconst.UI_DISABLED, width=264, height=264, texturePath='res:/UI/Texture/classes/ColorPicker/hatch.png', textureSecondaryPath='res:/UI/Texture/classes/ColorPicker/hatch_mask.png', spriteEffect=trinity.TR2_SFX_MODULATE, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, color=eveColor.WARNING_ORANGE, opacity=0.15, glowBrightness=0.1)
    313         self._update_hatch_position()
    314         uicore.uilib.RegisterForTriuiEvents(uiconst.UI_MOUSEMOVE, self._on_global_mouse_move)
    315 
    316     def _on_global_mouse_move(self, *args):
    317         if not self.destroyed and self._hatch:
    318             self._update_hatch_position()
    319             return True
    320         else:
    321             return False
    322 
    323     def _update_hatch_position(self):
    324         self._hatch.left = uicore.uilib.x - self.HATCH_SIZE_HALF
    325         self._hatch.top = uicore.uilib.y - self.HATCH_SIZE_HALF
    326         self._hatch.translationPrimary = (uicore.uilib.x % 11 / float(self.HATCH_SIZE), uicore.uilib.y % 11 / float(self.HATCH_SIZE))
    327 
    328     def _AppendChildRO(self, child):
    329         super(ModalLayer, self)._AppendChildRO(child)
    330         if self._hatch and child is not self._hatch:
    331             self._hatch.SetOrder(-1)
    332 
    333     def _InsertChildRO(self, idx, child):
    334         super(ModalLayer, self)._InsertChildRO(idx, child)
    335         if self._hatch and child is not self._hatch:
    336             self._hatch.SetOrder(-1)
    337 
    338     def OnMouseDown(self, *args):
    339         for element in (self._frame, self._header):
    340             if element:
    341                 animations.SpColorMorphTo(element, startColor=eveColor.WARNING_ORANGE, endColor=eveColor.WHITE, duration=0.4, loops=3, curveType=uiconst.ANIM_WAVE)
    342 
    343         if self._hatch:
    344             animations.FadeTo(self._hatch, startVal=0.3, endVal=0.15, duration=0.3)