Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c69970a
Add new features to optioncontainer.py
saroad2 Oct 21, 2020
488b1cc
Implement new optioncontainer.py features on windows
saroad2 Oct 21, 2020
d637a58
update optioncontainer example app with new features
saroad2 Oct 21, 2020
f5c3f31
Added missing unit tests to optioncontainer.py
saroad2 Oct 21, 2020
64b91f3
Add not implemented methods on optioncontainer.py
saroad2 Oct 21, 2020
a89b963
Fix flake8 error
saroad2 Oct 21, 2020
3f4b55e
Change API after review
saroad2 Nov 1, 2020
0a092e1
Add current tab increment and decrement
saroad2 Nov 1, 2020
8c96231
Fix example after API change
saroad2 Nov 1, 2020
32886aa
Merge branch 'master' into add_optionscontainer_abilities
saroad2 Nov 1, 2020
d0d3526
Include the selected option in the event message.
freakboy3742 Nov 28, 2020
6b2d1f6
Implement the tab selection APIs for Cocoa.
freakboy3742 Nov 28, 2020
af92a32
Reordered some calls to avoid invoking native properties before nativ…
freakboy3742 Nov 28, 2020
55056fa
Updated selection handler in optioncontainer demo.
freakboy3742 Nov 28, 2020
0be3e3f
Filled out GTK OptionContainer implementation
freakboy3742 Nov 28, 2020
a3e67cb
Remove use of private API for tab enabled status.
freakboy3742 Nov 29, 2020
122aaa3
Ensure option indicies are always accurate.
freakboy3742 Nov 29, 2020
2b20f17
Remove dependence on NSTabViewItem identifer.
freakboy3742 Nov 29, 2020
4eb9704
Correct GTK handling of add/remove tab.
freakboy3742 Nov 29, 2020
e31fc6e
Use a proxy object for current_tab.
freakboy3742 Nov 29, 2020
7efd437
Removed an unused import.
freakboy3742 Nov 29, 2020
e0ecd49
Simplify internal attribute handling
freakboy3742 Nov 29, 2020
fd21d37
Fix test cases.
freakboy3742 Nov 29, 2020
269b2e4
Correct not_required handling, and ignore Option class.
freakboy3742 Nov 29, 2020
55dc1d9
More decorator handling tweaks.
freakboy3742 Nov 29, 2020
d0c3974
Merge branch 'master' into add_optionscontainer_abilities
saroad2 Nov 29, 2020
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
41 changes: 39 additions & 2 deletions examples/optioncontainer/optioncontainer/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ def on_remove_option(self, button):
except toga.OptionContainer.OptionException as e:
self.main_window.info_dialog('Oops', str(e))

def set_next_tab(self, widget):
if self.optioncontainer.current_tab_index < self.optioncontainer.number_of_tabs - 1:
self.optioncontainer.current_tab_index += 1

def set_previous_tab(self, widget):
if self.optioncontainer.current_tab_index > 0:
self.optioncontainer.current_tab_index -= 1

def on_select_tab(self, widget):
self.selected_label.text = "Tab {} has been chosen: {}".format(
self.optioncontainer.current_tab_index,
self.optioncontainer.current_tab.label,
)

def startup(self):
# Set up main window
self.main_window = toga.MainWindow(title=self.name)
Expand Down Expand Up @@ -101,7 +115,11 @@ def startup(self):
children=[box_select, box_actions]
)

self.optioncontainer = toga.OptionContainer(style=Pack(padding_bottom=20))
self.selected_label = toga.Label("")
self.optioncontainer = toga.OptionContainer(
on_select=self.on_select_tab,
style=Pack(padding_bottom=20)
)
self._create_options()

btn_add = toga.Button('Add Option', on_press=self.on_add_option)
Expand All @@ -115,7 +133,8 @@ def startup(self):
children=[
box_general_actions,
box_container_actions,
self.optioncontainer
self.selected_label,
self.optioncontainer,
],
style=Pack(
flex=1,
Expand All @@ -124,8 +143,26 @@ def startup(self):
)
)

self.commands.add(
toga.Command(
self.set_next_tab,
"Next tab",
shortcut=toga.Key.MOD_1 + toga.Key.RIGHT,
group=toga.Group.COMMANDS,
order=1
),
toga.Command(
self.set_previous_tab,
"Previous tab",
shortcut=toga.Key.MOD_1 + toga.Key.LEFT,
group=toga.Group.COMMANDS,
order=1
)
)

# Add the content on the main window
self.main_window.content = outer_box
self.on_select_tab(None)

# Show the main window
self.main_window.show()
Expand Down
10 changes: 10 additions & 0 deletions src/cocoa/toga_cocoa/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,13 @@ def set_option_label(self, index, value):
def get_option_label(self, index):
tabview = self.native.tabViewItemAtIndex(index)
return tabview.label

def get_current_tab_index(self):
self.interface.factory.not_implemented(
'OptionContainer.get_current_tab_index()'
)

def set_current_tab_index(self, current_tab_index):
self.interface.factory.not_implemented(
'OptionContainer.set_current_tab_index()'
)
109 changes: 94 additions & 15 deletions src/core/tests/widgets/test_optioncontainer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest import mock

import toga
import toga_dummy
from toga_dummy.utils import TestCase, TestStyle
Expand All @@ -7,31 +9,108 @@ class OptionContainerTests(TestCase):
def setUp(self):
super().setUp()

self.op_container = toga.OptionContainer(style=TestStyle(), factory=toga_dummy.factory)
self.on_select = mock.Mock()
self.op_container = toga.OptionContainer(
style=TestStyle(),
factory=toga_dummy.factory,
on_select=self.on_select
)
self.widget = toga.Box(style=TestStyle(), factory=toga_dummy.factory)
self.label2, self.widget2 = "Widget 2", toga.Box(
style=TestStyle(), factory=toga_dummy.factory
)
self.label3, self.widget3 = "Widget 3", toga.Box(
style=TestStyle(), factory=toga_dummy.factory
)
self.label = 'New Container'
self.op_container.add(self.label, self.widget)

def add_widgets(self):
self.op_container.add(self.label2, self.widget2)
self.op_container.add(self.label3, self.widget3)

def test_on_select(self):
self.assertEqual(self.op_container.on_select._raw, self.on_select)

def test_widget_created(self):
self.assertEqual(self.op_container._impl.interface, self.op_container)
self.assertActionPerformed(self.op_container, 'create OptionContainer')

def test_adding_container_invokes_add_content(self):
widget = toga.Box(style=TestStyle(), factory=toga_dummy.factory)
label = 'New Container'

self.op_container.add(label, widget)
self.assertActionPerformedWith(self.op_container, 'add content', label=label, widget=widget._impl)
self.assertActionPerformedWith(
self.op_container, 'add content', label=self.label, widget=self.widget._impl
)

self.assertActionPerformedWith(widget, 'set bounds', x=0, y=0, width=0, height=0)
self.assertActionPerformedWith(
self.widget, 'set bounds', x=0, y=0, width=0, height=0
)

def test_widget_refresh_sublayouts(self):
widget = toga.Box(style=TestStyle(), factory=toga_dummy.factory)
label = 'New Container'

self.op_container.add(label, widget)
self.assertActionPerformedWith(self.op_container, 'add content', label=label, widget=widget._impl)
self.assertActionPerformedWith(widget, 'set bounds', x=0, y=0, width=0, height=0)

# Clear event log to verify new set bounds for refresh
self.reset_event_log()

self.op_container.refresh_sublayouts()
self.assertActionPerformedWith(widget, 'set bounds', x=0, y=0, width=0, height=0)
self.assertActionPerformedWith(
self.widget, 'set bounds', x=0, y=0, width=0, height=0
)

def test_set_current_tab(self):
self.add_widgets()
index = 1
self.op_container.current_tab_index = index
self.assertEqual(self.op_container.current_tab_index, index)
self.assertEqual(self.op_container.current_tab.index, index)
self.assertEqual(self.op_container.current_tab.label, self.label2)
self.assertEqual(self.op_container.current_tab.widget, self.widget2)
self.assertEqual(self.op_container.current_tab.interface, self.op_container)
self.assertEqual(self.op_container.current_tab.enabled, True)

def test_disable_tab(self):
self.op_container.current_tab.enabled = False
self.assertEqual(self.op_container.current_tab.enabled, False)

def test_content_repr(self):
self.add_widgets()
self.assertEqual(
(
"OptionList([OptionItem(title=New Container), "
"OptionItem(title=Widget 2), "
"OptionItem(title=Widget 3)])"
),
repr(self.op_container.content)
)

def test_add_tabs(self):
self.add_widgets()
self.assertEqual(self.op_container.number_of_tabs, 3)
self.assertEqual(self.op_container.content[0].widget, self.widget)
self.assertEqual(self.op_container.content[1].widget, self.widget2)
self.assertEqual(self.op_container.content[2].widget, self.widget3)

def test_remove_tab(self):
self.add_widgets()
self.op_container.remove(1)
self.assertEqual(self.op_container.number_of_tabs, 2)
self.assertEqual(self.op_container.content[0].widget, self.widget)
self.assertEqual(self.op_container.content[1].widget, self.widget3)

def test_set_content_in_constructor(self):
new_container = toga.OptionContainer(
style=TestStyle(),
factory=toga_dummy.factory,
content=[
(self.label, self.widget),
(self.label2, self.widget2),
(self.label3, self.widget3),
]
)
self.assertEqual(len(new_container.content), 3)
self.assertEqual(new_container.content[0].widget, self.widget)
self.assertEqual(new_container.content[1].widget, self.widget2)
self.assertEqual(new_container.content[2].widget, self.widget3)

def test_set_window(self):
window = mock.Mock()
self.op_container.window = window
for item in self.op_container.content:
self.assertEqual(item.widget.window, window)
22 changes: 21 additions & 1 deletion src/core/toga/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ def label(self):
def label(self, value):
self._interface._impl.set_option_label(self.index, value)

@property
def widget(self):
return self._widget

def refresh(self):
self._widget.refresh()

Expand Down Expand Up @@ -137,10 +141,26 @@ def content(self):
"""
return self._content

@property
def number_of_tabs(self):
return len(self.content)

@property
def current_tab_index(self):
return self._impl.get_current_tab_index()

@current_tab_index.setter
def current_tab_index(self, current_tab_index):
self._impl.set_current_tab_index(current_tab_index)

@property
def current_tab(self):
return self.content[self.current_tab_index]

def _set_window(self, window):
if self._content:
for content in self._content:
content.window = window
content.widget.window = window

def add(self, label, widget):
""" Add a new option to the option container.
Expand Down
14 changes: 10 additions & 4 deletions src/dummy/toga_dummy/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ def set_on_select(self, handler):
self._set_value('on_select', handler)

def set_option_enabled(self, index, enabled):
self._action('set option enabled', index=index)
self._set_value('option_{}_enabled'.format(index), value=enabled)

def is_option_enabled(self, index):
self._action('is enabled', index=index)
return self._get_value('option_{}_enabled'.format(index))

def set_option_label(self, index, value):
self._action('set option label', index=index, value=value)
self._set_value('option_{}_label'.format(index), value=value)

def get_option_label(self, index):
self._action('get label', index=index)
return self._get_value('option_{}_label'.format(index))

def set_current_tab_index(self, current_tab_index):
self._set_value('current_tab_index', current_tab_index)

def get_current_tab_index(self):
return self._get_value('current_tab_index', 0)
10 changes: 10 additions & 0 deletions src/gtk/toga_gtk/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ def set_option_label(self, index, value):

def get_option_label(self, index):
self.interface.factory.not_implemented('OptionContainer.get_option_label()')

def get_current_tab_index(self):
self.interface.factory.not_implemented(
'OptionContainer.get_current_tab_index()'
)

def set_current_tab_index(self, current_tab_index):
self.interface.factory.not_implemented(
'OptionContainer.set_current_tab_index()'
)
6 changes: 6 additions & 0 deletions src/winforms/toga_winforms/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ def set_option_label(self, index, value):
def get_option_label(self, index):
return self.native.TabPages[index].Text

def get_current_tab_index(self):
return self.native.SelectedIndex

def set_current_tab_index(self, current_tab_index):
self.native.SelectedIndex = current_tab_index

def winforms_selected(self, sender, event):
if self.interface.on_select:
self.interface.on_select(self.interface)