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

resizer.py (11828B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\window\resizer.py
      2 import math
      3 from carbonui import uiconst
      4 from carbonui.primitives.container import Container
      5 from carbonui.primitives.sprite import Sprite
      6 from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal
      7 from carbonui.primitives.stretchspritevertical import StretchSpriteVertical
      8 from carbonui.uianimations import animations
      9 from eve.client.script.ui import eveThemeColor
     10 
     11 class Side(object):
     12     LEFT = 1
     13     TOP = 2
     14     RIGHT = 3
     15     BOTTOM = 4
     16     _ALL = (LEFT,
     17      TOP,
     18      RIGHT,
     19      BOTTOM)
     20 
     21     @classmethod
     22     def iter(cls):
     23         return iter(cls._ALL)
     24 
     25 
     26 class Resizer(Container):
     27     DEFAULT_INNER_PADDING = (0, 0, 0, 0)
     28 
     29     def __init__(self, inner_padding = None, locked_sides = None, on_end_scale = None, on_start_scale = None, **kwargs):
     30         self._inner_padding = sanitize_padding(inner_padding, default=self.DEFAULT_INNER_PADDING)
     31         self._handles = []
     32         self._locked_sides = set(locked_sides or ())
     33         self._on_end_scale = on_end_scale
     34         self._on_start_scale = on_start_scale
     35         super(Resizer, self).__init__(**kwargs)
     36         self._create_handles()
     37 
     38     @property
     39     def inner_padding(self):
     40         return self._inner_padding
     41 
     42     @inner_padding.setter
     43     def inner_padding(self, value):
     44         value = sanitize_padding(value, default=self.DEFAULT_INNER_PADDING)
     45         if self._inner_padding != value:
     46             self._inner_padding = value
     47             self._update_inner_padding()
     48 
     49     @property
     50     def locked_sides(self):
     51         return frozenset(self._locked_sides)
     52 
     53     @locked_sides.setter
     54     def locked_sides(self, value):
     55         new_locked_sides = set(value)
     56         if self._locked_sides != new_locked_sides:
     57             self._locked_sides = new_locked_sides
     58             self._update_handle_locked_state()
     59 
     60     def _create_handles(self):
     61         for orientation in Orientation.iter():
     62             handle = ResizeHandle(parent=self, orientation=orientation, on_start_scale=lambda _handle: self._on_start_scale(Orientation.get_sides(_handle.orientation)), on_end_scale=lambda _handle: self._on_end_scale(Orientation.get_sides(_handle.orientation)), enabled=not self._is_orientation_locked(orientation), idx=0 if Orientation.is_corner(orientation) else -1)
     63             self._handles.append(handle)
     64 
     65     def _update_inner_padding(self):
     66         for handle in self._handles:
     67             handle.inner_padding = self._inner_padding
     68 
     69     def _update_handle_locked_state(self):
     70         for handle in self._handles:
     71             handle.enabled = not self._is_orientation_locked(handle.orientation)
     72 
     73     def _is_orientation_locked(self, orientation):
     74         return any((side in self._locked_sides for side in Orientation.get_sides(orientation)))
     75 
     76 
     77 def sanitize_padding(value, default):
     78     if not value:
     79         value = default
     80     if isinstance(value, int):
     81         value = (value,) * 4
     82     return value
     83 
     84 
     85 class Orientation(object):
     86     LEFT = 1
     87     TOP = 2
     88     RIGHT = 3
     89     BOTTOM = 4
     90     TOP_LEFT = 5
     91     TOP_RIGHT = 6
     92     BOTTOM_RIGHT = 7
     93     BOTTOM_LEFT = 8
     94     _ALL = (LEFT,
     95      TOP,
     96      RIGHT,
     97      BOTTOM,
     98      TOP_LEFT,
     99      TOP_RIGHT,
    100      BOTTOM_RIGHT,
    101      BOTTOM_LEFT)
    102     _HORIZONTAL_ORIENTATIONS = {LEFT,
    103      RIGHT,
    104      TOP_LEFT,
    105      TOP_RIGHT,
    106      BOTTOM_LEFT,
    107      BOTTOM_RIGHT}
    108     _VERTICAL_ORIENTATIONS = {TOP,
    109      BOTTOM,
    110      TOP_LEFT,
    111      TOP_RIGHT,
    112      BOTTOM_LEFT,
    113      BOTTOM_RIGHT}
    114     _CORNER_ORIENTATIONS = {TOP_LEFT,
    115      TOP_RIGHT,
    116      BOTTOM_LEFT,
    117      BOTTOM_RIGHT}
    118     _SIDES_BY_ORIENTATION = {LEFT: (Side.LEFT,),
    119      TOP: (Side.TOP,),
    120      RIGHT: (Side.RIGHT,),
    121      BOTTOM: (Side.BOTTOM,),
    122      TOP_LEFT: (Side.TOP, Side.LEFT),
    123      TOP_RIGHT: (Side.TOP, Side.RIGHT),
    124      BOTTOM_RIGHT: (Side.BOTTOM, Side.RIGHT),
    125      BOTTOM_LEFT: (Side.BOTTOM, Side.LEFT)}
    126 
    127     @classmethod
    128     def iter(cls):
    129         return iter(cls._ALL)
    130 
    131     @classmethod
    132     def get_sides(cls, orientation):
    133         return cls._SIDES_BY_ORIENTATION[orientation]
    134 
    135     @classmethod
    136     def is_corner(cls, orientation):
    137         return orientation in cls._CORNER_ORIENTATIONS
    138 
    139     @classmethod
    140     def is_horizontal(cls, orientation):
    141         return orientation in cls._HORIZONTAL_ORIENTATIONS
    142 
    143     @classmethod
    144     def is_vertical(cls, orientation):
    145         return orientation in cls._VERTICAL_ORIENTATIONS
    146 
    147 
    148 class ResizeHandle(Container):
    149     ALIGN_BY_ORIENTATION = {Orientation.LEFT: uiconst.TOLEFT_NOPUSH,
    150      Orientation.TOP: uiconst.TOTOP_NOPUSH,
    151      Orientation.RIGHT: uiconst.TORIGHT_NOPUSH,
    152      Orientation.BOTTOM: uiconst.TOBOTTOM_NOPUSH,
    153      Orientation.TOP_LEFT: uiconst.TOPLEFT,
    154      Orientation.TOP_RIGHT: uiconst.TOPRIGHT,
    155      Orientation.BOTTOM_RIGHT: uiconst.BOTTOMRIGHT,
    156      Orientation.BOTTOM_LEFT: uiconst.BOTTOMLEFT}
    157     CURSOR_BY_ORIENTATION = {Orientation.LEFT: uiconst.UICURSOR_LEFT_RIGHT_DRAG,
    158      Orientation.TOP: uiconst.UICURSOR_TOP_BOTTOM_DRAG,
    159      Orientation.RIGHT: uiconst.UICURSOR_LEFT_RIGHT_DRAG,
    160      Orientation.BOTTOM: uiconst.UICURSOR_TOP_BOTTOM_DRAG,
    161      Orientation.TOP_LEFT: uiconst.UICURSOR_TOP_LEFT_BOTTOM_RIGHT_DRAG,
    162      Orientation.TOP_RIGHT: uiconst.UICURSOR_TOP_RIGHT_BOTTOM_LEFT_DRAG,
    163      Orientation.BOTTOM_RIGHT: uiconst.UICURSOR_TOP_LEFT_BOTTOM_RIGHT_DRAG,
    164      Orientation.BOTTOM_LEFT: uiconst.UICURSOR_TOP_RIGHT_BOTTOM_LEFT_DRAG}
    165     SIZE_BY_ORIENTATION = {Orientation.LEFT: (8, 0),
    166      Orientation.TOP: (0, 8),
    167      Orientation.RIGHT: (8, 0),
    168      Orientation.BOTTOM: (0, 8),
    169      Orientation.TOP_LEFT: (8, 8),
    170      Orientation.TOP_RIGHT: (8, 8),
    171      Orientation.BOTTOM_RIGHT: (8, 8),
    172      Orientation.BOTTOM_LEFT: (8, 8)}
    173     HANDLE_ALIGN_BY_ORIENTATION = {Orientation.LEFT: uiconst.CENTERLEFT,
    174      Orientation.TOP: uiconst.CENTERTOP,
    175      Orientation.RIGHT: uiconst.CENTERRIGHT,
    176      Orientation.BOTTOM: uiconst.CENTERBOTTOM,
    177      Orientation.TOP_LEFT: uiconst.TOPLEFT,
    178      Orientation.TOP_RIGHT: uiconst.TOPRIGHT,
    179      Orientation.BOTTOM_RIGHT: uiconst.BOTTOMRIGHT,
    180      Orientation.BOTTOM_LEFT: uiconst.BOTTOMLEFT}
    181     TEXTURE_ROTATION_BY_ORIENTATION = {Orientation.LEFT: 0.0,
    182      Orientation.TOP: 0.0,
    183      Orientation.RIGHT: math.pi,
    184      Orientation.BOTTOM: math.pi,
    185      Orientation.TOP_LEFT: 0.0,
    186      Orientation.TOP_RIGHT: -math.pi / 2.0,
    187      Orientation.BOTTOM_RIGHT: -math.pi,
    188      Orientation.BOTTOM_LEFT: math.pi / 2.0}
    189     OPACITY_IDLE = 0.0
    190     OPACITY_HOVER = 0.5
    191     OPACITY_SCALING = 1.0
    192     DEFAULT_INNER_PADDING = (0, 0, 0, 0)
    193     _handle = None
    194     _handle_wrap = None
    195     _hovered = False
    196     _scaling = False
    197 
    198     def __init__(self, orientation, on_start_scale = None, on_end_scale = None, enabled = True, inner_padding = None, **kwargs):
    199         self._orientation = orientation
    200         self._on_start_scale = on_start_scale
    201         self._on_end_scale = on_end_scale
    202         self._enabled = enabled
    203         self._inner_padding = sanitize_padding(inner_padding, default=self.DEFAULT_INNER_PADDING)
    204         width, height = self._get_size(orientation=self._orientation, inner_padding=self._inner_padding)
    205         super(ResizeHandle, self).__init__(align=self.ALIGN_BY_ORIENTATION[orientation], cursor=self.CURSOR_BY_ORIENTATION[orientation], state=self._get_state(), width=width, height=height, opacity=self._get_opacity(), **kwargs)
    206         align = self.HANDLE_ALIGN_BY_ORIENTATION[orientation]
    207         rotation = self.TEXTURE_ROTATION_BY_ORIENTATION[orientation]
    208         self._handle_wrap = Container(parent=self, align=uiconst.TOALL, clipChildren=True, padding=self._get_handle_wrap_padding())
    209         if orientation in {Orientation.LEFT, Orientation.RIGHT}:
    210             self._handle = StretchSpriteVertical(parent=self._handle_wrap, align=align, width=2, height=64, topEdgeSize=2, bottomEdgeSize=2, texturePath='res:/UI/Texture/classes/Window/resize_handle_edge_vertical.png', rotation=rotation, color=self._get_color(), outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.5)
    211         elif orientation in {Orientation.TOP, Orientation.BOTTOM}:
    212             self._handle = StretchSpriteHorizontal(parent=self._handle_wrap, align=align, width=64, height=2, leftEdgeSize=2, rightEdgeSize=2, texturePath='res:/UI/Texture/classes/Window/resize_handle_edge_horizontal.png', rotation=rotation, color=self._get_color(), outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.5)
    213         else:
    214             self._handle = Sprite(parent=self._handle_wrap, align=align, width=8, height=8, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/classes/Window/resize_handle_corner.png', rotation=rotation, color=self._get_color(), outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.5)
    215 
    216     @property
    217     def enabled(self):
    218         return self._enabled
    219 
    220     @enabled.setter
    221     def enabled(self, value):
    222         if self._enabled != value:
    223             self._enabled = value
    224             self._update_state()
    225 
    226     @property
    227     def inner_padding(self):
    228         return self._inner_padding
    229 
    230     @inner_padding.setter
    231     def inner_padding(self, value):
    232         value = sanitize_padding(value, default=self.DEFAULT_INNER_PADDING)
    233         if self._inner_padding != value:
    234             self._inner_padding = value
    235             self._update_size()
    236             self._update_handle_wrap_padding()
    237 
    238     @property
    239     def orientation(self):
    240         return self._orientation
    241 
    242     def _get_state(self):
    243         if self._enabled:
    244             return uiconst.UI_NORMAL
    245         return uiconst.UI_DISABLED
    246 
    247     def _update_state(self):
    248         self.state = self._get_state()
    249         if not self._enabled:
    250             self._end_scaling()
    251 
    252     @classmethod
    253     def _get_size(cls, orientation, inner_padding):
    254         width, height = cls.SIZE_BY_ORIENTATION[orientation]
    255         pad_left, pad_top, pad_right, pad_bottom = inner_padding
    256         width += pad_left + pad_right
    257         height += pad_top + pad_bottom
    258         return (width, height)
    259 
    260     def _update_size(self):
    261         self.width, self.height = self._get_size(orientation=self._orientation, inner_padding=self._inner_padding)
    262 
    263     def _get_handle_wrap_padding(self):
    264         return self._inner_padding
    265 
    266     def _update_handle_wrap_padding(self):
    267         if self._handle_wrap:
    268             self._handle_wrap.padding = self._get_handle_wrap_padding()
    269 
    270     def _get_opacity(self):
    271         if not self._enabled:
    272             return self.OPACITY_IDLE
    273         elif self._scaling:
    274             return self.OPACITY_SCALING
    275         elif self._hovered:
    276             return self.OPACITY_HOVER
    277         else:
    278             return self.OPACITY_IDLE
    279 
    280     def _update_opacity(self):
    281         duration = 0.15 if self._hovered else 0.3
    282         animations.FadeTo(self, startVal=self.opacity, endVal=self._get_opacity(), duration=duration)
    283 
    284     def _start_scaling(self):
    285         if not self._scaling and self._enabled:
    286             self._scaling = True
    287             self._update_opacity()
    288             if self._on_start_scale:
    289                 self._on_start_scale(self)
    290 
    291     def _end_scaling(self):
    292         if self._scaling:
    293             self._scaling = False
    294             self._update_opacity()
    295             if self._on_end_scale:
    296                 self._on_end_scale(self)
    297 
    298     @staticmethod
    299     def _get_color():
    300         return eveThemeColor.THEME_ACCENT
    301 
    302     def OnColorThemeChanged(self):
    303         if self._handle is not None:
    304             self._handle.color = self._get_color()
    305 
    306     def OnMouseEnter(self, *args):
    307         self._hovered = True
    308         self._update_opacity()
    309 
    310     def OnMouseExit(self, *args):
    311         self._hovered = False
    312         self._update_opacity()
    313 
    314     def OnMouseDown(self, button, *args):
    315         if button == uiconst.MOUSELEFT and self._enabled:
    316             self._start_scaling()
    317 
    318     def OnMouseUp(self, button, *args):
    319         if button == uiconst.MOUSELEFT:
    320             self._end_scaling()