sync master with lastest vba changes
[ooovba.git] / sc / source / ui / cctrl / dpcontrol.cxx
blob02fb0b9ec5e0fcbcb28275af26ff1ffa455f3a5a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: document.hxx,v $
10 * $Revision: 1.115.36.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "dpcontrol.hxx"
38 #include "vcl/outdev.hxx"
39 #include "vcl/settings.hxx"
40 #include "vcl/wintypes.hxx"
41 #include "vcl/decoview.hxx"
43 #define MENU_NOT_SELECTED 999
45 using ::rtl::OUString;
46 using ::rtl::OUStringHash;
47 using ::std::vector;
48 using ::std::hash_map;
50 ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle) :
51 mpOutDev(pOutDev),
52 mpStyle(pStyle),
53 mbPopupButton(false),
54 mbHasHiddenMember(false)
58 ScDPFieldButton::~ScDPFieldButton()
62 void ScDPFieldButton::setText(const OUString& rText)
64 maText = rText;
67 void ScDPFieldButton::setBoundingBox(const Point& rPos, const Size& rSize)
69 maPos = rPos;
70 maSize = rSize;
73 void ScDPFieldButton::setDrawPopupButton(bool b)
75 mbPopupButton = b;
78 void ScDPFieldButton::setHasHiddenMember(bool b)
80 mbHasHiddenMember = b;
83 void ScDPFieldButton::draw()
85 const long nMargin = 2;
87 // Background
88 Rectangle aRect(maPos, maSize);
89 mpOutDev->SetLineColor(mpStyle->GetFaceColor());
90 mpOutDev->SetFillColor(mpStyle->GetFaceColor());
91 mpOutDev->DrawRect(aRect);
93 // Border lines
94 mpOutDev->SetLineColor(mpStyle->GetLightColor());
95 mpOutDev->DrawLine(Point(maPos), Point(maPos.X(), maPos.Y()+maSize.Height()-1));
96 mpOutDev->DrawLine(Point(maPos), Point(maPos.X()+maSize.Width()-1, maPos.Y()));
98 mpOutDev->SetLineColor(mpStyle->GetShadowColor());
99 mpOutDev->DrawLine(Point(maPos.X(), maPos.Y()+maSize.Height()-1),
100 Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
101 mpOutDev->DrawLine(Point(maPos.X()+maSize.Width()-1, maPos.Y()),
102 Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
104 // Field name
105 Font aTextFont( mpStyle->GetLabelFont() );
106 aTextFont.SetHeight(12);
107 mpOutDev->SetFont(aTextFont);
109 Point aTextPos = maPos;
110 long nTHeight = mpOutDev->GetTextHeight();
111 aTextPos.setX(maPos.getX() + nMargin);
112 aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
113 mpOutDev->DrawText(aTextPos, maText);
115 if (mbPopupButton)
116 drawPopupButton();
119 void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
121 long nW = maSize.getWidth()*0.5;
122 long nH = maSize.getHeight();
123 if (nW > 16)
124 nW = 16;
125 if (nH > 18)
126 nH = 18;
128 rPos.setX(maPos.getX() + maSize.getWidth() - nW);
129 rPos.setY(maPos.getY() + maSize.getHeight() - nH);
130 rSize.setWidth(nW);
131 rSize.setHeight(nH);
134 bool ScDPFieldButton::isPopupButton() const
136 return mbPopupButton;
139 void ScDPFieldButton::drawPopupButton()
141 Point aPos;
142 Size aSize;
143 getPopupBoundingBox(aPos, aSize);
145 // border lines
146 mpOutDev->SetLineColor(mpStyle->GetLightColor());
147 mpOutDev->DrawLine(aPos, Point(aPos.X(), aPos.Y()+aSize.Height()-1));
148 mpOutDev->DrawLine(aPos, Point(aPos.X()+aSize.Width()-1, aPos.Y()));
150 mpOutDev->SetLineColor(mpStyle->GetShadowColor());
151 mpOutDev->DrawLine(Point(aPos.X(), aPos.Y()+aSize.Height()-1),
152 Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
153 mpOutDev->DrawLine(Point(aPos.X()+aSize.Width()-1, aPos.Y()),
154 Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
156 // the arrowhead
157 Color aArrowColor = mbHasHiddenMember ? mpStyle->GetHighlightLinkColor() : mpStyle->GetButtonTextColor();
158 mpOutDev->SetLineColor(aArrowColor);
159 mpOutDev->SetFillColor(aArrowColor);
160 Point aCenter(aPos.X() + (aSize.Width() >> 1), aPos.Y() + (aSize.Height() >> 1));
161 Point aPos1, aPos2;
162 aPos1.X() = aCenter.X() - 4;
163 aPos2.X() = aCenter.X() + 4;
164 aPos1.Y() = aCenter.Y() - 3;
165 aPos2.Y() = aCenter.Y() - 3;
169 ++aPos1.X();
170 --aPos2.X();
171 ++aPos1.Y();
172 ++aPos2.Y();
173 mpOutDev->DrawLine(aPos1, aPos2);
175 while (aPos1 != aPos2);
177 if (mbHasHiddenMember)
179 // tiny little box to display in presence of hidden member(s).
180 Point aBoxPos(aPos.X() + aSize.Width() - 5, aPos.Y() + aSize.Height() - 5);
181 Size aBoxSize(3, 3);
182 mpOutDev->DrawRect(Rectangle(aBoxPos, aBoxSize));
186 // ============================================================================
188 ScMenuFloatingWindow::MenuItem::MenuItem() :
189 mbEnabled(true),
190 mpAction(static_cast<ScDPFieldPopupWindow::Action*>(NULL)),
191 mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
195 // ----------------------------------------------------------------------------
197 ScMenuFloatingWindow::SubMenuItem::SubMenuItem(ScMenuFloatingWindow* pParent) :
198 mpSubMenu(NULL),
199 mnMenuPos(MENU_NOT_SELECTED),
200 mpParent(pParent)
202 maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItem, TimeoutHdl) );
203 maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
206 void ScMenuFloatingWindow::SubMenuItem::reset()
208 mpSubMenu = NULL;
209 mnMenuPos = MENU_NOT_SELECTED;
210 maTimer.Stop();
213 IMPL_LINK( ScMenuFloatingWindow::SubMenuItem, TimeoutHdl, void*, EMPTYARG )
215 mpParent->handleMenuTimeout(this);
216 return 0;
219 // ----------------------------------------------------------------------------
221 ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent) :
222 FloatingWindow(pParent, (WB_SYSTEMFLOATWIN|WB_SYSTEMWINDOW|WB_NOBORDER)),
223 maOpenTimer(this),
224 maCloseTimer(this),
225 mnSelectedMenu(MENU_NOT_SELECTED),
226 mnClickedMenu(MENU_NOT_SELECTED),
227 mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
228 mpActiveSubMenu(NULL),
229 mbActionFired(false)
231 // TODO: How do we get the right font to use here ?
232 const sal_uInt16 nPopupFontHeight = 12;
233 const StyleSettings& rStyle = GetSettings().GetStyleSettings();
234 maLabelFont = rStyle.GetLabelFont();
235 maLabelFont.SetHeight(nPopupFontHeight);
236 SetFont(maLabelFont);
238 SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, EndPopupHdl) );
241 ScMenuFloatingWindow::~ScMenuFloatingWindow()
243 EndPopupMode();
246 void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
248 const Point& rPos = rMEvt.GetPosPixel();
249 size_t nSelectedMenu = getEnclosingMenuItem(rPos);
250 setSelectedMenuItem(nSelectedMenu);
252 Window::MouseMove(rMEvt);
255 void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
257 const Point& rPos = rMEvt.GetPosPixel();
258 mnClickedMenu = getEnclosingMenuItem(rPos);
259 Window::MouseButtonDown(rMEvt);
262 void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
264 executeMenu(mnClickedMenu);
265 mnClickedMenu = MENU_NOT_SELECTED;
266 Window::MouseButtonUp(rMEvt);
269 void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
271 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
272 bool bHandled = true;
273 size_t nSelectedMenu = mnSelectedMenu;
274 size_t nLastMenuPos = maMenuItems.size() - 1;
275 switch (rKeyCode.GetCode())
277 case KEY_UP:
278 if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
279 nSelectedMenu = nLastMenuPos;
280 else
281 --nSelectedMenu;
282 setSelectedMenuItem(nSelectedMenu, false);
283 break;
284 case KEY_DOWN:
285 if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
286 nSelectedMenu = 0;
287 else
288 ++nSelectedMenu;
289 setSelectedMenuItem(nSelectedMenu, false);
290 break;
291 case KEY_LEFT:
292 if (mpParentMenu)
293 mpParentMenu->endSubMenu();
294 break;
295 case KEY_RIGHT:
297 if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
298 break;
300 const MenuItem& rMenu = maMenuItems[mnSelectedMenu];
301 if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
302 break;
304 maOpenTimer.mnMenuPos = mnSelectedMenu;
305 maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
306 launchSubMenu(true);
308 break;
309 case KEY_RETURN:
310 if (nSelectedMenu != MENU_NOT_SELECTED)
311 executeMenu(nSelectedMenu);
312 break;
313 default:
314 bHandled = false;
317 if (!bHandled)
318 Window::KeyInput(rKEvt);
321 void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
323 const StyleSettings& rStyle = GetSettings().GetStyleSettings();
324 Color aBackColor = rStyle.GetMenuColor();
325 Color aBorderColor = rStyle.GetShadowColor();
327 Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
329 // Window background
330 bool bNativeDrawn = true;
331 if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
333 SetClipRegion();
334 bNativeDrawn = DrawNativeControl(
335 CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
336 ImplControlValue(), OUString());
338 else
339 bNativeDrawn = false;
341 if (!bNativeDrawn)
343 SetFillColor(aBackColor);
344 SetLineColor(aBorderColor);
345 DrawRect(aCtrlRect);
348 // Menu items
349 SetTextColor(rStyle.GetMenuTextColor());
350 drawAllMenuItems();
353 void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
355 MenuItem aItem;
356 aItem.maText = rText;
357 aItem.mbEnabled = bEnabled;
358 aItem.mpAction.reset(pAction);
359 maMenuItems.push_back(aItem);
362 ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
364 MenuItem aItem;
365 aItem.maText = rText;
366 aItem.mbEnabled = bEnabled;
367 aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this));
368 maMenuItems.push_back(aItem);
369 return aItem.mpSubMenuWin.get();
372 void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
374 if (nPos >= maMenuItems.size())
375 return;
377 Point aPos;
378 Size aSize;
379 getMenuItemPosSize(aPos, aSize, nPos);
381 DecorationView aDecoView(this);
382 long nXOffset = 5;
383 long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
384 DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
385 maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
387 if (maMenuItems[nPos].mpSubMenuWin)
389 long nFontHeight = maLabelFont.GetHeight();
390 Point aMarkerPos = aPos;
391 aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
392 aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
393 Size aMarkerSize(nFontHeight/2, nFontHeight/2);
394 aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
395 SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
399 void ScMenuFloatingWindow::drawAllMenuItems()
401 size_t n = maMenuItems.size();
402 for (size_t i = 0; i < n; ++i)
403 highlightMenuItem(i, i == mnSelectedMenu);
406 const Font& ScMenuFloatingWindow::getLabelFont() const
408 return maLabelFont;
411 void ScMenuFloatingWindow::executeMenu(size_t nPos)
413 if (nPos >= maMenuItems.size())
414 return;
416 if (!maMenuItems[nPos].mpAction)
417 // no action is defined.
418 return;
420 maMenuItems[nPos].mpAction->execute();
421 mbActionFired = true;
422 EndPopupMode();
425 void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer)
427 if (mnSelectedMenu != nPos)
429 selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
430 selectMenuItem(nPos, true, bSubMenuTimer);
431 mnSelectedMenu = nPos;
435 size_t ScMenuFloatingWindow::getSelectedMenuItem() const
437 return mnSelectedMenu;
440 void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItem* pTimer)
442 if (pTimer == &maOpenTimer)
444 // Close any open submenu immediately.
445 if (maCloseTimer.mpSubMenu)
447 maCloseTimer.mpSubMenu->EndPopupMode();
448 maCloseTimer.mpSubMenu = NULL;
449 maCloseTimer.maTimer.Stop();
452 launchSubMenu(false);
454 else if (pTimer == &maCloseTimer)
456 // end submenu.
457 if (maCloseTimer.mpSubMenu)
459 maOpenTimer.mpSubMenu = NULL;
461 maCloseTimer.mpSubMenu->EndPopupMode();
462 maCloseTimer.mpSubMenu = NULL;
464 highlightMenuItem(maOpenTimer.mnMenuPos, false);
465 maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
470 void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
472 if (!pMenu)
473 return;
475 // Set the submenu on launch queue.
476 if (maOpenTimer.mpSubMenu)
478 if (maOpenTimer.mpSubMenu == pMenu)
480 if (pMenu == maCloseTimer.mpSubMenu)
481 maCloseTimer.reset();
482 return;
485 // new submenu is being requested.
486 queueCloseSubMenu();
489 maOpenTimer.mpSubMenu = pMenu;
490 maOpenTimer.mnMenuPos = nPos;
491 maOpenTimer.maTimer.Start();
494 void ScMenuFloatingWindow::queueCloseSubMenu()
496 if (!maOpenTimer.mpSubMenu)
497 // There is no submenu to close.
498 return;
500 // Stop any submenu on queue for opening.
501 maOpenTimer.maTimer.Stop();
503 maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
504 maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
505 maCloseTimer.maTimer.Start();
508 void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
510 Point aPos;
511 Size aSize;
512 getMenuItemPosSize(aPos, aSize, maOpenTimer.mnMenuPos);
513 ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
515 if (!pSubMenu)
516 return;
518 sal_uInt32 nOldFlags = GetPopupModeFlags();
519 SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
520 pSubMenu->resetMenu(bSetMenuPos);
521 pSubMenu->StartPopupMode(
522 Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
523 pSubMenu->AddPopupModeWindow(this);
524 SetPopupModeFlags(nOldFlags);
527 void ScMenuFloatingWindow::endSubMenu()
529 if (maOpenTimer.mpSubMenu)
531 maOpenTimer.mpSubMenu->EndPopupMode();
532 maOpenTimer.mpSubMenu = NULL;
533 highlightMenuItem(maOpenTimer.mnMenuPos, true);
537 void ScMenuFloatingWindow::notify(NotificationType eType)
539 switch (eType)
541 case SUBMENU_FOCUSED:
542 // Cancel any request for ending submenu.
543 maCloseTimer.reset();
544 if (mnSelectedMenu != maOpenTimer.mnMenuPos)
546 highlightMenuItem(maOpenTimer.mnMenuPos, true);
547 mnSelectedMenu = maOpenTimer.mnMenuPos;
549 break;
550 default:
555 void ScMenuFloatingWindow::resetMenu(bool bSetMenuPos)
557 mnSelectedMenu = bSetMenuPos ? 0 : MENU_NOT_SELECTED;
558 resizeToFitMenuItems();
561 void ScMenuFloatingWindow::resizeToFitMenuItems()
563 if (maMenuItems.empty())
564 return;
566 vector<MenuItem>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
567 long nTextWidth = 0;
568 for (; itr != itrEnd; ++itr)
569 nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
571 size_t nLastPos = maMenuItems.size()-1;
572 Point aPos;
573 Size aSize;
574 getMenuItemPosSize(aPos, aSize, nLastPos);
575 aPos.X() += nTextWidth + 15;
576 aPos.Y() += aSize.Height() + 5;
577 SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
580 void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
582 if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
584 queueCloseSubMenu();
585 return;
588 if (!maMenuItems[nPos].mbEnabled)
590 queueCloseSubMenu();
591 return;
594 highlightMenuItem(nPos, bSelected);
596 if (bSelected)
598 if (mpParentMenu)
599 mpParentMenu->notify(SUBMENU_FOCUSED);
601 if (bSubMenuTimer)
603 if (maMenuItems[nPos].mpSubMenuWin)
605 ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
606 queueLaunchSubMenu(nPos, pSubMenu);
608 else
609 queueCloseSubMenu();
614 void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
616 const StyleSettings& rStyle = GetSettings().GetStyleSettings();
617 Color aBackColor = rStyle.GetMenuColor();
618 SetFillColor(aBackColor);
619 SetLineColor(aBackColor);
621 Point aPos;
622 Size aSize;
623 getMenuItemPosSize(aPos, aSize, nPos);
624 Region aRegion(Rectangle(aPos,aSize));
626 if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
628 Push(PUSH_CLIPREGION);
629 IntersectClipRegion(Rectangle(aPos, aSize));
630 Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
631 DrawNativeControl(
632 CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
633 ImplControlValue(), OUString());
635 Pop();
638 bool bNativeDrawn = true;
639 if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
641 ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
642 if (maMenuItems[nPos].mbEnabled)
643 nState |= CTRL_STATE_ENABLED;
644 bNativeDrawn = DrawNativeControl(
645 CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
647 else
648 bNativeDrawn = false;
650 if (!bNativeDrawn)
652 if (bSelected)
654 aBackColor = rStyle.GetMenuHighlightColor();
655 SetFillColor(aBackColor);
656 SetLineColor(aBackColor);
658 DrawRect(Rectangle(aPos,aSize));
661 Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
662 SetTextColor(aTextColor);
663 drawMenuItem(nPos);
666 void ScMenuFloatingWindow::getMenuItemPosSize(Point& rPos, Size& rSize, size_t nPos) const
668 const sal_uInt16 nLeftMargin = 5;
669 const sal_uInt16 nTopMargin = 5;
670 const sal_uInt16 nMenuItemHeight = maLabelFont.GetHeight()*1.8;
672 Size aWndSize = GetSizePixel();
674 Point aPos1(nLeftMargin, nTopMargin);
675 Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
677 rPos = aPos1;
678 rPos.Y() += aSize1.Height()*nPos;
679 rSize = aSize1;
682 size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
684 size_t n = maMenuItems.size();
685 for (size_t i = 0; i < n; ++i)
687 Point aPos;
688 Size aSize;
689 getMenuItemPosSize(aPos, aSize, i);
690 Rectangle aRect(aPos, aSize);
691 if (aRect.IsInside(rPos))
692 return i;
694 return MENU_NOT_SELECTED;
697 IMPL_LINK( ScMenuFloatingWindow, EndPopupHdl, void*, EMPTYARG )
699 if (mbActionFired && mpParentMenu)
700 mpParentMenu->EndPopupMode();
702 return 0;
705 // ============================================================================
707 ScDPFieldPopupWindow::Member::Member() :
708 mbVisible(true)
712 // ----------------------------------------------------------------------------
714 ScDPFieldPopupWindow::CancelButton::CancelButton(ScDPFieldPopupWindow* pParent) :
715 ::CancelButton(pParent), mpParent(pParent) {}
717 void ScDPFieldPopupWindow::CancelButton::Click()
719 mpParent->EndPopupMode();
720 ::CancelButton::Click();
723 // ----------------------------------------------------------------------------
725 ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent) :
726 ScMenuFloatingWindow(pParent),
727 maCheck0(this, 0),
728 maCheck1(this, 0),
729 maCheck2(this, 0),
730 maCheck3(this, 0),
731 maCheck4(this, 0),
732 maCheck5(this, 0),
733 maCheck6(this, 0),
734 maCheck7(this, 0),
735 maCheck8(this, 0),
736 maCheck9(this, 0),
737 maScrollBar(this, WB_VERT),
738 maBtnOk(this),
739 maBtnCancel(this),
740 mpExtendedData(NULL),
741 mpOKAction(NULL),
742 mnScrollPos(0)
744 Point aPos;
745 Size aSize;
746 getSectionPosSize(aPos, aSize, WHOLE);
747 SetOutputSizePixel(aSize);
748 Size aOutSize = GetOutputSizePixel();
750 mpCheckPtr.reserve(10);
751 mpCheckPtr.push_back(&maCheck0);
752 mpCheckPtr.push_back(&maCheck1);
753 mpCheckPtr.push_back(&maCheck2);
754 mpCheckPtr.push_back(&maCheck3);
755 mpCheckPtr.push_back(&maCheck4);
756 mpCheckPtr.push_back(&maCheck5);
757 mpCheckPtr.push_back(&maCheck6);
758 mpCheckPtr.push_back(&maCheck7);
759 mpCheckPtr.push_back(&maCheck8);
760 mpCheckPtr.push_back(&maCheck9);
762 getSectionPosSize(aPos, aSize, FIRST_LISTITEM);
763 for (vector<CheckBox*>::iterator itr = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
764 itr != itrEnd; ++itr)
766 CheckBox* p = *itr;
767 p->SetPosSizePixel(aPos, aSize);
768 p->SetFont(getLabelFont());
769 p->SetClickHdl( LINK(this, ScDPFieldPopupWindow, CheckBoxHdl) );
770 aPos.Y() += aSize.Height() + 1;
773 getSectionPosSize(aPos, aSize, BTN_OK);
774 maBtnOk.SetPosSizePixel(aPos, aSize);
775 maBtnOk.SetFont(getLabelFont());
776 maBtnOk.SetClickHdl( LINK(this, ScDPFieldPopupWindow, OKButtonHdl) );
777 maBtnOk.Show();
779 getSectionPosSize(aPos, aSize, BTN_CANCEL);
780 maBtnCancel.SetPosSizePixel(aPos, aSize);
781 maBtnCancel.SetFont(getLabelFont());
782 maBtnCancel.Show();
784 getSectionPosSize(aPos, aSize, SCROLL_BAR_V);
785 maScrollBar.SetPosSizePixel(aPos, aSize);
786 maScrollBar.SetPageSize(mpCheckPtr.size());
787 maScrollBar.SetVisibleSize(mpCheckPtr.size());
788 maScrollBar.SetLineSize(1);
789 maScrollBar.SetScrollHdl( LINK(this, ScDPFieldPopupWindow, ScrollHdl) );
790 maScrollBar.EnableDrag(true);
793 ScDPFieldPopupWindow::~ScDPFieldPopupWindow()
797 vector<ScDPFieldPopupWindow::Member>& ScDPFieldPopupWindow::getMembers()
799 return maMembers;
802 void ScDPFieldPopupWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
804 const sal_uInt16 nListBoxMargin = 5;
805 const sal_uInt16 nTopMargin = 5;
806 const sal_uInt16 nMenuHeight = 60;
807 const sal_uInt16 nBottomBtnAreaHeight = 50;
808 const sal_uInt16 nInnerItemMargin = 5;
809 const sal_uInt16 nScrollBarWidth = 17;
810 const sal_uInt16 nBtnWidth = 60;
811 const sal_uInt16 nBtnHeight = getLabelFont().GetHeight()*2;
812 const sal_uInt16 nBottomMargin = 10;
813 const sal_uInt16 nMenuListMargin = 20;
815 Size aWndSize = Size(160, 330);
817 switch (eType)
819 case WHOLE:
821 rPos = Point(0, 0);
822 rSize = aWndSize;
824 break;
825 case LISTBOX_AREA:
827 rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
828 rSize = Size(
829 aWndSize.Width() - nListBoxMargin*2,
830 aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight);
832 break;
833 case FIRST_LISTITEM:
835 rPos = Point(nListBoxMargin + nInnerItemMargin,
836 nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin);
837 rSize = Size(
838 aWndSize.Width() - nListBoxMargin*2 - nInnerItemMargin - nScrollBarWidth - 10,
839 17);
841 break;
842 case BTN_OK:
844 long x = (aWndSize.Width() - nBtnWidth*2)/3;
845 long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
846 rPos = Point(x, y);
847 rSize = Size(nBtnWidth, nBtnHeight);
849 break;
850 case BTN_CANCEL:
852 long x = (aWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
853 long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
854 rPos = Point(x, y);
855 rSize = Size(nBtnWidth, nBtnHeight);
857 break;
858 case SCROLL_BAR_V:
860 long x = aWndSize.Width() - nListBoxMargin - nInnerItemMargin - nScrollBarWidth;
861 long y = nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin;
862 rPos = Point(x, y);
863 long h = aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight - nInnerItemMargin*2;
864 rSize = Size(nScrollBarWidth, h);
866 break;
867 default:
872 void ScDPFieldPopupWindow::resetDisplayedItems()
874 long nScrollPos = maScrollBar.GetThumbPos();
875 if (nScrollPos < 0)
876 return;
878 mnScrollPos = static_cast<size_t>(nScrollPos);
879 size_t nCheckCount = mpCheckPtr.size();
880 for (size_t i = 0; i < nCheckCount; ++i)
882 CheckBox* p = mpCheckPtr[i];
883 p->SetText(maMembers[i+mnScrollPos].maName);
884 TriState nNewState = maMembers[i+mnScrollPos].mbVisible ? STATE_CHECK : STATE_NOCHECK;
885 p->SetState(nNewState);
889 IMPL_LINK( ScDPFieldPopupWindow, CheckBoxHdl, CheckBox*, pCheck )
891 vector<CheckBox*>::const_iterator itr, itrBeg = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
892 for (itr = itrBeg; itr != itrEnd; ++itr)
894 if (*itr == pCheck)
896 size_t nIndex = ::std::distance(itrBeg, itr);
897 maMembers[nIndex+mnScrollPos].mbVisible = !maMembers[nIndex+mnScrollPos].mbVisible;
900 return 0;
903 IMPL_LINK( ScDPFieldPopupWindow, OKButtonHdl, OKButton*, EMPTYARG )
905 close(true);
906 return 0;
909 IMPL_LINK( ScDPFieldPopupWindow, ScrollHdl, ScrollBar*, EMPTYARG )
911 resetDisplayedItems();
912 return 0;
915 void ScDPFieldPopupWindow::MouseMove(const MouseEvent& rMEvt)
917 ScMenuFloatingWindow::MouseMove(rMEvt);
919 size_t nSelectedMenu = getSelectedMenuItem();
920 if (nSelectedMenu == MENU_NOT_SELECTED)
921 queueCloseSubMenu();
924 void ScDPFieldPopupWindow::Paint(const Rectangle& rRect)
926 ScMenuFloatingWindow::Paint(rRect);
928 const StyleSettings& rStyle = GetSettings().GetStyleSettings();
929 Color aMemberBackColor = rStyle.GetFieldColor();
931 // Member list box background
932 SetFillColor(aMemberBackColor);
933 Point aPos;
934 Size aSize;
935 getSectionPosSize(aPos, aSize, LISTBOX_AREA);
936 DrawRect(Rectangle(aPos,aSize));
939 void ScDPFieldPopupWindow::setMemberSize(size_t n)
941 maMembers.reserve(n);
944 void ScDPFieldPopupWindow::addMember(const OUString& rName, bool bVisible)
946 Member aMember;
947 aMember.maName = rName;
948 aMember.mbVisible = bVisible;
949 maMembers.push_back(aMember);
952 void ScDPFieldPopupWindow::initMembers()
954 size_t nMemCount = maMembers.size();
955 size_t nCheckCount = mpCheckPtr.size();
956 bool bNeedsScroll = false;
957 if (nMemCount > nCheckCount)
959 nMemCount = nCheckCount;
960 bNeedsScroll = true;
963 for (size_t i = 0; i < nMemCount; ++i)
965 CheckBox* p = mpCheckPtr[i];
966 p->SetText(maMembers[i].maName);
967 p->Show();
968 p->SetState(maMembers[i].mbVisible ? STATE_CHECK : STATE_NOCHECK);
970 if (bNeedsScroll)
972 maScrollBar.SetRange(Range(0, maMembers.size()));
973 maScrollBar.Show();
977 void ScDPFieldPopupWindow::getResult(hash_map<OUString, bool, OUStringHash>& rResult)
979 typedef hash_map<OUString, bool, OUStringHash> ResultMap;
980 ResultMap aResult;
981 vector<Member>::const_iterator itr = maMembers.begin(), itrEnd = maMembers.end();
982 for (; itr != itrEnd; ++itr)
983 aResult.insert(ResultMap::value_type(itr->maName, itr->mbVisible));
984 rResult.swap(aResult);
987 void ScDPFieldPopupWindow::close(bool bOK)
989 if (bOK && mpOKAction.get())
990 mpOKAction->execute();
992 EndPopupMode();
995 void ScDPFieldPopupWindow::setExtendedData(ExtendedData* p)
997 mpExtendedData.reset(p);
1000 ScDPFieldPopupWindow::ExtendedData* ScDPFieldPopupWindow::getExtendedData()
1002 return mpExtendedData.get();
1005 void ScDPFieldPopupWindow::setOKAction(Action* p)
1007 mpOKAction.reset(p);