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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
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.
3 changes: 2 additions & 1 deletion iOS/src/toga_iOS/widgets/activityindicator.py
Original file line number Diff line number Diff line change
@@ -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


Expand All @@ -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):
Expand Down
20 changes: 6 additions & 14 deletions iOS/src/toga_iOS/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Member

Choose a reason for hiding this comment

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

Why secondarySystemBackgroundColor? This is a fairly big change - and looking at the most recent sample screenshot, it definitely doesn't look right for switch, and it's arguable whether it's correct for TextInput, MultilineTextInput et al

)
self.native.backgroundColor = (
default_background_color if color is None else native_color(color)
)

# INTERFACE
def add_child(self, child):
Expand Down
6 changes: 2 additions & 4 deletions iOS/src/toga_iOS/widgets/box.py
Original file line number Diff line number Diff line change
@@ -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


Expand All @@ -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)
6 changes: 2 additions & 4 deletions iOS/src/toga_iOS/widgets/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def create(self):

self._icon = None

self._default_background_color = None
# Add the layout constraints
self.add_constraints()

Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions iOS/src/toga_iOS/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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 (
Expand Down
12 changes: 3 additions & 9 deletions iOS/src/toga_iOS/widgets/imageview.py
Original file line number Diff line number Diff line change
@@ -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


Expand All @@ -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:
Expand Down
10 changes: 3 additions & 7 deletions iOS/src/toga_iOS/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand All @@ -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

Expand Down
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/multilinetextinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/numberinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 3 additions & 1 deletion iOS/src/toga_iOS/widgets/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions iOS/src/toga_iOS/widgets/scrollcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions iOS/src/toga_iOS/widgets/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from travertino.size import at_least

from toga_iOS.libs import (
UIColor,
UIControlEventTouchCancel,
UIControlEventTouchDown,
UIControlEventTouchUpInside,
Expand Down Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions iOS/src/toga_iOS/widgets/textinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions testbed/tests/widgets/test_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Loading