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

API consistency: switch widget #1526

Merged
merged 9 commits into from
Jul 27, 2022
4 changes: 2 additions & 2 deletions examples/box/box/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def startup(self):
self.inner_box,
toga.Label(text="Hello to my world!", style=Pack(text_align=CENTER)),
toga.Switch(
"Enable yellow", is_on=True, on_toggle=self.toggle_yellow_button
"Enable yellow", value=True, on_change=self.toggle_yellow_button
),
],
)
Expand All @@ -85,7 +85,7 @@ def reset_color(self, widget):
self.outer_box.style.background_color = None

def toggle_yellow_button(self, widget):
if widget.is_on:
if widget.value:
self.inner_box.insert(1, self.yellow_button)
else:
self.inner_box.remove(self.yellow_button)
Expand Down
8 changes: 4 additions & 4 deletions examples/canvas/canvas/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ def startup(self):
)
self.italic_switch = toga.Switch(
label="italic",
on_toggle=self.refresh_canvas
on_change=self.refresh_canvas
)
self.bold_switch = toga.Switch(
label="bold",
on_toggle=self.refresh_canvas
on_change=self.refresh_canvas
)
label_style = Pack(font_size=10, padding_left=5)

Expand Down Expand Up @@ -539,12 +539,12 @@ def draw_instructions(self, context, factor):
context.write_text(text, self.x_middle - width / 2, self.y_middle, font)

def get_weight(self):
if self.bold_switch.is_on:
if self.bold_switch.value:
return BOLD
return NORMAL

def get_style(self):
if self.italic_switch.is_on:
if self.italic_switch.value:
return ITALIC
return NORMAL

Expand Down
4 changes: 2 additions & 2 deletions examples/focus/focus/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def startup(self):
placeholder="A non-focussed text input.",
style=Pack(height=25, width=200, font_size=10),
)
self.switch = toga.Switch("Switch", on_toggle=self.on_switch_toggle)
self.switch = toga.Switch("Switch", on_change=self.on_switch_toggle)
self.info_label = toga.Label(
"Use keyboard shortcuts to focus on the different widgets",
style=Pack(font_size=10)
Expand Down Expand Up @@ -90,7 +90,7 @@ def on_button_press(self, widget: toga.Button):
)

def on_switch_toggle(self, widget: toga.Switch):
on_off = "on" if widget.is_on else "off"
on_off = "on" if widget.value else "off"
self.info_label.text = "Switch turned {on_off}!".format(on_off=on_off)

def on_textinput_gain_focus(self, widget: toga.TextInput):
Expand Down
8 changes: 4 additions & 4 deletions examples/progressbar/progressbar/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ def startup(self):
),
toga.Switch(
"Toggle indeterminate mode",
on_toggle=self.toggle_indeterminate,
on_change=self.toggle_indeterminate,
),
toga.Switch(
"Toggle running mode", on_toggle=self.toggle_running
"Toggle running mode", on_change=self.toggle_running
),
],
),
Expand Down Expand Up @@ -129,14 +129,14 @@ def decrease_progress(self, button, **kw):
self.progress_adder.value -= 0.1 * self.progress_adder.max

def toggle_indeterminate(self, switch, **kw):
if switch.is_on:
if switch.value:
self.progress_adder.max = None
else:
self.progress_adder.max = MAX_PROGRESSBAR_VALUE
print("is determinate: " + str(self.progress_adder.is_determinate))

def toggle_running(self, switch, **kw):
if switch.is_on:
if switch.value:
self.progress_adder.start()
else:
self.progress_adder.stop()
Expand Down
8 changes: 4 additions & 4 deletions examples/scrollcontainer/scrollcontainer/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def startup(self):
box.style.padding = 10
self.scroller = toga.ScrollContainer(horizontal=self.hscrolling, vertical=self.vscrolling)
switch_box = toga.Box(style=Pack(direction=ROW))
switch_box.add(toga.Switch('vertical scrolling', is_on=self.vscrolling, on_toggle=self.handle_vscrolling))
switch_box.add(toga.Switch('horizontal scrolling', is_on=self.hscrolling, on_toggle=self.handle_hscrolling))
switch_box.add(toga.Switch('vertical scrolling', value=self.vscrolling, on_change=self.handle_vscrolling))
switch_box.add(toga.Switch('horizontal scrolling', value=self.hscrolling, on_change=self.handle_hscrolling))
box.add(switch_box)

for x in range(100):
Expand Down Expand Up @@ -72,11 +72,11 @@ def startup(self):
)

def handle_hscrolling(self, widget):
self.hscrolling = widget.is_on
self.hscrolling = widget.value
self.scroller.horizontal = self.hscrolling

def handle_vscrolling(self, widget):
self.vscrolling = widget.is_on
self.vscrolling = widget.value
self.scroller.vertical = self.vscrolling

def toggle_up(self, widget):
Expand Down
6 changes: 3 additions & 3 deletions examples/switch_demo/switch_demo/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ def startup(self):
self.main_window.content = toga.Box(
children=[
# Simple switch with label and callback function called toggled
toga.Switch('Change Label', on_toggle=self.callbackLabel),
toga.Switch('Change Label', on_change=self.callbackLabel),

# Switch with initial state
toga.Switch('Initial state', is_on=True, style=Pack(padding_top=24)),
toga.Switch('Initial state', value=True, style=Pack(padding_top=24)),

# Switch with label and enable option
toga.Switch('Disabled', enabled=False, style=Pack(padding_top=24)),
Expand All @@ -35,7 +35,7 @@ def startup(self):
def callbackLabel(self, switch):
# Some action when you hit the switch
# In this case the label will change
switch.label = "switch is %s" % {0: "off", 1: "on"}[switch.is_on]
switch.label = "switch is %s" % {0: "off", 1: "on"}[switch.value]


def main():
Expand Down
14 changes: 7 additions & 7 deletions src/android/toga_android/widgets/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,29 @@ def __init__(self, impl):
self._impl = impl

def onCheckedChanged(self, _button, _checked):
if self._impl.interface.on_toggle:
self._impl.interface.on_toggle(widget=self._impl.interface)
if self._impl.interface.on_change:
self._impl.interface.on_change(widget=self._impl.interface)


class Switch(Widget):
def create(self):
self.native = A_Switch(self._native_activity)
self.native.setOnCheckedChangeListener(OnCheckedChangeListener(self))

def set_label(self, label):
def set_text(self, text):
# When changing the text, Android needs a `setSingleLine(False)` call in order
# to be willing to recompute the width of the text. Without the call, it will
# constrain the new text to have the same line width as the old text, resulting
# in unnecessary creation of new lines. In other words, `setSingleLine(False)`
# is required to get the text to truly **use** one single line!
self.native.setSingleLine(False)
self.native.setText(str(self.interface.label))
self.native.setText(str(self.interface.text))
self.rehint()

def set_is_on(self, value):
def set_value(self, value):
self.native.setChecked(bool(value))

def get_is_on(self):
def get_value(self):
return self.native.isChecked()

def set_font(self, font):
Expand All @@ -46,7 +46,7 @@ def set_font(self, font):
self.native.setTextSize(TypedValue.COMPLEX_UNIT_SP, font_impl.get_size())
self.native.setTypeface(font_impl.get_typeface(), font_impl.get_style())

def set_on_toggle(self, handler):
def set_on_change(self, handler):
# No special handling required
pass

Expand Down
22 changes: 11 additions & 11 deletions src/cocoa/toga_cocoa/widgets/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class TogaSwitch(NSButton):

@objc_method
def onPress_(self, obj) -> None:
if self.interface.on_toggle:
self.interface.on_toggle(self.interface)
if self.interface.on_change:
self.interface.on_change(self.interface)


class Switch(Widget):
Expand All @@ -39,32 +39,32 @@ def create(self):
# Add the layout constraints
self.add_constraints()

def set_label(self, label):
self.native.title = self.interface.label
def set_text(self, text):
self.native.title = self.interface.text

def set_font(self, font):
if font:
self.native.font = font.bind(self.interface.factory).native

def set_is_on(self, value):
def set_value(self, value):
if value is True:
self.native.state = NSOnState
elif value is False:
self.native.state = NSOffState

def get_is_on(self):
is_on = self.native.state
if is_on == 1:
def get_value(self):
value = self.native.state
if value == 1:
return True
elif is_on == 0:
elif value == 0:
return False
else:
raise Exception('Undefined value for is_on of {}'.format(__class__))
raise Exception('Undefined value for value of {}'.format(__class__))

def rehint(self):
content_size = self.native.intrinsicContentSize()
self.interface.intrinsic.height = content_size.height
self.interface.intrinsic.width = at_least(content_size.width)

def set_on_toggle(self, handler):
def set_on_change(self, handler):
pass
94 changes: 65 additions & 29 deletions src/core/tests/widgets/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ class SwitchTests(TestCase):
def setUp(self):
super().setUp()

self.label = 'Test Label'
self.text = 'Test Label'

def callback(widget):
pass

self.on_toggle = callback
self.is_on = True
self.on_change = callback
self.value = True
self.enabled = True
self.switch = toga.Switch(self.label,
on_toggle=self.on_toggle,
is_on=self.is_on,
self.switch = toga.Switch(self.text,
on_change=self.on_change,
value=self.value,
enabled=self.enabled,
factory=toga_dummy.factory)

Expand All @@ -26,44 +26,80 @@ def test_widget_created(self):
self.assertActionPerformed(self.switch, 'create Switch')

def test_arguments_are_all_set_properly(self):
self.assertEqual(self.switch.label, self.label)
self.assertEqual(self.switch._label, self.label)
self.assertEqual(self.switch.on_toggle._raw, self.on_toggle)
self.assertEqual(self.switch.text, self.text)
self.assertEqual(self.switch._text, self.text)
self.assertEqual(self.switch.on_change._raw, self.on_change)
self.assertEqual(self.switch.enabled, self.enabled)

def test_label_with_None(self):
self.switch.label = None
self.assertEqual(self.switch.label, '')
self.assertEqual(self.switch._label, '')
def test_text_with_None(self):
self.switch.text = None
self.assertEqual(self.switch.text, '')
self.assertEqual(self.switch._text, '')

def test_setting_label_invokes_impl_method(self):
new_label = 'New Label'
self.switch.label = new_label
self.assertValueSet(self.switch, 'label', new_label)
def test_setting_text_invokes_impl_method(self):
new_text = 'New Label'
self.switch.text = new_text
self.assertValueSet(self.switch, 'text', new_text)

def test_setting_is_on_invokes_impl_method(self):
def test_setting_value_invokes_impl_method(self):
new_value = False
self.switch.is_on = new_value
self.assertValueSet(self.switch, 'is_on', False)
self.switch.value = new_value
self.assertValueSet(self.switch, 'value', False)

def test_getting_is_on_invokes_impl_method(self):
self.switch.is_on
self.assertValueGet(self.switch, 'is_on')
def test_getting_value_invokes_impl_method(self):
self.switch.value
self.assertValueGet(self.switch, 'value')

def test_focus(self):
self.switch.focus()
self.assertActionPerformed(self.switch, "focus")

def test_toggle_from_true_to_false(self):
self.switch.is_on = True
self.switch.value = True
self.switch.toggle()
self.assertValueSet(self.switch, 'is_on', False)
self.assertValueSet(self.switch, 'value', False)

def test_toggle_from_false_to_true(self):
self.switch.is_on = False
self.switch.value = False
self.switch.toggle()
self.assertValueSet(self.switch, 'is_on', True)
self.assertValueSet(self.switch, 'value', True)

def test_set_is_on_with_non_boolean(self):
def test_set_value_with_non_boolean(self):
with self.assertRaises(ValueError):
self.switch.is_on = "on"
self.switch.value = "on"

def test_set_is_on(self):
new_value = False
with self.assertWarns(DeprecationWarning):
self.switch.is_on = new_value
self.assertValueSet(self.switch, 'value', False)

def test_get_is_on(self):
with self.assertWarns(DeprecationWarning):
self.switch.is_on
self.assertValueGet(self.switch, 'value')

def test_on_change(self):
def my_callback(widget):
pass

self.switch.on_change = my_callback
self.assertEqual(self.switch.on_change._raw, my_callback)

def test_on_toggle(self):
def my_callback(widget):
pass

with self.assertWarns(DeprecationWarning):
self.switch.on_toggle = my_callback
with self.assertWarns(DeprecationWarning):
self.assertEqual(self.switch.on_toggle._raw, my_callback)
self.assertEqual(self.switch.on_change._raw, my_callback)

def test_label_deprecated(self):
new_text = 'New Label'
with self.assertWarns(DeprecationWarning):
self.switch.label = new_text
with self.assertWarns(DeprecationWarning):
self.assertEqual(self.switch.label, new_text)
self.assertValueSet(self.switch, 'text', new_text)