Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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