diff options
author | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-09-12 21:12:57 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-09-12 21:14:01 -0400 |
commit | 7a60be6e00ce3ad15f9976f607f26e52e7d06fa7 (patch) | |
tree | aaeec748b45bfa01353f88792a4686e9d917694f /sc/source/ui/cctrl | |
parent | 0bc368babc36542cd157803fb9fefb4260f0a9e2 (diff) |
Move ScCheckListMenuWindow and ScMenuFloatingWindow into own files.
Diffstat (limited to 'sc/source/ui/cctrl')
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 1197 | ||||
-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.cxx | 1170 |
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: */ |