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

background_color Transparency Fixes #2484

Open
wants to merge 62 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
1e75114
Fixed transparency related bugs
proneon267 Apr 5, 2024
1e075fa
Minor tweaks
proneon267 Apr 5, 2024
ca50f58
Fixed cocoa table widget
proneon267 Apr 6, 2024
6c1aeea
Added changelog
proneon267 Apr 6, 2024
24abf08
Fixed test
proneon267 Apr 6, 2024
a94f0de
Fixed iOS progressbar
proneon267 Apr 6, 2024
c30aa56
Fixed android canvas test
proneon267 Apr 7, 2024
6fe78dd
Removed mocking from android canvas test
proneon267 Apr 7, 2024
4a242dd
Removed test debugging modification
proneon267 Apr 7, 2024
054e07b
Fixed android divider background_color
proneon267 Apr 7, 2024
6b1bf9e
Empty commit for CI
proneon267 Apr 7, 2024
4b5ed6f
Fixed winforms divider implementation
proneon267 Apr 7, 2024
77df2e9
Fixed winforms label transparency
proneon267 Apr 7, 2024
6981a7a
Fixed winforms box transparency
proneon267 Apr 9, 2024
b2ca091
Fixed winforms box test
proneon267 Apr 9, 2024
1b3122c
Fixed ackground_color and transparency on WinForms
proneon267 Apr 13, 2024
c767a5b
Empty commit for CI
proneon267 Apr 13, 2024
9921d79
Preliminary test to check for failures on all platforms
proneon267 Apr 25, 2024
06d40e1
Minor change on probes to run the tests
proneon267 Apr 25, 2024
9254e18
Fix winforms implementation and tests
proneon267 Apr 25, 2024
e53879d
Minor change on winforms
proneon267 Apr 25, 2024
d43aba4
Empty commit for CI
proneon267 Apr 25, 2024
059578f
100% coverage on winforms
proneon267 Apr 28, 2024
298d460
100% coverage on android
proneon267 May 5, 2024
c6382c3
Merge branch 'beeware:main' into transparency_fix
proneon267 May 5, 2024
e5e3e07
Minor modification on testbed
proneon267 May 7, 2024
ca4d5d9
Merge branch 'main' of https://github.com/proneon267/toga into transp…
proneon267 May 7, 2024
8c62422
Minor fix
proneon267 May 7, 2024
b0c8613
Merge branch 'transparency_fix' of https://github.com/proneon267/toga…
proneon267 May 7, 2024
b6cf7d5
Merge branch 'beeware:main' into transparency_fix
proneon267 May 7, 2024
4b7991d
Minor change on gtk
proneon267 May 7, 2024
9e354f8
Empty commit to restart CI for macOS
proneon267 May 7, 2024
71f461b
Minor modifications for testbed
proneon267 May 8, 2024
b2f73a7
Modifications on iOS
proneon267 May 8, 2024
a0e141f
Minor modification for transparency
proneon267 May 8, 2024
350b9d0
Minor modification on testbed
proneon267 May 8, 2024
aad928c
Minor modification on android test backend
proneon267 May 8, 2024
9e11129
Modifications on cocoa
proneon267 May 9, 2024
4aaedd4
Minor modification on cocoa
proneon267 May 9, 2024
a1cf579
Code cleanups
proneon267 May 9, 2024
2bb6a39
Fix typo
proneon267 May 9, 2024
c9c714e
Merge branch 'main' into transparency_fix
freakboy3742 May 28, 2024
553ac6e
Revert name changes
proneon267 May 30, 2024
2f657db
Merge branch 'transparency_fix' of https://github.com/proneon267/toga…
proneon267 May 30, 2024
f63859c
Re: Revert name changes
proneon267 May 30, 2024
3e0f883
Merge branch 'beeware:main' into transparency_fix
proneon267 May 30, 2024
6f75e5f
Re: Revert name changes
proneon267 May 30, 2024
a88cc13
Re: Revert name changes
proneon267 May 30, 2024
221fd10
Fixed background color assertion
proneon267 Jun 8, 2024
dbe7b42
Added default background color attribute to winforms widgets
proneon267 Jun 8, 2024
3054df1
Removed unused branch
proneon267 Jun 8, 2024
135741f
Modified as per review
proneon267 Jun 11, 2024
5991cd2
Modified as per review
proneon267 Jun 11, 2024
165d4b9
Update testbed/tests/widgets/test_button.py
proneon267 Jun 12, 2024
b2d0c47
Update testbed/tests/widgets/test_button.py
proneon267 Jun 12, 2024
a077b0e
Modified as per review
proneon267 Jun 12, 2024
d2bfbfb
Merge branch 'transparency_fix' of https://github.com/proneon267/toga…
proneon267 Jun 12, 2024
544802c
Merge branch 'beeware:main' into transparency_fix
proneon267 Jun 12, 2024
db05029
Added default background color attribute to iOS widgets
proneon267 Jun 13, 2024
f7687a8
Added default background color attribute to iOS widgets
proneon267 Jun 13, 2024
4e4a82e
Update 2484.bugfix.2.rst
proneon267 Jun 13, 2024
0ff7752
Merge branch 'beeware:main' into transparency_fix
proneon267 Jun 16, 2024
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
5 changes: 1 addition & 4 deletions testbed/tests/widgets/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,6 @@ async def test_background_color(widget, probe):
for color in COLORS:
widget.style.background_color = color
await probe.redraw("Widget background color should be %s" % color)
if not getattr(probe, "background_supports_alpha", True):
color.a = 1
assert_color(probe.background_color, color)


Expand All @@ -405,12 +403,11 @@ async def test_background_color_reset(widget, probe):
async def test_background_color_transparent(widget, probe):
"Background transparency is supported"
original = probe.background_color
supports_alpha = getattr(probe, "background_supports_alpha", True)

# Change the background color to transparent
widget.style.background_color = TRANSPARENT
await probe.redraw("Widget background color should be TRANSPARENT")
assert_color(probe.background_color, TRANSPARENT if supports_alpha else original)
assert_color(probe.background_color, TRANSPARENT)

# Restore original background color
del widget.style.background_color
Expand Down
58 changes: 53 additions & 5 deletions winforms/src/toga_winforms/colors.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,64 @@
from System.Drawing import Color
from travertino.colors import TRANSPARENT
from travertino.colors import TRANSPARENT, rgb, rgba

CACHE = {TRANSPARENT: Color.Transparent}


def native_color(c):
def native_color(toga_color):
try:
color = CACHE[c]
color = CACHE[toga_color]
except KeyError:
color = Color.FromArgb(
int(c.rgba.a * 255), int(c.rgba.r), int(c.rgba.g), int(c.rgba.b)
int(toga_color.rgba.a * 255),
int(toga_color.rgba.r),
int(toga_color.rgba.g),
int(toga_color.rgba.b),
)
CACHE[c] = color
CACHE[toga_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.

toga_color is also a method, so there's an inherent ambiguity here.


return color


def toga_color(native_color):
return rgba(native_color.R, native_color.G, native_color.B, native_color.A / 255)


def alpha_blending_over_operation(child_color, parent_color):
Copy link
Member

Choose a reason for hiding this comment

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

The use of child and parent nomenclature here presupposes the usage. Alpha blending is a generic task; back and front (or similar) would be better terminology.

I'd also be inclined to add this as a utility in core (or possibly even in Travertino). Although we're not actually using this anywhere other than Winforms, the generic ability to do alpha blending isn't a bad thing to have, and it would allow us to explicitly test the blending API with core tests, rather than implicitly testing it through usage in Winforms.

# The blending operation I have implemented here is the "over" operation and
Copy link
Member

Choose a reason for hiding this comment

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

Code comments generally shouldn't refer to the author. We're describing the current state of the code, which isn't dependent on any one author.

# replicates CSS's rgba mechanism. For the formula used here, see:
# https://en.wikipedia.org/wiki/Alpha_compositing#Description

blended_alpha = child_color.a + ((1 - child_color.a) * parent_color.a)

# Check if the blended alpha is zero, indicating no blending
if blended_alpha == 0:
# If both child and parent alphas are 0, no blending occurs, so return child color.
return child_color

blended_color = rgb(
# Red Component
(
(
(child_color.r * child_color.a)
+ (parent_color.r * parent_color.a * (1 - child_color.a))
)
/ blended_alpha
),
# Green Component
(
(
(child_color.g * child_color.a)
+ (parent_color.g * parent_color.a * (1 - child_color.a))
)
/ blended_alpha
),
# Blue Component
(
(
(child_color.b * child_color.a)
+ (parent_color.b * parent_color.a * (1 - child_color.a))
)
/ blended_alpha
),
)
return blended_color
43 changes: 24 additions & 19 deletions winforms/src/toga_winforms/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
from decimal import ROUND_HALF_EVEN, Decimal

from System.Drawing import (
Color,
Point,
Size,
SystemColors,
)
from travertino.size import at_least

from toga.colors import TRANSPARENT
from toga_winforms.colors import native_color
import toga
from toga.colors import TRANSPARENT, rgba
from toga_winforms.colors import alpha_blending_over_operation, native_color, toga_color


class Scalable:
Expand All @@ -37,10 +37,6 @@ def scale_round(self, value, rounding):


class Widget(ABC, Scalable):
# In some widgets, attempting to set a background color with any alpha value other
# than 1 raises "System.ArgumentException: Control does not support transparent
# background colors". Those widgets should set this attribute to False.
_background_supports_alpha = True

def __init__(self, interface):
self.interface = interface
Expand Down Expand Up @@ -119,17 +115,27 @@ def set_color(self, color):
self.native.ForeColor = native_color(color)

def set_background_color(self, color):
if not hasattr(self, "_default_background"):
self._default_background = self.native.BackColor
if color is None or (
color == TRANSPARENT and not self._background_supports_alpha
):
self.native.BackColor = self._default_background
if color is None or (color == TRANSPARENT and (not self.interface.parent)):
self.native.BackColor = SystemColors.Control
else:
win_color = native_color(color)
if not self._background_supports_alpha:
win_color = Color.FromArgb(255, win_color.R, win_color.G, win_color.B)
self.native.BackColor = win_color
if self.interface.parent:
parent_color = toga_color(
self.interface.parent._impl.native.BackColor
).rgba
if color is TRANSPARENT:
requested_color = rgba(0, 0, 0, 0)
else:
requested_color = color.rgba
blended_color = alpha_blending_over_operation(
requested_color, parent_color
)
self.native.BackColor = native_color(blended_color)
else:
self.native.BackColor = 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.

This branch is dealing with setting the color on the root element (i.e, parent is None); what happens if color has an alpha value (i.e., set the background color of the root element to 0.5 opacity red)? Do we need to do an alpha blend with SystemColors.Control?


if isinstance(self.interface, toga.Box):
Copy link
Member

Choose a reason for hiding this comment

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

This shouldn't be an explicit type check for Box. self.interface.children is None is a better check for widgets that cannot have children; if children is not None, then there are children to work with.

for child in self.interface.children:
child._impl.set_background_color(child.style.background_color)

# INTERFACE

Expand All @@ -151,8 +157,7 @@ def refresh(self):
# doesn't actually support transparency. It just copies the parent's
# BackColor to the widget. So, if a widget's parent changes then we need
# to reapply background_color to copy the new parent's BackColor.
if self.interface.style.background_color in {None, TRANSPARENT}:
self.set_background_color(self.interface.style.background_color)
self.set_background_color(self.interface.style.background_color)
Copy link
Member

Choose a reason for hiding this comment

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

I can see that re-application will be necessary, but it's not clear to me why this is happening in refresh. Refresh is a layout calculation mechanism; it shouldn't be interacting with color choices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure where should I move the re-application call to. I had thought refresh was to be used for reapplying changes related to both layout changes and style changes.

Copy link
Member

Choose a reason for hiding this comment

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

No - refresh is an internal trigger when something affecting widget layout has occurred - something that could change the size of the widget.

set_background_color() will be invoked when any style element that alters the background color of a widget changes.

What is the sequence of events that requires a call in refresh? How do you manufacture a problem that is resolved by this line of code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The background color needs to be reapplied when the widget's parent changes. Since refresh should be used for layout, I have moved the call to reapply background color, to the widget's container setter - as that is the place where the widget's parent changes.


def rehint(self):
pass
9 changes: 0 additions & 9 deletions winforms/src/toga_winforms/widgets/box.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import System.Windows.Forms as WinForms

from toga.colors import TRANSPARENT

from .base import Widget


class Box(Widget):
def create(self):
self.native = WinForms.Panel()

def set_background_color(self, color):
if color in {None, TRANSPARENT}:
if self.interface.parent:
self.native.BackColor = self.interface.parent._impl.native.BackColor
else:
super().set_background_color(color)
9 changes: 8 additions & 1 deletion winforms/src/toga_winforms/widgets/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import System.Windows.Forms as WinForms
from travertino.size import at_least

from toga.colors import TRANSPARENT

from ..libs.wrapper import WeakrefCallable
from .base import Widget


class Button(Widget):
_background_supports_alpha = False

def create(self):
self.native = WinForms.Button()
Expand Down Expand Up @@ -44,6 +45,12 @@ def set_icon(self, icon):
else:
self.native.Image = None

def set_background_color(self, color):
if color in {None, TRANSPARENT}:
super().set_background_color(None)
else:
super().set_background_color(color)

def rehint(self):
self.interface.intrinsic.width = self.scale_out(
at_least(self.native.PreferredSize.Width), ROUND_UP
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/dateinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ def native_date(py_date):


class DateInput(Widget):
_background_supports_alpha = False

def create(self):
self.native = WinForms.DateTimePicker()
Expand Down
4 changes: 2 additions & 2 deletions winforms/src/toga_winforms/widgets/divider.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from decimal import ROUND_UP

import System.Windows.Forms as WinForms
from System.Drawing import Color
from System.Drawing import SystemColors
from travertino.size import at_least

from .base import Widget
Expand Down Expand Up @@ -29,7 +29,7 @@ def set_direction(self, value):
def set_background_color(self, color):
if color is None:
# Background color needs to be set or else divider will not be visible.
self.native.BackColor = Color.Gray
self.native.BackColor = SystemColors.ControlDark
else:
super().set_background_color(color)

Expand Down
18 changes: 0 additions & 18 deletions winforms/src/toga_winforms/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import System.Windows.Forms as WinForms
from travertino.size import at_least

from toga.colors import TRANSPARENT
from toga_winforms.libs.fonts import TextAlignment

from .base import Widget
Expand All @@ -23,23 +22,6 @@ def get_text(self):
def set_text(self, value):
self.native.Text = value

def set_background_color(self, color):
if color in {None, TRANSPARENT}:
# Label though allows setting BackColor to Color.Transparent, but it doesn't
# actually work, the background color will be white when set to Color.Transparent
# Also tried:
# ```
# label1.Parent = pictureBox1
# label1.BackColor = Color.Transparent
# ```
# But it only works if the label is inside/above a PictureBox and not for other cases.
# So, the best bet for transparency is to make label background color same as the
# container inside which the widget is present.
if self.interface.parent:
self.native.BackColor = self.interface.parent._impl.native.BackColor
else:
super().set_background_color(color)

def rehint(self):
self.interface.intrinsic.width = self.scale_out(
at_least(self.native.PreferredSize.Width), ROUND_UP
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/numberinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def native_decimal(value):


class NumberInput(Widget):
_background_supports_alpha = False

def create(self):
self.native = WinForms.NumericUpDown()
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/progressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@


class ProgressBar(Widget):
_background_supports_alpha = False

TOGA_SCALE = 1000

Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def winforms_selected_index_changed(self, sender, event):


class Selection(Widget):
_background_supports_alpha = False

def create(self):
self.native = TogaComboBox(self)
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@


class Table(Widget):
_background_supports_alpha = False

# The following methods are overridden in DetailedList.
@property
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/textinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@


class TextInput(Widget):
_background_supports_alpha = False

def create(self):
self.native = WinForms.TextBox()
Expand Down
1 change: 0 additions & 1 deletion winforms/src/toga_winforms/widgets/timeinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def native_time(py_time):


class TimeInput(Widget):
_background_supports_alpha = False

def create(self):
self.native = WinForms.DateTimePicker()
Expand Down
29 changes: 25 additions & 4 deletions winforms/tests_backend/widgets/base.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import pytest
from pytest import approx
from System import EventArgs, Object
from System.Drawing import Color, SystemColors
from System.Drawing import SystemColors
from System.Windows.Forms import MouseButtons, MouseEventArgs

from toga.colors import TRANSPARENT
from toga.style.pack import JUSTIFY, LEFT
from toga_winforms.colors import alpha_blending_over_operation

from ..fonts import FontMixin
from ..probe import BaseProbe
from .properties import toga_color
from .properties import reverse_alpha_blending_over_operation, toga_color


class SimpleProbe(BaseProbe, FontMixin):
Expand Down Expand Up @@ -56,10 +57,30 @@ def color(self):

@property
def background_color(self):
if self.native.BackColor == Color.Transparent:
if (
self.widget.style.background_color is None
and self.native.BackColor.ToArgb() == SystemColors.Control.ToArgb()
):
return None

if self.widget.style.background_color is TRANSPARENT and (
self.native.BackColor.ToArgb()
== self.widget.parent._impl.native.BackColor.ToArgb()
):
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't seem quite right. The purpose of the probe is to return an "independent observer" value for things being tested - in this case, color. If we're testing how color and transparency works, we can't really include style.background color as part of that comparison.

On top of that, the second if will fail if invoked on the root widget in a tree (because it won't have a parent).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't seem quite right. The purpose of the probe is to return an "independent observer" value for things being tested - in this case, color. If we're testing how color and transparency works, we can't really include style.background color as part of that comparison.

I am not sure if there is an easy way out of this. To the native winforms, the blended colors all have an alpha value of 1. This is important because including an alpha component in the blended color whose value is not 1, will make winforms perform additional calculation and produce wrong results, since we are handling the alpha blending ourselves.

For example, if a child requests a background color of (0,0,255,0) and the parent has a background color of (255,0,0,1). Then the blended color would be (255,0,0,1). So, if we were to query to the native winforms about the color of the child, then it would report it as (255,0,0,1). So, now we would have no idea if the child background color was (0,0,255,0) or TRANSPARENT, because in both cases the blended color will be (255,0,0,1).

Though it may seem that (0,0,255,0) and TRANSPARENT are same, but the as the value of alpha increases between 0 to 1, the results would be vastly different. And the original requested color is something, we need to preserve in order to enable the user to make minor changes(like increasing or decreasing the alpha value) to the background color later on.

It is also evident from the reverse_alpha_blending_over_operation on the probe, that the original requested alpha value cannot be recovered from the blended color and the parent alone; We need the original requested color along with its alpha value.

Copy link
Member

Choose a reason for hiding this comment

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

The key idea that you need to keep in mind is what is the purpose of this test? We're not just trying to make the coverage check stop complaining - we're trying to validate correct behavior. In this case, that means getting the most independent possible validation that the color on a specific widget is correct. style.background_color is the thing we're trying to test; involving that value in the test is, at best, a weak test.

So how do we fix this? Well, the underlying problem is that on most platforms, we can compare the literal Conor; but on Winforms, we need to differentiate the transparent cases from the non-transparent cases.

So... do that. Differentiate the test cases. Have different tests, with different test assertions for transparent colors.

This might require modifying assert_color() so that there are 2 "expected" colors - the test color, and the alpha-blended color. Although the alpha-blended color is only needed in the Windows case, the test data isn't Windows specific - it's hypothetically possible that other backends might need to do this sort of blending; and you could imagine a theoretical probe on macOS that is able to inspect the display and return the actual displayed color of a specific pixel, and compare that to "blended" value (I'm not suggesting you do this last part - just pointing out that there's a difference between an "if windows" branch in a test, and writing a test in a way that the test case has multiple ways to evaluate success).

Alternatively - make assert_color a probe-level function. On most platforms, the implementation is the same as the current assert_color; but Winforms might need an implementation that does some sort of soft "is color compatible" comparison when the expected color is transparent. This may mean you pass in some additional arguments (such as details about the parent) that are ignored on most platforms, but used on Winforms.

It might even turn out that a combination of these approaches yields the best result - I haven't sat down and worked out all the details. What I'm pointing out is that when you're faced with a novel problem, sometimes you need to change the test, rather than trying to cram the novel problem into the existing test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you, modifications in either the tests or the probe or even both might be needed. I'll do more research and tests and report back to you.

return TRANSPARENT
else:
return toga_color(self.native.BackColor)
parent_color = toga_color(self.widget.parent._impl.native.BackColor)
Copy link
Member

Choose a reason for hiding this comment

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

Again - this requires that parent exists.

blended_color = alpha_blending_over_operation(
self.widget.style.background_color, parent_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 above - the value of background_color shouldn't matter; we're trying to establish ground truth.

if blended_color == parent_color:
return self.widget.style.background_color
else:
return reverse_alpha_blending_over_operation(
blended_color,
parent_color,
child_alpha=self.widget.style.background_color.rgba.a,
)

@property
def font(self):
Expand Down
10 changes: 0 additions & 10 deletions winforms/tests_backend/widgets/box.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import System.Windows.Forms

from toga.colors import TRANSPARENT

from .base import SimpleProbe
from .properties import toga_color


class BoxProbe(SimpleProbe):
native_class = System.Windows.Forms.Panel

@property
def background_color(self):
if self.native.BackColor == self.widget.parent._impl.native.BackColor:
return TRANSPARENT
else:
return toga_color(self.native.BackColor)
Loading
Loading