""" Abstract Input Event Base Class Platform-agnostic input event interface. """ from abc import ABC, abstractmethod from typing import Optional, Dict, Any, List from enum import Enum import json class EventType(Enum): """事件类型枚举 - 仅包含跨平台通用事件""" # 基础交互事件 TOUCH = "touch" LONG_TOUCH = "long_touch" SWIPE = "swipe" SCROLL = "scroll" # 文本输入事件 SET_TEXT = "set_text" # 按键事件 KEY = "key" # 应用控制事件(平台无关) LAUNCH_APP = "launch_app" # 启动应用 KILL_APP = "kill_app" # 强制终止应用 INTENT = "intent" # Android Intent事件 # 特殊事件 MANUAL = "manual" EXIT = "exit" # 选择事件 SELECT = "select" UNSELECT = "unselect" class AbstractInputEvent(ABC): """ 输入事件抽象基类 定义了所有输入事件的标准接口,包括: - 事件发送 - 事件序列化 - 事件字符串表示 """ def __init__(self, event_type: EventType): """ 初始化输入事件 :param event_type: 事件类型 """ self.event_type = event_type self.log_lines = None # ==================== 事件发送 ==================== @abstractmethod def send(self, device: 'AbstractDevice') -> bool: """ 发送事件到设备 :param device: 设备对象 :return: 是否发送成功 """ pass # ==================== 序列化 ==================== @abstractmethod def to_dict(self) -> Dict[str, Any]: """ 序列化为字典 :return: 事件信息字典 """ pass def to_json(self) -> str: """ 序列化为 JSON 字符串 :return: JSON 字符串 """ return json.dumps(self.to_dict()) def __str__(self) -> str: return self.to_json() # ==================== 事件描述 ==================== @abstractmethod def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: """ 获取事件的字符串描述 :param state: 可选的设备状态对象 :return: 事件描述字符串 """ pass # ==================== 视图信息 ==================== def get_views(self) -> List[Dict[str, Any]]: """ 获取事件关联的视图列表 :return: 视图字典列表 """ return [] # ==================== 基础事件类型 ==================== class BaseTouchEvent(AbstractInputEvent): """触摸事件基类""" def __init__(self, x: Optional[int] = None, y: Optional[int] = None, view: Optional[Dict[str, Any]] = None): """ 初始化触摸事件 :param x: X 坐标 :param y: Y 坐标 :param view: 目标视图(如果提供,将使用视图中心点) """ super().__init__(EventType.TOUCH) self.x = x self.y = y self.view = view # 如果提供了视图,使用视图中心点 if view is not None and (x is None or y is None): from .abstract_device_state import AbstractDeviceState center = AbstractDeviceState.get_view_center(view) self.x = int(center[0]) self.y = int(center[1]) def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseTouchEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "x": self.x, "y": self.y, "view": self.view } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: if self.view is not None: view_str = self.view.get('view_str', str(self.view)) return f"Touch({view_str})" return f"Touch({self.x}, {self.y})" class BaseLongTouchEvent(AbstractInputEvent): """长按事件基类""" def __init__(self, x: Optional[int] = None, y: Optional[int] = None, view: Optional[Dict[str, Any]] = None, duration: int = 2000): """ 初始化长按事件 :param x: X 坐标 :param y: Y 坐标 :param view: 目标视图 :param duration: 长按持续时间(毫秒) """ super().__init__(EventType.LONG_TOUCH) self.x = x self.y = y self.view = view self.duration = duration if view is not None and (x is None or y is None): from .abstract_device_state import AbstractDeviceState center = AbstractDeviceState.get_view_center(view) self.x = int(center[0]) self.y = int(center[1]) def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseLongTouchEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "x": self.x, "y": self.y, "duration": self.duration, "view": self.view } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: if self.view is not None: view_str = self.view.get('view_str', str(self.view)) return f"LongTouch({view_str})" return f"LongTouch({self.x}, {self.y}, {self.duration}ms)" class BaseSwipeEvent(AbstractInputEvent): """滑动事件基类""" def __init__(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: int = 500, view: Optional[Dict[str, Any]] = None): """ 初始化滑动事件 :param start_x: 起始 X 坐标 :param start_y: 起始 Y 坐标 :param end_x: 结束 X 坐标 :param end_y: 结束 Y 坐标 :param duration: 滑动持续时间(毫秒) :param view: 关联的视图字典(可选) """ super().__init__(EventType.SWIPE) self.start_x = start_x self.start_y = start_y self.end_x = end_x self.end_y = end_y self.duration = duration self.view = view def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseSwipeEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "start_x": self.start_x, "start_y": self.start_y, "end_x": self.end_x, "end_y": self.end_y, "duration": self.duration, "view": self.view } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: if self.view is not None: view_str = self.view.get('view_str', str(self.view)) return f"Swipe({view_str}, {self.start_x},{self.start_y} -> {self.end_x},{self.end_y})" return f"Swipe({self.start_x},{self.start_y} -> {self.end_x},{self.end_y})" class BaseScrollEvent(AbstractInputEvent): """滚动事件基类""" DIRECTION_UP = "up" DIRECTION_DOWN = "down" DIRECTION_LEFT = "left" DIRECTION_RIGHT = "right" def __init__(self, direction: str = "down", view: Optional[Dict[str, Any]] = None): """ 初始化滚动事件 :param direction: 滚动方向 ('up', 'down', 'left', 'right') :param view: 目标视图(可选) """ super().__init__(EventType.SCROLL) self.direction = direction self.view = view def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseScrollEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "direction": self.direction, "view": self.view } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: if self.view is not None: view_str = self.view.get('view_str', str(self.view)) return f"Scroll({view_str}, {self.direction})" return f"Scroll({self.direction})" class BaseSetTextEvent(AbstractInputEvent): """文本输入事件基类""" def __init__(self, text: str, view: Optional[Dict[str, Any]] = None): """ 初始化文本输入事件 :param text: 要输入的文本 :param view: 目标视图 """ super().__init__(EventType.SET_TEXT) self.text = text self.view = view def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseSetTextEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "text": self.text, "view": self.view } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: if self.view is not None: view_str = self.view.get('view_str', str(self.view)) return f"SetText({view_str}, '{self.text}')" return f"SetText('{self.text}')" class BaseKeyEvent(AbstractInputEvent): """按键事件基类""" # 通用按键名称 KEY_BACK = "BACK" KEY_HOME = "HOME" KEY_MENU = "MENU" KEY_ENTER = "ENTER" KEY_ESCAPE = "ESCAPE" def __init__(self, key_name: str): """ 初始化按键事件 :param key_name: 按键名称 """ super().__init__(EventType.KEY) self.key_name = key_name def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseKeyEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "key_name": self.key_name } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: return f"Key({self.key_name})" class BaseKillAppEvent(AbstractInputEvent): """终止应用事件基类""" def __init__(self, app=None): """ 初始化终止应用事件 :param app: 要终止的应用 """ super().__init__(EventType.KILL_APP) self.app = app def send(self, device: 'AbstractDevice') -> bool: """发送事件 - 需要由平台特定子类实现""" raise NotImplementedError("BaseKillAppEvent.send() must be implemented by platform-specific subclass") def to_dict(self) -> Dict[str, Any]: return { "event_type": self.event_type.value, "app": str(self.app) if self.app else None } def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: return f"KillApp({self.app})"