LCOV - code coverage report
Current view: top level - libreoffice/sc/source/ui/cctrl - checklistmenu.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 780 0.0 %
Date: 2012-12-27 Functions: 0 87 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10