Skip to content

Commit

Permalink
Merge branch 'main' into typing-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Mar 19, 2024
2 parents ee088ab + d3df9d0 commit 2d8f64c
Show file tree
Hide file tree
Showing 76 changed files with 2,923 additions and 937 deletions.
46 changes: 44 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

### Fixed

- Fixed a crash in `TextArea` when undoing an edit to a selection the selection was made backwards https://github.com/Textualize/textual/issues/4301

## [0.53.1] - 2023-03-18

### Fixed

- Fixed issue with data binding https://github.com/Textualize/textual/pull/4308

## [0.53.0] - 2023-03-18

### Added

- Mapping of ANSI colors to hex codes configurable via `App.ansi_theme_dark` and `App.ansi_theme_light` https://github.com/Textualize/textual/pull/4192
- `Pilot.resize_terminal` to resize the terminal in testing https://github.com/Textualize/textual/issues/4212
- Added `sort_children` method https://github.com/Textualize/textual/pull/4244
- Support for pseudo-classes in nested TCSS https://github.com/Textualize/textual/issues/4039

### Fixed

Expand All @@ -25,10 +40,33 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fixed `RichLog.min_width` not being used https://github.com/Textualize/textual/pull/4223
- Rename `CollapsibleTitle.action_toggle` to `action_toggle_collapsible` to fix clash with `DOMNode.action_toggle` https://github.com/Textualize/textual/pull/4221
- Markdown component classes weren't refreshed when watching for CSS https://github.com/Textualize/textual/issues/3464
- Rename `Switch.action_toggle` to `action_toggle_switch` to fix clash with `DOMNode.action_toggle` https://github.com/Textualize/textual/issues/4262
- Fixed `OptionList.OptionHighlighted` leaking out of `Select` https://github.com/Textualize/textual/issues/4224
- Fixed `Tab` enable/disable messages leaking into `TabbedContent` https://github.com/Textualize/textual/issues/4233
- Fixed a style leak from `TabbedContent` https://github.com/Textualize/textual/issues/4232
- Fixed active hidden scrollbars not releasing the mouse https://github.com/Textualize/textual/issues/4274
- Fixed the mouse not being released when hiding a `TextArea` while mouse selection is happening https://github.com/Textualize/textual/issues/4292
- Fix mouse scrolling not working when mouse cursor is over a disabled child widget https://github.com/Textualize/textual/issues/4242

### Added
### Changed

- `Pilot.resize_terminal` to resize the terminal in testing https://github.com/Textualize/textual/issues/4212
- Clicking a non focusable widget focus ancestors https://github.com/Textualize/textual/pull/4236
- BREAKING: widget class names must start with a capital letter or an underscore `_` https://github.com/Textualize/textual/pull/4252
- BREAKING: for many widgets, messages are now sent when programmatic changes that mirror user input are made https://github.com/Textualize/textual/pull/4256
- Changed `Collapsible`
- Changed `Markdown`
- Changed `Select`
- Changed `SelectionList`
- Changed `TabbedContent`
- Changed `Tabs`
- Changed `TextArea`
- Changed `Tree`
- Improved ETA calculation for ProgressBar https://github.com/Textualize/textual/pull/4271
- BREAKING: `AppFocus` and `AppBlur` are now posted when the terminal window gains or loses focus, if the terminal supports this https://github.com/Textualize/textual/pull/4265
- When the terminal window loses focus, the currently-focused widget will also lose focus.
- When the terminal window regains focus, the previously-focused widget will regain focus.
- TextArea binding for <kbd>ctrl</kbd>+<kbd>k</kbd> will now delete the line if the line is empty https://github.com/Textualize/textual/issues/4277
- The active tab (in `Tabs`) / tab pane (in `TabbedContent`) can now be unset https://github.com/Textualize/textual/issues/4241

## [0.52.1] - 2024-02-20

Expand Down Expand Up @@ -1755,6 +1793,10 @@ 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.53.1]: https://github.com/Textualize/textual/compare/v0.53.0...v0.53.1
[0.53.0]: https://github.com/Textualize/textual/compare/v0.52.1...v0.53.0
[0.52.1]: https://github.com/Textualize/textual/compare/v0.52.0...v0.52.1
[0.52.0]: https://github.com/Textualize/textual/compare/v0.51.0...v0.52.0
[0.51.0]: https://github.com/Textualize/textual/compare/v0.50.1...v0.51.0
[0.50.1]: https://github.com/Textualize/textual/compare/v0.50.0...v0.50.1
[0.50.0]: https://github.com/Textualize/textual/compare/v0.49.0...v0.50.0
Expand Down
6 changes: 6 additions & 0 deletions docs/blog/posts/toolong-retrospective.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ You register a file with a `Selector` object, then call `select()` which returns

See [watcher.py](https://github.com/Textualize/toolong/blob/main/src/toolong/watcher.py) in Toolong, which runs a thread to monitors files for changes with a selector.

!!! warning "Addendum"

So it turns out that watching regular files for changes with selectors only works with `KqueueSelector` which is the default on macOS.
Disappointingly, the Python docs aren't clear on this.
Toolong will use a polling approach where this selector is unavailable.

## Textual learnings

This project was a chance for me to "dogfood" Textual.
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/how-to/render_compose.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from time import time

from textual.app import App, ComposeResult, RenderableType
from textual.app import App, ComposeResult, RenderResult
from textual.containers import Container
from textual.renderables.gradient import LinearGradient
from textual.widgets import Static
Expand Down Expand Up @@ -41,7 +41,7 @@ def on_mount(self) -> None:
def compose(self) -> ComposeResult:
yield Static("Making a splash with Textual!") # (2)!

def render(self) -> RenderableType:
def render(self) -> RenderResult:
return LinearGradient(time() * 90, STOPS) # (3)!


Expand Down
16 changes: 11 additions & 5 deletions docs/examples/widgets/progress_bar_isolated_.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from textual.app import App, ComposeResult
from textual.clock import MockClock
from textual.containers import Center, Middle
from textual.timer import Timer
from textual.widgets import Footer, ProgressBar
Expand All @@ -11,13 +12,14 @@ class IndeterminateProgressBar(App[None]):
"""Timer to simulate progress happening."""

def compose(self) -> ComposeResult:
self.clock = MockClock()
with Center():
with Middle():
yield ProgressBar()
yield ProgressBar(clock=self.clock)
yield Footer()

def on_mount(self) -> None:
"""Set up a timer to simulate progess happening."""
"""Set up a timer to simulate progress happening."""
self.progress_timer = self.set_interval(1 / 10, self.make_progress, pause=True)

def make_progress(self) -> None:
Expand All @@ -31,14 +33,18 @@ def action_start(self) -> None:

def key_f(self) -> None:
# Freeze time for the indeterminate progress bar.
self.query_one(ProgressBar).query_one("#bar")._get_elapsed_time = lambda: 5
self.clock.set_time(5)
self.refresh()

def key_t(self) -> None:
# Freeze time to show always the same ETA.
self.query_one(ProgressBar).query_one("#eta")._get_elapsed_time = lambda: 3.9
self.query_one(ProgressBar).update(total=100, progress=39)
self.clock.set_time(0)
self.query_one(ProgressBar).update(total=100, progress=0)
self.clock.set_time(3.9)
self.query_one(ProgressBar).update(progress=39)

def key_u(self) -> None:
self.refresh()
self.query_one(ProgressBar).update(total=100, progress=100)


Expand Down
2 changes: 1 addition & 1 deletion docs/examples/widgets/progress_bar_styled.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def compose(self) -> ComposeResult:
yield Footer()

def on_mount(self) -> None:
"""Set up a timer to simulate progess happening."""
"""Set up a timer to simulate progress happening."""
self.progress_timer = self.set_interval(1 / 10, self.make_progress, pause=True)

def make_progress(self) -> None:
Expand Down
15 changes: 10 additions & 5 deletions docs/examples/widgets/progress_bar_styled_.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from textual.app import App, ComposeResult
from textual.clock import MockClock
from textual.containers import Center, Middle
from textual.timer import Timer
from textual.widgets import Footer, ProgressBar
Expand All @@ -12,13 +13,14 @@ class StyledProgressBar(App[None]):
"""Timer to simulate progress happening."""

def compose(self) -> ComposeResult:
self.clock = MockClock()
with Center():
with Middle():
yield ProgressBar()
yield ProgressBar(clock=self.clock)
yield Footer()

def on_mount(self) -> None:
"""Set up a timer to simulate progess happening."""
"""Set up a timer to simulate progress happening."""
self.progress_timer = self.set_interval(1 / 10, self.make_progress, pause=True)

def make_progress(self) -> None:
Expand All @@ -29,15 +31,18 @@ def action_start(self) -> None:
"""Start the progress tracking."""
self.query_one(ProgressBar).update(total=100)
self.progress_timer.resume()
self.query_one(ProgressBar).refresh()

def key_f(self) -> None:
# Freeze time for the indeterminate progress bar.
self.query_one(ProgressBar).query_one("#bar")._get_elapsed_time = lambda: 5
self.clock.set_time(5.0)

def key_t(self) -> None:
# Freeze time to show always the same ETA.
self.query_one(ProgressBar).query_one("#eta")._get_elapsed_time = lambda: 3.9
self.query_one(ProgressBar).update(total=100, progress=39)
self.clock.set_time(0)
self.query_one(ProgressBar).update(total=100, progress=0)
self.clock.set_time(3.9)
self.query_one(ProgressBar).update(progress=39)

def key_u(self) -> None:
self.query_one(ProgressBar).update(total=100, progress=100)
Expand Down
9 changes: 9 additions & 0 deletions docs/widgets/loading_indicator.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ Displays pulsating dots to indicate when data is being loaded.
- [ ] Focusable
- [ ] Container


!!! tip

Widgets have a [`loading`][textual.widget.Widget.loading] reactive which
you can use to temporarily replace your widget with a `LoadingIndicator`.
See the [Loading Indicator](../guide/widgets.md#loading-indicator) section
in the Widgets guide for details.


## Example

Simple usage example:
Expand Down
1 change: 1 addition & 0 deletions docs/widgets/tabbed_content.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ For example, to create a `TabbedContent` that has red and green labels:

## Messages

- [TabbedContent.Cleared][textual.widgets.TabbedContent.Cleared]
- [TabbedContent.TabActivated][textual.widgets.TabbedContent.TabActivated]

## Bindings
Expand Down
4 changes: 2 additions & 2 deletions mkdocs-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ nav:
- "events/screen_suspend.md"
- "events/show.md"
- Styles:
- "styles/index.md"
- "styles/align.md"
- "styles/background.md"
- "styles/border.md"
Expand All @@ -83,8 +84,6 @@ nav:
- "styles/content_align.md"
- "styles/display.md"
- "styles/dock.md"
- "styles/index.md"
- "styles/keyline.md"
- Grid:
- "styles/grid/index.md"
- "styles/grid/column_span.md"
Expand All @@ -94,6 +93,7 @@ nav:
- "styles/grid/grid_size.md"
- "styles/grid/row_span.md"
- "styles/height.md"
- "styles/keyline.md"
- "styles/layer.md"
- "styles/layers.md"
- "styles/layout.md"
Expand Down
Loading

0 comments on commit 2d8f64c

Please sign in to comment.