Skip to content

Commit

Permalink
Merge pull request #1794 from mhsmith/gtk-containers
Browse files Browse the repository at this point in the history
Modify container handling for GTK
  • Loading branch information
freakboy3742 authored Mar 5, 2023
2 parents 26ed94e + b58bb1b commit 4f6f7ab
Show file tree
Hide file tree
Showing 54 changed files with 510 additions and 253 deletions.
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)
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()

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()

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

0 comments on commit 4f6f7ab

Please sign in to comment.