improve layout explainer

This commit is contained in:
Aran-Fey
2025-02-22 21:45:17 +01:00
parent 7766454015
commit 5c87bd0cbf
2 changed files with 35 additions and 18 deletions

View File

@@ -40,7 +40,7 @@ FULL_SIZE_SINGLE_CONTAINERS: set[type[rio.Component]] = {
# These components make use of the `grow_...` attributes in at least one axis.
CONTAINERS_SUPPORTING_GROW: t.Iterable[type[rio.Component]] = {
CONTAINERS_SUPPORTING_GROW: set[type[rio.Component]] = {
rio.Column,
rio.Grid,
rio.Row,
@@ -155,11 +155,11 @@ class LayoutExplainer:
axis_xy = "y"
target_class_name = type(self.component).__name__
parent_class_name = type(self._parent).__name__
# Try to get a specialized explanation based on the parent
# self.component
if self._parent_layout is None:
return f"The self.component was allocated a {axis_name} of {allocated_space_before_alignment:.1f} by its parent."
return f"The component was allocated a {axis_name} of {allocated_space_before_alignment:.1f} by its parent."
# Prepare some commonly used values
if axis_name == "width":
@@ -171,8 +171,6 @@ class LayoutExplainer:
parent_natural_size = self._parent_layout.natural_height
is_grower = self.component.grow_y
parent_class_name = type(self._parent).__name__
# Toplevel?
if self.component is self.session._get_user_root_component():
return f"This is the app's top-level component. As such, the {target_class_name} was allocated the full {axis_name} of {allocated_space_before_alignment:.1f} available in the window."
@@ -310,6 +308,7 @@ class LayoutExplainer:
is_grower = self.component.grow_y
target_class_name = type(self.component).__name__
parent_class_name = type(self._parent).__name__
# Warn if the component has a `grow` attribute set, but is placed inside
# of a container that doesn't support it
@@ -319,7 +318,7 @@ class LayoutExplainer:
and type(self._parent) not in CONTAINERS_SUPPORTING_GROW
):
self.warnings.append(
f"The component has `grow_{axis_xy}=True` set, but is placed inside of a `{type(self._parent).__name__}`. {type(self._parent).__name__} components do not make use of this property, so it has no effect."
f"The component has `grow_{axis_xy}=True` set, but is placed inside of a `{parent_class_name}`. {parent_class_name} components do not make use of this property, so it has no effect."
)
# Warn if the component is aligned, but has no natural size
@@ -372,7 +371,7 @@ class LayoutExplainer:
# Warn if the specified minimum size is less than the natural one
if 0 < specified_min_size < natural_size:
self.warnings.append(
f"\n\nThe explicitly set minimum {axis_name} of {specified_min_size:.1f} has no effect, because it is less than the component's natural {axis_name} of {natural_size:.1f}. Components can never be smaller than their natural size."
f"The explicitly set minimum {axis_name} of {specified_min_size:.1f} has no effect, because it is less than the component's natural {axis_name} of {natural_size:.1f}. Components can never be smaller than their natural size."
)
# Suggest growing the component by setting an explicit size
@@ -413,5 +412,20 @@ class LayoutExplainer:
f"Remove the `align_{axis_xy}` attribute from the component, so it takes up all of the available space"
)
# If the component is at its minimum size, give tips on how to reduce
# its minimum size further
if allocated_size < natural_size + 0.1:
for suggestion in self._explain_how_to_reduce_natural_size(
axis_name
):
suggest_shrink(suggestion)
# Done!
return result.getvalue()
def _explain_how_to_reduce_natural_size(
self, axis_name: t.Literal["width", "height"]
) -> t.Iterable[str]:
if isinstance(self.component, rio.Text):
if axis_name == "width":
yield 'Set `overflow="wrap"` or `overflow="ellipsize"` to reduce the `Text`\'s natural width'

View File

@@ -141,7 +141,8 @@ class HelpAnchor(rio.Component):
class ActionAnchor(rio.Component):
icon: str
partial_name: str
action_name: str # Something like "shrink" or "reduce" or "increase"
dimension_name: t.Literal["width", "height"]
actions: list[str]
def build(self) -> rio.Component:
@@ -154,7 +155,7 @@ class ActionAnchor(rio.Component):
anchor = rio.Row(
rio.Icon(self.icon, fill=color),
rio.Text(
f"How to {self.partial_name}",
f"How to {self.action_name} {self.dimension_name}",
style=rio.TextStyle(fill=color),
),
spacing=0.3,
@@ -162,12 +163,10 @@ class ActionAnchor(rio.Component):
margin=0.5,
)
# If there aren't any options there is no need to go any further
# Prepare the markdown content (for the tooltip)
if not self.actions:
return anchor
# Prepare the markdown content
if len(self.actions) == 1:
markdown_source = f"The component's {self.dimension_name} is already at its minimum. It cannot be reduced further."
elif len(self.actions) == 1:
markdown_source = self.actions[0]
else:
markdown_source = "- " + "\n- ".join(self.actions)
@@ -258,12 +257,14 @@ class LayoutSubpage(rio.Component):
rio.Row(
ActionAnchor(
"close-fullscreen",
"shrink width",
"shrink",
"width",
self._layout_explainer.decrease_width,
),
ActionAnchor(
"open-in-full",
"grow width",
"grow",
"width",
self._layout_explainer.increase_width,
),
)
@@ -280,12 +281,14 @@ class LayoutSubpage(rio.Component):
rio.Row(
ActionAnchor(
"close-fullscreen",
"shrink height",
"shrink",
"height",
self._layout_explainer.decrease_height,
),
ActionAnchor(
"open-in-full",
"grow height",
"grow",
"height",
self._layout_explainer.increase_height,
),
)