class ScanMode(Timer): """ Abstract base class for all scanning modes. Specifies how the scanner moves between chunks of keys and when to activate them. Scan mode subclasses define a set of actions they support and the base class translates input device events into scan actions. Hierarchy: ScanMode --> AutoScan --> UserScan --> OverScan --> StepScan --> DirectScan """ """ Scan actions """ ACTION_STEP = 0 ACTION_LEFT = 1 ACTION_RIGHT = 2 ACTION_UP = 3 ACTION_DOWN = 4 ACTION_ACTIVATE = 5 ACTION_STEP_START = 6 ACTION_STEP_STOP = 7 ACTION_UNHANDLED = 8 """ Time between key activation flashes (in sec) """ ACTIVATION_FLASH_INTERVAL = 0.1 """ Number of key activation flashes """ ACTIVATION_FLASH_COUNT = 4 def __init__(self, redraw_callback, activate_callback): super(ScanMode, self).__init__() logger.debug("ScanMode.__init__()") """ Activation timer instance """ self._activation_timer = Timer() """ Counter for key flash animation """ self._flash = 0 """ Callback for key redraws """ self._redraw_callback = redraw_callback """ Callback for key activation """ self._activate_callback = activate_callback """ A Chunker instance """ self.chunker = None def __del__(self): logger.debug("ScanMode.__del__()") def map_actions(self, detail, pressed): """ Abstract: Convert input events into scan actions. """ raise NotImplementedError() def do_action(self, action): """ Abstract: Handle scan actions. """ raise NotImplementedError() def scan(self): """ Abstract: Move between chunks. """ raise NotImplementedError() def create_chunker(self): """ Abstract: Create a chunker instance. """ raise NotImplementedError() def init_position(self): """ Virtual: Called if a new layer was set or a key activated. """ pass def handle_event(self, event): """ Translate device events into scan actions. """ # Ignore events during key activation if self._activation_timer.is_running(): return event_type = event.xi_type if event_type == XIEventType.ButtonPress: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, True) elif event_type == XIEventType.ButtonRelease: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, False) elif event_type == XIEventType.KeyPress: key_map = config.scanner.device_key_map action = self.map_actions(key_map, event.keyval, True) elif event_type == XIEventType.KeyRelease: key_map = config.scanner.device_key_map action = self.map_actions(key_map, event.keyval, False) else: action = self.ACTION_UNHANDLED if action != self.ACTION_UNHANDLED: self.do_action(action) def on_timer(self): """ Override: Timer() callback. """ return self.scan() def max_cycles_reached(self): """ Check if the maximum number of scan cycles is reached. """ return self.chunker.cycles >= config.scanner.cycles def set_layer(self, layout, layer): """ Set the layer that should be scanned. """ self.reset() self.chunker = self.create_chunker() self.chunker.chunk(layout, layer) self.init_position() def _on_activation_timer(self, key): """ Timer callback: Flashes the key and finally activates it. """ if self._flash > 0: key.scanned = not key.scanned self._flash -= 1 self.redraw([key]) return True else: self._activate_callback(key) self.init_position() return False def activate(self): """ Activates a key and triggers feedback. """ key = self.chunker.get_key() if not key: return if config.scanner.feedback_flash: self._flash = self.ACTIVATION_FLASH_COUNT self._activation_timer.start(self.ACTIVATION_FLASH_INTERVAL, self._on_activation_timer, key) else: self._activate_callback(key) self.init_position() def reset(self): """ Stop scanning and clear all highlights. """ if self.is_running(): self.stop() if self.chunker: self.redraw(self.chunker.highlight_all(False)) def redraw(self, keys=None): """ Update individual keys or the entire keyboard. """ self._redraw_callback(keys) def finalize(self): """ Clean up the ScanMode instance. """ self.reset() self._activation_timer = None
class ScanMode(Timer): """ Abstract base class for all scanning modes. Specifies how the scanner moves between chunks of keys and when to activate them. Scan mode subclasses define a set of actions they support and the base class translates input device events into scan actions. Hierarchy: ScanMode --> AutoScan --> UserScan --> OverScan --> StepScan --> DirectScan """ """ Scan actions """ ACTION_STEP = 0 ACTION_LEFT = 1 ACTION_RIGHT = 2 ACTION_UP = 3 ACTION_DOWN = 4 ACTION_ACTIVATE = 5 ACTION_STEP_START = 6 ACTION_STEP_STOP = 7 ACTION_UNHANDLED = 8 """ Handles Key Events (Multiple Press at a time) """#In MUL_KEY = 0#In SCAN_PREV_ACTION = ACTION_UNHANDLED#In SCAN_ACTION_DO = True#In """ Time between key activation flashes (in sec) """ ACTIVATION_FLASH_INTERVAL = 0.1 """ Number of key activation flashes """ ACTIVATION_FLASH_COUNT = 2 def __init__(self, redraw_callback, activate_callback): super(ScanMode, self).__init__() logger.debug("ScanMode.__init__()") """ Activation timer instance """ self._activation_timer = Timer() """ Counter for key flash animation """ self._flash = 0 """ Counter for key popup animation """ self._popup_display=0 #In """ Callback for key redraws """ self._redraw_callback = redraw_callback """ Callback for key activation """ self._activate_callback = activate_callback """ A Chunker instance """ self.chunker = None """ Time between key activation flashes (in sec) """ self.ACTIVATION_FLASH_INTERVAL = config.scanner.activation_flash_interval #0.1 #In """ Number of key activation flashes """ self.ACTIVATION_FLASH_COUNT = config.scanner.activation_flash_count #2 #In def __del__(self): logger.debug("ScanMode.__del__()") def map_actions(self, detail, pressed): """ Abstract: Convert input events into scan actions. """ raise NotImplementedError() def do_action(self, action): """ Abstract: Handle scan actions. """ raise NotImplementedError() def scan(self): """ Abstract: Move between chunks. """ raise NotImplementedError() def create_chunker(self): """ Abstract: Create a chunker instance. """ raise NotImplementedError() def init_position(self): """ Virtual: Called if a new layer was set or a key activated. """ pass def handle_event(self, event): """ Translate device events into scan actions. """ # Ignore events during key activation if self._activation_timer.is_running(): return event_type = event.xi_type if event_type == XIEventType.ButtonPress: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, True) elif event_type == XIEventType.ButtonRelease: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, False) elif event_type == XIEventType.KeyPress: if self.MUL_KEY >= 0:#In key_map = config.scanner.device_key_map#In self.SCAN_PREV_ACTION = self.map_actions(key_map, event.keyval, True)#In self.MUL_KEY = self.MUL_KEY + 1#In return#In else: action = self.map_actions(key_map, event.keyval, False) elif event_type == XIEventType.KeyRelease: if self.MUL_KEY > 0:#In self.MUL_KEY = self.MUL_KEY - 1#In key_map = config.scanner.device_key_map action = self.map_actions(key_map, event.keyval, True)#In if action != self.SCAN_PREV_ACTION:#In self.SCAN_ACTION_DO = False#In if self.MUL_KEY > 0 or (self.MUL_KEY == 0 and self.SCAN_ACTION_DO != True):#In action = self.map_actions(key_map, event.keyval, False) if self.MUL_KEY == 0 and self.SCAN_ACTION_DO != True:#In """ print("E R R O R : PLEASE DONT PRESS BOTH FUNCTIONALITIES TOGETHER!!!")#In TODO : Show Error Message """ self.SCAN_ACTION_DO = True#In else: action = self.map_actions(key_map, event.keyval, False) else: action = self.ACTION_UNHANDLED if action != self.ACTION_UNHANDLED: self.do_action(action) def on_timer(self): """ Override: Timer() callback. """ return self.scan() def max_cycles_reached(self): """ Check if the maximum number of scan cycles is reached. """ return self.chunker.cycles >= config.scanner.cycles def set_layer(self, layout, layer): """ Set the layer that should be scanned. """ self.reset() self.chunker = self.create_chunker() self.chunker.chunk(layout, layer) self.init_position() def _on_activation_timer(self, key): """ Timer callback: Flashes the key and finally activates it. """ if self._flash > 0: key.scanned = not key.scanned self._flash -= 1 self.redraw([key]) return True else: self._activate_callback(key) self.init_position() return False def _on_activation_timer_popup(self, key):#In """ Timer callback: Reset Scanner. """ self.init_position() return False def activate(self): """ Activates a key and triggers feedback. """ key = self.chunker.get_key() if not key: return if config.scanner.feedback_flash: """ Scanner Blinking """ self._flash = self.ACTIVATION_FLASH_COUNT * 2 #In self._activation_timer.start(self.ACTIVATION_FLASH_INTERVAL, self._on_activation_timer, key) else:#In """ Scanner Popup """ delay = config.UNPRESS_DELAY #In config.UNPRESS_DELAY = config.scanner.scanner_popup_unpress_delay #In self._activate_callback(key) self._activation_timer.start(config.scanner.scanner_popup_unpress_delay, self._on_activation_timer_popup, key) #In config.UNPRESS_DELAY = delay #In #self.init_position() def reset(self): """ Stop scanning and clear all highlights. """ if self.is_running(): self.stop() if self.chunker: self.redraw(self.chunker.highlight_all(False)) def redraw(self, keys=None): """ Update individual keys or the entire keyboard. """ self._redraw_callback(keys) def finalize(self): """ Clean up the ScanMode instance. """ self.reset() self._activation_timer = None
class ScanMode(Timer): """ Abstract base class for all scanning modes. Specifies how the scanner moves between chunks of keys and when to activate them. Scan mode subclasses define a set of actions they support and the base class translates input device events into scan actions. Hierarchy: ScanMode --> AutoScan --> UserScan --> OverScan --> StepScan --> DirectScan """ """ Scan actions """ ACTION_STEP = 0 ACTION_LEFT = 1 ACTION_RIGHT = 2 ACTION_UP = 3 ACTION_DOWN = 4 ACTION_ACTIVATE = 5 ACTION_STEP_START = 6 ACTION_STEP_STOP = 7 ACTION_UNHANDLED = 8 """ Time between key activation flashes (in sec) """ ACTIVATION_FLASH_INTERVAL = 0.1 """ Number of key activation flashes """ ACTIVATION_FLASH_COUNT = 4 def __init__(self, redraw_callback, activate_callback): super(ScanMode, self).__init__() logger.debug("ScanMode.__init__()") """ Activation timer instance """ self._activation_timer = Timer() """ Counter for key flash animation """ self._flash = 0 """ Callback for key redraws """ self._redraw_callback = redraw_callback """ Callback for key activation """ self._activate_callback = activate_callback """ A Chunker instance """ self.chunker = None def __del__(self): logger.debug("ScanMode.__del__()") def map_actions(self, detail, pressed): """ Abstract: Convert input events into scan actions. """ raise NotImplementedError() def do_action(self, action): """ Abstract: Handle scan actions. """ raise NotImplementedError() def scan(self): """ Abstract: Move between chunks. """ raise NotImplementedError() def create_chunker(self): """ Abstract: Create a chunker instance. """ raise NotImplementedError() def init_position(self): """ Virtual: Called if a new layer was set or a key activated. """ pass def handle_event(self, event, detail): """ Translate device events into scan actions. """ # Ignore events during key activation if self._activation_timer.is_running(): return if event == "ButtonPress": button_map = config.scanner.device_button_map action = self.map_actions(button_map, detail, True) elif event == "ButtonRelease": button_map = config.scanner.device_button_map action = self.map_actions(button_map, detail, False) elif event == "KeyPress": key_map = config.scanner.device_key_map action = self.map_actions(key_map, detail, True) elif event == "KeyRelease": key_map = config.scanner.device_key_map action = self.map_actions(key_map, detail, False) else: action = self.ACTION_UNHANDLED if action != self.ACTION_UNHANDLED: self.do_action(action) def on_timer(self): """ Override: Timer() callback. """ return self.scan() def max_cycles_reached(self): """ Check if the maximum number of scan cycles is reached. """ return self.chunker.cycles >= config.scanner.cycles def set_layer(self, layout, layer): """ Set the layer that should be scanned. """ self.reset() self.chunker = self.create_chunker() self.chunker.chunk(layout, layer) self.init_position() def _on_activation_timer(self, key): """ Timer callback: Flashes the key and finally activates it. """ if self._flash > 0: key.scanned = not key.scanned self._flash -= 1 self.redraw([key]) return True else: self._activate_callback(key) self.init_position() return False def activate(self): """ Activates a key and triggers feedback. """ key = self.chunker.get_key() if not key: return if config.scanner.feedback_flash: self._flash = self.ACTIVATION_FLASH_COUNT self._activation_timer.start(self.ACTIVATION_FLASH_INTERVAL, self._on_activation_timer, key) else: self._activate_callback(key) self.init_position() def reset(self): """ Stop scanning and clear all highlights. """ if self.is_running(): self.stop() if self.chunker: self.redraw(self.chunker.highlight_all(False)) def redraw(self, keys=None): """ Update individual keys or the entire keyboard. """ self._redraw_callback(keys) def finalize(self): """ Clean up the ScanMode instance. """ self.reset() self._activation_timer = None
class ScanMode(Timer): """ Abstract base class for all scanning modes. Specifies how the scanner moves between chunks of keys and when to activate them. Scan mode subclasses define a set of actions they support and the base class translates input device events into scan actions. Hierarchy: ScanMode --> AutoScan --> UserScan --> OverScan --> StepScan --> DirectScan """ """ Scan actions """ ACTION_STEP = 0 ACTION_LEFT = 1 ACTION_RIGHT = 2 ACTION_UP = 3 ACTION_DOWN = 4 ACTION_ACTIVATE = 5 ACTION_STEP_START = 6 ACTION_STEP_STOP = 7 ACTION_UNHANDLED = 8 """ Handles Key Events (Multiple Press at a time) """ #In MUL_KEY = 0 #In SCAN_PREV_ACTION = ACTION_UNHANDLED #In SCAN_ACTION_DO = True #In """ Time between key activation flashes (in sec) """ ACTIVATION_FLASH_INTERVAL = 0.1 """ Number of key activation flashes """ ACTIVATION_FLASH_COUNT = 2 def __init__(self, redraw_callback, activate_callback): super(ScanMode, self).__init__() logger.debug("ScanMode.__init__()") """ Activation timer instance """ self._activation_timer = Timer() """ Counter for key flash animation """ self._flash = 0 """ Counter for key popup animation """ self._popup_display = 0 #In """ Callback for key redraws """ self._redraw_callback = redraw_callback """ Callback for key activation """ self._activate_callback = activate_callback """ A Chunker instance """ self.chunker = None """ Time between key activation flashes (in sec) """ self.ACTIVATION_FLASH_INTERVAL = config.scanner.activation_flash_interval #0.1 #In """ Number of key activation flashes """ self.ACTIVATION_FLASH_COUNT = config.scanner.activation_flash_count #2 #In def __del__(self): logger.debug("ScanMode.__del__()") def map_actions(self, detail, pressed): """ Abstract: Convert input events into scan actions. """ raise NotImplementedError() def do_action(self, action): """ Abstract: Handle scan actions. """ raise NotImplementedError() def scan(self): """ Abstract: Move between chunks. """ raise NotImplementedError() def create_chunker(self): """ Abstract: Create a chunker instance. """ raise NotImplementedError() def init_position(self): """ Virtual: Called if a new layer was set or a key activated. """ pass def handle_event(self, event): """ Translate device events into scan actions. """ # Ignore events during key activation if self._activation_timer.is_running(): return event_type = event.xi_type if event_type == XIEventType.ButtonPress: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, True) elif event_type == XIEventType.ButtonRelease: button_map = config.scanner.device_button_map action = self.map_actions(button_map, event.button, False) elif event_type == XIEventType.KeyPress: if self.MUL_KEY >= 0: #In key_map = config.scanner.device_key_map #In self.SCAN_PREV_ACTION = self.map_actions( key_map, event.keyval, True) #In self.MUL_KEY = self.MUL_KEY + 1 #In return #In else: action = self.map_actions(key_map, event.keyval, False) elif event_type == XIEventType.KeyRelease: if self.MUL_KEY > 0: #In self.MUL_KEY = self.MUL_KEY - 1 #In key_map = config.scanner.device_key_map action = self.map_actions(key_map, event.keyval, True) #In if action != self.SCAN_PREV_ACTION: #In self.SCAN_ACTION_DO = False #In if self.MUL_KEY > 0 or (self.MUL_KEY == 0 and self.SCAN_ACTION_DO != True): #In action = self.map_actions(key_map, event.keyval, False) if self.MUL_KEY == 0 and self.SCAN_ACTION_DO != True: #In """ print("E R R O R : PLEASE DONT PRESS BOTH FUNCTIONALITIES TOGETHER!!!")#In TODO : Show Error Message """ self.SCAN_ACTION_DO = True #In else: action = self.map_actions(key_map, event.keyval, False) else: action = self.ACTION_UNHANDLED if action != self.ACTION_UNHANDLED: self.do_action(action) def on_timer(self): """ Override: Timer() callback. """ return self.scan() def max_cycles_reached(self): """ Check if the maximum number of scan cycles is reached. """ return self.chunker.cycles >= config.scanner.cycles def set_layer(self, layout, layer): """ Set the layer that should be scanned. """ self.reset() self.chunker = self.create_chunker() self.chunker.chunk(layout, layer) self.init_position() def _on_activation_timer(self, key): """ Timer callback: Flashes the key and finally activates it. """ if self._flash > 0: key.scanned = not key.scanned self._flash -= 1 self.redraw([key]) return True else: self._activate_callback(key) self.init_position() return False def _on_activation_timer_popup(self, key): #In """ Timer callback: Reset Scanner. """ self.init_position() return False def activate(self): """ Activates a key and triggers feedback. """ key = self.chunker.get_key() if not key: return if config.scanner.feedback_flash: """ Scanner Blinking """ self._flash = self.ACTIVATION_FLASH_COUNT * 2 #In self._activation_timer.start(self.ACTIVATION_FLASH_INTERVAL, self._on_activation_timer, key) else: #In """ Scanner Popup """ delay = config.UNPRESS_DELAY #In config.UNPRESS_DELAY = config.scanner.scanner_popup_unpress_delay #In self._activate_callback(key) self._activation_timer.start( config.scanner.scanner_popup_unpress_delay, self._on_activation_timer_popup, key) #In config.UNPRESS_DELAY = delay #In #self.init_position() def reset(self): """ Stop scanning and clear all highlights. """ if self.is_running(): self.stop() if self.chunker: self.redraw(self.chunker.highlight_all(False)) def redraw(self, keys=None): """ Update individual keys or the entire keyboard. """ self._redraw_callback(keys) def finalize(self): """ Clean up the ScanMode instance. """ self.reset() self._activation_timer = None