Skip to content

Commit

Permalink
Allow empty content in split containers, and allow flex values <1
Browse files Browse the repository at this point in the history
  • Loading branch information
freakboy3742 committed Jul 12, 2023
1 parent 3399e45 commit 87b8500
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 51 deletions.
21 changes: 13 additions & 8 deletions cocoa/src/toga_cocoa/widgets/splitcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ def create(self):
def set_bounds(self, x, y, width, height):
super().set_bounds(x, y, width, height)
for container in self.sub_containers:
container.content.interface.refresh()
if container.content:
container.content.interface.refresh()

# Apply any pending split
self.native.performSelector(
Expand All @@ -72,15 +73,19 @@ def set_content(self, content, flex):

for index, widget in enumerate(content):
# Compute the minimum layout for the content
widget.interface.style.layout(widget.interface, MinimumContainer())
min_width = widget.interface.layout.width
min_height = widget.interface.layout.height
if widget:
widget.interface.style.layout(widget.interface, MinimumContainer())
min_width = widget.interface.layout.width
min_height = widget.interface.layout.height

# Create a container with that minimum size, and assign the widget as content
self.sub_containers[index].min_width = min_width
self.sub_containers[index].min_height = min_height
# Create a container with that minimum size, and assign the widget as content
self.sub_containers[index].min_width = min_width
self.sub_containers[index].min_height = min_height

self.sub_containers[index].content = widget
self.sub_containers[index].content = widget
else:
self.sub_containers[index].min_width = 0
self.sub_containers[index].min_height = 0

# We now know the initial positions of the split. However, we can't *set* the
# because Cocoa requires a pixel position, and the widget isn't visible yet.
Expand Down
51 changes: 31 additions & 20 deletions core/src/toga/widgets/splitcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ def __init__(
id=None,
style=None,
direction: Direction = Direction.VERTICAL,
content: list[Widget | tuple[Widget, int]] | None = None,
content: tuple[Widget | tuple[Widget, int], Widget | tuple[Widget, int]] = (
None,
None,
),
):
"""Create a new SplitContainer.
Expand All @@ -28,7 +31,7 @@ def __init__(
:attr:`~toga.constants.Direction.VERTICAL`; defaults to
:attr:`~toga.constants.Direction.VERTICAL`
:param content: The content that will fill the panels of the SplitContainer. A
list with 2 elements; each item in the list is either:
tuple with 2 elements; each item in the tuple is either:
* A tuple consisting of a widget and the initial flex value to apply to
that widget in the split.
Expand All @@ -37,13 +40,10 @@ def __init__(
"""
super().__init__(id=id, style=style)

self._content = []

# Create a platform specific implementation of a SplitContainer
self._impl = self.factory.SplitContainer(interface=self)

if content:
self.content = content
self.content = content
self.direction = direction

@property
Expand All @@ -64,7 +64,7 @@ def focus(self):
pass

@property
def content(self) -> list[Widget]:
def content(self) -> tuple[Widget, Widget]:
"""The widgets displayed in the SplitContainer.
When retrieved, only the list of widgets is returned.
Expand All @@ -80,10 +80,15 @@ def content(self) -> list[Widget]:
return self._content

@content.setter
def content(self, content):
if content is None or len(content) != 2:
def content(
self, content: tuple[Widget | tuple[Widget, int], Widget | tuple[Widget, int]]
):
try:
if len(content) != 2:
raise TypeError()
except TypeError:
raise ValueError(
"SplitContainer content must be a list with exactly 2 elements"
"SplitContainer content must be a sequence with exactly 2 elements"
)

_content = []
Expand All @@ -92,8 +97,10 @@ def content(self, content):
if isinstance(item, tuple):
if len(item) == 2:
widget, flex_value = item
if flex_value < 1:
flex_value = 1
if flex_value <= 0:
raise ValueError(
"The flex value for an item in a SplitContainer must be >0"
)
else:
raise ValueError(
"An item in SplitContainer content must be a 2-tuple "
Expand All @@ -107,11 +114,15 @@ def content(self, content):
_content.append(widget)
flex.append(flex_value)

widget.app = self.app
widget.window = self.window
if widget:
widget.app = self.app
widget.window = self.window

self._impl.set_content([w._impl for w in _content], flex)
self._content = _content
self._impl.set_content(
tuple(w._impl if w is not None else None for w in _content),
flex,
)
self._content = tuple(_content)
self.refresh()

@Widget.app.setter
Expand All @@ -120,8 +131,8 @@ def app(self, app):
Widget.app.fset(self, app)

# Also assign the app to the content in the container
if self.content:
for content in self.content:
for content in self.content:
if content:
content.app = app

@Widget.window.setter
Expand All @@ -130,8 +141,8 @@ def window(self, window):
Widget.window.fset(self, window)

# Also assign the window to the content in the container
if self._content:
for content in self._content:
for content in self._content:
if content:
content.window = window

@property
Expand Down
Loading

0 comments on commit 87b8500

Please sign in to comment.