LCOV - code coverage report
Current view: top level - sc/source/ui/cctrl - checklistmenu.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 927 0.1 %
Date: 2014-11-03 Functions: 2 96 2.1 %
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 <vcl/settings.hxx>
      26             : #include <tools/wintypes.hxx>
      27             : 
      28             : #include "AccessibleFilterMenu.hxx"
      29             : #include "AccessibleFilterTopWindow.hxx"
      30             : 
      31             : #include <com/sun/star/accessibility/XAccessible.hpp>
      32             : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
      33             : #include <svtools/fmtfield.hxx>
      34             : #include "document.hxx"
      35             : 
      36             : using namespace com::sun::star;
      37             : using ::com::sun::star::uno::Reference;
      38             : using ::com::sun::star::accessibility::XAccessible;
      39             : using ::com::sun::star::accessibility::XAccessibleContext;
      40             : using ::std::vector;
      41             : using ::boost::unordered_map;
      42             : 
      43           0 : ScMenuFloatingWindow::MenuItemData::MenuItemData() :
      44             :     mbEnabled(true), mbSeparator(false),
      45             :     mpAction(static_cast<ScCheckListMenuWindow::Action*>(NULL)),
      46           0 :     mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
      47             : {
      48           0 : }
      49             : 
      50           0 : ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
      51             :     mpSubMenu(NULL),
      52             :     mnMenuPos(MENU_NOT_SELECTED),
      53           0 :     mpParent(pParent)
      54             : {
      55           0 :     maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
      56           0 :     maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
      57           0 : }
      58             : 
      59           0 : void ScMenuFloatingWindow::SubMenuItemData::reset()
      60             : {
      61           0 :     mpSubMenu = NULL;
      62           0 :     mnMenuPos = MENU_NOT_SELECTED;
      63           0 :     maTimer.Stop();
      64           0 : }
      65             : 
      66           0 : IMPL_LINK_NOARG(ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl)
      67             : {
      68           0 :     mpParent->handleMenuTimeout(this);
      69           0 :     return 0;
      70             : }
      71             : 
      72             : size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
      73             : 
      74           0 : ScMenuFloatingWindow::ScMenuFloatingWindow(vcl::Window* pParent, ScDocument* pDoc, sal_uInt16 nMenuStackLevel) :
      75             :     PopupMenuFloatingWindow(pParent),
      76             :     maOpenTimer(this),
      77             :     maCloseTimer(this),
      78             :     maName("ScMenuFloatingWindow"),
      79             :     mnSelectedMenu(MENU_NOT_SELECTED),
      80             :     mnClickedMenu(MENU_NOT_SELECTED),
      81             :     mpDoc(pDoc),
      82           0 :     mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent))
      83             : {
      84           0 :     SetMenuStackLevel(nMenuStackLevel);
      85             : 
      86             :     // TODO: How do we get the right font to use here ?
      87           0 :     const sal_uInt16 nPopupFontHeight = 12;
      88           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
      89           0 :     maLabelFont = rStyle.GetLabelFont();
      90           0 :     maLabelFont.SetHeight(nPopupFontHeight);
      91           0 :     SetFont(maLabelFont);
      92             : 
      93           0 :     SetText( OUString("ScMenuFloatingWindow") );
      94           0 : }
      95             : 
      96           0 : ScMenuFloatingWindow::~ScMenuFloatingWindow()
      97             : {
      98           0 :     EndPopupMode();
      99           0 : }
     100             : 
     101           0 : void ScMenuFloatingWindow::PopupModeEnd()
     102             : {
     103           0 :     handlePopupEnd();
     104           0 : }
     105             : 
     106           0 : void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
     107             : {
     108           0 :     const Point& rPos = rMEvt.GetPosPixel();
     109           0 :     size_t nSelectedMenu = getEnclosingMenuItem(rPos);
     110           0 :     setSelectedMenuItem(nSelectedMenu, true, false);
     111             : 
     112           0 :     Window::MouseMove(rMEvt);
     113           0 : }
     114             : 
     115           0 : void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
     116             : {
     117           0 :     const Point& rPos = rMEvt.GetPosPixel();
     118           0 :     mnClickedMenu = getEnclosingMenuItem(rPos);
     119           0 :     Window::MouseButtonDown(rMEvt);
     120           0 : }
     121             : 
     122           0 : void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
     123             : {
     124           0 :     executeMenuItem(mnClickedMenu);
     125           0 :     mnClickedMenu = MENU_NOT_SELECTED;
     126           0 :     Window::MouseButtonUp(rMEvt);
     127           0 : }
     128             : 
     129           0 : void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
     130             : {
     131           0 :     if (maMenuItems.empty())
     132             :     {
     133           0 :         Window::KeyInput(rKEvt);
     134           0 :         return;
     135             :     }
     136             : 
     137           0 :     const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
     138           0 :     bool bHandled = true;
     139           0 :     size_t nSelectedMenu = mnSelectedMenu;
     140           0 :     size_t nLastMenuPos = maMenuItems.size() - 1;
     141           0 :     switch (rKeyCode.GetCode())
     142             :     {
     143             :         case KEY_UP:
     144             :         {
     145           0 :             if (nLastMenuPos == 0)
     146             :                 // There is only one menu item.  Do nothing.
     147           0 :                 break;
     148             : 
     149           0 :             size_t nOldPos = nSelectedMenu;
     150             : 
     151           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
     152           0 :                 nSelectedMenu = nLastMenuPos;
     153             :             else
     154           0 :                 --nSelectedMenu;
     155             : 
     156             :             // Loop until a non-separator menu item is found.
     157           0 :             while (nSelectedMenu != nOldPos)
     158             :             {
     159           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     160             :                 {
     161           0 :                     if (nSelectedMenu)
     162           0 :                         --nSelectedMenu;
     163             :                     else
     164           0 :                         nSelectedMenu = nLastMenuPos;
     165             :                 }
     166             :                 else
     167           0 :                     break;
     168             :             }
     169             : 
     170           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     171             :         }
     172           0 :         break;
     173             :         case KEY_DOWN:
     174             :         {
     175           0 :             if (nLastMenuPos == 0)
     176             :                 // There is only one menu item.  Do nothing.
     177           0 :                 break;
     178             : 
     179           0 :             size_t nOldPos = nSelectedMenu;
     180             : 
     181           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
     182           0 :                 nSelectedMenu = 0;
     183             :             else
     184           0 :                 ++nSelectedMenu;
     185             : 
     186             :             // Loop until a non-separator menu item is found.
     187           0 :             while (nSelectedMenu != nOldPos)
     188             :             {
     189           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     190             :                 {
     191           0 :                     if (nSelectedMenu == nLastMenuPos)
     192           0 :                         nSelectedMenu = 0;
     193             :                     else
     194           0 :                         ++nSelectedMenu;
     195             :                 }
     196             :                 else
     197           0 :                     break;
     198             :             }
     199             : 
     200           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     201             :         }
     202           0 :         break;
     203             :         case KEY_LEFT:
     204           0 :             if (mpParentMenu)
     205           0 :                 mpParentMenu->endSubMenu(this);
     206           0 :         break;
     207             :         case KEY_RIGHT:
     208             :         {
     209           0 :             if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
     210           0 :                 break;
     211             : 
     212           0 :             const MenuItemData& rMenu = maMenuItems[mnSelectedMenu];
     213           0 :             if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
     214           0 :                 break;
     215             : 
     216           0 :             maOpenTimer.mnMenuPos = mnSelectedMenu;
     217           0 :             maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
     218           0 :             launchSubMenu(true);
     219             :         }
     220           0 :         break;
     221             :         case KEY_RETURN:
     222           0 :             if (nSelectedMenu != MENU_NOT_SELECTED)
     223           0 :                 executeMenuItem(nSelectedMenu);
     224           0 :         break;
     225             :         default:
     226           0 :             bHandled = false;
     227             :     }
     228             : 
     229           0 :     if (!bHandled)
     230           0 :         Window::KeyInput(rKEvt);
     231             : }
     232             : 
     233           0 : void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
     234             : {
     235           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     236           0 :     Color aBackColor = rStyle.GetMenuColor();
     237           0 :     Color aBorderColor = rStyle.GetShadowColor();
     238             : 
     239           0 :     Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
     240             : 
     241             :     // Window background
     242           0 :     bool bNativeDrawn = true;
     243           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     244             :     {
     245           0 :         SetClipRegion();
     246             :         bNativeDrawn = DrawNativeControl(
     247             :             CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
     248           0 :             ImplControlValue(), OUString());
     249             :     }
     250             :     else
     251           0 :         bNativeDrawn = false;
     252             : 
     253           0 :     if (!bNativeDrawn)
     254             :     {
     255           0 :         SetFillColor(aBackColor);
     256           0 :         SetLineColor(aBorderColor);
     257           0 :         DrawRect(aCtrlRect);
     258             :     }
     259             : 
     260             :     // Menu items
     261           0 :     SetTextColor(rStyle.GetMenuTextColor());
     262           0 :     drawAllMenuItems();
     263           0 : }
     264             : 
     265           0 : Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
     266             : {
     267           0 :     if (!mxAccessible.is())
     268             :     {
     269             :         Reference<XAccessible> xAccParent = mpParentMenu ?
     270           0 :             mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
     271             : 
     272           0 :         mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999));
     273             :         ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
     274           0 :             mxAccessible.get());
     275             : 
     276           0 :         vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
     277           0 :         for (itr = itrBeg; itr != itrEnd; ++itr)
     278             :         {
     279           0 :             size_t nPos = ::std::distance(itrBeg, itr);
     280           0 :             p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
     281           0 :         }
     282             :     }
     283             : 
     284           0 :     return mxAccessible;
     285             : }
     286             : 
     287           0 : void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
     288             : {
     289           0 :     MenuItemData aItem;
     290           0 :     aItem.maText = rText;
     291           0 :     aItem.mbEnabled = bEnabled;
     292           0 :     aItem.mpAction.reset(pAction);
     293           0 :     maMenuItems.push_back(aItem);
     294           0 : }
     295             : 
     296           0 : void ScMenuFloatingWindow::addSeparator()
     297             : {
     298           0 :     MenuItemData aItem;
     299           0 :     aItem.mbSeparator = true;
     300           0 :     maMenuItems.push_back(aItem);
     301           0 : }
     302             : 
     303           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
     304             : {
     305           0 :     MenuItemData aItem;
     306           0 :     aItem.maText = rText;
     307           0 :     aItem.mbEnabled = bEnabled;
     308           0 :     aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
     309           0 :     aItem.mpSubMenuWin->setName(rText);
     310           0 :     maMenuItems.push_back(aItem);
     311           0 :     return aItem.mpSubMenuWin.get();
     312             : }
     313             : 
     314           0 : void ScMenuFloatingWindow::handlePopupEnd()
     315             : {
     316           0 :     clearSelectedMenuItem();
     317           0 : }
     318             : 
     319           0 : Size ScMenuFloatingWindow::getMenuSize() const
     320             : {
     321           0 :     if (maMenuItems.empty())
     322           0 :         return Size();
     323             : 
     324           0 :     vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
     325           0 :     long nTextWidth = 0;
     326           0 :     for (; itr != itrEnd; ++itr)
     327             :     {
     328           0 :         if (itr->mbSeparator)
     329           0 :             continue;
     330             : 
     331           0 :         nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
     332             :     }
     333             : 
     334           0 :     size_t nLastPos = maMenuItems.size()-1;
     335           0 :     Point aPos;
     336           0 :     Size aSize;
     337           0 :     getMenuItemPosSize(nLastPos, aPos, aSize);
     338           0 :     aPos.X() += nTextWidth + 15;
     339           0 :     aPos.Y() += aSize.Height() + 5;
     340           0 :     return Size(aPos.X(), aPos.Y());
     341             : }
     342             : 
     343           0 : void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
     344             : {
     345           0 :     if (nPos >= maMenuItems.size())
     346           0 :         return;
     347             : 
     348           0 :     Point aPos;
     349           0 :     Size aSize;
     350           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     351             : 
     352           0 :     DecorationView aDecoView(this);
     353           0 :     long nXOffset = 5;
     354           0 :     long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
     355           0 :     DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0,
     356           0 :                  maMenuItems[nPos].maText.getLength(),
     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 :                              SymbolType::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(PushFlags::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 : void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
     432             : {
     433           0 :     if (nPos >= maMenuItems.size())
     434           0 :         return;
     435             : 
     436           0 :     if (!maMenuItems[nPos].mpAction)
     437             :         // no action is defined.
     438           0 :         return;
     439             : 
     440           0 :     maMenuItems[nPos].mpAction->execute();
     441           0 :     terminateAllPopupMenus();
     442             : }
     443             : 
     444           0 : void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
     445             : {
     446           0 :     if (mnSelectedMenu == nPos)
     447             :         // nothing to do.
     448           0 :         return;
     449             : 
     450           0 :     if (bEnsureSubMenu)
     451             :     {
     452             :         // Dismiss any child popup menu windows.
     453           0 :         if (mnSelectedMenu < maMenuItems.size() &&
     454           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     455           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     456             :         {
     457           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     458             :         }
     459             : 
     460             :         // The popup is not visible, yet a menu item is selected.  The request
     461             :         // most likely comes from the accessible object.  Make sure this
     462             :         // window, as well as all its parent windows are visible.
     463           0 :         if (!IsVisible() && mpParentMenu)
     464           0 :             mpParentMenu->ensureSubMenuVisible(this);
     465             :     }
     466             : 
     467           0 :     selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
     468           0 :     selectMenuItem(nPos, true, bSubMenuTimer);
     469           0 :     mnSelectedMenu = nPos;
     470             : 
     471           0 :     fireMenuHighlightedEvent();
     472             : }
     473             : 
     474           0 : void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* pTimer)
     475             : {
     476           0 :     if (pTimer == &maOpenTimer)
     477             :     {
     478             :         // Close any open submenu immediately.
     479           0 :         if (maCloseTimer.mpSubMenu)
     480             :         {
     481           0 :             maCloseTimer.mpSubMenu->EndPopupMode();
     482           0 :             maCloseTimer.mpSubMenu = NULL;
     483           0 :             maCloseTimer.maTimer.Stop();
     484             :         }
     485             : 
     486           0 :         launchSubMenu(false);
     487             :     }
     488           0 :     else if (pTimer == &maCloseTimer)
     489             :     {
     490             :         // end submenu.
     491           0 :         if (maCloseTimer.mpSubMenu)
     492             :         {
     493           0 :             maOpenTimer.mpSubMenu = NULL;
     494             : 
     495           0 :             maCloseTimer.mpSubMenu->EndPopupMode();
     496           0 :             maCloseTimer.mpSubMenu = NULL;
     497             : 
     498           0 :             highlightMenuItem(maOpenTimer.mnMenuPos, false);
     499           0 :             maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
     500             :         }
     501             :     }
     502           0 : }
     503             : 
     504           0 : void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
     505             : {
     506           0 :     if (!pMenu)
     507           0 :         return;
     508             : 
     509             :     // Set the submenu on launch queue.
     510           0 :     if (maOpenTimer.mpSubMenu)
     511             :     {
     512           0 :         if (maOpenTimer.mpSubMenu == pMenu)
     513             :         {
     514           0 :             if (pMenu == maCloseTimer.mpSubMenu)
     515           0 :                 maCloseTimer.reset();
     516           0 :             return;
     517             :         }
     518             : 
     519             :         // new submenu is being requested.
     520           0 :         queueCloseSubMenu();
     521             :     }
     522             : 
     523           0 :     maOpenTimer.mpSubMenu = pMenu;
     524           0 :     maOpenTimer.mnMenuPos = nPos;
     525           0 :     maOpenTimer.maTimer.Start();
     526             : }
     527             : 
     528           0 : void ScMenuFloatingWindow::queueCloseSubMenu()
     529             : {
     530           0 :     if (!maOpenTimer.mpSubMenu)
     531             :         // There is no submenu to close.
     532           0 :         return;
     533             : 
     534             :     // Stop any submenu on queue for opening.
     535           0 :     maOpenTimer.maTimer.Stop();
     536             : 
     537           0 :     maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
     538           0 :     maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
     539           0 :     maCloseTimer.maTimer.Start();
     540             : }
     541             : 
     542           0 : void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
     543             : {
     544           0 :     Point aPos;
     545           0 :     Size aSize;
     546           0 :     getMenuItemPosSize(maOpenTimer.mnMenuPos, aPos, aSize);
     547           0 :     ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
     548             : 
     549           0 :     if (!pSubMenu)
     550           0 :         return;
     551             : 
     552           0 :     sal_uInt32 nOldFlags = GetPopupModeFlags();
     553           0 :     SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
     554           0 :     pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
     555             :     pSubMenu->StartPopupMode(
     556           0 :         Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
     557           0 :     pSubMenu->AddPopupModeWindow(this);
     558           0 :     if (bSetMenuPos)
     559           0 :         pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
     560           0 :     SetPopupModeFlags(nOldFlags);
     561             : }
     562             : 
     563           0 : void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
     564             : {
     565           0 :     if (!pSubMenu)
     566           0 :         return;
     567             : 
     568           0 :     pSubMenu->EndPopupMode();
     569           0 :     maOpenTimer.reset();
     570             : 
     571           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     572           0 :     if (nMenuPos != MENU_NOT_SELECTED)
     573             :     {
     574           0 :         highlightMenuItem(nMenuPos, true);
     575           0 :         mnSelectedMenu = nMenuPos;
     576           0 :         fireMenuHighlightedEvent();
     577             :     }
     578             : }
     579             : 
     580           0 : void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
     581             : {
     582           0 :     vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
     583           0 :     for (itr = itrBeg; itr != itrEnd; ++itr)
     584             :     {
     585           0 :         size_t nPos = ::std::distance(itrBeg, itr);
     586           0 :         pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
     587             :     }
     588           0 : }
     589             : 
     590           0 : void ScMenuFloatingWindow::resizeToFitMenuItems()
     591             : {
     592           0 :     SetOutputSizePixel(getMenuSize());
     593           0 : }
     594             : 
     595           0 : void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
     596             : {
     597           0 :     if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
     598             :     {
     599           0 :         queueCloseSubMenu();
     600           0 :         return;
     601             :     }
     602             : 
     603           0 :     if (!maMenuItems[nPos].mbEnabled)
     604             :     {
     605           0 :         queueCloseSubMenu();
     606           0 :         return;
     607             :     }
     608             : 
     609           0 :     highlightMenuItem(nPos, bSelected);
     610             : 
     611           0 :     if (bSelected)
     612             :     {
     613           0 :         if (mpParentMenu)
     614           0 :             mpParentMenu->setSubMenuFocused(this);
     615             : 
     616           0 :         if (bSubMenuTimer)
     617             :         {
     618           0 :             if (maMenuItems[nPos].mpSubMenuWin)
     619             :             {
     620           0 :                 ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
     621           0 :                 queueLaunchSubMenu(nPos, pSubMenu);
     622             :             }
     623             :             else
     624           0 :                 queueCloseSubMenu();
     625             :         }
     626             :     }
     627             : }
     628             : 
     629           0 : void ScMenuFloatingWindow::clearSelectedMenuItem()
     630             : {
     631           0 :     selectMenuItem(mnSelectedMenu, false, false);
     632           0 :     mnSelectedMenu = MENU_NOT_SELECTED;
     633           0 : }
     634             : 
     635           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
     636             : {
     637           0 :     if (maMenuItems.size() <= nPos)
     638           0 :         return NULL;
     639             : 
     640           0 :     return maMenuItems[nPos].mpSubMenuWin.get();
     641             : }
     642             : 
     643           0 : bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
     644             : {
     645           0 :     return nPos == mnSelectedMenu;
     646             : }
     647             : 
     648           0 : void ScMenuFloatingWindow::setName(const OUString& rName)
     649             : {
     650           0 :     maName = rName;
     651           0 : }
     652             : 
     653           0 : void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
     654             : {
     655           0 :     if (nPos == MENU_NOT_SELECTED)
     656           0 :         return;
     657             : 
     658           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     659           0 :     Color aBackColor = rStyle.GetMenuColor();
     660           0 :     SetFillColor(aBackColor);
     661           0 :     SetLineColor(aBackColor);
     662             : 
     663           0 :     Point aPos;
     664           0 :     Size aSize;
     665           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     666           0 :     Rectangle aRegion(aPos,aSize);
     667             : 
     668           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     669             :     {
     670           0 :         Push(PushFlags::CLIPREGION);
     671           0 :         IntersectClipRegion(Rectangle(aPos, aSize));
     672           0 :         Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
     673             :         DrawNativeControl(
     674             :             CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED,
     675           0 :             ImplControlValue(), OUString());
     676             : 
     677           0 :         Pop();
     678             :     }
     679             : 
     680           0 :     bool bNativeDrawn = true;
     681           0 :     if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
     682             :     {
     683           0 :         ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
     684           0 :         if (maMenuItems[nPos].mbEnabled)
     685           0 :             nState |= CTRL_STATE_ENABLED;
     686             :         bNativeDrawn = DrawNativeControl(
     687           0 :             CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
     688             :     }
     689             :     else
     690           0 :         bNativeDrawn = false;
     691             : 
     692           0 :     if (!bNativeDrawn)
     693             :     {
     694           0 :         if (bSelected)
     695             :         {
     696           0 :             aBackColor = rStyle.GetMenuHighlightColor();
     697           0 :             SetFillColor(aBackColor);
     698           0 :             SetLineColor(aBackColor);
     699             :         }
     700           0 :         DrawRect(Rectangle(aPos,aSize));
     701             :     }
     702             : 
     703           0 :     Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
     704           0 :     SetTextColor(aTextColor);
     705           0 :     drawMenuItem(nPos);
     706             : }
     707             : 
     708           0 : void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
     709             : {
     710           0 :     size_t nCount = maMenuItems.size();
     711           0 :     if (nPos >= nCount)
     712           0 :         return;
     713             : 
     714           0 :     const sal_uInt16 nLeftMargin = 5;
     715           0 :     const sal_uInt16 nTopMargin = 5;
     716           0 :     const sal_uInt16 nMenuItemHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*1.8);
     717           0 :     const sal_uInt16 nSepHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*0.8);
     718             : 
     719           0 :     Point aPos1(nLeftMargin, nTopMargin);
     720           0 :     rPos = aPos1;
     721           0 :     for (size_t i = 0; i < nPos; ++i)
     722           0 :         rPos.Y() += maMenuItems[i].mbSeparator ? nSepHeight : nMenuItemHeight;
     723             : 
     724           0 :     Size aWndSize = GetSizePixel();
     725           0 :     sal_uInt16 nH = maMenuItems[nPos].mbSeparator ? nSepHeight : nMenuItemHeight;
     726           0 :     rSize = Size(aWndSize.Width() - nLeftMargin*2, nH);
     727             : }
     728             : 
     729           0 : size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
     730             : {
     731           0 :     size_t n = maMenuItems.size();
     732           0 :     for (size_t i = 0; i < n; ++i)
     733             :     {
     734           0 :         Point aPos;
     735           0 :         Size aSize;
     736           0 :         getMenuItemPosSize(i, aPos, aSize);
     737           0 :         Rectangle aRect(aPos, aSize);
     738           0 :         if (aRect.IsInside(rPos))
     739           0 :             return maMenuItems[i].mbSeparator ? MENU_NOT_SELECTED : i;
     740             :     }
     741           0 :     return MENU_NOT_SELECTED;
     742             : }
     743             : 
     744           0 : size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
     745             : {
     746           0 :     size_t n = maMenuItems.size();
     747           0 :     for (size_t i = 0; i < n; ++i)
     748             :     {
     749           0 :         if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu)
     750           0 :             return i;
     751             :     }
     752           0 :     return MENU_NOT_SELECTED;
     753             : }
     754             : 
     755           0 : void ScMenuFloatingWindow::fireMenuHighlightedEvent()
     756             : {
     757           0 :     if (mnSelectedMenu == MENU_NOT_SELECTED)
     758           0 :         return;
     759             : 
     760           0 :     if (!mxAccessible.is())
     761           0 :         return;
     762             : 
     763           0 :     Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext();
     764           0 :     if (!xAccCxt.is())
     765           0 :         return;
     766             : 
     767           0 :     Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu);
     768           0 :     if (!xAccMenu.is())
     769           0 :         return;
     770             : 
     771           0 :     VclAccessibleEvent aEvent(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
     772           0 :     FireVclEvent(&aEvent);
     773             : }
     774             : 
     775           0 : void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
     776             : {
     777           0 :     maCloseTimer.reset();
     778           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     779           0 :     if (mnSelectedMenu != nMenuPos)
     780             :     {
     781           0 :         highlightMenuItem(nMenuPos, true);
     782           0 :         mnSelectedMenu = nMenuPos;
     783             :     }
     784           0 : }
     785             : 
     786           0 : void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
     787             : {
     788           0 :     if (mpParentMenu)
     789           0 :         mpParentMenu->ensureSubMenuVisible(this);
     790             : 
     791           0 :     if (pSubMenu->IsVisible())
     792           0 :         return;
     793             : 
     794             :     // Find the menu position of the submenu.
     795           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     796           0 :     if (nMenuPos != MENU_NOT_SELECTED)
     797             :     {
     798           0 :         setSelectedMenuItem(nMenuPos, false, false);
     799             : 
     800           0 :         Point aPos;
     801           0 :         Size aSize;
     802           0 :         getMenuItemPosSize(nMenuPos, aPos, aSize);
     803             : 
     804           0 :         sal_uInt32 nOldFlags = GetPopupModeFlags();
     805           0 :         SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
     806           0 :         pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
     807             :         pSubMenu->StartPopupMode(
     808           0 :             Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
     809           0 :         pSubMenu->AddPopupModeWindow(this);
     810           0 :         SetPopupModeFlags(nOldFlags);
     811             :     }
     812             : }
     813             : 
     814           0 : void ScMenuFloatingWindow::ensureSubMenuNotVisible()
     815             : {
     816           0 :     if (mnSelectedMenu <= maMenuItems.size() &&
     817           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     818           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     819             :     {
     820           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     821             :     }
     822             : 
     823           0 :     EndPopupMode();
     824           0 : }
     825             : 
     826           0 : void ScMenuFloatingWindow::terminateAllPopupMenus()
     827             : {
     828           0 :     EndPopupMode();
     829           0 :     if (mpParentMenu)
     830           0 :         mpParentMenu->terminateAllPopupMenus();
     831           0 : }
     832             : 
     833           0 : ScCheckListMenuWindow::Config::Config() :
     834           0 :     mbAllowEmptySet(true), mbRTL(false)
     835             : {
     836           0 : }
     837             : 
     838           0 : ScCheckListMenuWindow::Member::Member()
     839             :     : mbVisible(true)
     840             :     , mbDate(false)
     841             :     , mbLeaf(false)
     842           0 :     , mpParent(NULL)
     843             : {
     844           0 : }
     845             : 
     846           0 : ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) :
     847           0 :     ::CancelButton(pParent), mpParent(pParent) {}
     848             : 
     849           0 : void ScCheckListMenuWindow::CancelButton::Click()
     850             : {
     851           0 :     mpParent->EndPopupMode();
     852           0 :     ::CancelButton::Click();
     853           0 : }
     854             : 
     855           0 : ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc) :
     856             :     ScMenuFloatingWindow(pParent, pDoc),
     857             :     maChecks(this,  WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT ),
     858             :     maChkToggleAll(this, 0),
     859             :     maBtnSelectSingle  (this, 0),
     860             :     maBtnUnselectSingle(this, 0),
     861             :     maBtnOk(this),
     862             :     maBtnCancel(this),
     863             :     mnCurTabStop(0),
     864             :     mpExtendedData(NULL),
     865             :     mpOKAction(NULL),
     866             :     mpPopupEndAction(NULL),
     867             :     maWndSize(200, 330),
     868           0 :     mePrevToggleAllState(TRISTATE_INDET)
     869             : {
     870           0 :     maTabStopCtrls.reserve(7);
     871           0 :     maTabStopCtrls.push_back(this);
     872           0 :     maTabStopCtrls.push_back(&maChecks);
     873           0 :     maTabStopCtrls.push_back(&maChkToggleAll);
     874           0 :     maTabStopCtrls.push_back(&maBtnSelectSingle);
     875           0 :     maTabStopCtrls.push_back(&maBtnUnselectSingle);
     876           0 :     maTabStopCtrls.push_back(&maBtnOk);
     877           0 :     maTabStopCtrls.push_back(&maBtnCancel);
     878             : 
     879             :     // Enable type-ahead search in the check list box.
     880           0 :     maChecks.SetStyle(maChecks.GetStyle() | WB_QUICK_SEARCH);
     881           0 : }
     882             : 
     883           0 : ScCheckListMenuWindow::~ScCheckListMenuWindow()
     884             : {
     885           0 : }
     886             : 
     887           0 : void ScCheckListMenuWindow::getSectionPosSize(
     888             :     Point& rPos, Size& rSize, SectionType eType) const
     889             : {
     890             :     // constant parameters.
     891           0 :     const long nListBoxMargin = 5;            // horizontal distance from the side of the dialog to the listbox border.
     892           0 :     const long nListBoxInnerPadding = 5;
     893           0 :     const long nTopMargin = 5;
     894           0 :     const long nMenuHeight = maMenuSize.getHeight();
     895           0 :     const long nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
     896           0 :     const long nBottomBtnAreaHeight = 50;     // height of the bottom area where the OK and Cancel buttons are.
     897           0 :     const long nBtnWidth = 90;
     898           0 :     const long nLabelHeight = getLabelFont().GetHeight();
     899           0 :     const long nBtnHeight = nLabelHeight*2;
     900           0 :     const long nBottomMargin = 10;
     901           0 :     const long nMenuListMargin = 5;
     902             : 
     903             :     // parameters calculated from constants.
     904           0 :     const long nListBoxWidth = maWndSize.Width() - nListBoxMargin*2;
     905           0 :     const long nListBoxHeight = maWndSize.Height() - nTopMargin - nMenuHeight -
     906           0 :         nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight;
     907             : 
     908           0 :     const long nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
     909             : 
     910           0 :     switch (eType)
     911             :     {
     912             :         case WHOLE:
     913             :         {
     914           0 :             rPos  = Point(0, 0);
     915           0 :             rSize = maWndSize;
     916             :         }
     917           0 :         break;
     918             :         case LISTBOX_AREA_OUTER:
     919             :         {
     920           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
     921           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     922             :         }
     923           0 :         break;
     924             :         case LISTBOX_AREA_INNER:
     925             :         {
     926           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
     927           0 :             rPos.X() += nListBoxInnerPadding;
     928           0 :             rPos.Y() += nListBoxInnerPadding;
     929             : 
     930           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     931           0 :             rSize.Width()  -= nListBoxInnerPadding*2;
     932           0 :             rSize.Height() -= nListBoxInnerPadding*2;
     933             :         }
     934           0 :         break;
     935             :         case SINGLE_BTN_AREA:
     936             :         {
     937           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     938           0 :             rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
     939             :         }
     940           0 :         break;
     941             :         case CHECK_TOGGLE_ALL:
     942             :         {
     943           0 :             long h = std::min(maChkToggleAll.CalcMinimumSize().Height(), 26L);
     944           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     945           0 :             rPos.X() += 5;
     946           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     947           0 :             rSize = Size(70, h);
     948             :         }
     949           0 :         break;
     950             :         case BTN_SINGLE_SELECT:
     951             :         {
     952           0 :             long h = 26;
     953           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     954           0 :             rPos.X() += nListBoxWidth - h - 10 - h - 10;
     955           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     956           0 :             rSize = Size(h, h);
     957             :         }
     958           0 :         break;
     959             :         case BTN_SINGLE_UNSELECT:
     960             :         {
     961           0 :             long h = 26;
     962           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     963           0 :             rPos.X() += nListBoxWidth - h - 10;
     964           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     965           0 :             rSize = Size(h, h);
     966             :         }
     967           0 :         break;
     968             :         case BTN_OK:
     969             :         {
     970           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3;
     971           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
     972           0 :             rPos = Point(x, y);
     973           0 :             rSize = Size(nBtnWidth, nBtnHeight);
     974             :         }
     975           0 :         break;
     976             :         case BTN_CANCEL:
     977             :         {
     978           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
     979           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
     980           0 :             rPos = Point(x, y);
     981           0 :             rSize = Size(nBtnWidth, nBtnHeight);
     982             :         }
     983           0 :         break;
     984             :         default:
     985             :             ;
     986             :     }
     987           0 : }
     988             : 
     989           0 : void ScCheckListMenuWindow::packWindow()
     990             : {
     991           0 :     maMenuSize = getMenuSize();
     992             : 
     993           0 :     if (maWndSize.Width() < maMenuSize.Width())
     994             :         // Widen the window to fit the menu items.
     995           0 :         maWndSize.Width() = maMenuSize.Width();
     996             : 
     997             :     // Set proper window height based on the number of menu items.
     998           0 :     if (maWndSize.Height() < maMenuSize.Height()*2.8)
     999           0 :         maWndSize.Height() = maMenuSize.Height()*2.8;
    1000             : 
    1001             :     // TODO: Make sure the window height never exceeds the height of the
    1002             :     // screen. Also do adjustment based on the number of check box items.
    1003             : 
    1004           0 :     SetOutputSizePixel(maWndSize);
    1005             : 
    1006           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1007             : 
    1008           0 :     Point aPos;
    1009           0 :     Size aSize;
    1010           0 :     getSectionPosSize(aPos, aSize, WHOLE);
    1011           0 :     SetOutputSizePixel(aSize);
    1012             : 
    1013           0 :     getSectionPosSize(aPos, aSize, BTN_OK);
    1014           0 :     maBtnOk.SetPosSizePixel(aPos, aSize);
    1015           0 :     maBtnOk.SetFont(getLabelFont());
    1016           0 :     maBtnOk.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1017           0 :     maBtnOk.Show();
    1018             : 
    1019           0 :     getSectionPosSize(aPos, aSize, BTN_CANCEL);
    1020           0 :     maBtnCancel.SetPosSizePixel(aPos, aSize);
    1021           0 :     maBtnCancel.SetFont(getLabelFont());
    1022           0 :     maBtnCancel.Show();
    1023             : 
    1024           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER);
    1025           0 :     maChecks.SetPosSizePixel(aPos, aSize);
    1026           0 :     maChecks.SetFont(getLabelFont());
    1027           0 :     maChecks.SetCheckButtonHdl( LINK(this, ScCheckListMenuWindow, CheckHdl) );
    1028           0 :     maChecks.Show();
    1029             : 
    1030           0 :     getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL);
    1031           0 :     maChkToggleAll.SetPosSizePixel(aPos, aSize);
    1032           0 :     maChkToggleAll.SetFont(getLabelFont());
    1033           0 :     maChkToggleAll.SetText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL));
    1034           0 :     maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor());
    1035           0 :     maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
    1036           0 :     maChkToggleAll.SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) );
    1037           0 :     maChkToggleAll.Show();
    1038             : 
    1039           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
    1040           0 :     maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
    1041           0 :     maBtnSelectSingle.SetQuickHelpText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT));
    1042           0 :     maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)));
    1043           0 :     maBtnSelectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1044           0 :     maBtnSelectSingle.Show();
    1045             : 
    1046           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
    1047           0 :     maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
    1048           0 :     maBtnUnselectSingle.SetQuickHelpText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT));
    1049           0 :     maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)));
    1050           0 :     maBtnUnselectSingle.SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1051           0 :     maBtnUnselectSingle.Show();
    1052           0 : }
    1053             : 
    1054           0 : void ScCheckListMenuWindow::setAllMemberState(bool bSet)
    1055             : {
    1056           0 :     size_t n = maMembers.size();
    1057           0 :     for (size_t i = 0; i < n; ++i)
    1058           0 :         maChecks.CheckEntry( maMembers[i].maName, maMembers[i].mpParent, bSet);
    1059             : 
    1060           0 :     if (!maConfig.mbAllowEmptySet)
    1061             :         // We need to have at least one member selected.
    1062           0 :         maBtnOk.Enable(maChecks.GetCheckedEntryCount() != 0);
    1063           0 : }
    1064             : 
    1065           0 : void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
    1066             : {
    1067           0 :     setAllMemberState(!bSet);
    1068           0 :     SvTreeListEntry* pEntry = maChecks.GetCurEntry();
    1069           0 :     maChecks.CheckEntry(pEntry, bSet );
    1070           0 : }
    1071             : 
    1072           0 : void ScCheckListMenuWindow::cycleFocus(bool bReverse)
    1073             : {
    1074           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
    1075           0 :     maTabStopCtrls[mnCurTabStop]->LoseFocus();
    1076           0 :     if (mnCurTabStop == 0)
    1077           0 :         clearSelectedMenuItem();
    1078             : 
    1079           0 :     if (bReverse)
    1080             :     {
    1081           0 :         if (mnCurTabStop > 0)
    1082           0 :             --mnCurTabStop;
    1083             :         else
    1084           0 :             mnCurTabStop = maTabStopCtrls.size() - 1;
    1085             :     }
    1086             :     else
    1087             :     {
    1088           0 :         ++mnCurTabStop;
    1089           0 :         if (mnCurTabStop >= maTabStopCtrls.size())
    1090           0 :             mnCurTabStop = 0;
    1091             :     }
    1092           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
    1093           0 :     maTabStopCtrls[mnCurTabStop]->GrabFocus();
    1094           0 : }
    1095             : 
    1096           0 : IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn )
    1097             : {
    1098           0 :     if (pBtn == &maBtnOk)
    1099           0 :         close(true);
    1100           0 :     else if (pBtn == &maBtnSelectSingle)
    1101             :     {
    1102           0 :         selectCurrentMemberOnly(true);
    1103           0 :         CheckHdl(&maChecks);
    1104             :     }
    1105           0 :     else if (pBtn == &maBtnUnselectSingle)
    1106             :     {
    1107           0 :         selectCurrentMemberOnly(false);
    1108           0 :         CheckHdl(&maChecks);
    1109             :     }
    1110           0 :     return 0;
    1111             : }
    1112             : 
    1113           0 : IMPL_LINK_NOARG(ScCheckListMenuWindow, TriStateHdl)
    1114             : {
    1115           0 :     switch (mePrevToggleAllState)
    1116             :     {
    1117             :         case TRISTATE_FALSE:
    1118           0 :             maChkToggleAll.SetState(TRISTATE_TRUE);
    1119           0 :             setAllMemberState(true);
    1120           0 :         break;
    1121             :         case TRISTATE_TRUE:
    1122           0 :             maChkToggleAll.SetState(TRISTATE_FALSE);
    1123           0 :             setAllMemberState(false);
    1124           0 :         break;
    1125             :         case TRISTATE_INDET:
    1126             :         default:
    1127           0 :             maChkToggleAll.SetState(TRISTATE_TRUE);
    1128           0 :             setAllMemberState(true);
    1129           0 :         break;
    1130             :     }
    1131             : 
    1132           0 :     mePrevToggleAllState = maChkToggleAll.GetState();
    1133           0 :     return 0;
    1134             : }
    1135             : 
    1136           0 : IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
    1137             : {
    1138           0 :     if (pChecks != &maChecks)
    1139           0 :         return 0;
    1140           0 :     SvTreeListEntry* pEntry = pChecks->GetHdlEntry();
    1141           0 :     if ( pEntry )
    1142           0 :         maChecks.CheckEntry( pEntry,  ( pChecks->GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) );
    1143           0 :     size_t nNumChecked = maChecks.GetCheckedEntryCount();
    1144           0 :     if (nNumChecked == maMembers.size())
    1145             :         // all members visible
    1146           0 :         maChkToggleAll.SetState(TRISTATE_TRUE);
    1147           0 :     else if (nNumChecked == 0)
    1148             :         // no members visible
    1149           0 :         maChkToggleAll.SetState(TRISTATE_FALSE);
    1150             :     else
    1151           0 :         maChkToggleAll.SetState(TRISTATE_INDET);
    1152             : 
    1153           0 :     if (!maConfig.mbAllowEmptySet)
    1154             :         // We need to have at least one member selected.
    1155           0 :         maBtnOk.Enable(nNumChecked != 0);
    1156             : 
    1157           0 :     mePrevToggleAllState = maChkToggleAll.GetState();
    1158           0 :     return 0;
    1159             : }
    1160             : 
    1161           0 : void ScCheckListMenuWindow::MouseMove(const MouseEvent& rMEvt)
    1162             : {
    1163           0 :     ScMenuFloatingWindow::MouseMove(rMEvt);
    1164             : 
    1165           0 :     size_t nSelectedMenu = getSelectedMenuItem();
    1166           0 :     if (nSelectedMenu == MENU_NOT_SELECTED)
    1167           0 :         queueCloseSubMenu();
    1168           0 : }
    1169             : 
    1170           0 : bool ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
    1171             : {
    1172           0 :     switch (rNEvt.GetType())
    1173             :     {
    1174             :         case EVENT_KEYUP:
    1175             :         {
    1176           0 :             const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
    1177           0 :             const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode();
    1178           0 :             bool bShift = rCode.IsShift();
    1179           0 :             if (rCode.GetCode() == KEY_TAB)
    1180             :             {
    1181           0 :                 cycleFocus(bShift);
    1182           0 :                 return true;
    1183             :             }
    1184             :         }
    1185           0 :         break;
    1186             :     }
    1187           0 :     return ScMenuFloatingWindow::Notify(rNEvt);
    1188             : }
    1189             : 
    1190           0 : void ScCheckListMenuWindow::Paint(const Rectangle& rRect)
    1191             : {
    1192           0 :     ScMenuFloatingWindow::Paint(rRect);
    1193             : 
    1194           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1195           0 :     Color aMemberBackColor = rStyle.GetFieldColor();
    1196           0 :     Color aBorderColor = rStyle.GetShadowColor();
    1197             : 
    1198           0 :     Point aPos;
    1199           0 :     Size aSize;
    1200           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
    1201             : 
    1202             :     // Member list box background
    1203           0 :     SetFillColor(aMemberBackColor);
    1204           0 :     SetLineColor(aBorderColor);
    1205           0 :     DrawRect(Rectangle(aPos,aSize));
    1206             : 
    1207             :     // Single-action button box
    1208           0 :     getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
    1209           0 :     SetFillColor(rStyle.GetMenuColor());
    1210           0 :     DrawRect(Rectangle(aPos,aSize));
    1211           0 : }
    1212             : 
    1213           0 : vcl::Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
    1214             : {
    1215           0 :     return maTabStopCtrls[mnCurTabStop];
    1216             : }
    1217             : 
    1218           0 : Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
    1219             : {
    1220           0 :     if (!mxAccessible.is())
    1221             :     {
    1222             :         mxAccessible.set(new ScAccessibleFilterTopWindow(
    1223           0 :             GetAccessibleParentWindow()->GetAccessible(), this, getName()));
    1224           0 :         ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
    1225           0 :         fillMenuItemsToAccessible(pAccTop);
    1226             : 
    1227             :         pAccTop->setAccessibleChild(
    1228           0 :             maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
    1229             :         pAccTop->setAccessibleChild(
    1230           0 :             maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
    1231             :         pAccTop->setAccessibleChild(
    1232           0 :             maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
    1233             :         pAccTop->setAccessibleChild(
    1234           0 :             maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
    1235             :         pAccTop->setAccessibleChild(
    1236           0 :             maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
    1237             :         pAccTop->setAccessibleChild(
    1238           0 :             maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
    1239             :     }
    1240             : 
    1241           0 :     return mxAccessible;
    1242             : }
    1243             : 
    1244           0 : void ScCheckListMenuWindow::setMemberSize(size_t n)
    1245             : {
    1246           0 :     maMembers.reserve(n);
    1247           0 : }
    1248             : 
    1249           0 : void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, bool bVisible)
    1250             : {
    1251           0 :     ScDocument* pDoc = getDoc();
    1252           0 :     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
    1253             : 
    1254             :     // Convert the numeric date value to a date object.
    1255           0 :     Date aDate = *(pFormatter->GetNullDate());
    1256           0 :     aDate += static_cast<long>(rtl::math::approxFloor(nVal));
    1257             : 
    1258           0 :     sal_uInt16 nYear = aDate.GetYear();
    1259           0 :     sal_uInt16 nMonth = aDate.GetMonth();
    1260           0 :     sal_uInt16 nDay = aDate.GetDay();
    1261             : 
    1262             :     // Get the localized month name list.
    1263           0 :     CalendarWrapper* pCalendar = ScGlobal::GetCalendar();
    1264           0 :     uno::Sequence<i18n::CalendarItem2> aMonths = pCalendar->getMonths();
    1265           0 :     if (aMonths.getLength() < nMonth)
    1266           0 :         return;
    1267             : 
    1268           0 :     OUString aYearName = OUString::number(nYear);
    1269           0 :     OUString aMonthName = aMonths[nMonth-1].FullName;
    1270           0 :     OUString aDayName = OUString::number(nDay);
    1271             : 
    1272           0 :     maChecks.SetUpdateMode(false);
    1273             : 
    1274           0 :     SvTreeListEntry* pYearEntry = maChecks.FindEntry(NULL, aYearName);
    1275           0 :     if (!pYearEntry)
    1276             :     {
    1277           0 :         pYearEntry = maChecks.InsertEntry(aYearName, NULL, true);
    1278           0 :         Member aMemYear;
    1279           0 :         aMemYear.maName = aYearName;
    1280           0 :         aMemYear.maRealName = rsName;
    1281           0 :         aMemYear.mbDate = true;
    1282           0 :         aMemYear.mbLeaf = false;
    1283           0 :         aMemYear.mbVisible = bVisible;
    1284           0 :         aMemYear.mpParent = NULL;
    1285           0 :         maMembers.push_back(aMemYear);
    1286             :     }
    1287             : 
    1288           0 :     SvTreeListEntry* pMonthEntry = maChecks.FindEntry(pYearEntry, aMonthName);
    1289           0 :     if (!pMonthEntry)
    1290             :     {
    1291           0 :         pMonthEntry = maChecks.InsertEntry(aMonthName, pYearEntry, true);
    1292           0 :         Member aMemMonth;
    1293           0 :         aMemMonth.maName = aMonthName;
    1294           0 :         aMemMonth.maRealName = rsName;
    1295           0 :         aMemMonth.mbDate = true;
    1296           0 :         aMemMonth.mbLeaf = false;
    1297           0 :         aMemMonth.mbVisible = bVisible;
    1298           0 :         aMemMonth.mpParent = pYearEntry;
    1299           0 :         maMembers.push_back(aMemMonth);
    1300             :     }
    1301             : 
    1302           0 :     SvTreeListEntry* pDayEntry = maChecks.FindEntry(pMonthEntry, aDayName);
    1303           0 :     if (!pDayEntry)
    1304             :     {
    1305           0 :         maChecks.InsertEntry(aDayName, pMonthEntry, false);
    1306           0 :         Member aMemDay;
    1307           0 :         aMemDay.maName = aDayName;
    1308           0 :         aMemDay.maRealName = rsName;
    1309           0 :         aMemDay.mbDate = true;
    1310           0 :         aMemDay.mbLeaf = true;
    1311           0 :         aMemDay.mbVisible = bVisible;
    1312           0 :         aMemDay.mpParent = pMonthEntry;
    1313           0 :         maMembers.push_back(aMemDay);
    1314             :     }
    1315             : 
    1316           0 :     maChecks.SetUpdateMode(true);
    1317             : }
    1318             : 
    1319           0 : void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
    1320             : {
    1321           0 :     Member aMember;
    1322           0 :     aMember.maName = rName;
    1323           0 :     aMember.mbDate = false;
    1324           0 :     aMember.mbLeaf = true;
    1325           0 :     aMember.mbVisible = bVisible;
    1326           0 :     aMember.mpParent = NULL;
    1327           0 :     maMembers.push_back(aMember);
    1328           0 : }
    1329             : 
    1330           0 : ScCheckListBox::ScCheckListBox( vcl::Window* pParent, WinBits nWinStyle )
    1331           0 :    :  SvTreeListBox( pParent, nWinStyle ), mpCheckButton( NULL )
    1332             : {
    1333           0 :     Init();
    1334           0 : }
    1335             : 
    1336           0 : SvTreeListEntry* ScCheckListBox::FindEntry( SvTreeListEntry* pParent, const OUString& sNode )
    1337             : {
    1338           0 :     sal_uInt16 nRootPos = 0;
    1339           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos );
    1340           0 :     while ( pEntry )
    1341             :     {
    1342           0 :         if (  sNode.equals(GetEntryText( pEntry )) )
    1343           0 :             return pEntry;
    1344             : 
    1345           0 :         pEntry = pParent ? NextSibling( pEntry ) : GetEntry( ++nRootPos );
    1346             :     }
    1347           0 :     return NULL;
    1348             : }
    1349             : 
    1350           0 : void ScCheckListBox::Init()
    1351             : {
    1352           0 :     mpCheckButton = new SvLBoxButtonData( this );
    1353           0 :     EnableCheckButton( mpCheckButton );
    1354           0 :     SetNodeDefaultImages();
    1355           0 : }
    1356             : 
    1357           0 : bool ScCheckListBox::IsChecked( const OUString& sName, SvTreeListEntry* pParent )
    1358             : {
    1359           0 :     SvTreeListEntry* pEntry = FindEntry( pParent, sName );
    1360           0 :     if ( pEntry && GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED)
    1361           0 :         return true;
    1362           0 :     return false;
    1363             : }
    1364             : 
    1365           0 : void ScCheckListBox::CheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bCheck )
    1366             : {
    1367           0 :     SvTreeListEntry* pEntry = FindEntry( pParent, sName );
    1368           0 :     if ( pEntry )
    1369           0 :         CheckEntry(  pEntry, bCheck );
    1370           0 : }
    1371             : 
    1372             : // Recursively check all children of pParent
    1373           0 : void ScCheckListBox::CheckAllChildren( SvTreeListEntry* pParent, bool bCheck )
    1374             : {
    1375           0 :     if ( pParent )
    1376             :     {
    1377             :         SetCheckButtonState(
    1378             :             pParent, bCheck ? SvButtonState( SV_BUTTON_CHECKED ) :
    1379           0 :                                            SvButtonState( SV_BUTTON_UNCHECKED ) );
    1380             :     }
    1381           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1382           0 :     while ( pEntry )
    1383             :     {
    1384           0 :         CheckAllChildren( pEntry, bCheck );
    1385           0 :         pEntry = NextSibling( pEntry );
    1386             :     }
    1387           0 : }
    1388             : 
    1389           0 : void ScCheckListBox::CheckEntry( SvTreeListEntry* pParent, bool bCheck )
    1390             : {
    1391             :     // recursively check all items below pParent
    1392           0 :     CheckAllChildren( pParent, bCheck );
    1393             :     // checking pParent can affect ancestors, e.g. if ancestor is unchecked and pParent is
    1394             :     // now checked then the ancestor needs to be checked also
    1395           0 :     SvTreeListEntry* pAncestor = GetParent(pParent);
    1396           0 :     if ( pAncestor )
    1397             :     {
    1398           0 :         while ( pAncestor )
    1399             :         {
    1400             :             // if any first level children checked then ancestor
    1401             :             // needs to be checked, similarly if no first level children
    1402             :             // checked then ancestor needs to be unchecked
    1403           0 :             SvTreeListEntry* pChild = FirstChild( pAncestor );
    1404           0 :             bool bChildChecked = false;
    1405             : 
    1406           0 :             while ( pChild )
    1407             :             {
    1408           0 :                 if ( GetCheckButtonState( pChild ) == SV_BUTTON_CHECKED )
    1409             :                 {
    1410           0 :                     bChildChecked = true;
    1411           0 :                     break;
    1412             :                 }
    1413           0 :                 pChild = NextSibling( pChild );
    1414             :             }
    1415             :             SetCheckButtonState(
    1416             :                 pAncestor, bChildChecked ? SvButtonState( SV_BUTTON_CHECKED ) :
    1417           0 :                                            SvButtonState( SV_BUTTON_UNCHECKED ) );
    1418           0 :             pAncestor = GetParent(pAncestor);
    1419             :         }
    1420             :     }
    1421           0 : }
    1422             : 
    1423           0 : SvTreeListEntry* ScCheckListBox::CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const
    1424             : {
    1425           0 :     if ( pParent && GetCheckButtonState( pParent ) == SV_BUTTON_CHECKED  )
    1426           0 :         nCount++;
    1427             :     // Iterate over the children
    1428           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1429           0 :     while ( pEntry )
    1430             :     {
    1431           0 :         CountCheckedEntries( pEntry, nCount );
    1432           0 :         pEntry = NextSibling( pEntry );
    1433             :     }
    1434           0 :     return NULL;
    1435             : }
    1436             : 
    1437           0 : sal_uInt16 ScCheckListBox::GetCheckedEntryCount() const
    1438             : {
    1439           0 :     sal_uLong nCount = 0;
    1440           0 :     CountCheckedEntries( NULL,  nCount );
    1441           0 :     return nCount;
    1442             : }
    1443             : 
    1444           0 : void ScCheckListBox::ExpandChildren( SvTreeListEntry* pParent )
    1445             : {
    1446           0 :     if ( pParent )
    1447           0 :         Expand( pParent );
    1448             :     // Iterate over the children
    1449           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1450           0 :     while ( pEntry )
    1451             :     {
    1452           0 :         ExpandChildren( pEntry );
    1453           0 :         pEntry = NextSibling( pEntry );
    1454             :     }
    1455           0 : }
    1456             : 
    1457           0 : void ScCheckListBox::KeyInput( const KeyEvent& rKEvt )
    1458             : {
    1459           0 :     const vcl::KeyCode& rKey = rKEvt.GetKeyCode();
    1460             : 
    1461           0 :     if ( rKey.GetCode() == KEY_RETURN || rKey.GetCode() == KEY_SPACE )
    1462             :     {
    1463           0 :         SvTreeListEntry* pEntry = GetCurEntry();
    1464             : 
    1465           0 :         if ( pEntry )
    1466             :         {
    1467           0 :             bool bCheck = ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED );
    1468           0 :             CheckEntry( pEntry, !bCheck );
    1469           0 :             if ( bCheck != ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) )
    1470           0 :                 CheckButtonHdl();
    1471             :         }
    1472             :     }
    1473           0 :     else if ( GetEntryCount() )
    1474           0 :         SvTreeListBox::KeyInput( rKEvt );
    1475           0 : }
    1476             : 
    1477           0 : void ScCheckListMenuWindow::initMembers()
    1478             : {
    1479           0 :     size_t n = maMembers.size();
    1480           0 :     size_t nVisMemCount = 0;
    1481             : 
    1482           0 :     maChecks.SetUpdateMode(false);
    1483           0 :     maChecks.GetModel()->EnableInvalidate(false);
    1484             : 
    1485           0 :     for (size_t i = 0; i < n; ++i)
    1486             :     {
    1487           0 :         if (maMembers[i].mbDate)
    1488             :         {
    1489           0 :             maChecks.CheckEntry(maMembers[i].maName, maMembers[i].mpParent, maMembers[i].mbVisible);
    1490             :             // Expand first node of checked dates
    1491           0 :             if (!maMembers[i].mpParent && maChecks.IsChecked(maMembers[i].maName,  maMembers[i].mpParent))
    1492             :             {
    1493           0 :                 SvTreeListEntry* pEntry = maChecks.FindEntry(NULL, maMembers[i].maName);
    1494           0 :                 if (pEntry)
    1495           0 :                     maChecks.Expand(pEntry);
    1496             :             }
    1497             :         }
    1498             :         else
    1499             :         {
    1500             :             SvTreeListEntry* pEntry = maChecks.InsertEntry(
    1501           0 :                 maMembers[i].maName, NULL, false, TREELIST_APPEND, NULL,
    1502           0 :                 SvLBoxButtonKind_enabledCheckbox);
    1503             : 
    1504             :             maChecks.SetCheckButtonState(
    1505           0 :                 pEntry, maMembers[i].mbVisible ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED);
    1506             :         }
    1507             : 
    1508           0 :         if (maMembers[i].mbVisible)
    1509           0 :             ++nVisMemCount;
    1510             :     }
    1511           0 :     if (nVisMemCount == n)
    1512             :     {
    1513             :         // all members visible
    1514           0 :         maChkToggleAll.SetState(TRISTATE_TRUE);
    1515           0 :         mePrevToggleAllState = TRISTATE_TRUE;
    1516             :     }
    1517           0 :     else if (nVisMemCount == 0)
    1518             :     {
    1519             :         // no members visible
    1520           0 :         maChkToggleAll.SetState(TRISTATE_FALSE);
    1521           0 :         mePrevToggleAllState = TRISTATE_FALSE;
    1522             :     }
    1523             :     else
    1524             :     {
    1525           0 :         maChkToggleAll.SetState(TRISTATE_INDET);
    1526           0 :         mePrevToggleAllState = TRISTATE_INDET;
    1527             :     }
    1528             : 
    1529           0 :     maChecks.GetModel()->EnableInvalidate(true);
    1530           0 :     maChecks.SetUpdateMode(true);
    1531           0 : }
    1532             : 
    1533           0 : void ScCheckListMenuWindow::setConfig(const Config& rConfig)
    1534             : {
    1535           0 :     maConfig = rConfig;
    1536           0 : }
    1537             : 
    1538           0 : bool ScCheckListMenuWindow::isAllSelected() const
    1539             : {
    1540           0 :     return maChkToggleAll.IsChecked();
    1541             : }
    1542             : 
    1543           0 : void ScCheckListMenuWindow::getResult(ResultType& rResult)
    1544             : {
    1545           0 :     ResultType aResult;
    1546           0 :     size_t n = maMembers.size();
    1547           0 :     for (size_t i = 0; i < n; ++i)
    1548             :     {
    1549           0 :         if ( maMembers[i].mbLeaf )
    1550             :         {
    1551           0 :             bool bState =  maChecks.IsChecked( maMembers[i].maName,  maMembers[i].mpParent );
    1552           0 :             OUString sName;
    1553           0 :             if ( maMembers[i].mbDate )
    1554           0 :                 sName = maMembers[i].maRealName;
    1555             :             else
    1556           0 :                 sName = maMembers[i].maName;
    1557           0 :             aResult.insert(ResultType::value_type(sName, bState));
    1558             :         }
    1559             :     }
    1560           0 :     rResult.swap(aResult);
    1561           0 : }
    1562             : 
    1563           0 : void ScCheckListMenuWindow::launch(const Rectangle& rRect)
    1564             : {
    1565           0 :     packWindow();
    1566           0 :     if (!maConfig.mbAllowEmptySet)
    1567             :         // We need to have at least one member selected.
    1568           0 :         maBtnOk.Enable(maChecks.GetCheckedEntryCount() != 0);
    1569             : 
    1570           0 :     Rectangle aRect(rRect);
    1571           0 :     if (maConfig.mbRTL)
    1572             :     {
    1573             :         // In RTL mode, the logical "left" is visual "right".
    1574           0 :         long nLeft = aRect.Left() - aRect.GetWidth();
    1575           0 :         aRect.Left() = nLeft;
    1576             :     }
    1577           0 :     else if (maWndSize.Width() < aRect.GetWidth())
    1578             :     {
    1579             :         // Target rectangle (i.e. cell width) is wider than the window.
    1580             :         // Simulate right-aligned launch by modifying the target rectangle
    1581             :         // size.
    1582           0 :         long nDiff = aRect.GetWidth() - maWndSize.Width();
    1583           0 :         aRect.Left() += nDiff;
    1584             :     }
    1585             : 
    1586           0 :     StartPopupMode(aRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
    1587           0 :     cycleFocus(); // Set initial focus to the check list box.
    1588           0 : }
    1589             : 
    1590           0 : void ScCheckListMenuWindow::close(bool bOK)
    1591             : {
    1592           0 :     if (bOK && mpOKAction.get())
    1593           0 :         mpOKAction->execute();
    1594             : 
    1595           0 :     EndPopupMode();
    1596           0 : }
    1597             : 
    1598           0 : void ScCheckListMenuWindow::setExtendedData(ExtendedData* p)
    1599             : {
    1600           0 :     mpExtendedData.reset(p);
    1601           0 : }
    1602             : 
    1603           0 : ScCheckListMenuWindow::ExtendedData* ScCheckListMenuWindow::getExtendedData()
    1604             : {
    1605           0 :     return mpExtendedData.get();
    1606             : }
    1607             : 
    1608           0 : void ScCheckListMenuWindow::setOKAction(Action* p)
    1609             : {
    1610           0 :     mpOKAction.reset(p);
    1611           0 : }
    1612             : 
    1613           0 : void ScCheckListMenuWindow::setPopupEndAction(Action* p)
    1614             : {
    1615           0 :     mpPopupEndAction.reset(p);
    1616           0 : }
    1617             : 
    1618           0 : void ScCheckListMenuWindow::handlePopupEnd()
    1619             : {
    1620           0 :     clearSelectedMenuItem();
    1621           0 :     if (mpPopupEndAction)
    1622           0 :         mpPopupEndAction->execute();
    1623         228 : }
    1624             : 
    1625             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10