def test_list(self): title = to_formatted_text("Title", style="bg:red") elements = [ ListElement("One", on_select=lambda: print("Select")), ListElement("Two"), ListElement("Three", on_focus=lambda: print("Focus")), ] list = List( title=title, elements=elements, ) assert list.title_window.text == "Title" expected = dedent(""" One Two Three """).strip() assert to_text(list.list_window) == expected list.next() assert list.current_element.text == "Two" assert to_text(list.list_window) == expected list.previous() assert list.current_element.text == "One" assert to_text(list.list_window) == expected list.focus(2) assert list.current_element.text == "Three" assert to_text(list.list_window) == expected list.select(0) assert list.current_element.text == "One" assert to_text(list.list_window) == expected list.select(1) assert list.current_element.text == "Two" assert to_text(list.list_window) == expected mouse_event = MouseEvent(Point(0, 0), MouseEventType.MOUSE_DOWN) list.mouse_select(index=0, mouse_event=mouse_event) assert list.current_element.text == "Two" assert to_text(list.list_window) == expected mouse_event.event_type = MouseEventType.MOUSE_UP list.mouse_select(index=0, mouse_event=mouse_event) assert list.current_element.text == "One" assert to_text(list.list_window) == expected
def _mouse(event: E) -> None: """ Handling of mouse events for Windows. """ assert is_windows() # This key binding should only exist for Windows. # Parse data. pieces = event.data.split(";") event_type = MouseEventType(pieces[0]) x = int(pieces[1]) y = int(pieces[2]) # Make coordinates absolute to the visible part of the terminal. output = event.app.renderer.output from prompt_toolkit.output.win32 import Win32Output if isinstance(output, Win32Output): screen_buffer_info = output.get_win32_screen_buffer_info() rows_above_cursor = ( screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y ) y -= rows_above_cursor # Call the mouse event handler. handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type))
def test_no_mouse_handler(self): mouse_event = MouseEvent(Point(0, 0), MouseEventType.MOUSE_UP) handler = mock.MagicMock() formatted_text = to_formatted_text([("", "hello"), ("", "world", lambda x: handler(x)) ]) text_area = FormattedTextArea(formatted_text) text_area.control.mouse_handler(mouse_event) handler.assert_not_called()
def new_handler(event: MouseEvent) -> None: new_event = MouseEvent( position=Point( x=event.position.x - xpos, y=event.position.y + self.vertical_scroll - ypos, ), event_type=event.event_type, ) handler(new_event)
def mouse_handler(cli, mouse_event): """ Wrapper around the mouse_handler of the `UIControl` that turns absolute coordinates into relative coordinates. """ position = mouse_event.position # Call the mouse handler of the UIControl first. self._mouse_handler( cli, MouseEvent(position=Point(x=position.x - write_position.xpos, y=position.y - write_position.ypos + vertical_scroll), event_type=mouse_event.event_type))
def test_mouse_handler(self): handler = mock.MagicMock() handler_two = mock.MagicMock() mouse_event = MouseEvent(Point(0, 0), MouseEventType.MOUSE_UP) formatted_text = to_formatted_text([ ("", "hello", lambda x: handler(x)), ("", "world", lambda x: handler_two(x)), ]) text_area = FormattedTextArea(formatted_text) # Click on first character. text_area.control.mouse_handler(mouse_event) handler.assert_called_once() handler_two.assert_not_called() # Click outside the text area. mouse_event = MouseEvent(Point(99, 99), MouseEventType.MOUSE_UP) handler.reset_mock() handler_two.reset_mock() text_area.control.mouse_handler(mouse_event) handler.assert_not_called() handler_two.assert_not_called()
def test_test_block_edit_action_none(self, click_edit): toc = self.chapters[1].toc() section = toc[1][0] renderer = Renderer(tui=self.tui, section=section, width=37) renderer.render() text = "He's the creator of something..." node = section.children[1] assert node.tagname == "TestBlock" assert node.text() == text click_edit.return_value = None mouse_event = MouseEvent(Point(0, 0), MouseEventType.MOUSE_UP) renderer._edit_action(node, mouse_event) click_edit.assert_called_once_with( text=text, extension=".txt", ) assert node.text() == text
def _(event: E) -> None: """ Handling of mouse events for Windows. """ assert is_windows() # This key binding should only exist for Windows. # Parse data. event_type, x, y = event.data.split(';') x = int(x) y = int(y) # Make coordinates absolute to the visible part of the terminal. screen_buffer_info = event.app.renderer.output.get_win32_screen_buffer_info() rows_above_cursor = screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y y -= rows_above_cursor # Call the mouse event handler. handler = event.app.renderer.mouse_handlers.mouse_handlers[x, y] handler(MouseEvent(position=Point(x=x, y=y), event_type=event_type))
def mouse_handler(cli, mouse_event): """ Wrapper around the mouse_handler of the `UIControl` that turns absolute coordinates into relative coordinates. """ position = mouse_event.position # Call the mouse handler of the UIControl first. result = self.content.mouse_handler( cli, MouseEvent(position=Point(x=position.x - write_position.xpos - sum(left_margin_widths), y=position.y - write_position.ypos + self.vertical_scroll), event_type=mouse_event.event_type)) # If it returns NotImplemented, handle it here. if result == NotImplemented: return self._mouse_handler(cli, mouse_event) return result
def _mouse(event: E) -> "NotImplementedOrNone": """ Handling of mouse events for Windows. """ # This key binding should only exist for Windows. if sys.platform == "win32": # Parse data. pieces = event.data.split(";") button = MouseButton(pieces[0]) event_type = MouseEventType(pieces[1]) x = int(pieces[2]) y = int(pieces[3]) # Make coordinates absolute to the visible part of the terminal. output = event.app.renderer.output from prompt_toolkit.output.win32 import Win32Output from prompt_toolkit.output.windows10 import Windows10_Output if isinstance(output, (Win32Output, Windows10_Output)): screen_buffer_info = output.get_win32_screen_buffer_info() rows_above_cursor = (screen_buffer_info.dwCursorPosition.Y - event.app.renderer._cursor_pos.y) y -= rows_above_cursor # Call the mouse event handler. # (Can return `NotImplemented`.) handler = event.app.renderer.mouse_handlers.mouse_handlers[y][ x] return handler( MouseEvent( position=Point(x=x, y=y), event_type=event_type, button=button, modifiers=UNKNOWN_MODIFIER, )) # No mouse handler found. Return `NotImplemented` so that we don't # invalidate the UI. return NotImplemented
def _(event): """ Handling of incoming mouse event. """ # Typical: "Esc[MaB*" # Urxvt: "Esc[96;14;13M" # Xterm SGR: "Esc[<64;85;12M" # Parse incoming packet. if event.data[2] == 'M': # Typical. mouse_event, x, y = map(ord, event.data[3:]) mouse_event = { 32: MouseEventType.MOUSE_DOWN, 35: MouseEventType.MOUSE_UP, 96: MouseEventType.SCROLL_UP, 97: MouseEventType.SCROLL_DOWN, }.get(mouse_event) # Handle situations where `PosixStdinReader` used surrogateescapes. if x >= 0xdc00: x-= 0xdc00 if y >= 0xdc00: y-= 0xdc00 x -= 32 y -= 32 else: # Urxvt and Xterm SGR. # When the '<' is not present, we are not using the Xterm SGR mode, # but Urxvt instead. data = event.data[2:] if data[:1] == '<': sgr = True data = data[1:] else: sgr = False # Extract coordinates. mouse_event, x, y = map(int, data[:-1].split(';')) m = data[-1] # Parse event type. if sgr: mouse_event = { (0, 'M'): MouseEventType.MOUSE_DOWN, (0, 'm'): MouseEventType.MOUSE_UP, (64, 'M'): MouseEventType.SCROLL_UP, (65, 'M'): MouseEventType.SCROLL_DOWN, }.get((mouse_event, m)) else: mouse_event = { 32: MouseEventType.MOUSE_DOWN, 35: MouseEventType.MOUSE_UP, 96: MouseEventType.SCROLL_UP, 97: MouseEventType.SCROLL_DOWN, }.get(mouse_event) x -= 1 y -= 1 # Only handle mouse events when we know the window height. if event.cli.renderer.height_is_known and mouse_event is not None: # Take region above the layout into account. The reported # coordinates are absolute to the visible part of the terminal. try: y -= event.cli.renderer.rows_above_layout except HeightIsUnknownError: return # Call the mouse handler from the renderer. handler = event.cli.renderer.mouse_handlers.mouse_handlers[x,y] handler(event.cli, MouseEvent(position=Point(x=x, y=y), event_type=mouse_event))
def _(event: E) -> "NotImplementedOrNone": """ Handling of incoming mouse event. """ # TypicaL: "eSC[MaB*" # Urxvt: "Esc[96;14;13M" # Xterm SGR: "Esc[<64;85;12M" # Parse incoming packet. if event.data[2] == "M": # Typical. mouse_event, x, y = map(ord, event.data[3:]) # TODO: Is it possible to add modifiers here? mouse_button, mouse_event_type, mouse_modifiers = typical_mouse_events[ mouse_event] # Handle situations where `PosixStdinReader` used surrogateescapes. if x >= 0xDC00: x -= 0xDC00 if y >= 0xDC00: y -= 0xDC00 x -= 32 y -= 32 else: # Urxvt and Xterm SGR. # When the '<' is not present, we are not using the Xterm SGR mode, # but Urxvt instead. data = event.data[2:] if data[:1] == "<": sgr = True data = data[1:] else: sgr = False # Extract coordinates. mouse_event, x, y = map(int, data[:-1].split(";")) m = data[-1] # Parse event type. if sgr: try: ( mouse_button, mouse_event_type, mouse_modifiers, ) = xterm_sgr_mouse_events[mouse_event, m] except KeyError: return NotImplemented else: # Some other terminals, like urxvt, Hyper terminal, ... ( mouse_button, mouse_event_type, mouse_modifiers, ) = urxvt_mouse_events.get( mouse_event, (UNKNOWN_BUTTON, MOUSE_MOVE, UNKNOWN_MODIFIER)) x -= 1 y -= 1 # Only handle mouse events when we know the window height. if event.app.renderer.height_is_known and mouse_event_type is not None: # Take region above the layout into account. The reported # coordinates are absolute to the visible part of the terminal. from prompt_toolkit.renderer import HeightIsUnknownError try: y -= event.app.renderer.rows_above_layout except HeightIsUnknownError: return NotImplemented # Call the mouse handler from the renderer. # Note: This can return `NotImplemented` if no mouse handler was # found for this position, or if no repainting needs to # happen. this way, we avoid excessive repaints during mouse # movements. handler = event.app.renderer.mouse_handlers.mouse_handlers[y][x] return handler( MouseEvent( position=Point(x=x, y=y), event_type=mouse_event_type, button=mouse_button, modifiers=mouse_modifiers, )) return NotImplemented
def _(event: E) -> None: """ Handling of incoming mouse event. """ # TypicaL: "eSC[MaB*" # Urxvt: "Esc[96;14;13M" # Xterm SGR: "Esc[<64;85;12M" # Parse incoming packet. if event.data[2] == "M": # Typical. mouse_event, x, y = map(ord, event.data[3:]) # TODO: Is it possible to add modifiers here? mouse_button, mouse_event_type, mouse_modifier = typical_mouse_events[ mouse_event] # Handle situations where `PosixStdinReader` used surrogateescapes. if x >= 0xDC00: x -= 0xDC00 if y >= 0xDC00: y -= 0xDC00 x -= 32 y -= 32 else: # Urxvt and Xterm SGR. # When the '<' is not present, we are not using the Xterm SGR mode, # but Urxvt instead. data = event.data[2:] if data[:1] == "<": sgr = True data = data[1:] else: sgr = False # Extract coordinates. mouse_event, x, y = map(int, data[:-1].split(";")) m = data[-1] # Parse event type. if sgr: mouse_button, mouse_event_type, mouse_modifier = xterm_sgr_mouse_events[ mouse_event, m] else: # TODO: I don't know when this is triggered or how this mode works (though my Hyper terminal seems to use it), so I marked the buttons and modifiers UNKNOWN. # By replacing these UNKNOWN values with the correct values in urxvt_mouse_events, we can get more functionality in different terminal varieties mouse_button, mouse_event_type, mouse_modifier = urxvt_mouse_events.get( mouse_event, (UNKNOWN_BUTTON, MOUSE_MOVE, UNKNOWN_MODIFIER)) x -= 1 y -= 1 # Only handle mouse events when we know the window height. if event.app.renderer.height_is_known and mouse_event_type is not None: # Take region above the layout into account. The reported # coordinates are absolute to the visible part of the terminal. from prompt_toolkit.renderer import HeightIsUnknownError try: y -= event.app.renderer.rows_above_layout except HeightIsUnknownError: return # Call the mouse handler from the renderer. handler = event.app.renderer.mouse_handlers.mouse_handlers[y][x] handler( MouseEvent( position=Point(x=x, y=y), event_type=mouse_event_type, button=mouse_button, modifier=mouse_modifier, ))