diff options
-rw-r--r-- | sc/UIConfig_scalc.mk | 1 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter/autofilter.py | 48 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf117276.py | 8 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf117276_autofilter_reset.py | 6 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf122260.py | 4 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf140754.py | 4 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf141946.py | 8 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf46062.py | 2 | ||||
-rwxr-xr-x | sc/qa/uitest/autofilter2/tdf46184.py | 2 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf48025.py | 6 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf68113.py | 4 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter2/tdf97340.py | 2 | ||||
-rw-r--r-- | sc/qa/uitest/calc_tests9/pivotTable.py | 2 | ||||
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 370 | ||||
-rw-r--r-- | sc/source/ui/inc/checklistmenu.hxx | 95 | ||||
-rw-r--r-- | sc/source/ui/inc/gridwin.hxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 93 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin2.cxx | 45 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/filterdropdown.ui | 367 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/filtersubdropdown.ui | 79 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtkinst.cxx | 52 |
21 files changed, 693 insertions, 509 deletions
diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk index c1bd1b075926..336e1710958d 100644 --- a/sc/UIConfig_scalc.mk +++ b/sc/UIConfig_scalc.mk @@ -129,6 +129,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/filldlg \ sc/uiconfig/scalc/ui/filterlist \ sc/uiconfig/scalc/ui/filterdropdown \ + sc/uiconfig/scalc/ui/filtersubdropdown \ sc/uiconfig/scalc/ui/footerdialog \ sc/uiconfig/scalc/ui/formatcellsdialog \ sc/uiconfig/scalc/ui/formulacalculationoptions \ diff --git a/sc/qa/uitest/autofilter/autofilter.py b/sc/qa/uitest/autofilter/autofilter.py index 847aa8dcf8b6..eede08073388 100644 --- a/sc/qa/uitest/autofilter/autofilter.py +++ b/sc/qa/uitest/autofilter/autofilter.py @@ -20,7 +20,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_tree_box") xFirstEntry = xTreeList.getChild("0") @@ -42,7 +42,7 @@ class AutofilterTest(UITestCase): xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xFirstEntry = xTreeList.getChild("1") @@ -64,7 +64,7 @@ class AutofilterTest(UITestCase): xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "3"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") size1 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0]) xOkBtn = xFloatWindow.getChild("cancel") @@ -72,7 +72,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "3"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") size2 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0]) xOkBtn = xFloatWindow.getChild("cancel") @@ -80,7 +80,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "3", "ROW": "3"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") size3 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0]) xOkBtn = xFloatWindow.getChild("cancel") @@ -88,7 +88,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "4", "ROW": "3"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") size4 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0]) @@ -107,7 +107,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_tree_box") @@ -141,7 +141,7 @@ class AutofilterTest(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") @@ -166,7 +166,7 @@ class AutofilterTest(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") @@ -206,7 +206,7 @@ class AutofilterTest(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") @@ -225,7 +225,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_tree_box") self.assertEqual(3, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -233,7 +233,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(5, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -241,7 +241,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -254,7 +254,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(9, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -267,7 +267,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_tree_box") self.assertEqual(3, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -275,7 +275,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -283,7 +283,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(4, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -296,7 +296,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -309,7 +309,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(5, len(xTreeList.getChildren())) self.assertEqual('true', get_state_as_dict(xTreeList.getChild('0'))['IsChecked']) @@ -322,7 +322,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(2, len(xTreeList.getChildren())) xOkBtn = xFloatWindow.getChild("cancel") @@ -335,7 +335,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(5, len(xTreeList.getChildren())) self.assertEqual("0.000", get_state_as_dict(xTreeList.getChild('0'))['Text']) @@ -383,7 +383,7 @@ class AutofilterTest(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") # tdf140745 show (empty) entry on top of the checkbox list @@ -404,7 +404,7 @@ class AutofilterTest(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xList.getChildren())) self.assertEqual('false', get_state_as_dict(xList.getChild('0'))['IsChecked']) @@ -512,7 +512,7 @@ class AutofilterTest(UITestCase): xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "4", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(2, len(xTreeList.getChildren())) self.assertEqual("65.43", get_state_as_dict(xTreeList.getChild('0'))['Text']) diff --git a/sc/qa/uitest/autofilter2/tdf117276.py b/sc/qa/uitest/autofilter2/tdf117276.py index 2c5a44be4bd3..259ad4786592 100644 --- a/sc/qa/uitest/autofilter2/tdf117276.py +++ b/sc/qa/uitest/autofilter2/tdf117276.py @@ -20,7 +20,7 @@ class tdf117276(UITestCase): # 2. open filter of column B (Fabrikat) and deselect (Citroen, Fiat, Ford, Opel, Peugeot, Renault, Tesla) gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xCitroenEntry = xTreeList.getChild("2") @@ -48,7 +48,7 @@ class tdf117276(UITestCase): # 3. open filter of column I (Wert) and deselect 8000 (Values 7000 and 9000 are not shown) gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "8", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xCitroenEntry = xTreeList.getChild("0") @@ -64,7 +64,7 @@ class tdf117276(UITestCase): # 4. open filter of column B and select Tesla gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xTeslaEntry = xTreeList.getChild("4") xTeslaEntry.executeAction("CLICK", tuple()) #Tesla @@ -79,7 +79,7 @@ class tdf117276(UITestCase): #(which strings to show and which to hide, when multiple filters are in used). gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "8", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") x8000Entry = xTreeList.getChild("1") # check "8000" diff --git a/sc/qa/uitest/autofilter2/tdf117276_autofilter_reset.py b/sc/qa/uitest/autofilter2/tdf117276_autofilter_reset.py index c2c94d69df45..f9a26c8e5468 100644 --- a/sc/qa/uitest/autofilter2/tdf117276_autofilter_reset.py +++ b/sc/qa/uitest/autofilter2/tdf117276_autofilter_reset.py @@ -19,7 +19,7 @@ class tdf117276_autofilter_reset(UITestCase): self.assertIsNotNone(xFloatWindow) # get check list - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") self.assertIsNotNone(xCheckListMenu) xTreeList = xCheckListMenu.getChild("check_list_box") @@ -105,7 +105,7 @@ class tdf117276_autofilter_reset(UITestCase): # 3. open filter of column A and deselect first 3 entries (Unique a2, Unique a3, Unique a4) xGridWindow.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xEntry1 = xTreeList.getChild("0") @@ -138,7 +138,7 @@ class tdf117276_autofilter_reset(UITestCase): # 4. open filter of column B and deselect "Unique b5" xGridWindow.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xEntry = xTreeList.getChild("0") diff --git a/sc/qa/uitest/autofilter2/tdf122260.py b/sc/qa/uitest/autofilter2/tdf122260.py index fb2c905e3844..981dd6965d6c 100644 --- a/sc/qa/uitest/autofilter2/tdf122260.py +++ b/sc/qa/uitest/autofilter2/tdf122260.py @@ -19,7 +19,7 @@ class tdf122260(UITestCase): self.assertIsNotNone(xFloatWindow) # get check list - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") self.assertIsNotNone(xCheckListMenu) xTreeList = xCheckListMenu.getChild("check_list_box") @@ -43,7 +43,7 @@ class tdf122260(UITestCase): self.assertIsNotNone(xFloatWindow) # get check list - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") self.assertIsNotNone(xCheckListMenu) xTreeList = xCheckListMenu.getChild("check_list_box") diff --git a/sc/qa/uitest/autofilter2/tdf140754.py b/sc/qa/uitest/autofilter2/tdf140754.py index 1e539e93c5e8..60d9ade24ff7 100644 --- a/sc/qa/uitest/autofilter2/tdf140754.py +++ b/sc/qa/uitest/autofilter2/tdf140754.py @@ -42,7 +42,7 @@ class tdf140754(UITestCase): xAll = xFloatWindow.getChild("toggle_all") xAll.executeAction("CLICK", tuple()) - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(25, len(xList.getChildren())) @@ -61,7 +61,7 @@ class tdf140754(UITestCase): xAll = xFloatWindow.getChild("toggle_all") xAll.executeAction("CLICK", tuple()) - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(10, len(xList.getChildren())) diff --git a/sc/qa/uitest/autofilter2/tdf141946.py b/sc/qa/uitest/autofilter2/tdf141946.py index 4e0de348ee10..4415ec13a61b 100644 --- a/sc/qa/uitest/autofilter2/tdf141946.py +++ b/sc/qa/uitest/autofilter2/tdf141946.py @@ -32,7 +32,7 @@ class tdf141946(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") xEntry = xList.getChild("1") xEntry.executeAction("CLICK", tuple()) @@ -46,7 +46,7 @@ class tdf141946(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(2, len(xList.getChildren())) xCloseBtn = xFloatWindow.getChild("cancel") @@ -54,7 +54,7 @@ class tdf141946(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(1, len(xList.getChildren())) xCloseBtn = xFloatWindow.getChild("cancel") @@ -62,7 +62,7 @@ class tdf141946(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xList.getChildren())) xCloseBtn = xFloatWindow.getChild("cancel") diff --git a/sc/qa/uitest/autofilter2/tdf46062.py b/sc/qa/uitest/autofilter2/tdf46062.py index f0d16a358c9d..4d9c7b662aef 100644 --- a/sc/qa/uitest/autofilter2/tdf46062.py +++ b/sc/qa/uitest/autofilter2/tdf46062.py @@ -29,7 +29,7 @@ class tdf46062(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xList.getChildren())) diff --git a/sc/qa/uitest/autofilter2/tdf46184.py b/sc/qa/uitest/autofilter2/tdf46184.py index 08dfc520b640..8607a202d60a 100755 --- a/sc/qa/uitest/autofilter2/tdf46184.py +++ b/sc/qa/uitest/autofilter2/tdf46184.py @@ -70,7 +70,7 @@ class tdf46184(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xEntry = xTreeList.getChild("1") xEntry.executeAction("CLICK", tuple()) diff --git a/sc/qa/uitest/autofilter2/tdf48025.py b/sc/qa/uitest/autofilter2/tdf48025.py index f5e3e7836a2a..22fdfba0d006 100644 --- a/sc/qa/uitest/autofilter2/tdf48025.py +++ b/sc/qa/uitest/autofilter2/tdf48025.py @@ -37,7 +37,7 @@ class tdf48025(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") xEntry = xList.getChild("1") xEntry.executeAction("CLICK", tuple()) @@ -51,7 +51,7 @@ class tdf48025(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(3, len(xList.getChildren())) xCloseBtn = xFloatWindow.getChild("cancel") @@ -59,7 +59,7 @@ class tdf48025(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xList = xCheckListMenu.getChild("check_list_box") self.assertEqual(2, len(xList.getChildren())) xCloseBtn = xFloatWindow.getChild("cancel") diff --git a/sc/qa/uitest/autofilter2/tdf68113.py b/sc/qa/uitest/autofilter2/tdf68113.py index e6b98db0162d..cccc8e75cf76 100644 --- a/sc/qa/uitest/autofilter2/tdf68113.py +++ b/sc/qa/uitest/autofilter2/tdf68113.py @@ -39,7 +39,7 @@ class tdf68113(UITestCase): # Checkbox elements xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(5, len(xTreeList.getChildren())) self.assertEqual('true', get_state_as_dict(xTreeList.getChild('0'))['IsChecked']) @@ -61,7 +61,7 @@ class tdf68113(UITestCase): # Checkbox elements xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") self.assertEqual(5, len(xTreeList.getChildren())) self.assertEqual('false', get_state_as_dict(xTreeList.getChild('0'))['IsChecked']) diff --git a/sc/qa/uitest/autofilter2/tdf97340.py b/sc/qa/uitest/autofilter2/tdf97340.py index d7e7f0c2afa3..922dd809d98d 100644 --- a/sc/qa/uitest/autofilter2/tdf97340.py +++ b/sc/qa/uitest/autofilter2/tdf97340.py @@ -19,7 +19,7 @@ class tdf97340(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_tree_box") self.assertEqual(2, len(xTreeList.getChildren())) self.assertEqual("2016", get_state_as_dict(xTreeList.getChild('0'))['Text']) diff --git a/sc/qa/uitest/calc_tests9/pivotTable.py b/sc/qa/uitest/calc_tests9/pivotTable.py index 559073ab0507..09f81fa975fe 100644 --- a/sc/qa/uitest/calc_tests9/pivotTable.py +++ b/sc/qa/uitest/calc_tests9/pivotTable.py @@ -76,7 +76,7 @@ class pivotTable(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"PIVOTTABLE": "", "COL": "3", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xCheckListMenu = xFloatWindow.getChild("FilterDropDown") xTreeList = xCheckListMenu.getChild("check_list_box") xFirstEntry = xTreeList.getChild("0") diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 7dfb572d0182..05bd1cc15a0e 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -81,13 +81,6 @@ IMPL_LINK(ScCheckListMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool) switch (rKeyCode.GetCode()) { - case KEY_LEFT: - { - ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); - if (pParentMenu) - pParentMenu->get_widget().endSubMenu(*this); - break; - } case KEY_RIGHT: { if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED) @@ -99,7 +92,7 @@ IMPL_LINK(ScCheckListMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool) maOpenTimer.mnMenuPos = mnSelectedMenu; maOpenTimer.mpSubMenu = rMenu.mxSubMenuWin.get(); - launchSubMenu(true); + launchSubMenu(); } } @@ -112,7 +105,7 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, SelectHdl, weld::TreeView&, void) if (!mxMenu->get_selected(mxScratchIter.get())) { // reselect current item if its submenu is up and the launching item - // became unselected + // became unselected by mouse moving out of the top level menu if (mnSelectedMenu < maMenuItems.size() && maMenuItems[mnSelectedMenu].mxSubMenuWin && maMenuItems[mnSelectedMenu].mxSubMenuWin->IsVisible()) @@ -168,21 +161,14 @@ void ScCheckListMenuControl::CreateDropDown() DrawSymbolFlags::NONE); } -ScCheckListMenuWindow* ScCheckListMenuControl::addSubMenuItem(const OUString& rText, bool bEnabled) +ScListSubMenuControl* ScCheckListMenuControl::addSubMenuItem(const OUString& rText, bool bEnabled) { assert(mbCanHaveSubMenu); MenuItemData aItem; aItem.mbEnabled = bEnabled; - vcl::Window *pContainer = mxFrame->GetWindow(GetWindowType::FirstChild); - vcl::ILibreOfficeKitNotifier* pNotifier = nullptr; - if (comphelper::LibreOfficeKit::isActive()) - pNotifier = SfxViewShell::Current(); - - aItem.mxSubMenuWin.reset(VclPtr<ScCheckListMenuWindow>::Create(pContainer, mpDoc, false, - false, -1, mxFrame.get(), - pNotifier)); + aItem.mxSubMenuWin.reset(new ScListSubMenuControl(mxMenu.get(), *this, mpNotifier)); maMenuItems.emplace_back(std::move(aItem)); mxMenu->show(); @@ -223,12 +209,12 @@ void ScCheckListMenuControl::handleMenuTimeout(const SubMenuItemData* pTimer) // Close any open submenu immediately. if (maCloseTimer.mpSubMenu) { - vcl::Window::GetDockingManager()->EndPopupMode(maCloseTimer.mpSubMenu); + maCloseTimer.mpSubMenu->EndPopupMode(); maCloseTimer.mpSubMenu = nullptr; maCloseTimer.maTimer.Stop(); } - launchSubMenu(false); + launchSubMenu(); } else if (pTimer == &maCloseTimer) { @@ -237,15 +223,19 @@ void ScCheckListMenuControl::handleMenuTimeout(const SubMenuItemData* pTimer) { maOpenTimer.mpSubMenu = nullptr; - vcl::Window::GetDockingManager()->EndPopupMode(maCloseTimer.mpSubMenu); + maCloseTimer.mpSubMenu->EndPopupMode(); maCloseTimer.mpSubMenu = nullptr; + // EndPopup sends a user event, and we want this focus to be set after that has done its conflicting focus-setting work + if (!mnAsyncPostPopdownId) + mnAsyncPostPopdownId = Application::PostUserEvent(LINK(this, ScCheckListMenuControl, PostPopdownHdl)); + maOpenTimer.mnMenuPos = MENU_NOT_SELECTED; } } } -void ScCheckListMenuControl::queueLaunchSubMenu(size_t nPos, ScCheckListMenuWindow* pMenu) +void ScCheckListMenuControl::queueLaunchSubMenu(size_t nPos, ScListSubMenuControl* pMenu) { if (!pMenu) return; @@ -253,15 +243,16 @@ void ScCheckListMenuControl::queueLaunchSubMenu(size_t nPos, ScCheckListMenuWind // Set the submenu on launch queue. if (maOpenTimer.mpSubMenu) { - if (maOpenTimer.mpSubMenu == pMenu) + if (maOpenTimer.mpSubMenu != pMenu) + { + // new submenu is being requested. + queueCloseSubMenu(); + } + else { if (pMenu == maCloseTimer.mpSubMenu) maCloseTimer.reset(); - return; } - - // new submenu is being requested. - queueCloseSubMenu(); } maOpenTimer.mpSubMenu = pMenu; @@ -295,9 +286,9 @@ sal_Int32 ScCheckListMenuControl::ExecuteMenu(weld::Menu& rMenu) return rMenu.popup_at_rect(mxMenu.get(), GetSubMenuParentRect(), weld::Placement::End).toInt32(); } -void ScCheckListMenuControl::launchSubMenu(bool bSetMenuPos) +void ScCheckListMenuControl::launchSubMenu() { - ScCheckListMenuWindow* pSubMenu = maOpenTimer.mpSubMenu; + ScListSubMenuControl* pSubMenu = maOpenTimer.mpSubMenu; if (!pSubMenu) return; @@ -305,16 +296,10 @@ void ScCheckListMenuControl::launchSubMenu(bool bSetMenuPos) return; tools::Rectangle aRect = GetSubMenuParentRect(); - ScCheckListMenuControl& rSubMenuControl = pSubMenu->get_widget(); - rSubMenuControl.StartPopupMode(aRect, FloatWinPopupFlags::Right); - if (bSetMenuPos) - rSubMenuControl.setSelectedMenuItem(0, false); // select menu item after the popup becomes fully visible. + pSubMenu->StartPopupMode(mxMenu.get(), aRect); mxMenu->select(*mxScratchIter); - rSubMenuControl.GrabFocus(); - - if (comphelper::LibreOfficeKit::isActive()) - jsdialog::SendFullUpdate(pSubMenu->GetLOKWindowId(), "toggle_all"); + pSubMenu->GrabFocus(); } IMPL_LINK_NOARG(ScCheckListMenuControl, PostPopdownHdl, void*, void) @@ -323,7 +308,15 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, PostPopdownHdl, void*, void) mxMenu->grab_focus(); } -void ScCheckListMenuControl::endSubMenu(ScCheckListMenuControl& rSubMenu) +IMPL_LINK(ScCheckListMenuControl, MouseEnterHdl, const MouseEvent&, rMEvt, bool) +{ + if (!rMEvt.IsEnterWindow()) + return false; + selectMenuItem(MENU_NOT_SELECTED, true); + return false; +} + +void ScCheckListMenuControl::endSubMenu(ScListSubMenuControl& rSubMenu) { rSubMenu.EndPopupMode(); maOpenTimer.reset(); @@ -362,15 +355,11 @@ void ScCheckListMenuControl::selectMenuItem(size_t nPos, bool bSubMenuTimer) return; } - ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); - if (pParentMenu) - pParentMenu->get_widget().setSubMenuFocused(this); - if (bSubMenuTimer) { if (maMenuItems[nPos].mxSubMenuWin) { - ScCheckListMenuWindow* pSubMenu = maMenuItems[nPos].mxSubMenuWin.get(); + ScListSubMenuControl* pSubMenu = maMenuItems[nPos].mxSubMenuWin.get(); queueLaunchSubMenu(nPos, pSubMenu); } else @@ -383,20 +372,18 @@ void ScCheckListMenuControl::clearSelectedMenuItem() selectMenuItem(MENU_NOT_SELECTED, false); } -size_t ScCheckListMenuControl::getSubMenuPos(const ScCheckListMenuControl* pSubMenu) +size_t ScCheckListMenuControl::getSubMenuPos(const ScListSubMenuControl* pSubMenu) { size_t n = maMenuItems.size(); for (size_t i = 0; i < n; ++i) { - if (!maMenuItems[i].mxSubMenuWin) - continue; - if (&maMenuItems[i].mxSubMenuWin->get_widget() == pSubMenu) + if (maMenuItems[i].mxSubMenuWin.get() == pSubMenu) return i; } return MENU_NOT_SELECTED; } -void ScCheckListMenuControl::setSubMenuFocused(const ScCheckListMenuControl* pSubMenu) +void ScCheckListMenuControl::setSubMenuFocused(const ScListSubMenuControl* pSubMenu) { maCloseTimer.reset(); size_t nMenuPos = getSubMenuPos(pSubMenu); @@ -409,16 +396,14 @@ void ScCheckListMenuControl::setSubMenuFocused(const ScCheckListMenuControl* pSu void ScCheckListMenuControl::EndPopupMode() { - vcl::Window::GetDockingManager()->EndPopupMode(mxFrame); - mxFrame->EnableDocking(false); + mxPopover->popdown(); } -void ScCheckListMenuControl::StartPopupMode(const tools::Rectangle& rRect, FloatWinPopupFlags eFlags) +void ScCheckListMenuControl::StartPopupMode(weld::Widget* pParent, const tools::Rectangle& rRect) { - mxFrame->EnableDocking(true); - DockingManager* pDockingManager = vcl::Window::GetDockingManager(); - pDockingManager->SetPopupModeEndHdl(mxFrame, LINK(this, ScCheckListMenuControl, PopupModeEndHdl)); - pDockingManager->StartPopupMode(mxFrame, rRect, (eFlags | FloatWinPopupFlags::GrabFocus)); + mxPopover->connect_closed(LINK(this, ScCheckListMenuControl, PopupModeEndHdl)); + mxPopover->popup_at_rect(pParent, rRect); + GrabFocus(); } void ScCheckListMenuControl::terminateAllPopupMenus() @@ -427,9 +412,6 @@ void ScCheckListMenuControl::terminateAllPopupMenus() NotifyCloseLOK(); EndPopupMode(); - ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); - if (pParentMenu) - pParentMenu->get_widget().terminateAllPopupMenus(); } ScCheckListMenuControl::Config::Config() : @@ -447,14 +429,18 @@ ScCheckListMember::ScCheckListMember() { } -ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, vcl::Window* pContainer, +// the value of border-width of FilterDropDown +constexpr int nBorderWidth = 4; + +ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScDocument* pDoc, bool bCanHaveSubMenu, - bool bHasDates, int nWidth) - : mxFrame(pParent) - , mxBuilder(Application::CreateInterimBuilder(pContainer, "modules/scalc/ui/filterdropdown.ui", false)) - , mxContainer(mxBuilder->weld_container("FilterDropDown")) + bool bHasDates, int nWidth, vcl::ILibreOfficeKitNotifier* pNotifier) + : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/filterdropdown.ui")) + , mxPopover(mxBuilder->weld_popover("FilterDropDown")) + , mxContainer(mxBuilder->weld_container("container")) , mxMenu(mxBuilder->weld_tree_view("menu")) , mxScratchIter(mxMenu->make_iterator()) + , mxNonMenu(mxBuilder->weld_widget("nonmenu")) , mxEdSearch(mxBuilder->weld_entry("search_edit")) , mxBox(mxBuilder->weld_widget("box")) , mxListChecks(mxBuilder->weld_tree_view("check_list_box")) @@ -472,6 +458,7 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v , mnSelectedMenu(MENU_NOT_SELECTED) , mpDoc(pDoc) , mnAsyncPostPopdownId(nullptr) + , mpNotifier(pNotifier) , mbHasDates(bHasDates) , mbCanHaveSubMenu(bCanHaveSubMenu) , maOpenTimer(this) @@ -479,7 +466,16 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v { mxTreeChecks->set_clicks_to_toggle(1); mxListChecks->set_clicks_to_toggle(1); - mxMenu->hide(); // show only when has items + + mxNonMenu->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxEdSearch->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxListChecks->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxTreeChecks->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxChkToggleAll->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxBtnSelectSingle->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxBtnUnselectSingle->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxBtnOk->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); + mxBtnCancel->connect_mouse_move(LINK(this, ScCheckListMenuControl, MouseEnterHdl)); /* tdf#136559 If we have no dates we don't need a tree @@ -497,12 +493,10 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v mpChecks = mxListChecks.get(); } - bool bIsSubMenu = pParent->GetParentMenu(); - int nChecksHeight = mxTreeChecks->get_height_rows(9); - if (!bIsSubMenu && nWidth != -1) + if (nWidth != -1) { - mnCheckWidthReq = nWidth - mxFrame->get_border_width() * 2 - 4; + mnCheckWidthReq = nWidth - nBorderWidth * 2 - 4; mxTreeChecks->set_size_request(mnCheckWidthReq, nChecksHeight); mxListChecks->set_size_request(mnCheckWidthReq, nChecksHeight); } @@ -511,35 +505,28 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v // popup isn't a true dialog mxButtonBox->sort_native_button_order(); - if (!bIsSubMenu) - { - mxTreeChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); - mxListChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxTreeChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxListChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); - mxBox->show(); - mxEdSearch->show(); - mxButtonBox->show(); - } + mxBox->show(); + mxEdSearch->show(); + mxButtonBox->show(); - mxContainer->connect_focus_in(LINK(this, ScCheckListMenuControl, FocusHdl)); mxMenu->connect_row_activated(LINK(this, ScCheckListMenuControl, RowActivatedHdl)); mxMenu->connect_changed(LINK(this, ScCheckListMenuControl, SelectHdl)); mxMenu->connect_key_press(LINK(this, ScCheckListMenuControl, MenuKeyInputHdl)); - if (!bIsSubMenu) - { - mxBtnOk->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); - mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); - mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl)); - mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl)); - mxTreeChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); - mxTreeChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); - mxListChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); - mxListChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); - mxChkToggleAll->connect_toggled(LINK(this, ScCheckListMenuControl, TriStateHdl)); - mxBtnSelectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); - mxBtnUnselectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); - } + mxBtnOk->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); + mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); + mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl)); + mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl)); + mxTreeChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); + mxTreeChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); + mxListChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); + mxListChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); + mxChkToggleAll->connect_toggled(LINK(this, ScCheckListMenuControl, TriStateHdl)); + mxBtnSelectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); + mxBtnUnselectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); if (mbCanHaveSubMenu) { @@ -547,20 +534,12 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v mxMenu->connect_size_allocate(LINK(this, ScCheckListMenuControl, TreeSizeAllocHdl)); } - if (!bIsSubMenu) - { - // determine what width the checklist will end up with - mnCheckWidthReq = mxContainer->get_preferred_size().Width(); - // make that size fixed now, we can now use mnCheckWidthReq to speed up - // bulk_insert_for_each - mxTreeChecks->set_size_request(mnCheckWidthReq, nChecksHeight); - mxListChecks->set_size_request(mnCheckWidthReq, nChecksHeight); - } -} - -IMPL_LINK_NOARG(ScCheckListMenuControl, FocusHdl, weld::Widget&, void) -{ - GrabFocus(); + // determine what width the checklist will end up with + mnCheckWidthReq = mxContainer->get_preferred_size().Width(); + // make that size fixed now, we can now use mnCheckWidthReq to speed up + // bulk_insert_for_each + mxTreeChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + mxListChecks->set_size_request(mnCheckWidthReq, nChecksHeight); } void ScCheckListMenuControl::GrabFocus() @@ -578,7 +557,7 @@ ScCheckListMenuControl::~ScCheckListMenuControl() { EndPopupMode(); for (auto& rMenuItem : maMenuItems) - rMenuItem.mxSubMenuWin.disposeAndClear(); + rMenuItem.mxSubMenuWin.reset(); if (mnAsyncPostPopdownId) { Application::RemoveUserEvent(mnAsyncPostPopdownId); @@ -586,51 +565,6 @@ ScCheckListMenuControl::~ScCheckListMenuControl() } } -ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, bool bCanHaveSubMenu, - bool bTreeMode, int nWidth, ScCheckListMenuWindow* pParentMenu, - const vcl::ILibreOfficeKitNotifier* pNotifier) - : DropdownDockingWindow(pParent) - , mxParentMenu(pParentMenu) -{ - if (pNotifier) - SetLOKNotifier(pNotifier); - setDeferredProperties(); - mxControl.reset(new ScCheckListMenuControl(this, m_xBox.get(), pDoc, bCanHaveSubMenu, bTreeMode, nWidth)); - SetBackground(Application::GetSettings().GetStyleSettings().GetMenuColor()); - set_id("check_list_menu"); -} - -bool ScCheckListMenuWindow::EventNotify(NotifyEvent& rNEvt) -{ - if (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) - { - ScCheckListMenuControl& rMenuControl = get_widget(); - rMenuControl.queueCloseSubMenu(); - rMenuControl.clearSelectedMenuItem(); - } - return DropdownDockingWindow::EventNotify(rNEvt); -} - -ScCheckListMenuWindow::~ScCheckListMenuWindow() -{ - disposeOnce(); -} - -void ScCheckListMenuWindow::dispose() -{ - mxControl.reset(); - mxParentMenu.clear(); - DropdownDockingWindow::dispose(); -} - -void ScCheckListMenuWindow::GetFocus() -{ - DropdownDockingWindow::GetFocus(); - if (!mxControl) - return; - mxControl->GrabFocus(); -} - void ScCheckListMenuControl::prepWindow() { mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2); @@ -641,7 +575,7 @@ void ScCheckListMenuControl::prepWindow() mxMenu->unselect_all(); } - mnWndWidth = mxContainer->get_preferred_size().Width() + mxFrame->get_border_width() * 2 + 4; + mnWndWidth = mxContainer->get_preferred_size().Width() + nBorderWidth * 2 + 4; } void ScCheckListMenuControl::setAllMemberState(bool bSet) @@ -1395,7 +1329,7 @@ void ScCheckListMenuControl::getResult(ResultType& rResult) rResult.swap(aResult); } -void ScCheckListMenuControl::launch(const tools::Rectangle& rRect) +void ScCheckListMenuControl::launch(weld::Widget* pWidget, const tools::Rectangle& rRect) { prepWindow(); if (!maConfig.mbAllowEmptySet) @@ -1418,24 +1352,19 @@ void ScCheckListMenuControl::launch(const tools::Rectangle& rRect) aRect.AdjustLeft(nDiff ); } - StartPopupMode(aRect, FloatWinPopupFlags::Down); + StartPopupMode(pWidget, aRect); } void ScCheckListMenuControl::NotifyCloseLOK() { - VclPtr<vcl::Window> aNotifierWindow = mxFrame->GetParentWithLOKNotifier(); - if (!aNotifierWindow) - return; - - const vcl::ILibreOfficeKitNotifier* pNotifier = aNotifierWindow->GetLOKNotifier(); - if (pNotifier) + if (mpNotifier) { tools::JsonWriter aJsonWriter; aJsonWriter.put("jsontype", "autofilter"); aJsonWriter.put("action", "close"); const std::string message = aJsonWriter.extractAsStdString(); - pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str()); + mpNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str()); } } @@ -1469,7 +1398,7 @@ void ScCheckListMenuControl::setPopupEndAction(Action* p) mxPopupEndAction.reset(p); } -IMPL_LINK_NOARG(ScCheckListMenuControl, PopupModeEndHdl, FloatingWindow*, void) +IMPL_LINK_NOARG(ScCheckListMenuControl, PopupModeEndHdl, weld::Popover&, void) { clearSelectedMenuItem(); if (mxPopupEndAction) @@ -1486,7 +1415,7 @@ int ScCheckListMenuControl::GetTextWidth(const OUString& rsName) const int ScCheckListMenuControl::IncreaseWindowWidthToFitText(int nMaxTextWidth) { - int nBorder = mxFrame->get_border_width() * 2 + 4; + int nBorder = nBorderWidth * 2 + 4; int nNewWidth = nMaxTextWidth - nBorder; if (nNewWidth > mnCheckWidthReq) { @@ -1497,4 +1426,119 @@ int ScCheckListMenuControl::IncreaseWindowWidthToFitText(int nMaxTextWidth) return mnCheckWidthReq + nBorder; } +ScListSubMenuControl::ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, vcl::ILibreOfficeKitNotifier* pNotifier) + : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/filtersubdropdown.ui")) + , mxPopover(mxBuilder->weld_popover("FilterSubDropDown")) + , mxContainer(mxBuilder->weld_container("container")) + , mxMenu(mxBuilder->weld_tree_view("menu")) + , mxScratchIter(mxMenu->make_iterator()) + , mrParentControl(rParentControl) + , mpNotifier(pNotifier) +{ + mxMenu->connect_row_activated(LINK(this, ScListSubMenuControl, RowActivatedHdl)); + mxMenu->connect_key_press(LINK(this, ScListSubMenuControl, MenuKeyInputHdl)); +} + +void ScListSubMenuControl::StartPopupMode(weld::Widget* pParent, const tools::Rectangle& rRect) +{ + mxPopover->popup_at_rect(pParent, rRect, weld::Placement::End); + + mxMenu->set_cursor(0); + mxMenu->select(0); + + mrParentControl.setSubMenuFocused(this); +} + +void ScListSubMenuControl::EndPopupMode() +{ + mxPopover->popdown(); +} + +void ScListSubMenuControl::GrabFocus() +{ + mxMenu->grab_focus(); +} + +bool ScListSubMenuControl::IsVisible() const +{ + return mxPopover->get_visible(); +} + +void ScListSubMenuControl::resizeToFitMenuItems() +{ + mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2); +} + +void ScListSubMenuControl::addMenuItem(const OUString& rText, ScCheckListMenuControl::Action* pAction) +{ + ScCheckListMenuControl::MenuItemData aItem; + aItem.mbEnabled = true; + aItem.mxAction.reset(pAction); + maMenuItems.emplace_back(std::move(aItem)); + + mxMenu->show(); + mxMenu->append_text(rText); +} + +IMPL_LINK(ScListSubMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + bool bConsumed = false; + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + + switch (rKeyCode.GetCode()) + { + case KEY_ESCAPE: + case KEY_LEFT: + { + mrParentControl.endSubMenu(*this); + bConsumed = true; + break; + } + } + + return bConsumed; +} + +IMPL_LINK_NOARG(ScListSubMenuControl, RowActivatedHdl, weld::TreeView&, bool) +{ + executeMenuItem(mxMenu->get_selected_index()); + return true; +} + +void ScListSubMenuControl::executeMenuItem(size_t nPos) +{ + if (nPos >= maMenuItems.size()) + return; + + if (!maMenuItems[nPos].mxAction) + // no action is defined. + return; + + const bool bClosePopup = maMenuItems[nPos].mxAction->execute(); + if (bClosePopup) + terminateAllPopupMenus(); +} + +void ScListSubMenuControl::terminateAllPopupMenus() +{ + if (comphelper::LibreOfficeKit::isActive()) + NotifyCloseLOK(); + + EndPopupMode(); + mrParentControl.terminateAllPopupMenus(); +} + +void ScListSubMenuControl::NotifyCloseLOK() +{ + if (mpNotifier) + { + tools::JsonWriter aJsonWriter; + aJsonWriter.put("jsontype", "autofilter"); + aJsonWriter.put("action", "close"); + + const std::string message = aJsonWriter.extractAsStdString(); + mpNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str()); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx index c9ca6466dff7..dd398dd9f651 100644 --- a/sc/source/ui/inc/checklistmenu.hxx +++ b/sc/source/ui/inc/checklistmenu.hxx @@ -48,7 +48,11 @@ struct ScCheckListMember }; class ScCheckListMenuWindow; +class ScListSubMenuControl; +/** + * This class implements a popup window for the auto filter dropdown. + */ class ScCheckListMenuControl final { public: @@ -94,7 +98,7 @@ public: { bool mbEnabled:1; std::shared_ptr<Action> mxAction; - VclPtr<ScCheckListMenuWindow> mxSubMenuWin; + std::unique_ptr<ScListSubMenuControl> mxSubMenuWin; MenuItemData(); }; @@ -119,17 +123,18 @@ public: Config(); }; - ScCheckListMenuControl(ScCheckListMenuWindow* pParent, vcl::Window* pContainer, ScDocument* pDoc, - bool bCanHaveSubMenu, bool bTreeMode, int nWidth); + ScCheckListMenuControl(weld::Widget* pParent, ScDocument* pDoc, + bool bCanHaveSubMenu, bool bTreeMode, int nWidth, + vcl::ILibreOfficeKitNotifier* pNotifier); ~ScCheckListMenuControl(); void addMenuItem(const OUString& rText, Action* pAction); void addSeparator(); - ScCheckListMenuWindow* addSubMenuItem(const OUString& rText, bool bEnabled); + ScListSubMenuControl* addSubMenuItem(const OUString& rText, bool bEnabled); void resizeToFitMenuItems(); void selectMenuItem(size_t nPos, bool bSubMenuTimer); - void queueLaunchSubMenu(size_t nPos, ScCheckListMenuWindow* pMenu); + void queueLaunchSubMenu(size_t nPos, ScListSubMenuControl* pMenu); void setMemberSize(size_t n); void addDateMember(const OUString& rName, double nVal, bool bVisible); @@ -140,14 +145,14 @@ public: bool isAllSelected() const; void getResult(ResultType& rResult); - void launch(const tools::Rectangle& rRect); + void launch(weld::Widget* pWidget, const tools::Rectangle& rRect); void close(bool bOK); - void StartPopupMode(const tools::Rectangle& rRect, FloatWinPopupFlags eFlags); + void StartPopupMode(weld::Widget* pParent, const tools::Rectangle& rRect); void EndPopupMode(); - size_t getSubMenuPos(const ScCheckListMenuControl* pSubMenu); - void setSubMenuFocused(const ScCheckListMenuControl* pSubMenu); + size_t getSubMenuPos(const ScListSubMenuControl* pSubMenu); + void setSubMenuFocused(const ScListSubMenuControl* pSubMenu); void queueCloseSubMenu(); void clearSelectedMenuItem(); @@ -177,12 +182,9 @@ public: */ void terminateAllPopupMenus(); - /** - * Get the area of the active row. Suitable as the parent rectangle - * argument for Executing a popup - */ - tools::Rectangle GetSubMenuParentRect(); sal_Int32 ExecuteMenu(weld::Menu& rMenu); + + void endSubMenu(ScListSubMenuControl& rSubMenu); private: std::vector<MenuItemData> maMenuItems; @@ -210,13 +212,17 @@ private: void executeMenuItem(size_t nPos); - void endSubMenu(ScCheckListMenuControl& rSubMenu); + /** + * Get the area of the active row. Suitable as the parent rectangle + * argument for Executing a popup + */ + tools::Rectangle GetSubMenuParentRect(); struct SubMenuItemData; void handleMenuTimeout(const SubMenuItemData* pTimer); - void launchSubMenu(bool bSetMenuPos); + void launchSubMenu(); void CreateDropDown(); @@ -229,26 +235,27 @@ private: DECL_LINK(CheckHdl, const weld::TreeView::iter_col&, void); - DECL_LINK(PopupModeEndHdl, FloatingWindow*, void); + DECL_LINK(PopupModeEndHdl, weld::Popover&, void); DECL_LINK(EdModifyHdl, weld::Entry&, void); DECL_LINK(EdActivateHdl, weld::Entry&, bool); - DECL_LINK(FocusHdl, weld::Widget&, void); DECL_LINK(RowActivatedHdl, weld::TreeView& rMEvt, bool); DECL_LINK(SelectHdl, weld::TreeView&, void); DECL_LINK(TreeSizeAllocHdl, const Size&, void); DECL_LINK(KeyInputHdl, const KeyEvent&, bool); DECL_LINK(MenuKeyInputHdl, const KeyEvent&, bool); + DECL_LINK(MouseEnterHdl, const MouseEvent&, bool); DECL_LINK(PostPopdownHdl, void*, void); private: - VclPtr<ScCheckListMenuWindow> mxFrame; std::unique_ptr<weld::Builder> mxBuilder; + std::unique_ptr<weld::Popover> mxPopover; std::unique_ptr<weld::Container> mxContainer; std::unique_ptr<weld::TreeView> mxMenu; std::unique_ptr<weld::TreeIter> mxScratchIter; + std::unique_ptr<weld::Widget> mxNonMenu; std::unique_ptr<weld::Entry> mxEdSearch; std::unique_ptr<weld::Widget> mxBox; std::unique_ptr<weld::TreeView> mxListChecks; @@ -283,6 +290,7 @@ private: ScDocument* mpDoc; ImplSVEvent* mnAsyncPostPopdownId; + vcl::ILibreOfficeKitNotifier* mpNotifier; bool mbHasDates; bool mbCanHaveSubMenu; @@ -290,7 +298,7 @@ private: struct SubMenuItemData { Timer maTimer; - VclPtr<ScCheckListMenuWindow> mpSubMenu; + ScListSubMenuControl* mpSubMenu; size_t mnMenuPos; DECL_LINK( TimeoutHdl, Timer*, void ); @@ -306,28 +314,43 @@ private: SubMenuItemData maCloseTimer; }; -/** - * This class implements a popup window for the auto filter dropdown. - */ -class ScCheckListMenuWindow : public DropdownDockingWindow +class ScListSubMenuControl final { public: - explicit ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, - bool bCanHaveSubMenu, bool bTreeMode, int nWidth = -1, - ScCheckListMenuWindow* pParentMenu = nullptr, - const vcl::ILibreOfficeKitNotifier* pNotifier = nullptr); - virtual void dispose() override; - virtual ~ScCheckListMenuWindow() override; + ScListSubMenuControl(weld::Widget* pParent, ScCheckListMenuControl& rParentControl, vcl::ILibreOfficeKitNotifier* pNotifier); + + void GrabFocus(); + bool IsVisible() const; - virtual void GetFocus() override; - virtual bool EventNotify(NotifyEvent& rNEvt) override; + void StartPopupMode(weld::Widget* pParent, const tools::Rectangle& rRect); + void EndPopupMode(); + + void addMenuItem(const OUString& rText, ScCheckListMenuControl::Action* pAction); + void resizeToFitMenuItems(); - ScCheckListMenuWindow* GetParentMenu() { return mxParentMenu; } - ScCheckListMenuControl& get_widget() { return *mxControl; } + void setSelectedMenuItem(size_t nPos); + + /** + * Dismiss all visible popup menus and set focus back to the application + * window. This method is called e.g. when a menu action is fired. + */ + void terminateAllPopupMenus(); private: - VclPtr<ScCheckListMenuWindow> mxParentMenu; - std::unique_ptr<ScCheckListMenuControl, o3tl::default_delete<ScCheckListMenuControl>> mxControl; + std::unique_ptr<weld::Builder> mxBuilder; + std::unique_ptr<weld::Popover> mxPopover; + std::unique_ptr<weld::Container> mxContainer; + std::unique_ptr<weld::TreeView> mxMenu; + std::unique_ptr<weld::TreeIter> mxScratchIter; + std::vector<ScCheckListMenuControl::MenuItemData> maMenuItems; + ScCheckListMenuControl& mrParentControl; + vcl::ILibreOfficeKitNotifier* mpNotifier; + + DECL_LINK(RowActivatedHdl, weld::TreeView& rMEvt, bool); + DECL_LINK(MenuKeyInputHdl, const KeyEvent&, bool); + + void NotifyCloseLOK(); + void executeMenuItem(size_t nPos); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 0bf9fb7ce006..2f8ac0deacfc 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -152,8 +152,8 @@ class SAL_DLLPUBLIC_RTTI ScGridWindow : public vcl::Window, public DropTargetHel std::unique_ptr<ScNoteMarker, o3tl::default_delete<ScNoteMarker>> mpNoteMarker; std::shared_ptr<ScFilterListBox> mpFilterBox; - VclPtr<ScCheckListMenuWindow> mpAutoFilterPopup; - VclPtr<ScCheckListMenuWindow> mpDPFieldPopup; + std::unique_ptr<ScCheckListMenuControl> mpAutoFilterPopup; + std::unique_ptr<ScCheckListMenuControl> mpDPFieldPopup; std::unique_ptr<ScDPFieldButton> mpFilterButton; ScCheckListMenuControl::ResultType aSaveAutoFilterResult; diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 5b203addbb12..3116dfb9ac13 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -434,8 +434,8 @@ void ScGridWindow::dispose() mpFilterBox.reset(); mpNoteMarker.reset(); - mpAutoFilterPopup.disposeAndClear(); - mpDPFieldPopup.disposeAndClear(); + mpAutoFilterPopup.reset(); + mpDPFieldPopup.reset(); aComboButton.SetOutputDevice(nullptr); if (mpSpellCheckCxt) @@ -458,8 +458,8 @@ void ScGridWindow::ClickExtern() if (mpDPFieldPopup) { - mpDPFieldPopup->get_widget().close(false); - mpDPFieldPopup.disposeAndClear(); + mpDPFieldPopup->close(false); + mpDPFieldPopup.reset(); } } @@ -582,7 +582,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) ScDocument& rDoc = mrViewData.GetDocument(); bool bLOKActive = comphelper::LibreOfficeKit::isActive(); - mpAutoFilterPopup.disposeAndClear(); + mpAutoFilterPopup.reset(); // Estimate the width (in pixels) of the longest text in the list ScFilterEntries aFilterEntries; @@ -592,11 +592,10 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) if (bLOKActive) pNotifier = SfxViewShell::Current(); + weld::Window* pPopupParent = GetFrameWeld(); int nColWidth = ScViewData::ToPixel(rDoc.GetColWidth(nCol, nTab), mrViewData.GetPPTX()); - mpAutoFilterPopup.reset(VclPtr<ScCheckListMenuWindow>::Create(this, &rDoc, false, - aFilterEntries.mbHasDates, nColWidth, - nullptr, pNotifier)); - ScCheckListMenuControl& rControl = mpAutoFilterPopup->get_widget(); + mpAutoFilterPopup.reset(new ScCheckListMenuControl(pPopupParent, &rDoc, false, + aFilterEntries.mbHasDates, nColWidth, pNotifier)); int nMaxTextWidth = 0; if (aFilterEntries.size() <= 10) @@ -605,7 +604,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) for (const auto& rEntry : aFilterEntries) { const OUString& aText = rEntry.GetString(); - nMaxTextWidth = std::max<int>(nMaxTextWidth, rControl.GetTextWidth(aText) + aText.getLength() * 2); + nMaxTextWidth = std::max<int>(nMaxTextWidth, mpAutoFilterPopup->GetTextWidth(aText) + aText.getLength() * 2); } } else @@ -622,17 +621,17 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) itMax = it; } } - nMaxTextWidth = rControl.GetTextWidth(itMax->GetString()) + nMaxTextWidth * 2; + nMaxTextWidth = mpAutoFilterPopup->GetTextWidth(itMax->GetString()) + nMaxTextWidth * 2; } // window should be at least as wide as the column, or the longest text + checkbox, scrollbar ... (it is estimated with 70 pixel now) // window should be maximum 1024 pixel wide. int nWindowWidth = std::min<int>(1024, nMaxTextWidth + 70); - nWindowWidth = rControl.IncreaseWindowWidthToFitText(nWindowWidth); + nWindowWidth = mpAutoFilterPopup->IncreaseWindowWidthToFitText(nWindowWidth); nMaxTextWidth = std::max<int>(nMaxTextWidth, nWindowWidth - 70); - rControl.setOKAction(new AutoFilterAction(this, AutoFilterMode::Normal)); - rControl.setPopupEndAction( + mpAutoFilterPopup->setOKAction(new AutoFilterAction(this, AutoFilterMode::Normal)); + mpAutoFilterPopup->setPopupEndAction( new AutoFilterPopupEndAction(this, ScAddress(nCol, nRow, nTab))); std::unique_ptr<AutoFilterData> pData(new AutoFilterData); pData->maPos = ScAddress(nCol, nRow, nTab); @@ -660,7 +659,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) return; pData->mpData = pDBData; - rControl.setExtendedData(std::move(pData)); + mpAutoFilterPopup->setExtendedData(std::move(pData)); ScQueryParam aParam; pDBData->GetQueryParam(aParam); @@ -682,7 +681,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) } // Populate the check box list. - rControl.setMemberSize(aFilterEntries.size()); + mpAutoFilterPopup->setMemberSize(aFilterEntries.size()); for (auto it = aFilterEntries.begin(); it != aFilterEntries.end(); ++it) { // tdf#140745 show (empty) entry on top of the checkbox list @@ -695,7 +694,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) bSelected = aSelectedString.count(aStringVal) > 0; else if (bQueryByNonEmpty) bSelected = false; - rControl.addMember(aStringVal, aDoubleVal, bSelected); + mpAutoFilterPopup->addMember(aStringVal, aDoubleVal, bSelected); aFilterEntries.maStrData.erase(it); break; } @@ -716,49 +715,49 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) } if ( rEntry.IsDate() ) - rControl.addDateMember( aStringVal, rEntry.GetValue(), bSelected ); + mpAutoFilterPopup->addDateMember( aStringVal, rEntry.GetValue(), bSelected ); else - rControl.addMember( aStringVal, aRDoubleVal, bSelected, rEntry.GetStringType() == ScTypedStrData::Value ); + mpAutoFilterPopup->addMember( aStringVal, aRDoubleVal, bSelected, rEntry.GetStringType() == ScTypedStrData::Value ); } // Populate the menu. - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(STR_MENU_SORT_ASC), new AutoFilterAction(this, AutoFilterMode::SortAscending)); - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(STR_MENU_SORT_DESC), new AutoFilterAction(this, AutoFilterMode::SortDescending)); - rControl.addSeparator(); - rControl.addMenuItem( + mpAutoFilterPopup->addSeparator(); + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_TOP10FILTER), new AutoFilterAction(this, AutoFilterMode::Top10)); - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_FILTER_EMPTY), new AutoFilterAction(this, AutoFilterMode::Empty)); - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_FILTER_NOTEMPTY), new AutoFilterAction(this, AutoFilterMode::NonEmpty)); - rControl.addSeparator(); - rControl.addMenuItem( + mpAutoFilterPopup->addSeparator(); + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_FILTER_TEXT_COLOR), new AutoFilterAction(this, AutoFilterMode::TextColor)); - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_FILTER_BACKGROUND_COLOR), new AutoFilterAction(this, AutoFilterMode::BackgroundColor)); - rControl.addSeparator(); - rControl.addMenuItem( + mpAutoFilterPopup->addSeparator(); + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom)); if (aEntries.size()) - rControl.addMenuItem( + mpAutoFilterPopup->addMenuItem( ScResId(SCSTR_CLEAR_FILTER), new AutoFilterAction(this, AutoFilterMode::Clear)); - rControl.initMembers(nMaxTextWidth + 20); // 20 pixel estimated for the checkbox + mpAutoFilterPopup->initMembers(nMaxTextWidth + 20); // 20 pixel estimated for the checkbox ScCheckListMenuControl::Config aConfig; aConfig.mbAllowEmptySet = false; aConfig.mbRTL = mrViewData.GetDocument().IsLayoutRTL(mrViewData.GetTabNo()); - rControl.setConfig(aConfig); + mpAutoFilterPopup->setConfig(aConfig); if (IsMouseCaptured()) ReleaseMouse(); - rControl.launch(aCellRect); + mpAutoFilterPopup->launch(pPopupParent, aCellRect); // remember filter rules before modification - rControl.getResult(aSaveAutoFilterResult); + mpAutoFilterPopup->getResult(aSaveAutoFilterResult); collectUIInformation(OUString::number(nRow), OUString::number(nCol),"AUTOFILTER"); } @@ -776,15 +775,13 @@ void ScGridWindow::RefreshAutoFilterButton(const ScAddress& rPos) void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) { - ScCheckListMenuControl& rControl = mpAutoFilterPopup->get_widget(); - // Terminate autofilter popup now when there is no further user input needed bool bColorMode = eMode == AutoFilterMode::TextColor || eMode == AutoFilterMode::BackgroundColor; if (!bColorMode) - rControl.terminateAllPopupMenus(); + mpAutoFilterPopup->terminateAllPopupMenus(); const AutoFilterData* pData = - static_cast<const AutoFilterData*>(rControl.getExtendedData()); + static_cast<const AutoFilterData*>(mpAutoFilterPopup->getExtendedData()); if (!pData) return; @@ -848,13 +845,13 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) { // Do not recreate autofilter rules if there are no changes from the user ScCheckListMenuControl::ResultType aResult; - rControl.getResult(aResult); + mpAutoFilterPopup->getResult(aResult); if (aResult == aSaveAutoFilterResult) { SAL_INFO("sc.ui", "Apply autofilter to data when entries are the same"); - if (!rControl.isAllSelected()) + if (!mpAutoFilterPopup->isAllSelected()) { // Apply autofilter to data ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true); @@ -882,7 +879,7 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) } if (eMode != AutoFilterMode::Clear - && !(eMode == AutoFilterMode::Normal && rControl.isAllSelected())) + && !(eMode == AutoFilterMode::Normal && mpAutoFilterPopup->isAllSelected())) { // Try to use the existing entry for the column (if one exists). ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true); @@ -905,7 +902,7 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) pEntry->eOp = SC_EQUAL; ScCheckListMenuControl::ResultType aResult; - rControl.getResult(aResult); + mpAutoFilterPopup->getResult(aResult); ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems(); rItems.clear(); @@ -929,8 +926,8 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) ScFilterEntries aFilterEntries; rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries); - weld::Window* pPopupParent = mpAutoFilterPopup->GetFrameWeld(); - std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "modules/scalc/ui/colormenu.ui")); + weld::Window* pWindow = GetFrameWeld(); + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pWindow, "modules/scalc/ui/colormenu.ui")); std::unique_ptr<weld::Menu> xColorMenu(xBuilder->weld_menu("menu")); std::set<Color> aColors = eMode == AutoFilterMode::TextColor @@ -951,7 +948,7 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) else { // ColorListBox::ShowPreview is similar - ScopedVclPtr<VirtualDevice> xDev(pPopupParent->create_virtual_device()); + ScopedVclPtr<VirtualDevice> xDev(pWindow->create_virtual_device()); const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); xDev->SetOutputSize(aImageSize); @@ -976,13 +973,13 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) i++; } - sal_Int32 nSelected = rControl.ExecuteMenu(*xColorMenu); + sal_Int32 nSelected = mpAutoFilterPopup->ExecuteMenu(*xColorMenu); xColorMenu.reset(); if (nSelected == 0) return; - rControl.terminateAllPopupMenus(); + mpAutoFilterPopup->terminateAllPopupMenus(); // Disable color filter when active color was selected if (nSelected == nActive) diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx index db6c8c6066d3..8050310b107d 100644 --- a/sc/source/ui/view/gridwin2.cxx +++ b/sc/source/ui/view/gridwin2.cxx @@ -467,32 +467,31 @@ void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScr const ScDPLabelData& rLabelData = pDPData->maLabels; - mpDPFieldPopup.disposeAndClear(); + mpDPFieldPopup.reset(); vcl::ILibreOfficeKitNotifier* pNotifier = nullptr; if (comphelper::LibreOfficeKit::isActive()) pNotifier = SfxViewShell::Current(); - mpDPFieldPopup.reset(VclPtr<ScCheckListMenuWindow>::Create(this, &mrViewData.GetDocument(), - bDimOrientNotPage, false, -1, - nullptr, pNotifier)); + weld::Window* pPopupParent = GetFrameWeld(); + mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, &mrViewData.GetDocument(), + bDimOrientNotPage, false, -1, pNotifier)); - ScCheckListMenuControl& rControl = mpDPFieldPopup->get_widget(); - rControl.setExtendedData(std::move(pDPData)); - rControl.setOKAction(new DPFieldPopupOKAction(this)); + mpDPFieldPopup->setExtendedData(std::move(pDPData)); + mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this)); { // Populate field members. size_t n = rLabelData.maMembers.size(); - rControl.setMemberSize(n); + mpDPFieldPopup->setMemberSize(n); for (size_t i = 0; i < n; ++i) { const ScDPLabelData::Member& rMem = rLabelData.maMembers[i]; OUString aName = rMem.getDisplayName(); if (aName.isEmpty()) // Use special string for an empty name. - rControl.addMember(ScResId(STR_EMPTYDATA), 0.0, rMem.mbVisible); + mpDPFieldPopup->addMember(ScResId(STR_EMPTYDATA), 0.0, rMem.mbVisible); else - rControl.addMember(rMem.getDisplayName(), 0.0, rMem.mbVisible); + mpDPFieldPopup->addMember(rMem.getDisplayName(), 0.0, rMem.mbVisible); } } @@ -513,38 +512,36 @@ void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScr // Populate the menus. ScTabViewShell* pViewShell = mrViewData.GetViewShell(); - rControl.addMenuItem( + mpDPFieldPopup->addMenuItem( ScResId(STR_MENU_SORT_ASC), new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::ASCENDING, 0, pViewShell)); - rControl.addMenuItem( + mpDPFieldPopup->addMenuItem( ScResId(STR_MENU_SORT_DESC), new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::DESCENDING, 0, pViewShell)); - ScCheckListMenuWindow* pSubMenu = rControl.addSubMenuItem(ScResId(STR_MENU_SORT_CUSTOM), !aUserSortNames.empty()); + ScListSubMenuControl* pSubMenu = mpDPFieldPopup->addSubMenuItem(ScResId(STR_MENU_SORT_CUSTOM), !aUserSortNames.empty()); if (pSubMenu) { - ScCheckListMenuControl& rSubMenu = pSubMenu->get_widget(); size_t n = aUserSortNames.size(); for (size_t i = 0; i < n; ++i) { - rSubMenu.addMenuItem(aUserSortNames[i], - new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::CUSTOM, sal_uInt16(i), pViewShell)); + pSubMenu->addMenuItem(aUserSortNames[i], + new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::CUSTOM, sal_uInt16(i), pViewShell)); } - rSubMenu.resizeToFitMenuItems(); + pSubMenu->resizeToFitMenuItems(); } } - rControl.initMembers(); + mpDPFieldPopup->initMembers(); tools::Rectangle aCellRect(rScrPos, rScrSize); - ScCheckListMenuControl::Config aConfig; aConfig.mbAllowEmptySet = false; aConfig.mbRTL = mrViewData.GetDocument().IsLayoutRTL(mrViewData.GetTabNo()); - rControl.setConfig(aConfig); + mpDPFieldPopup->setConfig(aConfig); if (IsMouseCaptured()) ReleaseMouse(); - rControl.launch(aCellRect); + mpDPFieldPopup->launch(pPopupParent, aCellRect); } void ScGridWindow::UpdateDPFromFieldPopupMenu() @@ -554,9 +551,7 @@ void ScGridWindow::UpdateDPFromFieldPopupMenu() if (!mpDPFieldPopup) return; - ScCheckListMenuControl& rControl = mpDPFieldPopup->get_widget(); - - DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(rControl.getExtendedData()); + DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData()); if (!pDPData) return; @@ -577,7 +572,7 @@ void ScGridWindow::UpdateDPFromFieldPopupMenu() // The raw result may contain a mixture of layout names and original names. ScCheckListMenuControl::ResultType aRawResult; - rControl.getResult(aRawResult); + mpDPFieldPopup->getResult(aRawResult); std::unordered_map<OUString, bool> aResult; for (const auto& rItem : aRawResult) diff --git a/sc/uiconfig/scalc/ui/filterdropdown.ui b/sc/uiconfig/scalc/ui/filterdropdown.ui index 17bca296d8ef..a6f025acfeaa 100644 --- a/sc/uiconfig/scalc/ui/filterdropdown.ui +++ b/sc/uiconfig/scalc/ui/filterdropdown.ui @@ -50,14 +50,14 @@ <column type="gboolean"/> </columns> </object> - <object class="GtkBox" id="FilterDropDown"> - <property name="visible">True</property> + <object class="GtkPopover" id="FilterDropDown"> <property name="can-focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="orientation">vertical</property> + <property name="no-show-all">True</property> + <property name="border-width">4</property> + <property name="position">bottom</property> + <property name="constrain-to">none</property> <child> - <object class="GtkBox"> + <object class="GtkBox" id="container"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="hexpand">True</property> @@ -66,15 +66,15 @@ <property name="spacing">6</property> <child> <object class="GtkScrolledWindow"> - <property name="visible">True</property> <property name="can-focus">True</property> + <property name="no-show-all">True</property> <property name="hscrollbar-policy">never</property> <property name="vscrollbar-policy">never</property> <property name="shadow-type">in</property> <child> <object class="GtkTreeView" id="menu"> - <property name="visible">True</property> <property name="can-focus">True</property> + <property name="no-show-all">True</property> <property name="model">liststore1</property> <property name="headers-visible">False</property> <property name="headers-clickable">False</property> @@ -115,31 +115,20 @@ </packing> </child> <child> - <object class="GtkEntry" id="search_edit"> - <property name="can-focus">True</property> - <property name="no-show-all">True</property> - <property name="tooltip-text" translatable="yes" context="filterdropdown|STR_EDIT_SEARCH_ITEMS">Search items...</property> - <property name="activates-default">True</property> - <property name="truncate-multiline">True</property> - <property name="placeholder-text" translatable="yes" context="filterdropdown|STR_EDIT_SEARCH_ITEMS">Search items...</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkBox" id="box"> + <object class="GtkBox" id="nonmenu"> + <property name="visible">True</property> <property name="can-focus">False</property> - <property name="no-show-all">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkSeparator"> - <property name="visible">True</property> - <property name="can-focus">False</property> + <object class="GtkEntry" id="search_edit"> + <property name="can-focus">True</property> + <property name="no-show-all">True</property> + <property name="activates-default">True</property> + <property name="truncate-multiline">True</property> + <property name="placeholder-text" translatable="yes" context="filterdropdown|STR_EDIT_SEARCH_ITEMS">Search items...</property> </object> <packing> <property name="expand">False</property> @@ -148,20 +137,16 @@ </packing> </child> <child> - <object class="GtkBox"> - <property name="visible">True</property> + <object class="GtkBox" id="box"> <property name="can-focus">False</property> - <property name="border-width">3</property> - <property name="spacing">6</property> + <property name="no-show-all">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> <child> - <object class="GtkCheckButton" id="toggle_all"> - <property name="label" translatable="yes" context="filterdropdown|STR_BTN_TOGGLE_ALL">All</property> + <object class="GtkSeparator"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="hexpand">True</property> - <property name="use-underline">True</property> - <property name="draw-indicator">True</property> + <property name="can-focus">False</property> </object> <packing> <property name="expand">False</property> @@ -170,13 +155,57 @@ </packing> </child> <child> - <object class="GtkButton" id="select_current"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">True</property> - <property name="tooltip-text" translatable="yes" context="filterdropdown|STR_BTN_SELECT_CURRENT">Show only the current item.</property> - <property name="image">image1</property> - <property name="always-show-image">True</property> + <property name="can-focus">False</property> + <property name="border-width">3</property> + <property name="spacing">6</property> + <child> + <object class="GtkCheckButton" id="toggle_all"> + <property name="label" translatable="yes" context="filterdropdown|STR_BTN_TOGGLE_ALL">All</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="select_current"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="filterdropdown|STR_BTN_SELECT_CURRENT">Show only the current item.</property> + <property name="image">image1</property> + <property name="always-show-image">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="unselect_current"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="filterdropdown|STR_BTN_UNSELECT_CURRENT">Hide only the current item.</property> + <property name="image">image2</property> + <property name="always-show-image">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> @@ -185,193 +214,173 @@ </packing> </child> <child> - <object class="GtkButton" id="unselect_current"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">True</property> - <property name="tooltip-text" translatable="yes" context="filterdropdown|STR_BTN_UNSELECT_CURRENT">Hide only the current item.</property> - <property name="image">image2</property> - <property name="always-show-image">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <child> - <object class="GtkScrolledWindow"> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="shadow-type">in</property> <child> - <object class="GtkTreeView" id="check_list_box"> + <object class="GtkScrolledWindow"> <property name="can-focus">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="model">liststore2</property> - <property name="headers-visible">False</property> - <property name="headers-clickable">False</property> - <property name="search-column">1</property> - <property name="show-expanders">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> - </child> + <property name="shadow-type">in</property> <child> - <object class="GtkTreeViewColumn" id="treeviewcolumn4"> - <property name="resizable">True</property> - <property name="spacing">6</property> - <property name="alignment">0.5</property> - <child> - <object class="GtkCellRendererToggle" id="cellrenderer5"/> - <attributes> - <attribute name="visible">3</attribute> - <attribute name="active">0</attribute> - </attributes> + <object class="GtkTreeView" id="check_list_box"> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore2</property> + <property name="headers-visible">False</property> + <property name="headers-clickable">False</property> + <property name="search-column">1</property> + <property name="show-expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> </child> <child> - <object class="GtkCellRendererText" id="cellrenderer4"/> - <attributes> - <attribute name="text">1</attribute> - </attributes> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererToggle" id="cellrenderer5"/> + <attributes> + <attribute name="visible">3</attribute> + <attribute name="active">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="cellrenderer4"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> </child> </object> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkScrolledWindow"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="shadow-type">in</property> <child> - <object class="GtkTreeView" id="check_tree_box"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="model">treestore2</property> - <property name="headers-visible">False</property> - <property name="headers-clickable">False</property> - <property name="search-column">1</property> - <property name="enable-tree-lines">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> - </child> + <property name="shadow-type">in</property> <child> - <object class="GtkTreeViewColumn" id="treeviewcolumn2"> - <property name="resizable">True</property> - <property name="spacing">6</property> - <property name="alignment">0.5</property> - <child> - <object class="GtkCellRendererToggle" id="cellrenderer1"/> - <attributes> - <attribute name="visible">3</attribute> - <attribute name="active">0</attribute> - </attributes> + <object class="GtkTreeView" id="check_tree_box"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">treestore2</property> + <property name="headers-visible">False</property> + <property name="headers-clickable">False</property> + <property name="search-column">1</property> + <property name="enable-tree-lines">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> </child> <child> - <object class="GtkCellRendererText" id="cellrenderer2"/> - <attributes> - <attribute name="text">1</attribute> - </attributes> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererToggle" id="cellrenderer1"/> + <attributes> + <attribute name="visible">3</attribute> + <attribute name="active">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> </child> </object> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkButtonBox" id="buttonbox"> - <property name="can-focus">False</property> - <property name="no-show-all">True</property> - <property name="spacing">6</property> - <property name="layout-style">spread</property> - <child> - <object class="GtkButton" id="ok"> - <property name="label" translatable="yes" context="stock">_OK</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="can-default">True</property> - <property name="receives-default">True</property> - <property name="use-underline">True</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> - <object class="GtkButton" id="cancel"> - <property name="label" translatable="yes" context="stock">_Cancel</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">True</property> - <property name="use-underline">True</property> + <object class="GtkButtonBox" id="buttonbox"> + <property name="can-focus">False</property> + <property name="no-show-all">True</property> + <property name="spacing">6</property> + <property name="layout-style">spread</property> + <child> + <object class="GtkButton" id="ok"> + <property name="label" translatable="yes" context="stock">_OK</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="can-default">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="label" translatable="yes" context="stock">_Cancel</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> </object> <packing> - <property name="expand">True</property> + <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">3</property> + <property name="position">1</property> </packing> </child> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> </child> </object> </interface> diff --git a/sc/uiconfig/scalc/ui/filtersubdropdown.ui b/sc/uiconfig/scalc/ui/filtersubdropdown.ui new file mode 100644 index 000000000000..942cc4b9f75f --- /dev/null +++ b/sc/uiconfig/scalc/ui/filtersubdropdown.ui @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 --> +<interface domain="sc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore1"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name image1 --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkPopover" id="FilterSubDropDown"> + <property name="can-focus">False</property> + <property name="no-show-all">True</property> + <property name="position">right</property> + <property name="modal">False</property> + <property name="constrain-to">none</property> + <child> + <object class="GtkBox" id="container"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hscrollbar-policy">never</property> + <property name="vscrollbar-policy">never</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkTreeView" id="menu"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="model">liststore1</property> + <property name="headers-visible">False</property> + <property name="headers-clickable">False</property> + <property name="search-column">0</property> + <property name="hover-selection">True</property> + <property name="show-expanders">False</property> + <property name="activate-on-single-click">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn1"> + <child> + <object class="GtkCellRendererText" id="cellrenderertext1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <child> + <object class="GtkCellRendererPixbuf" id="cellrenderertext55"/> + <attributes> + <attribute name="pixbuf">1</attribute> + </attributes> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 0fc8ffd9366c..0d7ff1985619 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -9665,6 +9665,8 @@ GtkPositionType show_menu_older_gtk(GtkWidget* pMenuButton, GtkWindow* pMenu, co else x += nButtonWidth; + gtk_window_set_attached_to(pMenu, pMenuButton); + gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(pToplevel)), pMenu); gtk_window_set_transient_for(pMenu, GTK_WINDOW(pToplevel)); @@ -9783,19 +9785,19 @@ bool show_menu_newer_gtk(GtkWidget* pComboBox, GtkWindow* pMenu, const GdkRectan if (!window_move_to_rect) return false; -#if defined(GDK_WINDOWING_X11) // under wayland gdk_window_move_to_rect works great for me, but in my current // gtk 3.24 under X it leaves part of long menus outside the work area GdkDisplay *pDisplay = gtk_widget_get_display(pComboBox); if (DLSYM_GDK_IS_X11_DISPLAY(pDisplay)) return false; -#endif //place the toplevel just below its launcher button GtkWidget* pToplevel = widget_get_toplevel(pComboBox); gtk_coord x, y; gtk_widget_translate_coordinates(pComboBox, pToplevel, rAnchor.x, rAnchor.y, &x, &y); + gtk_window_set_attached_to(pMenu, pComboBox); + gtk_widget_realize(GTK_WIDGET(pMenu)); gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(pToplevel)), pMenu); gtk_window_set_transient_for(pMenu, GTK_WINDOW(pToplevel)); @@ -9903,6 +9905,8 @@ GtkPositionType MovePopoverContentsToWindow(GtkWidget* pPopover, GtkWindow* pMen GtkPositionType eRet = show_menu(pAnchor, pMenuHack, rAnchor, ePlace); + gtk_grab_add(GTK_WIDGET(pMenuHack)); + GdkSurface* pSurface = widget_get_surface(GTK_WIDGET(pMenuHack)); g_object_set_data(G_OBJECT(pSurface), "g-lo-InstancePopup", GINT_TO_POINTER(true)); @@ -9915,6 +9919,8 @@ void MoveWindowContentsToPopover(GtkWindow* pMenuHack, GtkWidget* pPopover, GtkW do_ungrab(GTK_WIDGET(pMenuHack)); + gtk_grab_remove(GTK_WIDGET(pMenuHack)); + gtk_widget_hide(GTK_WIDGET(pMenuHack)); //put contents back from where the came from GtkWidget* pChild = gtk_bin_get_child(GTK_BIN(pMenuHack)); @@ -9938,13 +9944,7 @@ void MoveWindowContentsToPopover(GtkWindow* pMenuHack, GtkWidget* pPopover, GtkW pFrame->UnblockTooltip(); if (bHadFocus) - { - GdkSurface* pParentSurface = pParent ? widget_get_surface(pParent) : nullptr; - void* pParentIsPopover = pParentSurface ? g_object_get_data(G_OBJECT(pParentSurface), "g-lo-InstancePopup") : nullptr; - if (pParentIsPopover) - do_grab(pAnchor); gtk_widget_grab_focus(pAnchor); - } } #endif @@ -22047,6 +22047,34 @@ private: return false; } + bool forward_event_if_popup_under_mouse(GdkEvent* pEvent) + { + GtkWidget* pEventWidget = gtk_get_event_widget(pEvent); + GtkWidget* pTopLevel = widget_get_toplevel(pEventWidget); + + if (pTopLevel == GTK_WIDGET(m_pMenuHack)) + return false; + + GdkSurface* pSurface = widget_get_surface(pTopLevel); + void* pMouseEnteredAnotherPopup = g_object_get_data(G_OBJECT(pSurface), "g-lo-InstancePopup"); + if (!pMouseEnteredAnotherPopup) + return false; + + return gtk_widget_event(pEventWidget, reinterpret_cast<GdkEvent*>(pEvent)); + } + + static gboolean signalButtonCrossing(GtkWidget*, GdkEvent* pEvent, gpointer widget) + { + GtkInstancePopover* pThis = static_cast<GtkInstancePopover*>(widget); + return pThis->forward_event_if_popup_under_mouse(pEvent); + } + + static gboolean signalMotion(GtkWidget*, GdkEvent* pEvent, gpointer widget) + { + GtkInstancePopover* pThis = static_cast<GtkInstancePopover*>(widget); + return pThis->forward_event_if_popup_under_mouse(pEvent); + } + static void signalGrabBroken(GtkWidget*, GdkEventGrabBroken *pEvent, gpointer widget) { GtkInstancePopover* pThis = static_cast<GtkInstancePopover*>(widget); @@ -22098,6 +22126,14 @@ public: g_signal_connect(m_pMenuHack, "grab-broken-event", G_CALLBACK(signalGrabBroken), this); g_signal_connect(m_pMenuHack, "button-press-event", G_CALLBACK(signalButtonPress), this); g_signal_connect(m_pMenuHack, "button-release-event", G_CALLBACK(signalButtonRelease), this); + // to emulate a modeless popover we forward the leave/enter/motion events to the widgets + // they would have gone to a if we were really modeless + if (!gtk_popover_get_modal(m_pPopover)) + { + g_signal_connect(m_pMenuHack, "leave-notify-event", G_CALLBACK(signalButtonCrossing), this); + g_signal_connect(m_pMenuHack, "enter-notify-event", G_CALLBACK(signalButtonCrossing), this); + g_signal_connect(m_pMenuHack, "motion-notify-event", G_CALLBACK(signalMotion), this); + } } #endif #endif |