Skip to content

Commit

Permalink
Fix visibility and display support in Pack()
Browse files Browse the repository at this point in the history
  • Loading branch information
ikus060 committed Mar 1, 2024
1 parent 83b9d0b commit b063a4d
Show file tree
Hide file tree
Showing 15 changed files with 56 additions and 52 deletions.
1 change: 1 addition & 0 deletions changes/2428.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Issue with `visibility` on GTK and `display` on all platform.
30 changes: 27 additions & 3 deletions core/src/toga/style/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _debug(self, *args): # pragma: no cover
@property
def _hidden(self):
"Does this style declaration define a object that should be hidden"
return self.visibility == HIDDEN
return self.visibility == HIDDEN or self.display == NONE

def apply(self, prop, value):
if self._applicator:
Expand All @@ -104,8 +104,8 @@ def apply(self, prop, value):
self._applicator.set_color(value)
elif prop == "background_color":
self._applicator.set_background_color(value)
elif prop == "visibility":
self._applicator.set_hidden(value == HIDDEN)
elif prop == "visibility" or prop == "display":
self._applicator.set_hidden(self._hidden)
elif prop in (
"font_family",
"font_size",
Expand Down Expand Up @@ -275,6 +275,9 @@ def _layout_row_children(
min_width = 0
remaining_width = available_width
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 1 {child}")
if child.style.width != NONE:
# self._debug(f"- fixed width {child.style.width}")
Expand Down Expand Up @@ -404,6 +407,9 @@ def _layout_row_children(
# Pass 2: Lay out children with an intrinsic flexible width,
# or no width specification at all.
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 2 {child}")
if child.style.width != NONE:
# self._debug("- already laid out (explicit width)")
Expand Down Expand Up @@ -489,6 +495,9 @@ def _layout_row_children(
height = 0
min_height = 0
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 3: {child} AT HORIZONTAL {offset=}")
if node.style.text_direction is RTL:
# self._debug("- RTL")
Expand Down Expand Up @@ -522,6 +531,9 @@ def _layout_row_children(

# Pass 4: set vertical position of each child.
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 4: {child}")
extra = height - (
child.layout.content_height
Expand Down Expand Up @@ -559,6 +571,9 @@ def _layout_column_children(
min_height = 0
remaining_height = available_height
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 1 {child}")
if child.style.height != NONE:
# self._debug(f"- fixed height {child.style.height}")
Expand Down Expand Up @@ -689,6 +704,9 @@ def _layout_column_children(
# Pass 2: Lay out children with an intrinsic flexible height,
# or no height specification at all.
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 2 {child}")
if child.style.height != NONE:
# self._debug("- already laid out (explicit height)")
Expand Down Expand Up @@ -775,6 +793,9 @@ def _layout_column_children(
width = 0
min_width = 0
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 3: {child} AT VERTICAL OFFSET {offset}")
offset += child.style.padding_top
child.layout.content_top = offset
Expand All @@ -800,6 +821,9 @@ def _layout_column_children(

# Pass 4: set horizontal position of each child.
for child in node.children:
# Skip calculation if widget is not displayed
if child.style.display == NONE:
continue
# self._debug(f"PASS 4: {child}")
extra = width - (
child.layout.content_width
Expand Down
5 changes: 1 addition & 4 deletions gtk/src/toga_gtk/widgets/activityindicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ def stop(self):
self.native.stop()

def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = width[0]
self.interface.intrinsic.height = height[0]
18 changes: 13 additions & 5 deletions gtk/src/toga_gtk/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ def container(self, container):
# setting container, adding self to container.native
self._container = container
self._container.add(self.native)
self.native.show_all()

for child in self.interface.children:
child._impl.container = container
Expand All @@ -84,6 +83,18 @@ def get_tab_index(self):
def set_tab_index(self, tab_index):
self.interface.factory.not_implemented("Widget.set_tab_index()")

def _get_preferred_size(self, native):
# Utility function to get the preferred size of widget regardless of it's visibility.
visible = native.get_visible()
if not visible:
native.set_visible(True)
# print("REHINT", self, native.get_preferred_width(), native.get_preferred_height())
width = native.get_preferred_width()
height = native.get_preferred_height()
if not visible:
native.set_visible(visible)
return width, height

######################################################################
# CSS tools
######################################################################
Expand Down Expand Up @@ -185,9 +196,6 @@ def refresh(self):

def rehint(self):
# Perform the actual GTK rehint.
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(width[0])
self.interface.intrinsic.height = at_least(height[0])
5 changes: 1 addition & 4 deletions gtk/src/toga_gtk/widgets/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ def set_background_color(self, color):
super().set_background_color(color)

def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(width[0])
self.interface.intrinsic.height = height[1]

Expand Down
1 change: 0 additions & 1 deletion gtk/src/toga_gtk/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ def get_image_data(self):

# Rehint
def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
# width = self.native.get_allocation().width
# height = self.native.get_allocation().height
width = self.interface._MIN_WIDTH
Expand Down
4 changes: 1 addition & 3 deletions gtk/src/toga_gtk/widgets/divider.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def create(self):
self.native = Gtk.Separator()

def rehint(self):
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
if self.get_direction() == self.interface.VERTICAL:
self.interface.intrinsic.width = width[0]
self.interface.intrinsic.height = at_least(height[1])
Expand Down
8 changes: 1 addition & 7 deletions gtk/src/toga_gtk/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ def set_text(self, value):
self.native.set_text(value)

def rehint(self):
# print("REHINT", self,
# self.native.get_preferred_width(), self.native.get_preferred_height(),
# getattr(self, '_fixed_height', False), getattr(self, '_fixed_width', False)
# )
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(width[0])
self.interface.intrinsic.height = height[1]
4 changes: 1 addition & 3 deletions gtk/src/toga_gtk/widgets/numberinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ def set_alignment(self, value):
self.native.set_alignment(xalign)

def rehint(self):
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(
max(self.interface._MIN_WIDTH, width[1])
)
Expand Down
5 changes: 1 addition & 4 deletions gtk/src/toga_gtk/widgets/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@ def stop(self):
self._stop_indeterminate()

def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(width[0])
self.interface.intrinsic.height = height[0]
3 changes: 1 addition & 2 deletions gtk/src/toga_gtk/widgets/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ def get_selected_index(self):
return index

def rehint(self):
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()
width, height = self._get_preferred_size(self.native)

# FIXME: 2023-05-31 This will always provide a size that is big enough,
# but sometimes it will be *too* big. For example, if you set the font size
Expand Down
3 changes: 1 addition & 2 deletions gtk/src/toga_gtk/widgets/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ def get_tick_count(self):
return self.tick_count

def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
height = self.native.get_preferred_height()
width, height = self._get_preferred_size(self.native)

# Set intrinsic width to at least the minimum width
self.interface.intrinsic.width = at_least(self.interface._MIN_WIDTH)
Expand Down
8 changes: 2 additions & 6 deletions gtk/src/toga_gtk/widgets/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,8 @@ def set_font(self, font):
self.apply_css("font", get_font_css(font), native=self.native_label)

def rehint(self):
# print("REHINT", self, self.native.get_preferred_width(), self.native.get_preferred_height())
label_width = self.native_label.get_preferred_width()
label_height = self.native_label.get_preferred_height()

switch_width = self.native_switch.get_preferred_width()
switch_height = self.native_switch.get_preferred_height()
label_width, label_height = self._get_preferred_size(native=self.native_label)
switch_width, switch_height = self._get_preferred_size(native=self.native_label)

# Set intrinsic width to at least the minimum width
self.interface.intrinsic.width = at_least(
Expand Down
8 changes: 1 addition & 7 deletions gtk/src/toga_gtk/widgets/textinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,7 @@ def set_value(self, value):
self.native.set_text(value)

def rehint(self):
# print("REHINT", self,
# self._impl.get_preferred_width(), self._impl.get_preferred_height(),
# getattr(self, '_fixed_height', False), getattr(self, '_fixed_width', False)
# )
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

width, height = self._get_preferred_size(self.native)
self.interface.intrinsic.width = at_least(
max(self.interface._MIN_WIDTH, width[1])
)
Expand Down
5 changes: 4 additions & 1 deletion gtk/src/toga_gtk/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ def set_app(self, app):
app.native.add_window(self.native)

def show(self):
self.native.show_all()
# Avoid calling show_all() as it change the visibility of all children.
self.native.show()
self.layout.show()
self.container.show()

######################################################################
# Window content and resources
Expand Down

0 comments on commit b063a4d

Please sign in to comment.