box model fixes and tests

This commit is contained in:
Will McGugan
2022-04-21 11:43:45 +01:00
parent 2823718011
commit bc63723363
8 changed files with 56 additions and 59 deletions

View File

@@ -10,27 +10,27 @@ Widget {
}
#thing {
width: auto;
height: auto;
height: 10;
background:magenta;
margin: 3;
padding: 1;
border: solid white;
box-sizing: content-box;
/* border: solid white; */
padding: 1;
border: solid white;
box-sizing: border-box;
border: solid white;
align-horizontal: center;
}
#thing2 {
width: auto;
height: 10;
/* border: solid white; */
outline: heavy blue;
border: solid white;
/* outline: heavy blue; */
padding: 1 2;
box-sizing: content-box;
box-sizing: border-box;
max-height: 100vh;
background:green;
align-horizontal: center;
@@ -39,8 +39,7 @@ Widget {
#thing3 {
width: 20;
height: 10;
margin: 1;
background:blue;
align-horizontal: center;

View File

@@ -201,7 +201,8 @@ Warning {
Success {
max-width: 80;
height:3;
height:3;
box-sizing: border-box;
background: $success-lighten-3;
color: $text-success-lighten-3-fade-1;
border-top: hkey $success;

View File

@@ -1,4 +1,5 @@
from __future__ import annotations
from operator import is_
from typing import Callable, NamedTuple, TYPE_CHECKING
@@ -18,8 +19,8 @@ def get_box_model(
styles: StylesBase,
container_size: Size,
parent_size: Size,
get_auto_width: Callable[[Size, Size, Spacing], int],
get_auto_height: Callable[[Size, Size, Spacing], int],
get_content_width: Callable[[Size, Size], int],
get_content_height: Callable[[Size, Size], int],
) -> BoxModel:
"""Resolve the box model for this Styles.
@@ -36,23 +37,30 @@ def get_box_model(
has_rule = styles.has_rule
width, height = container_size
is_content_box = styles.box_sizing == "content-box"
gutter = styles.padding + styles.border.spacing
gutter = Spacing(0, 0, 0, 0)
if styles.box_sizing == "content-box":
if has_rule("padding"):
gutter += styles.padding
gutter += styles.border.spacing
else: # border-box
gutter -= styles.border.spacing
if has_rule("width"):
if styles.width.is_auto:
width = get_auto_width(container_size, parent_size, gutter)
else:
width = styles.width.resolve_dimension(container_size, parent_size)
if not has_rule("width") or styles.width.is_auto:
# When width is auto, we want enough space to always fit the content
width = get_content_width(container_size, parent_size)
if not is_content_box:
# If box sizing is border box we want to enlarge the width so that it
# can accommodate padding + border
width += gutter.width
else:
width = max(0, width - styles.margin.width)
width = styles.width.resolve_dimension(container_size, parent_size)
if not has_rule("height") or styles.height.is_auto:
height = get_content_height(container_size, parent_size)
if not is_content_box:
height += gutter.height
else:
height = styles.height.resolve_dimension(container_size, parent_size)
if is_content_box:
gutter_width, gutter_height = gutter.totals
width += gutter_width
height += gutter_height
if has_rule("min_width"):
min_width = styles.min_width.resolve_dimension(container_size, parent_size)
@@ -62,23 +70,15 @@ def get_box_model(
max_width = styles.max_width.resolve_dimension(container_size, parent_size)
width = min(width, max_width)
if has_rule("height"):
if styles.height.is_auto:
height = get_auto_height(container_size, parent_size, gutter)
else:
height = styles.height.resolve_dimension(container_size, parent_size)
else:
height = max(0, height - styles.margin.height)
if has_rule("min_height"):
min_height = styles.min_height.resolve_dimension(container_size, parent_size)
height = max(height, min_height)
if has_rule("max_height"):
max_height = styles.max_height.resolve_dimension(container_size, parent_size)
height = min(width, max_height)
height = min(height, max_height)
size = Size(width, height) + gutter.totals
margin = styles.margin if has_rule("margin") else Spacing(0, 0, 0, 0)
size = Size(width, height)
margin = styles.margin
return BoxModel(size, margin)

View File

@@ -8,7 +8,6 @@ when setting and getting.
"""
from __future__ import annotations
from tkinter.tix import AUTO
from typing import Iterable, NamedTuple, TYPE_CHECKING, cast

View File

@@ -34,9 +34,10 @@ class HorizontalLayout(Layout):
max((box1.margin.right, box2.margin.left))
for box1, box2 in zip(box_models, box_models[1:])
]
margins.append(box_models[-1].margin.right)
if box_models:
margins.append(box_models[-1].margin.right)
x = box_models[0].margin.left
x = box_models[0].margin.left if box_models else 0
for widget, box_model, margin in zip(parent.children, box_models, margins):
content_width, content_height = box_model.size
@@ -47,7 +48,7 @@ class HorizontalLayout(Layout):
x += region.width + margin
max_width = x
max_width += margins[-1]
max_width += margins[-1] if margins else 0
total_region = Region(0, 0, max_width, max_height)
add_placement(WidgetPlacement(total_region, None, 0))

View File

@@ -35,9 +35,10 @@ class VerticalLayout(Layout):
max((box1.margin.bottom, box2.margin.top))
for box1, box2 in zip(box_models, box_models[1:])
]
margins.append(box_models[-1].margin.bottom)
if box_models:
margins.append(box_models[-1].margin.bottom)
y = box_models[0].margin.top
y = box_models[0].margin.top if box_models else 0
for widget, box_model, margin in zip(parent.children, box_models, margins):
content_width, content_height = box_model.size
@@ -48,7 +49,7 @@ class VerticalLayout(Layout):
y += region.height + margin
max_height = y
max_height += margins[-1]
max_height += margins[-1] if margins else 0
total_region = Region(0, 0, max_width, max_height)
add_placement(WidgetPlacement(total_region, None, 0))

View File

@@ -131,7 +131,8 @@ class Screen(Widget):
)
)
except Exception as error:
self.app.panic(error)
self.app.on_exception(error)
return
self.app.refresh()
self._dirty_widgets.clear()

View File

@@ -115,21 +115,16 @@ class Widget(DOMNode):
self.get_content_width,
self.get_content_height,
)
self.log(self, self.styles.padding, self.styles.border.spacing)
return box_model
def get_content_width(
self, container_size: Size, parent_size: Size, gutter: Spacing
) -> int:
def get_content_width(self, container_size: Size, parent_size: Size) -> int:
console = self.app.console
renderable = self.render()
measurement = Measurement.get(console, console.options, renderable)
return measurement.maximum
def get_content_height(
self, container_size: Size, parent_size: Size, gutter: Spacing
) -> int:
return container_size.height - gutter.height
def get_content_height(self, container_size: Size, parent_size: Size) -> int:
return container_size.height
async def watch_scroll_x(self, new_value: float) -> None:
self.horizontal_scrollbar.position = int(new_value)