diff --git a/traitsui/testing/tester/qt4/implementation/check_list_editor.py b/traitsui/testing/tester/qt4/implementation/check_list_editor.py index dfaca11ef..f0852f8cc 100644 --- a/traitsui/testing/tester/qt4/implementation/check_list_editor.py +++ b/traitsui/testing/tester/qt4/implementation/check_list_editor.py @@ -11,6 +11,7 @@ from traitsui.qt4.check_list_editor import CustomEditor from traitsui.testing.tester import command, locator +from traitsui.testing.tester.editors.layout import column_major_to_row_major from traitsui.testing.tester.qt4 import helpers @@ -69,12 +70,37 @@ def register(cls, registry): interaction_class=command.MouseClick, handler=lambda wrapper, _: helpers.mouse_click_qlayout( layout=wrapper.target.target.control.layout(), - index=wrapper.target.index, + index=convert_index( + wrapper.target.target.control.layout(), + wrapper.target.index + ), delay=wrapper.delay, ) ) +def convert_index(layout, index): + """ Helper function to convert an index for a QGridLayout so that the + index counts over the grid in the correct direction. + The grid is always populated in row major order, but it is done so in + such a way that the entries appear in column major order. + Qlayouts are indexed in the order they are populated, so to access + the correct element we may need to convert a column-major based index + into a row-major one. + + Parameters + ---------- + layout : QGridLayout + The layout of interest + index : int + the index of interest + """ + n = layout.count() + num_cols = layout.columnCount() + num_rows = layout.rowCount() + return column_major_to_row_major(index, n, num_rows, num_cols) + + def register(registry): """ Register interactions for the given registry. diff --git a/traitsui/testing/tester/wx/implementation/check_list_editor.py b/traitsui/testing/tester/wx/implementation/check_list_editor.py index dba4edead..b641de635 100644 --- a/traitsui/testing/tester/wx/implementation/check_list_editor.py +++ b/traitsui/testing/tester/wx/implementation/check_list_editor.py @@ -8,9 +8,11 @@ # # Thanks for using Enthought open source! # +import wx from traitsui.wx.check_list_editor import CustomEditor from traitsui.testing.tester import command, locator +from traitsui.testing.tester.editors.layout import column_major_to_row_major from traitsui.testing.tester.wx import helpers @@ -70,11 +72,41 @@ def register(cls, registry): handler=lambda wrapper, _: (helpers.mouse_click_checkbox_child_in_panel( control=wrapper.target.target.control, - index=wrapper.target.index, + index=convert_index( + wrapper.target.target, + wrapper.target.index, + ), delay=wrapper.delay)) ) +def convert_index(source, index): + """ Helper function to convert an index for a GridSizer so that the + index counts over the grid in the correct direction. + The grid is always populated in row major order, however, the elements + are assigned to each entry in the grid so that when displayed they appear + in column major order. + Sizers are indexed in the order they are populated, so to access + the correct element we may need to convert a column-major based index + into a row-major one. + + Parameters + ---------- + control : CustomEditor + The Custom CheckList Editor of interest. Its control is the wx.Panel + containing child objects organized with a wx.GridSizer + index : int + the index of interest + """ + sizer = source.control.GetSizer() + if isinstance(sizer, wx.BoxSizer): + return index + n = len(source.names) + num_cols = sizer.GetCols() + num_rows = sizer.GetEffectiveRowsCount() + return column_major_to_row_major(index, n, num_rows, num_cols) + + def register(registry): """ Register interactions for the given registry. diff --git a/traitsui/tests/editors/test_check_list_editor.py b/traitsui/tests/editors/test_check_list_editor.py index 2b65bf0f5..340bc0057 100644 --- a/traitsui/tests/editors/test_check_list_editor.py +++ b/traitsui/tests/editors/test_check_list_editor.py @@ -35,6 +35,20 @@ def get_view(style): ) +def get_view_custom_cols(cols): + return View( + UItem( + "value", + editor=CheckListEditor( + values=["one", "two", "three", "four", "five", "six", "seven"], + cols=cols, + ), + style="custom", + ), + resizable=True + ) + + def get_mapped_view(style): return View( UItem( @@ -464,6 +478,20 @@ class StrModel(HasTraits): self.assertEqual(str_edit.value, "three,one") + def test_custom_check_list_editor_grid_layout(self): + for cols in range(1, 8): + list_edit = ListModel() + tester = UITester() + view = get_view_custom_cols(cols=cols) + with tester.create_ui(list_edit, dict(view=view)) as ui: + self.assertEqual(list_edit.value, []) + check_list = tester.find_by_name(ui, "value") + item = check_list.locate(locator.Index(6)) + item.perform(command.MouseClick()) + self.assertEqual(list_edit.value, ["seven"]) + item.perform(command.MouseClick()) + self.assertEqual(list_edit.value, []) + @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) class TestTextCheckListEditor(unittest.TestCase):