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

Set default background color for widgets on iOS #3009

Merged
merged 13 commits into from
Jan 9, 2025
Merged
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
1 change: 1 addition & 0 deletions changes/767.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
On iOS, the default background color is now TRANSPARENT for Box, Canvas, ImageView, Label, ProgressBar, ScrollContainer and Slider widgets.
16 changes: 1 addition & 15 deletions iOS/src/toga_iOS/widgets/base.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@

from toga_iOS.colors import native_color
from toga_iOS.constraints import Constraints
from toga_iOS.libs import UIColor


class Widget:
@@ -88,20 +87,7 @@ def set_color(self, color):
pass

def set_background_color(self, color):
# By default, background color can't be changed
pass

# TODO: check if it's safe to make this the default implementation.
def set_background_color_simple(self, value):
if value:
self.native.backgroundColor = native_color(value)
else:
try:
# systemBackgroundColor() was introduced in iOS 13
# We don't test on iOS 12, so mark the other branch as nocover
self.native.backgroundColor = UIColor.systemBackgroundColor()
except AttributeError: # pragma: no cover
self.native.backgroundColor = UIColor.whiteColor
self.native.backgroundColor = None if color is None else native_color(color)

# INTERFACE
def add_child(self, child):
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/box.py
Original file line number Diff line number Diff line change
@@ -22,9 +22,6 @@ def create(self):
# Add the layout constraints
self.add_constraints()

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

def rehint(self):
self.interface.intrinsic.width = at_least(0)
self.interface.intrinsic.height = at_least(0)
5 changes: 1 addition & 4 deletions iOS/src/toga_iOS/widgets/button.py
Original file line number Diff line number Diff line change
@@ -68,10 +68,7 @@ def set_color(self, color):
)

def set_background_color(self, color):
if color == TRANSPARENT or color is None:
self.native.backgroundColor = None
else:
self.native.backgroundColor = native_color(color)
super().set_background_color(None if color in {None, TRANSPARENT} else color)

def set_font(self, font):
self.native.titleLabel.font = font._impl.native
8 changes: 0 additions & 8 deletions iOS/src/toga_iOS/widgets/imageview.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from toga.colors import TRANSPARENT
from toga.widgets.imageview import rehint_imageview
from toga_iOS.colors import native_color
from toga_iOS.libs import UIImageView, UIViewContentMode
from toga_iOS.widgets.base import Widget

@@ -17,12 +15,6 @@ def create(self):

self.add_constraints()

def set_background_color(self, color):
if color == TRANSPARENT or color is None:
self.native.backgroundColor = native_color(TRANSPARENT)
else:
self.native.backgroundColor = native_color(color)

def set_image(self, image):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the same implementation as Button... why hasn't the implementation changed in the same way?

Copy link
Contributor Author

@proneon267 proneon267 Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, the implementation of Button was:

def set_background_color(self, color):
    if color == TRANSPARENT or color is None:
        self.native.backgroundColor = None
    else:
        self.native.backgroundColor = native_color(color)

Here, TRANSPARENT and None are shorted to None, as the behavior of setting transparent or resetting the button background color is restoring to the original background color, like on other backends.

While the previous implementation of ImageView was:

def set_background_color(self, color):
    if color == TRANSPARENT or color is None:
        self.native.backgroundColor = native_color(TRANSPARENT)
    else:
        self.native.backgroundColor = native_color(color)

Here, TRANSPARENT and None are instead shorted to TRANSPARENT. Hence, the backgroundColor implementation is different from Button.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah - they're very similar, but not quite the same; the key difference being that Button is explicitly changing the interpretation of TRANSPARENT to "reset", whereas imageview/label are using the default interpretation (and relying on the fact that "clearColor" and "None" are effectively the same on iOS for these widgets). Thanks for the clarification.

if image:
self.native.image = image._impl.native
7 changes: 0 additions & 7 deletions iOS/src/toga_iOS/widgets/label.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@
from rubicon.objc import CGRect, NSInteger, NSMakeRect, objc_method, send_super
from travertino.size import at_least

from toga.colors import TRANSPARENT
from toga_iOS.colors import native_color
from toga_iOS.libs import (
NSLineBreakByClipping,
@@ -47,12 +46,6 @@ def set_text_align(self, value):
def set_color(self, value):
self.native.textColor = native_color(value)

def set_background_color(self, color):
if color == TRANSPARENT or color is None:
self.native.backgroundColor = native_color(TRANSPARENT)
else:
self.native.backgroundColor = native_color(color)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As with ImageView - why does the implementation change not match Button?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as #3009 (comment)


def set_font(self, font):
self.native.font = font._impl.native

3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/multilinetextinput.py
Original file line number Diff line number Diff line change
@@ -141,9 +141,6 @@ def set_color(self, value):
self.native.textColor = color
self.placeholder_label.textColor = color

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

def set_text_align(self, value):
self.native.textAlignment = NSTextAlignment(value)

3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/numberinput.py
Original file line number Diff line number Diff line change
@@ -117,9 +117,6 @@ def set_font(self, font):
def set_color(self, color):
self.native.textColor = native_color(color)

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

def rehint(self):
# Height of a text input is known.
fitting_size = self.native.systemLayoutSizeFittingSize(CGSize(0, 0))
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/scrollcontainer.py
Original file line number Diff line number Diff line change
@@ -68,9 +68,6 @@ def content_refreshed(self, container):

self.native.contentSize = NSMakeSize(width, height)

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

def rehint(self):
self.interface.intrinsic.width = at_least(self.interface._MIN_WIDTH)
self.interface.intrinsic.height = at_least(self.interface._MIN_HEIGHT)
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/selection.py
Original file line number Diff line number Diff line change
@@ -83,9 +83,6 @@ def set_text_align(self, value):
def set_color(self, color):
self.native.textColor = native_color(color)

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

def set_font(self, font):
self.native.font = font._impl.native

3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/textinput.py
Original file line number Diff line number Diff line change
@@ -138,9 +138,6 @@ def set_text_align(self, value):
def set_color(self, color):
self.native.textColor = native_color(color)

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

def set_font(self, font):
self.native.font = font._impl.native

7 changes: 5 additions & 2 deletions testbed/tests/widgets/test_button.py
Original file line number Diff line number Diff line change
@@ -101,6 +101,9 @@ async def test_press(widget, probe):

async def test_background_color_transparent(widget, probe):
"Buttons treat background transparency as a color reset."
del widget.style.background_color
original_background_color = probe.background_color

widget.style.background_color = TRANSPARENT
await probe.redraw("Button background color should be transparent")
assert_color(probe.background_color, None)
await probe.redraw("Button background color should be reset to the default color")
assert_color(probe.background_color, original_background_color)