Skip to content

Commit

Permalink
Merge branch 'main' into improve-nested-tcss
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigogiraoserrao authored Feb 7, 2024
2 parents 8c3f3ba + b28ad50 commit 3313787
Show file tree
Hide file tree
Showing 58 changed files with 2,360 additions and 429 deletions.
50 changes: 48 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,50 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Improve support for selector lists in nested TCSS https://github.com/Textualize/textual/issues/3969
- Improve support for rule declarations after nested TCSS rule sets https://github.com/Textualize/textual/issues/3999

## [0.48.0] - 2023-02-01
## [0.49.0] - 2024-02-07

### Fixed

- Fixed scrolling in long `OptionList` by adding max height of 100% https://github.com/Textualize/textual/issues/4021
- Fixed `DirectoryTree.clear_node` not clearing the node specified https://github.com/Textualize/textual/issues/4122

### Changed

- `DirectoryTree.reload` and `DirectoryTree.reload_node` now preserve state when reloading https://github.com/Textualize/textual/issues/4056
- Fixed a crash in the TextArea when performing a backward replace https://github.com/Textualize/textual/pull/4126
- Fixed selection not updating correctly when pasting while there's a non-zero selection https://github.com/Textualize/textual/pull/4126
- Breaking change: `TextArea` will not use `Escape` to shift focus if the `tab_behaviour` is the default https://github.com/Textualize/textual/issues/4110
- `TextArea` cursor will now be invisible before first focus https://github.com/Textualize/textual/pull/4128
- Fix toggling `TextArea.cursor_blink` reactive when widget does not have focus https://github.com/Textualize/textual/pull/4128

### Added

- Added DOMQuery.set https://github.com/Textualize/textual/pull/4075
- Added DOMNode.set_reactive https://github.com/Textualize/textual/pull/4075
- Added DOMNode.data_bind https://github.com/Textualize/textual/pull/4075
- Added DOMNode.action_toggle https://github.com/Textualize/textual/pull/4075
- Added Worker.cancelled_event https://github.com/Textualize/textual/pull/4075
- `Tree` (and `DirectoryTree`) grew an attribute `lock` that can be used for synchronization across coroutines https://github.com/Textualize/textual/issues/4056


## [0.48.2] - 2024-02-02

### Fixed

- Fixed a hang in the Linux driver when connected to a pipe https://github.com/Textualize/textual/issues/4104
- Fixed broken `OptionList` `Option.id` mappings https://github.com/Textualize/textual/issues/4101

### Changed

- Breaking change: keyboard navigation in `RadioSet`, `ListView`, `OptionList`, and `SelectionList`, no longer allows highlighting disabled items https://github.com/Textualize/textual/issues/3881

## [0.48.1] - 2024-02-01

### Fixed

- `TextArea` uses CSS theme by default instead of `monokai` https://github.com/Textualize/textual/pull/4091

## [0.48.0] - 2024-02-01

### Changed

Expand Down Expand Up @@ -60,7 +103,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fixed display of keys when used in conjunction with other keys https://github.com/Textualize/textual/pull/3050
- Fixed double detection of <kbd>Escape</kbd> on Windows https://github.com/Textualize/textual/issues/4038

## [0.47.1] - 2023-01-05
## [0.47.1] - 2024-01-05

### Fixed

Expand Down Expand Up @@ -1628,6 +1671,9 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
- New handler system for messages that doesn't require inheritance
- Improved traceback handling

[0.49.0]: https://github.com/Textualize/textual/compare/v0.48.2...v0.49.0
[0.48.2]: https://github.com/Textualize/textual/compare/v0.48.1...v0.48.2
[0.48.1]: https://github.com/Textualize/textual/compare/v0.48.0...v0.48.1
[0.48.0]: https://github.com/Textualize/textual/compare/v0.47.1...v0.48.0
[0.47.1]: https://github.com/Textualize/textual/compare/v0.47.0...v0.47.1
[0.47.0]: https://github.com/Textualize/textual/compare/v0.46.0...v0.47.0
Expand Down
67 changes: 67 additions & 0 deletions docs/examples/guide/reactivity/set_reactive01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.reactive import reactive, var
from textual.widgets import Label

GREETINGS = [
"Bonjour",
"Hola",
"こんにちは",
"你好",
"안녕하세요",
"Hello",
]


class Greeter(Horizontal):
"""Display a greeting and a name."""

DEFAULT_CSS = """
Greeter {
width: auto;
height: 1;
& Label {
margin: 0 1;
}
}
"""
greeting: reactive[str] = reactive("")
who: reactive[str] = reactive("")

def __init__(self, greeting: str = "Hello", who: str = "World!") -> None:
super().__init__()
self.greeting = greeting # (1)!
self.who = who

def compose(self) -> ComposeResult:
yield Label(self.greeting, id="greeting")
yield Label(self.who, id="name")

def watch_greeting(self, greeting: str) -> None:
self.query_one("#greeting", Label).update(greeting) # (2)!

def watch_who(self, who: str) -> None:
self.query_one("#who", Label).update(who)


class NameApp(App):

CSS = """
Screen {
align: center middle;
}
"""
greeting_no: var[int] = var(0)
BINDINGS = [("space", "greeting")]

def compose(self) -> ComposeResult:
yield Greeter(who="Textual")

def action_greeting(self) -> None:
self.greeting_no = (self.greeting_no + 1) % len(GREETINGS)
self.query_one(Greeter).greeting = GREETINGS[self.greeting_no]


if __name__ == "__main__":
app = NameApp()
app.run()
67 changes: 67 additions & 0 deletions docs/examples/guide/reactivity/set_reactive02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.reactive import reactive, var
from textual.widgets import Label

GREETINGS = [
"Bonjour",
"Hola",
"こんにちは",
"你好",
"안녕하세요",
"Hello",
]


class Greeter(Horizontal):
"""Display a greeting and a name."""

DEFAULT_CSS = """
Greeter {
width: auto;
height: 1;
& Label {
margin: 0 1;
}
}
"""
greeting: reactive[str] = reactive("")
who: reactive[str] = reactive("")

def __init__(self, greeting: str = "Hello", who: str = "World!") -> None:
super().__init__()
self.set_reactive(Greeter.greeting, greeting) # (1)!
self.set_reactive(Greeter.who, who)

def compose(self) -> ComposeResult:
yield Label(self.greeting, id="greeting")
yield Label(self.who, id="name")

def watch_greeting(self, greeting: str) -> None:
self.query_one("#greeting", Label).update(greeting)

def watch_who(self, who: str) -> None:
self.query_one("#who", Label).update(who)


class NameApp(App):

CSS = """
Screen {
align: center middle;
}
"""
greeting_no: var[int] = var(0)
BINDINGS = [("space", "greeting")]

def compose(self) -> ComposeResult:
yield Greeter(who="Textual")

def action_greeting(self) -> None:
self.greeting_no = (self.greeting_no + 1) % len(GREETINGS)
self.query_one(Greeter).greeting = GREETINGS[self.greeting_no]


if __name__ == "__main__":
app = NameApp()
app.run()
52 changes: 52 additions & 0 deletions docs/examples/guide/reactivity/world_clock01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from datetime import datetime

from pytz import timezone

from textual.app import App, ComposeResult
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Digits, Label


class WorldClock(Widget):

time: reactive[datetime] = reactive(datetime.now)

def __init__(self, timezone: str) -> None:
self.timezone = timezone
super().__init__()

def compose(self) -> ComposeResult:
yield Label(self.timezone)
yield Digits()

def watch_time(self, time: datetime) -> None:
localized_time = time.astimezone(timezone(self.timezone))
self.query_one(Digits).update(localized_time.strftime("%H:%M:%S"))


class WorldClockApp(App):
CSS_PATH = "world_clock01.tcss"

time: reactive[datetime] = reactive(datetime.now)

def compose(self) -> ComposeResult:
yield WorldClock("Europe/London")
yield WorldClock("Europe/Paris")
yield WorldClock("Asia/Tokyo")

def update_time(self) -> None:
self.time = datetime.now()

def watch_time(self, time: datetime) -> None:
for world_clock in self.query(WorldClock): # (1)!
world_clock.time = time

def on_mount(self) -> None:
self.update_time()
self.set_interval(1, self.update_time)


if __name__ == "__main__":
app = WorldClockApp()
app.run()
16 changes: 16 additions & 0 deletions docs/examples/guide/reactivity/world_clock01.tcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Screen {
align: center middle;
}

WorldClock {
width: auto;
height: auto;
padding: 1 2;
background: $panel;
border: wide $background;

& Digits {
width: auto;
color: $secondary;
}
}
47 changes: 47 additions & 0 deletions docs/examples/guide/reactivity/world_clock02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from datetime import datetime

from pytz import timezone

from textual.app import App, ComposeResult
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Digits, Label


class WorldClock(Widget):

time: reactive[datetime] = reactive(datetime.now)

def __init__(self, timezone: str) -> None:
self.timezone = timezone
super().__init__()

def compose(self) -> ComposeResult:
yield Label(self.timezone)
yield Digits()

def watch_time(self, time: datetime) -> None:
localized_time = time.astimezone(timezone(self.timezone))
self.query_one(Digits).update(localized_time.strftime("%H:%M:%S"))


class WorldClockApp(App):
CSS_PATH = "world_clock01.tcss"

time: reactive[datetime] = reactive(datetime.now)

def compose(self) -> ComposeResult:
yield WorldClock("Europe/London").data_bind(WorldClockApp.time) # (1)!
yield WorldClock("Europe/Paris").data_bind(WorldClockApp.time)
yield WorldClock("Asia/Tokyo").data_bind(WorldClockApp.time)

def update_time(self) -> None:
self.time = datetime.now()

def on_mount(self) -> None:
self.update_time()
self.set_interval(1, self.update_time)


if __name__ == "__main__":
WorldClockApp().run()
49 changes: 49 additions & 0 deletions docs/examples/guide/reactivity/world_clock03.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from datetime import datetime

from pytz import timezone

from textual.app import App, ComposeResult
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Digits, Label


class WorldClock(Widget):

clock_time: reactive[datetime] = reactive(datetime.now)

def __init__(self, timezone: str) -> None:
self.timezone = timezone
super().__init__()

def compose(self) -> ComposeResult:
yield Label(self.timezone)
yield Digits()

def watch_clock_time(self, time: datetime) -> None:
localized_time = time.astimezone(timezone(self.timezone))
self.query_one(Digits).update(localized_time.strftime("%H:%M:%S"))


class WorldClockApp(App):
CSS_PATH = "world_clock01.tcss"

time: reactive[datetime] = reactive(datetime.now)

def compose(self) -> ComposeResult:
yield WorldClock("Europe/London").data_bind(
clock_time=WorldClockApp.time # (1)!
)
yield WorldClock("Europe/Paris").data_bind(clock_time=WorldClockApp.time)
yield WorldClock("Asia/Tokyo").data_bind(clock_time=WorldClockApp.time)

def update_time(self) -> None:
self.time = datetime.now()

def on_mount(self) -> None:
self.update_time()
self.set_interval(1, self.update_time)


if __name__ == "__main__":
WorldClockApp().run()
2 changes: 1 addition & 1 deletion docs/examples/widgets/text_area_custom_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class HelloWorld {

class TextAreaCustomLanguage(App):
def compose(self) -> ComposeResult:
text_area = TextArea(text=java_code)
text_area = TextArea.code_editor(text=java_code)
text_area.cursor_blink = False

# Register the Java language and highlight query
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/widgets/text_area_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def goodbye(name):

class TextAreaExample(App):
def compose(self) -> ComposeResult:
yield TextArea(TEXT, language="python")
yield TextArea.code_editor(TEXT, language="python")


app = TextAreaExample()
Expand Down
Loading

0 comments on commit 3313787

Please sign in to comment.