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

[widget audit] toga.Button #1761

Merged
merged 66 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
92fd082
Whitespace change to use as the starting point for a PR.
freakboy3742 Jan 31, 2023
d206715
Add changenote.
freakboy3742 Jan 31, 2023
9fdf46e
Fix tracing on Windows
mhsmith Jan 31, 2023
38bd4d6
Migrate dummy widget tools to pytest.
freakboy3742 Feb 1, 2023
b541c09
Remove use of shadow attribute for button label.
freakboy3742 Feb 1, 2023
7077562
Convert Button tests to pytest.
freakboy3742 Feb 1, 2023
ec04ddc
Fix Android tests, get to 100% coverage.
freakboy3742 Feb 1, 2023
859ad48
Fix get_text implementation on gtk and winforms.
freakboy3742 Feb 1, 2023
f93158e
100% coverage on iOS.
freakboy3742 Feb 1, 2023
67f3374
Remove deprecated code from Button.
freakboy3742 Feb 1, 2023
ca8a760
Winforms to 100%.
freakboy3742 Feb 1, 2023
8a03783
GTK to 100%.
freakboy3742 Feb 1, 2023
37985ae
Winforms to 100%, no skips.
freakboy3742 Feb 2, 2023
2b9714e
Add test selection from the command line, and a slow mode.
freakboy3742 Feb 3, 2023
2ea497e
Fix and mark tests that aren't reliable
freakboy3742 Feb 6, 2023
c8e41b1
Updated dummy assertions to be simple functions.
freakboy3742 Feb 6, 2023
a07ebde
GTK Button color tests passing.
freakboy3742 Feb 7, 2023
e6c3096
Add a warning about UI animations.
freakboy3742 Feb 8, 2023
163fa97
Re-enable the button size test.
freakboy3742 Feb 16, 2023
8c24cbe
Correct handling of color for non-button widgets.
freakboy3742 Feb 16, 2023
df7c13e
Remove refresh calls that aren't needed any more.
freakboy3742 Feb 16, 2023
d1fdf8b
Removed the xfail marker from some tests.
freakboy3742 Feb 16, 2023
2e7f8d0
Modified the color test to assert all components in one assertion.
freakboy3742 Feb 20, 2023
da9c1ba
Use a programmatic approach to disable animations.
freakboy3742 Feb 20, 2023
50c4fee
iOS Button tests to 100%.
freakboy3742 Feb 22, 2023
4a2944f
iOS button to 100%.
freakboy3742 Feb 24, 2023
fe92bb9
Partial fixes for Android colors and fonts.
freakboy3742 Feb 24, 2023
73f0c5a
Implement `await redraw` for Android
mhsmith Feb 26, 2023
2ff0e95
Fix Android font size calculation
mhsmith Feb 26, 2023
e6ed1c1
Fix button background color
mhsmith Feb 27, 2023
db63ecc
Modify font size and font handling.
freakboy3742 Feb 28, 2023
493e722
Add support for resetting foreground color.
freakboy3742 Feb 28, 2023
c3d5c8a
Ensure size probes return SP not DP.
freakboy3742 Feb 28, 2023
542faf7
Use del rather than assigning None to clear style.
freakboy3742 Feb 28, 2023
d3581ec
Don't allow newlines in button text.
freakboy3742 Feb 28, 2023
e1458ba
Correct label color tests.
freakboy3742 Feb 28, 2023
32451bd
Button at 100% on all tested platforms!
freakboy3742 Feb 28, 2023
c788a8c
Rework the EventLog so it is global.
freakboy3742 Feb 28, 2023
da5105a
Disallow empty labels on buttons.
freakboy3742 Feb 28, 2023
5bf1cbb
Revert a libs restructure.
freakboy3742 Feb 28, 2023
29924f0
More tweaks to the dummy test assertions.
freakboy3742 Feb 28, 2023
7e2bc2d
Removed a redundant background color implementation.
freakboy3742 Feb 28, 2023
8211f8b
Add notes about button text restrictions.
freakboy3742 Feb 28, 2023
8cd8531
Merge branch 'main' into audit-button
freakboy3742 Mar 5, 2023
857d899
Change `= None` tests to `del`, for compatibility with travertino mai…
mhsmith Mar 13, 2023
7bd87a5
Fix Android font size, and add font size reset test
mhsmith Mar 13, 2023
16ec542
Add memory retention for cached font instances.
freakboy3742 Mar 13, 2023
8bd9528
Merge branch 'system-ci' into audit-button
mhsmith Mar 14, 2023
e83f2fa
Allow default font to be returned as SANS_SERIF as well as SYSTEM
mhsmith Mar 14, 2023
81e2d29
Add examples/font_size
mhsmith Mar 14, 2023
02a345d
Add bold and italic font tests (working on Android, Cocoa and iOS)
mhsmith Mar 16, 2023
9248973
Add bold and italic font tests (working on GTK and Winforms)
mhsmith Mar 17, 2023
45e52e6
Remove redundant set_font methods in dummy widgets
mhsmith Mar 17, 2023
8445dae
Merge branch 'main' into audit-button
freakboy3742 Mar 20, 2023
c646ef0
Improve comments
mhsmith Mar 20, 2023
e2da16b
Move generic font mapping assertions to tests_backend (Android, Cocoa…
mhsmith Mar 20, 2023
926c3d6
Move generic font mapping assertions to tests_backend (GTK)
mhsmith Mar 20, 2023
7f96efa
Move generic font mapping assertions to tests_backend (Winforms)
mhsmith Mar 20, 2023
36ed554
Fix typos
mhsmith Mar 20, 2023
091e3ec
Allow Button text to be set to an empty string, and make Winforms dis…
mhsmith Mar 20, 2023
dd73a9b
Use subclassing rather than an isinstance check.
freakboy3742 Mar 20, 2023
cfdc3e5
Revert the use of an interface state variable for button text.
freakboy3742 Mar 21, 2023
ce54201
Mark some classes with Test in the name as not-tests.
freakboy3742 Mar 21, 2023
5abe2f1
Tweak section heading.
freakboy3742 Mar 21, 2023
f76c90a
Modify the winforms button probe to do ZWS normalization.
freakboy3742 Mar 21, 2023
8f55716
Use correct zero width space character, and remove unnecessary workar…
mhsmith Mar 21, 2023
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
Prev Previous commit
Next Next commit
Partial fixes for Android colors and fonts.
  • Loading branch information
freakboy3742 committed Feb 25, 2023
commit fe92bb9bcc69a76628ef9270aa8e083ce29d4ebe
3 changes: 3 additions & 0 deletions android/src/toga_android/libs/android/content/res.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from rubicon.java import JavaClass

ColorStateList = JavaClass("android/content/res/ColorStateList")
1 change: 0 additions & 1 deletion android/src/toga_android/libs/android/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@
Path = JavaClass("android/graphics/Path")
Path__Direction = JavaClass("android/graphics/Path$Direction")
Paint__Style = JavaClass("android/graphics/Paint$Style")
PorterDuff__Mode = JavaClass("android/graphics/PorterDuff$Mode")
Rect = JavaClass("android/graphics/Rect")
Typeface = JavaClass("android/graphics/Typeface")
7 changes: 4 additions & 3 deletions android/src/toga_android/widgets/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ 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)
)
if value is None:
self.native.setBackgroundColor(native_color(TRANSPARENT))
else:
self.native.setBackgroundColor(native_color(value))
17 changes: 12 additions & 5 deletions android/src/toga_android/widgets/button.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from travertino.size import at_least

from toga.colors import TRANSPARENT
from toga_android.colors import native_color

from ..libs.android.graphics import PorterDuff__Mode
from ..libs.android.content.res import ColorStateList
from ..libs.android.util import TypedValue
from ..libs.android.view import OnClickListener, View__MeasureSpec
from ..libs.android.widget import Button as A_Button
Expand Down Expand Up @@ -42,14 +43,20 @@ def set_on_press(self, handler):
pass

def set_color(self, value):
if value:
if value is None:
pass
# TODO: set to system foreground
Copy link
Member

Choose a reason for hiding this comment

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

To save us from working out what the system foreground color is, how about making this method save the original color when it's called for the first time, so it can restore it later?

# self.native.setTextColor(native_color(value))
else:
self.native.setTextColor(native_color(value))

def set_background_color(self, value):
if value:
if value is None or value == TRANSPARENT:
self.native.setBackgroundTintList(None)
else:
# do not use self.native.setBackgroundColor - this messes with the button style!
self.native.getBackground().setColorFilter(
native_color(value), PorterDuff__Mode.MULTIPLY
self.native.setBackgroundTintList(
ColorStateList.valueOf(native_color(value))
)

def rehint(self):
Expand Down
18 changes: 14 additions & 4 deletions android/src/toga_android/widgets/label.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from travertino.size import at_least

from toga.colors import TRANSPARENT
from toga_android.colors import native_color

from ..libs.android.util import TypedValue
Expand All @@ -16,14 +17,23 @@ def set_text(self, value):
self.native.setText(value)

def set_font(self, font):
if font:
self.native.setTextSize(TypedValue.COMPLEX_UNIT_SP, font._impl.get_size())
self.native.setTypeface(font._impl.get_typeface(), font._impl.get_style())
self.native.setTextSize(TypedValue.COMPLEX_UNIT_SP, font._impl.get_size())
self.native.setTypeface(font._impl.get_typeface(), font._impl.get_style())

def set_color(self, color):
if color:
if color is None:
pass
# TODO: set to system foreground
# self.native.setTextColor(native_color(value))
else:
self.native.setTextColor(native_color(color))

def set_background_color(self, value):
if value is None:
self.native.setBackgroundColor(native_color(TRANSPARENT))
else:
self.native.setBackgroundColor(native_color(value))

def rehint(self):
# Refuse to rehint an Android TextView if it has no LayoutParams yet.
# Calling measure() on an Android TextView w/o LayoutParams raises NullPointerException.
Expand Down
6 changes: 6 additions & 0 deletions android/tests_backend/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ class SimpleProbe:
def __init__(self, widget):
self.widget = widget
self.native = widget._impl.native

# Store the device DPI, as it will be needed to scale some values
self.dpi = (
self.native.getContext().getResources().getDisplayMetrics().densityDpi
)

assert isinstance(self.native, self.native_class)

def assert_container(self, container):
Expand Down
11 changes: 11 additions & 0 deletions android/tests_backend/widgets/button.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
from java import jclass

from toga_android.libs.android import R__attr

from .label import LabelProbe
from .properties import toga_color


# On Android, a Button is just a TextView with a state-dependent background image.
class ButtonProbe(LabelProbe):
native_class = jclass("android.widget.Button")

@property
def background_color(self):
tint_list = self.native.getBackgroundTintList()
if tint_list:
return toga_color(tint_list.getColorForState([R__attr.state_enabled], 0))
else:
return None
8 changes: 6 additions & 2 deletions android/tests_backend/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pytest import skip

from .base import SimpleProbe
from .properties import toga_color
from .properties import toga_color, toga_font


class LabelProbe(SimpleProbe):
Expand All @@ -12,13 +12,17 @@ class LabelProbe(SimpleProbe):
def color(self):
return toga_color(self.native.getCurrentTextColor())

@property
def background_color(self):
return toga_color(self.native.getBackgroundColor())

@property
def text(self):
return str(self.native.getText())

@property
def font(self):
skip("Font probe not implemented")
return toga_font(self.native.getTypeface(), self.native.getTextSize(), self.dpi)

@property
def alignment(self):
Expand Down
25 changes: 24 additions & 1 deletion android/tests_backend/widgets/properties.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from java import jint
from travertino.fonts import Font

from android.graphics import Color
from android.graphics import Color, Typeface
from toga.colors import rgba
from toga.fonts import BOLD, ITALIC, MONOSPACE, NORMAL, SANS_SERIF, SERIF, SYSTEM


def toga_color(color_int):
Expand All @@ -13,3 +15,24 @@ def toga_color(color_int):
Color.blue(color_int),
Color.alpha(color_int) / 255,
)


def toga_font(typeface, size, dpi):
# Android provides font details in pixels; that size needs to be converted
# using the ratio between the display DPI and the baseline DPI (160).
size_in_points = size / (dpi * 160)

return Font(
family={
Typeface.DEFAULT: SYSTEM,
Typeface.MONOSPACE: MONOSPACE,
Typeface.SANS_SERIF: SANS_SERIF,
Typeface.SERIF: SERIF,
# : CURSIVE ??
# : FANTASY ??
}.get(typeface, "Unknown"),
size=size_in_points,
style=ITALIC if typeface.isItalic() else NORMAL,
variant=NORMAL,
weight=BOLD if typeface.isBold() else NORMAL,
)
14 changes: 4 additions & 10 deletions iOS/tests_backend/widgets/properties.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from ctypes import byref
from dataclasses import dataclass

from rubicon.objc import CGFloat
from travertino.fonts import Font

from toga.colors import rgba
from toga.fonts import FANTASY, NORMAL, SYSTEM
Expand All @@ -28,22 +28,16 @@ def toga_color(color):
return None


@dataclass
class Font:
family: str
size: int
style: str = NORMAL
variant: str = NORMAL
weight: str = NORMAL


def toga_font(font):
return Font(
family={
".AppleSystemUIFont": SYSTEM,
"Papyrus": FANTASY,
}.get(str(font.familyName), str(font.familyName)),
size=font.pointSize,
style=NORMAL, # TODO: ITALIC if..., SMALL_CAPS if ...
variant=NORMAL,
weight=NORMAL, # TODO: BOLD if ...
)


Expand Down
4 changes: 2 additions & 2 deletions testbed/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ requires = [
"../core",
]
test_requires = [
"coverage==7.0.5",
"coverage==7.2.0",
"pytest==7.2.0",
"pytest-asyncio==0.20.3",
]
Expand Down Expand Up @@ -88,7 +88,7 @@ test_sources = [
"../android/tests_backend",
]
requires = [
"../android"
"../android",
]
# Coverage requires access to individual .py files.
build_gradle_extra_content = "android.defaultConfig.python.extractPackages 'toga_android'"
Expand Down
11 changes: 0 additions & 11 deletions testbed/tests/widgets/properties.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
from pytest import mark

from toga.colors import RED, TRANSPARENT, color as named_color
from toga.fonts import FANTASY
from toga.platform import current_platform

from ..assertions import assert_color
from ..data import COLORS, TEXTS
Expand All @@ -18,10 +15,6 @@ async def test_text(widget, probe):
assert probe.text == text


@mark.skipif(
current_platform in {"android"},
reason="text width resizes don't work",
)
async def test_text_width_change(widget, probe):
"If the widget text is changed, the width of the widget changes"
orig_width = probe.width
Expand Down Expand Up @@ -76,10 +69,6 @@ async def test_color(widget, probe):
assert_color(probe.color, color)


@mark.skipif(
current_platform in {"android"},
reason="color resets don't work",
)
async def test_color_reset(widget, probe):
"The foreground color of a widget can be reset"
# Get the original color
Expand Down