Skip to content

Commit

Permalink
Merge pull request #5238 from Textualize/demo-polish
Browse files Browse the repository at this point in the history
Demo polish
  • Loading branch information
willmcgugan authored Nov 16, 2024
2 parents e8b1c21 + 060ae89 commit 495df59
Show file tree
Hide file tree
Showing 48 changed files with 1,733 additions and 945 deletions.
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased
## [0.86.0]

### Fixed

Expand All @@ -30,6 +30,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `textual.theme.ThemeProvider`, a command palette provider which returns all registered themes https://github.com/Textualize/textual/pull/5087
- Added several new built-in CSS variables https://github.com/Textualize/textual/pull/5087
- Added support for in-band terminal resize protocol https://github.com/Textualize/textual/pull/5217
- Added TEXTUAL_THEME environment var, which should be a comma separated list of desired themes https://github.com/Textualize/textual/pull/5238
- Added `Widget.is_scrolling` https://github.com/Textualize/textual/pull/5238
- Added `Tree.add_json` https://github.com/Textualize/textual/pull/5238

### Changed

Expand All @@ -38,12 +41,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `can_focus` and `can_focus_children` parameters to scrollable container types. https://github.com/Textualize/textual/pull/5226
- Added `textual.lazy.Reveal` https://github.com/Textualize/textual/pull/5226
- Added `Screen.action_blur` https://github.com/Textualize/textual/pull/5226

### Changed

- `Click` events can now be used with the on decorator to match the originally clicked widget https://github.com/Textualize/textual/pull/5238
- Breaking change: Removed `App.dark` reactive attribute https://github.com/Textualize/textual/pull/5087
- Breaking change: To improve consistency, several changes have been made to default widget CSS and the CSS variables which ship with Textual. On upgrading, your app will likely look different. All of these changes can be overidden with your own CSS. https://github.com/Textualize/textual/pull/5087

### Removed

- Removed `App.HOVER_EFFECTS_SCROLL_PAUSE` https://github.com/Textualize/textual/pull/5238

## [0.85.2] - 2024-11-02

- Fixed broken focus-within https://github.com/Textualize/textual/pull/5190
Expand Down Expand Up @@ -2532,6 +2537,7 @@ 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.86.0]: https://github.com/Textualize/textual/compare/v0.85.2...v0.86.0
[0.85.2]: https://github.com/Textualize/textual/compare/v0.85.1...v0.85.2
[0.85.1]: https://github.com/Textualize/textual/compare/v0.85.0...v0.85.1
[0.85.0]: https://github.com/Textualize/textual/compare/v0.84.0...v0.85.0
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "textual"
version = "0.85.2"
version = "0.86.0"
homepage = "https://github.com/Textualize/textual"
repository = "https://github.com/Textualize/textual"
documentation = "https://textual.textualize.io/"
Expand Down
1 change: 1 addition & 0 deletions src/textual/_xterm_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def parse_mouse_code(self, code: str) -> Message | None:
event_class = events.MouseDown if state == "M" else events.MouseUp

event = event_class(
None,
x,
y,
delta_x,
Expand Down
54 changes: 13 additions & 41 deletions src/textual/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,6 @@ class MyApp(App[None]):
SUSPENDED_SCREEN_CLASS: ClassVar[str] = ""
"""Class to apply to suspended screens, or empty string for no class."""

HOVER_EFFECTS_SCROLL_PAUSE: ClassVar[float] = 0.2
"""Seconds to pause hover effects for when scrolling."""

_PSEUDO_CLASSES: ClassVar[dict[str, Callable[[App[Any]], bool]]] = {
"focus": lambda app: app.app_focus,
"blur": lambda app: not app.app_focus,
Expand All @@ -487,7 +484,7 @@ class MyApp(App[None]):
get focus when the terminal widget has focus.
"""

theme: Reactive[str] = Reactive("textual-dark")
theme: Reactive[str] = Reactive(constants.DEFAULT_THEME)
"""The name of the currently active theme."""

ansi_theme_dark = Reactive(MONOKAI, init=False)
Expand Down Expand Up @@ -760,9 +757,6 @@ def __init__(
self._previous_inline_height: int | None = None
"""Size of previous inline update."""

self._paused_hover_effects: bool = False
"""Have the hover effects been paused?"""

self._hover_effects_timer: Timer | None = None

self._resize_event: events.Resize | None = None
Expand Down Expand Up @@ -1195,12 +1189,17 @@ def get_theme(self, theme_name: str) -> Theme | None:
"""Get a theme by name.
Args:
theme_name: The name of the theme to get.
theme_name: The name of the theme to get. May also be a comma
separated list of names, to pick the first available theme.
Returns:
A Theme instance and None if the theme doesn't exist.
"""
return self.available_themes[theme_name]
theme_names = [token.strip() for token in theme_name.split(",")]
for theme_name in theme_names:
if theme_name in self.available_themes:
return self.available_themes[theme_name]
return None

def register_theme(self, theme: Theme) -> None:
"""Register a theme with the app.
Expand Down Expand Up @@ -1236,6 +1235,8 @@ def available_themes(self) -> dict[str, Theme]:
@property
def current_theme(self) -> Theme:
theme = self.get_theme(self.theme)
if theme is None:
theme = self.get_theme("textual-dark")
assert theme is not None # validated by _validate_theme
return theme

Expand Down Expand Up @@ -2817,43 +2818,12 @@ def set_focus(self, widget: Widget | None, scroll_visible: bool = True) -> None:
"""
self.screen.set_focus(widget, scroll_visible)

def _pause_hover_effects(self):
"""Pause any hover effects based on Enter and Leave events for 200ms."""
if not self.HOVER_EFFECTS_SCROLL_PAUSE or self.is_headless:
return
self._paused_hover_effects = True
if self._hover_effects_timer is None:
self._hover_effects_timer = self.set_interval(
self.HOVER_EFFECTS_SCROLL_PAUSE, self._resume_hover_effects
)
else:
self._hover_effects_timer.reset()
self._hover_effects_timer.resume()

def _resume_hover_effects(self):
"""Resume sending Enter and Leave for hover effects."""
if not self.HOVER_EFFECTS_SCROLL_PAUSE or self.is_headless:
return
if self._paused_hover_effects:
self._paused_hover_effects = False
if self._hover_effects_timer is not None:
self._hover_effects_timer.pause()
try:
widget, _ = self.screen.get_widget_at(*self.mouse_position)
except NoWidget:
pass
else:
if widget is not self.mouse_over:
self._set_mouse_over(widget)

def _set_mouse_over(self, widget: Widget | None) -> None:
"""Called when the mouse is over another widget.
Args:
widget: Widget under mouse, or None for no widgets.
"""
if self._paused_hover_effects:
return
if widget is None:
if self.mouse_over is not None:
try:
Expand Down Expand Up @@ -3712,7 +3682,9 @@ async def on_event(self, event: events.Event) -> None:
self.get_widget_at(event.x, event.y)[0]
is self._mouse_down_widget
):
click_event = events.Click.from_event(event)
click_event = events.Click.from_event(
self._mouse_down_widget, event
)
self.screen._forward_event(click_event)
except NoWidget:
pass
Expand Down
3 changes: 2 additions & 1 deletion src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ class CommandPalette(SystemModalScreen[None]):
CommandPalette > .command-palette--help-text {
color: $text-muted;
background: transparent;
text-style: not bold dim;
text-style: not bold;
}
CommandPalette > .command-palette--highlight {
Expand All @@ -571,6 +571,7 @@ class CommandPalette(SystemModalScreen[None]):
height: 100%;
visibility: hidden;
background: $surface;
&:dark { background: $panel-darken-1; }
}
CommandPalette #--input {
Expand Down
5 changes: 5 additions & 0 deletions src/textual/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,8 @@ def _get_textual_animations() -> AnimationLevel:
"""The time threshold (in milliseconds) after which a warning is logged
if message processing exceeds this duration.
"""

DEFAULT_THEME: Final[str] = get_environ("TEXTUAL_THEME", "textual-dark")
"""Textual theme to make default. More than one theme may be specified in a comma separated list.
Textual will use the first theme that exists.
"""
9 changes: 9 additions & 0 deletions src/textual/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def __init__(
disabled: bool = False,
can_focus: bool | None = None,
can_focus_children: bool | None = None,
can_maximize: bool | None = None,
) -> None:
"""
Expand All @@ -93,6 +94,7 @@ def __init__(
disabled: Whether the widget is disabled or not.
can_focus: Can this container be focused?
can_focus_children: Can this container's children be focused?
can_maximized: Allow this container to maximize? `None` to use default logic.,
"""

super().__init__(
Expand All @@ -106,6 +108,13 @@ def __init__(
self.can_focus = can_focus
if can_focus_children is not None:
self.can_focus_children = can_focus_children
self.can_maximize = can_maximize

@property
def allow_maximize(self) -> bool:
if self.can_maximize is None:
return super().allow_maximize
return self.can_maximize


class Vertical(Widget, inherit_bindings=False):
Expand Down
5 changes: 4 additions & 1 deletion src/textual/css/stylesheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,10 @@ def apply(
node._has_hover_style = "hover" in all_pseudo_classes
node._has_focus_within = "focus-within" in all_pseudo_classes
node._has_order_style = not all_pseudo_classes.isdisjoint(
{"first-of-type", "last-of-type", "odd", "even"}
{"first-of-type", "last-of-type"}
)
node._has_odd_or_even = (
"odd" in all_pseudo_classes or "even" in all_pseudo_classes
)

cache_key: tuple | None = None
Expand Down
Loading

0 comments on commit 495df59

Please sign in to comment.