Skip to content

Commit

Permalink
Implement selectTextRange, setCaretPosition, getCaretLocation
Browse files Browse the repository at this point in the history
  • Loading branch information
Bogdan Condurache committed May 5, 2023
1 parent 22551bb commit c09d4c8
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Python wrapper around the Java Access Bridge / Windows Access Bridge.

Enable the Java Access Bridge in windows

C:\path\to\java\bin\jabswitch -enable
C:\path\to\java\bin\jabswitch /enable

# Install

Expand Down
42 changes: 42 additions & 0 deletions src/JABWrapper/context_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,48 @@ def get_visible_children(self) -> List:
visible_child = ContextNode(self._jab_wrapper, found_visible_children.children[i], self._lock, self.ancestry + 1, False)
visible_children.append(visible_child)
return visible_children

def set_caret_position(self, position):
"""
Set the caret to the given position
Args:
position: int representing the index where to set the caret.
Raises:
APIException: Failed to set the caret.
"""
self._jab_wrapper.set_caret_position(self.context, position)

def get_caret_position(self, index):
"""
Get the coordinates of the current caret location. External method uses `position` for consistency
instead of `location`.
Args:
context: the element context handle.
index: TODO
Returns:
An AccessibleTextRectInfo object.
Raises:
APIException: failed to call the java access bridge API with attributes or failed to get location.
"""
return self._jab_wrapper.get_caret_location(self.context, index)

def select_text_range(self, start_index: int, end_index: int):
"""
Select text within given range
Args:
start_index: int for start of selection as index.
end_index: int for end of selection as index.
Raises:
APIException: failed to call the java access bridge API with attributes or failed to make selection.
"""
return self._jab_wrapper.select_text_range(self.context, start_index, end_index)


class ContextTree:
Expand Down
72 changes: 69 additions & 3 deletions src/JABWrapper/jab_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,16 +395,23 @@ def _define_functions(self) -> None:
# BOOL requestFocus(long vmID, AccessibleContext context)
self._wab.requestFocus.argtypes = [c_long, JavaObject]
self._wab.requestFocus.restypes = wintypes.BOOL
# TODO: selectTextRange
# BOOL selectTextRangeFP (long vmID, AccessibleContext accessibleContext, int startIndex, int endIndex)
self._wab.selectTextRange.argtypes = [c_long, JavaObject, c_int, c_int]
self._wab.selectTextRange.restype = wintypes.BOOL
# TODO: getTextAttributesInRange
# int getVisibleChildrenCount(long vmID, AccessibleContext context)
self._wab.getVisibleChildrenCount.argtypes = [c_long, JavaObject]
self._wab.getVisibleChildrenCount.restype = c_int
# BOOL getVisibleChildren(long vmID, AccessibleContext context, int startIndex, VisibleChildrenInfo *visibleChilderInfo)
self._wab.getVisibleChildren.argtypes = [c_long, JavaObject, c_int, POINTER(VisibleChildrenInfo)]
self._wab.getVisibleChildren.restype = wintypes.BOOL
# TODO: setCaretPosition
# TODO: getCaretLocation
# BOOL setCaretPositionFP (long vmID, AccessibleContext accessibleContext, int position)
self._wab.setCaretPosition.argtypes = [c_long, JavaObject, c_int]
self._wab.setCaretPosition.restype = wintypes.BOOL
# TODO: Bogdan getCaretLocation
# BOOL getCaretLocationFP (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, int index);
self._wab.getCaretLocation.argtypes = [c_long, JavaObject, POINTER(AccessibleTextRectInfo), c_int]
self._wab.getCaretLocation.restype = wintypes.BOOL
# TODO: getEventsWaitingFP

def _define_callbacks(self) -> None:
Expand Down Expand Up @@ -1709,6 +1716,26 @@ def get_virtual_accessible_name(self, context: JavaObject) -> str:
if not ok:
raise APIException("Failed to get virtual accessible name")
return buf.value

def select_text_range(self, context: JavaObject, start_index: int, end_index: int) -> bool:
"""
Select text within given range
Args:
context: the element context handle.
start_index: int for start of selection as index.
end_index: int for end of selection as index.
Returns:
bool: should always be True if operation was successful.
Raises:
APIException: failed to call the java access bridge API with attributes or failed to make selection.
"""
ok = self._wab.selectTextRange(self._vmID, context, start_index, end_index)
if not ok:
raise APIException("Failed to select text")
return ok

def get_visible_children_count(self, context: JavaObject) -> int:
return self._wab.getVisibleChildrenCount(self._vmID, context)
Expand All @@ -1719,6 +1746,45 @@ def get_visible_children(self, context: JavaObject, start_index: int) -> Visible
if not ok:
raise APIException('Failed to get visible children info')
return visible_children

def set_caret_position(self, context: JavaObject, position: int) -> bool:
"""
Set the caret to the given position
Args:
context: the element context handle.
position: int representing the index where to set the caret.
Returns:
bool: should always be True if operation was successful.
Raises:
APIException: failed to call the java access bridge API with attributes or failed to set the caret.
"""
ok = self._wab.setCaretPosition(self._vmID, context, position)
if not ok:
raise APIException("Failed to select text")
return ok

def get_caret_location(self, context: JavaObject, index: int) -> AccessibleTextRectInfo:
"""
Get the coordinates of the current caret location.
Args:
context: the element context handle.
index: TODO
Returns:
An AccessibleTextRectInfo object.
Raises:
APIException: failed to call the java access bridge API with attributes or failed to get location.
"""
text_rect_info = AccessibleTextRectInfo()
ok = self._wab.getCaretLocation(self._vmID, context, byref(text_rect_info), index)
if not ok:
raise APIException("Failed to select text")
return text_rect_info

def register_callback(self, name: str, callback: Callable[[JavaObject], None]) -> None:
"""
Expand Down
16 changes: 14 additions & 2 deletions tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ def type_text_into_text_field(context_info_tree) -> ContextNode:
wait_until_text_contains(text_area, text)
return text_area

def set_caret_position(text_area):
text_area.set_caret_position(3)
logging.info("set_caret_position")

def get_caret_position(text_area):
pos = text_area.get_caret_position(0)
logging.info(f"get_caret_position: {pos.__dict__}")

def select_text_range(text_area):
text_area.select_text_range(1, 3)
logging.info(f"select_text_range")

def set_focus(context_info_tree):
# Set focus to main frame
Expand Down Expand Up @@ -227,6 +238,9 @@ def run_app_tests(jab_wrapper, window_id):
context_info_tree = parse_elements(jab_wrapper)
set_focus(context_info_tree)
text_area = type_text_into_text_field(context_info_tree)
set_caret_position(text_area)
get_caret_position(text_area)
select_text_range(text_area)
click_send_button(context_info_tree, text_area)
click_clear_button(context_info_tree, text_area)
verify_table_content(context_info_tree)
Expand Down Expand Up @@ -257,8 +271,6 @@ def main():
title = windows[0].title
assert title == "Foo bar", f"Invalid window found={title}"
run_app_tests(jab_wrapper, windows[0].pid)
except Exception as e:
logging.error(f"error={type(e)} - {e}")
finally:
logging.info("Shutting down JAB wrapper")
if jab_wrapper:
Expand Down

0 comments on commit c09d4c8

Please sign in to comment.