summaryrefslogtreecommitdiff
path: root/sc/source/ui
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui')
-rw-r--r--sc/source/ui/cctrl/dpcontrol.cxx1009
-rw-r--r--sc/source/ui/cctrl/dpcontrol.src49
-rw-r--r--sc/source/ui/cctrl/makefile.mk10
-rw-r--r--sc/source/ui/dbgui/pvlaydlg.cxx35
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx4
-rw-r--r--sc/source/ui/inc/dbfunc.hxx1
-rw-r--r--sc/source/ui/inc/dpcontrol.hrc40
-rw-r--r--sc/source/ui/inc/dpcontrol.hxx289
-rw-r--r--sc/source/ui/inc/gridwin.hxx15
-rw-r--r--sc/source/ui/inc/pvlaydlg.hxx2
-rw-r--r--sc/source/ui/undo/undodat.cxx4
-rw-r--r--sc/source/ui/view/dbfunc3.cxx137
-rw-r--r--sc/source/ui/view/gridwin.cxx2
-rw-r--r--sc/source/ui/view/gridwin2.cxx202
-rw-r--r--sc/source/ui/view/gridwin4.cxx17
15 files changed, 1785 insertions, 31 deletions
diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx
new file mode 100644
index 000000000000..d6aa21ab79bb
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.cxx
@@ -0,0 +1,1009 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.hxx,v $
+ * $Revision: 1.115.36.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "dpcontrol.hxx"
+
+#include "vcl/outdev.hxx"
+#include "vcl/settings.hxx"
+#include "vcl/wintypes.hxx"
+#include "vcl/decoview.hxx"
+
+#define MENU_NOT_SELECTED 999
+
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
+using ::std::vector;
+using ::std::hash_map;
+
+ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle) :
+ mpOutDev(pOutDev),
+ mpStyle(pStyle),
+ mbPopupButton(false),
+ mbHasHiddenMember(false)
+{
+}
+
+ScDPFieldButton::~ScDPFieldButton()
+{
+}
+
+void ScDPFieldButton::setText(const OUString& rText)
+{
+ maText = rText;
+}
+
+void ScDPFieldButton::setBoundingBox(const Point& rPos, const Size& rSize)
+{
+ maPos = rPos;
+ maSize = rSize;
+}
+
+void ScDPFieldButton::setDrawPopupButton(bool b)
+{
+ mbPopupButton = b;
+}
+
+void ScDPFieldButton::setHasHiddenMember(bool b)
+{
+ mbHasHiddenMember = b;
+}
+
+void ScDPFieldButton::draw()
+{
+ const long nMargin = 2;
+
+ // Background
+ Rectangle aRect(maPos, maSize);
+ mpOutDev->SetLineColor(mpStyle->GetFaceColor());
+ mpOutDev->SetFillColor(mpStyle->GetFaceColor());
+ mpOutDev->DrawRect(aRect);
+
+ // Border lines
+ mpOutDev->SetLineColor(mpStyle->GetLightColor());
+ mpOutDev->DrawLine(Point(maPos), Point(maPos.X(), maPos.Y()+maSize.Height()-1));
+ mpOutDev->DrawLine(Point(maPos), Point(maPos.X()+maSize.Width()-1, maPos.Y()));
+
+ mpOutDev->SetLineColor(mpStyle->GetShadowColor());
+ mpOutDev->DrawLine(Point(maPos.X(), maPos.Y()+maSize.Height()-1),
+ Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
+ mpOutDev->DrawLine(Point(maPos.X()+maSize.Width()-1, maPos.Y()),
+ Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
+
+ // Field name
+ Font aTextFont( mpStyle->GetLabelFont() );
+ aTextFont.SetHeight(12);
+ mpOutDev->SetFont(aTextFont);
+
+ Point aTextPos = maPos;
+ long nTHeight = mpOutDev->GetTextHeight();
+ aTextPos.setX(maPos.getX() + nMargin);
+ aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
+ mpOutDev->DrawText(aTextPos, maText);
+
+ if (mbPopupButton)
+ drawPopupButton();
+}
+
+void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
+{
+ long nW = maSize.getWidth()*0.5;
+ long nH = maSize.getHeight();
+ if (nW > 16)
+ nW = 16;
+ if (nH > 18)
+ nH = 18;
+
+ rPos.setX(maPos.getX() + maSize.getWidth() - nW);
+ rPos.setY(maPos.getY() + maSize.getHeight() - nH);
+ rSize.setWidth(nW);
+ rSize.setHeight(nH);
+}
+
+bool ScDPFieldButton::isPopupButton() const
+{
+ return mbPopupButton;
+}
+
+void ScDPFieldButton::drawPopupButton()
+{
+ Point aPos;
+ Size aSize;
+ getPopupBoundingBox(aPos, aSize);
+
+ // border lines
+ mpOutDev->SetLineColor(mpStyle->GetLightColor());
+ mpOutDev->DrawLine(aPos, Point(aPos.X(), aPos.Y()+aSize.Height()-1));
+ mpOutDev->DrawLine(aPos, Point(aPos.X()+aSize.Width()-1, aPos.Y()));
+
+ mpOutDev->SetLineColor(mpStyle->GetShadowColor());
+ mpOutDev->DrawLine(Point(aPos.X(), aPos.Y()+aSize.Height()-1),
+ Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
+ mpOutDev->DrawLine(Point(aPos.X()+aSize.Width()-1, aPos.Y()),
+ Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
+
+ // the arrowhead
+ Color aArrowColor = mbHasHiddenMember ? mpStyle->GetHighlightLinkColor() : mpStyle->GetButtonTextColor();
+ mpOutDev->SetLineColor(aArrowColor);
+ mpOutDev->SetFillColor(aArrowColor);
+ Point aCenter(aPos.X() + (aSize.Width() >> 1), aPos.Y() + (aSize.Height() >> 1));
+ Point aPos1, aPos2;
+ aPos1.X() = aCenter.X() - 4;
+ aPos2.X() = aCenter.X() + 4;
+ aPos1.Y() = aCenter.Y() - 3;
+ aPos2.Y() = aCenter.Y() - 3;
+
+ do
+ {
+ ++aPos1.X();
+ --aPos2.X();
+ ++aPos1.Y();
+ ++aPos2.Y();
+ mpOutDev->DrawLine(aPos1, aPos2);
+ }
+ while (aPos1 != aPos2);
+
+ if (mbHasHiddenMember)
+ {
+ // tiny little box to display in presence of hidden member(s).
+ Point aBoxPos(aPos.X() + aSize.Width() - 5, aPos.Y() + aSize.Height() - 5);
+ Size aBoxSize(3, 3);
+ mpOutDev->DrawRect(Rectangle(aBoxPos, aBoxSize));
+ }
+}
+
+// ============================================================================
+
+ScMenuFloatingWindow::MenuItem::MenuItem() :
+ mbEnabled(true),
+ mpAction(static_cast<ScDPFieldPopupWindow::Action*>(NULL)),
+ mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::SubMenuItem::SubMenuItem(ScMenuFloatingWindow* pParent) :
+ mpSubMenu(NULL),
+ mnMenuPos(MENU_NOT_SELECTED),
+ mpParent(pParent)
+{
+ maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItem, TimeoutHdl) );
+ maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
+}
+
+void ScMenuFloatingWindow::SubMenuItem::reset()
+{
+ mpSubMenu = NULL;
+ mnMenuPos = MENU_NOT_SELECTED;
+ maTimer.Stop();
+}
+
+IMPL_LINK( ScMenuFloatingWindow::SubMenuItem, TimeoutHdl, void*, EMPTYARG )
+{
+ mpParent->handleMenuTimeout(this);
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent) :
+ FloatingWindow(pParent, (WB_SYSTEMFLOATWIN|WB_SYSTEMWINDOW|WB_NOBORDER)),
+ maOpenTimer(this),
+ maCloseTimer(this),
+ mnSelectedMenu(MENU_NOT_SELECTED),
+ mnClickedMenu(MENU_NOT_SELECTED),
+ mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
+ mpActiveSubMenu(NULL),
+ mbActionFired(false)
+{
+ // TODO: How do we get the right font to use here ?
+ const sal_uInt16 nPopupFontHeight = 12;
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ maLabelFont = rStyle.GetLabelFont();
+ maLabelFont.SetHeight(nPopupFontHeight);
+ SetFont(maLabelFont);
+
+ SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, EndPopupHdl) );
+}
+
+ScMenuFloatingWindow::~ScMenuFloatingWindow()
+{
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ size_t nSelectedMenu = getEnclosingMenuItem(rPos);
+ setSelectedMenuItem(nSelectedMenu);
+
+ Window::MouseMove(rMEvt);
+}
+
+void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ mnClickedMenu = getEnclosingMenuItem(rPos);
+ Window::MouseButtonDown(rMEvt);
+}
+
+void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ executeMenu(mnClickedMenu);
+ mnClickedMenu = MENU_NOT_SELECTED;
+ Window::MouseButtonUp(rMEvt);
+}
+
+void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
+{
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ bool bHandled = true;
+ size_t nSelectedMenu = mnSelectedMenu;
+ size_t nLastMenuPos = maMenuItems.size() - 1;
+ switch (rKeyCode.GetCode())
+ {
+ case KEY_UP:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
+ nSelectedMenu = nLastMenuPos;
+ else
+ --nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false);
+ break;
+ case KEY_DOWN:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
+ nSelectedMenu = 0;
+ else
+ ++nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false);
+ break;
+ case KEY_LEFT:
+ if (mpParentMenu)
+ mpParentMenu->endSubMenu();
+ break;
+ case KEY_RIGHT:
+ {
+ if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
+ break;
+
+ const MenuItem& rMenu = maMenuItems[mnSelectedMenu];
+ if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
+ break;
+
+ maOpenTimer.mnMenuPos = mnSelectedMenu;
+ maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
+ launchSubMenu(true);
+ }
+ break;
+ case KEY_RETURN:
+ if (nSelectedMenu != MENU_NOT_SELECTED)
+ executeMenu(nSelectedMenu);
+ break;
+ default:
+ bHandled = false;
+ }
+
+ if (!bHandled)
+ Window::KeyInput(rKEvt);
+}
+
+void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
+{
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ Color aBorderColor = rStyle.GetShadowColor();
+
+ Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
+
+ // Window background
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ SetClipRegion();
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ SetFillColor(aBackColor);
+ SetLineColor(aBorderColor);
+ DrawRect(aCtrlRect);
+ }
+
+ // Menu items
+ SetTextColor(rStyle.GetMenuTextColor());
+ drawAllMenuItems();
+}
+
+void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
+{
+ MenuItem aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpAction.reset(pAction);
+ maMenuItems.push_back(aItem);
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
+{
+ MenuItem aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this));
+ maMenuItems.push_back(aItem);
+ return aItem.mpSubMenuWin.get();
+}
+
+void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nPos);
+
+ DecorationView aDecoView(this);
+ long nXOffset = 5;
+ long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
+ DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
+ maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
+
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ long nFontHeight = maLabelFont.GetHeight();
+ Point aMarkerPos = aPos;
+ aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
+ aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
+ Size aMarkerSize(nFontHeight/2, nFontHeight/2);
+ aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
+ SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
+ }
+}
+
+void ScMenuFloatingWindow::drawAllMenuItems()
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ highlightMenuItem(i, i == mnSelectedMenu);
+}
+
+const Font& ScMenuFloatingWindow::getLabelFont() const
+{
+ return maLabelFont;
+}
+
+void ScMenuFloatingWindow::executeMenu(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ if (!maMenuItems[nPos].mpAction)
+ // no action is defined.
+ return;
+
+ maMenuItems[nPos].mpAction->execute();
+ mbActionFired = true;
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer)
+{
+ if (mnSelectedMenu != nPos)
+ {
+ selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
+ selectMenuItem(nPos, true, bSubMenuTimer);
+ mnSelectedMenu = nPos;
+ }
+}
+
+size_t ScMenuFloatingWindow::getSelectedMenuItem() const
+{
+ return mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItem* pTimer)
+{
+ if (pTimer == &maOpenTimer)
+ {
+ // Close any open submenu immediately.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+ maCloseTimer.maTimer.Stop();
+ }
+
+ launchSubMenu(false);
+ }
+ else if (pTimer == &maCloseTimer)
+ {
+ // end submenu.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maOpenTimer.mpSubMenu = NULL;
+
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+
+ highlightMenuItem(maOpenTimer.mnMenuPos, false);
+ maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
+ }
+ }
+}
+
+void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
+{
+ if (!pMenu)
+ return;
+
+ // Set the submenu on launch queue.
+ if (maOpenTimer.mpSubMenu)
+ {
+ if (maOpenTimer.mpSubMenu == pMenu)
+ {
+ if (pMenu == maCloseTimer.mpSubMenu)
+ maCloseTimer.reset();
+ return;
+ }
+
+ // new submenu is being requested.
+ queueCloseSubMenu();
+ }
+
+ maOpenTimer.mpSubMenu = pMenu;
+ maOpenTimer.mnMenuPos = nPos;
+ maOpenTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::queueCloseSubMenu()
+{
+ if (!maOpenTimer.mpSubMenu)
+ // There is no submenu to close.
+ return;
+
+ // Stop any submenu on queue for opening.
+ maOpenTimer.maTimer.Stop();
+
+ maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
+ maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
+ maCloseTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
+{
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, maOpenTimer.mnMenuPos);
+ ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
+
+ if (!pSubMenu)
+ return;
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resetMenu(bSetMenuPos);
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ SetPopupModeFlags(nOldFlags);
+}
+
+void ScMenuFloatingWindow::endSubMenu()
+{
+ if (maOpenTimer.mpSubMenu)
+ {
+ maOpenTimer.mpSubMenu->EndPopupMode();
+ maOpenTimer.mpSubMenu = NULL;
+ highlightMenuItem(maOpenTimer.mnMenuPos, true);
+ }
+}
+
+void ScMenuFloatingWindow::notify(NotificationType eType)
+{
+ switch (eType)
+ {
+ case SUBMENU_FOCUSED:
+ // Cancel any request for ending submenu.
+ maCloseTimer.reset();
+ if (mnSelectedMenu != maOpenTimer.mnMenuPos)
+ {
+ highlightMenuItem(maOpenTimer.mnMenuPos, true);
+ mnSelectedMenu = maOpenTimer.mnMenuPos;
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void ScMenuFloatingWindow::resetMenu(bool bSetMenuPos)
+{
+ mnSelectedMenu = bSetMenuPos ? 0 : MENU_NOT_SELECTED;
+ resizeToFitMenuItems();
+}
+
+void ScMenuFloatingWindow::resizeToFitMenuItems()
+{
+ if (maMenuItems.empty())
+ return;
+
+ vector<MenuItem>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ long nTextWidth = 0;
+ for (; itr != itrEnd; ++itr)
+ nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
+
+ size_t nLastPos = maMenuItems.size()-1;
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nLastPos);
+ aPos.X() += nTextWidth + 15;
+ aPos.Y() += aSize.Height() + 5;
+ SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
+}
+
+void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
+{
+ if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ if (!maMenuItems[nPos].mbEnabled)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ highlightMenuItem(nPos, bSelected);
+
+ if (bSelected)
+ {
+ if (mpParentMenu)
+ mpParentMenu->notify(SUBMENU_FOCUSED);
+
+ if (bSubMenuTimer)
+ {
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
+ queueLaunchSubMenu(nPos, pSubMenu);
+ }
+ else
+ queueCloseSubMenu();
+ }
+ }
+}
+
+void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
+{
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nPos);
+ Region aRegion(Rectangle(aPos,aSize));
+
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ Push(PUSH_CLIPREGION);
+ IntersectClipRegion(Rectangle(aPos, aSize));
+ Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
+ DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+
+ Pop();
+ }
+
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
+ {
+ ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
+ if (maMenuItems[nPos].mbEnabled)
+ nState |= CTRL_STATE_ENABLED;
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ if (bSelected)
+ {
+ aBackColor = rStyle.GetMenuHighlightColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+ }
+ DrawRect(Rectangle(aPos,aSize));
+ }
+
+ Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
+ SetTextColor(aTextColor);
+ drawMenuItem(nPos);
+}
+
+void ScMenuFloatingWindow::getMenuItemPosSize(Point& rPos, Size& rSize, size_t nPos) const
+{
+ const sal_uInt16 nLeftMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuItemHeight = maLabelFont.GetHeight()*1.8;
+
+ Size aWndSize = GetSizePixel();
+
+ Point aPos1(nLeftMargin, nTopMargin);
+ Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
+
+ rPos = aPos1;
+ rPos.Y() += aSize1.Height()*nPos;
+ rSize = aSize1;
+}
+
+size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, i);
+ Rectangle aRect(aPos, aSize);
+ if (aRect.IsInside(rPos))
+ return i;
+ }
+ return MENU_NOT_SELECTED;
+}
+
+IMPL_LINK( ScMenuFloatingWindow, EndPopupHdl, void*, EMPTYARG )
+{
+ if (mbActionFired && mpParentMenu)
+ mpParentMenu->EndPopupMode();
+
+ return 0;
+}
+
+// ============================================================================
+
+ScDPFieldPopupWindow::Member::Member() :
+ mbVisible(true)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScDPFieldPopupWindow::CancelButton::CancelButton(ScDPFieldPopupWindow* pParent) :
+ ::CancelButton(pParent), mpParent(pParent) {}
+
+void ScDPFieldPopupWindow::CancelButton::Click()
+{
+ mpParent->EndPopupMode();
+ ::CancelButton::Click();
+}
+
+// ----------------------------------------------------------------------------
+
+ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent) :
+ ScMenuFloatingWindow(pParent),
+ maCheck0(this, 0),
+ maCheck1(this, 0),
+ maCheck2(this, 0),
+ maCheck3(this, 0),
+ maCheck4(this, 0),
+ maCheck5(this, 0),
+ maCheck6(this, 0),
+ maCheck7(this, 0),
+ maCheck8(this, 0),
+ maCheck9(this, 0),
+ maScrollBar(this, WB_VERT),
+ maBtnOk(this),
+ maBtnCancel(this),
+ mpExtendedData(NULL),
+ mpOKAction(NULL),
+ mnScrollPos(0)
+{
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, WHOLE);
+ SetOutputSizePixel(aSize);
+ Size aOutSize = GetOutputSizePixel();
+
+ mpCheckPtr.reserve(10);
+ mpCheckPtr.push_back(&maCheck0);
+ mpCheckPtr.push_back(&maCheck1);
+ mpCheckPtr.push_back(&maCheck2);
+ mpCheckPtr.push_back(&maCheck3);
+ mpCheckPtr.push_back(&maCheck4);
+ mpCheckPtr.push_back(&maCheck5);
+ mpCheckPtr.push_back(&maCheck6);
+ mpCheckPtr.push_back(&maCheck7);
+ mpCheckPtr.push_back(&maCheck8);
+ mpCheckPtr.push_back(&maCheck9);
+
+ getSectionPosSize(aPos, aSize, FIRST_LISTITEM);
+ for (vector<CheckBox*>::iterator itr = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
+ itr != itrEnd; ++itr)
+ {
+ CheckBox* p = *itr;
+ p->SetPosSizePixel(aPos, aSize);
+ p->SetFont(getLabelFont());
+ p->SetClickHdl( LINK(this, ScDPFieldPopupWindow, CheckBoxHdl) );
+ aPos.Y() += aSize.Height() + 1;
+ }
+
+ getSectionPosSize(aPos, aSize, BTN_OK);
+ maBtnOk.SetPosSizePixel(aPos, aSize);
+ maBtnOk.SetFont(getLabelFont());
+ maBtnOk.SetClickHdl( LINK(this, ScDPFieldPopupWindow, OKButtonHdl) );
+ maBtnOk.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_CANCEL);
+ maBtnCancel.SetPosSizePixel(aPos, aSize);
+ maBtnCancel.SetFont(getLabelFont());
+ maBtnCancel.Show();
+
+ getSectionPosSize(aPos, aSize, SCROLL_BAR_V);
+ maScrollBar.SetPosSizePixel(aPos, aSize);
+ maScrollBar.SetPageSize(mpCheckPtr.size());
+ maScrollBar.SetVisibleSize(mpCheckPtr.size());
+ maScrollBar.SetLineSize(1);
+ maScrollBar.SetScrollHdl( LINK(this, ScDPFieldPopupWindow, ScrollHdl) );
+ maScrollBar.EnableDrag(true);
+}
+
+ScDPFieldPopupWindow::~ScDPFieldPopupWindow()
+{
+}
+
+vector<ScDPFieldPopupWindow::Member>& ScDPFieldPopupWindow::getMembers()
+{
+ return maMembers;
+}
+
+void ScDPFieldPopupWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
+{
+ const sal_uInt16 nListBoxMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuHeight = 60;
+ const sal_uInt16 nBottomBtnAreaHeight = 50;
+ const sal_uInt16 nInnerItemMargin = 5;
+ const sal_uInt16 nScrollBarWidth = 17;
+ const sal_uInt16 nBtnWidth = 60;
+ const sal_uInt16 nBtnHeight = getLabelFont().GetHeight()*2;
+ const sal_uInt16 nBottomMargin = 10;
+ const sal_uInt16 nMenuListMargin = 20;
+
+ Size aWndSize = Size(160, 330);
+
+ switch (eType)
+ {
+ case WHOLE:
+ {
+ rPos = Point(0, 0);
+ rSize = aWndSize;
+ }
+ break;
+ case LISTBOX_AREA:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rSize = Size(
+ aWndSize.Width() - nListBoxMargin*2,
+ aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight);
+ }
+ break;
+ case FIRST_LISTITEM:
+ {
+ rPos = Point(nListBoxMargin + nInnerItemMargin,
+ nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin);
+ rSize = Size(
+ aWndSize.Width() - nListBoxMargin*2 - nInnerItemMargin - nScrollBarWidth - 10,
+ 17);
+ }
+ break;
+ case BTN_OK:
+ {
+ long x = (aWndSize.Width() - nBtnWidth*2)/3;
+ long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ case BTN_CANCEL:
+ {
+ long x = (aWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
+ long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ case SCROLL_BAR_V:
+ {
+ long x = aWndSize.Width() - nListBoxMargin - nInnerItemMargin - nScrollBarWidth;
+ long y = nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin;
+ rPos = Point(x, y);
+ long h = aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight - nInnerItemMargin*2;
+ rSize = Size(nScrollBarWidth, h);
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void ScDPFieldPopupWindow::resetDisplayedItems()
+{
+ long nScrollPos = maScrollBar.GetThumbPos();
+ if (nScrollPos < 0)
+ return;
+
+ mnScrollPos = static_cast<size_t>(nScrollPos);
+ size_t nCheckCount = mpCheckPtr.size();
+ for (size_t i = 0; i < nCheckCount; ++i)
+ {
+ CheckBox* p = mpCheckPtr[i];
+ p->SetText(maMembers[i+mnScrollPos].maName);
+ TriState nNewState = maMembers[i+mnScrollPos].mbVisible ? STATE_CHECK : STATE_NOCHECK;
+ p->SetState(nNewState);
+ }
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, CheckBoxHdl, CheckBox*, pCheck )
+{
+ vector<CheckBox*>::const_iterator itr, itrBeg = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ if (*itr == pCheck)
+ {
+ size_t nIndex = ::std::distance(itrBeg, itr);
+ maMembers[nIndex+mnScrollPos].mbVisible = !maMembers[nIndex+mnScrollPos].mbVisible;
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, OKButtonHdl, OKButton*, EMPTYARG )
+{
+ close(true);
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, ScrollHdl, ScrollBar*, EMPTYARG )
+{
+ resetDisplayedItems();
+ return 0;
+}
+
+void ScDPFieldPopupWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ ScMenuFloatingWindow::MouseMove(rMEvt);
+
+ size_t nSelectedMenu = getSelectedMenuItem();
+ if (nSelectedMenu == MENU_NOT_SELECTED)
+ queueCloseSubMenu();
+}
+
+void ScDPFieldPopupWindow::Paint(const Rectangle& rRect)
+{
+ ScMenuFloatingWindow::Paint(rRect);
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aMemberBackColor = rStyle.GetFieldColor();
+
+ // Member list box background
+ SetFillColor(aMemberBackColor);
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, LISTBOX_AREA);
+ DrawRect(Rectangle(aPos,aSize));
+}
+
+void ScDPFieldPopupWindow::setMemberSize(size_t n)
+{
+ maMembers.reserve(n);
+}
+
+void ScDPFieldPopupWindow::addMember(const OUString& rName, bool bVisible)
+{
+ Member aMember;
+ aMember.maName = rName;
+ aMember.mbVisible = bVisible;
+ maMembers.push_back(aMember);
+}
+
+void ScDPFieldPopupWindow::initMembers()
+{
+ size_t nMemCount = maMembers.size();
+ size_t nCheckCount = mpCheckPtr.size();
+ bool bNeedsScroll = false;
+ if (nMemCount > nCheckCount)
+ {
+ nMemCount = nCheckCount;
+ bNeedsScroll = true;
+ }
+
+ for (size_t i = 0; i < nMemCount; ++i)
+ {
+ CheckBox* p = mpCheckPtr[i];
+ p->SetText(maMembers[i].maName);
+ p->Show();
+ p->SetState(maMembers[i].mbVisible ? STATE_CHECK : STATE_NOCHECK);
+ }
+ if (bNeedsScroll)
+ {
+ maScrollBar.SetRange(Range(0, maMembers.size()));
+ maScrollBar.Show();
+ }
+}
+
+void ScDPFieldPopupWindow::getResult(hash_map<OUString, bool, OUStringHash>& rResult)
+{
+ typedef hash_map<OUString, bool, OUStringHash> ResultMap;
+ ResultMap aResult;
+ vector<Member>::const_iterator itr = maMembers.begin(), itrEnd = maMembers.end();
+ for (; itr != itrEnd; ++itr)
+ aResult.insert(ResultMap::value_type(itr->maName, itr->mbVisible));
+ rResult.swap(aResult);
+}
+
+void ScDPFieldPopupWindow::close(bool bOK)
+{
+ if (bOK && mpOKAction.get())
+ mpOKAction->execute();
+
+ EndPopupMode();
+}
+
+void ScDPFieldPopupWindow::setExtendedData(ExtendedData* p)
+{
+ mpExtendedData.reset(p);
+}
+
+ScDPFieldPopupWindow::ExtendedData* ScDPFieldPopupWindow::getExtendedData()
+{
+ return mpExtendedData.get();
+}
+
+void ScDPFieldPopupWindow::setOKAction(Action* p)
+{
+ mpOKAction.reset(p);
+}
+
diff --git a/sc/source/ui/cctrl/dpcontrol.src b/sc/source/ui/cctrl/dpcontrol.src
new file mode 100644
index 000000000000..5f7ab9a66a9f
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.src
@@ -0,0 +1,49 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: globstr.src,v $
+ * $Revision: 1.74.96.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "dpcontrol.hrc"
+
+Resource RID_POPUP_FILTER
+{
+ String STR_MENU_SORT_ASC
+ {
+ Text [ en-US ] = "Sort Ascending" ;
+ };
+
+ String STR_MENU_SORT_DESC
+ {
+ Text [ en-US ] = "Sort Descending" ;
+ };
+
+ String STR_MENU_SORT_CUSTOM
+ {
+ Text [ en-US ] = "Custom Sort" ;
+ };
+};
diff --git a/sc/source/ui/cctrl/makefile.mk b/sc/source/ui/cctrl/makefile.mk
index e7b96afd7b9a..541a90cc4347 100644
--- a/sc/source/ui/cctrl/makefile.mk
+++ b/sc/source/ui/cctrl/makefile.mk
@@ -45,22 +45,30 @@ LIBTARGET=NO
# --- Files --------------------------------------------------------
EXCEPTIONSFILES= \
- $(SLO)$/tbzoomsliderctrl.obj
+ $(SLO)$/tbzoomsliderctrl.obj \
+ $(SLO)$/dpcontrol.obj
SLOFILES = \
$(SLO)$/popmenu.obj \
$(SLO)$/tbinsert.obj \
$(SLO)$/cbuttonw.obj \
+ $(SLO)$/dpcontrol.obj \
$(SLO)$/editfield.obj \
$(EXCEPTIONSFILES)
+SRS1NAME=$(TARGET)
+SRC1FILES = \
+ dpcontrol.src
+
LIB1TARGET=$(SLB)$/$(TARGET).lib
LIB1OBJFILES= \
$(SLO)$/popmenu.obj \
$(SLO)$/tbinsert.obj \
$(SLO)$/cbuttonw.obj \
+ $(SLO)$/dpcontrol.obj \
$(SLO)$/tbzoomsliderctrl.obj
+
# --- Tagets -------------------------------------------------------
.INCLUDE : target.mk
diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index c23068b82200..688c0d60f79e 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -64,6 +64,7 @@
#include "scabstdlg.hxx" //CHINA001
using namespace com::sun::star;
using ::rtl::OUString;
+using ::std::vector;
//----------------------------------------------------------------------------
@@ -379,24 +380,23 @@ void ScDPLayoutDlg::StateChanged( StateChangedType nStateChange )
//----------------------------------------------------------------------------
-void ScDPLayoutDlg::InitWndSelect( LabelData** ppLabelArr, long nLabels )
+void ScDPLayoutDlg::InitWndSelect( const vector<ScDPLabelDataRef>& rLabels )
{
- if ( ppLabelArr )
+ size_t nLabelCount = rLabels.size();
+ if (nLabelCount > MAX_LABELS)
+ nLabelCount = MAX_LABELS;
+ size_t nLast = (nLabelCount > PAGE_SIZE) ? (PAGE_SIZE - 1) : (nLabelCount - 1);
+
+ aLabelDataArr.clear();
+ aLabelDataArr.reserve( nLabelCount );
+ for ( size_t i=0; i < nLabelCount; i++ )
{
- size_t nLabelCount = static_cast< size_t >( (nLabels > MAX_LABELS) ? MAX_LABELS : nLabels );
- size_t nLast = (nLabelCount > PAGE_SIZE) ? (PAGE_SIZE - 1) : (nLabelCount - 1);
+ aLabelDataArr.push_back(*rLabels[i]);
- aLabelDataArr.clear();
- aLabelDataArr.reserve( nLabelCount );
- for ( size_t i=0; i < nLabelCount; i++ )
+ if ( i <= nLast )
{
- aLabelDataArr.push_back( *ppLabelArr[i] );
-
- if ( i <= nLast )
- {
- aWndSelect.AddField( aLabelDataArr[i].maName, i );
- aSelectArr[i].reset( new ScDPFuncData( aLabelDataArr[i].mnCol, aLabelDataArr[i].mnFuncMask ) );
- }
+ aWndSelect.AddField( aLabelDataArr[i].maName, i );
+ aSelectArr[i].reset( new ScDPFuncData( aLabelDataArr[i].mnCol, aLabelDataArr[i].mnFuncMask ) );
}
}
}
@@ -494,18 +494,19 @@ void ScDPLayoutDlg::InitFocus()
void ScDPLayoutDlg::InitFields()
{
- InitWndSelect( thePivotData.ppLabelArr, static_cast<long>(thePivotData.nLabels) );
+ InitWndSelect(thePivotData.maLabelArray);
InitWnd( thePivotData.aPageArr, static_cast<long>(thePivotData.nPageCount), TYPE_PAGE );
InitWnd( thePivotData.aColArr, static_cast<long>(thePivotData.nColCount), TYPE_COL );
InitWnd( thePivotData.aRowArr, static_cast<long>(thePivotData.nRowCount), TYPE_ROW );
InitWnd( thePivotData.aDataArr, static_cast<long>(thePivotData.nDataCount), TYPE_DATA );
+ size_t nLabels = thePivotData.maLabelArray.size();
aSlider.SetPageSize( PAGE_SIZE );
aSlider.SetVisibleSize( PAGE_SIZE );
aSlider.SetLineSize( LINE_SIZE );
- aSlider.SetRange( Range( 0, static_cast<long>(((thePivotData.nLabels+LINE_SIZE-1)/LINE_SIZE)*LINE_SIZE) ) );
+ aSlider.SetRange( Range( 0, static_cast<long>(((nLabels+LINE_SIZE-1)/LINE_SIZE)*LINE_SIZE) ) );
- if ( thePivotData.nLabels > PAGE_SIZE )
+ if ( nLabels > PAGE_SIZE )
{
aSlider.SetEndScrollHdl( LINK( this, ScDPLayoutDlg, ScrollHdl ) );
aSlider.Show();
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 1e85f3c01f3e..ebbdd6cfbae4 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -1233,7 +1233,7 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb
aRange.aEnd.Col(), aRange.aEnd.Row(),
nTab, SC_MF_AUTO );
- pDoc->GetDPCollection()->Free( pOldObj ); // object is deleted here
+ pDoc->GetDPCollection()->FreeTable( pOldObj ); // object is deleted here
rDocShell.PostPaintGridAll(); //! only necessary parts
rDocShell.PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), nTab,
@@ -1277,7 +1277,7 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb
pDestObj = new ScDPObject( *pNewObj );
pDestObj->SetAlive(TRUE);
- if ( !pDoc->GetDPCollection()->Insert(pDestObj) )
+ if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
{
DBG_ERROR("cannot insert DPObject");
DELETEZ( pDestObj );
diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx
index 82739bfdd274..afeb90df1a79 100644
--- a/sc/source/ui/inc/dbfunc.hxx
+++ b/sc/source/ui/inc/dbfunc.hxx
@@ -99,6 +99,7 @@ public:
void UngroupDataPilot();
void DataPilotInput( const ScAddress& rPos, const String& rString );
+ bool DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId = NULL );
BOOL DataPilotMove( const ScRange& rSource, const ScAddress& rDest );
BOOL HasSelectionForDrillDown( USHORT& rOrientation );
diff --git a/sc/source/ui/inc/dpcontrol.hrc b/sc/source/ui/inc/dpcontrol.hrc
new file mode 100644
index 000000000000..7ec03c5134ae
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hrc
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: protectiondlg.hrc,v $
+ * $Revision: 1.1.2.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __DPCONTROL_HRC__
+#define __DPCONTROL_HRC__
+
+#include <sc.hrc>
+
+#define STR_MENU_SORT_ASC 1
+#define STR_MENU_SORT_DESC 2
+#define STR_MENU_SORT_CUSTOM 3
+
+#endif
diff --git a/sc/source/ui/inc/dpcontrol.hxx b/sc/source/ui/inc/dpcontrol.hxx
new file mode 100644
index 000000000000..5c1e7a59aad2
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hxx
@@ -0,0 +1,289 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.hxx,v $
+ * $Revision: 1.115.36.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_DPCONTROL_HXX
+#define SC_DPCONTROL_HXX
+
+#include "rtl/ustring.hxx"
+#include "tools/gen.hxx"
+#include "vcl/floatwin.hxx"
+#include "vcl/button.hxx"
+#include "vcl/scrbar.hxx"
+#include "vcl/timer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <hash_map>
+
+class OutputDevice;
+class Point;
+class Size;
+class StyleSettings;
+class Window;
+
+/**
+ * This class takes care of physically drawing field button controls inside
+ * data pilot tables.
+ */
+class ScDPFieldButton
+{
+public:
+ ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle);
+ ~ScDPFieldButton();
+
+ void setText(const ::rtl::OUString& rText);
+ void setBoundingBox(const Point& rPos, const Size& rSize);
+ void setDrawPopupButton(bool b);
+ void setHasHiddenMember(bool b);
+ void draw();
+
+ void getPopupBoundingBox(Point& rPos, Size& rSize) const;
+ bool isPopupButton() const;
+
+private:
+ void drawPopupButton();
+
+private:
+ Point maPos;
+ Size maSize;
+ ::rtl::OUString maText;
+ OutputDevice* mpOutDev;
+ const StyleSettings* mpStyle;
+ bool mbPopupButton;
+ bool mbHasHiddenMember;
+};
+
+// ============================================================================
+
+class ScMenuFloatingWindow : public FloatingWindow
+{
+public:
+ /**
+ * Action to perform when an event takes place. Create a sub-class of
+ * this to implement the desired action.
+ */
+ class Action
+ {
+ public:
+ virtual void execute() = 0;
+ };
+
+ explicit ScMenuFloatingWindow(Window* pParent);
+ virtual ~ScMenuFloatingWindow();
+
+ virtual void MouseMove(const MouseEvent& rMEvt);
+ virtual void MouseButtonDown(const MouseEvent& rMEvt);
+ virtual void MouseButtonUp(const MouseEvent& rMEvt);
+ virtual void KeyInput(const KeyEvent& rKEvt);
+ virtual void Paint(const Rectangle& rRect);
+
+ void addMenuItem(const ::rtl::OUString& rText, bool bEnabled, Action* pAction);
+ ScMenuFloatingWindow* addSubMenuItem(const ::rtl::OUString& rText, bool bEnabled);
+
+protected:
+ void drawMenuItem(size_t nPos);
+ void drawAllMenuItems();
+ const Font& getLabelFont() const;
+
+ void executeMenu(size_t nPos);
+ void setSelectedMenuItem(size_t nPos, bool bSubMenuTimer = true);
+ size_t getSelectedMenuItem() const;
+ void queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu);
+ void queueCloseSubMenu();
+ void launchSubMenu(bool bSetMenuPos);
+ void endSubMenu();
+
+private:
+ struct SubMenuItem;
+ void handleMenuTimeout(SubMenuItem* pTimer);
+
+ enum NotificationType { SUBMENU_FOCUSED };
+ void notify(NotificationType eType);
+
+ void resetMenu(bool bSetMenuPos);
+ void resizeToFitMenuItems();
+ void selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer);
+ void highlightMenuItem(size_t nPos, bool bSelected);
+
+ void getMenuItemPosSize(Point& rPos, Size& rSize, size_t nPos) const;
+ size_t getEnclosingMenuItem(const Point& rPos) const;
+
+ DECL_LINK( EndPopupHdl, void* );
+
+private:
+ struct MenuItem
+ {
+ ::rtl::OUString maText;
+ bool mbEnabled;
+
+ ::boost::shared_ptr<Action> mpAction;
+ ::boost::shared_ptr<ScMenuFloatingWindow> mpSubMenuWin;
+
+ MenuItem();
+ };
+
+ ::std::vector<MenuItem> maMenuItems;
+
+ struct SubMenuItem
+ {
+ Timer maTimer;
+ ScMenuFloatingWindow* mpSubMenu;
+ size_t mnMenuPos;
+
+ DECL_LINK( TimeoutHdl, void* );
+
+ SubMenuItem(ScMenuFloatingWindow* pParent);
+ void reset();
+
+ private:
+ ScMenuFloatingWindow* mpParent;
+ };
+ SubMenuItem maOpenTimer;
+ SubMenuItem maCloseTimer;
+
+ Font maLabelFont;
+
+ size_t mnSelectedMenu;
+ size_t mnClickedMenu;
+
+ ScMenuFloatingWindow* mpParentMenu;
+ ScMenuFloatingWindow* mpActiveSubMenu;
+
+ bool mbActionFired;
+};
+
+// ============================================================================
+
+/**
+ * This class implements a popup window for field button, for quick access
+ * of hide-item list, and possibly more stuff related to field options.
+ */
+class ScDPFieldPopupWindow : public ScMenuFloatingWindow
+{
+public:
+ /**
+ * Extended data that the client code may need to store. Create a
+ * sub-class of this and store data there.
+ */
+ struct ExtendedData {};
+
+ explicit ScDPFieldPopupWindow(Window* pParent);
+ virtual ~ScDPFieldPopupWindow();
+
+ virtual void MouseMove(const MouseEvent& rMEvt);
+ virtual void Paint(const Rectangle& rRect);
+
+ void setMemberSize(size_t n);
+ void addMember(const ::rtl::OUString& rName, bool bVisible);
+ void initMembers();
+
+ void getResult(::std::hash_map< ::rtl::OUString, bool, ::rtl::OUStringHash>& rResult);
+ void close(bool bOK);
+
+ /**
+ * Set auxiliary data that the client code might need. Note that this
+ * popup window class manages its life time; no explicit deletion of the
+ * instance is needed in the client code.
+ */
+ void setExtendedData(ExtendedData* p);
+
+ /**
+ * Get the store auxiliary data, or NULL if no such data is stored.
+ */
+ ExtendedData* getExtendedData();
+
+ void setOKAction(Action* p);
+
+private:
+ struct Member
+ {
+ ::rtl::OUString maName;
+ bool mbVisible;
+
+ Member();
+ };
+
+ class CancelButton : public ::CancelButton
+ {
+ public:
+ CancelButton(ScDPFieldPopupWindow* pParent);
+
+ virtual void Click();
+
+ private:
+ ScDPFieldPopupWindow* mpParent;
+ };
+
+ ::std::vector<Member>& getMembers();
+
+ enum SectionType {
+ WHOLE, // entire window
+ LISTBOX_AREA, // box enclosing the check box items.
+ FIRST_LISTITEM, // first list item at the top
+ BTN_OK, // OK button
+ BTN_CANCEL, // Cancel button
+ SCROLL_BAR_V, // vertical scroll bar along the right edge of the list box.
+ };
+ void getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const;
+
+ void resetDisplayedItems();
+
+ DECL_LINK( CheckBoxHdl, CheckBox* );
+ DECL_LINK( OKButtonHdl, OKButton* );
+ DECL_LINK( ScrollHdl, ScrollBar* );
+
+private:
+
+ CheckBox maCheck0;
+ CheckBox maCheck1;
+ CheckBox maCheck2;
+ CheckBox maCheck3;
+ CheckBox maCheck4;
+ CheckBox maCheck5;
+ CheckBox maCheck6;
+ CheckBox maCheck7;
+ CheckBox maCheck8;
+ CheckBox maCheck9;
+
+ ScrollBar maScrollBar;
+
+ OKButton maBtnOk;
+ CancelButton maBtnCancel;
+
+ ::std::vector<CheckBox*> mpCheckPtr;
+
+ ::std::vector<Member> maMembers;
+ ::std::auto_ptr<ExtendedData> mpExtendedData;
+ ::std::auto_ptr<Action> mpOKAction;
+
+ size_t mnScrollPos;
+};
+
+#endif
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 9b31289d13d0..32ecaf26cc56 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -39,6 +39,7 @@
#include <svx/sdr/overlay/overlayobject.hxx>
#include <vector>
+#include <memory>
// ---------------------------------------------------------------------------
@@ -48,6 +49,7 @@ class ScViewSelectionEngine;
class ScPivot;
#endif
class ScDPObject;
+class ScDPFieldPopupWindow;
class ScOutputData;
class ScFilterListBox;
class AutoFilterPopup;
@@ -159,6 +161,7 @@ private:
ScFilterListBox* pFilterBox;
FloatingWindow* pFilterFloat;
+ ::std::auto_ptr<ScDPFieldPopupWindow> mpDPFieldPopup;
USHORT nCursorHideCount;
@@ -245,6 +248,16 @@ private:
void DPMouseButtonUp( const MouseEvent& rMEvt );
void DPTestMouse( const MouseEvent& rMEvt, BOOL bMove );
+ /**
+ * Check if the mouse click is on a field popup button.
+ *
+ * @return bool true if the field popup menu has been launched and no
+ * further mouse event handling is necessary, false otherwise.
+ */
+ bool DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj);
+ void DPLaunchFieldPopupMenu(
+ const Point& rSrcPos, const Size& rSrcSize, const ScAddress& rPos, ScDPObject* pDPObj);
+
void RFMouseMove( const MouseEvent& rMEvt, BOOL bUp );
void PagebreakMove( const MouseEvent& rMEvt, BOOL bUp );
@@ -409,6 +422,8 @@ public:
void CheckNeedsRepaint();
+ void UpdateDPFromFieldPopupMenu();
+
// #114409#
void CursorChanged();
void DrawLayerCreated();
diff --git a/sc/source/ui/inc/pvlaydlg.hxx b/sc/source/ui/inc/pvlaydlg.hxx
index b7a71aebc1fe..c77364d3761f 100644
--- a/sc/source/ui/inc/pvlaydlg.hxx
+++ b/sc/source/ui/inc/pvlaydlg.hxx
@@ -193,7 +193,7 @@ private:
private:
ScDPFieldWindow& GetFieldWindow ( ScDPFieldType eType );
void Init ();
- void InitWndSelect ( LabelData** ppLabelArr, long nLabels );
+ void InitWndSelect ( const ::std::vector<ScDPLabelDataRef>& rLabels );
void InitWnd ( PivotField* pArr, long nCount, ScDPFieldType eType );
void InitFocus ();
void InitFields ();
diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx
index f16409b37239..ffc750a7ceb8 100644
--- a/sc/source/ui/undo/undodat.cxx
+++ b/sc/source/ui/undo/undodat.cxx
@@ -1876,7 +1876,7 @@ void __EXPORT ScUndoDataPilot::Undo()
else
{
// delete inserted object
- pDoc->GetDPCollection()->Free(pDocObj);
+ pDoc->GetDPCollection()->FreeTable(pDocObj);
}
}
}
@@ -1886,7 +1886,7 @@ void __EXPORT ScUndoDataPilot::Undo()
ScDPObject* pDestObj = new ScDPObject( *pOldDPObject );
pDestObj->SetAlive(TRUE);
- if ( !pDoc->GetDPCollection()->Insert(pDestObj) )
+ if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
{
DBG_ERROR("cannot insert DPObject");
DELETEZ( pDestObj );
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index c71bc31a1150..e0d6693b39ef 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -81,9 +81,13 @@
#include "patattr.hxx"
#include "unonames.hxx"
#include "cell.hxx"
+#include "userlist.hxx"
#include <hash_set>
+#include <hash_map>
#include <memory>
+#include <list>
+#include <vector>
using namespace com::sun::star;
using ::com::sun::star::uno::Any;
@@ -94,8 +98,13 @@ using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::container::XNameAccess;
using ::com::sun::star::sheet::XDimensionsSupplier;
using ::rtl::OUString;
+using ::rtl::OUStringHash;
using ::rtl::OUStringBuffer;
using ::std::auto_ptr;
+using ::std::list;
+using ::std::vector;
+using ::std::hash_map;
+using ::std::hash_set;
// STATIC DATA -----------------------------------------------------------
@@ -1681,6 +1690,134 @@ void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName )
// puts it to the end of the list even if it was in the list before.
}
+bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab());
+ if (!pDPObj)
+ return false;
+
+ // We need to run this to get all members later.
+ pDPObj->BuildAllDimensionMembers();
+
+ USHORT nOrientation;
+ long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation);
+ if (nDimIndex < 0)
+ // Invalid dimension index. Bail out.
+ return false;
+
+ BOOL bDataLayout;
+ ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+ if (!pSaveData)
+ return false;
+
+ ScDPSaveData aNewSaveData(*pSaveData);
+ String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
+ ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
+ if (!pSaveDim)
+ return false;
+
+ typedef ScDPSaveDimension::MemberList MemList;
+ const MemList& rDimMembers = pSaveDim->GetMembers();
+ list<OUString> aMembers;
+ hash_set<OUString, ::rtl::OUStringHash> aMemberSet;
+ size_t nMemberCount = 0;
+ for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end();
+ itr != itrEnd; ++itr)
+ {
+ ScDPSaveMember* pMem = *itr;
+ aMembers.push_back(pMem->GetName());
+ aMemberSet.insert(pMem->GetName());
+ ++nMemberCount;
+ }
+
+ // Sort the member list in ascending order.
+ aMembers.sort();
+
+ // Collect and rank those custom sort strings that also exist in the member name list.
+
+ typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap;
+ UserSortMap aSubStrs;
+ sal_uInt16 nSubCount = 0;
+ if (pUserListId)
+ {
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ if (!pUserList)
+ return false;
+
+ {
+ sal_uInt16 n = pUserList->GetCount();
+ if (!n || *pUserListId >= n)
+ return false;
+ }
+
+ ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]);
+ if (pData)
+ {
+ sal_uInt16 n = pData->GetSubCount();
+ for (sal_uInt16 i = 0; i < n; ++i)
+ {
+ OUString aSub = pData->GetSubStr(i);
+ if (!aMemberSet.count(aSub))
+ // This string doesn't exist in the member name set. Don't add this.
+ continue;
+
+ aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++));
+ }
+ }
+ }
+
+ // Rank all members.
+
+ vector<OUString> aRankedNames(nMemberCount);
+ sal_uInt16 nCurStrId = 0;
+ for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end();
+ itr != itrEnd; ++itr)
+ {
+ OUString aName = *itr;
+ sal_uInt16 nRank = 0;
+ UserSortMap::const_iterator itrSub = aSubStrs.find(aName);
+ if (itrSub == aSubStrs.end())
+ nRank = nSubCount + nCurStrId++;
+ else
+ nRank = itrSub->second;
+
+ if (!bAscending)
+ nRank = nMemberCount - nRank - 1;
+
+ aRankedNames[nRank] = aName;
+ }
+
+ // Re-order ScDPSaveMember instances with the new ranks.
+
+ for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end();
+ itr != itrEnd; ++itr)
+ {
+ const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr);
+ if (!pOldMem)
+ // All members are supposed to be present.
+ continue;
+
+ ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem);
+ pSaveDim->AddMember(pNewMem);
+ }
+
+ // Set the sorting mode to manual for now. We may introduce a new sorting
+ // mode later on.
+
+ sheet::DataPilotFieldSortInfo aSortInfo;
+ aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
+ pSaveDim->SetSortInfo(&aSortInfo);
+
+ // Update the datapilot with the newly sorted field members.
+
+ auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
+ pNewObj->SetSaveData(aNewSaveData);
+ ScDBDocFunc aFunc(*GetViewData()->GetDocShell());
+
+ return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
+}
+
BOOL ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
{
BOOL bRet = FALSE;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 5591a2a496be..8949d2bd29a9 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -119,6 +119,7 @@
#include "drwlayer.hxx"
#include "attrib.hxx"
#include "validat.hxx"
+#include "dpcontrol.hxx"
// #114409#
#include <vcl/salbtype.hxx> // FRound
@@ -370,6 +371,7 @@ ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhic
pNoteMarker( NULL ),
pFilterBox( NULL ),
pFilterFloat( NULL ),
+ mpDPFieldPopup(NULL),
nCursorHideCount( 0 ),
bMarking( FALSE ),
nButtonDown( 0 ),
diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx
index 92743ef65524..1cfb5bdf71c0 100644
--- a/sc/source/ui/view/gridwin2.cxx
+++ b/sc/source/ui/view/gridwin2.cxx
@@ -55,11 +55,23 @@
#include "dpoutput.hxx" // ScDPPositionData
#include "dpshttab.hxx"
#include "dbdocfun.hxx"
+#include "dpcontrol.hxx"
+#include "dpcontrol.hrc"
+#include "strload.hxx"
+#include "userlist.hxx"
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include "scabstdlg.hxx" //CHINA001
-using namespace com::sun::star;
+#include <vector>
+#include <hash_map>
+
+using namespace com::sun::star;
+using ::std::vector;
+using ::std::auto_ptr;
+using ::std::hash_map;
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
// STATIC DATA -----------------------------------------------------------
@@ -199,6 +211,15 @@ void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt
bDPMouse = TRUE;
nDPField = nField;
pDragDPObj = pDPObj;
+
+ if (DPTestFieldPopupArrow(rMEvt, aPos, pDPObj))
+ {
+ // field name pop up menu has been launched. Don't activate
+ // field move.
+ bDPMouse = false;
+ return;
+ }
+
DPTestMouse( rMEvt, TRUE );
StartTracking();
}
@@ -726,6 +747,185 @@ void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, BOOL bMove )
pViewData->GetView()->ResetTimer();
}
+bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj)
+{
+ // Get the geometry of the cell.
+ Point aSrcPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich);
+ long nSizeX, nSizeY;
+ pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
+ Size aSrcSize(nSizeX-1, nSizeY-1);
+
+ // Check if the mouse cursor is clicking on the popup arrow box.
+ ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings());
+ aBtn.setBoundingBox(aSrcPos, aSrcSize);
+ Point aPopupPos;
+ Size aPopupSize;
+ aBtn.getPopupBoundingBox(aPopupPos, aPopupSize);
+ Rectangle aRec(aPopupPos, aPopupSize);
+ if (aRec.IsInside(rMEvt.GetPosPixel()))
+ {
+ // Mouse cursor inside the popup arrow box. Launch the field menu.
+ DPLaunchFieldPopupMenu(OutputToScreenPixel(aSrcPos), aSrcSize, rPos, pDPObj);
+ return true;
+ }
+
+ return false;
+}
+
+namespace {
+
+struct DPFieldPopupData : public ScDPFieldPopupWindow::ExtendedData
+{
+ ScPivotParam maDPParam;
+ ScDPObject* mpDPObj;
+ long mnDim;
+};
+
+class DPFieldPopupOKAction : public ScMenuFloatingWindow::Action
+{
+public:
+ explicit DPFieldPopupOKAction(ScGridWindow* p) :
+ mpGridWindow(p) {}
+
+ virtual void execute()
+ {
+ mpGridWindow->UpdateDPFromFieldPopupMenu();
+ }
+private:
+ ScGridWindow* mpGridWindow;
+};
+
+class PopupSortAction : public ScMenuFloatingWindow::Action
+{
+public:
+ enum SortType { ASCENDING, DESCENDING, CUSTOM };
+
+ explicit PopupSortAction(const ScAddress& rPos, SortType eType, sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell) :
+ maPos(rPos), meType(eType), mnUserListIndex(nUserListIndex), mpViewShell(pViewShell) {}
+
+ virtual void execute()
+ {
+ switch (meType)
+ {
+ case ASCENDING:
+ mpViewShell->DataPilotSort(maPos, true);
+ break;
+ case DESCENDING:
+ mpViewShell->DataPilotSort(maPos, false);
+ break;
+ case CUSTOM:
+ mpViewShell->DataPilotSort(maPos, true, &mnUserListIndex);
+ break;
+ default:
+ ;
+ }
+ }
+
+private:
+ ScAddress maPos;
+ SortType meType;
+ sal_uInt16 mnUserListIndex;
+ ScTabViewShell* mpViewShell;
+};
+
+}
+
+void ScGridWindow::DPLaunchFieldPopupMenu(
+ const Point& rSrcPos, const Size& rSrcSize, const ScAddress& rPos, ScDPObject* pDPObj)
+{
+ // We need to get the list of field members.
+ auto_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData);
+ pDPObj->FillLabelData(pDPData->maDPParam);
+ pDPData->mpDPObj = pDPObj;
+
+ USHORT nOrient;
+ pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient);
+
+ if (pDPData->maDPParam.maLabelArray.size() <= static_cast<size_t>(pDPData->mnDim))
+ // out-of-bound dimension ID. This should never happen!
+ return;
+
+ const ScDPLabelData& rLabelData = *pDPData->maDPParam.maLabelArray[pDPData->mnDim];
+
+ mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this));
+ mpDPFieldPopup->setExtendedData(pDPData.release());
+ mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this));
+ {
+ sal_Int32 n = rLabelData.maMembers.getLength();
+ mpDPFieldPopup->setMemberSize(n);
+ for (sal_Int32 i = 0; i < n; ++i)
+ mpDPFieldPopup->addMember(rLabelData.maMembers[i], rLabelData.maVisible[i]);
+ mpDPFieldPopup->initMembers();
+ }
+
+ vector<OUString> aUserSortNames;
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ if (pUserList)
+ {
+ sal_uInt16 n = pUserList->GetCount();
+ aUserSortNames.reserve(n);
+ for (sal_uInt16 i = 0; i < n; ++i)
+ {
+ ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[i]);
+ aUserSortNames.push_back(pData->GetString());
+ }
+ }
+
+ // Populate the menus.
+ ScTabViewShell* pViewShell = pViewData->GetViewShell();
+ mpDPFieldPopup->addMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(), true,
+ new PopupSortAction(rPos, PopupSortAction::ASCENDING, 0, pViewShell));
+ mpDPFieldPopup->addMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(), true,
+ new PopupSortAction(rPos, PopupSortAction::DESCENDING, 0, pViewShell));
+ ScMenuFloatingWindow* pSubMenu = mpDPFieldPopup->addSubMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_CUSTOM).GetString(), !aUserSortNames.empty());
+
+ if (pSubMenu && !aUserSortNames.empty())
+ {
+ size_t n = aUserSortNames.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ pSubMenu->addMenuItem(
+ aUserSortNames[i], true,
+ new PopupSortAction(rPos, PopupSortAction::CUSTOM, i, pViewShell));
+ }
+ }
+
+ mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) );
+ Rectangle aCellRect(rSrcPos, rSrcSize);
+ mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
+}
+
+void ScGridWindow::UpdateDPFromFieldPopupMenu()
+{
+ if (!mpDPFieldPopup.get())
+ return;
+
+ DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData());
+ if (!pDPData)
+ return;
+
+ ScDPObject* pDPObj = pDPData->mpDPObj;
+ ScDPObject aNewDPObj(*pDPObj);
+ aNewDPObj.BuildAllDimensionMembers();
+ ScDPSaveData* pSaveData = aNewDPObj.GetSaveData();
+
+ BOOL bIsDataLayout;
+ String aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout);
+ ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName);
+ if (!pDim)
+ return;
+
+ hash_map<OUString, bool, OUStringHash> aResult;
+ mpDPFieldPopup->getResult(aResult);
+ pDim->UpdateMemberVisibility(aResult);
+
+ ScDBDocFunc aFunc(*pViewData->GetDocShell());
+ aFunc.DataPilotUpdate(pDPObj, &aNewDPObj, true, false);
+}
+
void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt )
{
DPTestMouse( rMEvt, TRUE );
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index b90e5d3e802e..e6466e7ba3b1 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -73,6 +73,7 @@
#include "editutil.hxx"
#include "inputopt.hxx"
#include "fillinfo.hxx"
+#include "dpcontrol.hxx"
#include "sc.hrc"
#include <vcl/virdev.hxx>
@@ -1203,6 +1204,8 @@ void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2
{
aComboButton.SetOutputDevice( pContentDev );
+ ScDPFieldButton aDPFieldBtn(pContentDev, &GetSettings().GetStyleSettings());
+
SCCOL nCol;
SCROW nRow;
SCSIZE nArrY;
@@ -1318,13 +1321,13 @@ void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2
nPosX -= nSizeX - 2;
}
- pContentDev->SetLineColor( GetSettings().GetStyleSettings().GetLightColor() );
- pContentDev->DrawLine( Point(nPosX,nPosY), Point(nPosX,nPosY+nSizeY-1) );
- pContentDev->DrawLine( Point(nPosX,nPosY), Point(nPosX+nSizeX-1,nPosY) );
- pContentDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
- pContentDev->DrawLine( Point(nPosX,nPosY+nSizeY-1), Point(nPosX+nSizeX-1,nPosY+nSizeY-1) );
- pContentDev->DrawLine( Point(nPosX+nSizeX-1,nPosY), Point(nPosX+nSizeX-1,nPosY+nSizeY-1) );
- pContentDev->SetLineColor( COL_BLACK );
+ String aStr;
+ pDoc->GetString(nCol, nRow, nTab, aStr);
+ aDPFieldBtn.setText(aStr);
+ aDPFieldBtn.setBoundingBox(Point(nPosX,nPosY), Size(nSizeX-1, nSizeY-1));
+ aDPFieldBtn.setDrawPopupButton(pInfo->bPopupButton);
+ aDPFieldBtn.setHasHiddenMember(pInfo->bFilterActive);
+ aDPFieldBtn.draw();
}
}
}