-
-
Notifications
You must be signed in to change notification settings - Fork 671
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
Implemented Selection.set_font() for Android #2130
base: main
Are you sure you want to change the base?
Changes from 20 commits
37d6551
f8d428c
e95e04d
e94c038
057afb7
27e93cc
c5f1378
e3e95a6
7a26027
d019817
67a16fd
99644e4
c172e07
19951dd
c8a34db
9a50e01
aa1b2d3
5afcc4c
5417c42
de8694a
a8207cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,9 @@ | |
|
||
from android import R | ||
from android.view import View | ||
from android.widget import AdapterView, ArrayAdapter, Spinner | ||
from android.widget import AdapterView, ArrayAdapter, Spinner, SpinnerAdapter | ||
|
||
from . import label | ||
from .base import Widget | ||
|
||
|
||
|
@@ -20,14 +21,90 @@ def onNothingSelected(self, parent): | |
self.impl.on_change(None) | ||
|
||
|
||
class TogaArrayAdapter(dynamic_proxy(SpinnerAdapter)): | ||
def __init__(self, impl): | ||
super().__init__() | ||
self.impl = impl | ||
self._default_textsize = -1 | ||
self._default_typeface = None | ||
self.adapter = ArrayAdapter( | ||
self.impl._native_activity, R.layout.simple_spinner_item | ||
) | ||
self.adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item) | ||
|
||
def apply_font(self, tv): | ||
if self.impl._font_impl and tv: | ||
label.set_textview_font( | ||
tv, | ||
self.impl._font_impl, | ||
self._default_typeface, | ||
self._default_textsize, | ||
) | ||
|
||
def cache_textview_defaults(self, tv): | ||
self._default_textsize = tv.getTextSize() | ||
self._default_typeface = tv.getTypeface() | ||
|
||
def getDropDownView(self, position, convertView, parent): | ||
tv = self.adapter.getDropDownView(position, convertView, parent) | ||
self.apply_font(tv) | ||
return tv | ||
|
||
def getView(self, position, convertView, parent): | ||
tv = self.adapter.getView(position, convertView, parent) | ||
if self._default_textsize == -1: | ||
self.cache_textview_defaults(tv) | ||
self.apply_font(tv) | ||
return tv | ||
|
||
def clear(self): | ||
return self.adapter.clear() | ||
|
||
def getAutofillOptions(self): | ||
return self.adapter.getAutofillOptions() | ||
|
||
def getCount(self): | ||
return self.adapter.getCount() | ||
|
||
def getItem(self, position): | ||
return self.adapter.getItem(position) | ||
|
||
def getItemId(self, position): | ||
return self.adapter.getItemId(position) | ||
|
||
def getItemViewType(self, position): | ||
return self.adapter.getItemViewType(position) | ||
|
||
def getViewTypeCount(self): | ||
return self.adapter.getViewTypeCount() | ||
|
||
def hasStableIds(self): | ||
return self.adapter.hasStableIds() | ||
|
||
def insert(self, object, index): | ||
return self.adapter.insert(object, index) | ||
|
||
def isEmpty(self): | ||
return self.adapter.isEmpty() | ||
|
||
def registerDataSetObserver(self, observer): | ||
self.adapter.registerDataSetObserver(observer) | ||
|
||
def remove(self, object): | ||
self.adapter.remove(object) | ||
|
||
def unregisterDataSetObserver(self, observer): | ||
self.adapter.unregisterDataSetObserver(observer) | ||
|
||
|
||
class Selection(Widget): | ||
focusable = False | ||
_font_impl = None | ||
|
||
def create(self): | ||
self.native = Spinner(self._native_activity, Spinner.MODE_DROPDOWN) | ||
self.native.setOnItemSelectedListener(TogaOnItemSelectedListener(impl=self)) | ||
self.adapter = ArrayAdapter(self._native_activity, R.layout.simple_spinner_item) | ||
self.adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item) | ||
self.adapter = TogaArrayAdapter(impl=self) | ||
self.native.setAdapter(self.adapter) | ||
self.last_selection = None | ||
|
||
|
@@ -87,3 +164,9 @@ def rehint(self): | |
self.native.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) | ||
self.interface.intrinsic.width = at_least(self.native.getMeasuredWidth()) | ||
self.interface.intrinsic.height = self.native.getMeasuredHeight() | ||
|
||
def set_font(self, font): | ||
self._font_impl = font._impl | ||
tv = self.native.getSelectedView() | ||
if tv: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above - how/when is this branch not triggered? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. During the creation of the widget, I saw that set_font() is called and tv was null |
||
self.adapter.apply_font(tv) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
The set_font() method has been implemented for Selection on Android |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -320,9 +320,13 @@ async def test_font(widget, probe, verify_font_sizes): | |
if verify_font_sizes[1]: | ||
assert probe.height > orig_height | ||
|
||
# Reset to original family and size. | ||
del widget.style.font_family | ||
# Reset to original size. | ||
del widget.style.font_size | ||
await probe.redraw(message="Widget text should be reset to original size") | ||
probe.assert_font_size(SYSTEM_DEFAULT_FONT_SIZE) | ||
|
||
# Reset to original family | ||
del widget.style.font_family | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This clearly makes the test pass, but I think it is masking the underlying problem. Running the test in In this case, using If you change the order of the deletions - deleting the family, then the size - the widget height is correct, and the test passes. So - introducing the extra probe redraw here actually isn't the fix. It's the fact that you've changed the order of the deletions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made all kinds of changes to test_font() and although, it visually looked ok (with --slow), the test failed when checking the resetted widget height. Doing the same kind of changes in the selection example works, though. There, the widget height does not only look ok, Spinner.getHeight() in fact returns its original value. So, if you've found a better way to make the testbed work, please apply these changes to this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't speak to your own personal setup - but the CI setup reveals the problem, and I can reproduce the problem locally, so this isn't an oddity of the testbed. There's a problem here that needs to be resolved. What you're looking for is the amout of space above the text in the widget. The text has the right sized font, but there's a border above the widget (and presumably below as well), which effectively represents the old widget size, with the smaller text vertically centered in that space. As for a fix... you're the person proposing the change. It's up to you to fix problems that are found. I'm telling you by way of code review that the change you've made to the test suite isn't acceptable. Maybe @mhsmith has some more ideas about places to look for a fix, but we both have other development priorities (not the least of which is finally getting the next Toga release out the door), so we're not in a position to drop everything to hunt a bug that isn't a high priority for us personally. |
||
await probe.redraw( | ||
message="Widget text should be reset to original family and size" | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How/when does this method get invoked when tv is None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During the creation of the widget, this can happen.