windows-mcp 0.5.7__py3-none-any.whl → 0.5.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
windows_mcp/tree/utils.py CHANGED
@@ -1,22 +1,22 @@
1
- import random
2
- from uiautomation import Control
3
-
4
- def random_point_within_bounding_box(node: Control, scale_factor: float = 1.0) -> tuple[int, int]:
5
- """
6
- Generate a random point within a scaled-down bounding box.
7
-
8
- Args:
9
- node (Control): The node with a bounding rectangle
10
- scale_factor (float, optional): The factor to scale down the bounding box. Defaults to 1.0.
11
-
12
- Returns:
13
- tuple: A random point (x, y) within the scaled-down bounding box
14
- """
15
- box = node.BoundingRectangle
16
- scaled_width = int(box.width() * scale_factor)
17
- scaled_height = int(box.height() * scale_factor)
18
- scaled_left = box.left + (box.width() - scaled_width) // 2
19
- scaled_top = box.top + (box.height() - scaled_height) // 2
20
- x = random.randint(scaled_left, scaled_left + scaled_width)
21
- y = random.randint(scaled_top, scaled_top + scaled_height)
1
+ import random
2
+ from windows_mcp.uia import Control
3
+
4
+ def random_point_within_bounding_box(node: Control, scale_factor: float = 1.0) -> tuple[int, int]:
5
+ """
6
+ Generate a random point within a scaled-down bounding box.
7
+
8
+ Args:
9
+ node (Control): The node with a bounding rectangle
10
+ scale_factor (float, optional): The factor to scale down the bounding box. Defaults to 1.0.
11
+
12
+ Returns:
13
+ tuple: A random point (x, y) within the scaled-down bounding box
14
+ """
15
+ box = node.BoundingRectangle
16
+ scaled_width = int(box.width() * scale_factor)
17
+ scaled_height = int(box.height() * scale_factor)
18
+ scaled_left = box.left + (box.width() - scaled_width) // 2
19
+ scaled_top = box.top + (box.height() - scaled_height) // 2
20
+ x = random.randint(scaled_left, scaled_left + scaled_width)
21
+ y = random.randint(scaled_top, scaled_top + scaled_height)
22
22
  return (x, y)
windows_mcp/tree/views.py CHANGED
@@ -1,116 +1,116 @@
1
- from dataclasses import dataclass,field
2
- from tabulate import tabulate
3
- from typing import Optional
4
-
5
- @dataclass
6
- class DOMInfo:
7
- horizontal_scrollable: bool
8
- horizontal_scroll_percent: float
9
- vertical_scrollable: bool
10
- vertical_scroll_percent: float
11
-
12
- @dataclass
13
- class TreeState:
14
- interactive_nodes:list['TreeElementNode']=field(default_factory=list)
15
- scrollable_nodes:list['ScrollElementNode']=field(default_factory=list)
16
- dom_informative_nodes:list['TextElementNode']=field(default_factory=list)
17
- dom_info:Optional['DOMInfo']=None
18
-
19
- def interactive_elements_to_string(self) -> str:
20
- if not self.interactive_nodes:
21
- return "No interactive elements"
22
- headers = ["Label", "App Name", "ControlType", "Name", "Value", "Shortcut", "Coordinates" ,"IsFocused"]
23
- rows = [node.to_row(idx) for idx, node in enumerate(self.interactive_nodes)]
24
- return tabulate(rows, headers=headers, tablefmt="simple")
25
-
26
- def scrollable_elements_to_string(self) -> str:
27
- if not self.scrollable_nodes:
28
- return "No scrollable elements"
29
- headers = [
30
- "Label", "App Name", "ControlType", "Name", "Coordinates",
31
- "Horizontal Scrollable", "Horizontal Scroll Percent(%)", "Vertical Scrollable", "Vertical Scroll Percent(%)", "IsFocused"
32
- ]
33
- base_index = len(self.interactive_nodes)
34
- rows = [node.to_row(idx, base_index) for idx, node in enumerate(self.scrollable_nodes)]
35
- return tabulate(rows, headers=headers, tablefmt="simple")
36
-
37
- @dataclass
38
- class BoundingBox:
39
- left:int
40
- top:int
41
- right:int
42
- bottom:int
43
- width:int
44
- height:int
45
-
46
- def get_center(self)->'Center':
47
- return Center(x=self.left+self.width//2,y=self.top+self.height//2)
48
-
49
- def xywh_to_string(self):
50
- return f'({self.left},{self.top},{self.width},{self.height})'
51
-
52
- def xyxy_to_string(self):
53
- x1,y1,x2,y2=self.convert_xywh_to_xyxy()
54
- return f'({x1},{y1},{x2},{y2})'
55
-
56
- def convert_xywh_to_xyxy(self)->tuple[int,int,int,int]:
57
- x1,y1=self.left,self.top
58
- x2,y2=self.left+self.width,self.top+self.height
59
- return x1,y1,x2,y2
60
-
61
- @dataclass
62
- class Center:
63
- x:int
64
- y:int
65
-
66
- def to_string(self)->str:
67
- return f'({self.x},{self.y})'
68
-
69
- @dataclass
70
- class TreeElementNode:
71
- name: str
72
- control_type: str
73
- app_name: str
74
- value:str
75
- shortcut: str
76
- bounding_box: BoundingBox
77
- center: Center
78
- xpath:str
79
- is_focused:bool
80
-
81
- def to_row(self, index: int):
82
- return [index, self.app_name, self.control_type, self.name, self.value, self.shortcut, self.center.to_string(),self.is_focused]
83
-
84
- @dataclass
85
- class ScrollElementNode:
86
- name: str
87
- control_type: str
88
- xpath:str
89
- app_name: str
90
- bounding_box: BoundingBox
91
- center: Center
92
- horizontal_scrollable: bool
93
- horizontal_scroll_percent: float
94
- vertical_scrollable: bool
95
- vertical_scroll_percent: float
96
- is_focused: bool
97
-
98
- def to_row(self, index: int, base_index: int):
99
- return [
100
- base_index + index,
101
- self.app_name,
102
- self.control_type,
103
- self.name,
104
- self.center.to_string(),
105
- self.horizontal_scrollable,
106
- self.horizontal_scroll_percent,
107
- self.vertical_scrollable,
108
- self.vertical_scroll_percent,
109
- self.is_focused
110
- ]
111
-
112
- @dataclass
113
- class TextElementNode:
114
- text:str
115
-
1
+ from dataclasses import dataclass,field
2
+ from tabulate import tabulate
3
+ from typing import Optional
4
+
5
+ @dataclass
6
+ class DOMInfo:
7
+ horizontal_scrollable: bool
8
+ horizontal_scroll_percent: float
9
+ vertical_scrollable: bool
10
+ vertical_scroll_percent: float
11
+
12
+ @dataclass
13
+ class TreeState:
14
+ interactive_nodes:list['TreeElementNode']=field(default_factory=list)
15
+ scrollable_nodes:list['ScrollElementNode']=field(default_factory=list)
16
+ dom_informative_nodes:list['TextElementNode']=field(default_factory=list)
17
+ dom_info:Optional['DOMInfo']=None
18
+
19
+ def interactive_elements_to_string(self) -> str:
20
+ if not self.interactive_nodes:
21
+ return "No interactive elements"
22
+ headers = ["Label", "App Name", "ControlType", "Name", "Value", "Shortcut", "Coordinates" ,"IsFocused"]
23
+ rows = [node.to_row(idx) for idx, node in enumerate(self.interactive_nodes)]
24
+ return tabulate(rows, headers=headers, tablefmt="simple")
25
+
26
+ def scrollable_elements_to_string(self) -> str:
27
+ if not self.scrollable_nodes:
28
+ return "No scrollable elements"
29
+ headers = [
30
+ "Label", "App Name", "ControlType", "Name", "Coordinates",
31
+ "Horizontal Scrollable", "Horizontal Scroll Percent(%)", "Vertical Scrollable", "Vertical Scroll Percent(%)", "IsFocused"
32
+ ]
33
+ base_index = len(self.interactive_nodes)
34
+ rows = [node.to_row(idx, base_index) for idx, node in enumerate(self.scrollable_nodes)]
35
+ return tabulate(rows, headers=headers, tablefmt="simple")
36
+
37
+ @dataclass
38
+ class BoundingBox:
39
+ left:int
40
+ top:int
41
+ right:int
42
+ bottom:int
43
+ width:int
44
+ height:int
45
+
46
+ def get_center(self)->'Center':
47
+ return Center(x=self.left+self.width//2,y=self.top+self.height//2)
48
+
49
+ def xywh_to_string(self):
50
+ return f'({self.left},{self.top},{self.width},{self.height})'
51
+
52
+ def xyxy_to_string(self):
53
+ x1,y1,x2,y2=self.convert_xywh_to_xyxy()
54
+ return f'({x1},{y1},{x2},{y2})'
55
+
56
+ def convert_xywh_to_xyxy(self)->tuple[int,int,int,int]:
57
+ x1,y1=self.left,self.top
58
+ x2,y2=self.left+self.width,self.top+self.height
59
+ return x1,y1,x2,y2
60
+
61
+ @dataclass
62
+ class Center:
63
+ x:int
64
+ y:int
65
+
66
+ def to_string(self)->str:
67
+ return f'({self.x},{self.y})'
68
+
69
+ @dataclass
70
+ class TreeElementNode:
71
+ name: str
72
+ control_type: str
73
+ app_name: str
74
+ value:str
75
+ shortcut: str
76
+ bounding_box: BoundingBox
77
+ center: Center
78
+ xpath:str
79
+ is_focused:bool
80
+
81
+ def to_row(self, index: int):
82
+ return [index, self.app_name, self.control_type, self.name, self.value, self.shortcut, self.center.to_string(),self.is_focused]
83
+
84
+ @dataclass
85
+ class ScrollElementNode:
86
+ name: str
87
+ control_type: str
88
+ xpath:str
89
+ app_name: str
90
+ bounding_box: BoundingBox
91
+ center: Center
92
+ horizontal_scrollable: bool
93
+ horizontal_scroll_percent: float
94
+ vertical_scrollable: bool
95
+ vertical_scroll_percent: float
96
+ is_focused: bool
97
+
98
+ def to_row(self, index: int, base_index: int):
99
+ return [
100
+ base_index + index,
101
+ self.app_name,
102
+ self.control_type,
103
+ self.name,
104
+ self.center.to_string(),
105
+ self.horizontal_scrollable,
106
+ self.horizontal_scroll_percent,
107
+ self.vertical_scrollable,
108
+ self.vertical_scroll_percent,
109
+ self.is_focused
110
+ ]
111
+
112
+ @dataclass
113
+ class TextElementNode:
114
+ text:str
115
+
116
116
  ElementNode=TreeElementNode|ScrollElementNode
@@ -0,0 +1,4 @@
1
+ from .enums import *
2
+ from .core import *
3
+ from .patterns import *
4
+ from .controls import *