layout.py (6122B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\window\layout.py 2 import mathext 3 from carbonui.uicore import uicore 4 from carbonui.window.snap import SNAP_DISTANCE 5 from functools import reduce 6 7 class AnchorSide(object): 8 LEFT = 1 9 TOP = 2 10 RIGHT = 3 11 BOTTOM = 4 12 HORIZONTAL = 5 13 VERTICAL = 6 14 15 16 class Anchor(object): 17 18 def __init__(self, side, offset): 19 self.side = side 20 self.offset = offset 21 22 23 class Rect(object): 24 25 def __init__(self, x, y, width, height): 26 self.x = x 27 self.y = y 28 self.width = width 29 self.height = height 30 31 @property 32 def left(self): 33 return self.x 34 35 @property 36 def top(self): 37 return self.y 38 39 @property 40 def right(self): 41 return self.x + self.width 42 43 @property 44 def bottom(self): 45 return self.y + self.height 46 47 @classmethod 48 def from_element(cls, element): 49 left, top, width, height = element.GetAbsolute() 50 return cls(left, top, width, height) 51 52 @classmethod 53 def from_elements(cls, elements): 54 return reduce(lambda a, b: a.merge(b), [ cls.from_element(e) for e in elements ]) 55 56 def merge(self, other): 57 left = min(self.x, other.x) 58 top = min(self.y, other.y) 59 right = max(self.right, other.right) 60 bottom = max(self.bottom, other.bottom) 61 return Rect(x=left, y=top, width=right - left, height=bottom - top) 62 63 64 class AnchoredWindowGroup(object): 65 66 def __init__(self, anchors, windows, boundaries): 67 self.anchors = anchors 68 self.windows = windows 69 self.boundaries = boundaries 70 71 72 def capture_desktop_window_layout(): 73 all_windows = uicore.registry.GetValidWindows(getModals=True, floatingOnly=True, getHidden=True) 74 desktop_rect = Rect.from_element(uicore.desktop) 75 window_groups = [] 76 processed_windows = set() 77 for window in all_windows: 78 if window in processed_windows: 79 continue 80 connected_windows = window.FindConnectingWindows(validWnds=all_windows, fullSideOnly=False) 81 group_rect = Rect.from_elements(connected_windows) 82 group = AnchoredWindowGroup(anchors=_get_window_desktop_anchors(window_group_rect=group_rect, desktop_rect=desktop_rect), windows=connected_windows, boundaries=group_rect) 83 window_groups.append(group) 84 processed_windows.update(connected_windows) 85 86 return window_groups 87 88 89 CENTER_THRESHOLD = 32 90 91 def _get_window_desktop_anchors(window_group_rect, desktop_rect): 92 anchors = [] 93 left_offset, right_offset = _get_side_offset() 94 margin_left = window_group_rect.left - desktop_rect.left 95 margin_right = desktop_rect.right - window_group_rect.right 96 if margin_left in (0, left_offset, left_offset + SNAP_DISTANCE): 97 anchors.append(Anchor(side=AnchorSide.LEFT, offset=margin_left)) 98 elif margin_right in (0, right_offset, right_offset + SNAP_DISTANCE): 99 anchors.append(Anchor(side=AnchorSide.RIGHT, offset=margin_right)) 100 elif abs(margin_left - margin_right) < CENTER_THRESHOLD: 101 anchors.append(Anchor(AnchorSide.HORIZONTAL, offset=0.5)) 102 elif margin_left < margin_right: 103 anchors.append(Anchor(side=AnchorSide.LEFT, offset=margin_left)) 104 else: 105 anchors.append(Anchor(side=AnchorSide.RIGHT, offset=margin_right)) 106 margin_top = window_group_rect.top - desktop_rect.top 107 margin_bottom = desktop_rect.bottom - window_group_rect.bottom 108 if margin_top in (0, SNAP_DISTANCE): 109 anchors.append(Anchor(side=AnchorSide.TOP, offset=margin_top)) 110 elif margin_bottom in (0, SNAP_DISTANCE): 111 anchors.append(Anchor(side=AnchorSide.BOTTOM, offset=margin_bottom)) 112 elif abs(margin_top - margin_bottom) < CENTER_THRESHOLD: 113 anchors.append(Anchor(AnchorSide.VERTICAL, offset=0.5)) 114 elif margin_top < margin_bottom: 115 anchors.append(Anchor(side=AnchorSide.TOP, offset=margin_top)) 116 else: 117 anchors.append(Anchor(side=AnchorSide.BOTTOM, offset=margin_bottom)) 118 return anchors 119 120 121 def apply_desktop_window_layout(anchored_window_groups): 122 for anchored_window_group in anchored_window_groups: 123 group_rect = anchored_window_group.boundaries 124 for anchor in anchored_window_group.anchors: 125 for window in anchored_window_group.windows: 126 if anchor.side == AnchorSide.LEFT: 127 window.left = min(max(0, uicore.desktop.width - window.width), anchor.offset + (window.left - group_rect.left)) 128 elif anchor.side == AnchorSide.TOP: 129 window.top = min(max(0, uicore.desktop.height - window.height), anchor.offset + (window.top - group_rect.top)) 130 elif anchor.side == AnchorSide.RIGHT: 131 window.left = min(max(0, uicore.desktop.width - window.width), uicore.desktop.width - (anchor.offset + group_rect.width) + (window.left - group_rect.left)) 132 elif anchor.side == AnchorSide.BOTTOM: 133 window.top = max(0, uicore.desktop.height - (anchor.offset + group_rect.height) + (window.top - group_rect.top)) 134 elif anchor.side == AnchorSide.HORIZONTAL: 135 group_half_width = int(round(group_rect.width / 2.0)) 136 group_center = uicore.desktop.width * anchor.offset 137 offset_in_group = window.left - group_rect.left 138 window.left = mathext.clamp(value=group_center - group_half_width + offset_in_group, low=0, high=uicore.desktop.width - window.width) 139 elif anchor.side == AnchorSide.VERTICAL: 140 group_half_height = int(round(group_rect.height / 2.0)) 141 group_center = uicore.desktop.height * anchor.offset 142 offset_in_group = window.top - group_rect.top 143 window.top = mathext.clamp(value=group_center - group_half_height + offset_in_group, low=0, high=uicore.desktop.height - window.height) 144 145 146 def _get_side_offset(): 147 side_panel_layer = uicore.layer.sidePanels 148 if side_panel_layer: 149 return side_panel_layer.GetSideOffset() 150 return (0, 0)