diff --git a/changes/767.bugfix.rst b/changes/767.bugfix.rst new file mode 100644 index 0000000000..46592cd08c --- /dev/null +++ b/changes/767.bugfix.rst @@ -0,0 +1 @@ +On iOS, the default background color is now TRANSPARENT for Box, Canvas, ImageView, Label, ProgressBar, ScrollContainer and Slider widgets. diff --git a/iOS/src/toga_iOS/widgets/activityindicator.py b/iOS/src/toga_iOS/widgets/activityindicator.py index 4d17e4c8a0..36a480c918 100644 --- a/iOS/src/toga_iOS/widgets/activityindicator.py +++ b/iOS/src/toga_iOS/widgets/activityindicator.py @@ -1,6 +1,6 @@ from rubicon.objc import CGSize -from toga_iOS.libs import UIActivityIndicatorView +from toga_iOS.libs import UIActivityIndicatorView, UIColor from toga_iOS.widgets.base import Widget @@ -11,6 +11,7 @@ def create(self): self.native.translatesAutoresizingMaskIntoConstraints = False self.native.sizeToFit() + self._default_background_color = UIColor.clearColor self.add_constraints() def set_hidden(self, hidden): diff --git a/iOS/src/toga_iOS/widgets/base.py b/iOS/src/toga_iOS/widgets/base.py index 59cb4f241b..80d22c5481 100644 --- a/iOS/src/toga_iOS/widgets/base.py +++ b/iOS/src/toga_iOS/widgets/base.py @@ -90,20 +90,12 @@ 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 + default_background_color = getattr( + self, "_default_background_color", UIColor.secondarySystemBackgroundColor() + ) + self.native.backgroundColor = ( + default_background_color if color is None else native_color(color) + ) # INTERFACE def add_child(self, child): diff --git a/iOS/src/toga_iOS/widgets/box.py b/iOS/src/toga_iOS/widgets/box.py index 7a110c303c..8df0af9e03 100644 --- a/iOS/src/toga_iOS/widgets/box.py +++ b/iOS/src/toga_iOS/widgets/box.py @@ -1,7 +1,7 @@ from rubicon.objc import objc_property from travertino.size import at_least -from toga_iOS.libs import UIView +from toga_iOS.libs import UIColor, UIView from toga_iOS.widgets.base import Widget @@ -19,12 +19,10 @@ def create(self): self.native.interface = self.interface self.native.impl = self + self._default_background_color = UIColor.clearColor # 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) diff --git a/iOS/src/toga_iOS/widgets/button.py b/iOS/src/toga_iOS/widgets/button.py index c53bbb73ab..5c54060a0a 100644 --- a/iOS/src/toga_iOS/widgets/button.py +++ b/iOS/src/toga_iOS/widgets/button.py @@ -38,6 +38,7 @@ def create(self): self._icon = None + self._default_background_color = None # Add the layout constraints self.add_constraints() @@ -68,10 +69,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 diff --git a/iOS/src/toga_iOS/widgets/canvas.py b/iOS/src/toga_iOS/widgets/canvas.py index 9fc213f304..d241c8cc47 100644 --- a/iOS/src/toga_iOS/widgets/canvas.py +++ b/iOS/src/toga_iOS/widgets/canvas.py @@ -15,7 +15,7 @@ ) from travertino.size import at_least -from toga.colors import BLACK, TRANSPARENT, color +from toga.colors import BLACK, TRANSPARENT, color as toga_color from toga.constants import Baseline, FillRule from toga_iOS.colors import native_color from toga_iOS.images import nsdata_to_bytes @@ -70,6 +70,8 @@ def create(self): self.native.interface = self.interface self.native.impl = self + self._default_background_color = UIColor.clearColor + # Add the layout constraints self.add_constraints() @@ -260,7 +262,7 @@ def _line_height(self, font): def measure_text(self, text, font): # We need at least a fill color to render, but that won't change the size. sizes = [ - self._render_string(line, font, fill_color=color(BLACK)).size() + self._render_string(line, font, fill_color=toga_color(BLACK)).size() for line in text.splitlines() ] return ( diff --git a/iOS/src/toga_iOS/widgets/imageview.py b/iOS/src/toga_iOS/widgets/imageview.py index 02f5fc2866..bfe022bdf3 100644 --- a/iOS/src/toga_iOS/widgets/imageview.py +++ b/iOS/src/toga_iOS/widgets/imageview.py @@ -1,7 +1,5 @@ -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.libs import UIColor, UIImageView, UIViewContentMode from toga_iOS.widgets.base import Widget @@ -15,13 +13,9 @@ def create(self): self.native.setTranslatesAutoresizingMaskIntoConstraints_(False) self.native.setAutoresizesSubviews_(False) - self.add_constraints() + self._default_background_color = UIColor.clearColor - 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) + self.add_constraints() def set_image(self, image): if image: diff --git a/iOS/src/toga_iOS/widgets/label.py b/iOS/src/toga_iOS/widgets/label.py index 0426fc3cc8..008a82946e 100644 --- a/iOS/src/toga_iOS/widgets/label.py +++ b/iOS/src/toga_iOS/widgets/label.py @@ -3,11 +3,11 @@ 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, NSTextAlignment, + UIColor, UILabel, ) from toga_iOS.widgets.base import Widget @@ -38,6 +38,8 @@ def create(self): # We shouldn't ever word wrap; if faced with that option, clip. self.native.lineBreakMode = NSLineBreakByClipping + self._default_background_color = UIColor.clearColor + # Add the layout constraints self.add_constraints() @@ -47,12 +49,6 @@ def set_alignment(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) - def set_font(self, font): self.native.font = font._impl.native diff --git a/iOS/src/toga_iOS/widgets/multilinetextinput.py b/iOS/src/toga_iOS/widgets/multilinetextinput.py index 9959712e6f..81756699d0 100644 --- a/iOS/src/toga_iOS/widgets/multilinetextinput.py +++ b/iOS/src/toga_iOS/widgets/multilinetextinput.py @@ -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_alignment(self, value): self.native.textAlignment = NSTextAlignment(value) diff --git a/iOS/src/toga_iOS/widgets/numberinput.py b/iOS/src/toga_iOS/widgets/numberinput.py index cbb7ca0b45..4b99be0882 100644 --- a/iOS/src/toga_iOS/widgets/numberinput.py +++ b/iOS/src/toga_iOS/widgets/numberinput.py @@ -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)) diff --git a/iOS/src/toga_iOS/widgets/progressbar.py b/iOS/src/toga_iOS/widgets/progressbar.py index 3cbb80c03b..90cf6f6f35 100644 --- a/iOS/src/toga_iOS/widgets/progressbar.py +++ b/iOS/src/toga_iOS/widgets/progressbar.py @@ -2,7 +2,7 @@ from travertino.size import at_least -from toga_iOS.libs import CGSize, UIProgressView, UIProgressViewStyle +from toga_iOS.libs import CGSize, UIColor, UIProgressView, UIProgressViewStyle from toga_iOS.widgets.base import Widget # Implementation notes @@ -41,6 +41,8 @@ def create(self): self.native = UIProgressView.alloc().initWithProgressViewStyle_( UIProgressViewStyle.Default ) + self._default_background_color = UIColor.clearColor + self.add_constraints() self._running = False diff --git a/iOS/src/toga_iOS/widgets/scrollcontainer.py b/iOS/src/toga_iOS/widgets/scrollcontainer.py index de4fe7f1bf..8fa4e1074f 100644 --- a/iOS/src/toga_iOS/widgets/scrollcontainer.py +++ b/iOS/src/toga_iOS/widgets/scrollcontainer.py @@ -2,7 +2,7 @@ from travertino.size import at_least from toga_iOS.container import Container -from toga_iOS.libs import UIScrollView +from toga_iOS.libs import UIColor, UIScrollView from toga_iOS.widgets.base import Widget @@ -31,6 +31,8 @@ def create(self): self.native.impl = self self.native.delegate = self.native + self._default_background_color = UIColor.clearColor + # UIScrollView doesn't have a native ability to disable a scrolling direction; # it's handled by controlling the scrollable area. self._allow_horizontal = True @@ -68,9 +70,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) diff --git a/iOS/src/toga_iOS/widgets/selection.py b/iOS/src/toga_iOS/widgets/selection.py index 52af947f42..5cf2381948 100644 --- a/iOS/src/toga_iOS/widgets/selection.py +++ b/iOS/src/toga_iOS/widgets/selection.py @@ -83,9 +83,6 @@ def set_alignment(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 diff --git a/iOS/src/toga_iOS/widgets/slider.py b/iOS/src/toga_iOS/widgets/slider.py index 6db9758378..d7936930c5 100644 --- a/iOS/src/toga_iOS/widgets/slider.py +++ b/iOS/src/toga_iOS/widgets/slider.py @@ -2,6 +2,7 @@ from travertino.size import at_least from toga_iOS.libs import ( + UIColor, UIControlEventTouchCancel, UIControlEventTouchDown, UIControlEventTouchUpInside, @@ -49,6 +50,8 @@ def create(self): self.native.interface = self.interface self.native.impl = self + self._default_background_color = UIColor.clearColor + # Dummy values used during initialization. self.value = 0 self.min_value = 0 diff --git a/iOS/src/toga_iOS/widgets/textinput.py b/iOS/src/toga_iOS/widgets/textinput.py index 2397249bf7..9fc2d4a00a 100644 --- a/iOS/src/toga_iOS/widgets/textinput.py +++ b/iOS/src/toga_iOS/widgets/textinput.py @@ -138,9 +138,6 @@ def set_alignment(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 diff --git a/testbed/tests/widgets/test_button.py b/testbed/tests/widgets/test_button.py index 05025eb308..3def3771cf 100644 --- a/testbed/tests/widgets/test_button.py +++ b/testbed/tests/widgets/test_button.py @@ -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)