summaryrefslogtreecommitdiff
path: root/sc/source/ui/cctrl
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@suse.com>2011-09-12 21:12:57 -0400
committerKohei Yoshida <kohei.yoshida@suse.com>2011-09-12 21:14:01 -0400
commit7a60be6e00ce3ad15f9976f607f26e52e7d06fa7 (patch)
treeaaeec748b45bfa01353f88792a4686e9d917694f /sc/source/ui/cctrl
parent0bc368babc36542cd157803fb9fefb4260f0a9e2 (diff)
Move ScCheckListMenuWindow and ScMenuFloatingWindow into own files.
Diffstat (limited to 'sc/source/ui/cctrl')
-rw-r--r--sc/source/ui/cctrl/checklistmenu.cxx1197
-rw-r--r--sc/source/ui/cctrl/checklistmenu.src (renamed from sc/source/ui/cctrl/dpcontrol.src)2
-rw-r--r--sc/source/ui/cctrl/dpcontrol.cxx1170
3 files changed, 1199 insertions, 1170 deletions
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
new file mode 100644
index 000000000000..76b75c01d5ae
--- /dev/null
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -0,0 +1,1197 @@
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2011 Kohei Yoshida <kohei.yoshida@suse.com>
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include "checklistmenu.hxx"
+#include "checklistmenu.hrc"
+#include "strload.hxx"
+
+#include <vcl/decoview.hxx>
+#include <tools/wintypes.hxx>
+
+#include "AccessibleFilterMenu.hxx"
+#include "AccessibleFilterTopWindow.hxx"
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::accessibility::XAccessible;
+using ::com::sun::star::accessibility::XAccessibleContext;
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
+using ::std::vector;
+using ::boost::unordered_map;
+using ::std::auto_ptr;
+
+ScMenuFloatingWindow::MenuItemData::MenuItemData() :
+ mbEnabled(true),
+ mpAction(static_cast<ScCheckListMenuWindow::Action*>(NULL)),
+ mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
+ mpSubMenu(NULL),
+ mnMenuPos(MENU_NOT_SELECTED),
+ mpParent(pParent)
+{
+ maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
+ maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
+}
+
+void ScMenuFloatingWindow::SubMenuItemData::reset()
+{
+ mpSubMenu = NULL;
+ mnMenuPos = MENU_NOT_SELECTED;
+ maTimer.Stop();
+}
+
+IMPL_LINK( ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, void*, EMPTYARG )
+{
+ mpParent->handleMenuTimeout(this);
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
+
+ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) :
+ PopupMenuFloatingWindow(pParent),
+ maOpenTimer(this),
+ maCloseTimer(this),
+ maName(RTL_CONSTASCII_USTRINGPARAM("ScMenuFloatingWindow")),
+ mnSelectedMenu(MENU_NOT_SELECTED),
+ mnClickedMenu(MENU_NOT_SELECTED),
+ mpDoc(pDoc),
+ mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
+ mpActiveSubMenu(NULL)
+{
+ SetMenuStackLevel(nMenuStackLevel);
+
+ // TODO: How do we get the right font to use here ?
+ const sal_uInt16 nPopupFontHeight = 12;
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ maLabelFont = rStyle.GetLabelFont();
+ maLabelFont.SetHeight(nPopupFontHeight);
+ SetFont(maLabelFont);
+
+ SetText( OUString(RTL_CONSTASCII_USTRINGPARAM("ScMenuFloatingWindow")) );
+ SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, PopupEndHdl) );
+}
+
+ScMenuFloatingWindow::~ScMenuFloatingWindow()
+{
+ EndPopupMode();
+}
+
+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)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ mnClickedMenu = getEnclosingMenuItem(rPos);
+ Window::MouseButtonDown(rMEvt);
+}
+
+void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ executeMenuItem(mnClickedMenu);
+ mnClickedMenu = MENU_NOT_SELECTED;
+ Window::MouseButtonUp(rMEvt);
+}
+
+void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
+{
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ bool bHandled = true;
+ size_t nSelectedMenu = mnSelectedMenu;
+ size_t nLastMenuPos = maMenuItems.size() - 1;
+ switch (rKeyCode.GetCode())
+ {
+ case KEY_UP:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
+ nSelectedMenu = nLastMenuPos;
+ else
+ --nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false, false);
+ break;
+ case KEY_DOWN:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
+ nSelectedMenu = 0;
+ else
+ ++nSelectedMenu;
+ 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)
+ break;
+
+ maOpenTimer.mnMenuPos = mnSelectedMenu;
+ maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
+ launchSubMenu(true);
+ }
+ break;
+ case KEY_RETURN:
+ if (nSelectedMenu != MENU_NOT_SELECTED)
+ executeMenuItem(nSelectedMenu);
+ break;
+ default:
+ bHandled = false;
+ }
+
+ if (!bHandled)
+ Window::KeyInput(rKEvt);
+}
+
+void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
+{
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ Color aBorderColor = rStyle.GetShadowColor();
+
+ Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
+
+ // Window background
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ SetClipRegion();
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ SetFillColor(aBackColor);
+ SetLineColor(aBorderColor);
+ DrawRect(aCtrlRect);
+ }
+
+ // Menu items
+ SetTextColor(rStyle.GetMenuTextColor());
+ drawAllMenuItems();
+}
+
+Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
+{
+ if (!mxAccessible.is())
+ {
+ Reference<XAccessible> xAccParent = mpParentMenu ?
+ mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
+
+ mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999, getDoc()));
+ ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
+ mxAccessible.get());
+
+ vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ size_t nPos = ::std::distance(itrBeg, itr);
+ p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
+ }
+ }
+
+ return mxAccessible;
+}
+
+void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
+{
+ MenuItemData aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpAction.reset(pAction);
+ maMenuItems.push_back(aItem);
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
+{
+ MenuItemData aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
+ aItem.mpSubMenuWin->setName(rText);
+ maMenuItems.push_back(aItem);
+ return aItem.mpSubMenuWin.get();
+}
+
+void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nPos, aPos, aSize);
+
+ DecorationView aDecoView(this);
+ long nXOffset = 5;
+ long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
+ DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
+ maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
+
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ long nFontHeight = maLabelFont.GetHeight();
+ Point aMarkerPos = aPos;
+ aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
+ aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
+ Size aMarkerSize(nFontHeight/2, nFontHeight/2);
+ aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
+ SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
+ }
+}
+
+void ScMenuFloatingWindow::drawAllMenuItems()
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ highlightMenuItem(i, i == mnSelectedMenu);
+}
+
+const Font& ScMenuFloatingWindow::getLabelFont() const
+{
+ return maLabelFont;
+}
+
+void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ if (!maMenuItems[nPos].mpAction)
+ // no action is defined.
+ return;
+
+ maMenuItems[nPos].mpAction->execute();
+ terminateAllPopupMenus();
+}
+
+void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
+{
+ if (mnSelectedMenu == nPos)
+ // nothing to do.
+ return;
+
+ if (bEnsureSubMenu)
+ {
+ // Dismiss any child popup menu windows.
+ if (mnSelectedMenu < maMenuItems.size() &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
+ {
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->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();
+}
+
+size_t ScMenuFloatingWindow::getSelectedMenuItem() const
+{
+ return mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* pTimer)
+{
+ if (pTimer == &maOpenTimer)
+ {
+ // Close any open submenu immediately.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+ maCloseTimer.maTimer.Stop();
+ }
+
+ launchSubMenu(false);
+ }
+ else if (pTimer == &maCloseTimer)
+ {
+ // end submenu.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maOpenTimer.mpSubMenu = NULL;
+
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+
+ highlightMenuItem(maOpenTimer.mnMenuPos, false);
+ maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
+ }
+ }
+}
+
+void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
+{
+ if (!pMenu)
+ return;
+
+ // Set the submenu on launch queue.
+ if (maOpenTimer.mpSubMenu)
+ {
+ if (maOpenTimer.mpSubMenu == pMenu)
+ {
+ if (pMenu == maCloseTimer.mpSubMenu)
+ maCloseTimer.reset();
+ return;
+ }
+
+ // new submenu is being requested.
+ queueCloseSubMenu();
+ }
+
+ maOpenTimer.mpSubMenu = pMenu;
+ maOpenTimer.mnMenuPos = nPos;
+ maOpenTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::queueCloseSubMenu()
+{
+ if (!maOpenTimer.mpSubMenu)
+ // There is no submenu to close.
+ return;
+
+ // Stop any submenu on queue for opening.
+ maOpenTimer.maTimer.Stop();
+
+ maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
+ maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
+ maCloseTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
+{
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize);
+ ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
+
+ if (!pSubMenu)
+ return;
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ if (bSetMenuPos)
+ pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
+ SetPopupModeFlags(nOldFlags);
+}
+
+void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
+{
+ if (!pSubMenu)
+ return;
+
+ pSubMenu->EndPopupMode();
+ maOpenTimer.reset();
+
+ size_t nMenuPos = getSubMenuPos(pSubMenu);
+ if (nMenuPos != MENU_NOT_SELECTED)
+ {
+ highlightMenuItem(nMenuPos, true);
+ mnSelectedMenu = nMenuPos;
+ fireMenuHighlightedEvent();
+ }
+}
+
+void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
+{
+ vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ size_t nPos = ::std::distance(itrBeg, itr);
+ pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
+ }
+}
+
+ScDocument* ScMenuFloatingWindow::getDoc()
+{
+ return mpDoc;
+}
+
+void ScMenuFloatingWindow::resizeToFitMenuItems()
+{
+ if (maMenuItems.empty())
+ return;
+
+ vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ long nTextWidth = 0;
+ for (; itr != itrEnd; ++itr)
+ nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
+
+ size_t nLastPos = maMenuItems.size()-1;
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nLastPos, aPos, aSize);
+ aPos.X() += nTextWidth + 15;
+ aPos.Y() += aSize.Height() + 5;
+ SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
+}
+
+void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
+{
+ if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ if (!maMenuItems[nPos].mbEnabled)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ highlightMenuItem(nPos, bSelected);
+
+ if (bSelected)
+ {
+ if (mpParentMenu)
+ mpParentMenu->setSubMenuFocused(this);
+
+ if (bSubMenuTimer)
+ {
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
+ queueLaunchSubMenu(nPos, pSubMenu);
+ }
+ else
+ queueCloseSubMenu();
+ }
+ }
+}
+
+void ScMenuFloatingWindow::clearSelectedMenuItem()
+{
+ selectMenuItem(mnSelectedMenu, false, false);
+ mnSelectedMenu = MENU_NOT_SELECTED;
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
+{
+ if (maMenuItems.size() <= nPos)
+ return NULL;
+
+ return maMenuItems[nPos].mpSubMenuWin.get();
+}
+
+bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
+{
+ return nPos == mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::setName(const OUString& rName)
+{
+ maName = rName;
+}
+
+const OUString& ScMenuFloatingWindow::getName() const
+{
+ return maName;
+}
+
+void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
+{
+ if (nPos == MENU_NOT_SELECTED)
+ return;
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nPos, aPos, aSize);
+ Rectangle aRegion(aPos,aSize);
+
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ Push(PUSH_CLIPREGION);
+ IntersectClipRegion(Rectangle(aPos, aSize));
+ Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
+ DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+
+ Pop();
+ }
+
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
+ {
+ ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
+ if (maMenuItems[nPos].mbEnabled)
+ nState |= CTRL_STATE_ENABLED;
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ if (bSelected)
+ {
+ aBackColor = rStyle.GetMenuHighlightColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+ }
+ DrawRect(Rectangle(aPos,aSize));
+ }
+
+ Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
+ SetTextColor(aTextColor);
+ drawMenuItem(nPos);
+}
+
+void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
+{
+ const sal_uInt16 nLeftMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuItemHeight = static_cast< sal_uInt16 >( maLabelFont.GetHeight()*1.8 );
+
+ Size aWndSize = GetSizePixel();
+
+ Point aPos1(nLeftMargin, nTopMargin);
+ Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
+
+ rPos = aPos1;
+ rPos.Y() += aSize1.Height()*nPos;
+ rSize = aSize1;
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::getParentMenuWindow() const
+{
+ return mpParentMenu;
+}
+
+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);
+ Rectangle aRect(aPos, aSize);
+ if (aRect.IsInside(rPos))
+ return i;
+ }
+ return MENU_NOT_SELECTED;
+}
+
+size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (maMenuItems[i].mpSubMenuWin.get() == 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(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
+ FireVclEvent(&aEvent);
+}
+
+void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
+{
+ maCloseTimer.reset();
+ size_t nMenuPos = getSubMenuPos(pSubMenu);
+ if (mnSelectedMenu != nMenuPos)
+ {
+ highlightMenuItem(nMenuPos, true);
+ mnSelectedMenu = nMenuPos;
+ }
+}
+
+void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
+{
+ if (mpParentMenu)
+ mpParentMenu->ensureSubMenuVisible(this);
+
+ if (pSubMenu->IsVisible())
+ return;
+
+ // 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);
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ SetPopupModeFlags(nOldFlags);
+ }
+}
+
+void ScMenuFloatingWindow::ensureSubMenuNotVisible()
+{
+ if (mnSelectedMenu <= maMenuItems.size() &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
+ {
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
+ }
+
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::terminateAllPopupMenus()
+{
+ EndPopupMode();
+ if (mpParentMenu)
+ mpParentMenu->terminateAllPopupMenus();
+}
+
+IMPL_LINK( ScMenuFloatingWindow, PopupEndHdl, void*, EMPTYARG )
+{
+ clearSelectedMenuItem();
+ return 0;
+}
+
+// ============================================================================
+
+ScCheckListMenuWindow::Member::Member() :
+ mbVisible(true)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) :
+ ::CancelButton(pParent), mpParent(pParent) {}
+
+void ScCheckListMenuWindow::CancelButton::Click()
+{
+ mpParent->EndPopupMode();
+ ::CancelButton::Click();
+}
+
+// ----------------------------------------------------------------------------
+
+ScCheckListMenuWindow::ScCheckListMenuWindow(Window* pParent, ScDocument* pDoc) :
+ ScMenuFloatingWindow(pParent, pDoc),
+ maChecks(this, 0),
+ maChkToggleAll(this, 0),
+ maBtnSelectSingle (this, 0),
+ maBtnUnselectSingle(this, 0),
+ maBtnOk(this),
+ maBtnCancel(this),
+ mnCurTabStop(0),
+ mpExtendedData(NULL),
+ mpOKAction(NULL),
+ maWndSize(240, 330),
+ mePrevToggleAllState(STATE_DONTKNOW)
+{
+ maTabStopCtrls.reserve(7);
+ maTabStopCtrls.push_back(this);
+ maTabStopCtrls.push_back(&maChecks);
+ maTabStopCtrls.push_back(&maChkToggleAll);
+ maTabStopCtrls.push_back(&maBtnSelectSingle);
+ maTabStopCtrls.push_back(&maBtnUnselectSingle);
+ maTabStopCtrls.push_back(&maBtnOk);
+ maTabStopCtrls.push_back(&maBtnCancel);
+
+ 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, 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(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
+ maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor());
+ maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
+ maChkToggleAll.SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) );
+ maChkToggleAll.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
+ maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
+ maBtnSelectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT).GetString());
+ maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)));
+ maBtnSelectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
+ maBtnSelectSingle.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
+ maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
+ maBtnUnselectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT).GetString());
+ maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)));
+ maBtnUnselectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
+ maBtnUnselectSingle.Show();
+}
+
+ScCheckListMenuWindow::~ScCheckListMenuWindow()
+{
+}
+
+void ScCheckListMenuWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
+{
+ // constant parameters.
+ const sal_uInt16 nListBoxMargin = 5; // horizontal distance from the side of the dialog to the listbox border.
+ const sal_uInt16 nListBoxInnerPadding = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuHeight = 60;
+ const sal_uInt16 nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
+ const sal_uInt16 nBottomBtnAreaHeight = 50; // height of the bottom area where the OK and Cancel buttons are.
+ const sal_uInt16 nBtnWidth = 90;
+ const sal_uInt16 nLabelHeight = static_cast< sal_uInt16 >( getLabelFont().GetHeight() );
+ const sal_uInt16 nBtnHeight = nLabelHeight*2;
+ const sal_uInt16 nBottomMargin = 10;
+ const sal_uInt16 nMenuListMargin = 20;
+
+ // parameters calculated from constants.
+ const sal_uInt16 nListBoxWidth = static_cast< sal_uInt16 >( maWndSize.Width() - nListBoxMargin*2 );
+ const sal_uInt16 nListBoxHeight = static_cast< sal_uInt16 >( maWndSize.Height() - nTopMargin - nMenuHeight -
+ nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight );
+
+ const sal_uInt16 nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
+
+ switch (eType)
+ {
+ case WHOLE:
+ {
+ rPos = Point(0, 0);
+ rSize = maWndSize;
+ }
+ break;
+ case LISTBOX_AREA_OUTER:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rSize = Size(nListBoxWidth, nListBoxHeight);
+ }
+ break;
+ case LISTBOX_AREA_INNER:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rPos.X() += nListBoxInnerPadding;
+ rPos.Y() += nListBoxInnerPadding;
+
+ rSize = Size(nListBoxWidth, nListBoxHeight);
+ rSize.Width() -= nListBoxInnerPadding*2;
+ rSize.Height() -= nListBoxInnerPadding*2;
+ }
+ break;
+ case SINGLE_BTN_AREA:
+ {
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
+ }
+ break;
+ case CHECK_TOGGLE_ALL:
+ {
+ long h = nLabelHeight*3/2; // check box height is heuristically 150% of the text height.
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 5;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(70, h);
+ }
+ break;
+ case BTN_SINGLE_SELECT:
+ {
+ long h = 26;
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 150;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(h, h);
+ }
+ break;
+ case BTN_SINGLE_UNSELECT:
+ {
+ long h = 26;
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 150 + h + 10;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(h, h);
+ }
+ 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:
+ ;
+ }
+}
+
+void ScCheckListMenuWindow::setAllMemberState(bool bSet)
+{
+ size_t n = maMembers.size();
+ for (size_t i = 0; i < n; ++i)
+ maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), bSet);
+}
+
+void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
+{
+ setAllMemberState(!bSet);
+ sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
+ maChecks.CheckEntryPos(nSelected, bSet);
+}
+
+void ScCheckListMenuWindow::cycleFocus(bool bReverse)
+{
+ maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
+ maTabStopCtrls[mnCurTabStop]->LoseFocus();
+ if (mnCurTabStop == 0)
+ clearSelectedMenuItem();
+
+ if (bReverse)
+ {
+ if (mnCurTabStop > 0)
+ --mnCurTabStop;
+ else
+ mnCurTabStop = maTabStopCtrls.size() - 1;
+ }
+ else
+ {
+ ++mnCurTabStop;
+ if (mnCurTabStop >= maTabStopCtrls.size())
+ mnCurTabStop = 0;
+ }
+ maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
+ maTabStopCtrls[mnCurTabStop]->GrabFocus();
+}
+
+IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn )
+{
+ if (pBtn == &maBtnOk)
+ close(true);
+ else if (pBtn == &maBtnSelectSingle)
+ {
+ selectCurrentMemberOnly(true);
+ CheckHdl(&maChecks);
+ }
+ else if (pBtn == &maBtnUnselectSingle)
+ {
+ selectCurrentMemberOnly(false);
+ CheckHdl(&maChecks);
+ }
+ return 0;
+}
+
+IMPL_LINK( ScCheckListMenuWindow, TriStateHdl, TriStateBox*, EMPTYARG )
+{
+ switch (mePrevToggleAllState)
+ {
+ case STATE_NOCHECK:
+ maChkToggleAll.SetState(STATE_CHECK);
+ setAllMemberState(true);
+ break;
+ case STATE_CHECK:
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ setAllMemberState(false);
+ break;
+ case STATE_DONTKNOW:
+ default:
+ maChkToggleAll.SetState(STATE_CHECK);
+ setAllMemberState(true);
+ break;
+ }
+
+ mePrevToggleAllState = maChkToggleAll.GetState();
+ return 0;
+}
+
+IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
+{
+ if (pChecks != &maChecks)
+ return 0;
+
+ size_t nNumChecked = maChecks.GetCheckedEntryCount();
+ if (nNumChecked == maMembers.size())
+ // all members visible
+ maChkToggleAll.SetState(STATE_CHECK);
+ else if (nNumChecked == 0)
+ // no members visible
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ else
+ maChkToggleAll.SetState(STATE_DONTKNOW);
+
+ mePrevToggleAllState = maChkToggleAll.GetState();
+ return 0;
+}
+
+void ScCheckListMenuWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ ScMenuFloatingWindow::MouseMove(rMEvt);
+
+ size_t nSelectedMenu = getSelectedMenuItem();
+ if (nSelectedMenu == MENU_NOT_SELECTED)
+ queueCloseSubMenu();
+}
+
+long ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
+{
+ switch (rNEvt.GetType())
+ {
+ case EVENT_KEYUP:
+ {
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ const KeyCode& rCode = pKeyEvent->GetKeyCode();
+ bool bShift = rCode.IsShift();
+ if (rCode.GetCode() == KEY_TAB)
+ {
+ cycleFocus(bShift);
+ return true;
+ }
+ }
+ break;
+ }
+ return ScMenuFloatingWindow::Notify(rNEvt);
+}
+
+void ScCheckListMenuWindow::Paint(const Rectangle& rRect)
+{
+ ScMenuFloatingWindow::Paint(rRect);
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aMemberBackColor = rStyle.GetFieldColor();
+ Color aBorderColor = rStyle.GetShadowColor();
+
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
+
+ // Member list box background
+ SetFillColor(aMemberBackColor);
+ SetLineColor(aBorderColor);
+ DrawRect(Rectangle(aPos,aSize));
+
+ // Single-action button box
+ getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
+ SetFillColor(rStyle.GetMenuColor());
+ DrawRect(Rectangle(aPos,aSize));
+}
+
+Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
+{
+ return maTabStopCtrls[mnCurTabStop];
+}
+
+Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
+{
+ if (!mxAccessible.is())
+ {
+ mxAccessible.set(new ScAccessibleFilterTopWindow(
+ GetAccessibleParentWindow()->GetAccessible(), this, getName(), getDoc()));
+ ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
+ fillMenuItemsToAccessible(pAccTop);
+
+ pAccTop->setAccessibleChild(
+ maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
+ pAccTop->setAccessibleChild(
+ maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
+ pAccTop->setAccessibleChild(
+ maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
+ }
+
+ return mxAccessible;
+}
+
+void ScCheckListMenuWindow::setMemberSize(size_t n)
+{
+ maMembers.reserve(n);
+}
+
+void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
+{
+ Member aMember;
+ aMember.maName = rName;
+ aMember.mbVisible = bVisible;
+ maMembers.push_back(aMember);
+}
+
+void ScCheckListMenuWindow::initMembers()
+{
+ size_t n = maMembers.size();
+ size_t nVisMemCount = 0;
+ for (size_t i = 0; i < n; ++i)
+ {
+ maChecks.InsertEntry(maMembers[i].maName);
+ maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), maMembers[i].mbVisible);
+ if (maMembers[i].mbVisible)
+ ++nVisMemCount;
+ }
+ if (nVisMemCount == n)
+ {
+ // all members visible
+ maChkToggleAll.SetState(STATE_CHECK);
+ mePrevToggleAllState = STATE_CHECK;
+ }
+ else if (nVisMemCount == 0)
+ {
+ // no members visible
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ mePrevToggleAllState = STATE_NOCHECK;
+ }
+ else
+ {
+ maChkToggleAll.SetState(STATE_DONTKNOW);
+ mePrevToggleAllState = STATE_DONTKNOW;
+ }
+}
+
+const Size& ScCheckListMenuWindow::getWindowSize() const
+{
+ return maWndSize;
+}
+
+void ScCheckListMenuWindow::getResult(boost::unordered_map<OUString, bool, OUStringHash>& rResult)
+{
+ typedef boost::unordered_map<OUString, bool, OUStringHash> ResultMap;
+ ResultMap aResult;
+ size_t n = maMembers.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ bool bState = maChecks.IsChecked(static_cast< sal_uInt16 >( i ));
+ aResult.insert(ResultMap::value_type(maMembers[i].maName, bState));
+ }
+ rResult.swap(aResult);
+}
+
+void ScCheckListMenuWindow::close(bool bOK)
+{
+ if (bOK && mpOKAction.get())
+ mpOKAction->execute();
+
+ EndPopupMode();
+}
+
+void ScCheckListMenuWindow::setExtendedData(ExtendedData* p)
+{
+ mpExtendedData.reset(p);
+}
+
+ScCheckListMenuWindow::ExtendedData* ScCheckListMenuWindow::getExtendedData()
+{
+ return mpExtendedData.get();
+}
+
+void ScCheckListMenuWindow::setOKAction(Action* p)
+{
+ mpOKAction.reset(p);
+}
diff --git a/sc/source/ui/cctrl/dpcontrol.src b/sc/source/ui/cctrl/checklistmenu.src
index b38548369be5..9247596499b2 100644
--- a/sc/source/ui/cctrl/dpcontrol.src
+++ b/sc/source/ui/cctrl/checklistmenu.src
@@ -25,7 +25,7 @@
*
************************************************************************/
-#include "dpcontrol.hrc"
+#include "checklistmenu.hrc"
Resource RID_POPUP_FILTER
{
diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx
index 41888aef658b..d9f072f62a57 100644
--- a/sc/source/ui/cctrl/dpcontrol.cxx
+++ b/sc/source/ui/cctrl/dpcontrol.cxx
@@ -32,33 +32,16 @@
// INCLUDE ---------------------------------------------------------------
#include "dpcontrol.hxx"
-#include "dpcontrol.hrc"
#include <vcl/outdev.hxx>
#include <vcl/settings.hxx>
-#include <tools/wintypes.hxx>
-#include <vcl/decoview.hxx>
-#include "strload.hxx"
#include "global.hxx"
#include "scitems.hxx"
#include "document.hxx"
#include "docpool.hxx"
#include "patattr.hxx"
-#include "AccessibleFilterMenu.hxx"
-#include "AccessibleFilterTopWindow.hxx"
-
-#include <com/sun/star/accessibility/XAccessible.hpp>
-#include <com/sun/star/accessibility/XAccessibleContext.hpp>
-
-using ::com::sun::star::uno::Reference;
-using ::com::sun::star::accessibility::XAccessible;
-using ::com::sun::star::accessibility::XAccessibleContext;
-using ::rtl::OUString;
-using ::rtl::OUStringHash;
-using ::std::vector;
-using ::boost::unordered_map;
-using ::std::auto_ptr;
+using rtl::OUString;
ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomX, const Fraction* pZoomY, ScDocument* pDoc) :
mpDoc(pDoc),
@@ -270,1155 +253,4 @@ void ScDPFieldButton::drawPopupButton()
}
}
-// ============================================================================
-
-ScMenuFloatingWindow::MenuItemData::MenuItemData() :
- mbEnabled(true),
- mpAction(static_cast<ScCheckListMenuWindow::Action*>(NULL)),
- mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
-{
-}
-
-// ----------------------------------------------------------------------------
-
-ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
- mpSubMenu(NULL),
- mnMenuPos(MENU_NOT_SELECTED),
- mpParent(pParent)
-{
- maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
- maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
-}
-
-void ScMenuFloatingWindow::SubMenuItemData::reset()
-{
- mpSubMenu = NULL;
- mnMenuPos = MENU_NOT_SELECTED;
- maTimer.Stop();
-}
-
-IMPL_LINK( ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, void*, EMPTYARG )
-{
- mpParent->handleMenuTimeout(this);
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-
-size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
-
-ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) :
- PopupMenuFloatingWindow(pParent),
- maOpenTimer(this),
- maCloseTimer(this),
- maName(RTL_CONSTASCII_USTRINGPARAM("ScMenuFloatingWindow")),
- mnSelectedMenu(MENU_NOT_SELECTED),
- mnClickedMenu(MENU_NOT_SELECTED),
- mpDoc(pDoc),
- mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
- mpActiveSubMenu(NULL)
-{
- SetMenuStackLevel(nMenuStackLevel);
-
- // TODO: How do we get the right font to use here ?
- const sal_uInt16 nPopupFontHeight = 12;
- const StyleSettings& rStyle = GetSettings().GetStyleSettings();
- maLabelFont = rStyle.GetLabelFont();
- maLabelFont.SetHeight(nPopupFontHeight);
- SetFont(maLabelFont);
-
- SetText( OUString(RTL_CONSTASCII_USTRINGPARAM("ScMenuFloatingWindow")) );
- SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, PopupEndHdl) );
-}
-
-ScMenuFloatingWindow::~ScMenuFloatingWindow()
-{
- EndPopupMode();
-}
-
-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)
-{
- const Point& rPos = rMEvt.GetPosPixel();
- mnClickedMenu = getEnclosingMenuItem(rPos);
- Window::MouseButtonDown(rMEvt);
-}
-
-void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
-{
- executeMenuItem(mnClickedMenu);
- mnClickedMenu = MENU_NOT_SELECTED;
- Window::MouseButtonUp(rMEvt);
-}
-
-void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
-{
- const KeyCode& rKeyCode = rKEvt.GetKeyCode();
- bool bHandled = true;
- size_t nSelectedMenu = mnSelectedMenu;
- size_t nLastMenuPos = maMenuItems.size() - 1;
- switch (rKeyCode.GetCode())
- {
- case KEY_UP:
- if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
- nSelectedMenu = nLastMenuPos;
- else
- --nSelectedMenu;
- setSelectedMenuItem(nSelectedMenu, false, false);
- break;
- case KEY_DOWN:
- if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
- nSelectedMenu = 0;
- else
- ++nSelectedMenu;
- 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)
- break;
-
- maOpenTimer.mnMenuPos = mnSelectedMenu;
- maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
- launchSubMenu(true);
- }
- break;
- case KEY_RETURN:
- if (nSelectedMenu != MENU_NOT_SELECTED)
- executeMenuItem(nSelectedMenu);
- break;
- default:
- bHandled = false;
- }
-
- if (!bHandled)
- Window::KeyInput(rKEvt);
-}
-
-void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
-{
- const StyleSettings& rStyle = GetSettings().GetStyleSettings();
- Color aBackColor = rStyle.GetMenuColor();
- Color aBorderColor = rStyle.GetShadowColor();
-
- Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
-
- // Window background
- bool bNativeDrawn = true;
- if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
- {
- SetClipRegion();
- bNativeDrawn = DrawNativeControl(
- CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
- ImplControlValue(), OUString());
- }
- else
- bNativeDrawn = false;
-
- if (!bNativeDrawn)
- {
- SetFillColor(aBackColor);
- SetLineColor(aBorderColor);
- DrawRect(aCtrlRect);
- }
-
- // Menu items
- SetTextColor(rStyle.GetMenuTextColor());
- drawAllMenuItems();
-}
-
-Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
-{
- if (!mxAccessible.is())
- {
- Reference<XAccessible> xAccParent = mpParentMenu ?
- mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
-
- mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999, getDoc()));
- ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
- mxAccessible.get());
-
- vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
- for (itr = itrBeg; itr != itrEnd; ++itr)
- {
- size_t nPos = ::std::distance(itrBeg, itr);
- p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
- }
- }
-
- return mxAccessible;
-}
-
-void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
-{
- MenuItemData aItem;
- aItem.maText = rText;
- aItem.mbEnabled = bEnabled;
- aItem.mpAction.reset(pAction);
- maMenuItems.push_back(aItem);
-}
-
-ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
-{
- MenuItemData aItem;
- aItem.maText = rText;
- aItem.mbEnabled = bEnabled;
- aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
- aItem.mpSubMenuWin->setName(rText);
- maMenuItems.push_back(aItem);
- return aItem.mpSubMenuWin.get();
-}
-
-void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
-{
- if (nPos >= maMenuItems.size())
- return;
-
- Point aPos;
- Size aSize;
- getMenuItemPosSize(nPos, aPos, aSize);
-
- DecorationView aDecoView(this);
- long nXOffset = 5;
- long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
- DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
- maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
-
- if (maMenuItems[nPos].mpSubMenuWin)
- {
- long nFontHeight = maLabelFont.GetHeight();
- Point aMarkerPos = aPos;
- aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
- aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
- Size aMarkerSize(nFontHeight/2, nFontHeight/2);
- aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
- SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
- }
-}
-
-void ScMenuFloatingWindow::drawAllMenuItems()
-{
- size_t n = maMenuItems.size();
- for (size_t i = 0; i < n; ++i)
- highlightMenuItem(i, i == mnSelectedMenu);
-}
-
-const Font& ScMenuFloatingWindow::getLabelFont() const
-{
- return maLabelFont;
-}
-
-void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
-{
- if (nPos >= maMenuItems.size())
- return;
-
- if (!maMenuItems[nPos].mpAction)
- // no action is defined.
- return;
-
- maMenuItems[nPos].mpAction->execute();
- terminateAllPopupMenus();
-}
-
-void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
-{
- if (mnSelectedMenu == nPos)
- // nothing to do.
- return;
-
- if (bEnsureSubMenu)
- {
- // Dismiss any child popup menu windows.
- if (mnSelectedMenu < maMenuItems.size() &&
- maMenuItems[mnSelectedMenu].mpSubMenuWin &&
- maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
- {
- maMenuItems[mnSelectedMenu].mpSubMenuWin->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();
-}
-
-size_t ScMenuFloatingWindow::getSelectedMenuItem() const
-{
- return mnSelectedMenu;
-}
-
-void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* pTimer)
-{
- if (pTimer == &maOpenTimer)
- {
- // Close any open submenu immediately.
- if (maCloseTimer.mpSubMenu)
- {
- maCloseTimer.mpSubMenu->EndPopupMode();
- maCloseTimer.mpSubMenu = NULL;
- maCloseTimer.maTimer.Stop();
- }
-
- launchSubMenu(false);
- }
- else if (pTimer == &maCloseTimer)
- {
- // end submenu.
- if (maCloseTimer.mpSubMenu)
- {
- maOpenTimer.mpSubMenu = NULL;
-
- maCloseTimer.mpSubMenu->EndPopupMode();
- maCloseTimer.mpSubMenu = NULL;
-
- highlightMenuItem(maOpenTimer.mnMenuPos, false);
- maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
- }
- }
-}
-
-void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
-{
- if (!pMenu)
- return;
-
- // Set the submenu on launch queue.
- if (maOpenTimer.mpSubMenu)
- {
- if (maOpenTimer.mpSubMenu == pMenu)
- {
- if (pMenu == maCloseTimer.mpSubMenu)
- maCloseTimer.reset();
- return;
- }
-
- // new submenu is being requested.
- queueCloseSubMenu();
- }
-
- maOpenTimer.mpSubMenu = pMenu;
- maOpenTimer.mnMenuPos = nPos;
- maOpenTimer.maTimer.Start();
-}
-
-void ScMenuFloatingWindow::queueCloseSubMenu()
-{
- if (!maOpenTimer.mpSubMenu)
- // There is no submenu to close.
- return;
-
- // Stop any submenu on queue for opening.
- maOpenTimer.maTimer.Stop();
-
- maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
- maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
- maCloseTimer.maTimer.Start();
-}
-
-void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
-{
- Point aPos;
- Size aSize;
- getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize);
- ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
-
- if (!pSubMenu)
- return;
-
- sal_uInt32 nOldFlags = GetPopupModeFlags();
- SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
- pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
- pSubMenu->StartPopupMode(
- Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
- pSubMenu->AddPopupModeWindow(this);
- if (bSetMenuPos)
- pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
- SetPopupModeFlags(nOldFlags);
-}
-
-void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
-{
- if (!pSubMenu)
- return;
-
- pSubMenu->EndPopupMode();
- maOpenTimer.reset();
-
- size_t nMenuPos = getSubMenuPos(pSubMenu);
- if (nMenuPos != MENU_NOT_SELECTED)
- {
- highlightMenuItem(nMenuPos, true);
- mnSelectedMenu = nMenuPos;
- fireMenuHighlightedEvent();
- }
-}
-
-void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
-{
- vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
- for (itr = itrBeg; itr != itrEnd; ++itr)
- {
- size_t nPos = ::std::distance(itrBeg, itr);
- pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
- }
-}
-
-ScDocument* ScMenuFloatingWindow::getDoc()
-{
- return mpDoc;
-}
-
-void ScMenuFloatingWindow::resizeToFitMenuItems()
-{
- if (maMenuItems.empty())
- return;
-
- vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
- long nTextWidth = 0;
- for (; itr != itrEnd; ++itr)
- nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
-
- size_t nLastPos = maMenuItems.size()-1;
- Point aPos;
- Size aSize;
- getMenuItemPosSize(nLastPos, aPos, aSize);
- aPos.X() += nTextWidth + 15;
- aPos.Y() += aSize.Height() + 5;
- SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
-}
-
-void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
-{
- if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
- {
- queueCloseSubMenu();
- return;
- }
-
- if (!maMenuItems[nPos].mbEnabled)
- {
- queueCloseSubMenu();
- return;
- }
-
- highlightMenuItem(nPos, bSelected);
-
- if (bSelected)
- {
- if (mpParentMenu)
- mpParentMenu->setSubMenuFocused(this);
-
- if (bSubMenuTimer)
- {
- if (maMenuItems[nPos].mpSubMenuWin)
- {
- ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
- queueLaunchSubMenu(nPos, pSubMenu);
- }
- else
- queueCloseSubMenu();
- }
- }
-}
-
-void ScMenuFloatingWindow::clearSelectedMenuItem()
-{
- selectMenuItem(mnSelectedMenu, false, false);
- mnSelectedMenu = MENU_NOT_SELECTED;
-}
-
-ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
-{
- if (maMenuItems.size() <= nPos)
- return NULL;
-
- return maMenuItems[nPos].mpSubMenuWin.get();
-}
-
-bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
-{
- return nPos == mnSelectedMenu;
-}
-
-void ScMenuFloatingWindow::setName(const OUString& rName)
-{
- maName = rName;
-}
-
-const OUString& ScMenuFloatingWindow::getName() const
-{
- return maName;
-}
-
-void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
-{
- if (nPos == MENU_NOT_SELECTED)
- return;
-
- const StyleSettings& rStyle = GetSettings().GetStyleSettings();
- Color aBackColor = rStyle.GetMenuColor();
- SetFillColor(aBackColor);
- SetLineColor(aBackColor);
-
- Point aPos;
- Size aSize;
- getMenuItemPosSize(nPos, aPos, aSize);
- Rectangle aRegion(aPos,aSize);
-
- if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
- {
- Push(PUSH_CLIPREGION);
- IntersectClipRegion(Rectangle(aPos, aSize));
- Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
- DrawNativeControl(
- CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
- ImplControlValue(), OUString());
-
- Pop();
- }
-
- bool bNativeDrawn = true;
- if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
- {
- ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
- if (maMenuItems[nPos].mbEnabled)
- nState |= CTRL_STATE_ENABLED;
- bNativeDrawn = DrawNativeControl(
- CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
- }
- else
- bNativeDrawn = false;
-
- if (!bNativeDrawn)
- {
- if (bSelected)
- {
- aBackColor = rStyle.GetMenuHighlightColor();
- SetFillColor(aBackColor);
- SetLineColor(aBackColor);
- }
- DrawRect(Rectangle(aPos,aSize));
- }
-
- Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
- SetTextColor(aTextColor);
- drawMenuItem(nPos);
-}
-
-void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
-{
- const sal_uInt16 nLeftMargin = 5;
- const sal_uInt16 nTopMargin = 5;
- const sal_uInt16 nMenuItemHeight = static_cast< sal_uInt16 >( maLabelFont.GetHeight()*1.8 );
-
- Size aWndSize = GetSizePixel();
-
- Point aPos1(nLeftMargin, nTopMargin);
- Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
-
- rPos = aPos1;
- rPos.Y() += aSize1.Height()*nPos;
- rSize = aSize1;
-}
-
-ScMenuFloatingWindow* ScMenuFloatingWindow::getParentMenuWindow() const
-{
- return mpParentMenu;
-}
-
-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);
- Rectangle aRect(aPos, aSize);
- if (aRect.IsInside(rPos))
- return i;
- }
- return MENU_NOT_SELECTED;
-}
-
-size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
-{
- size_t n = maMenuItems.size();
- for (size_t i = 0; i < n; ++i)
- {
- if (maMenuItems[i].mpSubMenuWin.get() == 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(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
- FireVclEvent(&aEvent);
-}
-
-void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
-{
- maCloseTimer.reset();
- size_t nMenuPos = getSubMenuPos(pSubMenu);
- if (mnSelectedMenu != nMenuPos)
- {
- highlightMenuItem(nMenuPos, true);
- mnSelectedMenu = nMenuPos;
- }
-}
-
-void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
-{
- if (mpParentMenu)
- mpParentMenu->ensureSubMenuVisible(this);
-
- if (pSubMenu->IsVisible())
- return;
-
- // 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);
-
- sal_uInt32 nOldFlags = GetPopupModeFlags();
- SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
- pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
- pSubMenu->StartPopupMode(
- Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
- pSubMenu->AddPopupModeWindow(this);
- SetPopupModeFlags(nOldFlags);
- }
-}
-
-void ScMenuFloatingWindow::ensureSubMenuNotVisible()
-{
- if (mnSelectedMenu <= maMenuItems.size() &&
- maMenuItems[mnSelectedMenu].mpSubMenuWin &&
- maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
- {
- maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
- }
-
- EndPopupMode();
-}
-
-void ScMenuFloatingWindow::terminateAllPopupMenus()
-{
- EndPopupMode();
- if (mpParentMenu)
- mpParentMenu->terminateAllPopupMenus();
-}
-
-IMPL_LINK( ScMenuFloatingWindow, PopupEndHdl, void*, EMPTYARG )
-{
- clearSelectedMenuItem();
- return 0;
-}
-
-// ============================================================================
-
-ScCheckListMenuWindow::Member::Member() :
- mbVisible(true)
-{
-}
-
-// ----------------------------------------------------------------------------
-
-ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) :
- ::CancelButton(pParent), mpParent(pParent) {}
-
-void ScCheckListMenuWindow::CancelButton::Click()
-{
- mpParent->EndPopupMode();
- ::CancelButton::Click();
-}
-
-// ----------------------------------------------------------------------------
-
-ScCheckListMenuWindow::ScCheckListMenuWindow(Window* pParent, ScDocument* pDoc) :
- ScMenuFloatingWindow(pParent, pDoc),
- maChecks(this, 0),
- maChkToggleAll(this, 0),
- maBtnSelectSingle (this, 0),
- maBtnUnselectSingle(this, 0),
- maBtnOk(this),
- maBtnCancel(this),
- mnCurTabStop(0),
- mpExtendedData(NULL),
- mpOKAction(NULL),
- maWndSize(240, 330),
- mePrevToggleAllState(STATE_DONTKNOW)
-{
- maTabStopCtrls.reserve(7);
- maTabStopCtrls.push_back(this);
- maTabStopCtrls.push_back(&maChecks);
- maTabStopCtrls.push_back(&maChkToggleAll);
- maTabStopCtrls.push_back(&maBtnSelectSingle);
- maTabStopCtrls.push_back(&maBtnUnselectSingle);
- maTabStopCtrls.push_back(&maBtnOk);
- maTabStopCtrls.push_back(&maBtnCancel);
-
- 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, 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(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
- maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor());
- maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
- maChkToggleAll.SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) );
- maChkToggleAll.Show();
-
- getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
- maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
- maBtnSelectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT).GetString());
- maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)));
- maBtnSelectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
- maBtnSelectSingle.Show();
-
- getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
- maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
- maBtnUnselectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT).GetString());
- maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)));
- maBtnUnselectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
- maBtnUnselectSingle.Show();
-}
-
-ScCheckListMenuWindow::~ScCheckListMenuWindow()
-{
-}
-
-void ScCheckListMenuWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
-{
- // constant parameters.
- const sal_uInt16 nListBoxMargin = 5; // horizontal distance from the side of the dialog to the listbox border.
- const sal_uInt16 nListBoxInnerPadding = 5;
- const sal_uInt16 nTopMargin = 5;
- const sal_uInt16 nMenuHeight = 60;
- const sal_uInt16 nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
- const sal_uInt16 nBottomBtnAreaHeight = 50; // height of the bottom area where the OK and Cancel buttons are.
- const sal_uInt16 nBtnWidth = 90;
- const sal_uInt16 nLabelHeight = static_cast< sal_uInt16 >( getLabelFont().GetHeight() );
- const sal_uInt16 nBtnHeight = nLabelHeight*2;
- const sal_uInt16 nBottomMargin = 10;
- const sal_uInt16 nMenuListMargin = 20;
-
- // parameters calculated from constants.
- const sal_uInt16 nListBoxWidth = static_cast< sal_uInt16 >( maWndSize.Width() - nListBoxMargin*2 );
- const sal_uInt16 nListBoxHeight = static_cast< sal_uInt16 >( maWndSize.Height() - nTopMargin - nMenuHeight -
- nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight );
-
- const sal_uInt16 nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
-
- switch (eType)
- {
- case WHOLE:
- {
- rPos = Point(0, 0);
- rSize = maWndSize;
- }
- break;
- case LISTBOX_AREA_OUTER:
- {
- rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
- rSize = Size(nListBoxWidth, nListBoxHeight);
- }
- break;
- case LISTBOX_AREA_INNER:
- {
- rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
- rPos.X() += nListBoxInnerPadding;
- rPos.Y() += nListBoxInnerPadding;
-
- rSize = Size(nListBoxWidth, nListBoxHeight);
- rSize.Width() -= nListBoxInnerPadding*2;
- rSize.Height() -= nListBoxInnerPadding*2;
- }
- break;
- case SINGLE_BTN_AREA:
- {
- rPos = Point(nListBoxMargin, nSingleBtnAreaY);
- rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
- }
- break;
- case CHECK_TOGGLE_ALL:
- {
- long h = nLabelHeight*3/2; // check box height is heuristically 150% of the text height.
- rPos = Point(nListBoxMargin, nSingleBtnAreaY);
- rPos.X() += 5;
- rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
- rSize = Size(70, h);
- }
- break;
- case BTN_SINGLE_SELECT:
- {
- long h = 26;
- rPos = Point(nListBoxMargin, nSingleBtnAreaY);
- rPos.X() += 150;
- rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
- rSize = Size(h, h);
- }
- break;
- case BTN_SINGLE_UNSELECT:
- {
- long h = 26;
- rPos = Point(nListBoxMargin, nSingleBtnAreaY);
- rPos.X() += 150 + h + 10;
- rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
- rSize = Size(h, h);
- }
- 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:
- ;
- }
-}
-
-void ScCheckListMenuWindow::setAllMemberState(bool bSet)
-{
- size_t n = maMembers.size();
- for (size_t i = 0; i < n; ++i)
- maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), bSet);
-}
-
-void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
-{
- setAllMemberState(!bSet);
- sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
- maChecks.CheckEntryPos(nSelected, bSet);
-}
-
-void ScCheckListMenuWindow::cycleFocus(bool bReverse)
-{
- maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
- maTabStopCtrls[mnCurTabStop]->LoseFocus();
- if (mnCurTabStop == 0)
- clearSelectedMenuItem();
-
- if (bReverse)
- {
- if (mnCurTabStop > 0)
- --mnCurTabStop;
- else
- mnCurTabStop = maTabStopCtrls.size() - 1;
- }
- else
- {
- ++mnCurTabStop;
- if (mnCurTabStop >= maTabStopCtrls.size())
- mnCurTabStop = 0;
- }
- maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
- maTabStopCtrls[mnCurTabStop]->GrabFocus();
-}
-
-IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn )
-{
- if (pBtn == &maBtnOk)
- close(true);
- else if (pBtn == &maBtnSelectSingle)
- {
- selectCurrentMemberOnly(true);
- CheckHdl(&maChecks);
- }
- else if (pBtn == &maBtnUnselectSingle)
- {
- selectCurrentMemberOnly(false);
- CheckHdl(&maChecks);
- }
- return 0;
-}
-
-IMPL_LINK( ScCheckListMenuWindow, TriStateHdl, TriStateBox*, EMPTYARG )
-{
- switch (mePrevToggleAllState)
- {
- case STATE_NOCHECK:
- maChkToggleAll.SetState(STATE_CHECK);
- setAllMemberState(true);
- break;
- case STATE_CHECK:
- maChkToggleAll.SetState(STATE_NOCHECK);
- setAllMemberState(false);
- break;
- case STATE_DONTKNOW:
- default:
- maChkToggleAll.SetState(STATE_CHECK);
- setAllMemberState(true);
- break;
- }
-
- mePrevToggleAllState = maChkToggleAll.GetState();
- return 0;
-}
-
-IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
-{
- if (pChecks != &maChecks)
- return 0;
-
- size_t nNumChecked = maChecks.GetCheckedEntryCount();
- if (nNumChecked == maMembers.size())
- // all members visible
- maChkToggleAll.SetState(STATE_CHECK);
- else if (nNumChecked == 0)
- // no members visible
- maChkToggleAll.SetState(STATE_NOCHECK);
- else
- maChkToggleAll.SetState(STATE_DONTKNOW);
-
- mePrevToggleAllState = maChkToggleAll.GetState();
- return 0;
-}
-
-void ScCheckListMenuWindow::MouseMove(const MouseEvent& rMEvt)
-{
- ScMenuFloatingWindow::MouseMove(rMEvt);
-
- size_t nSelectedMenu = getSelectedMenuItem();
- if (nSelectedMenu == MENU_NOT_SELECTED)
- queueCloseSubMenu();
-}
-
-long ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
-{
- switch (rNEvt.GetType())
- {
- case EVENT_KEYUP:
- {
- const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
- const KeyCode& rCode = pKeyEvent->GetKeyCode();
- bool bShift = rCode.IsShift();
- if (rCode.GetCode() == KEY_TAB)
- {
- cycleFocus(bShift);
- return true;
- }
- }
- break;
- }
- return ScMenuFloatingWindow::Notify(rNEvt);
-}
-
-void ScCheckListMenuWindow::Paint(const Rectangle& rRect)
-{
- ScMenuFloatingWindow::Paint(rRect);
-
- const StyleSettings& rStyle = GetSettings().GetStyleSettings();
- Color aMemberBackColor = rStyle.GetFieldColor();
- Color aBorderColor = rStyle.GetShadowColor();
-
- Point aPos;
- Size aSize;
- getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
-
- // Member list box background
- SetFillColor(aMemberBackColor);
- SetLineColor(aBorderColor);
- DrawRect(Rectangle(aPos,aSize));
-
- // Single-action button box
- getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
- SetFillColor(rStyle.GetMenuColor());
- DrawRect(Rectangle(aPos,aSize));
-}
-
-Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
-{
- return maTabStopCtrls[mnCurTabStop];
-}
-
-Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
-{
- if (!mxAccessible.is())
- {
- mxAccessible.set(new ScAccessibleFilterTopWindow(
- GetAccessibleParentWindow()->GetAccessible(), this, getName(), getDoc()));
- ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
- fillMenuItemsToAccessible(pAccTop);
-
- pAccTop->setAccessibleChild(
- maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
- pAccTop->setAccessibleChild(
- maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
- pAccTop->setAccessibleChild(
- maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
- pAccTop->setAccessibleChild(
- maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
- pAccTop->setAccessibleChild(
- maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
- pAccTop->setAccessibleChild(
- maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
- }
-
- return mxAccessible;
-}
-
-void ScCheckListMenuWindow::setMemberSize(size_t n)
-{
- maMembers.reserve(n);
-}
-
-void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
-{
- Member aMember;
- aMember.maName = rName;
- aMember.mbVisible = bVisible;
- maMembers.push_back(aMember);
-}
-
-void ScCheckListMenuWindow::initMembers()
-{
- size_t n = maMembers.size();
- size_t nVisMemCount = 0;
- for (size_t i = 0; i < n; ++i)
- {
- maChecks.InsertEntry(maMembers[i].maName);
- maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), maMembers[i].mbVisible);
- if (maMembers[i].mbVisible)
- ++nVisMemCount;
- }
- if (nVisMemCount == n)
- {
- // all members visible
- maChkToggleAll.SetState(STATE_CHECK);
- mePrevToggleAllState = STATE_CHECK;
- }
- else if (nVisMemCount == 0)
- {
- // no members visible
- maChkToggleAll.SetState(STATE_NOCHECK);
- mePrevToggleAllState = STATE_NOCHECK;
- }
- else
- {
- maChkToggleAll.SetState(STATE_DONTKNOW);
- mePrevToggleAllState = STATE_DONTKNOW;
- }
-}
-
-const Size& ScCheckListMenuWindow::getWindowSize() const
-{
- return maWndSize;
-}
-
-void ScCheckListMenuWindow::getResult(boost::unordered_map<OUString, bool, OUStringHash>& rResult)
-{
- typedef boost::unordered_map<OUString, bool, OUStringHash> ResultMap;
- ResultMap aResult;
- size_t n = maMembers.size();
- for (size_t i = 0; i < n; ++i)
- {
- bool bState = maChecks.IsChecked(static_cast< sal_uInt16 >( i ));
- aResult.insert(ResultMap::value_type(maMembers[i].maName, bState));
- }
- rResult.swap(aResult);
-}
-
-void ScCheckListMenuWindow::close(bool bOK)
-{
- if (bOK && mpOKAction.get())
- mpOKAction->execute();
-
- EndPopupMode();
-}
-
-void ScCheckListMenuWindow::setExtendedData(ExtendedData* p)
-{
- mpExtendedData.reset(p);
-}
-
-ScCheckListMenuWindow::ExtendedData* ScCheckListMenuWindow::getExtendedData()
-{
- return mpExtendedData.get();
-}
-
-void ScCheckListMenuWindow::setOKAction(Action* p)
-{
- mpOKAction.reset(p);
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */