Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify container handling for GTK #1794

Merged
merged 18 commits into from
Mar 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion android/src/toga_android/widgets/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from toga.constants import CENTER, JUSTIFY, LEFT, RIGHT
from toga.constants import CENTER, JUSTIFY, LEFT, RIGHT, TRANSPARENT

from ..colors import native_color
from ..libs.activity import MainActivity
from ..libs.android.view import Gravity, View

Expand Down Expand Up @@ -111,6 +112,14 @@ def set_background_color(self, color):
# By default, background color can't be changed.
pass

# Although setBackgroundColor is defined in the View base class, we can't use it as
# a default implementation because it often overwrites other aspects of the widget's
# appearance.
def set_background_color_simple(self, value):
self.native.setBackgroundColor(
native_color(TRANSPARENT if (value is None) else value)
)

def set_alignment(self, alignment):
pass # If appropriate, a widget subclass will implement this.

Expand All @@ -132,6 +141,9 @@ def insert_child(self, index, child):
def remove_child(self, child):
child.container = None

def refresh(self):
self.rehint()

def rehint(self):
pass

Expand Down
11 changes: 6 additions & 5 deletions android/src/toga_android/widgets/box.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from travertino.constants import TRANSPARENT
from travertino.size import at_least

from ..colors import native_color
from ..libs.activity import MainActivity
from ..libs.android.widget import RelativeLayout, RelativeLayout__LayoutParams
from .base import Widget
Expand All @@ -24,6 +23,8 @@ def set_child_bounds(self, widget, x, y, width, height):
self.native.updateViewLayout(widget.native, layout_params)

def set_background_color(self, value):
self.native.setBackgroundColor(
native_color(TRANSPARENT if (value is None) else value)
)
self.set_background_color_simple(value)

def rehint(self):
self.interface.intrinsic.width = at_least(0)
self.interface.intrinsic.height = at_least(0)
freakboy3742 marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 0 additions & 3 deletions android/src/toga_android/widgets/datepicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,3 @@ def _create_dialog(self):
self.set_min_date(self.interface._min_date)
self.set_max_date(self.interface._max_date)
self._dialog.show()

def rehint(self):
return super().rehint()
3 changes: 3 additions & 0 deletions android/src/toga_android/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def set_font(self, font):
self.native.setTextSize(TypedValue.COMPLEX_UNIT_SP, font._impl.get_size())
self.native.setTypeface(font._impl.get_typeface(), font._impl.get_style())

def set_background_color(self, value):
self.set_background_color_simple(value)

def set_color(self, color):
if color:
self.native.setTextColor(native_color(color))
Expand Down
1 change: 0 additions & 1 deletion android/src/toga_android/widgets/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def set_text(self, text):
# is required to get the text to truly **use** one single line!
self.native.setSingleLine(False)
self.native.setText(str(self.interface.text))
self.rehint()
freakboy3742 marked this conversation as resolved.
Show resolved Hide resolved

def set_value(self, value):
self.native.setChecked(bool(value))
Expand Down
3 changes: 0 additions & 3 deletions android/src/toga_android/widgets/timepicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,3 @@ def _create_dialog(self):
True,
)
self._dialog.show()

def rehint(self):
return super().rehint()
1 change: 1 addition & 0 deletions changes/1205.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Issues with reducing the size of windows on GTK have been resolved.
1 change: 1 addition & 0 deletions changes/1794.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The handling of GTK layouts has been modified to reduce the frequency and increase the accuracy of layout results.
1 change: 0 additions & 1 deletion cocoa/src/toga_cocoa/widgets/activityindicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ def create(self):

# Add the layout constraints
self.add_constraints()
self.rehint()
freakboy3742 marked this conversation as resolved.
Show resolved Hide resolved

def start(self):
self.native.startAnimation(self.native)
Expand Down
3 changes: 3 additions & 0 deletions cocoa/src/toga_cocoa/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,8 @@ def add_constraints(self):
self.native.translatesAutoresizingMaskIntoConstraints = False
self.constraints = Constraints(self)

def refresh(self):
self.rehint()

def rehint(self):
pass
1 change: 0 additions & 1 deletion cocoa/src/toga_cocoa/widgets/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def create(self):

# Add the layout constraints
self.add_constraints()
self.rehint()

def set_value(self, value):
self.native.doubleValue = self.interface.value
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/style/applicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def set_hidden(self, hidden):

def set_font(self, font):
self.widget._impl.set_font(font)
self.widget._impl.rehint()
self.widget.refresh()

def set_color(self, color):
self.widget._impl.set_color(color)
Expand Down
2 changes: 2 additions & 0 deletions core/src/toga/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ def enabled(self, value):
self._impl.set_enabled(value)

def refresh(self):
self._impl.refresh()

# Refresh the layout
if self._root:
self._root.refresh()
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def text(self, value):
else:
self._text = str(value)
self._impl.set_text(value)
self._impl.rehint()
self.refresh()

@property
def on_press(self):
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/divider.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ def direction(self):
def direction(self, value):
self._direction = value
self._impl.set_direction(value)
self._impl.rehint()
self.refresh()
2 changes: 1 addition & 1 deletion core/src/toga/widgets/imageview.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def image(self, image):

if self._image is not None:
self._impl.set_image(image)
self._impl.rehint()
self.refresh()

# @property
# def alignment(self):
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ def text(self, value):
else:
self._text = str(value)
self._impl.set_text(value)
self._impl.rehint()
self.refresh()
2 changes: 1 addition & 1 deletion core/src/toga/widgets/multilinetextinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def value(self):
def value(self, value):
cleaned_value = "" if value is None else str(value)
self._impl.set_value(cleaned_value)
self._impl.rehint()
self.refresh()

def clear(self):
"""Clears the text from the widget."""
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/scrollcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def content(self, widget):
self._content = widget

self._impl.set_content(widget._impl)
self._impl.rehint()
self.refresh()

widget.refresh()

Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/splitcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,4 @@ def direction(self):
def direction(self, value):
self._direction = value
self._impl.set_direction(value)
self._impl.rehint()
self.refresh()
2 changes: 1 addition & 1 deletion core/src/toga/widgets/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def text(self, value):
else:
self._text = str(value)
self._impl.set_text(value)
self._impl.rehint()
self.refresh()

@property
def on_change(self):
Expand Down
2 changes: 1 addition & 1 deletion core/tests/widgets/test_divider.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ def test_update_direction(self):
self.divider.direction = new_direction
self.assertEqual(self.divider.direction, new_direction)
self.assertValueSet(self.divider, "direction", new_direction)
self.assertActionPerformed(self.divider, "rehint")
self.assertActionPerformed(self.divider, "refresh")
2 changes: 1 addition & 1 deletion core/tests/widgets/test_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_update_label_text(self):
self.label.text = new_text
self.assertEqual(self.label.text, new_text)
self.assertValueSet(self.label, "text", new_text)
self.assertActionPerformed(self.label, "rehint")
self.assertActionPerformed(self.label, "refresh")

self.label.text = None
self.assertEqual(self.label.text, "")
Expand Down
4 changes: 2 additions & 2 deletions dummy/src/toga_dummy/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ def remove_child(self, child):
def add_constraints(self):
self._action("add constraints")

def rehint(self):
self._action("rehint")
def refresh(self):
self._action("refresh")
12 changes: 12 additions & 0 deletions examples/resize/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Resize Test
===========

Test app that demonstrates resizing of widgets and windows.

Quickstart
~~~~~~~~~~

To run this example:

$ pip install toga
$ python -m resize
55 changes: 55 additions & 0 deletions examples/resize/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[build-system]
requires = ["briefcase"]

[tool.briefcase]
project_name = "Resize Test"
bundle = "org.beeware"
version = "0.0.1"
url = "https://beeware.org"
license = "BSD license"
author = 'Tiberius Yak'
author_email = "[email protected]"

[tool.briefcase.app.resize]
formal_name = "Resize Test"
description = "A testing app"
sources = ['resize']
requires = [
'../../core',
]


[tool.briefcase.app.resize.macOS]
requires = [
'../../cocoa',
'std-nslog>=1.0.0',
]

[tool.briefcase.app.resize.linux]
requires = [
'../../gtk',
]

[tool.briefcase.app.resize.windows]
requires = [
'../../winforms',
]

# Mobile deployments
[tool.briefcase.app.resize.iOS]
requires = [
'../../iOS',
'std-nslog>=1.0.0',
]

[tool.briefcase.app.resize.android]
requires = [
'../../android',
]

# Web deployment
[tool.briefcase.app.resize.web]
requires = [
'../../web',
]
style_framework = "Bootstrap v4.6"
Empty file.
4 changes: 4 additions & 0 deletions examples/resize/resize/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from resize.app import main

if __name__ == "__main__":
main().main_loop()
99 changes: 99 additions & 0 deletions examples/resize/resize/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW


class SizeButton(toga.Button):
def __init__(self, text, *, value, max, on_press):
self.value = value
self.max = max
self.on_press_impl = on_press
super().__init__(text, on_press=self.on_press_wrapper)

def on_press_wrapper(self, button):
self.value = (self.value + 1) % (self.max + 1)
self.on_press_impl(button)


class SizePanel(toga.Box):
def __init__(self, title, *, on_change):
self.on_change = on_change
self.width, self.height = (
SizeButton(text, value=1, max=6, on_press=self.on_press)
for text in ["W", "H"]
)
self.flex = SizeButton("F", value=0, max=3, on_press=self.on_press)
super().__init__(
style=Pack(direction=COLUMN, alignment="center"),
children=[
toga.Label(title.upper(), style=Pack(font_weight="bold")),
toga.Box(
style=Pack(direction=ROW),
children=[self.width, self.height, self.flex],
),
],
)
self.on_press(None)

def on_press(self, button):
self.on_change(self, self.width.value, self.height.value, self.flex.value)


class Resize(toga.App):
def startup(self):
self.text_label, self.style_label = (
toga.Label("", style=Pack(background_color="cyan")) for i in range(2)
)
main_box = toga.Box(
style=Pack(direction=COLUMN),
children=[
toga.Box(
style=Pack(direction=ROW),
children=[
SizePanel("Text", on_change=self.on_change_text),
toga.Box(style=Pack(flex=1)),
SizePanel("Style", on_change=self.on_change_style),
],
),
toga.Box(
style=Pack(direction=ROW),
children=[
self.text_label,
toga.Label("", style=Pack(background_color="pink", flex=1)),
toga.Label("", style=Pack(background_color="yellow", flex=1)),
self.style_label,
],
),
toga.Box(style=Pack(background_color="pink", flex=1)),
toga.Box(style=Pack(background_color="yellow", flex=1)),
],
)

self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()

def on_change_text(self, panel, width, height, flex):
text = "\n".join(" ".join("X" for i in range(width)) for j in range(height))
setattr_if_changed(self.text_label, "text", text)
setattr_if_changed(self.text_label.style, "flex", flex)

def on_change_style(self, panel, width, height, flex):
# Increment should be large enough that the minimum window width can be determined
# by either the buttons or the labels, depending on the labels' size.
INCREMENT = 70
setattr_if_changed(self.style_label.style, "width", width * INCREMENT)
setattr_if_changed(self.style_label.style, "height", height * INCREMENT)
setattr_if_changed(self.style_label.style, "flex", flex)


def setattr_if_changed(obj, name, value):
"""Ensure that each button click only changes one thing."""

old_value = getattr(obj, name)
if old_value != value:
setattr(obj, name, value)


def main():
return Resize("Resize", "org.beeware.resize")
Loading