Skip to content

Commit c09d4c8

Browse files
author
Bogdan Condurache
committed
Implement selectTextRange, setCaretPosition, getCaretLocation
1 parent 22551bb commit c09d4c8

File tree

4 files changed

+126
-6
lines changed

4 files changed

+126
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Python wrapper around the Java Access Bridge / Windows Access Bridge.
1313

1414
Enable the Java Access Bridge in windows
1515

16-
C:\path\to\java\bin\jabswitch -enable
16+
C:\path\to\java\bin\jabswitch /enable
1717

1818
# Install
1919

src/JABWrapper/context_tree.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,48 @@ def get_visible_children(self) -> List:
240240
visible_child = ContextNode(self._jab_wrapper, found_visible_children.children[i], self._lock, self.ancestry + 1, False)
241241
visible_children.append(visible_child)
242242
return visible_children
243+
244+
def set_caret_position(self, position):
245+
"""
246+
Set the caret to the given position
247+
248+
Args:
249+
position: int representing the index where to set the caret.
250+
251+
Raises:
252+
APIException: Failed to set the caret.
253+
"""
254+
self._jab_wrapper.set_caret_position(self.context, position)
255+
256+
def get_caret_position(self, index):
257+
"""
258+
Get the coordinates of the current caret location. External method uses `position` for consistency
259+
instead of `location`.
260+
261+
Args:
262+
context: the element context handle.
263+
index: TODO
264+
265+
Returns:
266+
An AccessibleTextRectInfo object.
267+
268+
Raises:
269+
APIException: failed to call the java access bridge API with attributes or failed to get location.
270+
"""
271+
return self._jab_wrapper.get_caret_location(self.context, index)
272+
273+
def select_text_range(self, start_index: int, end_index: int):
274+
"""
275+
Select text within given range
276+
277+
Args:
278+
start_index: int for start of selection as index.
279+
end_index: int for end of selection as index.
280+
281+
Raises:
282+
APIException: failed to call the java access bridge API with attributes or failed to make selection.
283+
"""
284+
return self._jab_wrapper.select_text_range(self.context, start_index, end_index)
243285

244286

245287
class ContextTree:

src/JABWrapper/jab_wrapper.py

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,16 +395,23 @@ def _define_functions(self) -> None:
395395
# BOOL requestFocus(long vmID, AccessibleContext context)
396396
self._wab.requestFocus.argtypes = [c_long, JavaObject]
397397
self._wab.requestFocus.restypes = wintypes.BOOL
398-
# TODO: selectTextRange
398+
# BOOL selectTextRangeFP (long vmID, AccessibleContext accessibleContext, int startIndex, int endIndex)
399+
self._wab.selectTextRange.argtypes = [c_long, JavaObject, c_int, c_int]
400+
self._wab.selectTextRange.restype = wintypes.BOOL
399401
# TODO: getTextAttributesInRange
400402
# int getVisibleChildrenCount(long vmID, AccessibleContext context)
401403
self._wab.getVisibleChildrenCount.argtypes = [c_long, JavaObject]
402404
self._wab.getVisibleChildrenCount.restype = c_int
403405
# BOOL getVisibleChildren(long vmID, AccessibleContext context, int startIndex, VisibleChildrenInfo *visibleChilderInfo)
404406
self._wab.getVisibleChildren.argtypes = [c_long, JavaObject, c_int, POINTER(VisibleChildrenInfo)]
405407
self._wab.getVisibleChildren.restype = wintypes.BOOL
406-
# TODO: setCaretPosition
407-
# TODO: getCaretLocation
408+
# BOOL setCaretPositionFP (long vmID, AccessibleContext accessibleContext, int position)
409+
self._wab.setCaretPosition.argtypes = [c_long, JavaObject, c_int]
410+
self._wab.setCaretPosition.restype = wintypes.BOOL
411+
# TODO: Bogdan getCaretLocation
412+
# BOOL getCaretLocationFP (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, int index);
413+
self._wab.getCaretLocation.argtypes = [c_long, JavaObject, POINTER(AccessibleTextRectInfo), c_int]
414+
self._wab.getCaretLocation.restype = wintypes.BOOL
408415
# TODO: getEventsWaitingFP
409416

410417
def _define_callbacks(self) -> None:
@@ -1709,6 +1716,26 @@ def get_virtual_accessible_name(self, context: JavaObject) -> str:
17091716
if not ok:
17101717
raise APIException("Failed to get virtual accessible name")
17111718
return buf.value
1719+
1720+
def select_text_range(self, context: JavaObject, start_index: int, end_index: int) -> bool:
1721+
"""
1722+
Select text within given range
1723+
1724+
Args:
1725+
context: the element context handle.
1726+
start_index: int for start of selection as index.
1727+
end_index: int for end of selection as index.
1728+
1729+
Returns:
1730+
bool: should always be True if operation was successful.
1731+
1732+
Raises:
1733+
APIException: failed to call the java access bridge API with attributes or failed to make selection.
1734+
"""
1735+
ok = self._wab.selectTextRange(self._vmID, context, start_index, end_index)
1736+
if not ok:
1737+
raise APIException("Failed to select text")
1738+
return ok
17121739

17131740
def get_visible_children_count(self, context: JavaObject) -> int:
17141741
return self._wab.getVisibleChildrenCount(self._vmID, context)
@@ -1719,6 +1746,45 @@ def get_visible_children(self, context: JavaObject, start_index: int) -> Visible
17191746
if not ok:
17201747
raise APIException('Failed to get visible children info')
17211748
return visible_children
1749+
1750+
def set_caret_position(self, context: JavaObject, position: int) -> bool:
1751+
"""
1752+
Set the caret to the given position
1753+
1754+
Args:
1755+
context: the element context handle.
1756+
position: int representing the index where to set the caret.
1757+
1758+
Returns:
1759+
bool: should always be True if operation was successful.
1760+
1761+
Raises:
1762+
APIException: failed to call the java access bridge API with attributes or failed to set the caret.
1763+
"""
1764+
ok = self._wab.setCaretPosition(self._vmID, context, position)
1765+
if not ok:
1766+
raise APIException("Failed to select text")
1767+
return ok
1768+
1769+
def get_caret_location(self, context: JavaObject, index: int) -> AccessibleTextRectInfo:
1770+
"""
1771+
Get the coordinates of the current caret location.
1772+
1773+
Args:
1774+
context: the element context handle.
1775+
index: TODO
1776+
1777+
Returns:
1778+
An AccessibleTextRectInfo object.
1779+
1780+
Raises:
1781+
APIException: failed to call the java access bridge API with attributes or failed to get location.
1782+
"""
1783+
text_rect_info = AccessibleTextRectInfo()
1784+
ok = self._wab.getCaretLocation(self._vmID, context, byref(text_rect_info), index)
1785+
if not ok:
1786+
raise APIException("Failed to select text")
1787+
return text_rect_info
17221788

17231789
def register_callback(self, name: str, callback: Callable[[JavaObject], None]) -> None:
17241790
"""

tests/test.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ def type_text_into_text_field(context_info_tree) -> ContextNode:
135135
wait_until_text_contains(text_area, text)
136136
return text_area
137137

138+
def set_caret_position(text_area):
139+
text_area.set_caret_position(3)
140+
logging.info("set_caret_position")
141+
142+
def get_caret_position(text_area):
143+
pos = text_area.get_caret_position(0)
144+
logging.info(f"get_caret_position: {pos.__dict__}")
145+
146+
def select_text_range(text_area):
147+
text_area.select_text_range(1, 3)
148+
logging.info(f"select_text_range")
138149

139150
def set_focus(context_info_tree):
140151
# Set focus to main frame
@@ -227,6 +238,9 @@ def run_app_tests(jab_wrapper, window_id):
227238
context_info_tree = parse_elements(jab_wrapper)
228239
set_focus(context_info_tree)
229240
text_area = type_text_into_text_field(context_info_tree)
241+
set_caret_position(text_area)
242+
get_caret_position(text_area)
243+
select_text_range(text_area)
230244
click_send_button(context_info_tree, text_area)
231245
click_clear_button(context_info_tree, text_area)
232246
verify_table_content(context_info_tree)
@@ -257,8 +271,6 @@ def main():
257271
title = windows[0].title
258272
assert title == "Foo bar", f"Invalid window found={title}"
259273
run_app_tests(jab_wrapper, windows[0].pid)
260-
except Exception as e:
261-
logging.error(f"error={type(e)} - {e}")
262274
finally:
263275
logging.info("Shutting down JAB wrapper")
264276
if jab_wrapper:

0 commit comments

Comments
 (0)