Apply margins to widgets on layout.

This commit is contained in:
Russell Keith-Magee 2023-08-19 23:32:21 +09:30
parent 4f492a0e68
commit 96305083e8
No known key found for this signature in database
GPG key ID: 3D2DAB6A37BB5BC3
6 changed files with 71 additions and 34 deletions

View file

@ -38,7 +38,7 @@ def build(app):
c_box.style.update(direction=ROW, padding=5)
c_input.style.update(flex=1)
f_input.style.update(flex=1, padding_left=160)
f_input.style.update(flex=1, padding_left=210)
c_label.style.update(width=100, padding_left=10)
f_label.style.update(width=100, padding_left=10)
join_label.style.update(width=200, padding_right=10)

View file

@ -26,7 +26,8 @@ class Container(Scalable):
@property
def height(self):
return self.scale_out_vertical(self.native_parent.size[1])
# Subtract 1 to remove the height of the header
return self.scale_out_vertical(self.native_parent.size[1] - 1)
def refreshed(self):
if self.on_refresh:

View file

@ -1,5 +1,7 @@
from travertino.size import at_least
from toga.style.pack import ROW
# We assume a terminal is 800x600 pixels, mapping to 80x25 characters.
# This results in an uneven scale in the horizontal and vertical directions
@ -64,31 +66,70 @@ class Widget(Scalable):
# APPLICATOR
######################################################################
@property
def width_adjustment(self):
return 0
@property
def height_adjustment(self):
return 0
def set_bounds(self, x, y, width, height):
# Convert the width and height back into terminal coordinates,
# subtracting the extra spacing associated with the widget itself.
self.native.styles.width = (
self.scale_in_horizontal(width) - self.width_adjustment
)
self.native.styles.height = (
self.scale_in_horizontal(height) - self.height_adjustment
)
# Convert the width and height back into terminal coordinates
self.native.styles.width = self.scale_in_horizontal(width)
self.native.styles.height = self.scale_in_vertical(height)
# Apply margins to the widget based on content spacing.
# self.native.styles.margin = (
# self.scale_in_vertical(self.interface.layout.content_top),
# self.scale_in_horizontal(self.interface.layout.content_right),
# self.scale_in_vertical(self.interface.layout.content_bottom),
# self.scale_in_horizontal(self.interface.layout.content_left),
# )
# Positions are more complicated. The (x,y) provided as an argument is
# in absolute coordinates. The `content_left` ad `content_right` values
# of the layout are relative coordianate. Textual doesn't allow specifying
# either absolute *or* relative - we can only specify margin values within
# a row/column box. This means we need to reverse engineer the margins from
# the computed layout.
parent = self.interface.parent
if parent is None:
# Root object in a layout; Margins are the literal content offsets
margin_top = self.interface.layout.content_top
margin_right = self.interface.layout.content_right
margin_bottom = self.interface.layout.content_bottom
margin_left = self.interface.layout.content_left
else:
# Look for this widget in the children of the parent
index = parent.children.index(self.interface)
if index == 0:
# First child in the container; margins are the literal content offsets
margin_top = self.interface.layout.content_top
margin_right = self.interface.layout.content_right
margin_bottom = self.interface.layout.content_bottom
margin_left = self.interface.layout.content_left
else:
# 2nd+ child in the container. Right and Bottom content offsets are as
# computed by layout. If the parent is a row box, the top offset is as
# computed, but the left offset must be computed relative to the right
# margin of the predecessor. If the parent is a column box, the left
# offset is as computed, but the top offset must be computed relative to
# the bottom margin of the predecessor.
predecessor = parent.children[index - 1]
margin_top = self.interface.layout.content_top
margin_right = self.interface.layout.content_right
margin_bottom = self.interface.layout.content_bottom
margin_left = self.interface.layout.content_left
# The layout doesn't have a concept of flow direction; this is a
# property of the style language. However, we don't have any other way
# to establish whether this is a row or a column box.
if parent.style.direction == ROW:
margin_left -= (
predecessor.layout.content_left
+ predecessor.layout.content_width
+ predecessor.layout.content_right
)
else:
margin_top -= (
predecessor.layout.content_top
+ predecessor.layout.content_height
+ predecessor.layout.content_bottom
)
# Convert back into terminal coordinates, and apply margins to the widget.
self.native.styles.margin = (
self.scale_in_vertical(margin_top),
self.scale_in_horizontal(margin_right),
self.scale_in_vertical(margin_bottom),
self.scale_in_horizontal(margin_left),
)
def set_alignment(self, alignment):
pass

View file

@ -12,6 +12,9 @@ class Box(Widget):
def set_bounds(self, x, y, width, height):
super().set_bounds(x, y, width, height)
# The layout doesn't have a concept of flow direction; this is a property of the
# style language. However, we don't have any other way to establish whether this
# is a row or a column box.
if self.interface.style.direction == ROW:
self.native.styles.layout = "horizontal"
else:

View file

@ -25,14 +25,6 @@ class Button(Widget):
def set_text(self, text):
self.native.label = text
@property
def width_adjustment(self):
return 2
@property
def height_adjustment(self):
return 2
def rehint(self):
self.interface.intrinsic.width = at_least(len(self.native.label) + 8)
self.interface.intrinsic.height = 3

View file

@ -10,7 +10,7 @@ class Label(Widget):
self.native = TextualLabel()
def get_text(self):
return self.native.renderable
return str(self.native.renderable)
def set_text(self, value):
self.native.renderable = value