mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge branch 'main' into sleep-tweak
This commit is contained in:
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [0.10.0] - Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `MouseScrollUp` and `MouseScrollDown` now inherit from `MouseEvent` and have attached modifier keys. https://github.com/Textualize/textual/pull/1458
|
||||||
|
|
||||||
## [0.9.1] - 2022-12-30
|
## [0.9.1] - 2022-12-30
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ The first argument to `reactive` may be a default value or a callable that retur
|
|||||||
The `time` attribute has a simple float as the default value, so `self.time` will be `0` on start.
|
The `time` attribute has a simple float as the default value, so `self.time` will be `0` on start.
|
||||||
|
|
||||||
|
|
||||||
The `on_mount` method is an event handler called then the widget is first added to the application (or _mounted_). In this method we call [set_interval()][textual.message_pump.MessagePump.set_interval] to create a timer which calls `self.update_time` sixty times a second. This `update_time` method calculates the time elapsed since the widget started and assigns it to `self.time`. Which brings us to one of Reactive's super-powers.
|
The `on_mount` method is an event handler called when the widget is first added to the application (or _mounted_). In this method we call [set_interval()][textual.message_pump.MessagePump.set_interval] to create a timer which calls `self.update_time` sixty times a second. This `update_time` method calculates the time elapsed since the widget started and assigns it to `self.time`. Which brings us to one of Reactive's super-powers.
|
||||||
|
|
||||||
If you implement a method that begins with `watch_` followed by the name of a reactive attribute (making it a _watch method_), that method will be called when the attribute is modified.
|
If you implement a method that begins with `watch_` followed by the name of a reactive attribute (making it a _watch method_), that method will be called when the attribute is modified.
|
||||||
|
|
||||||
|
|||||||
@@ -54,24 +54,28 @@ class XTermParser(Parser[events.Event]):
|
|||||||
if sgr_match:
|
if sgr_match:
|
||||||
_buttons, _x, _y, state = sgr_match.groups()
|
_buttons, _x, _y, state = sgr_match.groups()
|
||||||
buttons = int(_buttons)
|
buttons = int(_buttons)
|
||||||
button = (buttons + 1) & 3
|
|
||||||
x = int(_x) - 1
|
x = int(_x) - 1
|
||||||
y = int(_y) - 1
|
y = int(_y) - 1
|
||||||
delta_x = x - self.last_x
|
delta_x = x - self.last_x
|
||||||
delta_y = y - self.last_y
|
delta_y = y - self.last_y
|
||||||
self.last_x = x
|
self.last_x = x
|
||||||
self.last_y = y
|
self.last_y = y
|
||||||
event: events.Event
|
event_class: type[events.MouseEvent]
|
||||||
|
|
||||||
if buttons & 64:
|
if buttons & 64:
|
||||||
event = (
|
event_class = (
|
||||||
events.MouseScrollUp if button == 1 else events.MouseScrollDown
|
events.MouseScrollDown if buttons & 1 else events.MouseScrollUp
|
||||||
)(sender, x, y)
|
)
|
||||||
|
button = 0
|
||||||
else:
|
else:
|
||||||
event = (
|
if buttons & 32:
|
||||||
events.MouseMove
|
event_class = events.MouseMove
|
||||||
if buttons & 32
|
else:
|
||||||
else (events.MouseDown if state == "M" else events.MouseUp)
|
event_class = events.MouseDown if state == "M" else events.MouseUp
|
||||||
)(
|
|
||||||
|
button = (buttons + 1) & 3
|
||||||
|
|
||||||
|
event = event_class(
|
||||||
sender,
|
sender,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
|||||||
@@ -419,22 +419,14 @@ class MouseUp(MouseEvent, bubble=True, verbose=True):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MouseScrollDown(InputEvent, bubble=True, verbose=True):
|
@rich.repr.auto
|
||||||
__slots__ = ["x", "y"]
|
class MouseScrollDown(MouseEvent, bubble=True):
|
||||||
|
pass
|
||||||
def __init__(self, sender: MessageTarget, x: int, y: int) -> None:
|
|
||||||
super().__init__(sender)
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
|
|
||||||
|
|
||||||
class MouseScrollUp(InputEvent, bubble=True, verbose=True):
|
@rich.repr.auto
|
||||||
__slots__ = ["x", "y"]
|
class MouseScrollUp(MouseEvent, bubble=True):
|
||||||
|
pass
|
||||||
def __init__(self, sender: MessageTarget, x: int, y: int) -> None:
|
|
||||||
super().__init__(sender)
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
|
|
||||||
|
|
||||||
class Click(MouseEvent, bubble=True):
|
class Click(MouseEvent, bubble=True):
|
||||||
|
|||||||
@@ -236,14 +236,14 @@ def test_mouse_move(parser, sequence, shift, meta, button):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"sequence",
|
"sequence, shift, meta",
|
||||||
[
|
[
|
||||||
"\x1b[<64;18;25M",
|
("\x1b[<64;18;25M", False, False),
|
||||||
"\x1b[<68;18;25M",
|
("\x1b[<68;18;25M", True, False),
|
||||||
"\x1b[<72;18;25M",
|
("\x1b[<72;18;25M", False, True),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_mouse_scroll_up(parser, sequence):
|
def test_mouse_scroll_up(parser, sequence, shift, meta):
|
||||||
"""Scrolling the mouse with and without modifiers held down.
|
"""Scrolling the mouse with and without modifiers held down.
|
||||||
We don't currently capture modifier keys in scroll events.
|
We don't currently capture modifier keys in scroll events.
|
||||||
"""
|
"""
|
||||||
@@ -256,17 +256,19 @@ def test_mouse_scroll_up(parser, sequence):
|
|||||||
assert isinstance(event, MouseScrollUp)
|
assert isinstance(event, MouseScrollUp)
|
||||||
assert event.x == 17
|
assert event.x == 17
|
||||||
assert event.y == 24
|
assert event.y == 24
|
||||||
|
assert event.shift is shift
|
||||||
|
assert event.meta is meta
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"sequence",
|
"sequence, shift, meta",
|
||||||
[
|
[
|
||||||
"\x1b[<65;18;25M",
|
("\x1b[<65;18;25M", False, False),
|
||||||
"\x1b[<69;18;25M",
|
("\x1b[<69;18;25M", True, False),
|
||||||
"\x1b[<73;18;25M",
|
("\x1b[<73;18;25M", False, True),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_mouse_scroll_down(parser, sequence):
|
def test_mouse_scroll_down(parser, sequence, shift, meta):
|
||||||
events = list(parser.feed(sequence))
|
events = list(parser.feed(sequence))
|
||||||
|
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
@@ -276,6 +278,8 @@ def test_mouse_scroll_down(parser, sequence):
|
|||||||
assert isinstance(event, MouseScrollDown)
|
assert isinstance(event, MouseScrollDown)
|
||||||
assert event.x == 17
|
assert event.x == 17
|
||||||
assert event.y == 24
|
assert event.y == 24
|
||||||
|
assert event.shift is shift
|
||||||
|
assert event.meta is meta
|
||||||
|
|
||||||
|
|
||||||
def test_mouse_event_detected_but_info_not_parsed(parser):
|
def test_mouse_event_detected_but_info_not_parsed(parser):
|
||||||
|
|||||||
Reference in New Issue
Block a user