LCOV - code coverage report
Current view: top level - sc/source/ui/cctrl - checklistmenu.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 1027 0.1 %
Date: 2015-06-13 12:38:46 Functions: 2 104 1.9 %
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             : #include "globstr.hrc"
      24             : 
      25             : #include <vcl/decoview.hxx>
      26             : #include <vcl/settings.hxx>
      27             : #include <tools/wintypes.hxx>
      28             : 
      29             : #include "AccessibleFilterMenu.hxx"
      30             : #include "AccessibleFilterTopWindow.hxx"
      31             : 
      32             : #include <com/sun/star/accessibility/XAccessible.hpp>
      33             : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
      34             : #include <svtools/fmtfield.hxx>
      35             : #include <svtools/treelistentry.hxx>
      36             : #include "document.hxx"
      37             : 
      38             : using namespace com::sun::star;
      39             : using ::com::sun::star::uno::Reference;
      40             : using ::com::sun::star::accessibility::XAccessible;
      41             : using ::com::sun::star::accessibility::XAccessibleContext;
      42             : using ::std::vector;
      43             : 
      44           0 : ScMenuFloatingWindow::MenuItemData::MenuItemData() :
      45             :     mbEnabled(true), mbSeparator(false),
      46             :     mpAction(static_cast<ScCheckListMenuWindow::Action*>(NULL)),
      47           0 :     mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
      48             : {
      49           0 : }
      50             : 
      51           0 : ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
      52             :     mpSubMenu(NULL),
      53             :     mnMenuPos(MENU_NOT_SELECTED),
      54           0 :     mpParent(pParent)
      55             : {
      56           0 :     maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
      57           0 :     maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
      58           0 : }
      59             : 
      60           0 : void ScMenuFloatingWindow::SubMenuItemData::reset()
      61             : {
      62           0 :     mpSubMenu = NULL;
      63           0 :     mnMenuPos = MENU_NOT_SELECTED;
      64           0 :     maTimer.Stop();
      65           0 : }
      66             : 
      67           0 : IMPL_LINK_NOARG_TYPED(ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, Timer *, void)
      68             : {
      69           0 :     mpParent->handleMenuTimeout(this);
      70           0 : }
      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           0 :     SetText(OUString("ScMenuFloatingWindow"));
      86             : 
      87           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
      88             : 
      89           0 :     sal_Int32 nScaleFactor = GetDPIScaleFactor();
      90           0 :     const sal_uInt16 nPopupFontHeight = 12 * nScaleFactor;
      91           0 :     maLabelFont = rStyle.GetLabelFont();
      92           0 :     maLabelFont.SetHeight(nPopupFontHeight);
      93           0 : }
      94             : 
      95           0 : ScMenuFloatingWindow::~ScMenuFloatingWindow()
      96             : {
      97           0 :     disposeOnce();
      98           0 : }
      99             : 
     100           0 : void ScMenuFloatingWindow::dispose()
     101             : {
     102           0 :     EndPopupMode();
     103           0 :     mpParentMenu.clear();
     104           0 :     PopupMenuFloatingWindow::dispose();
     105           0 : }
     106             : 
     107           0 : void ScMenuFloatingWindow::PopupModeEnd()
     108             : {
     109           0 :     handlePopupEnd();
     110           0 : }
     111             : 
     112           0 : void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
     113             : {
     114           0 :     const Point& rPos = rMEvt.GetPosPixel();
     115           0 :     size_t nSelectedMenu = getEnclosingMenuItem(rPos);
     116           0 :     setSelectedMenuItem(nSelectedMenu, true, false);
     117             : 
     118           0 :     Window::MouseMove(rMEvt);
     119           0 : }
     120             : 
     121           0 : void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
     122             : {
     123           0 :     const Point& rPos = rMEvt.GetPosPixel();
     124           0 :     mnClickedMenu = getEnclosingMenuItem(rPos);
     125           0 :     Window::MouseButtonDown(rMEvt);
     126           0 : }
     127             : 
     128           0 : void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
     129             : {
     130           0 :     executeMenuItem(mnClickedMenu);
     131           0 :     mnClickedMenu = MENU_NOT_SELECTED;
     132           0 :     Window::MouseButtonUp(rMEvt);
     133           0 : }
     134             : 
     135           0 : void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
     136             : {
     137           0 :     if (maMenuItems.empty())
     138             :     {
     139           0 :         Window::KeyInput(rKEvt);
     140           0 :         return;
     141             :     }
     142             : 
     143           0 :     const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
     144           0 :     bool bHandled = true;
     145           0 :     size_t nSelectedMenu = mnSelectedMenu;
     146           0 :     size_t nLastMenuPos = maMenuItems.size() - 1;
     147           0 :     switch (rKeyCode.GetCode())
     148             :     {
     149             :         case KEY_UP:
     150             :         {
     151           0 :             if (nLastMenuPos == 0)
     152             :                 // There is only one menu item.  Do nothing.
     153           0 :                 break;
     154             : 
     155           0 :             size_t nOldPos = nSelectedMenu;
     156             : 
     157           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
     158           0 :                 nSelectedMenu = nLastMenuPos;
     159             :             else
     160           0 :                 --nSelectedMenu;
     161             : 
     162             :             // Loop until a non-separator menu item is found.
     163           0 :             while (nSelectedMenu != nOldPos)
     164             :             {
     165           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     166             :                 {
     167           0 :                     if (nSelectedMenu)
     168           0 :                         --nSelectedMenu;
     169             :                     else
     170           0 :                         nSelectedMenu = nLastMenuPos;
     171             :                 }
     172             :                 else
     173           0 :                     break;
     174             :             }
     175             : 
     176           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     177             :         }
     178           0 :         break;
     179             :         case KEY_DOWN:
     180             :         {
     181           0 :             if (nLastMenuPos == 0)
     182             :                 // There is only one menu item.  Do nothing.
     183           0 :                 break;
     184             : 
     185           0 :             size_t nOldPos = nSelectedMenu;
     186             : 
     187           0 :             if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
     188           0 :                 nSelectedMenu = 0;
     189             :             else
     190           0 :                 ++nSelectedMenu;
     191             : 
     192             :             // Loop until a non-separator menu item is found.
     193           0 :             while (nSelectedMenu != nOldPos)
     194             :             {
     195           0 :                 if (maMenuItems[nSelectedMenu].mbSeparator)
     196             :                 {
     197           0 :                     if (nSelectedMenu == nLastMenuPos)
     198           0 :                         nSelectedMenu = 0;
     199             :                     else
     200           0 :                         ++nSelectedMenu;
     201             :                 }
     202             :                 else
     203           0 :                     break;
     204             :             }
     205             : 
     206           0 :             setSelectedMenuItem(nSelectedMenu, false, false);
     207             :         }
     208           0 :         break;
     209             :         case KEY_LEFT:
     210           0 :             if (mpParentMenu)
     211           0 :                 mpParentMenu->endSubMenu(this);
     212           0 :         break;
     213             :         case KEY_RIGHT:
     214             :         {
     215           0 :             if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
     216           0 :                 break;
     217             : 
     218           0 :             const MenuItemData& rMenu = maMenuItems[mnSelectedMenu];
     219           0 :             if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
     220           0 :                 break;
     221             : 
     222           0 :             maOpenTimer.mnMenuPos = mnSelectedMenu;
     223           0 :             maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
     224           0 :             launchSubMenu(true);
     225             :         }
     226           0 :         break;
     227             :         case KEY_RETURN:
     228           0 :             if (nSelectedMenu != MENU_NOT_SELECTED)
     229           0 :                 executeMenuItem(nSelectedMenu);
     230           0 :         break;
     231             :         default:
     232           0 :             bHandled = false;
     233             :     }
     234             : 
     235           0 :     if (!bHandled)
     236           0 :         Window::KeyInput(rKEvt);
     237             : }
     238             : 
     239           0 : void ScMenuFloatingWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/)
     240             : {
     241           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
     242             : 
     243           0 :     SetFont(maLabelFont);
     244             : 
     245           0 :     Color aBackColor = rStyle.GetMenuColor();
     246           0 :     Color aBorderColor = rStyle.GetShadowColor();
     247             : 
     248           0 :     Rectangle aCtrlRect(Point(0, 0), rRenderContext.GetOutputSizePixel());
     249             : 
     250             :     // Window background
     251           0 :     bool bNativeDrawn = true;
     252           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     253             :     {
     254           0 :         rRenderContext.SetClipRegion();
     255             :         bNativeDrawn = rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect,
     256           0 :                                                         ControlState::ENABLED, ImplControlValue(), OUString());
     257             :     }
     258             :     else
     259           0 :         bNativeDrawn = false;
     260             : 
     261           0 :     if (!bNativeDrawn)
     262             :     {
     263           0 :         rRenderContext.SetFillColor(aBackColor);
     264           0 :         rRenderContext.SetLineColor(aBorderColor);
     265           0 :         rRenderContext.DrawRect(aCtrlRect);
     266             :     }
     267             : 
     268             :     // Menu items
     269           0 :     rRenderContext.SetTextColor(rStyle.GetMenuTextColor());
     270           0 :     drawAllMenuItems(rRenderContext);
     271           0 : }
     272             : 
     273           0 : Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
     274             : {
     275           0 :     if (!mxAccessible.is())
     276             :     {
     277             :         Reference<XAccessible> xAccParent = mpParentMenu ?
     278           0 :             mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
     279             : 
     280           0 :         mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999));
     281             :         ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
     282           0 :             mxAccessible.get());
     283             : 
     284           0 :         vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
     285           0 :         for (itr = itrBeg; itr != itrEnd; ++itr)
     286             :         {
     287           0 :             size_t nPos = ::std::distance(itrBeg, itr);
     288           0 :             p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
     289           0 :         }
     290             :     }
     291             : 
     292           0 :     return mxAccessible;
     293             : }
     294             : 
     295           0 : void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
     296             : {
     297           0 :     MenuItemData aItem;
     298           0 :     aItem.maText = rText;
     299           0 :     aItem.mbEnabled = bEnabled;
     300           0 :     aItem.mpAction.reset(pAction);
     301           0 :     maMenuItems.push_back(aItem);
     302           0 : }
     303             : 
     304           0 : void ScMenuFloatingWindow::addSeparator()
     305             : {
     306           0 :     MenuItemData aItem;
     307           0 :     aItem.mbSeparator = true;
     308           0 :     maMenuItems.push_back(aItem);
     309           0 : }
     310             : 
     311           0 : ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
     312             : {
     313           0 :     MenuItemData aItem;
     314           0 :     aItem.maText = rText;
     315           0 :     aItem.mbEnabled = bEnabled;
     316           0 :     aItem.mpSubMenuWin.reset(VclPtr<ScMenuFloatingWindow>::Create(this, mpDoc, GetMenuStackLevel()+1));
     317           0 :     aItem.mpSubMenuWin->setName(rText);
     318           0 :     maMenuItems.push_back(aItem);
     319           0 :     return aItem.mpSubMenuWin.get();
     320             : }
     321             : 
     322           0 : void ScMenuFloatingWindow::handlePopupEnd()
     323             : {
     324           0 :     clearSelectedMenuItem();
     325           0 : }
     326             : 
     327           0 : Size ScMenuFloatingWindow::getMenuSize() const
     328             : {
     329           0 :     if (maMenuItems.empty())
     330           0 :         return Size();
     331             : 
     332           0 :     vector<MenuItemData>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
     333           0 :     long nTextWidth = 0;
     334           0 :     for (; itr != itrEnd; ++itr)
     335             :     {
     336           0 :         if (itr->mbSeparator)
     337           0 :             continue;
     338             : 
     339           0 :         nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
     340             :     }
     341             : 
     342           0 :     size_t nLastPos = maMenuItems.size()-1;
     343           0 :     Point aPos;
     344           0 :     Size aSize;
     345           0 :     getMenuItemPosSize(nLastPos, aPos, aSize);
     346           0 :     aPos.X() += nTextWidth + 15;
     347           0 :     aPos.Y() += aSize.Height() + 5;
     348           0 :     return Size(aPos.X(), aPos.Y());
     349             : }
     350             : 
     351           0 : void ScMenuFloatingWindow::drawMenuItem(vcl::RenderContext& rRenderContext, size_t nPos)
     352             : {
     353           0 :     if (nPos >= maMenuItems.size())
     354           0 :         return;
     355             : 
     356           0 :     Point aPos;
     357           0 :     Size aSize;
     358           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     359             : 
     360           0 :     DecorationView aDecoView(&rRenderContext);
     361           0 :     long nXOffset = 5;
     362           0 :     long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
     363           0 :     rRenderContext. DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0,
     364           0 :                                  maMenuItems[nPos].maText.getLength(),
     365           0 :                                  maMenuItems[nPos].mbEnabled ? DrawTextFlags::Mnemonic : DrawTextFlags::Disable);
     366             : 
     367           0 :     if (maMenuItems[nPos].mpSubMenuWin)
     368             :     {
     369           0 :         long nFontHeight = maLabelFont.GetHeight();
     370           0 :         Point aMarkerPos = aPos;
     371           0 :         aMarkerPos.Y() += aSize.Height() / 2 - nFontHeight / 4 + 1;
     372           0 :         aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight / 4;
     373           0 :         Size aMarkerSize(nFontHeight / 2, nFontHeight / 2);
     374           0 :         aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize), SymbolType::SPIN_RIGHT, GetTextColor());
     375           0 :     }
     376             : }
     377             : 
     378           0 : void ScMenuFloatingWindow::drawSeparator(vcl::RenderContext& rRenderContext, size_t nPos)
     379             : {
     380           0 :     Point aPos;
     381           0 :     Size aSize;
     382           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     383           0 :     Rectangle aRegion(aPos,aSize);
     384             : 
     385           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     386             :     {
     387           0 :         rRenderContext.Push(PushFlags::CLIPREGION);
     388           0 :         rRenderContext.IntersectClipRegion(aRegion);
     389           0 :         Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
     390             :         rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect,
     391           0 :                                          ControlState::ENABLED, ImplControlValue(), OUString());
     392             : 
     393           0 :         rRenderContext.Pop();
     394             :     }
     395             : 
     396           0 :     bool bNativeDrawn = false;
     397           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_SEPARATOR))
     398             :     {
     399           0 :         ControlState nState = ControlState::NONE;
     400           0 :         const MenuItemData& rData = maMenuItems[nPos];
     401           0 :         if (rData.mbEnabled)
     402           0 :             nState |= ControlState::ENABLED;
     403             : 
     404             :         bNativeDrawn = rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
     405           0 :                                                         aRegion, nState, ImplControlValue(), OUString());
     406             :     }
     407             : 
     408           0 :     if (!bNativeDrawn)
     409             :     {
     410           0 :         const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings();
     411           0 :         Point aTmpPos = aPos;
     412           0 :         aTmpPos.Y() += aSize.Height() / 2;
     413           0 :         rRenderContext.SetLineColor(rStyle.GetShadowColor());
     414           0 :         rRenderContext.DrawLine(aTmpPos, Point(aSize.Width() + aTmpPos.X(), aTmpPos.Y()));
     415           0 :         ++aTmpPos.Y();
     416           0 :         rRenderContext.SetLineColor(rStyle.GetLightColor());
     417           0 :         rRenderContext.DrawLine(aTmpPos, Point(aSize.Width() + aTmpPos.X(), aTmpPos.Y()));
     418           0 :         rRenderContext.SetLineColor();
     419             :     }
     420           0 : }
     421             : 
     422           0 : void ScMenuFloatingWindow::drawAllMenuItems(vcl::RenderContext& rRenderContext)
     423             : {
     424           0 :     size_t n = maMenuItems.size();
     425             : 
     426           0 :     for (size_t i = 0; i < n; ++i)
     427             :     {
     428           0 :         if (maMenuItems[i].mbSeparator)
     429             :         {
     430             :             // Separator
     431           0 :             drawSeparator(rRenderContext, i);
     432             :         }
     433             :         else
     434             :         {
     435             :             // Normal menu item
     436           0 :             highlightMenuItem(rRenderContext, i, i == mnSelectedMenu);
     437             :         }
     438             :     }
     439           0 : }
     440             : 
     441           0 : void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
     442             : {
     443           0 :     if (nPos >= maMenuItems.size())
     444           0 :         return;
     445             : 
     446           0 :     if (!maMenuItems[nPos].mpAction)
     447             :         // no action is defined.
     448           0 :         return;
     449             : 
     450           0 :     maMenuItems[nPos].mpAction->execute();
     451           0 :     terminateAllPopupMenus();
     452             : }
     453             : 
     454           0 : void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
     455             : {
     456           0 :     if (mnSelectedMenu == nPos)
     457             :         // nothing to do.
     458           0 :         return;
     459             : 
     460           0 :     if (bEnsureSubMenu)
     461             :     {
     462             :         // Dismiss any child popup menu windows.
     463           0 :         if (mnSelectedMenu < maMenuItems.size() &&
     464           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     465           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     466             :         {
     467           0 :             maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     468             :         }
     469             : 
     470             :         // The popup is not visible, yet a menu item is selected.  The request
     471             :         // most likely comes from the accessible object.  Make sure this
     472             :         // window, as well as all its parent windows are visible.
     473           0 :         if (!IsVisible() && mpParentMenu)
     474           0 :             mpParentMenu->ensureSubMenuVisible(this);
     475             :     }
     476             : 
     477           0 :     selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
     478           0 :     selectMenuItem(nPos, true, bSubMenuTimer);
     479           0 :     mnSelectedMenu = nPos;
     480             : 
     481           0 :     fireMenuHighlightedEvent();
     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 :             Invalidate();
     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 :     FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
     563           0 :     SetPopupModeFlags(nOldFlags | FloatWinPopupFlags::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), (FloatWinPopupFlags::Right | FloatWinPopupFlags::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 :         mnSelectedMenu = nMenuPos;
     585           0 :         Invalidate();
     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 :     Invalidate();
     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 : void ScMenuFloatingWindow::highlightMenuItem(vcl::RenderContext& rRenderContext, size_t nPos, bool bSelected)
     664             : {
     665           0 :     if (nPos == MENU_NOT_SELECTED)
     666           0 :         return;
     667             : 
     668           0 :     const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings();
     669           0 :     Color aBackColor = rStyle.GetMenuColor();
     670           0 :     rRenderContext.SetFillColor(aBackColor);
     671           0 :     rRenderContext.SetLineColor(aBackColor);
     672             : 
     673           0 :     Point aPos;
     674           0 :     Size aSize;
     675           0 :     getMenuItemPosSize(nPos, aPos, aSize);
     676           0 :     Rectangle aRegion(aPos,aSize);
     677             : 
     678           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     679             :     {
     680           0 :         rRenderContext.Push(PushFlags::CLIPREGION);
     681           0 :         rRenderContext.IntersectClipRegion(Rectangle(aPos, aSize));
     682           0 :         Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
     683             :         rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, aCtrlRect, ControlState::ENABLED,
     684           0 :                                          ImplControlValue(), OUString());
     685           0 :         rRenderContext.Pop();
     686             :     }
     687             : 
     688           0 :     bool bNativeDrawn = true;
     689           0 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
     690             :     {
     691           0 :         ControlState nState = bSelected ? ControlState::SELECTED : ControlState::NONE;
     692           0 :         if (maMenuItems[nPos].mbEnabled)
     693           0 :             nState |= ControlState::ENABLED;
     694             :         bNativeDrawn = rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_ITEM,
     695           0 :                                                         aRegion, nState, ImplControlValue(), OUString());
     696             :     }
     697             :     else
     698           0 :         bNativeDrawn = false;
     699             : 
     700           0 :     if (!bNativeDrawn)
     701             :     {
     702           0 :         if (bSelected)
     703             :         {
     704           0 :             aBackColor = rStyle.GetMenuHighlightColor();
     705           0 :             rRenderContext.SetFillColor(aBackColor);
     706           0 :             rRenderContext.SetLineColor(aBackColor);
     707             :         }
     708           0 :         rRenderContext.DrawRect(Rectangle(aPos,aSize));
     709             :     }
     710             : 
     711           0 :     Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
     712           0 :     rRenderContext.SetTextColor(aTextColor);
     713           0 :     drawMenuItem(rRenderContext, nPos);
     714             : }
     715             : 
     716           0 : void ScMenuFloatingWindow::getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const
     717             : {
     718           0 :     size_t nCount = maMenuItems.size();
     719           0 :     if (nPos >= nCount)
     720           0 :         return;
     721             : 
     722           0 :     const sal_uInt16 nLeftMargin = 5;
     723           0 :     const sal_uInt16 nTopMargin = 5;
     724           0 :     const sal_uInt16 nMenuItemHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*1.8);
     725           0 :     const sal_uInt16 nSepHeight = static_cast<sal_uInt16>(maLabelFont.GetHeight()*0.8);
     726             : 
     727           0 :     Point aPos1(nLeftMargin, nTopMargin);
     728           0 :     rPos = aPos1;
     729           0 :     for (size_t i = 0; i < nPos; ++i)
     730           0 :         rPos.Y() += maMenuItems[i].mbSeparator ? nSepHeight : nMenuItemHeight;
     731             : 
     732           0 :     Size aWndSize = GetSizePixel();
     733           0 :     sal_uInt16 nH = maMenuItems[nPos].mbSeparator ? nSepHeight : nMenuItemHeight;
     734           0 :     rSize = Size(aWndSize.Width() - nLeftMargin*2, nH);
     735             : }
     736             : 
     737           0 : size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
     738             : {
     739           0 :     size_t n = maMenuItems.size();
     740           0 :     for (size_t i = 0; i < n; ++i)
     741             :     {
     742           0 :         Point aPos;
     743           0 :         Size aSize;
     744           0 :         getMenuItemPosSize(i, aPos, aSize);
     745           0 :         Rectangle aRect(aPos, aSize);
     746           0 :         if (aRect.IsInside(rPos))
     747           0 :             return maMenuItems[i].mbSeparator ? MENU_NOT_SELECTED : i;
     748             :     }
     749           0 :     return MENU_NOT_SELECTED;
     750             : }
     751             : 
     752           0 : size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
     753             : {
     754           0 :     size_t n = maMenuItems.size();
     755           0 :     for (size_t i = 0; i < n; ++i)
     756             :     {
     757           0 :         if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu)
     758           0 :             return i;
     759             :     }
     760           0 :     return MENU_NOT_SELECTED;
     761             : }
     762             : 
     763           0 : void ScMenuFloatingWindow::fireMenuHighlightedEvent()
     764             : {
     765           0 :     if (mnSelectedMenu == MENU_NOT_SELECTED)
     766           0 :         return;
     767             : 
     768           0 :     if (!mxAccessible.is())
     769           0 :         return;
     770             : 
     771           0 :     Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext();
     772           0 :     if (!xAccCxt.is())
     773           0 :         return;
     774             : 
     775           0 :     Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu);
     776           0 :     if (!xAccMenu.is())
     777           0 :         return;
     778             : 
     779           0 :     VclAccessibleEvent aEvent(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
     780           0 :     FireVclEvent(&aEvent);
     781             : }
     782             : 
     783           0 : void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
     784             : {
     785           0 :     maCloseTimer.reset();
     786           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     787           0 :     if (mnSelectedMenu != nMenuPos)
     788             :     {
     789           0 :         mnSelectedMenu = nMenuPos;
     790           0 :         Invalidate();
     791             :     }
     792           0 : }
     793             : 
     794           0 : void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
     795             : {
     796           0 :     if (mpParentMenu)
     797           0 :         mpParentMenu->ensureSubMenuVisible(this);
     798             : 
     799           0 :     if (pSubMenu->IsVisible())
     800           0 :         return;
     801             : 
     802             :     // Find the menu position of the submenu.
     803           0 :     size_t nMenuPos = getSubMenuPos(pSubMenu);
     804           0 :     if (nMenuPos != MENU_NOT_SELECTED)
     805             :     {
     806           0 :         setSelectedMenuItem(nMenuPos, false, false);
     807             : 
     808           0 :         Point aPos;
     809           0 :         Size aSize;
     810           0 :         getMenuItemPosSize(nMenuPos, aPos, aSize);
     811             : 
     812           0 :         FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
     813           0 :         SetPopupModeFlags(nOldFlags | FloatWinPopupFlags::NoAppFocusClose);
     814           0 :         pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
     815             :         pSubMenu->StartPopupMode(
     816           0 :             Rectangle(aPos,aSize), (FloatWinPopupFlags::Right | FloatWinPopupFlags::GrabFocus));
     817           0 :         pSubMenu->AddPopupModeWindow(this);
     818           0 :         SetPopupModeFlags(nOldFlags);
     819             :     }
     820             : }
     821             : 
     822           0 : void ScMenuFloatingWindow::ensureSubMenuNotVisible()
     823             : {
     824           0 :     if (mnSelectedMenu <= maMenuItems.size() &&
     825           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin &&
     826           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
     827             :     {
     828           0 :         maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
     829             :     }
     830             : 
     831           0 :     EndPopupMode();
     832           0 : }
     833             : 
     834           0 : void ScMenuFloatingWindow::terminateAllPopupMenus()
     835             : {
     836           0 :     EndPopupMode();
     837           0 :     if (mpParentMenu)
     838           0 :         mpParentMenu->terminateAllPopupMenus();
     839           0 : }
     840             : 
     841           0 : ScCheckListMenuWindow::Config::Config() :
     842           0 :     mbAllowEmptySet(true), mbRTL(false)
     843             : {
     844           0 : }
     845             : 
     846           0 : ScCheckListMenuWindow::Member::Member()
     847             :     : mbVisible(true)
     848             :     , mbDate(false)
     849             :     , mbLeaf(false)
     850           0 :     , mpParent(NULL)
     851             : {
     852           0 : }
     853             : 
     854           0 : ScCheckListMenuWindow::CancelButton::CancelButton(ScCheckListMenuWindow* pParent) :
     855           0 :     ::CancelButton(pParent), mpParent(pParent) {}
     856             : 
     857           0 : ScCheckListMenuWindow::CancelButton::~CancelButton()
     858             : {
     859           0 :     disposeOnce();
     860           0 : }
     861             : 
     862           0 : void ScCheckListMenuWindow::CancelButton::dispose()
     863             : {
     864           0 :     mpParent.clear();
     865           0 :     ::CancelButton::dispose();
     866           0 : }
     867             : 
     868           0 : void ScCheckListMenuWindow::CancelButton::Click()
     869             : {
     870           0 :     mpParent->EndPopupMode();
     871           0 :     ::CancelButton::Click();
     872           0 : }
     873             : 
     874           0 : ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc) :
     875             :     ScMenuFloatingWindow(pParent, pDoc),
     876             :     maEdSearch(VclPtr<Edit>::Create(this)),
     877             :     maChecks(VclPtr<ScCheckListBox>::Create(this,  WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT) ),
     878             :     maChkToggleAll(VclPtr<TriStateBox>::Create(this, 0)),
     879             :     maBtnSelectSingle(VclPtr<ImageButton>::Create(this, 0)),
     880             :     maBtnUnselectSingle(VclPtr<ImageButton>::Create(this, 0)),
     881             :     maBtnOk(VclPtr<OKButton>::Create(this)),
     882             :     maBtnCancel(VclPtr<CancelButton>::Create(this)),
     883             :     mnCurTabStop(0),
     884             :     mpExtendedData(NULL),
     885             :     mpOKAction(NULL),
     886             :     mpPopupEndAction(NULL),
     887             :     maWndSize(),
     888           0 :     mePrevToggleAllState(TRISTATE_INDET)
     889             : {
     890           0 :     sal_Int32 nScaleFactor = GetDPIScaleFactor();
     891             : 
     892           0 :     maWndSize = Size(200 * nScaleFactor, 330 * nScaleFactor);
     893             : 
     894           0 :     maTabStopCtrls.reserve(8);
     895           0 :     maTabStopCtrls.push_back(this);
     896           0 :     maTabStopCtrls.push_back(maEdSearch.get());
     897           0 :     maTabStopCtrls.push_back(maChecks.get());
     898           0 :     maTabStopCtrls.push_back(maChkToggleAll.get());
     899           0 :     maTabStopCtrls.push_back(maBtnSelectSingle.get());
     900           0 :     maTabStopCtrls.push_back(maBtnUnselectSingle.get());
     901           0 :     maTabStopCtrls.push_back(maBtnOk.get());
     902           0 :     maTabStopCtrls.push_back(maBtnCancel.get());
     903             : 
     904             :     // Enable type-ahead search in the check list box.
     905           0 :     maChecks->SetStyle(maChecks->GetStyle() | WB_QUICK_SEARCH);
     906           0 : }
     907             : 
     908           0 : ScCheckListMenuWindow::~ScCheckListMenuWindow()
     909             : {
     910           0 :     disposeOnce();
     911           0 : }
     912             : 
     913           0 : void ScCheckListMenuWindow::dispose()
     914             : {
     915           0 :     maEdSearch.disposeAndClear();
     916           0 :     maChecks.disposeAndClear();
     917           0 :     maChkToggleAll.disposeAndClear();
     918           0 :     maBtnSelectSingle.disposeAndClear();
     919           0 :     maBtnUnselectSingle.disposeAndClear();
     920           0 :     maBtnOk.disposeAndClear();
     921           0 :     maBtnCancel.disposeAndClear();
     922           0 :     ScMenuFloatingWindow::dispose();
     923           0 : }
     924             : 
     925           0 : void ScCheckListMenuWindow::getSectionPosSize(
     926             :     Point& rPos, Size& rSize, SectionType eType) const
     927             : {
     928           0 :     sal_Int32 nScaleFactor = GetDPIScaleFactor();
     929             : 
     930             :     // constant parameters.
     931           0 :     const long nSearchBoxMargin = 10 *nScaleFactor;
     932           0 :     const long nListBoxMargin = 5 * nScaleFactor;            // horizontal distance from the side of the dialog to the listbox border.
     933           0 :     const long nListBoxInnerPadding = 5 * nScaleFactor;
     934           0 :     const long nTopMargin = 5 * nScaleFactor;
     935           0 :     const long nMenuHeight = maMenuSize.getHeight();
     936           0 :     const long nSingleItemBtnAreaHeight = 32 * nScaleFactor; // height of the middle area below the list box where the single-action buttons are.
     937           0 :     const long nBottomBtnAreaHeight = 50 * nScaleFactor;     // height of the bottom area where the OK and Cancel buttons are.
     938           0 :     const long nBtnWidth = 90 * nScaleFactor;
     939           0 :     const long nLabelHeight = getLabelFont().GetHeight();
     940           0 :     const long nBtnHeight = nLabelHeight * 2;
     941           0 :     const long nBottomMargin = 10 * nScaleFactor;
     942           0 :     const long nMenuListMargin = 5 * nScaleFactor;
     943           0 :     const long nSearchBoxHeight = nLabelHeight * 2;
     944             : 
     945             :     // parameters calculated from constants.
     946           0 :     const long nListBoxWidth = maWndSize.Width() - nListBoxMargin*2;
     947           0 :     const long nListBoxHeight = maWndSize.Height() - nTopMargin - nMenuHeight -
     948           0 :         nMenuListMargin - nSearchBoxHeight - nSearchBoxMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight;
     949             : 
     950           0 :     const long nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin + nSearchBoxHeight + nSearchBoxMargin - 1;
     951             : 
     952           0 :     switch (eType)
     953             :     {
     954             :         case WHOLE:
     955             :         {
     956           0 :             rPos  = Point(0, 0);
     957           0 :             rSize = maWndSize;
     958             :         }
     959           0 :         break;
     960             :         case EDIT_SEARCH:
     961             :         {
     962           0 :             rPos = Point(nSearchBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
     963           0 :             rSize = Size(maWndSize.Width() - 2*nSearchBoxMargin, nSearchBoxHeight);
     964             :         }
     965           0 :         break;
     966             :         case LISTBOX_AREA_OUTER:
     967             :         {
     968           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin + nSearchBoxHeight + nSearchBoxMargin);
     969           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     970             :         }
     971           0 :         break;
     972             :         case LISTBOX_AREA_INNER:
     973             :         {
     974           0 :             rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin + nSearchBoxHeight + nSearchBoxMargin);
     975           0 :             rPos.X() += nListBoxInnerPadding;
     976           0 :             rPos.Y() += nListBoxInnerPadding;
     977             : 
     978           0 :             rSize = Size(nListBoxWidth, nListBoxHeight);
     979           0 :             rSize.Width()  -= nListBoxInnerPadding*2;
     980           0 :             rSize.Height() -= nListBoxInnerPadding*2;
     981             :         }
     982           0 :         break;
     983             :         case SINGLE_BTN_AREA:
     984             :         {
     985           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     986           0 :             rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
     987             :         }
     988           0 :         break;
     989             :         case CHECK_TOGGLE_ALL:
     990             :         {
     991           0 :             long h = std::min(maChkToggleAll->CalcMinimumSize().Height(), 26L);
     992           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
     993           0 :             rPos.X() += 5;
     994           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
     995           0 :             rSize = Size(70, h);
     996             :         }
     997           0 :         break;
     998             :         case BTN_SINGLE_SELECT:
     999             :         {
    1000           0 :             long h = 26 * nScaleFactor;
    1001           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
    1002           0 :             rPos.X() += nListBoxWidth - h - 10 - h - 10;
    1003           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
    1004           0 :             rSize = Size(h, h);
    1005             :         }
    1006           0 :         break;
    1007             :         case BTN_SINGLE_UNSELECT:
    1008             :         {
    1009           0 :             long h = 26 * nScaleFactor;
    1010           0 :             rPos = Point(nListBoxMargin, nSingleBtnAreaY);
    1011           0 :             rPos.X() += nListBoxWidth - h - 10;
    1012           0 :             rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
    1013           0 :             rSize = Size(h, h);
    1014             :         }
    1015           0 :         break;
    1016             :         case BTN_OK:
    1017             :         {
    1018           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3;
    1019           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
    1020           0 :             rPos = Point(x, y);
    1021           0 :             rSize = Size(nBtnWidth, nBtnHeight);
    1022             :         }
    1023           0 :         break;
    1024             :         case BTN_CANCEL:
    1025             :         {
    1026           0 :             long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
    1027           0 :             long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
    1028           0 :             rPos = Point(x, y);
    1029           0 :             rSize = Size(nBtnWidth, nBtnHeight);
    1030             :         }
    1031           0 :         break;
    1032             :         default:
    1033             :             ;
    1034             :     }
    1035           0 : }
    1036             : 
    1037           0 : void ScCheckListMenuWindow::packWindow()
    1038             : {
    1039           0 :     maMenuSize = getMenuSize();
    1040             : 
    1041           0 :     if (maWndSize.Width() < maMenuSize.Width())
    1042             :         // Widen the window to fit the menu items.
    1043           0 :         maWndSize.Width() = maMenuSize.Width();
    1044             : 
    1045             :     // Set proper window height based on the number of menu items.
    1046           0 :     if (maWndSize.Height() < maMenuSize.Height()*2.8)
    1047           0 :         maWndSize.Height() = maMenuSize.Height()*2.8;
    1048             : 
    1049             :     // TODO: Make sure the window height never exceeds the height of the
    1050             :     // screen. Also do adjustment based on the number of check box items.
    1051             : 
    1052           0 :     SetOutputSizePixel(maWndSize);
    1053             : 
    1054           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1055             : 
    1056           0 :     Point aPos;
    1057           0 :     Size aSize;
    1058           0 :     getSectionPosSize(aPos, aSize, WHOLE);
    1059           0 :     SetOutputSizePixel(aSize);
    1060             : 
    1061           0 :     getSectionPosSize(aPos, aSize, BTN_OK);
    1062           0 :     maBtnOk->SetPosSizePixel(aPos, aSize);
    1063           0 :     maBtnOk->SetFont(getLabelFont());
    1064           0 :     maBtnOk->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1065           0 :     maBtnOk->Show();
    1066             : 
    1067           0 :     getSectionPosSize(aPos, aSize, BTN_CANCEL);
    1068           0 :     maBtnCancel->SetPosSizePixel(aPos, aSize);
    1069           0 :     maBtnCancel->SetFont(getLabelFont());
    1070           0 :     maBtnCancel->Show();
    1071             : 
    1072           0 :     getSectionPosSize(aPos, aSize, EDIT_SEARCH);
    1073           0 :     maEdSearch->SetPosSizePixel(aPos, aSize);
    1074           0 :     maEdSearch->SetFont(getLabelFont());
    1075           0 :     maEdSearch->SetControlBackground(rStyle.GetFieldColor());
    1076           0 :     maEdSearch->SetPlaceholderText(SC_STRLOAD(RID_POPUP_FILTER, STR_EDIT_SEARCH_ITEMS));
    1077           0 :     maEdSearch->SetModifyHdl( LINK(this, ScCheckListMenuWindow, EdModifyHdl) );
    1078           0 :     maEdSearch->Show();
    1079             : 
    1080           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER);
    1081           0 :     maChecks->SetPosSizePixel(aPos, aSize);
    1082           0 :     maChecks->SetFont(getLabelFont());
    1083           0 :     maChecks->SetCheckButtonHdl( LINK(this, ScCheckListMenuWindow, CheckHdl) );
    1084           0 :     maChecks->Show();
    1085             : 
    1086           0 :     getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL);
    1087           0 :     maChkToggleAll->SetPosSizePixel(aPos, aSize);
    1088           0 :     maChkToggleAll->SetFont(getLabelFont());
    1089           0 :     maChkToggleAll->SetText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL));
    1090           0 :     maChkToggleAll->SetTextColor(rStyle.GetMenuTextColor());
    1091           0 :     maChkToggleAll->SetControlBackground(rStyle.GetMenuColor());
    1092           0 :     maChkToggleAll->SetClickHdl( LINK(this, ScCheckListMenuWindow, TriStateHdl) );
    1093           0 :     maChkToggleAll->Show();
    1094             : 
    1095           0 :     sal_Int32 nScaleFactor = GetDPIScaleFactor();
    1096             : 
    1097           0 :     Image aSingleSelect(ScResId(RID_IMG_SELECT_CURRENT));
    1098           0 :     if (nScaleFactor != 1)
    1099             :     {
    1100           0 :         BitmapEx aBitmap = aSingleSelect.GetBitmapEx();
    1101           0 :         aBitmap.Scale(nScaleFactor, nScaleFactor, BmpScaleFlag::Fast);
    1102           0 :         aSingleSelect = Image(aBitmap);
    1103             :     }
    1104             : 
    1105           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
    1106           0 :     maBtnSelectSingle->SetPosSizePixel(aPos, aSize);
    1107           0 :     maBtnSelectSingle->SetQuickHelpText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT));
    1108           0 :     maBtnSelectSingle->SetModeImage(aSingleSelect);
    1109           0 :     maBtnSelectSingle->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1110           0 :     maBtnSelectSingle->Show();
    1111             : 
    1112           0 :     Image aSingleUnselect(ScResId(RID_IMG_UNSELECT_CURRENT));
    1113           0 :     if (nScaleFactor != 1)
    1114             :     {
    1115           0 :         BitmapEx aBitmap = aSingleUnselect.GetBitmapEx();
    1116           0 :         aBitmap.Scale(nScaleFactor, nScaleFactor, BmpScaleFlag::Fast);
    1117           0 :         aSingleUnselect = Image(aBitmap);
    1118             :     }
    1119             : 
    1120           0 :     getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
    1121           0 :     maBtnUnselectSingle->SetPosSizePixel(aPos, aSize);
    1122           0 :     maBtnUnselectSingle->SetQuickHelpText(SC_STRLOAD(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT));
    1123           0 :     maBtnUnselectSingle->SetModeImage(aSingleUnselect);
    1124           0 :     maBtnUnselectSingle->SetClickHdl( LINK(this, ScCheckListMenuWindow, ButtonHdl) );
    1125           0 :     maBtnUnselectSingle->Show();
    1126           0 : }
    1127             : 
    1128           0 : void ScCheckListMenuWindow::setAllMemberState(bool bSet)
    1129             : {
    1130           0 :     size_t n = maMembers.size();
    1131           0 :     OUString aLabel;
    1132           0 :     for (size_t i = 0; i < n; ++i) {
    1133           0 :         aLabel = maMembers[i].maName;
    1134           0 :         if (aLabel.isEmpty())
    1135           0 :             aLabel = ScGlobal::GetRscString(STR_EMPTYDATA);
    1136           0 :         maChecks->ShowCheckEntry( aLabel, maMembers[i].mpParent, true, bSet);
    1137             :     }
    1138             : 
    1139           0 :     if (!maConfig.mbAllowEmptySet)
    1140             :         // We need to have at least one member selected.
    1141           0 :         maBtnOk->Enable(maChecks->GetCheckedEntryCount() != 0);
    1142           0 : }
    1143             : 
    1144           0 : void ScCheckListMenuWindow::selectCurrentMemberOnly(bool bSet)
    1145             : {
    1146           0 :     setAllMemberState(!bSet);
    1147           0 :     SvTreeListEntry* pEntry = maChecks->GetCurEntry();
    1148           0 :     if (!pEntry)
    1149           0 :         return;
    1150           0 :     maChecks->CheckEntry(pEntry, bSet );
    1151             : }
    1152             : 
    1153           0 : void ScCheckListMenuWindow::cycleFocus(bool bReverse)
    1154             : {
    1155           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
    1156           0 :     maTabStopCtrls[mnCurTabStop]->LoseFocus();
    1157           0 :     if (mnCurTabStop == 0)
    1158           0 :         clearSelectedMenuItem();
    1159             : 
    1160           0 :     if (bReverse)
    1161             :     {
    1162           0 :         if (mnCurTabStop > 0)
    1163           0 :             --mnCurTabStop;
    1164             :         else
    1165           0 :             mnCurTabStop = maTabStopCtrls.size() - 1;
    1166             :     }
    1167             :     else
    1168             :     {
    1169           0 :         ++mnCurTabStop;
    1170           0 :         if (mnCurTabStop >= maTabStopCtrls.size())
    1171           0 :             mnCurTabStop = 0;
    1172             :     }
    1173           0 :     maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
    1174           0 :     maTabStopCtrls[mnCurTabStop]->GrabFocus();
    1175           0 : }
    1176             : 
    1177           0 : IMPL_LINK( ScCheckListMenuWindow, ButtonHdl, Button*, pBtn )
    1178             : {
    1179           0 :     if (pBtn == maBtnOk.get())
    1180           0 :         close(true);
    1181           0 :     else if (pBtn == maBtnSelectSingle.get())
    1182             :     {
    1183           0 :         selectCurrentMemberOnly(true);
    1184           0 :         CheckHdl(maChecks.get());
    1185             :     }
    1186           0 :     else if (pBtn == maBtnUnselectSingle.get())
    1187             :     {
    1188           0 :         selectCurrentMemberOnly(false);
    1189           0 :         CheckHdl(maChecks.get());
    1190             :     }
    1191           0 :     return 0;
    1192             : }
    1193             : 
    1194           0 : IMPL_LINK_NOARG(ScCheckListMenuWindow, TriStateHdl)
    1195             : {
    1196           0 :     switch (mePrevToggleAllState)
    1197             :     {
    1198             :         case TRISTATE_FALSE:
    1199           0 :             maChkToggleAll->SetState(TRISTATE_TRUE);
    1200           0 :             setAllMemberState(true);
    1201           0 :         break;
    1202             :         case TRISTATE_TRUE:
    1203           0 :             maChkToggleAll->SetState(TRISTATE_FALSE);
    1204           0 :             setAllMemberState(false);
    1205           0 :         break;
    1206             :         case TRISTATE_INDET:
    1207             :         default:
    1208           0 :             maChkToggleAll->SetState(TRISTATE_TRUE);
    1209           0 :             setAllMemberState(true);
    1210           0 :         break;
    1211             :     }
    1212             : 
    1213           0 :     mePrevToggleAllState = maChkToggleAll->GetState();
    1214           0 :     return 0;
    1215             : }
    1216             : 
    1217           0 : IMPL_LINK_NOARG(ScCheckListMenuWindow, EdModifyHdl)
    1218             : {
    1219           0 :     OUString aSearchText = maEdSearch->GetText();
    1220           0 :     aSearchText = aSearchText.toAsciiLowerCase();
    1221           0 :     bool bSearchTextEmpty = aSearchText.isEmpty();
    1222           0 :     size_t n = maMembers.size();
    1223           0 :     size_t nSelCount = 0;
    1224           0 :     OUString aLabelDisp;
    1225             : 
    1226           0 :     for (size_t i = 0; i < n; ++i)
    1227             :     {
    1228           0 :         aLabelDisp = maMembers[i].maName;
    1229             : 
    1230           0 :         if ( aLabelDisp.isEmpty() )
    1231           0 :             aLabelDisp = ScGlobal::GetRscString( STR_EMPTYDATA );
    1232             : 
    1233           0 :         if ( bSearchTextEmpty )
    1234             :         {
    1235           0 :             maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent, true, maMembers[i].mbVisible );
    1236           0 :             if ( maMembers[i].mbVisible )
    1237           0 :                 ++nSelCount;
    1238           0 :             continue;
    1239             :         }
    1240             : 
    1241           0 :         if ( aLabelDisp.toAsciiLowerCase().indexOf( aSearchText ) != -1 )
    1242             :         {
    1243           0 :             maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent, true, true );
    1244           0 :             ++nSelCount;
    1245             :         }
    1246             :         else
    1247           0 :             maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent, false, false );
    1248             :     }
    1249             : 
    1250           0 :     if ( nSelCount == n )
    1251           0 :         maChkToggleAll->SetState( TRISTATE_TRUE );
    1252           0 :     else if ( nSelCount == 0 )
    1253           0 :         maChkToggleAll->SetState( TRISTATE_FALSE );
    1254             :     else
    1255           0 :         maChkToggleAll->SetState( TRISTATE_INDET );
    1256             : 
    1257           0 :     return 0;
    1258             : }
    1259             : 
    1260           0 : IMPL_LINK( ScCheckListMenuWindow, CheckHdl, SvTreeListBox*, pChecks )
    1261             : {
    1262           0 :     if (pChecks != maChecks.get())
    1263           0 :         return 0;
    1264           0 :     SvTreeListEntry* pEntry = pChecks->GetHdlEntry();
    1265           0 :     if ( pEntry )
    1266           0 :         maChecks->CheckEntry( pEntry,  ( pChecks->GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) );
    1267           0 :     size_t nNumChecked = maChecks->GetCheckedEntryCount();
    1268           0 :     if (nNumChecked == maMembers.size())
    1269             :         // all members visible
    1270           0 :         maChkToggleAll->SetState(TRISTATE_TRUE);
    1271           0 :     else if (nNumChecked == 0)
    1272             :         // no members visible
    1273           0 :         maChkToggleAll->SetState(TRISTATE_FALSE);
    1274             :     else
    1275           0 :         maChkToggleAll->SetState(TRISTATE_INDET);
    1276             : 
    1277           0 :     if (!maConfig.mbAllowEmptySet)
    1278             :         // We need to have at least one member selected.
    1279           0 :         maBtnOk->Enable(nNumChecked != 0);
    1280             : 
    1281           0 :     mePrevToggleAllState = maChkToggleAll->GetState();
    1282           0 :     return 0;
    1283             : }
    1284             : 
    1285           0 : void ScCheckListMenuWindow::MouseMove(const MouseEvent& rMEvt)
    1286             : {
    1287           0 :     ScMenuFloatingWindow::MouseMove(rMEvt);
    1288             : 
    1289           0 :     size_t nSelectedMenu = getSelectedMenuItem();
    1290           0 :     if (nSelectedMenu == MENU_NOT_SELECTED)
    1291           0 :         queueCloseSubMenu();
    1292           0 : }
    1293             : 
    1294           0 : bool ScCheckListMenuWindow::Notify(NotifyEvent& rNEvt)
    1295             : {
    1296           0 :     if (rNEvt.GetType() == MouseNotifyEvent::KEYUP)
    1297             :     {
    1298           0 :         const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
    1299           0 :         const vcl::KeyCode& rCode = pKeyEvent->GetKeyCode();
    1300           0 :         bool bShift = rCode.IsShift();
    1301           0 :         if (rCode.GetCode() == KEY_TAB)
    1302             :         {
    1303           0 :             cycleFocus(bShift);
    1304           0 :             return true;
    1305             :         }
    1306             :     }
    1307           0 :     return ScMenuFloatingWindow::Notify(rNEvt);
    1308             : }
    1309             : 
    1310           0 : void ScCheckListMenuWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
    1311             : {
    1312           0 :     ScMenuFloatingWindow::Paint(rRenderContext, rRect);
    1313             : 
    1314           0 :     const StyleSettings& rStyle = GetSettings().GetStyleSettings();
    1315           0 :     Color aMemberBackColor = rStyle.GetFieldColor();
    1316           0 :     Color aBorderColor = rStyle.GetShadowColor();
    1317             : 
    1318           0 :     Point aPos;
    1319           0 :     Size aSize;
    1320           0 :     getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
    1321             : 
    1322             :     // Member list box background
    1323           0 :     rRenderContext.SetFillColor(aMemberBackColor);
    1324           0 :     rRenderContext.SetLineColor(aBorderColor);
    1325           0 :     rRenderContext.DrawRect(Rectangle(aPos,aSize));
    1326             : 
    1327             :     // Single-action button box
    1328           0 :     getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
    1329           0 :     rRenderContext.SetFillColor(rStyle.GetMenuColor());
    1330           0 :     rRenderContext.DrawRect(Rectangle(aPos,aSize));
    1331           0 : }
    1332             : 
    1333           0 : vcl::Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow()
    1334             : {
    1335           0 :     return maTabStopCtrls[mnCurTabStop];
    1336             : }
    1337             : 
    1338           0 : Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible()
    1339             : {
    1340           0 :     if (!mxAccessible.is())
    1341             :     {
    1342             :         mxAccessible.set(new ScAccessibleFilterTopWindow(
    1343           0 :             GetAccessibleParentWindow()->GetAccessible(), this, getName()));
    1344           0 :         ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
    1345           0 :         fillMenuItemsToAccessible(pAccTop);
    1346             : 
    1347             :         pAccTop->setAccessibleChild(
    1348           0 :             maEdSearch->CreateAccessible(), ScAccessibleFilterTopWindow::EDIT_SEARCH_BOX);
    1349             :         pAccTop->setAccessibleChild(
    1350           0 :             maChecks->CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
    1351             :         pAccTop->setAccessibleChild(
    1352           0 :             maChkToggleAll->CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
    1353             :         pAccTop->setAccessibleChild(
    1354           0 :             maBtnSelectSingle->CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
    1355             :         pAccTop->setAccessibleChild(
    1356           0 :             maBtnUnselectSingle->CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
    1357             :         pAccTop->setAccessibleChild(
    1358           0 :             maBtnOk->CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
    1359             :         pAccTop->setAccessibleChild(
    1360           0 :             maBtnCancel->CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
    1361             :     }
    1362             : 
    1363           0 :     return mxAccessible;
    1364             : }
    1365             : 
    1366           0 : void ScCheckListMenuWindow::setMemberSize(size_t n)
    1367             : {
    1368           0 :     maMembers.reserve(n);
    1369           0 : }
    1370             : 
    1371           0 : void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, bool bVisible)
    1372             : {
    1373           0 :     ScDocument* pDoc = getDoc();
    1374           0 :     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
    1375             : 
    1376             :     // Convert the numeric date value to a date object.
    1377           0 :     Date aDate = *(pFormatter->GetNullDate());
    1378           0 :     aDate += static_cast<long>(rtl::math::approxFloor(nVal));
    1379             : 
    1380           0 :     sal_uInt16 nYear = aDate.GetYear();
    1381           0 :     sal_uInt16 nMonth = aDate.GetMonth();
    1382           0 :     sal_uInt16 nDay = aDate.GetDay();
    1383             : 
    1384             :     // Get the localized month name list.
    1385           0 :     CalendarWrapper* pCalendar = ScGlobal::GetCalendar();
    1386           0 :     uno::Sequence<i18n::CalendarItem2> aMonths = pCalendar->getMonths();
    1387           0 :     if (aMonths.getLength() < nMonth)
    1388           0 :         return;
    1389             : 
    1390           0 :     OUString aYearName = OUString::number(nYear);
    1391           0 :     OUString aMonthName = aMonths[nMonth-1].FullName;
    1392           0 :     OUString aDayName = OUString::number(nDay);
    1393             : 
    1394           0 :     maChecks->SetUpdateMode(false);
    1395             : 
    1396           0 :     SvTreeListEntry* pYearEntry = maChecks->FindEntry(NULL, aYearName);
    1397           0 :     if (!pYearEntry)
    1398             :     {
    1399           0 :         pYearEntry = maChecks->InsertEntry(aYearName, NULL, true);
    1400           0 :         Member aMemYear;
    1401           0 :         aMemYear.maName = aYearName;
    1402           0 :         aMemYear.maRealName = rsName;
    1403           0 :         aMemYear.mbDate = true;
    1404           0 :         aMemYear.mbLeaf = false;
    1405           0 :         aMemYear.mbVisible = bVisible;
    1406           0 :         aMemYear.mpParent = NULL;
    1407           0 :         maMembers.push_back(aMemYear);
    1408             :     }
    1409             : 
    1410           0 :     SvTreeListEntry* pMonthEntry = maChecks->FindEntry(pYearEntry, aMonthName);
    1411           0 :     if (!pMonthEntry)
    1412             :     {
    1413           0 :         pMonthEntry = maChecks->InsertEntry(aMonthName, pYearEntry, true);
    1414           0 :         Member aMemMonth;
    1415           0 :         aMemMonth.maName = aMonthName;
    1416           0 :         aMemMonth.maRealName = rsName;
    1417           0 :         aMemMonth.mbDate = true;
    1418           0 :         aMemMonth.mbLeaf = false;
    1419           0 :         aMemMonth.mbVisible = bVisible;
    1420           0 :         aMemMonth.mpParent = pYearEntry;
    1421           0 :         maMembers.push_back(aMemMonth);
    1422             :     }
    1423             : 
    1424           0 :     SvTreeListEntry* pDayEntry = maChecks->FindEntry(pMonthEntry, aDayName);
    1425           0 :     if (!pDayEntry)
    1426             :     {
    1427           0 :         maChecks->InsertEntry(aDayName, pMonthEntry, false);
    1428           0 :         Member aMemDay;
    1429           0 :         aMemDay.maName = aDayName;
    1430           0 :         aMemDay.maRealName = rsName;
    1431           0 :         aMemDay.mbDate = true;
    1432           0 :         aMemDay.mbLeaf = true;
    1433           0 :         aMemDay.mbVisible = bVisible;
    1434           0 :         aMemDay.mpParent = pMonthEntry;
    1435           0 :         maMembers.push_back(aMemDay);
    1436             :     }
    1437             : 
    1438           0 :     maChecks->SetUpdateMode(true);
    1439             : }
    1440             : 
    1441           0 : void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible)
    1442             : {
    1443           0 :     Member aMember;
    1444           0 :     aMember.maName = rName;
    1445           0 :     aMember.mbDate = false;
    1446           0 :     aMember.mbLeaf = true;
    1447           0 :     aMember.mbVisible = bVisible;
    1448           0 :     aMember.mpParent = NULL;
    1449           0 :     maMembers.push_back(aMember);
    1450           0 : }
    1451             : 
    1452           0 : ScCheckListBox::ScCheckListBox( vcl::Window* pParent, WinBits nWinStyle )
    1453           0 :    :  SvTreeListBox( pParent, nWinStyle ), mpCheckButton( NULL )
    1454             : {
    1455           0 :     Init();
    1456           0 : }
    1457             : 
    1458           0 : SvTreeListEntry* ScCheckListBox::FindEntry( SvTreeListEntry* pParent, const OUString& sNode )
    1459             : {
    1460           0 :     sal_uInt16 nRootPos = 0;
    1461           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos );
    1462           0 :     while ( pEntry )
    1463             :     {
    1464           0 :         if (  sNode.equals(GetEntryText( pEntry )) )
    1465           0 :             return pEntry;
    1466             : 
    1467           0 :         pEntry = pParent ? NextSibling( pEntry ) : GetEntry( ++nRootPos );
    1468             :     }
    1469           0 :     return NULL;
    1470             : }
    1471             : 
    1472           0 : void ScCheckListBox::Init()
    1473             : {
    1474           0 :     mpCheckButton = new SvLBoxButtonData( this );
    1475           0 :     EnableCheckButton( mpCheckButton );
    1476           0 :     SetNodeDefaultImages();
    1477           0 : }
    1478             : 
    1479           0 : bool ScCheckListBox::IsChecked( const OUString& sName, SvTreeListEntry* pParent )
    1480             : {
    1481           0 :     SvTreeListEntry* pEntry = FindEntry( pParent, sName );
    1482           0 :     if ( pEntry && GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED)
    1483           0 :         return true;
    1484           0 :     return false;
    1485             : }
    1486             : 
    1487           0 : void ScCheckListBox::CheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bCheck )
    1488             : {
    1489           0 :     SvTreeListEntry* pEntry = FindEntry( pParent, sName );
    1490           0 :     if ( pEntry )
    1491           0 :         CheckEntry(  pEntry, bCheck );
    1492           0 : }
    1493             : 
    1494             : // Recursively check all children of pParent
    1495           0 : void ScCheckListBox::CheckAllChildren( SvTreeListEntry* pParent, bool bCheck )
    1496             : {
    1497           0 :     if ( pParent )
    1498             :     {
    1499             :         SetCheckButtonState(
    1500             :             pParent, bCheck ? SvButtonState( SV_BUTTON_CHECKED ) :
    1501           0 :                                            SvButtonState( SV_BUTTON_UNCHECKED ) );
    1502             :     }
    1503           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1504           0 :     while ( pEntry )
    1505             :     {
    1506           0 :         CheckAllChildren( pEntry, bCheck );
    1507           0 :         pEntry = NextSibling( pEntry );
    1508             :     }
    1509           0 : }
    1510             : 
    1511           0 : void ScCheckListBox::CheckEntry( SvTreeListEntry* pParent, bool bCheck )
    1512             : {
    1513             :     // recursively check all items below pParent
    1514           0 :     CheckAllChildren( pParent, bCheck );
    1515             :     // checking pParent can affect ancestors, e.g. if ancestor is unchecked and pParent is
    1516             :     // now checked then the ancestor needs to be checked also
    1517           0 :     SvTreeListEntry* pAncestor = GetParent(pParent);
    1518           0 :     if ( pAncestor )
    1519             :     {
    1520           0 :         while ( pAncestor )
    1521             :         {
    1522             :             // if any first level children checked then ancestor
    1523             :             // needs to be checked, similarly if no first level children
    1524             :             // checked then ancestor needs to be unchecked
    1525           0 :             SvTreeListEntry* pChild = FirstChild( pAncestor );
    1526           0 :             bool bChildChecked = false;
    1527             : 
    1528           0 :             while ( pChild )
    1529             :             {
    1530           0 :                 if ( GetCheckButtonState( pChild ) == SV_BUTTON_CHECKED )
    1531             :                 {
    1532           0 :                     bChildChecked = true;
    1533           0 :                     break;
    1534             :                 }
    1535           0 :                 pChild = NextSibling( pChild );
    1536             :             }
    1537             :             SetCheckButtonState(
    1538             :                 pAncestor, bChildChecked ? SvButtonState( SV_BUTTON_CHECKED ) :
    1539           0 :                                            SvButtonState( SV_BUTTON_UNCHECKED ) );
    1540           0 :             pAncestor = GetParent(pAncestor);
    1541             :         }
    1542             :     }
    1543           0 : }
    1544             : 
    1545           0 : void ScCheckListBox::ShowCheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bShow, bool bCheck )
    1546             : {
    1547           0 :     SvTreeListEntry* pEntry = FindEntry( pParent, sName );
    1548           0 :     if ( bShow )
    1549             :     {
    1550           0 :         if ( !pEntry )
    1551             :         {
    1552             :             pEntry = InsertEntry(
    1553             :                 sName, NULL, false, TREELIST_APPEND, NULL,
    1554           0 :                 SvLBoxButtonKind_enabledCheckbox);
    1555             : 
    1556             :             SetCheckButtonState(
    1557           0 :                 pEntry, bCheck ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED);
    1558             :         }
    1559             :         else
    1560           0 :             CheckEntry( pEntry, bCheck );
    1561             :     }
    1562           0 :     else if ( pEntry )
    1563           0 :         RemoveParentKeepChildren( pEntry );
    1564           0 : }
    1565             : 
    1566           0 : SvTreeListEntry* ScCheckListBox::CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const
    1567             : {
    1568           0 :     if ( pParent && GetCheckButtonState( pParent ) == SV_BUTTON_CHECKED  )
    1569           0 :         nCount++;
    1570             :     // Iterate over the children
    1571           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1572           0 :     while ( pEntry )
    1573             :     {
    1574           0 :         CountCheckedEntries( pEntry, nCount );
    1575           0 :         pEntry = NextSibling( pEntry );
    1576             :     }
    1577           0 :     return NULL;
    1578             : }
    1579             : 
    1580           0 : sal_uInt16 ScCheckListBox::GetCheckedEntryCount() const
    1581             : {
    1582           0 :     sal_uLong nCount = 0;
    1583           0 :     CountCheckedEntries( NULL,  nCount );
    1584           0 :     return nCount;
    1585             : }
    1586             : 
    1587           0 : void ScCheckListBox::ExpandChildren( SvTreeListEntry* pParent )
    1588             : {
    1589           0 :     if ( pParent )
    1590           0 :         Expand( pParent );
    1591             :     // Iterate over the children
    1592           0 :     SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : First();
    1593           0 :     while ( pEntry )
    1594             :     {
    1595           0 :         ExpandChildren( pEntry );
    1596           0 :         pEntry = NextSibling( pEntry );
    1597             :     }
    1598           0 : }
    1599             : 
    1600           0 : void ScCheckListBox::KeyInput( const KeyEvent& rKEvt )
    1601             : {
    1602           0 :     const vcl::KeyCode& rKey = rKEvt.GetKeyCode();
    1603             : 
    1604           0 :     if ( rKey.GetCode() == KEY_RETURN || rKey.GetCode() == KEY_SPACE )
    1605             :     {
    1606           0 :         SvTreeListEntry* pEntry = GetCurEntry();
    1607           0 :         if ( pEntry )
    1608             :         {
    1609           0 :             bool bCheck = ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED );
    1610           0 :             CheckEntry( pEntry, !bCheck );
    1611           0 :             if ( bCheck != ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) )
    1612           0 :                 CheckButtonHdl();
    1613             :         }
    1614             :     }
    1615           0 :     else if ( GetEntryCount() )
    1616           0 :         SvTreeListBox::KeyInput( rKEvt );
    1617           0 : }
    1618             : 
    1619           0 : void ScCheckListMenuWindow::initMembers()
    1620             : {
    1621           0 :     size_t n = maMembers.size();
    1622           0 :     size_t nVisMemCount = 0;
    1623             : 
    1624           0 :     maChecks->SetUpdateMode(false);
    1625           0 :     maChecks->GetModel()->EnableInvalidate(false);
    1626             : 
    1627           0 :     for (size_t i = 0; i < n; ++i)
    1628             :     {
    1629           0 :         if (maMembers[i].mbDate)
    1630             :         {
    1631           0 :             maChecks->CheckEntry(maMembers[i].maName, maMembers[i].mpParent, maMembers[i].mbVisible);
    1632             :             // Expand first node of checked dates
    1633           0 :             if (!maMembers[i].mpParent && maChecks->IsChecked(maMembers[i].maName,  maMembers[i].mpParent))
    1634             :             {
    1635           0 :                 SvTreeListEntry* pEntry = maChecks->FindEntry(NULL, maMembers[i].maName);
    1636           0 :                 if (pEntry)
    1637           0 :                     maChecks->Expand(pEntry);
    1638             :             }
    1639             :         }
    1640             :         else
    1641             :         {
    1642           0 :             OUString aLabel = maMembers[i].maName;
    1643           0 :             if (aLabel.isEmpty())
    1644           0 :                 aLabel = ScGlobal::GetRscString(STR_EMPTYDATA);
    1645           0 :             SvTreeListEntry* pEntry = maChecks->InsertEntry(
    1646             :                 aLabel, NULL, false, TREELIST_APPEND, NULL,
    1647           0 :                 SvLBoxButtonKind_enabledCheckbox);
    1648             : 
    1649           0 :             maChecks->SetCheckButtonState(
    1650           0 :                 pEntry, maMembers[i].mbVisible ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED);
    1651             :         }
    1652             : 
    1653           0 :         if (maMembers[i].mbVisible)
    1654           0 :             ++nVisMemCount;
    1655             :     }
    1656           0 :     if (nVisMemCount == n)
    1657             :     {
    1658             :         // all members visible
    1659           0 :         maChkToggleAll->SetState(TRISTATE_TRUE);
    1660           0 :         mePrevToggleAllState = TRISTATE_TRUE;
    1661             :     }
    1662           0 :     else if (nVisMemCount == 0)
    1663             :     {
    1664             :         // no members visible
    1665           0 :         maChkToggleAll->SetState(TRISTATE_FALSE);
    1666           0 :         mePrevToggleAllState = TRISTATE_FALSE;
    1667             :     }
    1668             :     else
    1669             :     {
    1670           0 :         maChkToggleAll->SetState(TRISTATE_INDET);
    1671           0 :         mePrevToggleAllState = TRISTATE_INDET;
    1672             :     }
    1673             : 
    1674           0 :     maChecks->GetModel()->EnableInvalidate(true);
    1675           0 :     maChecks->SetUpdateMode(true);
    1676           0 : }
    1677             : 
    1678           0 : void ScCheckListMenuWindow::setConfig(const Config& rConfig)
    1679             : {
    1680           0 :     maConfig = rConfig;
    1681           0 : }
    1682             : 
    1683           0 : bool ScCheckListMenuWindow::isAllSelected() const
    1684             : {
    1685           0 :     return maChkToggleAll->IsChecked();
    1686             : }
    1687             : 
    1688           0 : void ScCheckListMenuWindow::getResult(ResultType& rResult)
    1689             : {
    1690           0 :     ResultType aResult;
    1691           0 :     size_t n = maMembers.size();
    1692           0 :     for (size_t i = 0; i < n; ++i)
    1693             :     {
    1694           0 :         if ( maMembers[i].mbLeaf )
    1695             :         {
    1696           0 :             OUString aLabel = maMembers[i].maName;
    1697           0 :             if (aLabel.isEmpty())
    1698           0 :                 aLabel = ScGlobal::GetRscString(STR_EMPTYDATA);
    1699           0 :             bool bState =  maChecks->IsChecked( aLabel,  maMembers[i].mpParent );
    1700           0 :             OUString sName;
    1701           0 :             if ( maMembers[i].mbDate )
    1702           0 :                 sName = maMembers[i].maRealName;
    1703             :             else
    1704           0 :                 sName = maMembers[i].maName;
    1705           0 :             aResult.insert(ResultType::value_type(sName, bState));
    1706             :         }
    1707             :     }
    1708           0 :     rResult.swap(aResult);
    1709           0 : }
    1710             : 
    1711           0 : void ScCheckListMenuWindow::launch(const Rectangle& rRect)
    1712             : {
    1713           0 :     packWindow();
    1714           0 :     if (!maConfig.mbAllowEmptySet)
    1715             :         // We need to have at least one member selected.
    1716           0 :         maBtnOk->Enable(maChecks->GetCheckedEntryCount() != 0);
    1717             : 
    1718           0 :     Rectangle aRect(rRect);
    1719           0 :     if (maConfig.mbRTL)
    1720             :     {
    1721             :         // In RTL mode, the logical "left" is visual "right".
    1722           0 :         long nLeft = aRect.Left() - aRect.GetWidth();
    1723           0 :         aRect.Left() = nLeft;
    1724             :     }
    1725           0 :     else if (maWndSize.Width() < aRect.GetWidth())
    1726             :     {
    1727             :         // Target rectangle (i.e. cell width) is wider than the window.
    1728             :         // Simulate right-aligned launch by modifying the target rectangle
    1729             :         // size.
    1730           0 :         long nDiff = aRect.GetWidth() - maWndSize.Width();
    1731           0 :         aRect.Left() += nDiff;
    1732             :     }
    1733             : 
    1734           0 :     StartPopupMode(aRect, (FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus));
    1735           0 :     cycleFocus(); // Set initial focus to the check list box.
    1736           0 : }
    1737             : 
    1738           0 : void ScCheckListMenuWindow::close(bool bOK)
    1739             : {
    1740           0 :     if (bOK && mpOKAction.get())
    1741           0 :         mpOKAction->execute();
    1742             : 
    1743           0 :     EndPopupMode();
    1744           0 : }
    1745             : 
    1746           0 : void ScCheckListMenuWindow::setExtendedData(ExtendedData* p)
    1747             : {
    1748           0 :     mpExtendedData.reset(p);
    1749           0 : }
    1750             : 
    1751           0 : ScCheckListMenuWindow::ExtendedData* ScCheckListMenuWindow::getExtendedData()
    1752             : {
    1753           0 :     return mpExtendedData.get();
    1754             : }
    1755             : 
    1756           0 : void ScCheckListMenuWindow::setOKAction(Action* p)
    1757             : {
    1758           0 :     mpOKAction.reset(p);
    1759           0 : }
    1760             : 
    1761           0 : void ScCheckListMenuWindow::setPopupEndAction(Action* p)
    1762             : {
    1763           0 :     mpPopupEndAction.reset(p);
    1764           0 : }
    1765             : 
    1766           0 : void ScCheckListMenuWindow::handlePopupEnd()
    1767             : {
    1768           0 :     clearSelectedMenuItem();
    1769           0 :     if (mpPopupEndAction)
    1770           0 :         mpPopupEndAction->execute();
    1771         156 : }
    1772             : 
    1773             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11