1from __future__ import annotations 
    2 
    3from collections import defaultdict 
    4from typing import TYPE_CHECKING, Callable 
    5 
    6from prompt_toolkit.mouse_events import MouseEvent 
    7 
    8if TYPE_CHECKING: 
    9    from prompt_toolkit.key_binding.key_bindings import NotImplementedOrNone 
    10 
    11__all__ = [ 
    12    "MouseHandler", 
    13    "MouseHandlers", 
    14] 
    15 
    16 
    17MouseHandler = Callable[[MouseEvent], "NotImplementedOrNone"] 
    18 
    19 
    20class MouseHandlers: 
    21    """ 
    22    Two dimensional raster of callbacks for mouse events. 
    23    """ 
    24 
    25    def __init__(self) -> None: 
    26        def dummy_callback(mouse_event: MouseEvent) -> NotImplementedOrNone: 
    27            """ 
    28            :param mouse_event: `MouseEvent` instance. 
    29            """ 
    30            return NotImplemented 
    31 
    32        # NOTE: Previously, the data structure was a dictionary mapping (x,y) 
    33        # to the handlers. This however would be more inefficient when copying 
    34        # over the mouse handlers of the visible region in the scrollable pane. 
    35 
    36        # Map y (row) to x (column) to handlers. 
    37        self.mouse_handlers: defaultdict[int, defaultdict[int, MouseHandler]] = ( 
    38            defaultdict(lambda: defaultdict(lambda: dummy_callback)) 
    39        ) 
    40 
    41    def set_mouse_handler_for_range( 
    42        self, 
    43        x_min: int, 
    44        x_max: int, 
    45        y_min: int, 
    46        y_max: int, 
    47        handler: Callable[[MouseEvent], NotImplementedOrNone], 
    48    ) -> None: 
    49        """ 
    50        Set mouse handler for a region. 
    51        """ 
    52        for y in range(y_min, y_max): 
    53            row = self.mouse_handlers[y] 
    54 
    55            for x in range(x_min, x_max): 
    56                row[x] = handler