LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/ui/cctrl - checklistmenu.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 782 0.1 %
Date: 2013-07-09 Functions: 2 88 2.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "checklistmenu.hxx"
      21             : #include "checklistmenu.hrc"
      22             : #include "strload.hxx"
      23             : 
      24             : #include <vcl/decoview.hxx>
      25             : #include <tools/wintypes.hxx>
      26             : 
      27             : #include "AccessibleFilterMenu.hxx"
      28             : #include "AccessibleFilterTopWindow.hxx"
      29             : 
      30             : #include <com/sun/star/accessibility/XAccessible.hpp>
      31             : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
      32             : 
      33             : using ::com::sun::star::uno::Reference;
      34             : using ::com::sun::star::accessibility::XAccessible;
      35             : using ::com::sun::star::accessibility::XAccessibleContext;
      36             : using ::std::vector;
      37             : using ::boost::unordered_map;
      38             : using ::std::auto_ptr;
      39             : 
      40           0 : ScMenuFloatingWindow::MenuItemData::MenuItemData() :
      41             :     mbEnabled(true), mbSeparator(false),
      42             :     mpAction(static_cast<ScCheckListMenuWindow::Action*>(NULL)),
      43           0 :     mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
      44             : {
      45           0 : }
      46             : 
      47             : // ----------------------------------------------------------------------------
      48             : 
      49           0 : ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
      50             :     mpSubMenu(NULL),
      51             :     mnMenuPos(MENU_NOT_SELECTED),
      52           0 :     mpParent(pParent)
      53             : {
      54           0 :     maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
      55           0 :     maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
      56           0 : }
      57             : 
      58           0 : void ScMenuFloatingWindow::SubMenuItemData::reset()
      59             : {
      60           0 :     mpSubMenu = NULL;
      61           0 :     mnMenuPos = MENU_NOT_SELECTED;
      62           0 :     maTimer.Stop();
      63           0 : }
      64             : 
      65           0 : IMPL_LINK_NOARG(ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl)
      66             : {
      67           0 :     mpParent->handleMenuTimeout(this);
      68           0 :     return 0;
      69             : }
      70             : 
      71             : // ----------------------------------------------------------------------------
      72             : 
      73             : size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
      74             : 
      75           0 : ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) :
      76             :     PopupMenuFloatingWindow(pParent),
      77             :     maOpenTimer(this),
      78             :     maCloseTimer(this),
      79             :     maName("ScMenuFloatingWindow"),
      80             :     mnSelectedMenu(MENU_NOT_SELECTED),
      81             :     mnClickedMenu(MENU_NOT_SELECTED),
      82             :     mpDoc(pDoc),
      83           0 :     mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent))
      84             : {
      85           0 :     SetMenuStackLevel(nMenuStackLevel);
      86             : 
      87             :     // TODO: How do we get the right font to use here ?
      88           0 :     const sal_uInt16 nPopupFontHeight = 12;
      89           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
      90           0 :     maLabelFont = rStyle.GetLabelFont();
      91           0 :     maLabelFont.SetHeight(nPopupFontHeight);
      92           0 :     SetFont(maLabelFont);
      93             : 
      94           0 :     SetText( OUString("ScMenuFloatingWindow") );
      95           0 : }
      96             : 
      97           0 : ScMenuFloatingWindow::~ScMenuFloatingWindow()
      98             : {
      99           0 :     EndPopupMode();
     100           0 : }
     101             : 
     102           0 : void ScMenuFloatingWindow::PopupModeEnd()
     103             : {
     104           0 :     handlePopupEnd();
     105           0 : }
     106             : 
     107           0 : void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
     108             : {
     109           0 :     const Point& rPos = rMEvt.GetPosPixel();
     110           0 :     size_t nSelectedMenu = getEnclosingMenuItem(rPos);
     111           0 :     setSelectedMenuItem(nSelectedMenu, true, false);
     112             : 
     113           0 :     Window::MouseMove(rMEvt);
     114           0 : }
     115             : 
     116           0 : void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
     117             : {
     118           0 :     const Point& rPos = rMEvt.GetPosPixel();
     119           0 :     mnClickedMenu = getEnclosingMenuItem(rPos);
     120           0 :     Window::MouseButtonDown(rMEvt);
     121           0 : }
     122             : 
     123           0 : void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
     124             : {
     125           0 :     executeMenuItem(mnClickedMenu);
     126           0 :     mnClickedMenu = MENU_NOT_SELECTED;
     127           0 :     Window::MouseButtonUp(rMEvt);
     128           0 : }
     129             : 
     130           0 : void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
     131             : {
     132           0 :     if (maMenuItems.empty())
     133             :     {
     134           0 :         Window::KeyInput(rKEvt);
     135           0 :         return;
     136             :     }
     137             : 
     138           0 :     const KeyCode& rKeyCode = rKEvt.GetKeyCode();
     139           0 :     bool bHandled = true;
     140           0 :     size_t nSelectedMenu = mnSelectedMenu;
     141           0 :     size_t nLastMenuPos = maMenuItems.size() - 1;
     142           0 :     switch (rKeyCode.GetCode())
     143             :     {
     144             :         case KEY_UP:
     145             :         {
     146           0 :             if (nLastMenuPos == 0)
     147             :                 // There is only one menu item.  Do nothing.
     148           0 :                 break;
     149             : 
     150           0 :             size_t nOldPos = nSelectedMenu;
     151             : 
     152           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
     153           0 :                 nSelectedMenu = nLastMenuPos;
     154             :             else
     155           0 :                 --nSelectedMenu;
     156             : 
     157             :             // Loop until a non-separator menu item is found.
     158           0 :             while (nSelectedMenu != nOldPos)
     159             :             {
     160           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     161             :                 {
     162           0 :                     if (nSelectedMenu)
     163           0 :                         --nSelectedMenu;
     164             :                     else
     165           0 :                         nSelectedMenu = nLastMenuPos;
     166             :                 }
     167             :                 else
     168           0 :                     break;
     169             :             }
     170             : 
     171           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     172             :         }
     173           0 :         break;
     174             :         case KEY_DOWN:
     175             :         {
     176           0 :             if (nLastMenuPos == 0)
     177             :                 // There is only one menu item.  Do nothing.
     178           0 :                 break;
     179             : 
     180           0 :             size_t nOldPos = nSelectedMenu;
     181             : 
     182           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
     183           0 :                 nSelectedMenu = 0;
     184             :             else
     185           0 :                 ++nSelectedMenu;
     186             : 
     187             :             // Loop until a non-separator menu item is found.
     188           0 :             while (nSelectedMenu != nOldPos)
     189             :             {
     190           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     191             :                 {
     192           0 :                     if (nSelectedMenu == nLastMenuPos)
     193           0 :                         nSelectedMenu = 0;
     194             :                     else
     195           0 :                         ++nSelectedMenu;
     196             :                 }
     197             :                 else
     198           0 :                     break;
     199             :             }
     200             : 
     201           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     202             :         }
     203           0 :         break;
     204             :         case KEY_LEFT:
     205           0 :             if (mpParentMenu)
     206           0 :                 mpParentMenu->endSubMenu(this);
     207           0 :         break;
     208             :         case KEY_RIGHT:
     209             :         {
     210           0 :             if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
     211           0 :                 break;
     212             : 
     213           0 :             const MenuItemData& rMenu = maMenuItems[mnSelectedMenu];
     214           0 :             if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
     215           0 :                 break;
     216             : 
     217           0 :             maOpenTimer.mnMenuPos = mnSelectedMenu;
     218           0 :             maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
     219           0 :             launchSubMenu(true);
     220             :         }
     221           0 :         break;
     222             :         case KEY_RETURN:
     223           0 :             if (nSelectedMenu != MENU_NOT_SELECTED)
     224           0 :                 executeMenuItem(nSelectedMenu);
     225           0 :         break;
     226             :         default:
     227           0 :             bHandled = false;
     228             :     }
     229             : 
     230           0 :     if (!bHandled)
     231           0 :         Window::KeyInput(rKEvt);
     232             : }
     233             : 
     234           0 : void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
     235             : {
     236           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     237           0 :     Color aBackColor = rStyle.GetMenuColor();
     238           0 :     Color aBorderColor = rStyle.GetShadowColor();
     239             : 
     240           0 :     Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
     241             : 
     242             :     // Window background
     243           0 :     bool bNativeDrawn = true;
     244           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     245             :     {
     246           0 :         SetClipRegion();
     247             :         bNativeDrawn = DrawNativeControl(
     248             :             CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
     249           0 :             ImplControlValue(), OUString());
     250             :     }
     251             :     else
     252           0 :         bNativeDrawn = false;
     253             : 
     254           0 :     if (!bNativeDrawn)
     255             :     {
     256           0 :         SetFillColor(aBackColor);
     257           0 :         SetLineColor(aBorderColor);
     258           0 :         DrawRect(aCtrlRect);
     259             :     }
     260             : 
     261             :     // Menu items
     262           0 :     SetTextColor(rStyle.GetMenuTextColor());
     263           0 :     drawAllMenuItems();
     264           0 : }
     265             : 
     266           0 : Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
     267             : {
     268           0 :     if (!mxAccessible.is())
     269             :     {
     270             :         Reference<XAccessible> xAccParent = mpParentMenu ?
     271           0 :             mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
     272             : 
     273           0 :         mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999));
     274             :         ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
     275           0 :             mxAccessible.get());
     276             : 
     277           0 :         vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
     278           0 :         for (itr = itrBeg; itr != itrEnd; ++itr)
     279             :         {
     280           0 :             size_t nPos = ::std::distance(itrBeg, itr);
     281           0 :             p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
     282           0 :         }
     283             :     }
     284             : 
     285           0 :     return mxAccessible;
     286             : }
     287             : 
     288           0 : void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
     289             : {
     290           0 :     MenuItemData aItem;
     291           0 :     aItem.maText = rText;
     292           0 :     aItem.mbEnabled = bEnabled;
     293           0 :     aItem.mpAction.reset(pAction);
     294           0 :     maMenuItems.push_back(aItem);
     295           0 : }
     296             : 
     297           0 : void ScMenuFloatingWindow::addSeparator()
     298             : {
     299           0 :     MenuItemData aItem;
     300           0 :     aItem.mbSeparator = true;
     301           0 :     maMenuItems.push_back(aItem);
     302           0 : }
     303             : 
     304           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
     305             : {
     306           0 :     MenuItemData aItem;
     307           0 :     aItem.maText = rText;
     308           0 :     aItem.mbEnabled = bEnabled;
     309           0 :     aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
     310           0 :     aItem.mpSubMenuWin->setName(rText);
     311           0 :     maMenuItems.push_back(aItem);
     312           0 :     return aItem.mpSubMenuWin.get();
     313             : }
     314             : 
     315           0 : void ScMenuFloatingWindow::handlePopupEnd()
     316             : {
     317           0 :     clearSelectedMenuItem();
     318           0 : }
     319             : 
     320           0 : Size ScMenuFloatingWindow::getMenuSize() const
     321             : {
     322           0 :     if (maMenuItems.empty())
     323           0 :         return Size();
     324             : 
     325           0 :     vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
     326           0 :     long nTextWidth = 0;
     327           0 :     for (; itr != itrEnd; ++itr)
     328             :     {
     329           0 :         if (itr->mbSeparator)
     330           0 :             continue;
     331             : 
     332           0 :         nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
     333             :     }
     334             : 
     335           0 :     size_t nLastPos = maMenuItems.size()-1;
     336           0 :     Point aPos;
     337           0 :     Size aSize;
     338           0 :     getMenuItemPosSize(nLastPos, aPos, aSize);
     339           0 :     aPos.X() += nTextWidth + 15;
     340           0 :     aPos.Y() += aSize.Height() + 5;
     341           0 :     return Size(aPos.X(), aPos.Y());
     342             : }
     343             : 
     344           0 : void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
     345             : {
     346           0 :     if (nPos >= maMenuItems.size())
     347           0 :         return;
     348             : 
     349           0 :     Point aPos;
     350           0 :     Size aSize;
     351           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     352             : 
     353           0 :     DecorationView aDecoView(this);
     354           0 :     long nXOffset = 5;
     355           0 :     long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
     356           0 :     DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
     357           0 :                  maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
     358             : 
     359           0 :     if (maMenuItems[nPos].mpSubMenuWin)
     360             :     {
     361           0 :         long nFontHeight = maLabelFont.GetHeight();
     362           0 :         Point aMarkerPos = aPos;
     363           0 :         aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
     364           0 :         aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
     365           0 :         Size aMarkerSize(nFontHeight/2, nFontHeight/2);
     366             :         aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
     367           0 :                              SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
     368             :     }
     369             : }
     370             : 
     371           0 : void ScMenuFloatingWindow::drawSeparator(size_t nPos)
     372             : {
     373           0 :     Point aPos;
     374           0 :     Size aSize;
     375           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     376           0 :     Rectangle aRegion(aPos,aSize);
     377             : 
     378           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     379             :     {
     380           0 :         Push(PUSH_CLIPREGION);
     381           0 :         IntersectClipRegion(aRegion);
     382           0 :         Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
     383             :         DrawNativeControl(
     384             :             CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
     385           0 :             ImplControlValue(), OUString());
     386             : 
     387           0 :         Pop();
     388             :     }
     389             : 
     390           0 :     bool bNativeDrawn = false;
     391           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_SEPARATOR))
     392             :     {
     393           0 :         ControlState nState = 0;
     394           0 :         const MenuItemData& rData = maMenuItems[nPos];
     395           0 :         if (rData.mbEnabled)
     396           0 :             nState |= CTRL_STATE_ENABLED;
     397             : 
     398             :         bNativeDrawn = DrawNativeControl(
     399             :             CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
     400           0 :             aRegion, nState, ImplControlValue(), OUString());
     401             :     }
     402             : 
     403           0 :     if (!bNativeDrawn)
     404             :     {
     405           0 :         const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     406           0 :         Point aTmpPos = aPos;
     407           0 :         aTmpPos.Y() += aSize.Height()/2;
     408           0 :         SetLineColor(rStyle.GetShadowColor());
     409           0 :         DrawLine(aTmpPos, Point(aSize.Width()+aTmpPos.X(), aTmpPos.Y()));
     410           0 :         ++aTmpPos.Y();
     411           0 :         SetLineColor(rStyle.GetLightColor());
     412           0 :         DrawLine(aTmpPos, Point(aSize.Width()+aTmpPos.X(), aTmpPos.Y()));
     413           0 :         SetLineColor();
     414             :     }
     415           0 : }
     416             : 
     417           0 : void ScMenuFloatingWindow::drawAllMenuItems()
     418             : {
     419           0 :     size_t n = maMenuItems.size();
     420           0 :     for (size_t i = 0; i < n; ++i)
     421             :     {
     422           0 :         if (maMenuItems[i].mbSeparator)
     423             :             // Separator
     424           0 :             drawSeparator(i);
     425             :         else
     426             :             // Normal menu item
     427           0 :             highlightMenuItem(i, i == mnSelectedMenu);
     428             :     }
     429           0 : }
     430             : 
     431           0 : const Font& ScMenuFloatingWindow::getLabelFont() const
     432             : {
     433           0 :     return maLabelFont;
     434             : }
     435             : 
     436           0 : void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
     437             : {
     438           0 :     if (nPos >= maMenuItems.size())
     439           0 :         return;
     440             : 
     441           0 :     if (!maMenuItems[nPos].mpAction)
     442             :         // no action is defined.
     443           0 :         return;
     444             : 
     445           0 :     maMenuItems[nPos].mpAction->execute();
     446           0 :     terminateAllPopupMenus();
     447             : }
     448             : 
     449           0 : void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
     450             : {
     451           0 :     if (mnSelectedMenu == nPos)
     452             :         // nothing to do.
     453           0 :         return;
     454             : 
     455           0 :     if (bEnsureSubMenu)
     456             :     {
     457             :         // Dismiss any child popup menu windows.
     458           0 :         if (mnSelectedMenu < maMenuItems.size() &&
     459           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     460           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     461             :         {
     462           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     463             :         }
     464             : 
     465             :         // The popup is not visible, yet a menu item is selected.  The request
     466             :         // most likely comes from the accessible object.  Make sure this
     467             :         // window, as well as all its parent windows are visible.
     468           0 :         if (!IsVisible() && mpParentMenu)
     469           0 :             mpParentMenu->ensureSubMenuVisible(this);
     470             :     }
     471             : 
     472           0 :     selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
     473           0 :     selectMenuItem(nPos, true, bSubMenuTimer);
     474           0 :     mnSelectedMenu = nPos;
     475             : 
     476           0 :     fireMenuHighlightedEvent();
     477             : }
     478             : 
     479           0 : size_t ScMenuFloatingWindow::getSelectedMenuItem() const
     480             : {
     481           0 :     return mnSelectedMenu;
     482             : }
     483             : 
     484           0 : void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* pTimer)
     485             : {
     486           0 :     if (pTimer == &maOpenTimer)
     487             :     {
     488             :         // Close any open submenu immediately.
     489           0 :         if (maCloseTimer.mpSubMenu)
     490             :         {
     491           0 :             maCloseTimer.mpSubMenu->EndPopupMode();
     492           0 :             maCloseTimer.mpSubMenu = NULL;
     493           0 :             maCloseTimer.maTimer.Stop();
     494             :         }
     495             : 
     496           0 :         launchSubMenu(false);
     497             :     }
     498           0 :     else if (pTimer == &maCloseTimer)
     499             :     {
     500             :         // end submenu.
     501           0 :         if (maCloseTimer.mpSubMenu)
     502             :         {
     503           0 :             maOpenTimer.mpSubMenu = NULL;
     504             : 
     505           0 :             maCloseTimer.mpSubMenu->EndPopupMode();
     506           0 :             maCloseTimer.mpSubMenu = NULL;
     507             : 
     508           0 :             highlightMenuItem(maOpenTimer.mnMenuPos, false);
     509           0 :             maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
     510             :         }
     511             :     }
     512           0 : }
     513             : 
     514           0 : void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
     515             : {
     516           0 :     if (!pMenu)
     517           0 :         return;
     518             : 
     519             :     // Set the submenu on launch queue.
     520           0 :     if (maOpenTimer.mpSubMenu)
     521             :     {
     522           0 :         if (maOpenTimer.mpSubMenu == pMenu)
     523             :         {
     524           0 :             if (pMenu == maCloseTimer.mpSubMenu)
     525           0 :                 maCloseTimer.reset();
     526           0 :             return;
     527             :         }
     528             : 
     529             :         // new submenu is being requested.
     530           0 :         queueCloseSubMenu();
     531             :     }
     532             : 
     533           0 :     maOpenTimer.mpSubMenu = pMenu;
     534           0 :     maOpenTimer.mnMenuPos = nPos;
     535           0 :     maOpenTimer.maTimer.Start();
     536             : }
     537             : 
     538           0 : void ScMenuFloatingWindow::queueCloseSubMenu()
     539             : {
     540           0 :     if (!maOpenTimer.mpSubMenu)
     541             :         // There is no submenu to close.
     542           0 :         return;
     543             : 
     544             :     // Stop any submenu on queue for opening.
     545           0 :     maOpenTimer.maTimer.Stop();
     546             : 
     547           0 :     maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
     548           0 :     maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
     549           0 :     maCloseTimer.maTimer.Start();
     550             : }
     551             : 
     552           0 : void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
     553             : {
     554           0 :     Point aPos;
     555           0 :     Size aSize;
     556           0 :     getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize);
     557           0 :     ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
     558             : 
     559           0 :     if (!pSubMenu)
     560           0 :         return;
     561             : 
     562           0 :     sal_uInt32 nOldFlags = GetPopupModeFlags();
     563           0 :     SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
     564           0 :     pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
     565             :     pSubMenu->StartPopupMode(
     566           0 :         Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
     567           0 :     pSubMenu->AddPopupModeWindow(this);
     568           0 :     if (bSetMenuPos)
     569           0 :         pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
     570           0 :     SetPopupModeFlags(nOldFlags);
     571             : }
     572             : 
     573           0 : void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
     574             : {
     575           0 :     if (!pSubMenu)
     576           0 :         return;
     577             : 
     578           0 :     pSubMenu->EndPopupMode();
     579           0 :     maOpenTimer.reset();
     580             : 
     581           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     582           0 :     if (nMenuPos != MENU_NOT_SELECTED)
     583             :     {
     584           0 :         highlightMenuItem(nMenuPos, true);
     585           0 :         mnSelectedMenu = nMenuPos;
     586           0 :         fireMenuHighlightedEvent();
     587             :     }
     588             : }
     589             : 
     590           0 : void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
     591             : {
     592           0 :     vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
     593           0 :     for (itr = itrBeg; itr != itrEnd; ++itr)
     594             :     {
     595           0 :         size_t nPos = ::std::distance(itrBeg, itr);
     596           0 :         pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
     597             :     }
     598           0 : }
     599             : 
     600           0 : void ScMenuFloatingWindow::resizeToFitMenuItems()
     601             : {
     602           0 :     SetOutputSizePixel(getMenuSize());
     603           0 : }
     604             : 
     605           0 : void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
     606             : {
     607           0 :     if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
     608             :     {
     609           0 :         queueCloseSubMenu();
     610           0 :         return;
     611             :     }
     612             : 
     613           0 :     if (!maMenuItems[nPos].mbEnabled)
     614             :     {
     615           0 :         queueCloseSubMenu();
     616           0 :         return;
     617             :     }
     618             : 
     619           0 :     highlightMenuItem(nPos, bSelected);
     620             : 
     621           0 :     if (bSelected)
     622             :     {
     623           0 :         if (mpParentMenu)
     624           0 :             mpParentMenu->setSubMenuFocused(this);
     625             : 
     626           0 :         if (bSubMenuTimer)
     627             :         {
     628           0 :             if (maMenuItems[nPos].mpSubMenuWin)
     629             :             {
     630           0 :                 ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
     631           0 :                 queueLaunchSubMenu(nPos, pSubMenu);
     632             :             }
     633             :             else
     634           0 :                 queueCloseSubMenu();
     635             :         }
     636             :     }
     637             : }
     638             : 
     639           0 : void ScMenuFloatingWindow::clearSelectedMenuItem()
     640             : {
     641           0 :     selectMenuItem(mnSelectedMenu, false, false);
     642           0 :     mnSelectedMenu = MENU_NOT_SELECTED;
     643           0 : }
     644             : 
     645           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
     646             : {
     647           0 :     if (maMenuItems.size() <= nPos)
     648           0 :         return NULL;
     649             : 
     650           0 :     return maMenuItems[nPos].mpSubMenuWin.get();
     651             : }
     652             : 
     653           0 : bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
     654             : {
     655           0 :     return nPos == mnSelectedMenu;
     656             : }
     657             : 
     658           0 : void ScMenuFloatingWindow::setName(const OUString& rName)
     659             : {
     660           0 :     maName = rName;
     661           0 : }
     662             : 
     663           0 : const OUString& ScMenuFloatingWindow::getName() const
     664             : {
     665           0 :     return maName;
     666             : }
     667             : 
     668           0 : void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
     669             : {
     670           0 :     if (nPos == MENU_NOT_SELECTED)
     671           0 :         return;
     672             : 
     673           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     674           0 :     Color aBackColor = rStyle.GetMenuColor();
     675           0 :     SetFillColor(aBackColor);
     676           0 :     SetLineColor(aBackColor);
     677             : 
     678           0 :     Point aPos;
     679           0 :     Size aSize;
     680           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     681           0 :     Rectangle aRegion(aPos,aSize);
     682             : 
     683           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     684             :     {
     685           0 :         Push(PUSH_CLIPREGION);
     686           0 :         IntersectClipRegion(Rectangle(aPos, aSize));
     687           0 :         Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
     688             :         DrawNativeControl(
     689             :             CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
     690           0 :             ImplControlValue(), OUString());
     691             : 
     692           0 :         Pop();
     693             :     }
     694             : 
     695           0 :     bool bNativeDrawn = true;
     696           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
     697             :     {
     698           0 :         ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
     699           0 :         if (maMenuItems[nPos].mbEnabled)
     700           0 :             nState |= CTRL_STATE_ENABLED;
     701             :         bNativeDrawn = DrawNativeControl(
     702           0 :             CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
     703             :     }
     704             :     else
     705           0 :         bNativeDrawn = false;
     706             : 
     707           0 :     if (!bNativeDrawn)
     708             :     {
     709           0 :         if (bSelected)
     710             :         {
     711           0 :             aBackColor = rStyle.GetMenuHighlightColor();
     712           0 :             SetFillColor(aBackColor);
     713           0 :             SetLineColor(aBackColor);
     714             :         }
     715           0 :         DrawRect(Rectangle(aPos,aSize));
     716             :     }
     717             : 
     718           0 :     Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
     719           0 :     SetTextColor(aTextColor);
     720           0 :     drawMenuItem(nPos);
     721             : }
     722             : 
     723           0 : void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
     724             : {
     725           0 :     size_t nCount = maMenuItems.size();
     726           0 :     if (nPos >= nCount)
     727           0 :         return;
     728             : 
     729           0 :     const sal_uInt16 nLeftMargin = 5;
     730           0 :     const sal_uInt16 nTopMargin = 5;
     731           0 :     const sal_uInt16 nMenuItemHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*1.8);
     732           0 :     const sal_uInt16 nSepHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*0.8);
     733             : 
     734           0 :     Point aPos1(nLeftMargin, nTopMargin);
     735           0 :     rPos = aPos1;
     736           0 :     for (size_t i = 0; i < nPos; ++i)
     737           0 :         rPos.Y() += maMenuItems[i].mbSeparator ? nSepHeight : nMenuItemHeight;
     738             : 
     739           0 :     Size aWndSize = GetSizePixel();
     740           0 :     sal_uInt16 nH = maMenuItems[nPos].mbSeparator ? nSepHeight : nMenuItemHeight;
     741           0 :     rSize = Size(aWndSize.Width() - nLeftMargin*2, nH);
     742             : }
     743             : 
     744           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::getParentMenuWindow() const
     745             : {
     746           0 :     return mpParentMenu;
     747             : }
     748             : 
     749           0 : size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
     750             : {
     751           0 :     size_t n = maMenuItems.size();
     752           0 :     for (size_t i = 0; i < n; ++i)
     753             :     {
     754           0 :         Point aPos;
     755           0 :         Size aSize;
     756           0 :         getMenuItemPosSize(i, aPos, aSize);
     757           0 :         Rectangle aRect(aPos, aSize);
     758           0 :         if (aRect.IsInside(rPos))
     759           0 :             return maMenuItems[i].mbSeparator ? MENU_NOT_SELECTED : i;
     760             :     }
     761           0 :     return MENU_NOT_SELECTED;
     762             : }
     763             : 
     764           0 : size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
     765             : {
     766           0 :     size_t n = maMenuItems.size();
     767           0 :     for (size_t i = 0; i < n; ++i)
     768             :     {
     769           0 :         if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu)
     770           0 :             return i;
     771             :     }
     772           0 :     return MENU_NOT_SELECTED;
     773             : }
     774             : 
     775           0 : void ScMenuFloatingWindow::fireMenuHighlightedEvent()
     776             : {
     777           0 :     if (mnSelectedMenu == MENU_NOT_SELECTED)
     778           0 :         return;
     779             : 
     780           0 :     if (!mxAccessible.is())
     781           0 :         return;
     782             : 
     783           0 :     Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext();
     784           0 :     if (!xAccCxt.is())
     785           0 :         return;
     786             : 
     787           0 :     Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu);
     788           0 :     if (!xAccMenu.is())
     789           0 :         return;
     790             : 
     791           0 :     VclAccessibleEvent aEvent(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
     792           0 :     FireVclEvent(&aEvent);
     793             : }
     794             : 
     795           0 : void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
     796             : {
     797           0 :     maCloseTimer.reset();
     798           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     799           0 :     if (mnSelectedMenu != nMenuPos)
     800             :     {
     801           0 :         highlightMenuItem(nMenuPos, true);
     802           0 :         mnSelectedMenu = nMenuPos;
     803             :     }
     804           0 : }
     805             : 
     806           0 : void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
     807             : {
     808           0 :     if (mpParentMenu)
     809           0 :         mpParentMenu->ensureSubMenuVisible(this);
     810             : 
     811           0 :     if (pSubMenu->IsVisible())
     812           0 :         return;
     813             : 
     814             :     // Find the menu position of the submenu.
     815           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     816           0 :     if (nMenuPos != MENU_NOT_SELECTED)
     817             :     {
     818           0 :         setSelectedMenuItem(nMenuPos, false, false);
     819             : 
     820           0 :         Point aPos;
     821           0 :         Size aSize;
     822           0 :         getMenuItemPosSize(nMenuPos, aPos, aSize);
     823             : 
     824           0 :         sal_uInt32 nOldFlags = GetPopupModeFlags();
     825           0 :         SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
     826           0 :         pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
     827             :         pSubMenu->StartPopupMode(
     828           0 :             Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
     829           0 :         pSubMenu->AddPopupModeWindow(this);
     830           0 :         SetPopupModeFlags(nOldFlags);
     831             :     }
     832             : }
     833             : 
     834           0 : void ScMenuFloatingWindow::ensureSubMenuNotVisible()
     835             : {
     836           0 :     if (mnSelectedMenu <= maMenuItems.size() &&
     837           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     838           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     839             :     {
     840           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     841             :     }
     842             : 
     843           0 :     EndPopupMode();
     844           0 : }
     845             : 
     846           0 : void ScMenuFloatingWindow::terminateAllPopupMenus()
     847             : {
     848           0 :     EndPopupMode();
     849           0 :     if (mpParentMenu)
     850           0 :         mpParentMenu->terminateAllPopupMenus();
     851           0 : }
     852             : 
     853             : // ============================================================================
     854             : 
     855           0 : ScCheckListMenuWindow::Config::Config() :
     856           0 :     mbAllowEmptySet(true), mbRTL(false)
     857             : {
     858           0 : }
     859             : 
     860           0 : ScCheckListMenuWindow::Member::Member() :
     861           0 :     mbVisible(true)
     862             : {
     863           0 : }
     864             : 
     865             : // ----------------------------------------------------------------------------
     866             : 
     867           0 : ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) :
     868           0 :     ::CancelButton(pParent), mpParent(pParent) {}
     869             : 
     870           0 : void ScCheckListMenuWindow::CancelButton::Click()
     871             : {
     872           0 :     mpParent->EndPopupMode();
     873           0 :     ::CancelButton::Click();
     874           0 : }
     875             : 
     876             : // ----------------------------------------------------------------------------
     877             : 
     878           0 : ScCheckListMenuWindow::ScCheckListMenuWindow(Window* pParent, ScDocument* pDoc) :
     879             :     ScMenuFloatingWindow(pParent, pDoc),
     880             :     maChecks(this, 0),
     881             :     maChkToggleAll(this, 0),
     882             :     maBtnSelectSingle  (this, 0),
     883             :     maBtnUnselectSingle(this, 0),
     884             :     maBtnOk(this),
     885             :     maBtnCancel(this),
     886             :     mnCurTabStop(0),
     887             :     mpExtendedData(NULL),
     888             :     mpOKAction(NULL),
     889             :     mpPopupEndAction(NULL),
     890             :     maWndSize(200, 330),
     891           0 :     mePrevToggleAllState(STATE_DONTKNOW)
     892             : {
     893           0 :     maTabStopCtrls.reserve(7);
     894           0 :     maTabStopCtrls.push_back(this);
     895           0 :     maTabStopCtrls.push_back(&maChecks);
     896           0 :     maTabStopCtrls.push_back(&maChkToggleAll);
     897           0 :     maTabStopCtrls.push_back(&maBtnSelectSingle);
     898           0 :     maTabStopCtrls.push_back(&maBtnUnselectSingle);
     899           0 :     maTabStopCtrls.push_back(&maBtnOk);
     900           0 :     maTabStopCtrls.push_back(&maBtnCancel);
     901             : 
     902             :     // Enable type-ahead search in the check list box.
     903           0 :     maChecks.SetStyle(maChecks.GetStyle() | WB_QUICK_SEARCH);
     904           0 : }
     905             : 
     906           0 : ScCheckListMenuWindow::~ScCheckListMenuWindow()
     907             : {
     908           0 : }
     909             : 
     910           0 : void ScCheckListMenuWindow::getSectionPosSize(
     911             :     Point& rPos, Size& rSize, SectionType eType) const
     912             : {
     913             :     // constant parameters.
     914           0 :     const long nListBoxMargin = 5;            // horizontal distance from the side of the dialog to the listbox border.
     915           0 :     const long nListBoxInnerPadding = 5;
     916           0 :     const long nTopMargin = 5;
     917           0 :     const long nMenuHeight = maMenuSize.getHeight();
     918           0 :     const long nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
     919           0 :     const long nBottomBtnAreaHeight = 50;     // height of the bottom area where the OK and Cancel buttons are.
     920           0 :     const long nBtnWidth = 90;
     921           0 :     const long nLabelHeight = getLabelFont().GetHeight();
     922           0 :     const long nBtnHeight = nLabelHeight*2;
     923           0 :     const long nBottomMargin = 10;
     924           0 :     const long nMenuListMargin = 5;
     925             : 
     926             :     // parameters calculated from constants.
     927           0 :     const long nListBoxWidth = maWndSize.Width() - nListBoxMargin*2;
     928           0 :     const long nListBoxHeight = maWndSize.Height() - nTopMargin - nMenuHeight -
     929           0 :         nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight;
     930             : 
     931           0 :     const long nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
     932             : 
     933           0 :     switch (eType)
     934             :     {
     935             :         case WHOLE:
     936             :         {
     937           0 :             rPos  = Point(0, 0);
     938           0 :             rSize = maWndSize;
     939             :         }
     940           0 :         break;
     941             :         case LISTBOX_AREA_OUTER:
     942             :         {
     943           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
     944           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     945             :         }
     946           0 :         break;
     947             :         case LISTBOX_AREA_INNER:
     948             :         {
     949           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
     950           0 :             rPos.X() += nListBoxInnerPadding;
     951           0 :             rPos.Y() += nListBoxInnerPadding;
     952             : 
     953           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     954           0 :             rSize.Width()  -= nListBoxInnerPadding*2;
     955           0 :             rSize.Height() -= nListBoxInnerPadding*2;
     956             :         }
     957           0 :         break;
     958             :         case SINGLE_BTN_AREA:
     959             :         {
     960           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     961           0 :             rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
     962             :         }
     963           0 :         break;
     964             :         case CHECK_TOGGLE_ALL:
     965             :         {
     966           0 :             long h = nLabelHeight*3/2; // check box height is heuristically 150% of the text height.
     967           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     968           0 :             rPos.X() += 5;
     969           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     970           0 :             rSize = Size(70, h);
     971             :         }
     972           0 :         break;
     973             :         case BTN_SINGLE_SELECT:
     974             :         {
     975           0 :             long h = 26;
     976           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     977           0 :             rPos.X() += nListBoxWidth - h - 10 - h - 10;
     978           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     979           0 :             rSize = Size(h, h);
     980             :         }
     981           0 :         break;
     982             :         case BTN_SINGLE_UNSELECT:
     983             :         {
     984           0 :             long h = 26;
     985           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     986           0 :             rPos.X() += nListBoxWidth - h - 10;
     987           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     988           0 :             rSize = Size(h, h);
     989             :         }
     990           0 :         break;
     991             :         case BTN_OK:
     992             :         {
     993           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3;
     994           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
     995           0 :             rPos = Point(x, y);
     996           0 :             rSize = Size(nBtnWidth, nBtnHeight);
     997             :         }
     998           0 :         break;
     999             :         case BTN_CANCEL:
    1000             :         {
    1001           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
    1002           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
    1003           0 :             rPos = Point(x, y);
    1004           0 :             rSize = Size(nBtnWidth, nBtnHeight);
    1005             :         }
    1006           0 :         break;
    1007             :         default:
    1008             :             ;
    1009             :     }
    1010           0 : }
    1011             : 
    1012           0 : void ScCheckListMenuWindow::packWindow()
    1013             : {
    1014           0 :     maMenuSize = getMenuSize();
    1015             : 
    1016           0 :     if (maWndSize.Width() < maMenuSize.Width())
    1017             :         // Widen the window to fit the menu items.
    1018           0 :         maWndSize.Width() = maMenuSize.Width();
    1019             : 
    1020             :     // Set proper window height based on the number of menu items.
    1021           0 :     if (maWndSize.Height() < maMenuSize.Height()*2.8)
    1022           0 :         maWndSize.Height() = maMenuSize.Height()*2.8;
    1023             : 
    1024             :     // TODO: Make sure the window height never exceeds the height of the
    1025             :     // screen. Also do adjustment based on the number of check box items.
    1026             : 
    1027           0 :     SetOutputSizePixel(maWndSize);
    1028             : 
    1029           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1030             : 
    1031           0 :     Point aPos;
    1032           0 :     Size aSize;
    1033           0 :     getSectionPosSize(aPos, aSize, WHOLE);
    1034           0 :     SetOutputSizePixel(aSize);
    1035             : 
    1036           0 :     getSectionPosSize(aPos, aSize, BTN_OK);
    1037           0 :     maBtnOk.SetPosSizePixel(aPos, aSize);
    1038           0 :     maBtnOk.SetFont(getLabelFont());
    1039           0 :     maBtnOk.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1040           0 :     maBtnOk.Show();
    1041             : 
    1042           0 :     getSectionPosSize(aPos, aSize, BTN_CANCEL);
    1043           0 :     maBtnCancel.SetPosSizePixel(aPos, aSize);
    1044           0 :     maBtnCancel.SetFont(getLabelFont());
    1045           0 :     maBtnCancel.Show();
    1046             : 
    1047           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER);
    1048           0 :     maChecks.SetPosSizePixel(aPos, aSize);
    1049           0 :     maChecks.SetFont(getLabelFont());
    1050           0 :     maChecks.SetCheckButtonHdl( LINK(this, ScCheckListMenuWindow, CheckHdl) );
    1051           0 :     maChecks.Show();
    1052             : 
    1053           0 :     getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL);
    1054           0 :     maChkToggleAll.SetPosSizePixel(aPos, aSize);
    1055           0 :     maChkToggleAll.SetFont(getLabelFont());
    1056           0 :     maChkToggleAll.SetText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
    1057           0 :     maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor());
    1058           0 :     maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
    1059           0 :     maChkToggleAll.SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) );
    1060           0 :     maChkToggleAll.Show();
    1061             : 
    1062           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
    1063           0 :     maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
    1064           0 :     maBtnSelectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT).GetString());
    1065           0 :     maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)));
    1066           0 :     maBtnSelectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1067           0 :     maBtnSelectSingle.Show();
    1068             : 
    1069           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
    1070           0 :     maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
    1071           0 :     maBtnUnselectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT).GetString());
    1072           0 :     maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)));
    1073           0 :     maBtnUnselectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1074           0 :     maBtnUnselectSingle.Show();
    1075           0 : }
    1076             : 
    1077           0 : void ScCheckListMenuWindow::setAllMemberState(bool bSet)
    1078             : {
    1079           0 :     size_t n = maMembers.size();
    1080           0 :     for (size_t i = 0; i < n; ++i)
    1081           0 :         maChecks.CheckEntryPos(static_cast<sal_uInt16>(i), bSet);
    1082             : 
    1083           0 :     if (!maConfig.mbAllowEmptySet)
    1084             :         // We need to have at least one member selected.
    1085           0 :         maBtnOk.Enable(maChecks.GetCheckedEntryCount() != 0);
    1086           0 : }
    1087             : 
    1088           0 : void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
    1089             : {
    1090           0 :     setAllMemberState(!bSet);
    1091           0 :     sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
    1092           0 :     maChecks.CheckEntryPos(nSelected, bSet);
    1093           0 : }
    1094             : 
    1095           0 : void ScCheckListMenuWindow::cycleFocus(bool bReverse)
    1096             : {
    1097           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
    1098           0 :     maTabStopCtrls[mnCurTabStop]->LoseFocus();
    1099           0 :     if (mnCurTabStop == 0)
    1100           0 :         clearSelectedMenuItem();
    1101             : 
    1102           0 :     if (bReverse)
    1103             :     {
    1104           0 :         if (mnCurTabStop > 0)
    1105           0 :             --mnCurTabStop;
    1106             :         else
    1107           0 :             mnCurTabStop = maTabStopCtrls.size() - 1;
    1108             :     }
    1109             :     else
    1110             :     {
    1111           0 :         ++mnCurTabStop;
    1112           0 :         if (mnCurTabStop >= maTabStopCtrls.size())
    1113           0 :             mnCurTabStop = 0;
    1114             :     }
    1115           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
    1116           0 :     maTabStopCtrls[mnCurTabStop]->GrabFocus();
    1117           0 : }
    1118             : 
    1119           0 : IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn )
    1120             : {
    1121           0 :     if (pBtn == &maBtnOk)
    1122           0 :         close(true);
    1123           0 :     else if (pBtn == &maBtnSelectSingle)
    1124             :     {
    1125           0 :         selectCurrentMemberOnly(true);
    1126           0 :         CheckHdl(&maChecks);
    1127             :     }
    1128           0 :     else if (pBtn == &maBtnUnselectSingle)
    1129             :     {
    1130           0 :         selectCurrentMemberOnly(false);
    1131           0 :         CheckHdl(&maChecks);
    1132             :     }
    1133           0 :     return 0;
    1134             : }
    1135             : 
    1136           0 : IMPL_LINK_NOARG(ScCheckListMenuWindow, TriStateHdl)
    1137             : {
    1138           0 :     switch (mePrevToggleAllState)
    1139             :     {
    1140             :         case STATE_NOCHECK:
    1141           0 :             maChkToggleAll.SetState(STATE_CHECK);
    1142           0 :             setAllMemberState(true);
    1143           0 :         break;
    1144             :         case STATE_CHECK:
    1145           0 :             maChkToggleAll.SetState(STATE_NOCHECK);
    1146           0 :             setAllMemberState(false);
    1147           0 :         break;
    1148             :         case STATE_DONTKNOW:
    1149             :         default:
    1150           0 :             maChkToggleAll.SetState(STATE_CHECK);
    1151           0 :             setAllMemberState(true);
    1152           0 :         break;
    1153             :     }
    1154             : 
    1155           0 :     mePrevToggleAllState = maChkToggleAll.GetState();
    1156           0 :     return 0;
    1157             : }
    1158             : 
    1159           0 : IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
    1160             : {
    1161           0 :     if (pChecks != &maChecks)
    1162           0 :         return 0;
    1163             : 
    1164           0 :     size_t nNumChecked = maChecks.GetCheckedEntryCount();
    1165           0 :     if (nNumChecked == maMembers.size())
    1166             :         // all members visible
    1167           0 :         maChkToggleAll.SetState(STATE_CHECK);
    1168           0 :     else if (nNumChecked == 0)
    1169             :         // no members visible
    1170           0 :         maChkToggleAll.SetState(STATE_NOCHECK);
    1171             :     else
    1172           0 :         maChkToggleAll.SetState(STATE_DONTKNOW);
    1173             : 
    1174           0 :     if (!maConfig.mbAllowEmptySet)
    1175             :         // We need to have at least one member selected.
    1176           0 :         maBtnOk.Enable(nNumChecked != 0);
    1177             : 
    1178           0 :     mePrevToggleAllState = maChkToggleAll.GetState();
    1179           0 :     return 0;
    1180             : }
    1181             : 
    1182           0 : void ScCheckListMenuWindow::MouseMove(const MouseEvent& rMEvt)
    1183             : {
    1184           0 :     ScMenuFloatingWindow::MouseMove(rMEvt);
    1185             : 
    1186           0 :     size_t nSelectedMenu = getSelectedMenuItem();
    1187           0 :     if (nSelectedMenu == MENU_NOT_SELECTED)
    1188           0 :         queueCloseSubMenu();
    1189           0 : }
    1190             : 
    1191           0 : long ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
    1192             : {
    1193           0 :     switch (rNEvt.GetType())
    1194             :     {
    1195             :         case EVENT_KEYUP:
    1196             :         {
    1197           0 :             const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
    1198           0 :             const KeyCode& rCode = pKeyEvent->GetKeyCode();
    1199           0 :             bool bShift = rCode.IsShift();
    1200           0 :             if (rCode.GetCode() == KEY_TAB)
    1201             :             {
    1202           0 :                 cycleFocus(bShift);
    1203           0 :                 return true;
    1204             :             }
    1205             :         }
    1206           0 :         break;
    1207             :     }
    1208           0 :     return ScMenuFloatingWindow::Notify(rNEvt);
    1209             : }
    1210             : 
    1211           0 : void ScCheckListMenuWindow::Paint(const Rectangle& rRect)
    1212             : {
    1213           0 :     ScMenuFloatingWindow::Paint(rRect);
    1214             : 
    1215           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1216           0 :     Color aMemberBackColor = rStyle.GetFieldColor();
    1217           0 :     Color aBorderColor = rStyle.GetShadowColor();
    1218             : 
    1219           0 :     Point aPos;
    1220           0 :     Size aSize;
    1221           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
    1222             : 
    1223             :     // Member list box background
    1224           0 :     SetFillColor(aMemberBackColor);
    1225           0 :     SetLineColor(aBorderColor);
    1226           0 :     DrawRect(Rectangle(aPos,aSize));
    1227             : 
    1228             :     // Single-action button box
    1229           0 :     getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
    1230           0 :     SetFillColor(rStyle.GetMenuColor());
    1231           0 :     DrawRect(Rectangle(aPos,aSize));
    1232           0 : }
    1233             : 
    1234           0 : Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
    1235             : {
    1236           0 :     return maTabStopCtrls[mnCurTabStop];
    1237             : }
    1238             : 
    1239           0 : Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
    1240             : {
    1241           0 :     if (!mxAccessible.is())
    1242             :     {
    1243             :         mxAccessible.set(new ScAccessibleFilterTopWindow(
    1244           0 :             GetAccessibleParentWindow()->GetAccessible(), this, getName()));
    1245           0 :         ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
    1246           0 :         fillMenuItemsToAccessible(pAccTop);
    1247             : 
    1248             :         pAccTop->setAccessibleChild(
    1249           0 :             maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
    1250             :         pAccTop->setAccessibleChild(
    1251           0 :             maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
    1252             :         pAccTop->setAccessibleChild(
    1253           0 :             maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
    1254             :         pAccTop->setAccessibleChild(
    1255           0 :             maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
    1256             :         pAccTop->setAccessibleChild(
    1257           0 :             maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
    1258             :         pAccTop->setAccessibleChild(
    1259           0 :             maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
    1260             :     }
    1261             : 
    1262           0 :     return mxAccessible;
    1263             : }
    1264             : 
    1265           0 : void ScCheckListMenuWindow::setMemberSize(size_t n)
    1266             : {
    1267           0 :     maMembers.reserve(n);
    1268           0 : }
    1269             : 
    1270           0 : void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
    1271             : {
    1272           0 :     Member aMember;
    1273           0 :     aMember.maName = rName;
    1274           0 :     aMember.mbVisible = bVisible;
    1275           0 :     maMembers.push_back(aMember);
    1276           0 : }
    1277             : 
    1278           0 : void ScCheckListMenuWindow::initMembers()
    1279             : {
    1280           0 :     size_t n = maMembers.size();
    1281           0 :     size_t nVisMemCount = 0;
    1282           0 :     maChecks.SetUpdateMode(false);
    1283           0 :     for (size_t i = 0; i < n; ++i)
    1284             :     {
    1285           0 :         maChecks.InsertEntry(maMembers[i].maName);
    1286           0 :         maChecks.CheckEntryPos(static_cast< sal_uInt16 >( i ), maMembers[i].mbVisible);
    1287           0 :         if (maMembers[i].mbVisible)
    1288           0 :             ++nVisMemCount;
    1289             :     }
    1290           0 :     if (nVisMemCount == n)
    1291             :     {
    1292             :         // all members visible
    1293           0 :         maChkToggleAll.SetState(STATE_CHECK);
    1294           0 :         mePrevToggleAllState = STATE_CHECK;
    1295             :     }
    1296           0 :     else if (nVisMemCount == 0)
    1297             :     {
    1298             :         // no members visible
    1299           0 :         maChkToggleAll.SetState(STATE_NOCHECK);
    1300           0 :         mePrevToggleAllState = STATE_NOCHECK;
    1301             :     }
    1302             :     else
    1303             :     {
    1304           0 :         maChkToggleAll.SetState(STATE_DONTKNOW);
    1305           0 :         mePrevToggleAllState = STATE_DONTKNOW;
    1306             :     }
    1307           0 :     maChecks.SetUpdateMode(true);
    1308           0 : }
    1309             : 
    1310           0 : void ScCheckListMenuWindow::setConfig(const Config& rConfig)
    1311             : {
    1312           0 :     maConfig = rConfig;
    1313           0 : }
    1314             : 
    1315           0 : bool ScCheckListMenuWindow::isAllSelected() const
    1316             : {
    1317           0 :     return maChkToggleAll.IsChecked();
    1318             : }
    1319             : 
    1320           0 : void ScCheckListMenuWindow::getResult(ResultType& rResult)
    1321             : {
    1322           0 :     ResultType aResult;
    1323           0 :     size_t n = maMembers.size();
    1324           0 :     for (size_t i = 0; i < n; ++i)
    1325             :     {
    1326           0 :         bool bState = maChecks.IsChecked(static_cast< sal_uInt16 >( i ));
    1327           0 :         aResult.insert(ResultType::value_type(maMembers[i].maName, bState));
    1328             :     }
    1329           0 :     rResult.swap(aResult);
    1330           0 : }
    1331             : 
    1332           0 : void ScCheckListMenuWindow::launch(const Rectangle& rRect)
    1333             : {
    1334           0 :     packWindow();
    1335           0 :     if (!maConfig.mbAllowEmptySet)
    1336             :         // We need to have at least one member selected.
    1337           0 :         maBtnOk.Enable(maChecks.GetCheckedEntryCount() != 0);
    1338             : 
    1339           0 :     Rectangle aRect(rRect);
    1340           0 :     if (maConfig.mbRTL)
    1341             :     {
    1342             :         // In RTL mode, the logical "left" is visual "right".
    1343           0 :         long nLeft = aRect.Left() - aRect.GetWidth();
    1344           0 :         aRect.Left() = nLeft;
    1345             :     }
    1346           0 :     else if (maWndSize.Width() < aRect.GetWidth())
    1347             :     {
    1348             :         // Target rectangle (i.e. cell width) is wider than the window.
    1349             :         // Simulate right-aligned launch by modifying the target rectangle
    1350             :         // size.
    1351           0 :         long nDiff = aRect.GetWidth() - maWndSize.Width();
    1352           0 :         aRect.Left() += nDiff;
    1353             :     }
    1354             : 
    1355           0 :     StartPopupMode(aRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
    1356           0 :     cycleFocus(); // Set initial focus to the check list box.
    1357           0 : }
    1358             : 
    1359           0 : void ScCheckListMenuWindow::close(bool bOK)
    1360             : {
    1361           0 :     if (bOK && mpOKAction.get())
    1362           0 :         mpOKAction->execute();
    1363             : 
    1364           0 :     EndPopupMode();
    1365           0 : }
    1366             : 
    1367           0 : void ScCheckListMenuWindow::setExtendedData(ExtendedData* p)
    1368             : {
    1369           0 :     mpExtendedData.reset(p);
    1370           0 : }
    1371             : 
    1372           0 : ScCheckListMenuWindow::ExtendedData* ScCheckListMenuWindow::getExtendedData()
    1373             : {
    1374           0 :     return mpExtendedData.get();
    1375             : }
    1376             : 
    1377           0 : void ScCheckListMenuWindow::setOKAction(Action* p)
    1378             : {
    1379           0 :     mpOKAction.reset(p);
    1380           0 : }
    1381             : 
    1382           0 : void ScCheckListMenuWindow::setPopupEndAction(Action* p)
    1383             : {
    1384           0 :     mpPopupEndAction.reset(p);
    1385           0 : }
    1386             : 
    1387           0 : void ScCheckListMenuWindow::handlePopupEnd()
    1388             : {
    1389           0 :     clearSelectedMenuItem();
    1390           0 :     if (mpPopupEndAction)
    1391           0 :         mpPopupEndAction->execute();
    1392          93 : }
    1393             : 
    1394             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10