compilerplugins/clang/constantparam.numbers.results | 4 include/vcl/dockwin.hxx | 5 sc/IwyuFilter_sc.yaml | 6 sc/Library_sc.mk | 3 sc/UIConfig_scalc.mk | 2 sc/inc/AccessibleFilterMenu.hxx | 139 - sc/inc/AccessibleFilterMenuItem.hxx | 95 sc/inc/AccessibleFilterTopWindow.hxx | 81 sc/inc/strings.hrc | 4 sc/qa/uitest/autofilter/tdf126306.py | 41 sc/source/ui/Accessibility/AccessibleFilterMenu.cxx | 331 -- sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx | 166 - sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx | 118 sc/source/ui/app/inputwin.cxx | 1 sc/source/ui/cctrl/checklistmenu.cxx | 1862 ++++----------- sc/source/ui/docshell/docsh4.cxx | 1 sc/source/ui/inc/checklistmenu.hxx | 472 +-- sc/source/ui/inc/gridwin.hxx | 2 sc/source/ui/view/gridwin.cxx | 74 sc/source/ui/view/gridwin2.cxx | 62 sc/uiconfig/scalc/ui/filterdropdown.ui | 304 ++ sc/uiconfig/scalc/ui/listmenu.ui | 9 solenv/clang-format/blacklist | 6 svtools/source/control/toolbarmenu.cxx | 2 vcl/source/window/dockmgr.cxx | 9 25 files changed, 1172 insertions(+), 2627 deletions(-)
New commits: commit a16e6122dc62f545df90b9ea4d1f4723c46336b6 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Thu May 28 15:24:29 2020 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Jun 12 20:03:54 2020 +0200 weld checklistmenu rework the "menu" to be a treeview using hover selection instead of a custom set of widgetry, and drop the newly unused custom a11y code Change-Id: Ie7d9b7875ce00843b3f262882816cebb472bf681 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95223 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/compilerplugins/clang/constantparam.numbers.results b/compilerplugins/clang/constantparam.numbers.results index dd73f620e594..49da62a78ecf 100644 --- a/compilerplugins/clang/constantparam.numbers.results +++ b/compilerplugins/clang/constantparam.numbers.results @@ -1826,10 +1826,6 @@ sax/source/tools/converter.cxx:994 enum sax::(anonymous namespace)::Result readUnsignedNumberMaxDigits(int,const class rtl::OUString &,int &,int &) int maxDigits 9 -sc/inc/AccessibleFilterMenu.hxx:41 - void ScAccessibleFilterMenu::ScAccessibleFilterMenu(const class com::sun::star::uno::Reference<class com::sun::star::accessibility::XAccessible> &,class ScMenuFloatingWindow *,const class rtl::OUString &,unsigned long) - unsigned long nMenuPos - 999 sc/inc/address.hxx:334 void ScAddress::Format(class rtl::OStringBuffer &,enum ScRefFlags,const class ScDocument *,const struct ScAddress::Details &) const enum ScRefFlags nFlags diff --git a/include/vcl/dockwin.hxx b/include/vcl/dockwin.hxx index f0f0ee5d60f5..689a2f4c60c3 100644 --- a/include/vcl/dockwin.hxx +++ b/include/vcl/dockwin.hxx @@ -83,6 +83,7 @@ private: VclPtr<FloatingWindow> mpFloatWin; VclPtr<vcl::Window> mpOldBorderWin; VclPtr<vcl::Window> mpParent; + Link<FloatingWindow*,void> maPopupModeEndHdl; Point maFloatPos; Point maDockPos; Point maMouseOff; @@ -138,6 +139,8 @@ public: void StartPopupMode( ToolBox* pParentToolBox, FloatWinPopupFlags nPopupModeFlags ); bool IsInPopupMode() const; + void SetPopupModeEndHdl( const Link<FloatingWindow*,void>& rLink ) { maPopupModeEndHdl = rLink; } + void TitleButtonClick( TitleButton nButton ); void Resizing( Size& rSize ); void Tracking( const TrackingEvent& rTEvt ); @@ -193,6 +196,8 @@ public: void StartPopupMode( ToolBox *pParentToolBox, const vcl::Window *pWin ); void StartPopupMode( ToolBox *pParentToolBox, const vcl::Window *pWin, FloatWinPopupFlags nPopupModeFlags ); + void SetPopupModeEndHdl( const vcl::Window *pWindow, const Link<FloatingWindow*,void>& rLink ); + bool IsInPopupMode( const vcl::Window *pWin ); void EndPopupMode( const vcl::Window *pWin ); diff --git a/sc/IwyuFilter_sc.yaml b/sc/IwyuFilter_sc.yaml index 03e98182ac73..ee2301087b23 100644 --- a/sc/IwyuFilter_sc.yaml +++ b/sc/IwyuFilter_sc.yaml @@ -4,12 +4,6 @@ blacklist: sc/inc/AccessibleGlobal.hxx: # base class has to be a complete type - com/sun/star/accessibility/XAccessibleStateSet.hpp - sc/inc/AccessibleFilterMenu.hxx: - # base class has to be a complete type - - com/sun/star/accessibility/XAccessibleSelection.hpp - sc/inc/AccessibleFilterMenuItem.hxx: - # base class has to be a complete type - - com/sun/star/accessibility/XAccessibleAction.hpp sc/inc/addruno.hxx: # base class has to be a complete type - com/sun/star/beans/XPropertySet.hpp diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 997b14c0add9..47b801f799c4 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -363,9 +363,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/Accessibility/AccessibleDocumentBase \ sc/source/ui/Accessibility/AccessibleDocumentPagePreview \ sc/source/ui/Accessibility/AccessibleEditObject \ - sc/source/ui/Accessibility/AccessibleFilterMenu \ - sc/source/ui/Accessibility/AccessibleFilterMenuItem \ - sc/source/ui/Accessibility/AccessibleFilterTopWindow \ sc/source/ui/Accessibility/AccessibleGlobal \ sc/source/ui/Accessibility/AccessiblePageHeader \ sc/source/ui/Accessibility/AccessiblePageHeaderArea \ diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk index 8e3de9629a7f..38b6acaf0f0d 100644 --- a/sc/UIConfig_scalc.mk +++ b/sc/UIConfig_scalc.mk @@ -127,6 +127,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/exponentialsmoothingdialog \ sc/uiconfig/scalc/ui/filldlg \ sc/uiconfig/scalc/ui/filterlist \ + sc/uiconfig/scalc/ui/filterdropdown \ sc/uiconfig/scalc/ui/footerdialog \ sc/uiconfig/scalc/ui/formatcellsdialog \ sc/uiconfig/scalc/ui/formulacalculationoptions \ @@ -149,6 +150,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/integerdialog \ sc/uiconfig/scalc/ui/leftfooterdialog \ sc/uiconfig/scalc/ui/leftheaderdialog \ + sc/uiconfig/scalc/ui/listmenu \ sc/uiconfig/scalc/ui/namerangesdialog \ sc/uiconfig/scalc/ui/notebookbar \ sc/uiconfig/scalc/ui/notebookbar_compact \ diff --git a/sc/inc/AccessibleFilterMenu.hxx b/sc/inc/AccessibleFilterMenu.hxx deleted file mode 100644 index 878c27a637c3..000000000000 --- a/sc/inc/AccessibleFilterMenu.hxx +++ /dev/null @@ -1,139 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_SC_INC_ACCESSIBLEFILTERMENU_HXX -#define INCLUDED_SC_INC_ACCESSIBLEFILTERMENU_HXX - -#include <AccessibleContextBase.hxx> -#include <cppuhelper/implbase1.hxx> - -#include <com/sun/star/accessibility/XAccessibleSelection.hpp> -#include <vcl/vclptr.hxx> - -#include <vector> - -class ScMenuFloatingWindow; - -typedef ::cppu::ImplHelper1< - css::accessibility::XAccessibleSelection > ScAccessibleFilterMenu_BASE; - -class ScAccessibleFilterMenu : - public ScAccessibleContextBase, - public ScAccessibleFilterMenu_BASE -{ -public: - explicit ScAccessibleFilterMenu( - const css::uno::Reference< css::accessibility::XAccessible>& rxParent, - ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos); - virtual ~ScAccessibleFilterMenu() override; - - virtual bool isVisible() override; - - /// XAccessibleComponent - - virtual css::uno::Reference< css::accessibility::XAccessible > - SAL_CALL getAccessibleAtPoint( const css::awt::Point& rPoint ) override; - - virtual void SAL_CALL grabFocus() override; - - virtual sal_Int32 SAL_CALL getForeground() override; - - virtual sal_Int32 SAL_CALL getBackground() override; - - /// XAccessibleContext - - virtual sal_Int32 SAL_CALL getAccessibleChildCount() override; - - virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL - getAccessibleChild(sal_Int32 nIndex) override; - - virtual css::uno::Reference< - css::accessibility::XAccessibleStateSet> SAL_CALL - getAccessibleStateSet() override; - - virtual OUString SAL_CALL getImplementationName() override; - - /// XAccessibleEventBroadcaster - virtual void SAL_CALL - addAccessibleEventListener( - const css::uno::Reference< css::accessibility::XAccessibleEventListener>& xListener) override; - - /// Remove an existing event listener. - virtual void SAL_CALL - removeAccessibleEventListener( - const css::uno::Reference< css::accessibility::XAccessibleEventListener>& xListener) override; - - /// XAccessibleSelection - - virtual void SAL_CALL selectAccessibleChild(sal_Int32 nChildIndex) override; - - virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int32 nChildIndex) override; - - virtual void SAL_CALL clearAccessibleSelection() override; - - virtual void SAL_CALL selectAllAccessibleChildren() override; - - virtual ::sal_Int32 SAL_CALL getSelectedAccessibleChildCount() override; - - virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL - getSelectedAccessibleChild(sal_Int32 nChildIndex) override; - - virtual void SAL_CALL deselectAccessibleChild(sal_Int32 nChildIndex) override; - - /// XInterface - - virtual css::uno::Any SAL_CALL queryInterface( - css::uno::Type const & rType ) override; - - virtual void SAL_CALL acquire() throw () override; - virtual void SAL_CALL release() throw () override; - - /// XTypeProvider - - virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override; - - /// non-UNO methods - - void appendMenuItem(const OUString& rName, size_t nMenuPos); - void setMenuPos(size_t nMenuPos); - -protected: - - sal_Int32 getMenuItemCount() const; - - virtual tools::Rectangle GetBoundingBoxOnScreen() const override; - - virtual tools::Rectangle GetBoundingBox() const override; - -private: - bool isSelected() const; - - void updateStates(); - -private: - ::std::vector< css::uno::Reference< css::accessibility::XAccessible > > maMenuItems; - css::uno::Reference< css::accessibility::XAccessibleStateSet > mxStateSet; - - size_t mnMenuPos; - VclPtr<ScMenuFloatingWindow> mpWindow; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/AccessibleFilterMenuItem.hxx b/sc/inc/AccessibleFilterMenuItem.hxx deleted file mode 100644 index d45b4c2890e2..000000000000 --- a/sc/inc/AccessibleFilterMenuItem.hxx +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_SC_INC_ACCESSIBLEFILTERMENUITEM_HXX -#define INCLUDED_SC_INC_ACCESSIBLEFILTERMENUITEM_HXX - -#include <AccessibleContextBase.hxx> -#include <cppuhelper/implbase1.hxx> - -#include <com/sun/star/accessibility/XAccessibleAction.hpp> -#include <vcl/vclptr.hxx> - -class ScMenuFloatingWindow; - -typedef ::cppu::ImplHelper1< - css::accessibility::XAccessibleAction > ScAccessibleFilterMenuItem_BASE; - -class ScAccessibleFilterMenuItem final : - public ScAccessibleContextBase, - public ScAccessibleFilterMenuItem_BASE -{ -public: - explicit ScAccessibleFilterMenuItem( - const css::uno::Reference< css::accessibility::XAccessible>& rxParent, - ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos); - - virtual ~ScAccessibleFilterMenuItem() override; - - /// XAccessibleContext - - virtual sal_Int32 SAL_CALL getAccessibleChildCount() override; - - virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL - getAccessibleChild(sal_Int32 nIndex) override; - - virtual css::uno::Reference< css::accessibility::XAccessibleStateSet> SAL_CALL - getAccessibleStateSet() override; - - virtual OUString SAL_CALL getImplementationName() override; - - /// XAccessibleAction - - virtual ::sal_Int32 SAL_CALL getAccessibleActionCount() override; - - virtual sal_Bool SAL_CALL doAccessibleAction(sal_Int32 nIndex) override; - - virtual OUString SAL_CALL getAccessibleActionDescription(sal_Int32 nIndex) override; - - virtual css::uno::Reference< css::accessibility::XAccessibleKeyBinding > SAL_CALL - getAccessibleActionKeyBinding(sal_Int32 nIndex) override; - - /// XInterface - - virtual css::uno::Any SAL_CALL queryInterface( - css::uno::Type const & rType ) override; - - virtual void SAL_CALL acquire() throw () override; - virtual void SAL_CALL release() throw () override; - - /// Non-UNO Methods - -private: - - virtual tools::Rectangle GetBoundingBoxOnScreen() const override; - - virtual tools::Rectangle GetBoundingBox() const override; - - bool isSelected() const; - void updateStateSet(); - - css::uno::Reference< css::accessibility::XAccessibleStateSet > mxStateSet; - - VclPtr<ScMenuFloatingWindow> mpWindow; - size_t mnMenuPos; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/AccessibleFilterTopWindow.hxx b/sc/inc/AccessibleFilterTopWindow.hxx deleted file mode 100644 index 90dd9bbbfd30..000000000000 --- a/sc/inc/AccessibleFilterTopWindow.hxx +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_SC_INC_ACCESSIBLEFILTERTOPWINDOW_HXX -#define INCLUDED_SC_INC_ACCESSIBLEFILTERTOPWINDOW_HXX - -#include "AccessibleFilterMenu.hxx" - -class ScCheckListMenuWindow; - -class ScAccessibleFilterTopWindow final : public ScAccessibleFilterMenu -{ -public: - ScAccessibleFilterTopWindow( - const css::uno::Reference< css::accessibility::XAccessible>& rxParent, - ScCheckListMenuWindow* pWin, - const OUString& rName); - virtual ~ScAccessibleFilterTopWindow() override; - - // XAccessibleContext - - virtual sal_Int32 SAL_CALL getAccessibleChildCount() override; - - virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL - getAccessibleChild(sal_Int32 nIndex) override; - - virtual OUString SAL_CALL getImplementationName() override; - - // Non-UNO Methods - - enum ChildControlType { - EDIT_SEARCH_BOX, LISTBOX, TOGGLE_ALL, SINGLE_ON_BTN, SINGLE_OFF_BTN, OK_BTN, CANCEL_BTN - }; - void setAccessibleChild( - const css::uno::Reference< css::accessibility::XAccessible >& rAccessible, - ChildControlType eType); - -private: - /** Edit search box for searching field members */ - css::uno::Reference< css::accessibility::XAccessible > - mxAccEditSearchBox; - /** check list box for field member visibility */ - css::uno::Reference< css::accessibility::XAccessible > - mxAccListBox; - - /** check box for toggling all field member's visibility. */ - css::uno::Reference< css::accessibility::XAccessible > - mxAccToggleAll; - - css::uno::Reference< css::accessibility::XAccessible > - mxAccSingleOnBtn; - - css::uno::Reference< css::accessibility::XAccessible > - mxAccSingleOffBtn; - - css::uno::Reference< css::accessibility::XAccessible > - mxAccOkBtn; - - css::uno::Reference< css::accessibility::XAccessible > - mxAccCancelBtn; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc index a685c1ef9d28..6f6b0299c28a 100644 --- a/sc/inc/strings.hrc +++ b/sc/inc/strings.hrc @@ -164,10 +164,6 @@ #define STR_MENU_SORT_ASC NC_("STR_MENU_SORT_ASC", "Sort Ascending") #define STR_MENU_SORT_DESC NC_("STR_MENU_SORT_DESC", "Sort Descending") #define STR_MENU_SORT_CUSTOM NC_("STR_MENU_SORT_CUSTOM", "Custom Sort") -#define STR_BTN_TOGGLE_ALL NC_("STR_BTN_TOGGLE_ALL", "All") -#define STR_BTN_SELECT_CURRENT NC_("STR_BTN_SELECT_CURRENT", "Show only the current item.") -#define STR_BTN_UNSELECT_CURRENT NC_("STR_BTN_UNSELECT_CURRENT", "Hide only the current item.") -#define STR_EDIT_SEARCH_ITEMS NC_("STR_EDIT_SEARCH_ITEMS", "Search items...") #define SCSTR_QHELP_POSWND NC_("SCSTR_QHELP_POSWND", "Name Box") #define SCSTR_QHELP_INPUTWND NC_("SCSTR_QHELP_INPUTWND", "Input line") diff --git a/sc/qa/uitest/autofilter/tdf126306.py b/sc/qa/uitest/autofilter/tdf126306.py index 5446d3337049..5a1a6ab7b053 100644 --- a/sc/qa/uitest/autofilter/tdf126306.py +++ b/sc/qa/uitest/autofilter/tdf126306.py @@ -48,8 +48,9 @@ class tdf126306(UITestCase): # Sort ascending button xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SHIFT+TAB"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) + xMenu = xFloatWindow.getChild("menu") + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SPACE"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) sort_asc_values = [0, 3, 8, 9, 17, 19, 25, 25, 33, 89, 107, 204, 453, 1023] self.check_values(document, sort_asc_values) @@ -63,9 +64,9 @@ class tdf126306(UITestCase): # Sort descending button xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SHIFT+TAB"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) + xMenu = xFloatWindow.getChild("menu") + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) sort_des_values = [1023, 453, 204, 107, 89, 33, 25, 25, 19, 17, 9, 8, 3, 0] self.check_values(document, sort_des_values) @@ -79,10 +80,10 @@ class tdf126306(UITestCase): # Top 10 button xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SHIFT+TAB"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) + xMenu = xFloatWindow.getChild("menu") + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) top10_hidden_values = [True, True, True, False, True, False, True, True, False, True, True, False, True, True] @@ -99,11 +100,11 @@ class tdf126306(UITestCase): # Empty button xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SHIFT+TAB"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) + xMenu = xFloatWindow.getChild("menu") + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) empty_values = [False] * 14 #Values are the same @@ -118,12 +119,12 @@ class tdf126306(UITestCase): # Not Empty button xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"SHIFT+TAB"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) - xFloatWindow.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) + xMenu = xFloatWindow.getChild("menu") + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"})) + xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"})) #Nothing should change self.check_values(document, default_values) diff --git a/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx b/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx deleted file mode 100644 index 48149e53d69c..000000000000 --- a/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx +++ /dev/null @@ -1,331 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <AccessibleGlobal.hxx> -#include <AccessibleFilterMenu.hxx> -#include <AccessibleFilterMenuItem.hxx> - -#include <o3tl/safeint.hxx> -#include <tools/gen.hxx> -#include <checklistmenu.hxx> - -#include <com/sun/star/accessibility/AccessibleRole.hpp> -#include <com/sun/star/accessibility/AccessibleStateType.hpp> -#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> - -using namespace ::com::sun::star; -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::accessibility::AccessibleStateType; - -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::lang::IndexOutOfBoundsException; -using ::std::for_each; - -namespace { - -class AddRemoveEventListener -{ -public: - explicit AddRemoveEventListener(const Reference<XAccessibleEventListener>& rListener, bool bAdd) : - mxListener(rListener), mbAdd(bAdd) {} - - void operator() (const Reference<XAccessible>& xAccessible) const - { - if (!xAccessible.is()) - return; - - Reference<XAccessibleEventBroadcaster> xBc(xAccessible, UNO_QUERY); - if (xBc.is()) - { - if (mbAdd) - xBc->addAccessibleEventListener(mxListener); - else - xBc->removeAccessibleEventListener(mxListener); - } - } -private: - Reference<XAccessibleEventListener> mxListener; - bool mbAdd; -}; - -} - -ScAccessibleFilterMenu::ScAccessibleFilterMenu(const Reference<XAccessible>& rxParent, ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos) : - ScAccessibleContextBase(rxParent, AccessibleRole::MENU), - mnMenuPos(nMenuPos), - mpWindow(pWin) -{ - SetName(rName); -} - -ScAccessibleFilterMenu::~ScAccessibleFilterMenu() -{ -} - -// XAccessibleComponent - -Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleAtPoint( const css::awt::Point& /*rPoint*/ ) -{ - return this; -} - -bool ScAccessibleFilterMenu::isVisible() -{ - return mpWindow->IsVisible(); -} - -void ScAccessibleFilterMenu::grabFocus() -{ -} - -sal_Int32 ScAccessibleFilterMenu::getForeground() -{ - return 0; -} - -sal_Int32 ScAccessibleFilterMenu::getBackground() -{ - return 0; -} - -// XAccessibleContext - -sal_Int32 ScAccessibleFilterMenu::getAccessibleChildCount() -{ - return getMenuItemCount(); -} - -Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleChild(sal_Int32 nIndex) -{ - if (maMenuItems.size() <= o3tl::make_unsigned(nIndex)) - throw IndexOutOfBoundsException(); - - return maMenuItems[nIndex]; -} - -Reference<XAccessibleStateSet> ScAccessibleFilterMenu::getAccessibleStateSet() -{ - updateStates(); - return mxStateSet; -} - -OUString ScAccessibleFilterMenu::getImplementationName() -{ - return "ScAccessibleFilterMenu"; -} - -// XAccessibleEventBroadcaster - -void ScAccessibleFilterMenu::addAccessibleEventListener( - const css::uno::Reference<css::accessibility::XAccessibleEventListener>& xListener) -{ - ScAccessibleContextBase::addAccessibleEventListener(xListener); - for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, true)); -} - -void ScAccessibleFilterMenu::removeAccessibleEventListener( - const css::uno::Reference<css::accessibility::XAccessibleEventListener>& xListener) -{ - ScAccessibleContextBase::removeAccessibleEventListener(xListener); - for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, false)); -} - -// XAccessibleSelection - -void ScAccessibleFilterMenu::selectAccessibleChild(sal_Int32 nChildIndex) -{ - if (o3tl::make_unsigned(nChildIndex) >= maMenuItems.size()) - throw IndexOutOfBoundsException(); - - mpWindow->setSelectedMenuItem(nChildIndex, false, true); -} - -sal_Bool ScAccessibleFilterMenu::isAccessibleChildSelected(sal_Int32 nChildIndex) -{ - if (o3tl::make_unsigned(nChildIndex) >= maMenuItems.size()) - throw IndexOutOfBoundsException(); - - return mpWindow->isMenuItemSelected(static_cast<size_t>(nChildIndex)); -} - -void ScAccessibleFilterMenu::clearAccessibleSelection() -{ - mpWindow->clearSelectedMenuItem(); -} - -void ScAccessibleFilterMenu::selectAllAccessibleChildren() -{ - // not supported - this is a menu, you can't select all menu items. -} - -sal_Int32 ScAccessibleFilterMenu::getSelectedAccessibleChildCount() -{ - // Since this is a menu, either one menu item is selected, or none at all. - return mpWindow->getSelectedMenuItem() == ScMenuFloatingWindow::MENU_NOT_SELECTED ? 0 : 1; -} - -Reference<XAccessible> ScAccessibleFilterMenu::getSelectedAccessibleChild(sal_Int32 nChildIndex) -{ - if (o3tl::make_unsigned(nChildIndex) >= maMenuItems.size()) - throw IndexOutOfBoundsException(); - - return maMenuItems[nChildIndex]; -} - -void ScAccessibleFilterMenu::deselectAccessibleChild(sal_Int32 nChildIndex) -{ - if (o3tl::make_unsigned(nChildIndex) >= maMenuItems.size()) - throw IndexOutOfBoundsException(); - - mpWindow->selectMenuItem(nChildIndex, false, false); -} - -// XInterface - -uno::Any SAL_CALL ScAccessibleFilterMenu::queryInterface( uno::Type const & rType ) -{ - Any any = ScAccessibleContextBase::queryInterface(rType); - if (any.hasValue()) - return any; - - return ScAccessibleFilterMenu_BASE::queryInterface(rType); -} - -void SAL_CALL ScAccessibleFilterMenu::acquire() throw () -{ - ScAccessibleContextBase::acquire(); -} - -void SAL_CALL ScAccessibleFilterMenu::release() throw () -{ - ScAccessibleContextBase::release(); -} - -// XTypeProvider - -Sequence<sal_Int8> ScAccessibleFilterMenu::getImplementationId() -{ - return css::uno::Sequence<sal_Int8>(); -} - -tools::Rectangle ScAccessibleFilterMenu::GetBoundingBoxOnScreen() const -{ - if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED) - return tools::Rectangle(); - - // Menu object's bounding box is the bounding box of the menu item that - // launches the menu, which belongs to the parent window. - ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow(); - if (!pParentWin) - return tools::Rectangle(); - - if (!pParentWin->IsVisible()) - return tools::Rectangle(); - - Point aPos = pParentWin->OutputToAbsoluteScreenPixel(Point(0,0)); - Point aMenuPos; - Size aMenuSize; - pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); - tools::Rectangle aRect(aPos + aMenuPos, aMenuSize); - return aRect; -} - -tools::Rectangle ScAccessibleFilterMenu::GetBoundingBox() const -{ - if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED) - return tools::Rectangle(); - - // Menu object's bounding box is the bounding box of the menu item that - // launches the menu, which belongs to the parent window. - ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow(); - if (!pParentWin) - return tools::Rectangle(); - - if (!pParentWin->IsVisible()) - return tools::Rectangle(); - - Point aMenuPos; - Size aMenuSize; - pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); - tools::Rectangle aRect(aMenuPos, aMenuSize); - return aRect; -} - -void ScAccessibleFilterMenu::appendMenuItem(const OUString& rName, size_t nMenuPos) -{ - // Check whether this menu item is a sub menu or a regular menu item. - ScMenuFloatingWindow* pSubMenu = mpWindow->getSubMenuWindow(nMenuPos); - Reference<XAccessible> xAccessible; - if (pSubMenu) - { - xAccessible = pSubMenu->CreateAccessible(); - ScAccessibleFilterMenu* p = - static_cast<ScAccessibleFilterMenu*>(xAccessible.get()); - p->setMenuPos(nMenuPos); - } - else - { - xAccessible.set(new ScAccessibleFilterMenuItem(this, mpWindow, rName, nMenuPos)); - } - maMenuItems.push_back(xAccessible); -} - -void ScAccessibleFilterMenu::setMenuPos(size_t nMenuPos) -{ - mnMenuPos = nMenuPos; -} - -sal_Int32 ScAccessibleFilterMenu::getMenuItemCount() const -{ - return maMenuItems.size(); -} - -bool ScAccessibleFilterMenu::isSelected() const -{ - // Check to see if any of the child menu items is selected. - return mpWindow->isMenuItemSelected(mnMenuPos); -} - -void ScAccessibleFilterMenu::updateStates() -{ - if (!mxStateSet.is()) - mxStateSet.set(new ScAccessibleStateSet); - - ScAccessibleStateSet* p = static_cast<ScAccessibleStateSet*>( - mxStateSet.get()); - - p->clear(); - - p->insert(ENABLED); - p->insert(FOCUSABLE); - p->insert(SELECTABLE); - p->insert(SENSITIVE); - p->insert(OPAQUE); - - if (isSelected()) - p->insert(FOCUSED); - - if (isSelected()) - p->insert(SELECTED); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx b/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx deleted file mode 100644 index 71b63fb76a70..000000000000 --- a/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <AccessibleGlobal.hxx> -#include <AccessibleFilterMenuItem.hxx> -#include <checklistmenu.hxx> - -#include <com/sun/star/accessibility/AccessibleRole.hpp> -#include <com/sun/star/accessibility/AccessibleStateType.hpp> -#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> - -using namespace ::com::sun::star; -using namespace ::com::sun::star::accessibility; -using namespace ::com::sun::star::accessibility::AccessibleStateType; - -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::lang::IndexOutOfBoundsException; - -ScAccessibleFilterMenuItem::ScAccessibleFilterMenuItem( - const Reference<XAccessible>& rxParent, ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos) : - ScAccessibleContextBase(rxParent, AccessibleRole::MENU_ITEM), - mpWindow(pWin), - mnMenuPos(nMenuPos) -{ - SetName(rName); -} - -ScAccessibleFilterMenuItem::~ScAccessibleFilterMenuItem() -{ -} - -sal_Int32 ScAccessibleFilterMenuItem::getAccessibleChildCount() -{ - return 0; -} - -Reference<XAccessible> ScAccessibleFilterMenuItem::getAccessibleChild(sal_Int32 /*nIndex*/) -{ - throw IndexOutOfBoundsException(); -} - -Reference<XAccessibleStateSet> ScAccessibleFilterMenuItem::getAccessibleStateSet() -{ - updateStateSet(); - return mxStateSet; -} - -OUString ScAccessibleFilterMenuItem::getImplementationName() -{ - return "ScAccessibleFilterMenuItem"; -} - -// XAccessibleAction - -sal_Int32 ScAccessibleFilterMenuItem::getAccessibleActionCount() -{ - return 1; -} - -sal_Bool ScAccessibleFilterMenuItem::doAccessibleAction(sal_Int32 /*nIndex*/) -{ - mpWindow->executeMenuItem(mnMenuPos); - return true; -} - -OUString ScAccessibleFilterMenuItem::getAccessibleActionDescription(sal_Int32 /*nIndex*/) -{ - return "click"; -} - -Reference<XAccessibleKeyBinding> ScAccessibleFilterMenuItem::getAccessibleActionKeyBinding( - sal_Int32 /*nIndex*/) -{ - return Reference<XAccessibleKeyBinding>(); -} - -Any SAL_CALL ScAccessibleFilterMenuItem::queryInterface( uno::Type const & rType ) -{ - Any any = ScAccessibleContextBase::queryInterface(rType); - if (any.hasValue()) - return any; - - return ScAccessibleFilterMenuItem_BASE::queryInterface(rType); -} - -void SAL_CALL ScAccessibleFilterMenuItem::acquire() throw () -{ - ScAccessibleContextBase::acquire(); -} - -void SAL_CALL ScAccessibleFilterMenuItem::release() throw () -{ - ScAccessibleContextBase::release(); -} - -bool ScAccessibleFilterMenuItem::isSelected() const -{ - return mpWindow->isMenuItemSelected(mnMenuPos); -} - -tools::Rectangle ScAccessibleFilterMenuItem::GetBoundingBoxOnScreen() const -{ - if (!mpWindow->IsVisible()) - return tools::Rectangle(); - - Point aPos = mpWindow->OutputToAbsoluteScreenPixel(Point(0,0)); - Point aMenuPos; - Size aMenuSize; - mpWindow->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); - tools::Rectangle aRect(aPos + aMenuPos, aMenuSize); - return aRect; -} - -tools::Rectangle ScAccessibleFilterMenuItem::GetBoundingBox() const -{ - if (!mpWindow->IsVisible()) - return tools::Rectangle(); - - Point aMenuPos; - Size aMenuSize; - mpWindow->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize); - tools::Rectangle aRect(aMenuPos, aMenuSize); - return aRect; -} - -void ScAccessibleFilterMenuItem::updateStateSet() -{ - if (!mxStateSet.is()) - mxStateSet.set(new ScAccessibleStateSet); - - ScAccessibleStateSet* p = static_cast<ScAccessibleStateSet*>( - mxStateSet.get()); - - p->clear(); - - p->insert(ENABLED); - p->insert(FOCUSABLE); - p->insert(SELECTABLE); - p->insert(SENSITIVE); - p->insert(OPAQUE); - - if (isSelected()) - p->insert(FOCUSED); - - if (isSelected()) - p->insert(SELECTED); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx b/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx deleted file mode 100644 index da8cefdb04c2..000000000000 --- a/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <AccessibleFilterTopWindow.hxx> -#include <AccessibleFilterMenu.hxx> -#include <checklistmenu.hxx> - -#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> - -using namespace ::com::sun::star; -using namespace ::com::sun::star::accessibility; -using ::com::sun::star::lang::IndexOutOfBoundsException; -using ::com::sun::star::uno::Reference; - -ScAccessibleFilterTopWindow::ScAccessibleFilterTopWindow( - const Reference<XAccessible>& rxParent, ScCheckListMenuWindow* pWin, const OUString& rName) : - ScAccessibleFilterMenu(rxParent, pWin, rName, ScMenuFloatingWindow::MENU_NOT_SELECTED) -{ - SetName(rName); -} - -ScAccessibleFilterTopWindow::~ScAccessibleFilterTopWindow() -{ -} - -// XAccessibleContext - -sal_Int32 ScAccessibleFilterTopWindow::getAccessibleChildCount() -{ - sal_Int32 nMenuCount = getMenuItemCount(); - return nMenuCount + 6; -} - -Reference<XAccessible> ScAccessibleFilterTopWindow::getAccessibleChild( - sal_Int32 nIndex) -{ - if (nIndex >= getAccessibleChildCount()) - throw IndexOutOfBoundsException(); - - sal_Int32 nMenuCount = getMenuItemCount(); - if (nIndex < nMenuCount) - return ScAccessibleFilterMenu::getAccessibleChild(nIndex); - - nIndex -= nMenuCount; - switch (nIndex) - { - case 0: - return mxAccEditSearchBox; - case 1: - return mxAccListBox; - case 2: - return mxAccToggleAll; - case 3: - return mxAccSingleOnBtn; - case 4: - return mxAccSingleOffBtn; - case 5: - return mxAccOkBtn; - case 6: - return mxAccCancelBtn; - default: - ; - } - - return Reference<XAccessible>(); -} - -OUString ScAccessibleFilterTopWindow::getImplementationName() -{ - return "ScAccessibleFilterTopWindow"; -} - -void ScAccessibleFilterTopWindow::setAccessibleChild( - const Reference<XAccessible>& rAccessible, ChildControlType eType) -{ - switch (eType) - { - case EDIT_SEARCH_BOX: - mxAccEditSearchBox = rAccessible; - break; - case LISTBOX: - mxAccListBox = rAccessible; - break; - case TOGGLE_ALL: - mxAccToggleAll = rAccessible; - break; - case SINGLE_ON_BTN: - mxAccSingleOnBtn = rAccessible; - break; - case SINGLE_OFF_BTN: - mxAccSingleOffBtn = rAccessible; - break; - case OK_BTN: - mxAccOkBtn = rAccessible; - break; - case CANCEL_BTN: - mxAccCancelBtn = rAccessible; - break; - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index cb2b00b51d58..58a8a9e861d1 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -39,6 +39,7 @@ #include <editeng/scriptspaceitem.hxx> #include <vcl/commandevent.hxx> #include <vcl/cursor.hxx> +#include <vcl/edit.hxx> #include <vcl/help.hxx> #include <vcl/settings.hxx> #include <svl/stritem.hxx> diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 27976641e37d..0739b81457db 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -25,438 +25,177 @@ #include <vcl/decoview.hxx> #include <vcl/event.hxx> +#include <vcl/floatwin.hxx> #include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> #include <rtl/math.hxx> #include <tools/wintypes.hxx> #include <unotools/charclass.hxx> -#include <AccessibleFilterMenu.hxx> -#include <AccessibleFilterTopWindow.hxx> - -#include <com/sun/star/accessibility/XAccessible.hpp> -#include <com/sun/star/accessibility/XAccessibleContext.hpp> -#include <vcl/svlbitm.hxx> -#include <vcl/treelistentry.hxx> #include <document.hxx> using namespace com::sun::star; using ::com::sun::star::uno::Reference; -using ::com::sun::star::accessibility::XAccessible; -using ::com::sun::star::accessibility::XAccessibleContext; -ScMenuFloatingWindow::MenuItemData::MenuItemData() : - mbEnabled(true), mbSeparator(false), - mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(nullptr)) +ScCheckListMenuControl::MenuItemData::MenuItemData() + : mbEnabled(true) + , mbSeparator(false) { } -ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) : - mpSubMenu(nullptr), - mnMenuPos(MENU_NOT_SELECTED), - mpParent(pParent) +ScCheckListMenuControl::SubMenuItemData::SubMenuItemData(ScCheckListMenuControl* pParent) + : mpSubMenu(nullptr) + , mnMenuPos(MENU_NOT_SELECTED) + , mpParent(pParent) { - maTimer.SetInvokeHandler( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) ); - maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay()); + maTimer.SetInvokeHandler(LINK(this, ScCheckListMenuControl::SubMenuItemData, TimeoutHdl)); + maTimer.SetTimeout(Application::GetSettings().GetMouseSettings().GetMenuDelay()); } -void ScMenuFloatingWindow::SubMenuItemData::reset() +void ScCheckListMenuControl::SubMenuItemData::reset() { mpSubMenu = nullptr; mnMenuPos = MENU_NOT_SELECTED; maTimer.Stop(); } -IMPL_LINK_NOARG(ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, Timer *, void) +IMPL_LINK_NOARG(ScCheckListMenuControl::SubMenuItemData, TimeoutHdl, Timer *, void) { mpParent->handleMenuTimeout(this); } -ScMenuFloatingWindow::ScMenuFloatingWindow(vcl::Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) : - PopupMenuFloatingWindow(pParent), - maOpenTimer(this), - maCloseTimer(this), - maName("ScMenuFloatingWindow"), - mnSelectedMenu(MENU_NOT_SELECTED), - mnClickedMenu(MENU_NOT_SELECTED), - mpDoc(pDoc), - mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)) -{ - SetMenuStackLevel(nMenuStackLevel); - SetText("ScMenuFloatingWindow"); - - const StyleSettings& rStyle = GetSettings().GetStyleSettings(); - - const sal_uInt16 nPopupFontHeight = 12 * GetDPIScaleFactor(); - maLabelFont = rStyle.GetLabelFont(); - maLabelFont.SetFontHeight(nPopupFontHeight); -} - -ScMenuFloatingWindow::~ScMenuFloatingWindow() -{ - disposeOnce(); -} - -void ScMenuFloatingWindow::dispose() -{ - EndPopupMode(); - for (auto& rMenuItem : maMenuItems) - rMenuItem.mpSubMenuWin.disposeAndClear(); - mpParentMenu.clear(); - PopupMenuFloatingWindow::dispose(); -} - -void ScMenuFloatingWindow::PopupModeEnd() -{ - handlePopupEnd(); -} - -void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt) -{ - const Point& rPos = rMEvt.GetPosPixel(); - size_t nSelectedMenu = getEnclosingMenuItem(rPos); - setSelectedMenuItem(nSelectedMenu, true, false); - - Window::MouseMove(rMEvt); -} - -void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt) +IMPL_LINK_NOARG(ScCheckListMenuControl, RowActivatedHdl, weld::TreeView&, bool) { - const Point& rPos = rMEvt.GetPosPixel(); - mnClickedMenu = getEnclosingMenuItem(rPos); - Window::MouseButtonDown(rMEvt); + executeMenuItem(mxMenu->get_selected_index()); + return true; } -void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt) +IMPL_LINK(ScCheckListMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, bool) { - executeMenuItem(mnClickedMenu); - mnClickedMenu = MENU_NOT_SELECTED; - Window::MouseButtonUp(rMEvt); -} - -void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt) -{ - if (maMenuItems.empty()) - { - Window::KeyInput(rKEvt); - return; - } - const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); - bool bHandled = true; - size_t nSelectedMenu = mnSelectedMenu; - size_t nLastMenuPos = maMenuItems.size() - 1; + switch (rKeyCode.GetCode()) { - case KEY_UP: + case KEY_LEFT: { - if (nLastMenuPos == 0) - // There is only one menu item. Do nothing. - break; - - size_t nOldPos = nSelectedMenu; - - if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0) - nSelectedMenu = nLastMenuPos; - else - --nSelectedMenu; - - // Loop until a non-separator menu item is found. - while (nSelectedMenu != nOldPos) - { - if (maMenuItems[nSelectedMenu].mbSeparator) - { - if (nSelectedMenu) - --nSelectedMenu; - else - nSelectedMenu = nLastMenuPos; - } - else - break; - } - - setSelectedMenuItem(nSelectedMenu, false, false); + ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); + if (pParentMenu) + pParentMenu->get_widget().endSubMenu(*this); + break; } - break; - case KEY_DOWN: - { - if (nLastMenuPos == 0) - // There is only one menu item. Do nothing. - break; - - size_t nOldPos = nSelectedMenu; - - if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos) - nSelectedMenu = 0; - else - ++nSelectedMenu; - - // Loop until a non-separator menu item is found. - while (nSelectedMenu != nOldPos) - { - if (maMenuItems[nSelectedMenu].mbSeparator) - { - if (nSelectedMenu == nLastMenuPos) - nSelectedMenu = 0; - else - ++nSelectedMenu; - } - else - break; - } - - setSelectedMenuItem(nSelectedMenu, false, false); - } - break; - case KEY_LEFT: - if (mpParentMenu) - mpParentMenu->endSubMenu(this); - break; case KEY_RIGHT: { if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED) break; const MenuItemData& rMenu = maMenuItems[mnSelectedMenu]; - if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin) + if (!rMenu.mbEnabled || !rMenu.mxSubMenuWin) break; maOpenTimer.mnMenuPos = mnSelectedMenu; - maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get(); + maOpenTimer.mpSubMenu = rMenu.mxSubMenuWin.get(); launchSubMenu(true); } - break; - case KEY_RETURN: - if (nSelectedMenu != MENU_NOT_SELECTED) - executeMenuItem(nSelectedMenu); - break; - default: - bHandled = false; } - if (!bHandled) - Window::KeyInput(rKEvt); + return false; } -void ScMenuFloatingWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +IMPL_LINK_NOARG(ScCheckListMenuControl, SelectHdl, weld::TreeView&, void) { - const StyleSettings& rStyle = GetSettings().GetStyleSettings(); - - SetFont(maLabelFont); - - Color aBackColor = rStyle.GetMenuColor(); - Color aBorderColor = rStyle.GetShadowColor(); - - tools::Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel()); - - // Window background - bool bNativeDrawn = true; - if (rRenderContext.IsNativeControlSupported(ControlType::MenuPopup, ControlPart::Entire)) + sal_uInt32 nSelectedMenu = MENU_NOT_SELECTED; + if (!mxMenu->get_selected(mxScratchIter.get())) { - rRenderContext.SetClipRegion(); - bNativeDrawn = rRenderContext.DrawNativeControl(ControlType::MenuPopup, ControlPart::Entire, aCtrlRect, - ControlState::ENABLED, ImplControlValue(), OUString()); - } - else - bNativeDrawn = false; - - if (!bNativeDrawn) - { - rRenderContext.SetFillColor(aBackColor); - rRenderContext.SetLineColor(aBorderColor); - rRenderContext.DrawRect(aCtrlRect); - } - - // Menu items - rRenderContext.SetTextColor(rStyle.GetMenuTextColor()); - drawAllMenuItems(rRenderContext); -} - -Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible() -{ - if (!mxAccessible.is()) - { - Reference<XAccessible> xAccParent = mpParentMenu ? - mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible(); - - mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999)); - ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>( - mxAccessible.get()); - - size_t nPos = 0; - for (const auto& rMenuItem : maMenuItems) + // reselect current item if its submenu is up and the launching item + // became unselected + if (mnSelectedMenu < maMenuItems.size() && + maMenuItems[mnSelectedMenu].mxSubMenuWin && + maMenuItems[mnSelectedMenu].mxSubMenuWin->IsVisible()) { - p->appendMenuItem(rMenuItem.maText, nPos); - ++nPos; + mxMenu->select(mnSelectedMenu); + return; } } + else + nSelectedMenu = mxMenu->get_iter_index_in_parent(*mxScratchIter); - return mxAccessible; + setSelectedMenuItem(nSelectedMenu, true, false); } -void ScMenuFloatingWindow::addMenuItem(const OUString& rText, Action* pAction) +void ScCheckListMenuControl::addMenuItem(const OUString& rText, Action* pAction) { MenuItemData aItem; aItem.maText = rText; aItem.mbEnabled = true; - aItem.mpAction.reset(pAction); - maMenuItems.push_back(aItem); + aItem.mxAction.reset(pAction); + maMenuItems.emplace_back(std::move(aItem)); + + mxMenu->append_text(rText); + if (mbCanHaveSubMenu) + mxMenu->set_image(mxMenu->n_children() - 1, css::uno::Reference<css::graphic::XGraphic>(), 1); } -void ScMenuFloatingWindow::addSeparator() +void ScCheckListMenuControl::addSeparator() { MenuItemData aItem; aItem.mbSeparator = true; - maMenuItems.push_back(aItem); -} + maMenuItems.emplace_back(std::move(aItem)); -ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled) -{ - MenuItemData aItem; - aItem.maText = rText; - aItem.mbEnabled = bEnabled; - aItem.mpSubMenuWin.reset(VclPtr<ScMenuFloatingWindow>::Create(this, mpDoc, GetMenuStackLevel()+1)); - aItem.mpSubMenuWin->setName(rText); - maMenuItems.push_back(aItem); - return aItem.mpSubMenuWin.get(); + mxMenu->append_separator("seperator" + OUString::number(maMenuItems.size())); } -void ScMenuFloatingWindow::handlePopupEnd() +IMPL_LINK(ScCheckListMenuControl, TreeSizeAllocHdl, const Size&, rSize, void) { - clearSelectedMenuItem(); + assert(mbCanHaveSubMenu); + std::vector<int> aWidths; + aWidths.push_back(rSize.Width() - (mxMenu->get_text_height() * 3) / 4 - 6); + mxMenu->set_column_fixed_widths(aWidths); } -Size ScMenuFloatingWindow::getMenuSize() const +void ScCheckListMenuControl::CreateDropDown() { - if (maMenuItems.empty()) - return Size(); - - auto itr = std::max_element(maMenuItems.begin(), maMenuItems.end(), - [this](const MenuItemData& a, const MenuItemData& b) { - long aTextWidth = a.mbSeparator ? 0 : GetTextWidth(a.maText); - long bTextWidth = b.mbSeparator ? 0 : GetTextWidth(b.maText); - return aTextWidth < bTextWidth; - }); - long nTextWidth = itr->mbSeparator ? 0 : GetTextWidth(itr->maText); - - size_t nLastPos = maMenuItems.size()-1; - Point aPos; - Size aSize; - getMenuItemPosSize(nLastPos, aPos, aSize); - aPos.AdjustX(nTextWidth + 15 ); - aPos.AdjustY(aSize.Height() + 5 ); - return Size(aPos.X(), aPos.Y()); + int nWidth = (mxMenu->get_text_height() * 3) / 4; + mxDropDown->SetOutputSizePixel(Size(nWidth, nWidth)); + DecorationView aDecoView(mxDropDown.get()); + aDecoView.DrawSymbol(tools::Rectangle(Point(0, 0), Size(nWidth, nWidth)), + SymbolType::SPIN_RIGHT, mxDropDown->GetTextColor(), + DrawSymbolFlags::NONE); } -void ScMenuFloatingWindow::drawMenuItem(vcl::RenderContext& rRenderContext, size_t nPos) +ScCheckListMenuWindow* ScCheckListMenuControl::addSubMenuItem(const OUString& rText, bool bEnabled) { - if (nPos >= maMenuItems.size()) - return; - - Point aPos; - Size aSize; - getMenuItemPosSize(nPos, aPos, aSize); - - DecorationView aDecoView(&rRenderContext); - long const nXOffset = 5; - long nYOffset = (aSize.Height() - maLabelFont.GetFontHeight())/2; - - // Make sure the label font is used for the menu item text. - rRenderContext.Push(PushFlags::FONT); - rRenderContext.SetFont(maLabelFont); - rRenderContext. DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, - maMenuItems[nPos].maText.getLength(), - maMenuItems[nPos].mbEnabled ? DrawTextFlags::Mnemonic : DrawTextFlags::Disable); - rRenderContext.Pop(); - - if (maMenuItems[nPos].mpSubMenuWin) - { - long nFontHeight = maLabelFont.GetFontHeight(); - Point aMarkerPos = aPos; - aMarkerPos.AdjustY(aSize.Height() / 2 - nFontHeight / 4 + 1 ); - aMarkerPos.AdjustX(aSize.Width() - nFontHeight + nFontHeight / 4 ); - Size aMarkerSize(nFontHeight / 2, nFontHeight / 2); - aDecoView.DrawSymbol(tools::Rectangle(aMarkerPos, aMarkerSize), SymbolType::SPIN_RIGHT, GetTextColor()); - } -} - -void ScMenuFloatingWindow::drawSeparator(vcl::RenderContext& rRenderContext, size_t nPos) -{ - Point aPos; - Size aSize; - getMenuItemPosSize(nPos, aPos, aSize); - tools::Rectangle aRegion(aPos,aSize); - - if (rRenderContext.IsNativeControlSupported(ControlType::MenuPopup, ControlPart::Entire)) - { - rRenderContext.Push(PushFlags::CLIPREGION); - rRenderContext.IntersectClipRegion(aRegion); - tools::Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel()); - rRenderContext.DrawNativeControl(ControlType::MenuPopup, ControlPart::Entire, aCtrlRect, - ControlState::ENABLED, ImplControlValue(), OUString()); - - rRenderContext.Pop(); - } + assert(mbCanHaveSubMenu); - bool bNativeDrawn = false; - if (rRenderContext.IsNativeControlSupported(ControlType::MenuPopup, ControlPart::Separator)) - { - ControlState nState = ControlState::NONE; - const MenuItemData& rData = maMenuItems[nPos]; - if (rData.mbEnabled) - nState |= ControlState::ENABLED; - - bNativeDrawn = rRenderContext.DrawNativeControl(ControlType::MenuPopup, ControlPart::Separator, - aRegion, nState, ImplControlValue(), OUString()); - } - - if (!bNativeDrawn) - { - const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings(); - Point aTmpPos = aPos; - aTmpPos.AdjustY(aSize.Height() / 2 ); - rRenderContext.SetLineColor(rStyle.GetShadowColor()); - rRenderContext.DrawLine(aTmpPos, Point(aSize.Width() + aTmpPos.X(), aTmpPos.Y())); - aTmpPos.AdjustY( 1 ); - rRenderContext.SetLineColor(rStyle.GetLightColor()); - rRenderContext.DrawLine(aTmpPos, Point(aSize.Width() + aTmpPos.X(), aTmpPos.Y())); - rRenderContext.SetLineColor(); - } -} + MenuItemData aItem; + aItem.maText = rText; + aItem.mbEnabled = bEnabled; + vcl::Window *pContainer = mxFrame->GetWindow(GetWindowType::FirstChild); + aItem.mxSubMenuWin.reset(VclPtr<ScCheckListMenuWindow>::Create(pContainer, mpDoc, false, -1, mxFrame->GetMenuStackLevel()+1, mxFrame.get())); + maMenuItems.emplace_back(std::move(aItem)); -void ScMenuFloatingWindow::drawAllMenuItems(vcl::RenderContext& rRenderContext) -{ - size_t n = maMenuItems.size(); + mxMenu->append_text(rText); + if (mbCanHaveSubMenu) + mxMenu->set_image(mxMenu->n_children() - 1, *mxDropDown, 1); - for (size_t i = 0; i < n; ++i) - { - if (maMenuItems[i].mbSeparator) - { - // Separator - drawSeparator(rRenderContext, i); - } - else - { - // Normal menu item - highlightMenuItem(rRenderContext, i, i == mnSelectedMenu); - } - } + return maMenuItems.back().mxSubMenuWin.get(); } -void ScMenuFloatingWindow::executeMenuItem(size_t nPos) +void ScCheckListMenuControl::executeMenuItem(size_t nPos) { if (nPos >= maMenuItems.size()) return; - if (!maMenuItems[nPos].mpAction) + if (!maMenuItems[nPos].mxAction) // no action is defined. return; terminateAllPopupMenus(); - maMenuItems[nPos].mpAction->execute(); + maMenuItems[nPos].mxAction->execute(); } -void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu) +void ScCheckListMenuControl::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu) { if (mnSelectedMenu == nPos) // nothing to do. @@ -466,34 +205,24 @@ void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, { // Dismiss any child popup menu windows. if (mnSelectedMenu < maMenuItems.size() && - maMenuItems[mnSelectedMenu].mpSubMenuWin && - maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible()) + maMenuItems[mnSelectedMenu].mxSubMenuWin && + maMenuItems[mnSelectedMenu].mxSubMenuWin->IsVisible()) { - maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible(); + maMenuItems[mnSelectedMenu].mxSubMenuWin->get_widget().ensureSubMenuNotVisible(); } - - // The popup is not visible, yet a menu item is selected. The request - // most likely comes from the accessible object. Make sure this - // window, as well as all its parent windows are visible. - if (!IsVisible() && mpParentMenu) - mpParentMenu->ensureSubMenuVisible(this); } - selectMenuItem(mnSelectedMenu, false, bSubMenuTimer); - selectMenuItem(nPos, true, bSubMenuTimer); - mnSelectedMenu = nPos; - - fireMenuHighlightedEvent(); + selectMenuItem(nPos, bSubMenuTimer); } -void ScMenuFloatingWindow::handleMenuTimeout(const SubMenuItemData* pTimer) +void ScCheckListMenuControl::handleMenuTimeout(const SubMenuItemData* pTimer) { if (pTimer == &maOpenTimer) { // Close any open submenu immediately. if (maCloseTimer.mpSubMenu) { - maCloseTimer.mpSubMenu->EndPopupMode(); + vcl::Window::GetDockingManager()->EndPopupMode(maCloseTimer.mpSubMenu); maCloseTimer.mpSubMenu = nullptr; maCloseTimer.maTimer.Stop(); } @@ -507,16 +236,15 @@ void ScMenuFloatingWindow::handleMenuTimeout(const SubMenuItemData* pTimer) { maOpenTimer.mpSubMenu = nullptr; - maCloseTimer.mpSubMenu->EndPopupMode(); + vcl::Window::GetDockingManager()->EndPopupMode(maCloseTimer.mpSubMenu); maCloseTimer.mpSubMenu = nullptr; - Invalidate(); maOpenTimer.mnMenuPos = MENU_NOT_SELECTED; } } } -void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu) +void ScCheckListMenuControl::queueLaunchSubMenu(size_t nPos, ScCheckListMenuWindow* pMenu) { if (!pMenu) return; @@ -540,7 +268,7 @@ void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* maOpenTimer.maTimer.Start(); } -void ScMenuFloatingWindow::queueCloseSubMenu() +void ScCheckListMenuControl::queueCloseSubMenu() { if (!maOpenTimer.mpSubMenu) // There is no submenu to close. @@ -554,61 +282,58 @@ void ScMenuFloatingWindow::queueCloseSubMenu() maCloseTimer.maTimer.Start(); } -void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos) +void ScCheckListMenuControl::launchSubMenu(bool bSetMenuPos) { - Point aPos; - Size aSize; - getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize); - ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu; - + ScCheckListMenuWindow* pSubMenu = maOpenTimer.mpSubMenu; if (!pSubMenu) return; - FloatWinPopupFlags nOldFlags = GetPopupModeFlags(); - SetPopupModeFlags(nOldFlags | FloatWinPopupFlags::NoAppFocusClose); - pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly. - pSubMenu->StartPopupMode( - tools::Rectangle(aPos,aSize), (FloatWinPopupFlags::Right | FloatWinPopupFlags::GrabFocus)); - pSubMenu->AddPopupModeWindow(this); + if (!mxMenu->get_selected(mxScratchIter.get())) + return; + + tools::Rectangle aRect = mxMenu->get_row_area(*mxScratchIter); + ScCheckListMenuControl& rSubMenuControl = pSubMenu->get_widget(); + rSubMenuControl.StartPopupMode(aRect, (FloatWinPopupFlags::Right | FloatWinPopupFlags::GrabFocus)); if (bSetMenuPos) - pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible. - SetPopupModeFlags(nOldFlags); + rSubMenuControl.setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible. + + mxMenu->select(*mxScratchIter); + rSubMenuControl.GrabFocus(); } -void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu) +IMPL_LINK_NOARG(ScCheckListMenuControl, PostPopdownHdl, void*, void) { - if (!pSubMenu) - return; + mnAsyncPostPopdownId = nullptr; + mxMenu->grab_focus(); +} - pSubMenu->EndPopupMode(); +void ScCheckListMenuControl::endSubMenu(ScCheckListMenuControl& rSubMenu) +{ + rSubMenu.EndPopupMode(); maOpenTimer.reset(); - size_t nMenuPos = getSubMenuPos(pSubMenu); + // 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)); + + size_t nMenuPos = getSubMenuPos(&rSubMenu); if (nMenuPos != MENU_NOT_SELECTED) { mnSelectedMenu = nMenuPos; - Invalidate(); - fireMenuHighlightedEvent(); + mxMenu->select(mnSelectedMenu); } } -void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const +void ScCheckListMenuControl::resizeToFitMenuItems() { - size_t nPos = 0; - for (const auto& rMenuItem : maMenuItems) - { - pAccMenu->appendMenuItem(rMenuItem.maText, nPos); - ++nPos; - } + mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2); } -void ScMenuFloatingWindow::resizeToFitMenuItems() +void ScCheckListMenuControl::selectMenuItem(size_t nPos, bool bSubMenuTimer) { - SetOutputSizePixel(getMenuSize()); -} + mxMenu->select(nPos == MENU_NOT_SELECTED ? -1 : nPos); + mnSelectedMenu = nPos; -void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer) -{ if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED) { queueCloseSubMenu(); @@ -621,18 +346,18 @@ void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSub return; } - Invalidate(); - if (bSelected) + if (nPos != MENU_NOT_SELECTED) { - if (mpParentMenu) - mpParentMenu->setSubMenuFocused(this); + ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); + if (pParentMenu) + pParentMenu->get_widget().setSubMenuFocused(this); if (bSubMenuTimer) { - if (maMenuItems[nPos].mpSubMenuWin) + if (maMenuItems[nPos].mxSubMenuWin) { - ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get(); + ScCheckListMenuWindow* pSubMenu = maMenuItems[nPos].mxSubMenuWin.get(); queueLaunchSubMenu(nPos, pSubMenu); } else @@ -641,209 +366,70 @@ void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSub } } -void ScMenuFloatingWindow::clearSelectedMenuItem() +void ScCheckListMenuControl::clearSelectedMenuItem() { - selectMenuItem(mnSelectedMenu, false, false); - mnSelectedMenu = MENU_NOT_SELECTED; -} - -ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const -{ - if (maMenuItems.size() <= nPos) - return nullptr; - - return maMenuItems[nPos].mpSubMenuWin.get(); + selectMenuItem(MENU_NOT_SELECTED, false); } -bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const -{ - return nPos == mnSelectedMenu; -} - -void ScMenuFloatingWindow::setName(const OUString& rName) -{ - maName = rName; -} - -void ScMenuFloatingWindow::highlightMenuItem(vcl::RenderContext& rRenderContext, size_t nPos, bool bSelected) -{ - if (nPos == MENU_NOT_SELECTED) - return; - - const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings(); - Color aBackColor = rStyle.GetMenuColor(); - rRenderContext.SetFillColor(aBackColor); - rRenderContext.SetLineColor(aBackColor); - - Point aPos; - Size aSize; - getMenuItemPosSize(nPos, aPos, aSize); - tools::Rectangle aRegion(aPos,aSize); - - if (rRenderContext.IsNativeControlSupported(ControlType::MenuPopup, ControlPart::Entire)) - { - rRenderContext.Push(PushFlags::CLIPREGION); - rRenderContext.IntersectClipRegion(tools::Rectangle(aPos, aSize)); - tools::Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel()); - rRenderContext.DrawNativeControl(ControlType::MenuPopup, ControlPart::Entire, aCtrlRect, ControlState::ENABLED, - ImplControlValue(), OUString()); - rRenderContext.Pop(); - } - - bool bNativeDrawn = true; - if (rRenderContext.IsNativeControlSupported(ControlType::MenuPopup, ControlPart::MenuItem)) - { - ControlState nState = bSelected ? ControlState::SELECTED : ControlState::NONE; - if (maMenuItems[nPos].mbEnabled) - nState |= ControlState::ENABLED; - bNativeDrawn = rRenderContext.DrawNativeControl(ControlType::MenuPopup, ControlPart::MenuItem, - aRegion, nState, ImplControlValue(), OUString()); - } - else - bNativeDrawn = false; - - if (!bNativeDrawn) - { - if (bSelected) - { - aBackColor = rStyle.GetMenuHighlightColor(); - rRenderContext.SetFillColor(aBackColor); - rRenderContext.SetLineColor(aBackColor); - } - rRenderContext.DrawRect(tools::Rectangle(aPos,aSize)); - } - - Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor(); - rRenderContext.SetTextColor(aTextColor); - drawMenuItem(rRenderContext, nPos); -} - -void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const -{ - size_t nCount = maMenuItems.size(); - if (nPos >= nCount) - return; - - const sal_uInt16 nLeftMargin = 5; - const sal_uInt16 nTopMargin = 5; - const sal_uInt16 nMenuItemHeight = static_cast<sal_uInt16>(maLabelFont.GetFontHeight()*1.8); - const sal_uInt16 nSepHeight = static_cast<sal_uInt16>(maLabelFont.GetFontHeight()*0.8); - - Point aPos1(nLeftMargin, nTopMargin); - rPos = aPos1; - for (size_t i = 0; i < nPos; ++i) - rPos.AdjustY(maMenuItems[i].mbSeparator ? nSepHeight : nMenuItemHeight ); - - Size aWndSize = GetSizePixel(); - sal_uInt16 nH = maMenuItems[nPos].mbSeparator ? nSepHeight : nMenuItemHeight; - rSize = Size(aWndSize.Width() - nLeftMargin*2, nH); -} - -size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const -{ - size_t n = maMenuItems.size(); - for (size_t i = 0; i < n; ++i) - { - Point aPos; - Size aSize; - getMenuItemPosSize(i, aPos, aSize); - tools::Rectangle aRect(aPos, aSize); - if (aRect.IsInside(rPos)) - return maMenuItems[i].mbSeparator ? MENU_NOT_SELECTED : i; - } - return MENU_NOT_SELECTED; -} - -size_t ScMenuFloatingWindow::getSubMenuPos(const ScMenuFloatingWindow* pSubMenu) +size_t ScCheckListMenuControl::getSubMenuPos(const ScCheckListMenuControl* pSubMenu) { size_t n = maMenuItems.size(); for (size_t i = 0; i < n; ++i) { - if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu) + if (!maMenuItems[i].mxSubMenuWin) + continue; + if (&maMenuItems[i].mxSubMenuWin->get_widget() == pSubMenu) return i; } return MENU_NOT_SELECTED; } -void ScMenuFloatingWindow::fireMenuHighlightedEvent() -{ - if (mnSelectedMenu == MENU_NOT_SELECTED) - return; - - if (!mxAccessible.is()) - return; - - Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext(); - if (!xAccCxt.is()) - return; - - Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu); - if (!xAccMenu.is()) - return; - - VclAccessibleEvent aEvent(VclEventId::MenuHighlight, xAccMenu); - FireVclEvent(aEvent); -} - -void ScMenuFloatingWindow::setSubMenuFocused(const ScMenuFloatingWindow* pSubMenu) +void ScCheckListMenuControl::setSubMenuFocused(const ScCheckListMenuControl* pSubMenu) { maCloseTimer.reset(); size_t nMenuPos = getSubMenuPos(pSubMenu); if (mnSelectedMenu != nMenuPos) { mnSelectedMenu = nMenuPos; - Invalidate(); + mxMenu->select(mnSelectedMenu); } } -void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu) +void ScCheckListMenuControl::EndPopupMode() { - if (mpParentMenu) - mpParentMenu->ensureSubMenuVisible(this); - - if (pSubMenu->IsVisible()) - return; + vcl::Window::GetDockingManager()->EndPopupMode(mxFrame); + mxFrame->EnableDocking(false); +} - // Find the menu position of the submenu. - size_t nMenuPos = getSubMenuPos(pSubMenu); - if (nMenuPos != MENU_NOT_SELECTED) - { - setSelectedMenuItem(nMenuPos, false, false); - - Point aPos; - Size aSize; - getMenuItemPosSize(nMenuPos, aPos, aSize); - - FloatWinPopupFlags nOldFlags = GetPopupModeFlags(); - SetPopupModeFlags(nOldFlags | FloatWinPopupFlags::NoAppFocusClose); - pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly. - pSubMenu->StartPopupMode( - tools::Rectangle(aPos,aSize), (FloatWinPopupFlags::Right | FloatWinPopupFlags::GrabFocus)); - pSubMenu->AddPopupModeWindow(this); - SetPopupModeFlags(nOldFlags); - } +void ScCheckListMenuControl::StartPopupMode(const tools::Rectangle& rRect, FloatWinPopupFlags nPopupModeFlags) +{ + mxFrame->EnableDocking(true); + DockingManager* pDockingManager = vcl::Window::GetDockingManager(); + pDockingManager->SetPopupModeEndHdl(mxFrame, LINK(this, ScCheckListMenuControl, PopupModeEndHdl)); + pDockingManager->StartPopupMode(mxFrame, rRect, nPopupModeFlags); } -void ScMenuFloatingWindow::ensureSubMenuNotVisible() +void ScCheckListMenuControl::ensureSubMenuNotVisible() { if (mnSelectedMenu < maMenuItems.size() && - maMenuItems[mnSelectedMenu].mpSubMenuWin && - maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible()) + maMenuItems[mnSelectedMenu].mxSubMenuWin && + maMenuItems[mnSelectedMenu].mxSubMenuWin->IsVisible()) { - maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible(); + maMenuItems[mnSelectedMenu].mxSubMenuWin->get_widget().ensureSubMenuNotVisible(); } EndPopupMode(); } -void ScMenuFloatingWindow::terminateAllPopupMenus() +void ScCheckListMenuControl::terminateAllPopupMenus() { EndPopupMode(); - if (mpParentMenu) - mpParentMenu->terminateAllPopupMenus(); + ScCheckListMenuWindow* pParentMenu = mxFrame->GetParentMenu(); + if (pParentMenu) + pParentMenu->get_widget().terminateAllPopupMenus(); } -ScCheckListMenuWindow::Config::Config() : +ScCheckListMenuControl::Config::Config() : mbAllowEmptySet(true), mbRTL(false) { } @@ -853,67 +439,104 @@ ScCheckListMember::ScCheckListMember() , mbDate(false) , mbLeaf(false) , meDatePartType(YEAR) - , mpParent(nullptr) { } -ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) : - ::CancelButton(pParent), mpParent(pParent) {} - -ScCheckListMenuWindow::CancelButton::~CancelButton() +ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, vcl::Window* pContainer, + ScDocument* pDoc, bool bCanHaveSubMenu, int nWidth) + : mxFrame(pParent) + , mxBuilder(Application::CreateInterimBuilder(pContainer, "modules/scalc/ui/filterdropdown.ui")) + , mxContainer(mxBuilder->weld_container("FilterDropDown")) + , mxMenu(mxBuilder->weld_tree_view("menu")) + , mxScratchIter(mxMenu->make_iterator()) + , mxEdSearch(mxBuilder->weld_entry("search_edit")) + , mxBox(mxBuilder->weld_widget("box")) + , mxChecks(mxBuilder->weld_tree_view("check_list_box")) + , mxChkToggleAll(mxBuilder->weld_check_button("toggle_all")) + , mxBtnSelectSingle(mxBuilder->weld_button("select_current")) + , mxBtnUnselectSingle(mxBuilder->weld_button("unselect_current")) + , mxButtonBox(mxBuilder->weld_box("buttonbox")) + , mxBtnOk(mxBuilder->weld_button("ok")) + , mxBtnCancel(mxBuilder->weld_button("cancel")) + , mxDropDown(mxMenu->create_virtual_device()) + , mnWidthHint(nWidth) + , maWndSize() + , mePrevToggleAllState(TRISTATE_INDET) + , mnSelectedMenu(MENU_NOT_SELECTED) + , mpDoc(pDoc) + , mnAsyncPostPopdownId(nullptr) + , mbHasDates(false) + , mbCanHaveSubMenu(bCanHaveSubMenu) + , maOpenTimer(this) + , maCloseTimer(this) { - disposeOnce(); + // sort ok/cancel into native order, if this was a dialog they would be auto-sorted, but this + // popup isn't a true dialog + mxButtonBox->sort_native_button_order(); + + mxChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + + 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 (mbCanHaveSubMenu) + { + CreateDropDown(); + mxMenu->connect_size_allocate(LINK(this, ScCheckListMenuControl, TreeSizeAllocHdl)); + } } -void ScCheckListMenuWindow::CancelButton::dispose() +IMPL_LINK_NOARG(ScCheckListMenuControl, FocusHdl, weld::Widget&, void) { - mpParent.clear(); - ::CancelButton::dispose(); + GrabFocus(); } -void ScCheckListMenuWindow::CancelButton::Click() +void ScCheckListMenuControl::GrabFocus() { - mpParent->EndPopupMode(); - ::CancelButton::Click(); + if (mxEdSearch->get_visible()) + mxEdSearch->grab_focus(); + else + { + mxMenu->set_cursor(0); + mxMenu->grab_focus(); + } } -ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, int nWidth) : - ScMenuFloatingWindow(pParent, pDoc), - maEdSearch(VclPtr<ScSearchEdit>::Create(this)), - maChecks(VclPtr<ScCheckListBox>::Create(this)), - maChkToggleAll(VclPtr<CheckBox>::Create(this, 0)), - maBtnSelectSingle(VclPtr<ImageButton>::Create(this, 0)), - maBtnUnselectSingle(VclPtr<ImageButton>::Create(this, 0)), - maBtnOk(VclPtr<OKButton>::Create(this)), - maBtnCancel(VclPtr<CancelButton>::Create(this)), - maWndSize(), - mePrevToggleAllState(TRISTATE_INDET), - maTabStops(this), - mbHasDates(false) +ScCheckListMenuControl::~ScCheckListMenuControl() { - maChkToggleAll->EnableTriState(true); - - float fScaleFactor = GetDPIScaleFactor(); - - nWidth = std::max<int>(nWidth, 200 * fScaleFactor); - maWndSize = Size(nWidth, 330 * fScaleFactor); - - maTabStops.AddTabStop( this ); - maTabStops.AddTabStop( maEdSearch.get() ); - maTabStops.AddTabStop( maChecks.get() ); - maTabStops.AddTabStop( maChkToggleAll.get() ); - maTabStops.AddTabStop( maBtnSelectSingle.get() ); - maTabStops.AddTabStop( maBtnUnselectSingle.get() ); - maTabStops.AddTabStop( maBtnOk.get() ); - maTabStops.AddTabStop( maBtnCancel.get() ); - - maEdSearch->SetTabStopsContainer( &maTabStops ); - maChecks->SetTabStopsContainer( &maTabStops ); + EndPopupMode(); + for (auto& rMenuItem : maMenuItems) + rMenuItem.mxSubMenuWin.disposeAndClear(); + if (mnAsyncPostPopdownId) + { + Application::RemoveUserEvent(mnAsyncPostPopdownId); + mnAsyncPostPopdownId = nullptr; + } +} +ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, bool bCanHaveSubMenu, + int nWidth, sal_uInt16 nMenuStackLevel, ScCheckListMenuWindow* pParentMenu) + : DockingWindow(pParent, "InterimDockParent", "svx/ui/interimdockparent.ui") + , mxParentMenu(pParentMenu) + , mxBox(get("box")) + , mxControl(new ScCheckListMenuControl(this, mxBox.get(), pDoc, bCanHaveSubMenu, nWidth)) + , mnMenuStackLevel(nMenuStackLevel) +{ + SetBackground(Application::GetSettings().GetStyleSettings().GetMenuColor()); set_id("check_list_menu"); - maChkToggleAll->set_id("toggle_all"); - maBtnSelectSingle->set_id("select_current"); - maBtnUnselectSingle->set_id("unselect_current"); +} + +bool ScCheckListMenuWindow::EventNotify(NotifyEvent& rNEvt) +{ + if (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) + { + ScCheckListMenuControl& rMenuControl = get_widget(); + rMenuControl.queueCloseSubMenu(); + rMenuControl.clearSelectedMenuItem(); + } + return DockingWindow::EventNotify(rNEvt); } ScCheckListMenuWindow::~ScCheckListMenuWindow() @@ -923,315 +546,123 @@ ScCheckListMenuWindow::~ScCheckListMenuWindow() void ScCheckListMenuWindow::dispose() { - maTabStops.clear(); - maEdSearch.disposeAndClear(); - maChecks.disposeAndClear(); - maChkToggleAll.disposeAndClear(); - maBtnSelectSingle.disposeAndClear(); - maBtnUnselectSingle.disposeAndClear(); - maBtnOk.disposeAndClear(); - maBtnCancel.disposeAndClear(); - ScMenuFloatingWindow::dispose(); -} - -void ScCheckListMenuWindow::getSectionPosSize( - Point& rPos, Size& rSize, SectionType eType) const -{ - float fScaleFactor = GetDPIScaleFactor(); - - // constant parameters. - const long nSearchBoxMargin = 10 *fScaleFactor; - const long nListBoxMargin = 5 * fScaleFactor; // horizontal distance from the side of the dialog to the listbox border. - const long nListBoxInnerPadding = 5 * fScaleFactor; - const long nTopMargin = 5 * fScaleFactor; - const long nMenuHeight = maMenuSize.getHeight(); - const long nSingleItemBtnAreaHeight = 32 * fScaleFactor; // height of the middle area below the list box where the single-action buttons are. - const long nBottomBtnAreaHeight = 50 * fScaleFactor; // height of the bottom area where the OK and Cancel buttons are. - const long nBtnWidth = 90 * fScaleFactor; - const long nLabelHeight = getLabelFont().GetFontHeight(); - const long nBtnHeight = nLabelHeight * 2; - const long nBottomMargin = 10 * fScaleFactor; - const long nMenuListMargin = 5 * fScaleFactor; - const long nSearchBoxHeight = nLabelHeight * 2; - - // parameters calculated from constants. - const long nListBoxWidth = maWndSize.Width() - nListBoxMargin*2; - const long nListBoxHeight = maWndSize.Height() - nTopMargin - nMenuHeight - - nMenuListMargin - nSearchBoxHeight - nSearchBoxMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight; - - const long nSingleBtnAreaY = nTopMargin + nMenuHeight + nMenuListMargin + nSearchBoxHeight + nSearchBoxMargin; - - switch (eType) - { - case WHOLE: - { - rPos = Point(0, 0); - rSize = maWndSize; - } - break; - case EDIT_SEARCH: - { - rPos = Point(nSearchBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin); - rSize = Size(maWndSize.Width() - 2*nSearchBoxMargin, nSearchBoxHeight); - } - break; - case SINGLE_BTN_AREA: - { - rPos = Point(nListBoxMargin, nSingleBtnAreaY); - rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight); - } - break; - case CHECK_TOGGLE_ALL: - { - long h = std::min(maChkToggleAll->CalcMinimumSize().Height(), 26L); - rPos = Point(nListBoxMargin, nSingleBtnAreaY); - rPos.AdjustX(5 ); - rPos.AdjustY((nSingleItemBtnAreaHeight - h)/2 ); - rSize = Size(70, h); - } - break; - case BTN_SINGLE_SELECT: - { - long h = 26 * fScaleFactor; - rPos = Point(nListBoxMargin, nSingleBtnAreaY); - rPos.AdjustX(nListBoxWidth - h - 10 - h - 10 ); - rPos.AdjustY((nSingleItemBtnAreaHeight - h)/2 ); - rSize = Size(h, h); - } - break; - case BTN_SINGLE_UNSELECT: - { - long h = 26 * fScaleFactor; - rPos = Point(nListBoxMargin, nSingleBtnAreaY); - rPos.AdjustX(nListBoxWidth - h - 10 ); - rPos.AdjustY((nSingleItemBtnAreaHeight - h)/2 ); - rSize = Size(h, h); - } - break; - case LISTBOX_AREA_OUTER: - { - rPos = Point(nListBoxMargin, nSingleBtnAreaY + nSingleItemBtnAreaHeight-1); - rSize = Size(nListBoxWidth, nListBoxHeight); - } - break; - case LISTBOX_AREA_INNER: - { - rPos = Point(nListBoxMargin, nSingleBtnAreaY + nSingleItemBtnAreaHeight-1); - rPos.AdjustX(nListBoxInnerPadding ); - rPos.AdjustY(nListBoxInnerPadding ); - - rSize = Size(nListBoxWidth, nListBoxHeight); - rSize.AdjustWidth( -(nListBoxInnerPadding*2) ); - rSize.AdjustHeight( -(nListBoxInnerPadding*2) ); - } - break; - case BTN_OK: - { - long x = (maWndSize.Width() - nBtnWidth*2)/3; - long y = maWndSize.Height() - nBottomMargin - nBtnHeight; - rPos = Point(x, y); - rSize = Size(nBtnWidth, nBtnHeight); - } - break; - case BTN_CANCEL: - { - long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth; - long y = maWndSize.Height() - nBottomMargin - nBtnHeight; - rPos = Point(x, y); - rSize = Size(nBtnWidth, nBtnHeight); - } - break; - default: - ; - } + mxControl.reset(); + mxBox.disposeAndClear(); + mxParentMenu.clear(); + DockingWindow::dispose(); } -void ScCheckListMenuWindow::packWindow() +void ScCheckListMenuWindow::GetFocus() { - maMenuSize = getMenuSize(); - - if (maWndSize.Width() < maMenuSize.Width()) - // Widen the window to fit the menu items. - maWndSize.setWidth( maMenuSize.Width() ); - - // Set proper window height based on the number of menu items. - if (maWndSize.Height() < maMenuSize.Height()*2.8) - maWndSize.setHeight( maMenuSize.Height()*2.8 ); - - // TODO: Make sure the window height never exceeds the height of the - // screen. Also do adjustment based on the number of check box items. - - SetOutputSizePixel(maWndSize); - - const StyleSettings& rStyle = GetSettings().GetStyleSettings(); - - Point aPos; - Size aSize; - getSectionPosSize(aPos, aSize, WHOLE); - SetOutputSizePixel(aSize); - - getSectionPosSize(aPos, aSize, BTN_OK); - maBtnOk->SetPosSizePixel(aPos, aSize); - maBtnOk->SetFont(getLabelFont()); - maBtnOk->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) ); - maBtnOk->Show(); - - getSectionPosSize(aPos, aSize, BTN_CANCEL); - maBtnCancel->SetPosSizePixel(aPos, aSize); - maBtnCancel->SetFont(getLabelFont()); - maBtnCancel->Show(); - - getSectionPosSize(aPos, aSize, EDIT_SEARCH); - maEdSearch->SetPosSizePixel(aPos, aSize); - maEdSearch->SetFont(getLabelFont()); - maEdSearch->SetControlBackground(rStyle.GetFieldColor()); - maEdSearch->SetPlaceholderText(ScResId(STR_EDIT_SEARCH_ITEMS)); - maEdSearch->SetModifyHdl( LINK(this, ScCheckListMenuWindow, EdModifyHdl) ); - maEdSearch->Show(); - - getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER); - maChecks->SetPosSizePixel(aPos, aSize); - maChecks->SetFont(getLabelFont()); - maChecks->SetCheckButtonHdl( LINK(this, ScCheckListMenuWindow, CheckHdl) ); - maChecks->Show(); - - getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL); - maChkToggleAll->SetPosSizePixel(aPos, aSize); - maChkToggleAll->SetFont(getLabelFont()); - maChkToggleAll->SetText(ScResId(STR_BTN_TOGGLE_ALL)); - maChkToggleAll->SetTextColor(rStyle.GetMenuTextColor()); - maChkToggleAll->SetControlBackground(rStyle.GetMenuColor()); - maChkToggleAll->SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) ); - maChkToggleAll->Show(); - - float fScaleFactor = GetDPIScaleFactor(); - - ; + DockingWindow::GetFocus(); + if (!mxControl) + return; + mxControl->GrabFocus(); +} - getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT); - maBtnSelectSingle->SetPosSizePixel(aPos, aSize); - maBtnSelectSingle->SetQuickHelpText(ScResId(STR_BTN_SELECT_CURRENT)); - maBtnSelectSingle->SetModeImage(Image(StockImage::Yes, RID_BMP_SELECT_CURRENT)); - maBtnSelectSingle->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) ); - maBtnSelectSingle->Show(); +void ScCheckListMenuControl::packWindow() +{ + mxBox->show(); + mxEdSearch->show(); + mxButtonBox->show(); - BitmapEx aSingleUnselectBmp(RID_BMP_UNSELECT_CURRENT); - if (fScaleFactor > 1) - aSingleUnselectBmp.Scale(fScaleFactor, fScaleFactor, BmpScaleFlag::Fast); - Image aSingleUnselect(aSingleUnselectBmp); + 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)); + mxChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); + mxChecks->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)); - getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT); - maBtnUnselectSingle->SetPosSizePixel(aPos, aSize); - maBtnUnselectSingle->SetQuickHelpText(ScResId(STR_BTN_UNSELECT_CURRENT)); - maBtnUnselectSingle->SetModeImage(aSingleUnselect); - maBtnUnselectSingle->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) ); - maBtnUnselectSingle->Show(); -} + mxChecks->set_size_request(-1, mxChecks->get_height_rows(9)); + mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2); + mnSelectedMenu = 0; + mxMenu->set_cursor(mnSelectedMenu); + mxMenu->unselect_all(); -void ScCheckListMenuWindow::setAllMemberState(bool bSet) -{ - size_t n = maMembers.size(); - std::set<SvTreeListEntry*> aParents; - for (size_t i = 0; i < n; ++i) + maWndSize = mxContainer->get_preferred_size(); + if (maWndSize.Width() < mnWidthHint) { - aParents.insert(maMembers[i].mpParent); + mxContainer->set_size_request(mnWidthHint, -1); + maWndSize.setWidth(mnWidthHint); } +} - for (const auto& pParent : aParents) - { - if (!pParent) - { - sal_uInt32 nCount = maChecks->GetEntryCount(); - for( sal_uInt32 i = 0; i < nCount; ++i) - { - SvTreeListEntry* pEntry = maChecks->GetEntry(i); - if (!pEntry) - continue; - - maChecks->CheckEntry(pEntry, bSet); - } - } - else - { - SvTreeListEntries& rEntries = pParent->GetChildEntries(); - for (const auto& rxEntry : rEntries) - { - maChecks->CheckEntry(rxEntry.get(), bSet); - } - } - } +void ScCheckListMenuControl::setAllMemberState(bool bSet) +{ + CheckAllChildren(nullptr, bSet); if (!maConfig.mbAllowEmptySet) + { // We need to have at least one member selected. - maBtnOk->Enable(maChecks->GetCheckedEntryCount() != 0); + mxBtnOk->set_sensitive(GetCheckedEntryCount() != 0); + } } -void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet) +void ScCheckListMenuControl::selectCurrentMemberOnly(bool bSet) { setAllMemberState(!bSet); - SvTreeListEntry* pEntry = maChecks->GetCurEntry(); - if (!pEntry) + std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); + if (!mxChecks->get_cursor(xEntry.get())) return; - maChecks->CheckEntry(pEntry, bSet ); - - // Make sure all checkboxes are invalidated. - Invalidate(); + mxChecks->set_toggle(*xEntry, bSet ? TRISTATE_TRUE : TRISTATE_FALSE); } -IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn, void ) +IMPL_LINK(ScCheckListMenuControl, ButtonHdl, weld::Button&, rBtn, void) { - if (pBtn == maBtnOk.get()) + if (&rBtn == mxBtnOk.get()) close(true); - else if (pBtn == maBtnSelectSingle.get()) - { - selectCurrentMemberOnly(true); - CheckHdl(maChecks.get()); - } - else if (pBtn == maBtnUnselectSingle.get()) + else if (&rBtn == mxBtnCancel.get()) + close(false); + else if (&rBtn == mxBtnSelectSingle.get() || &rBtn == mxBtnUnselectSingle.get()) { - selectCurrentMemberOnly(false); - CheckHdl(maChecks.get()); + selectCurrentMemberOnly(&rBtn == mxBtnSelectSingle.get()); + std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); + if (!mxChecks->get_cursor(xEntry.get())) + xEntry.reset(); + Check(xEntry.get()); } } -IMPL_LINK_NOARG(ScCheckListMenuWindow, TriStateHdl, Button*, void) +IMPL_LINK_NOARG(ScCheckListMenuControl, TriStateHdl, weld::ToggleButton&, void) { switch (mePrevToggleAllState) { case TRISTATE_FALSE: - maChkToggleAll->SetState(TRISTATE_TRUE); + mxChkToggleAll->set_state(TRISTATE_TRUE); setAllMemberState(true); break; case TRISTATE_TRUE: - maChkToggleAll->SetState(TRISTATE_FALSE); + mxChkToggleAll->set_state(TRISTATE_FALSE); setAllMemberState(false); break; case TRISTATE_INDET: default: - maChkToggleAll->SetState(TRISTATE_TRUE); + mxChkToggleAll->set_state(TRISTATE_TRUE); setAllMemberState(true); break; } - mePrevToggleAllState = maChkToggleAll->GetState(); - maTabStops.SetTabStop(maChkToggleAll); // Needed for when accelerator is used + mePrevToggleAllState = mxChkToggleAll->get_state(); } -IMPL_LINK_NOARG(ScCheckListMenuWindow, EdModifyHdl, Edit&, void) +IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) { - OUString aSearchText = maEdSearch->GetText(); + OUString aSearchText = mxEdSearch->get_text(); aSearchText = ScGlobal::getCharClassPtr()->lowercase( aSearchText ); bool bSearchTextEmpty = aSearchText.isEmpty(); size_t n = maMembers.size(); size_t nSelCount = 0; bool bSomeDateDeletes = false; - maChecks->SetUpdateMode(false); + mxChecks->freeze(); if (bSearchTextEmpty && !mbHasDates) { // when there are a lot of rows, it is cheaper to simply clear the tree and re-initialise - maChecks->Clear(); + mxChecks->clear(); nSelCount = initMembers(); } else @@ -1260,8 +691,8 @@ IMPL_LINK_NOARG(ScCheckListMenuWindow, EdModifyHdl, Edit&, void) if ( bSearchTextEmpty ) { - SvTreeListEntry* pLeaf = maChecks->ShowCheckEntry( aLabelDisp, maMembers[i], true, maMembers[i].mbVisible ); - updateMemberParents( pLeaf, i ); + auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[i], true, maMembers[i].mbVisible); + updateMemberParents(xLeaf.get(), i); if ( maMembers[i].mbVisible ) ++nSelCount; continue; @@ -1269,13 +700,13 @@ IMPL_LINK_NOARG(ScCheckListMenuWindow, EdModifyHdl, Edit&, void) if ( bPartialMatch ) { - SvTreeListEntry* pLeaf = maChecks->ShowCheckEntry( aLabelDisp, maMembers[i] ); - updateMemberParents( pLeaf, i ); + auto xLeaf = ShowCheckEntry(aLabelDisp, maMembers[i]); + updateMemberParents(xLeaf.get(), i); ++nSelCount; } else { - maChecks->ShowCheckEntry( aLabelDisp, maMembers[i], false, false ); + ShowCheckEntry(aLabelDisp, maMembers[i], false, false); if( bIsDate ) bSomeDateDeletes = true; } @@ -1286,115 +717,69 @@ IMPL_LINK_NOARG(ScCheckListMenuWindow, EdModifyHdl, Edit&, void) { for (size_t i = 0; i < n; ++i) { - if ( !maMembers[i].mbDate ) continue; - if ( maMembers[i].meDatePartType != ScCheckListMember::DAY ) continue; - updateMemberParents( nullptr, i ); + if (!maMembers[i].mbDate) + continue; + if (maMembers[i].meDatePartType != ScCheckListMember::DAY) + continue; + updateMemberParents(nullptr, i); } } - maChecks->SetUpdateMode(true); + mxChecks->thaw(); if ( nSelCount == n ) - maChkToggleAll->SetState( TRISTATE_TRUE ); + mxChkToggleAll->set_state( TRISTATE_TRUE ); else if ( nSelCount == 0 ) - maChkToggleAll->SetState( TRISTATE_FALSE ); + mxChkToggleAll->set_state( TRISTATE_FALSE ); else - maChkToggleAll->SetState( TRISTATE_INDET ); + mxChkToggleAll->set_state( TRISTATE_INDET ); if ( !maConfig.mbAllowEmptySet ) { const bool bEmptySet( nSelCount == 0 ); - maChecks->Enable( !bEmptySet ); - maChkToggleAll->Enable( !bEmptySet ); - maBtnSelectSingle->Enable( !bEmptySet ); - maBtnUnselectSingle->Enable( !bEmptySet ); - maBtnOk->Enable( !bEmptySet ); + mxChecks->set_sensitive(!bEmptySet); + mxChkToggleAll->set_sensitive(!bEmptySet); + mxBtnSelectSingle->set_sensitive(!bEmptySet); + mxBtnUnselectSingle->set_sensitive(!bEmptySet); + mxBtnOk->set_sensitive(!bEmptySet); } } -IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks, void ) +IMPL_LINK_NOARG(ScCheckListMenuControl, EdActivateHdl, weld::Entry&, bool) { - if (pChecks != maChecks.get()) - return; - SvTreeListEntry* pEntry = pChecks->GetHdlEntry(); - if ( pEntry ) - maChecks->CheckEntry( pEntry, ( pChecks->GetCheckButtonState( pEntry ) == SvButtonState::Checked ) ); - size_t nNumChecked = maChecks->GetCheckedEntryCount(); + if (mxBtnOk->get_sensitive()) + close(true); + return true; +} + +IMPL_LINK( ScCheckListMenuControl, CheckHdl, const weld::TreeView::iter_col&, rRowCol, void ) +{ + Check(&rRowCol.first); +} + +void ScCheckListMenuControl::Check(const weld::TreeIter* pEntry) +{ + if (pEntry) + CheckEntry(pEntry, mxChecks->get_toggle(*pEntry) == TRISTATE_TRUE); + size_t nNumChecked = GetCheckedEntryCount(); if (nNumChecked == maMembers.size()) // all members visible - maChkToggleAll->SetState(TRISTATE_TRUE); + mxChkToggleAll->set_state(TRISTATE_TRUE); else if (nNumChecked == 0) // no members visible ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits