summaryrefslogtreecommitdiff
path: root/sc/source/ui
diff options
context:
space:
mode:
authorThomas Benisch <tbe@openoffice.org>2010-02-17 16:24:29 +0100
committerThomas Benisch <tbe@openoffice.org>2010-02-17 16:24:29 +0100
commiteee5ae330a49c18c4fe8666bc1c2dbc949dc0914 (patch)
tree8450428110c4300040e8d20bfba601bd231114da /sc/source/ui
parent6fae3f3921beb7214a77887e083852f27011179a (diff)
parent25b005cbda460837f063ddf996c1ec72d4f4865b (diff)
chartlayout: merge with DEV300_m71
Diffstat (limited to 'sc/source/ui')
-rw-r--r--sc/source/ui/Accessibility/AccessibleContextBase.cxx5
-rw-r--r--sc/source/ui/Accessibility/AccessibleFilterMenu.cxx401
-rw-r--r--sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx208
-rw-r--r--sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx137
-rw-r--r--sc/source/ui/Accessibility/AccessibleGlobal.cxx98
-rw-r--r--sc/source/ui/Accessibility/makefile.mk8
-rw-r--r--sc/source/ui/cctrl/dpcontrol.cxx1419
-rw-r--r--sc/source/ui/cctrl/dpcontrol.src82
-rw-r--r--sc/source/ui/cctrl/makefile.mk10
-rw-r--r--sc/source/ui/dbgui/makefile.mk1
-rw-r--r--sc/source/ui/dbgui/pvfundlg.cxx66
-rw-r--r--sc/source/ui/dbgui/pvlaydlg.cxx106
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx4
-rw-r--r--sc/source/ui/docshell/docsh4.cxx7
-rw-r--r--sc/source/ui/inc/AccessibleContextBase.hxx2
-rw-r--r--sc/source/ui/inc/dbfunc.hxx3
-rw-r--r--sc/source/ui/inc/dpcontrol.hrc43
-rw-r--r--sc/source/ui/inc/dpcontrol.hxx366
-rw-r--r--sc/source/ui/inc/gridwin.hxx25
-rw-r--r--sc/source/ui/inc/pfuncache.hxx6
-rw-r--r--sc/source/ui/inc/pvfundlg.hxx11
-rw-r--r--sc/source/ui/inc/pvlaydlg.hxx2
-rw-r--r--sc/source/ui/src/scstring.src26
-rw-r--r--sc/source/ui/undo/undodat.cxx4
-rw-r--r--sc/source/ui/unoobj/dapiuno.cxx13
-rw-r--r--sc/source/ui/unoobj/docuno.cxx322
-rw-r--r--sc/source/ui/unoobj/miscuno.cxx37
-rw-r--r--sc/source/ui/unoobj/viewuno.cxx4
-rw-r--r--sc/source/ui/view/cellsh2.cxx15
-rw-r--r--sc/source/ui/view/dbfunc.cxx18
-rw-r--r--sc/source/ui/view/dbfunc3.cxx509
-rw-r--r--sc/source/ui/view/gridwin.cxx120
-rw-r--r--sc/source/ui/view/gridwin2.cxx320
-rwxr-xr-x[-rw-r--r--]sc/source/ui/view/gridwin3.cxx1
-rw-r--r--sc/source/ui/view/gridwin4.cxx30
-rw-r--r--sc/source/ui/view/makefile.mk4
-rw-r--r--sc/source/ui/view/olkact.cxx2
-rwxr-xr-x[-rw-r--r--]sc/source/ui/view/output3.cxx3
-rw-r--r--sc/source/ui/view/pfuncache.cxx4
-rw-r--r--sc/source/ui/view/prevwsh2.cxx2
-rwxr-xr-x[-rw-r--r--]sc/source/ui/view/printfun.cxx24
-rw-r--r--sc/source/ui/view/tabview.cxx30
-rw-r--r--sc/source/ui/view/viewfun3.cxx2
43 files changed, 4225 insertions, 275 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleContextBase.cxx b/sc/source/ui/Accessibility/AccessibleContextBase.cxx
index b611198974de..c6c08e8a9c65 100644
--- a/sc/source/ui/Accessibility/AccessibleContextBase.cxx
+++ b/sc/source/ui/Accessibility/AccessibleContextBase.cxx
@@ -628,3 +628,8 @@ void ScAccessibleContextBase::IsObjectValid() const
if (rBHelper.bDisposed || rBHelper.bInDispose)
throw lang::DisposedException();
}
+
+void ScAccessibleContextBase::SetRole(sal_Int16 nRole)
+{
+ maRole = nRole;
+}
diff --git a/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx b/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx
new file mode 100644
index 000000000000..0c663af87fd1
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleFilterMenu.cxx
@@ -0,0 +1,401 @@
+/*************************************************************************
+ *
+ * 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: AccessibleDataPilotControl.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 "AccessibleGlobal.hxx"
+#include "AccessibleFilterMenu.hxx"
+#include "AccessibleFilterMenuItem.hxx"
+#include "unoguard.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+
+#include "tools/gen.hxx"
+#include "svx/unoedsrc.hxx"
+#include "svx/editdata.hxx"
+#include "svx/outliner.hxx"
+#include "vcl/unohelp.hxx"
+#include "dpcontrol.hxx"
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::accessibility::AccessibleStateType;
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::lang::IllegalArgumentException;
+using ::com::sun::star::uno::RuntimeException;
+using ::rtl::OUString;
+using ::std::for_each;
+using ::std::vector;
+
+// ============================================================================
+
+namespace {
+
+class AddRemoveEventListener : public ::std::unary_function<void, Reference<XAccessible> >
+{
+public:
+ explicit AddRemoveEventListener(const Reference<XAccessibleEventListener>& rListener, bool bAdd) :
+ mxListener(rListener), mbAdd(bAdd) {}
+
+ void operator() (const Reference<XAccessible>& xAccessible) const
+ {
+ if (!xAccessible.is())
+ return;
+
+ Reference<XAccessibleEventBroadcaster> xBc(xAccessible, UNO_QUERY);
+ if (xBc.is())
+ {
+ if (mbAdd)
+ xBc->addEventListener(mxListener);
+ else
+ xBc->removeEventListener(mxListener);
+ }
+ }
+private:
+ Reference<XAccessibleEventListener> mxListener;
+ bool mbAdd;
+};
+
+}
+
+// ============================================================================
+
+ScAccessibleFilterMenu::ScAccessibleFilterMenu(const Reference<XAccessible>& rxParent, ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos, ScDocument* pDoc) :
+ ScAccessibleContextBase(rxParent, AccessibleRole::MENU),
+ mnMenuPos(nMenuPos),
+ mpWindow(pWin),
+ mpDoc(pDoc),
+ mbEnabled(true)
+{
+ SetName(rName);
+}
+
+ScAccessibleFilterMenu::~ScAccessibleFilterMenu()
+{
+}
+
+// XAccessibleComponent
+
+Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleAtPoint( const ::com::sun::star::awt::Point& /*rPoint*/ )
+ throw (RuntimeException)
+{
+ return this;
+}
+
+sal_Bool ScAccessibleFilterMenu::isVisible() throw (RuntimeException)
+{
+ return mpWindow->IsVisible();
+}
+
+void ScAccessibleFilterMenu::grabFocus()
+ throw (RuntimeException)
+{
+}
+
+sal_Int32 ScAccessibleFilterMenu::getForeground()
+ throw (RuntimeException)
+{
+ return 0;
+}
+
+sal_Int32 ScAccessibleFilterMenu::getBackground()
+ throw (RuntimeException)
+{
+ return 0;
+}
+
+// XAccessibleContext
+
+OUString ScAccessibleFilterMenu::getAccessibleName() throw (RuntimeException)
+{
+ return ScAccessibleContextBase::getAccessibleName();
+}
+
+sal_Int32 ScAccessibleFilterMenu::getAccessibleChildCount()
+ throw (RuntimeException)
+{
+ return getMenuItemCount();
+}
+
+Reference<XAccessible> ScAccessibleFilterMenu::getAccessibleChild(sal_Int32 nIndex)
+ throw (RuntimeException, IndexOutOfBoundsException)
+{
+ if (maMenuItems.size() <= static_cast<size_t>(nIndex))
+ throw IndexOutOfBoundsException();
+
+ return maMenuItems[nIndex];
+}
+
+Reference<XAccessibleStateSet> ScAccessibleFilterMenu::getAccessibleStateSet()
+ throw (RuntimeException)
+{
+ updateStates();
+ return mxStateSet;
+}
+
+OUString ScAccessibleFilterMenu::getImplementationName()
+ throw (RuntimeException)
+{
+ return OUString::createFromAscii("ScAccessibleFilterMenu");
+}
+
+// XAccessibleEventBroadcaster
+
+void ScAccessibleFilterMenu::addEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener>& xListener)
+ throw (com::sun::star::uno::RuntimeException)
+{
+ ScAccessibleContextBase::addEventListener(xListener);
+ for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, true));
+}
+
+void ScAccessibleFilterMenu::removeEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener>& xListener)
+ throw (com::sun::star::uno::RuntimeException)
+{
+ ScAccessibleContextBase::removeEventListener(xListener);
+ for_each(maMenuItems.begin(), maMenuItems.end(), AddRemoveEventListener(xListener, false));
+}
+
+// XAccessibleSelection
+
+void ScAccessibleFilterMenu::selectAccessibleChild(sal_Int32 nChildIndex)
+ throw (IndexOutOfBoundsException, RuntimeException)
+{
+ if (static_cast<size_t>(nChildIndex) >= maMenuItems.size())
+ throw IndexOutOfBoundsException();
+
+ mpWindow->setSelectedMenuItem(nChildIndex, false, true);
+}
+
+sal_Bool ScAccessibleFilterMenu::isAccessibleChildSelected(sal_Int32 nChildIndex)
+ throw (IndexOutOfBoundsException, RuntimeException)
+{
+ if (static_cast<size_t>(nChildIndex) >= maMenuItems.size())
+ throw IndexOutOfBoundsException();
+
+ return mpWindow->isMenuItemSelected(static_cast<size_t>(nChildIndex));
+}
+
+void ScAccessibleFilterMenu::clearAccessibleSelection() throw (RuntimeException)
+{
+ mpWindow->clearSelectedMenuItem();
+}
+
+void ScAccessibleFilterMenu::selectAllAccessibleChildren() throw (RuntimeException)
+{
+ // not suported - this is a menu, you can't select all menu items.
+}
+
+sal_Int32 ScAccessibleFilterMenu::getSelectedAccessibleChildCount() throw (RuntimeException)
+{
+ // Since this is a menu, either one menu item is selected, or none at all.
+ return mpWindow->getSelectedMenuItem() == ScMenuFloatingWindow::MENU_NOT_SELECTED ? 0 : 1;
+}
+
+Reference<XAccessible> ScAccessibleFilterMenu::getSelectedAccessibleChild(sal_Int32 nChildIndex)
+ throw (IndexOutOfBoundsException, RuntimeException)
+{
+ if (static_cast<size_t>(nChildIndex) >= maMenuItems.size())
+ throw IndexOutOfBoundsException();
+
+ return maMenuItems[nChildIndex];
+}
+
+void ScAccessibleFilterMenu::deselectAccessibleChild(sal_Int32 nChildIndex) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ if (static_cast<size_t>(nChildIndex) >= maMenuItems.size())
+ throw IndexOutOfBoundsException();
+
+ mpWindow->selectMenuItem(nChildIndex, false, false);
+}
+
+// XInterface
+
+uno::Any SAL_CALL ScAccessibleFilterMenu::queryInterface( uno::Type const & rType )
+ throw (RuntimeException)
+{
+ Any any = ScAccessibleContextBase::queryInterface(rType);
+ if (any.hasValue())
+ return any;
+
+ return ScAccessibleFilterMenu_BASE::queryInterface(rType);
+}
+
+void SAL_CALL ScAccessibleFilterMenu::acquire() throw ()
+{
+ ScAccessibleContextBase::acquire();
+}
+
+void SAL_CALL ScAccessibleFilterMenu::release() throw ()
+{
+ ScAccessibleContextBase::release();
+}
+
+// XTypeProvider
+
+Sequence<sal_Int8> ScAccessibleFilterMenu::getImplementationId()
+ throw (RuntimeException)
+{
+ Sequence<sal_Int8> aId(16);
+ return aId;
+}
+
+Rectangle ScAccessibleFilterMenu::GetBoundingBoxOnScreen() const
+ throw (RuntimeException)
+{
+ if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED)
+ return Rectangle();
+
+ // Menu object's bounding box is the bounding box of the menu item that
+ // launches the menu, which belongs to the parent window.
+ ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow();
+ if (!pParentWin)
+ return Rectangle();
+
+ if (!pParentWin->IsVisible())
+ return Rectangle();
+
+ Point aPos = pParentWin->OutputToAbsoluteScreenPixel(Point(0,0));
+ Point aMenuPos;
+ Size aMenuSize;
+ pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize);
+ Rectangle aRect(aPos + aMenuPos, aMenuSize);
+ return aRect;
+}
+
+Rectangle ScAccessibleFilterMenu::GetBoundingBox() const
+ throw (RuntimeException)
+{
+ if (mnMenuPos == ScMenuFloatingWindow::MENU_NOT_SELECTED)
+ return Rectangle();
+
+ // Menu object's bounding box is the bounding box of the menu item that
+ // launches the menu, which belongs to the parent window.
+ ScMenuFloatingWindow* pParentWin = mpWindow->getParentMenuWindow();
+ if (!pParentWin)
+ return Rectangle();
+
+ if (!pParentWin->IsVisible())
+ return Rectangle();
+
+ Point aMenuPos;
+ Size aMenuSize;
+ pParentWin->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize);
+ Rectangle aRect(aMenuPos, aMenuSize);
+ return aRect;
+}
+
+void ScAccessibleFilterMenu::appendMenuItem(const OUString& rName, bool bEnabled, size_t nMenuPos)
+{
+ // Check weather this menu item is a sub menu or a regular menu item.
+ ScMenuFloatingWindow* pSubMenu = mpWindow->getSubMenuWindow(nMenuPos);
+ Reference<XAccessible> xAccessible;
+ if (pSubMenu)
+ {
+ xAccessible = pSubMenu->CreateAccessible();
+ ScAccessibleFilterMenu* p =
+ static_cast<ScAccessibleFilterMenu*>(xAccessible.get());
+ p->setEnabled(bEnabled);
+ p->setMenuPos(nMenuPos);
+ }
+ else
+ {
+ xAccessible.set(new ScAccessibleFilterMenuItem(this, mpWindow, rName, nMenuPos));
+ ScAccessibleFilterMenuItem* p =
+ static_cast<ScAccessibleFilterMenuItem*>(xAccessible.get());
+ p->setEnabled(bEnabled);
+ }
+ maMenuItems.push_back(xAccessible);
+}
+
+void ScAccessibleFilterMenu::setMenuPos(size_t nMenuPos)
+{
+ mnMenuPos = nMenuPos;
+}
+
+void ScAccessibleFilterMenu::setEnabled(bool bEnabled)
+{
+ mbEnabled = bEnabled;
+}
+
+sal_Int32 ScAccessibleFilterMenu::getMenuItemCount() const
+{
+ return maMenuItems.size();
+}
+
+bool ScAccessibleFilterMenu::isSelected() const
+{
+ // Check to see if any of the child menu items is selected.
+ return mpWindow->isMenuItemSelected(mnMenuPos);
+}
+
+bool ScAccessibleFilterMenu::isFocused() const
+{
+ return isSelected();
+}
+
+void ScAccessibleFilterMenu::updateStates()
+{
+ if (!mxStateSet.is())
+ mxStateSet.set(new ScAccessibleStateSet);
+
+ ScAccessibleStateSet* p = static_cast<ScAccessibleStateSet*>(
+ mxStateSet.get());
+
+ p->clear();
+
+ p->insert(ENABLED);
+ p->insert(FOCUSABLE);
+ p->insert(SELECTABLE);
+ p->insert(SENSITIVE);
+ p->insert(OPAQUE);
+
+ if (isFocused())
+ p->insert(FOCUSED);
+
+ if (isSelected())
+ p->insert(SELECTED);
+}
diff --git a/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx b/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx
new file mode 100644
index 000000000000..9f5524dcb8ce
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleFilterMenuItem.cxx
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * 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: AccessibleDataPilotControl.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 "AccessibleGlobal.hxx"
+#include "AccessibleFilterMenuItem.hxx"
+#include "dpcontrol.hxx"
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleEventObject.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::accessibility::AccessibleStateType;
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::uno::RuntimeException;
+using ::rtl::OUString;
+
+ScAccessibleFilterMenuItem::ScAccessibleFilterMenuItem(
+ const Reference<XAccessible>& rxParent, ScMenuFloatingWindow* pWin, const OUString& rName, size_t nMenuPos) :
+ ScAccessibleContextBase(rxParent, AccessibleRole::MENU_ITEM),
+ mpWindow(pWin),
+ maName(rName),
+ mnMenuPos(nMenuPos),
+ mbEnabled(true)
+{
+ SetName(rName);
+}
+
+ScAccessibleFilterMenuItem::~ScAccessibleFilterMenuItem()
+{
+}
+
+sal_Int32 ScAccessibleFilterMenuItem::getAccessibleChildCount()
+ throw (RuntimeException)
+{
+ return 0;
+}
+
+Reference<XAccessible> ScAccessibleFilterMenuItem::getAccessibleChild(sal_Int32 /*nIndex*/)
+ throw (RuntimeException, IndexOutOfBoundsException)
+{
+ throw IndexOutOfBoundsException();
+}
+
+Reference<XAccessibleStateSet> ScAccessibleFilterMenuItem::getAccessibleStateSet()
+ throw (RuntimeException)
+{
+ updateStateSet();
+ return mxStateSet;
+}
+
+OUString ScAccessibleFilterMenuItem::getImplementationName()
+ throw (RuntimeException)
+{
+ return OUString::createFromAscii("ScAccessibleFilterMenuItem");
+}
+
+// XAccessibleAction
+
+sal_Int32 ScAccessibleFilterMenuItem::getAccessibleActionCount() throw (RuntimeException)
+{
+ return 1;
+}
+
+sal_Bool ScAccessibleFilterMenuItem::doAccessibleAction(sal_Int32 /*nIndex*/)
+ throw (IndexOutOfBoundsException, RuntimeException)
+{
+ mpWindow->executeMenuItem(mnMenuPos);
+ return true;
+}
+
+OUString ScAccessibleFilterMenuItem::getAccessibleActionDescription(sal_Int32 /*nIndex*/)
+ throw (IndexOutOfBoundsException, RuntimeException)
+{
+ return OUString::createFromAscii("click");
+}
+
+Reference<XAccessibleKeyBinding> ScAccessibleFilterMenuItem::getAccessibleActionKeyBinding(
+ sal_Int32 /*nIndex*/) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ return Reference<XAccessibleKeyBinding>();
+}
+
+Any SAL_CALL ScAccessibleFilterMenuItem::queryInterface( uno::Type const & rType )
+ throw (RuntimeException)
+{
+ Any any = ScAccessibleContextBase::queryInterface(rType);
+ if (any.hasValue())
+ return any;
+
+ return ScAccessibleFilterMenuItem_BASE::queryInterface(rType);
+}
+
+void SAL_CALL ScAccessibleFilterMenuItem::acquire() throw ()
+{
+ ScAccessibleContextBase::acquire();
+}
+
+void SAL_CALL ScAccessibleFilterMenuItem::release() throw ()
+{
+ ScAccessibleContextBase::release();
+}
+
+bool ScAccessibleFilterMenuItem::isSelected() const
+{
+ return mpWindow->isMenuItemSelected(mnMenuPos);
+}
+
+bool ScAccessibleFilterMenuItem::isFocused() const
+{
+ return isSelected();
+}
+
+void ScAccessibleFilterMenuItem::setEnabled(bool bEnabled)
+{
+ mbEnabled = bEnabled;
+}
+
+Rectangle ScAccessibleFilterMenuItem::GetBoundingBoxOnScreen() const
+ throw (RuntimeException)
+{
+ if (!mpWindow->IsVisible())
+ return Rectangle();
+
+ Point aPos = mpWindow->OutputToAbsoluteScreenPixel(Point(0,0));
+ Point aMenuPos;
+ Size aMenuSize;
+ mpWindow->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize);
+ Rectangle aRect(aPos + aMenuPos, aMenuSize);
+ return aRect;
+}
+
+Rectangle ScAccessibleFilterMenuItem::GetBoundingBox() const
+ throw (RuntimeException)
+{
+ if (!mpWindow->IsVisible())
+ return Rectangle();
+
+ Point aMenuPos;
+ Size aMenuSize;
+ mpWindow->getMenuItemPosSize(mnMenuPos, aMenuPos, aMenuSize);
+ Rectangle aRect(aMenuPos, aMenuSize);
+ return aRect;
+}
+
+void ScAccessibleFilterMenuItem::updateStateSet()
+{
+ if (!mxStateSet.is())
+ mxStateSet.set(new ScAccessibleStateSet);
+
+ ScAccessibleStateSet* p = static_cast<ScAccessibleStateSet*>(
+ mxStateSet.get());
+
+ p->clear();
+
+ p->insert(ENABLED);
+ p->insert(FOCUSABLE);
+ p->insert(SELECTABLE);
+ p->insert(SENSITIVE);
+ p->insert(OPAQUE);
+
+ if (isFocused())
+ p->insert(FOCUSED);
+
+ if (isSelected())
+ p->insert(SELECTED);
+}
+
diff --git a/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx b/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx
new file mode 100644
index 000000000000..832cb37dd096
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleFilterTopWindow.cxx
@@ -0,0 +1,137 @@
+/*************************************************************************
+ *
+ * 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: AccessibleDataPilotControl.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 "AccessibleFilterTopWindow.hxx"
+#include "AccessibleFilterMenu.hxx"
+#include "dpcontrol.hxx"
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+using ::rtl::OUString;
+
+ScAccessibleFilterTopWindow::ScAccessibleFilterTopWindow(
+ const Reference<XAccessible>& rxParent, ScDPFieldPopupWindow* pWin, const OUString& rName, ScDocument* pDoc) :
+ ScAccessibleFilterMenu(rxParent, pWin, rName, ScMenuFloatingWindow::MENU_NOT_SELECTED, pDoc),
+ mpWindow(pWin),
+ mpDoc(pDoc)
+{
+ SetName(rName);
+}
+
+ScAccessibleFilterTopWindow::~ScAccessibleFilterTopWindow()
+{
+}
+
+// XAccessibleContext
+
+sal_Int32 ScAccessibleFilterTopWindow::getAccessibleChildCount() throw (RuntimeException)
+{
+ sal_Int32 nMenuCount = getMenuItemCount();
+ return nMenuCount + 6;
+}
+
+Reference<XAccessible> ScAccessibleFilterTopWindow::getAccessibleChild(
+ sal_Int32 nIndex) throw (RuntimeException, IndexOutOfBoundsException)
+{
+ if (nIndex >= getAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nMenuCount = getMenuItemCount();
+ if (nIndex < nMenuCount)
+ return ScAccessibleFilterMenu::getAccessibleChild(nIndex);
+
+ nIndex -= nMenuCount;
+ switch (nIndex)
+ {
+ case 0:
+ return mxAccListBox;
+ case 1:
+ return mxAccToggleAll;
+ case 2:
+ return mxAccSingleOnBtn;
+ case 3:
+ return mxAccSingleOffBtn;
+ case 4:
+ return mxAccOkBtn;
+ case 5:
+ return mxAccCancelBtn;
+ default:
+ ;
+ }
+
+ return Reference<XAccessible>();
+}
+
+OUString ScAccessibleFilterTopWindow::getImplementationName() throw (RuntimeException)
+{
+ return OUString::createFromAscii("ScAccessibleFilterTopWindow");
+}
+
+Reference<XAccessible> ScAccessibleFilterTopWindow::getAccessibleChildMenu()
+{
+ if (!mxAccMenu.is())
+ mxAccMenu.set(new ScAccessibleFilterMenu(this, mpWindow, getAccessibleName(), ScMenuFloatingWindow::MENU_NOT_SELECTED, mpDoc));
+ return mxAccMenu;
+}
+
+void ScAccessibleFilterTopWindow::setAccessibleChild(
+ const Reference<XAccessible>& rAccessible, ChildControlType eType)
+{
+ switch (eType)
+ {
+ case LISTBOX:
+ mxAccListBox = rAccessible;
+ break;
+ case TOGGLE_ALL:
+ mxAccToggleAll = rAccessible;
+ break;
+ case SINGLE_ON_BTN:
+ mxAccSingleOnBtn = rAccessible;
+ break;
+ case SINGLE_OFF_BTN:
+ mxAccSingleOffBtn = rAccessible;
+ break;
+ case OK_BTN:
+ mxAccOkBtn = rAccessible;
+ break;
+ case CANCEL_BTN:
+ mxAccCancelBtn = rAccessible;
+ break;
+ }
+}
+
diff --git a/sc/source/ui/Accessibility/AccessibleGlobal.cxx b/sc/source/ui/Accessibility/AccessibleGlobal.cxx
new file mode 100644
index 000000000000..6ac7190a132b
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleGlobal.cxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * 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: AccessibleDataPilotControl.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 "AccessibleGlobal.hxx"
+
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::std::set;
+
+ScAccessibleStateSet::ScAccessibleStateSet()
+{
+}
+
+ScAccessibleStateSet::~ScAccessibleStateSet()
+{
+}
+
+// XAccessibleStateSet
+
+sal_Bool SAL_CALL ScAccessibleStateSet::isEmpty() throw (RuntimeException)
+{
+ return maStates.empty();
+}
+
+sal_Bool SAL_CALL ScAccessibleStateSet::contains(sal_Int16 nState)
+ throw (RuntimeException)
+{
+ return maStates.count(nState) != 0;
+}
+
+sal_Bool SAL_CALL ScAccessibleStateSet::containsAll(
+ const Sequence<sal_Int16>& aStateSet) throw (RuntimeException)
+{
+ sal_Int32 n = aStateSet.getLength();
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ if (!maStates.count(aStateSet[i]))
+ // This state is not set.
+ return false;
+ }
+ // All specified states are set.
+ return true;
+}
+
+Sequence<sal_Int16> SAL_CALL ScAccessibleStateSet::getStates()
+ throw (RuntimeException)
+{
+ Sequence<sal_Int16> aSeq(0);
+ set<sal_Int16>::const_iterator itr = maStates.begin(), itrEnd = maStates.end();
+ for (size_t i = 0; itr != itrEnd; ++itr, ++i)
+ {
+ aSeq.realloc(i+1);
+ aSeq[i] = *itr;
+ }
+ return aSeq;
+}
+
+void ScAccessibleStateSet::insert(sal_Int16 nState)
+{
+ maStates.insert(nState);
+}
+
+void ScAccessibleStateSet::clear()
+{
+ maStates.clear();
+}
+
diff --git a/sc/source/ui/Accessibility/makefile.mk b/sc/source/ui/Accessibility/makefile.mk
index dfa5ac94b63f..1ef6db37e0c1 100644
--- a/sc/source/ui/Accessibility/makefile.mk
+++ b/sc/source/ui/Accessibility/makefile.mk
@@ -47,12 +47,16 @@ SLOFILES = \
$(SLO)$/AccessibleContextBase.obj \
$(SLO)$/AccessibleTableBase.obj \
$(SLO)$/AccessibleDocument.obj \
+ $(SLO)$/AccessibleGlobal.obj \
$(SLO)$/AccessibleSpreadsheet.obj \
$(SLO)$/AccessibleCell.obj \
$(SLO)$/AccessibilityHints.obj \
$(SLO)$/AccessibleDocumentBase.obj \
$(SLO)$/AccessibleCellBase.obj \
$(SLO)$/AccessibleDocumentPagePreview.obj \
+ $(SLO)$/AccessibleFilterMenu.obj \
+ $(SLO)$/AccessibleFilterMenuItem.obj \
+ $(SLO)$/AccessibleFilterTopWindow.obj \
$(SLO)$/AccessiblePreviewTable.obj \
$(SLO)$/AccessiblePreviewCell.obj \
$(SLO)$/AccessiblePreviewHeaderCell.obj \
@@ -68,11 +72,15 @@ EXCEPTIONSFILES= \
$(SLO)$/AccessibleContextBase.obj \
$(SLO)$/AccessibleTableBase.obj \
$(SLO)$/AccessibleDocument.obj \
+ $(SLO)$/AccessibleGlobal.obj \
$(SLO)$/AccessibleSpreadsheet.obj \
$(SLO)$/AccessibleCell.obj \
$(SLO)$/AccessibleDocumentBase.obj \
$(SLO)$/AccessibleCellBase.obj \
$(SLO)$/AccessibleDocumentPagePreview.obj \
+ $(SLO)$/AccessibleFilterMenu.obj \
+ $(SLO)$/AccessibleFilterMenuItem.obj \
+ $(SLO)$/AccessibleFilterTopWindow.obj \
$(SLO)$/AccessiblePreviewTable.obj \
$(SLO)$/AccessiblePreviewCell.obj \
$(SLO)$/AccessiblePreviewHeaderCell.obj \
diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx
new file mode 100644
index 000000000000..a938948e1b26
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.cxx
@@ -0,0 +1,1419 @@
+/*************************************************************************
+ *
+ * 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 "dpcontrol.hrc"
+
+#include "vcl/outdev.hxx"
+#include "vcl/settings.hxx"
+#include "vcl/wintypes.hxx"
+#include "vcl/decoview.hxx"
+#include "strload.hxx"
+#include "global.hxx"
+
+#include "AccessibleFilterMenu.hxx"
+#include "AccessibleFilterTopWindow.hxx"
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::accessibility::XAccessible;
+using ::com::sun::star::accessibility::XAccessibleContext;
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
+using ::std::vector;
+using ::std::hash_map;
+using ::std::auto_ptr;
+
+ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomX, const Fraction* pZoomY) :
+ mpOutDev(pOutDev),
+ mpStyle(pStyle),
+ mbBaseButton(true),
+ mbPopupButton(false),
+ mbHasHiddenMember(false),
+ mbPopupPressed(false)
+{
+ if (pZoomX)
+ maZoomX = *pZoomX;
+ else
+ maZoomX = Fraction(1, 1);
+
+ if (pZoomY)
+ maZoomY = *pZoomY;
+ else
+ maZoomY = Fraction(1, 1);
+}
+
+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::setDrawBaseButton(bool b)
+{
+ mbBaseButton = b;
+}
+
+void ScDPFieldButton::setDrawPopupButton(bool b)
+{
+ mbPopupButton = b;
+}
+
+void ScDPFieldButton::setHasHiddenMember(bool b)
+{
+ mbHasHiddenMember = b;
+}
+
+void ScDPFieldButton::setPopupPressed(bool b)
+{
+ mbPopupPressed = b;
+}
+
+void ScDPFieldButton::draw()
+{
+ const long nMargin = 2;
+ bool bOldMapEnablaed = mpOutDev->IsMapModeEnabled();
+ mpOutDev->EnableMapMode(false);
+
+ if (mbBaseButton)
+ {
+ // 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() );
+ double fFontHeight = 12.0;
+ fFontHeight *= static_cast<double>(maZoomY.GetNumerator()) / static_cast<double>(maZoomY.GetDenominator());
+ aTextFont.SetHeight(static_cast<long>(fFontHeight));
+ mpOutDev->SetFont(aTextFont);
+
+ Point aTextPos = maPos;
+ long nTHeight = static_cast<long>(fFontHeight);
+ aTextPos.setX(maPos.getX() + nMargin);
+ aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
+ mpOutDev->DrawText(aTextPos, maText);
+ }
+
+ if (mbPopupButton)
+ drawPopupButton();
+
+ mpOutDev->EnableMapMode(bOldMapEnablaed);
+}
+
+void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
+{
+ long nW = maSize.getWidth() / 2;
+ long nH = maSize.getHeight();
+ if (nW > 18)
+ nW = 18;
+ 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);
+
+ // Background & outer black border
+ mpOutDev->SetLineColor(COL_BLACK);
+ mpOutDev->SetFillColor(mpStyle->GetFaceColor());
+ mpOutDev->DrawRect(Rectangle(aPos, aSize));
+
+ if (!mbPopupPressed)
+ {
+ // border lines
+ mpOutDev->SetLineColor(mpStyle->GetLightColor());
+ mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+1), Point(aPos.X()+1, aPos.Y()+aSize.Height()-2));
+ mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+1), Point(aPos.X()+aSize.Width()-2, aPos.Y()+1));
+
+ mpOutDev->SetLineColor(mpStyle->GetShadowColor());
+ mpOutDev->DrawLine(Point(aPos.X()+1, aPos.Y()+aSize.Height()-2),
+ Point(aPos.X()+aSize.Width()-2, aPos.Y()+aSize.Height()-2));
+ mpOutDev->DrawLine(Point(aPos.X()+aSize.Width()-2, aPos.Y()+1),
+ Point(aPos.X()+aSize.Width()-2, aPos.Y()+aSize.Height()-2));
+ }
+
+ // 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;
+
+ if (mbPopupPressed)
+ {
+ aPos1.X() += 1;
+ aPos2.X() += 1;
+ aPos1.Y() += 1;
+ aPos2.Y() += 1;
+ }
+
+ 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);
+ if (mbPopupPressed)
+ {
+ aBoxPos.X() += 1;
+ aBoxPos.Y() += 1;
+ }
+ Size aBoxSize(3, 3);
+ mpOutDev->DrawRect(Rectangle(aBoxPos, aBoxSize));
+ }
+}
+
+// ============================================================================
+
+ScMenuFloatingWindow::MenuItemData::MenuItemData() :
+ mbEnabled(true),
+ mpAction(static_cast<ScDPFieldPopupWindow::Action*>(NULL)),
+ mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::SubMenuItemData::SubMenuItemData(ScMenuFloatingWindow* pParent) :
+ mpSubMenu(NULL),
+ mnMenuPos(MENU_NOT_SELECTED),
+ mpParent(pParent)
+{
+ maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl) );
+ maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
+}
+
+void ScMenuFloatingWindow::SubMenuItemData::reset()
+{
+ mpSubMenu = NULL;
+ mnMenuPos = MENU_NOT_SELECTED;
+ maTimer.Stop();
+}
+
+IMPL_LINK( ScMenuFloatingWindow::SubMenuItemData, TimeoutHdl, void*, EMPTYARG )
+{
+ mpParent->handleMenuTimeout(this);
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+size_t ScMenuFloatingWindow::MENU_NOT_SELECTED = 999;
+
+ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent, ScDocument* pDoc, USHORT nMenuStackLevel) :
+ PopupMenuFloatingWindow(pParent),
+ maOpenTimer(this),
+ maCloseTimer(this),
+ maName(OUString::createFromAscii("ScMenuFloatingWindow")),
+ mnSelectedMenu(MENU_NOT_SELECTED),
+ mnClickedMenu(MENU_NOT_SELECTED),
+ mpDoc(pDoc),
+ mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
+ mpActiveSubMenu(NULL)
+{
+ SetMenuStackLevel(nMenuStackLevel);
+
+ // 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);
+
+ SetText(OUString::createFromAscii("ScMenuFloatingWindow"));
+ SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, PopupEndHdl) );
+}
+
+ScMenuFloatingWindow::~ScMenuFloatingWindow()
+{
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ size_t nSelectedMenu = getEnclosingMenuItem(rPos);
+ setSelectedMenuItem(nSelectedMenu, true, false);
+
+ 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)
+{
+ executeMenuItem(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, false);
+ break;
+ case KEY_DOWN:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
+ nSelectedMenu = 0;
+ else
+ ++nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false, false);
+ break;
+ case KEY_LEFT:
+ if (mpParentMenu)
+ mpParentMenu->endSubMenu(this);
+ break;
+ case KEY_RIGHT:
+ {
+ if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
+ break;
+
+ const MenuItemData& 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)
+ executeMenuItem(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();
+}
+
+Reference<XAccessible> ScMenuFloatingWindow::CreateAccessible()
+{
+ if (!mxAccessible.is())
+ {
+ Reference<XAccessible> xAccParent = mpParentMenu ?
+ mpParentMenu->GetAccessible() : GetAccessibleParentWindow()->GetAccessible();
+
+ mxAccessible.set(new ScAccessibleFilterMenu(xAccParent, this, maName, 999, getDoc()));
+ ScAccessibleFilterMenu* p = static_cast<ScAccessibleFilterMenu*>(
+ mxAccessible.get());
+
+ vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ size_t nPos = ::std::distance(itrBeg, itr);
+ p->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
+ }
+ }
+
+ return mxAccessible;
+}
+
+void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
+{
+ MenuItemData aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpAction.reset(pAction);
+ maMenuItems.push_back(aItem);
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
+{
+ MenuItemData aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this, mpDoc, GetMenuStackLevel()+1));
+ aItem.mpSubMenuWin->setName(rText);
+ maMenuItems.push_back(aItem);
+ return aItem.mpSubMenuWin.get();
+}
+
+void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nPos, aPos, aSize);
+
+ 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::executeMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ if (!maMenuItems[nPos].mpAction)
+ // no action is defined.
+ return;
+
+ maMenuItems[nPos].mpAction->execute();
+ terminateAllPopupMenus();
+}
+
+void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
+{
+ if (mnSelectedMenu == nPos)
+ // nothing to do.
+ return;
+
+ if (bEnsureSubMenu)
+ {
+ // Dismiss any child popup menu windows.
+ if (mnSelectedMenu < maMenuItems.size() &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
+ {
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
+ }
+
+ // The popup is not visible, yet a menu item is selected. The request
+ // most likely comes from the accessible object. Make sure this
+ // window, as well as all its parent windows are visible.
+ if (!IsVisible() && mpParentMenu)
+ mpParentMenu->ensureSubMenuVisible(this);
+ }
+
+ selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
+ selectMenuItem(nPos, true, bSubMenuTimer);
+ mnSelectedMenu = nPos;
+
+ fireMenuHighlightedEvent();
+}
+
+size_t ScMenuFloatingWindow::getSelectedMenuItem() const
+{
+ return mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItemData* 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(maOpenTimer.mnMenuPos, aPos, aSize);
+ ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
+
+ if (!pSubMenu)
+ return;
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ if (bSetMenuPos)
+ pSubMenu->setSelectedMenuItem(0, false, false); // select menu item after the popup becomes fully visible.
+ SetPopupModeFlags(nOldFlags);
+}
+
+void ScMenuFloatingWindow::endSubMenu(ScMenuFloatingWindow* pSubMenu)
+{
+ if (!pSubMenu)
+ return;
+
+ pSubMenu->EndPopupMode();
+ maOpenTimer.reset();
+
+ size_t nMenuPos = getSubMenuPos(pSubMenu);
+ if (nMenuPos != MENU_NOT_SELECTED)
+ {
+ highlightMenuItem(nMenuPos, true);
+ mnSelectedMenu = nMenuPos;
+ fireMenuHighlightedEvent();
+ }
+}
+
+void ScMenuFloatingWindow::fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const
+{
+ vector<MenuItemData>::const_iterator itr, itrBeg = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ size_t nPos = ::std::distance(itrBeg, itr);
+ pAccMenu->appendMenuItem(itr->maText, itr->mbEnabled, nPos);
+ }
+}
+
+ScDocument* ScMenuFloatingWindow::getDoc()
+{
+ return mpDoc;
+}
+
+void ScMenuFloatingWindow::resizeToFitMenuItems()
+{
+ if (maMenuItems.empty())
+ return;
+
+ vector<MenuItemData>::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(nLastPos, aPos, aSize);
+ 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->setSubMenuFocused(this);
+
+ if (bSubMenuTimer)
+ {
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
+ queueLaunchSubMenu(nPos, pSubMenu);
+ }
+ else
+ queueCloseSubMenu();
+ }
+ }
+}
+
+void ScMenuFloatingWindow::clearSelectedMenuItem()
+{
+ selectMenuItem(mnSelectedMenu, false, false);
+ mnSelectedMenu = MENU_NOT_SELECTED;
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::getSubMenuWindow(size_t nPos) const
+{
+ if (maMenuItems.size() <= nPos)
+ return NULL;
+
+ return maMenuItems[nPos].mpSubMenuWin.get();
+}
+
+size_t ScMenuFloatingWindow::getMenuItemCount() const
+{
+ return maMenuItems.size();
+}
+
+OUString ScMenuFloatingWindow::getMenuItemName(size_t nPos) const
+{
+ if (maMenuItems.size() <= nPos)
+ return ScGlobal::GetEmptyString();
+
+ return maMenuItems[nPos].maText;
+}
+
+bool ScMenuFloatingWindow::isMenuItemEnabled(size_t nPos) const
+{
+ if (maMenuItems.size() <= nPos)
+ return false;
+
+ return maMenuItems[nPos].mbEnabled;
+}
+
+bool ScMenuFloatingWindow::isMenuItemSelected(size_t nPos) const
+{
+ return nPos == mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::setName(const OUString& rName)
+{
+ maName = rName;
+}
+
+const OUString& ScMenuFloatingWindow::getName() const
+{
+ return maName;
+}
+
+void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
+{
+ if (nPos == MENU_NOT_SELECTED)
+ return;
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nPos, aPos, aSize);
+ 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(size_t nPos, Point& rPos, Size& rSize) const
+{
+ const sal_uInt16 nLeftMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuItemHeight = static_cast< sal_uInt16 >( 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;
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::getParentMenuWindow() const
+{
+ return mpParentMenu;
+}
+
+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(i, aPos, aSize);
+ Rectangle aRect(aPos, aSize);
+ if (aRect.IsInside(rPos))
+ return i;
+ }
+ return MENU_NOT_SELECTED;
+}
+
+size_t ScMenuFloatingWindow::getSubMenuPos(ScMenuFloatingWindow* pSubMenu)
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (maMenuItems[i].mpSubMenuWin.get() == pSubMenu)
+ return i;
+ }
+ return MENU_NOT_SELECTED;
+}
+
+void ScMenuFloatingWindow::fireMenuHighlightedEvent()
+{
+ if (mnSelectedMenu == MENU_NOT_SELECTED)
+ return;
+
+ if (!mxAccessible.is())
+ return;
+
+ Reference<XAccessibleContext> xAccCxt = mxAccessible->getAccessibleContext();
+ if (!xAccCxt.is())
+ return;
+
+ Reference<XAccessible> xAccMenu = xAccCxt->getAccessibleChild(mnSelectedMenu);
+ if (!xAccMenu.is())
+ return;
+
+ VclAccessibleEvent aEvent(VCLEVENT_MENU_HIGHLIGHT, xAccMenu);
+ FireVclEvent(&aEvent);
+}
+
+void ScMenuFloatingWindow::setSubMenuFocused(ScMenuFloatingWindow* pSubMenu)
+{
+ maCloseTimer.reset();
+ size_t nMenuPos = getSubMenuPos(pSubMenu);
+ if (mnSelectedMenu != nMenuPos)
+ {
+ highlightMenuItem(nMenuPos, true);
+ mnSelectedMenu = nMenuPos;
+ }
+}
+
+void ScMenuFloatingWindow::ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu)
+{
+ if (mpParentMenu)
+ mpParentMenu->ensureSubMenuVisible(this);
+
+ if (pSubMenu->IsVisible())
+ return;
+
+ // Find the menu position of the submenu.
+ size_t nMenuPos = getSubMenuPos(pSubMenu);
+ if (nMenuPos != MENU_NOT_SELECTED)
+ {
+ setSelectedMenuItem(nMenuPos, false, false);
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(nMenuPos, aPos, aSize);
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resizeToFitMenuItems(); // set the size before launching the popup to get it positioned correctly.
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ SetPopupModeFlags(nOldFlags);
+ }
+}
+
+void ScMenuFloatingWindow::ensureSubMenuNotVisible()
+{
+ if (mnSelectedMenu <= maMenuItems.size() &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin &&
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->IsVisible())
+ {
+ maMenuItems[mnSelectedMenu].mpSubMenuWin->ensureSubMenuNotVisible();
+ }
+
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::terminateAllPopupMenus()
+{
+ EndPopupMode();
+ if (mpParentMenu)
+ mpParentMenu->terminateAllPopupMenus();
+}
+
+IMPL_LINK( ScMenuFloatingWindow, PopupEndHdl, void*, EMPTYARG )
+{
+ clearSelectedMenuItem();
+ 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, ScDocument* pDoc) :
+ ScMenuFloatingWindow(pParent, pDoc),
+ maChecks(this, 0),
+ maChkToggleAll(this, 0),
+ maBtnSelectSingle (this, 0),
+ maBtnUnselectSingle(this, 0),
+ maBtnOk(this),
+ maBtnCancel(this),
+ mnCurTabStop(0),
+ mpExtendedData(NULL),
+ mpOKAction(NULL),
+ maWndSize(160, 330),
+ mePrevToggleAllState(STATE_DONTKNOW)
+{
+ maTabStopCtrls.reserve(7);
+ maTabStopCtrls.push_back(this);
+ maTabStopCtrls.push_back(&maChecks);
+ maTabStopCtrls.push_back(&maChkToggleAll);
+ maTabStopCtrls.push_back(&maBtnSelectSingle);
+ maTabStopCtrls.push_back(&maBtnUnselectSingle);
+ maTabStopCtrls.push_back(&maBtnOk);
+ maTabStopCtrls.push_back(&maBtnCancel);
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, WHOLE);
+ SetOutputSizePixel(aSize);
+ Size aOutSize = GetOutputSizePixel();
+
+ getSectionPosSize(aPos, aSize, BTN_OK);
+ maBtnOk.SetPosSizePixel(aPos, aSize);
+ maBtnOk.SetFont(getLabelFont());
+ maBtnOk.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
+ maBtnOk.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_CANCEL);
+ maBtnCancel.SetPosSizePixel(aPos, aSize);
+ maBtnCancel.SetFont(getLabelFont());
+ maBtnCancel.Show();
+
+ getSectionPosSize(aPos, aSize, LISTBOX_AREA_INNER);
+ maChecks.SetPosSizePixel(aPos, aSize);
+ maChecks.SetFont(getLabelFont());
+ maChecks.SetCheckButtonHdl( LINK(this, ScDPFieldPopupWindow, CheckHdl) );
+ maChecks.Show();
+
+ getSectionPosSize(aPos, aSize, CHECK_TOGGLE_ALL);
+ maChkToggleAll.SetPosSizePixel(aPos, aSize);
+ maChkToggleAll.SetFont(getLabelFont());
+ maChkToggleAll.SetText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString());
+ maChkToggleAll.SetControlBackground(rStyle.GetMenuColor());
+ maChkToggleAll.SetClickHdl( LINK(this, ScDPFieldPopupWindow, TriStateHdl) );
+ maChkToggleAll.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_SINGLE_SELECT);
+ maBtnSelectSingle.SetPosSizePixel(aPos, aSize);
+ maBtnSelectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_SELECT_CURRENT).GetString());
+ maBtnSelectSingle.SetModeImage(Image(ScResId(RID_IMG_SELECT_CURRENT)), BMP_COLOR_NORMAL);
+ maBtnSelectSingle.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
+ maBtnSelectSingle.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_SINGLE_UNSELECT);
+ maBtnUnselectSingle.SetPosSizePixel(aPos, aSize);
+ maBtnUnselectSingle.SetQuickHelpText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_UNSELECT_CURRENT).GetString());
+ maBtnUnselectSingle.SetModeImage(Image(ScResId(RID_IMG_UNSELECT_CURRENT)), BMP_COLOR_NORMAL);
+ maBtnUnselectSingle.SetClickHdl( LINK(this, ScDPFieldPopupWindow, ButtonHdl) );
+ maBtnUnselectSingle.Show();
+}
+
+ScDPFieldPopupWindow::~ScDPFieldPopupWindow()
+{
+}
+
+void ScDPFieldPopupWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
+{
+ // constant parameters.
+ const sal_uInt16 nListBoxMargin = 5; // horizontal distance from the side of the dialog to the listbox border.
+ const sal_uInt16 nListBoxInnerPadding = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuHeight = 60;
+ const sal_uInt16 nSingleItemBtnAreaHeight = 32; // height of the middle area below the list box where the single-action buttons are.
+ const sal_uInt16 nBottomBtnAreaHeight = 50; // height of the bottom area where the OK and Cancel buttons are.
+ const sal_uInt16 nBtnWidth = 60;
+ const sal_uInt16 nLabelHeight = static_cast< sal_uInt16 >( getLabelFont().GetHeight() );
+ const sal_uInt16 nBtnHeight = nLabelHeight*2;
+ const sal_uInt16 nBottomMargin = 10;
+ const sal_uInt16 nMenuListMargin = 20;
+
+ // parameters calculated from constants.
+ const sal_uInt16 nListBoxWidth = static_cast< sal_uInt16 >( maWndSize.Width() - nListBoxMargin*2 );
+ const sal_uInt16 nListBoxHeight = static_cast< sal_uInt16 >( maWndSize.Height() - nTopMargin - nMenuHeight -
+ nMenuListMargin - nSingleItemBtnAreaHeight - nBottomBtnAreaHeight );
+
+ const sal_uInt16 nSingleBtnAreaY = nTopMargin + nMenuHeight + nListBoxHeight + nMenuListMargin - 1;
+
+ switch (eType)
+ {
+ case WHOLE:
+ {
+ rPos = Point(0, 0);
+ rSize = maWndSize;
+ }
+ break;
+ case LISTBOX_AREA_OUTER:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rSize = Size(nListBoxWidth, nListBoxHeight);
+ }
+ break;
+ case LISTBOX_AREA_INNER:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rPos.X() += nListBoxInnerPadding;
+ rPos.Y() += nListBoxInnerPadding;
+
+ rSize = Size(nListBoxWidth, nListBoxHeight);
+ rSize.Width() -= nListBoxInnerPadding*2;
+ rSize.Height() -= nListBoxInnerPadding*2;
+ }
+ break;
+ case SINGLE_BTN_AREA:
+ {
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rSize = Size(nListBoxWidth, nSingleItemBtnAreaHeight);
+ }
+ break;
+ case CHECK_TOGGLE_ALL:
+ {
+ long h = nLabelHeight*3/2; // check box height is heuristically 150% of the text height.
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 5;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(70, h);
+ }
+ break;
+ case BTN_SINGLE_SELECT:
+ {
+ long h = 26;
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 75;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(h, h);
+ }
+ break;
+ case BTN_SINGLE_UNSELECT:
+ {
+ long h = 26;
+ rPos = Point(nListBoxMargin, nSingleBtnAreaY);
+ rPos.X() += 75 + h + 10;
+ rPos.Y() += (nSingleItemBtnAreaHeight - h)/2;
+ rSize = Size(h, h);
+ }
+ break;
+ case BTN_OK:
+ {
+ long x = (maWndSize.Width() - nBtnWidth*2)/3;
+ long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ case BTN_CANCEL:
+ {
+ long x = (maWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
+ long y = maWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void ScDPFieldPopupWindow::setAllMemberState(bool bSet)
+{
+ size_t n = maMembers.size();
+ for (size_t i = 0; i < n; ++i)
+ maChecks.CheckEntryPos(static_cast< USHORT >( i ), bSet);
+}
+
+void ScDPFieldPopupWindow::selectCurrentMemberOnly(bool bSet)
+{
+ setAllMemberState(!bSet);
+ sal_uInt16 nSelected = maChecks.GetSelectEntryPos();
+ maChecks.CheckEntryPos(nSelected, bSet);
+}
+
+void ScDPFieldPopupWindow::cycleFocus(bool bReverse)
+{
+ maTabStopCtrls[mnCurTabStop]->SetFakeFocus(false);
+ maTabStopCtrls[mnCurTabStop]->LoseFocus();
+ if (mnCurTabStop == 0)
+ clearSelectedMenuItem();
+
+ if (bReverse)
+ {
+ if (mnCurTabStop > 0)
+ --mnCurTabStop;
+ else
+ mnCurTabStop = maTabStopCtrls.size() - 1;
+ }
+ else
+ {
+ ++mnCurTabStop;
+ if (mnCurTabStop >= maTabStopCtrls.size())
+ mnCurTabStop = 0;
+ }
+ maTabStopCtrls[mnCurTabStop]->SetFakeFocus(true);
+ maTabStopCtrls[mnCurTabStop]->GrabFocus();
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, ButtonHdl, Button*, pBtn )
+{
+ if (pBtn == &maBtnOk)
+ close(true);
+ else if (pBtn == &maBtnSelectSingle)
+ {
+ selectCurrentMemberOnly(true);
+ CheckHdl(&maChecks);
+ }
+ else if (pBtn == &maBtnUnselectSingle)
+ {
+ selectCurrentMemberOnly(false);
+ CheckHdl(&maChecks);
+ }
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, TriStateHdl, TriStateBox*, EMPTYARG )
+{
+ switch (mePrevToggleAllState)
+ {
+ case STATE_NOCHECK:
+ maChkToggleAll.SetState(STATE_CHECK);
+ setAllMemberState(true);
+ break;
+ case STATE_CHECK:
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ setAllMemberState(false);
+ break;
+ case STATE_DONTKNOW:
+ default:
+ maChkToggleAll.SetState(STATE_CHECK);
+ setAllMemberState(true);
+ break;
+ }
+
+ mePrevToggleAllState = maChkToggleAll.GetState();
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, CheckHdl, SvTreeListBox*, pChecks )
+{
+ if (pChecks != &maChecks)
+ return 0;
+
+ size_t nNumChecked = maChecks.GetCheckedEntryCount();
+ if (nNumChecked == maMembers.size())
+ // all members visible
+ maChkToggleAll.SetState(STATE_CHECK);
+ else if (nNumChecked == 0)
+ // no members visible
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ else
+ maChkToggleAll.SetState(STATE_DONTKNOW);
+
+ mePrevToggleAllState = maChkToggleAll.GetState();
+ return 0;
+}
+
+void ScDPFieldPopupWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ ScMenuFloatingWindow::MouseMove(rMEvt);
+
+ size_t nSelectedMenu = getSelectedMenuItem();
+ if (nSelectedMenu == MENU_NOT_SELECTED)
+ queueCloseSubMenu();
+}
+
+long ScDPFieldPopupWindow::Notify(NotifyEvent& rNEvt)
+{
+ switch (rNEvt.GetType())
+ {
+ case EVENT_KEYUP:
+ {
+ const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
+ const KeyCode& rCode = pKeyEvent->GetKeyCode();
+ bool bShift = rCode.IsShift();
+ if (rCode.GetCode() == KEY_TAB)
+ {
+ cycleFocus(bShift);
+ return true;
+ }
+ }
+ break;
+ }
+ return ScMenuFloatingWindow::Notify(rNEvt);
+}
+
+void ScDPFieldPopupWindow::Paint(const Rectangle& rRect)
+{
+ ScMenuFloatingWindow::Paint(rRect);
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aMemberBackColor = rStyle.GetFieldColor();
+ Color aBorderColor = rStyle.GetShadowColor();
+
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, LISTBOX_AREA_OUTER);
+
+ // Member list box background
+ SetFillColor(aMemberBackColor);
+ SetLineColor(aBorderColor);
+ DrawRect(Rectangle(aPos,aSize));
+
+ // Single-action button box
+ getSectionPosSize(aPos, aSize, SINGLE_BTN_AREA);
+ SetFillColor(rStyle.GetMenuColor());
+ DrawRect(Rectangle(aPos,aSize));
+}
+
+Window* ScDPFieldPopupWindow::GetPreferredKeyInputWindow()
+{
+ return maTabStopCtrls[mnCurTabStop];
+}
+
+Reference<XAccessible> ScDPFieldPopupWindow::CreateAccessible()
+{
+ if (!mxAccessible.is())
+ {
+ mxAccessible.set(new ScAccessibleFilterTopWindow(
+ GetAccessibleParentWindow()->GetAccessible(), this, getName(), getDoc()));
+ ScAccessibleFilterTopWindow* pAccTop = static_cast<ScAccessibleFilterTopWindow*>(mxAccessible.get());
+ fillMenuItemsToAccessible(pAccTop);
+
+ pAccTop->setAccessibleChild(
+ maChecks.CreateAccessible(), ScAccessibleFilterTopWindow::LISTBOX);
+ pAccTop->setAccessibleChild(
+ maChkToggleAll.CreateAccessible(), ScAccessibleFilterTopWindow::TOGGLE_ALL);
+ pAccTop->setAccessibleChild(
+ maBtnSelectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_ON_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnUnselectSingle.CreateAccessible(), ScAccessibleFilterTopWindow::SINGLE_OFF_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnOk.CreateAccessible(), ScAccessibleFilterTopWindow::OK_BTN);
+ pAccTop->setAccessibleChild(
+ maBtnCancel.CreateAccessible(), ScAccessibleFilterTopWindow::CANCEL_BTN);
+ }
+
+ return mxAccessible;
+}
+
+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 n = maMembers.size();
+ size_t nVisMemCount = 0;
+ for (size_t i = 0; i < n; ++i)
+ {
+ maChecks.InsertEntry(maMembers[i].maName);
+ maChecks.CheckEntryPos(static_cast< USHORT >( i ), maMembers[i].mbVisible);
+ if (maMembers[i].mbVisible)
+ ++nVisMemCount;
+ }
+ if (nVisMemCount == n)
+ {
+ // all members visible
+ maChkToggleAll.SetState(STATE_CHECK);
+ mePrevToggleAllState = STATE_CHECK;
+ }
+ else if (nVisMemCount == 0)
+ {
+ // no members visible
+ maChkToggleAll.SetState(STATE_NOCHECK);
+ mePrevToggleAllState = STATE_NOCHECK;
+ }
+ else
+ {
+ maChkToggleAll.SetState(STATE_DONTKNOW);
+ mePrevToggleAllState = STATE_DONTKNOW;
+ }
+}
+
+const Size& ScDPFieldPopupWindow::getWindowSize() const
+{
+ return maWndSize;
+}
+
+void ScDPFieldPopupWindow::getResult(hash_map<OUString, bool, OUStringHash>& rResult)
+{
+ typedef hash_map<OUString, bool, OUStringHash> ResultMap;
+ ResultMap aResult;
+ size_t n = maMembers.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ bool bState = maChecks.IsChecked(static_cast< USHORT >( i ));
+ aResult.insert(ResultMap::value_type(maMembers[i].maName, bState));
+ }
+ 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..31cbb62085e5
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.src
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * 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" ;
+ };
+
+ String STR_BTN_TOGGLE_ALL
+ {
+ Text [ en-US ] = "All" ;
+ };
+
+ String STR_BTN_SELECT_CURRENT
+ {
+ Text [ en-US ] = "Show only the current item." ;
+ };
+
+ String STR_BTN_UNSELECT_CURRENT
+ {
+ Text [ en-US ] = "Hide only the current item." ;
+ };
+};
+
+Image RID_IMG_SELECT_CURRENT
+{
+ ImageBitmap = Bitmap
+ {
+ File = "popup_select_current.png";
+ };
+ MaskColor = STD_MASKCOLOR;
+};
+
+Image RID_IMG_UNSELECT_CURRENT
+{
+ ImageBitmap = Bitmap
+ {
+ File = "popup_unselect_current.png";
+ };
+ MaskColor = STD_MASKCOLOR;
+};
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/makefile.mk b/sc/source/ui/dbgui/makefile.mk
index b495b5eabcc9..9ff21b6c4d08 100644
--- a/sc/source/ui/dbgui/makefile.mk
+++ b/sc/source/ui/dbgui/makefile.mk
@@ -80,6 +80,7 @@ EXCEPTIONSFILES= \
$(SLO)$/csvsplits.obj \
$(SLO)$/csvtablebox.obj \
$(SLO)$/fieldwnd.obj \
+ $(SLO)$/pvfundlg.obj \
$(SLO)$/pvlaydlg.obj \
$(SLO)$/dapidata.obj \
$(SLO)$/validate.obj
diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx
index d44791ff6972..30ee1a44d384 100644
--- a/sc/source/ui/dbgui/pvfundlg.cxx
+++ b/sc/source/ui/dbgui/pvfundlg.cxx
@@ -48,12 +48,15 @@
#include "pvfundlg.hrc"
#include "globstr.hrc"
+#include <vector>
+
// ============================================================================
using namespace ::com::sun::star::sheet;
using ::rtl::OUString;
using ::com::sun::star::uno::Sequence;
+using ::std::vector;
// ============================================================================
@@ -86,6 +89,25 @@ bool lclFillListBox( ListBoxType& rLBox, const Sequence< OUString >& rStrings, U
return bEmpty;
}
+template< typename ListBoxType >
+bool lclFillListBox( ListBoxType& rLBox, const vector<ScDPLabelData::Member>& rMembers, USHORT nEmptyPos = LISTBOX_APPEND )
+{
+ bool bEmpty = false;
+ vector<ScDPLabelData::Member>::const_iterator itr = rMembers.begin(), itrEnd = rMembers.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ OUString aName = itr->getDisplayName();
+ if (aName.getLength())
+ rLBox.InsertEntry(aName);
+ else
+ {
+ rLBox.InsertEntry(ScGlobal::GetRscString(STR_EMPTYDATA), nEmptyPos);
+ bEmpty = true;
+ }
+ }
+ return bEmpty;
+}
+
/** Searches for a listbox entry, starts search at specified position. */
USHORT lclFindListBoxEntry( const ListBox& rLBox, const String& rEntry, USHORT nStartPos )
{
@@ -253,7 +275,7 @@ void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScDPFuncData&
maLbFunc.SetSelection( nFuncMask );
// field name
- maFtName.SetText( rLabelData.maName );
+ maFtName.SetText(rLabelData.getDisplayName());
// "More button" controls
maBtnMore.AddWindow( &maFlDisplay );
@@ -271,7 +293,7 @@ void ScDPFunctionDlg::Init( const ScDPLabelData& rLabelData, const ScDPFuncData&
// base field list box
for( ScDPLabelDataVec::const_iterator aIt = mrLabelVec.begin(), aEnd = mrLabelVec.end(); aIt != aEnd; ++aIt )
- maLbBaseField.InsertEntry( aIt->maName );
+ maLbBaseField.InsertEntry(aIt->getDisplayName());
// base item list box
maLbBaseItem.SetSeparatorPos( SC_BASEITEM_USER_POS - 1 );
@@ -414,8 +436,6 @@ void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const
rLabelData.mnUsedHier = maLabelData.mnUsedHier;
rLabelData.mbShowAll = maCbShowAll.IsChecked();
rLabelData.maMembers = maLabelData.maMembers;
- rLabelData.maVisible = maLabelData.maVisible;
- rLabelData.maShowDet = maLabelData.maShowDet;
rLabelData.maSortInfo = maLabelData.maSortInfo;
rLabelData.maLayoutInfo = maLabelData.maLayoutInfo;
rLabelData.maShowInfo = maLabelData.maShowInfo;
@@ -424,7 +444,7 @@ void ScDPSubtotalDlg::FillLabelData( ScDPLabelData& rLabelData ) const
void ScDPSubtotalDlg::Init( const ScDPLabelData& rLabelData, const ScDPFuncData& rFuncData )
{
// field name
- maFtName.SetText( rLabelData.maName );
+ maFtName.SetText(rLabelData.getDisplayName());
// radio buttons
maRbNone.SetClickHdl( LINK( this, ScDPSubtotalDlg, RadioClickHdl ) );
@@ -547,9 +567,8 @@ void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const
rLabelData.maMembers = maLabelData.maMembers;
ULONG nVisCount = maLbHide.GetEntryCount();
- rLabelData.maVisible.realloc( nVisCount );
for( USHORT nPos = 0; nPos < nVisCount; ++nPos )
- rLabelData.maVisible[ nPos ] = !maLbHide.IsChecked( nPos );
+ rLabelData.maMembers[nPos].mbVisible = !maLbHide.IsChecked(nPos);
// *** HIERARCHY ***
@@ -563,7 +582,8 @@ void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayou
sal_Int32 nSortMode = maLabelData.maSortInfo.Mode;
// sort fields list box
- maLbSortBy.InsertEntry( maLabelData.maName );
+ maLbSortBy.InsertEntry(maLabelData.getDisplayName());
+
for( ScDPNameVec::const_iterator aIt = rDataFields.begin(), aEnd = rDataFields.end(); aIt != aEnd; ++aIt )
{
maLbSortBy.InsertEntry( *aIt );
@@ -656,8 +676,9 @@ void ScDPSubtotalOptDlg::InitHideListBox()
{
maLbHide.Clear();
lclFillListBox( maLbHide, maLabelData.maMembers );
- for( sal_Int32 nVisIdx = 0, nVisSize = maLabelData.maVisible.getLength(); nVisIdx < nVisSize; ++nVisIdx )
- maLbHide.CheckEntryPos( static_cast< USHORT >( nVisIdx ), !maLabelData.maVisible[ nVisIdx ] );
+ size_t n = maLabelData.maMembers.size();
+ for (size_t i = 0; i < n; ++i)
+ maLbHide.CheckEntryPos(static_cast<USHORT>(i), !maLabelData.maMembers[i].mbVisible);
bool bEnable = maLbHide.GetEntryCount() > 0;
maFlHide.Enable( bEnable );
maLbHide.Enable( bEnable );
@@ -690,8 +711,7 @@ IMPL_LINK( ScDPSubtotalOptDlg, SelectHdl, ListBox*, pLBox )
{
if( pLBox == &maLbHierarchy )
{
- mrDPObj.GetMembers( maLabelData.mnCol, maLbHierarchy.GetSelectEntryPos(),
- maLabelData.maMembers, &maLabelData.maVisible, &maLabelData.maShowDet );
+ mrDPObj.GetMembers(maLabelData.mnCol, maLbHierarchy.GetSelectEntryPos(), maLabelData.maMembers);
InitHideListBox();
}
return 0;
@@ -705,7 +725,9 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR
maLbDims ( this, ScResId( LB_DIMS ) ),
maBtnOk ( this, ScResId( BTN_OK ) ),
maBtnCancel ( this, ScResId( BTN_CANCEL ) ),
- maBtnHelp ( this, ScResId( BTN_HELP ) )
+ maBtnHelp ( this, ScResId( BTN_HELP ) ),
+
+ mrDPObj(rDPObj)
{
FreeResource();
@@ -719,7 +741,13 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR
{
const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : 0;
if ( !pDimension || (pDimension->GetOrientation() != nOrient) )
+ {
+ const OUString* pLayoutName = pDimension->GetLayoutName();
+ if (pLayoutName)
+ aName = *pLayoutName;
maLbDims.InsertEntry( aName );
+ maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim));
+ }
}
}
if( maLbDims.GetEntryCount() )
@@ -735,7 +763,17 @@ short ScDPShowDetailDlg::Execute()
String ScDPShowDetailDlg::GetDimensionName() const
{
- return maLbDims.GetSelectEntry();
+ // Look up the internal dimension name which may be different from the
+ // displayed field name.
+ String aSelectedName = maLbDims.GetSelectEntry();
+ DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName);
+ if (itr == maNameIndexMap.end())
+ // This should never happen!
+ return aSelectedName;
+
+ long nDim = itr->second;
+ BOOL bIsDataLayout = false;
+ return mrDPObj.GetDimName(nDim, bIsDataLayout);
}
IMPL_LINK( ScDPShowDetailDlg, DblClickHdl, ListBox*, pLBox )
diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index 7b03e067a865..6a9bb63e3ae3 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -63,6 +63,8 @@
#include "sc.hrc" //CHINA001
#include "scabstdlg.hxx" //CHINA001
using namespace com::sun::star;
+using ::rtl::OUString;
+using ::std::vector;
//----------------------------------------------------------------------------
@@ -378,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].getDisplayName(), i);
+ aSelectArr[i].reset( new ScDPFuncData( aLabelDataArr[i].mnCol, aLabelDataArr[i].mnFuncMask ) );
}
}
}
@@ -493,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();
@@ -594,7 +596,7 @@ void ScDPLayoutDlg::AddField( size_t nFromIndex, ScDPFieldType eToType, const Po
if ( !bDataArr )
{
- if ( toWnd->AddField( rData.maName,
+ if ( toWnd->AddField( rData.getDisplayName(),
DlgPos2WndPos( rAtPos, *toWnd ),
nAddedAt ) )
{
@@ -605,9 +607,9 @@ void ScDPLayoutDlg::AddField( size_t nFromIndex, ScDPFieldType eToType, const Po
else
{
USHORT nMask = fData.mnFuncMask;
- String aStr( GetFuncString( nMask, rData.mbIsValue ) );
+ OUString aStr = GetFuncString( nMask, rData.mbIsValue );
- aStr += rData.maName;
+ aStr += rData.getDisplayName();
if ( toWnd->AddField( aStr,
DlgPos2WndPos( rAtPos, *toWnd ),
@@ -1215,7 +1217,7 @@ String ScDPLayoutDlg::GetLabelString( SCsCOL nCol )
ScDPLabelData* pData = GetLabelData( nCol );
DBG_ASSERT( pData, "LabelData not found" );
if (pData)
- return pData->maName;
+ return pData->getDisplayName();
return String();
}
@@ -1491,6 +1493,8 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG )
nPageCount, nColCount, nRowCount, nDataCount );
if ( bFit )
{
+ ScDPSaveData* pOldSaveData = xDlgDPObject->GetSaveData();
+
ScRange aOutRange( aAdrDest ); // bToNewTable is passed separately
ScDPSaveData aSaveData;
@@ -1522,31 +1526,63 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG )
pDim->SetSortInfo( &aIt->maSortInfo );
pDim->SetLayoutInfo( &aIt->maLayoutInfo );
pDim->SetAutoShowInfo( &aIt->maShowInfo );
+ ScDPSaveDimension* pOldDim = NULL;
+ if (pOldSaveData)
+ {
+ // Transfer the existing layout names to new dimension instance.
+ pOldDim = pOldSaveData->GetExistingDimensionByName(aIt->maName);
+ if (pOldDim)
+ {
+ const OUString* pLayoutName = pOldDim->GetLayoutName();
+ if (pLayoutName)
+ pDim->SetLayoutName(*pLayoutName);
+
+ const OUString* pSubtotalName = pOldDim->GetSubtotalName();
+ if (pSubtotalName)
+ pDim->SetSubtotalName(*pSubtotalName);
+ }
+ }
bool bManualSort = ( aIt->maSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL );
// visibility of members
- if( const rtl::OUString* pItem = aIt->maMembers.getConstArray() )
+ for (vector<ScDPLabelData::Member>::const_iterator itr = aIt->maMembers.begin(), itrEnd = aIt->maMembers.end();
+ itr != itrEnd; ++itr)
{
- sal_Int32 nIdx = 0;
- sal_Int32 nVisSize = aIt->maVisible.getLength();
- sal_Int32 nShowSize = aIt->maShowDet.getLength();
- for( const rtl::OUString* pEnd = pItem + aIt->maMembers.getLength(); pItem != pEnd; ++pItem, ++nIdx )
+ ScDPSaveMember* pMember = pDim->GetMemberByName(itr->maName);
+
+ // #i40054# create/access members only if flags are not default
+ // (or in manual sorting mode - to keep the order)
+ if (bManualSort || !itr->mbVisible || !itr->mbShowDetails)
+ {
+ pMember->SetIsVisible(itr->mbVisible);
+ pMember->SetShowDetails(itr->mbShowDetails);
+ }
+ if (pOldDim)
{
- // #i40054# create/access members only if flags are not default
- // (or in manual sorting mode - to keep the order)
- bool bIsVisible = (nIdx >= nVisSize) || aIt->maVisible[ nIdx ];
- bool bShowDetails = (nIdx >= nShowSize) || aIt->maShowDet[ nIdx ];
- if( bManualSort || !bIsVisible || !bShowDetails )
+ // Transfer the existing layout name.
+ ScDPSaveMember* pOldMember = pOldDim->GetMemberByName(itr->maName);
+ if (pOldMember)
{
- ScDPSaveMember* pMember = pDim->GetMemberByName( *pItem );
- pMember->SetIsVisible( bIsVisible );
- pMember->SetShowDetails( bShowDetails );
+ const OUString* pLayoutName = pOldMember->GetLayoutName();
+ if (pLayoutName)
+ pMember->SetLayoutName(*pLayoutName);
}
}
}
}
}
+ ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension();
+ if (pDim && pOldSaveData)
+ {
+ ScDPSaveDimension* pOldDim = pOldSaveData->GetDataLayoutDimension();
+ if (pOldDim)
+ {
+ const OUString* pLayoutName = pOldDim->GetLayoutName();
+ if (pLayoutName)
+ pDim->SetLayoutName(*pLayoutName);
+ }
+ }
USHORT nWhichPivot = SC_MOD()->GetPool().GetWhich( SID_PIVOT_TABLE );
ScPivotItem aOutItem( nWhichPivot, &aSaveData, &aOutRange, bToNewTable );
@@ -1720,7 +1756,7 @@ IMPL_LINK( ScDPLayoutDlg, ScrollHdl, ScrollBar *, EMPTYARG )
for ( i=0; i<nFields; i++ )
{
const ScDPLabelData& rData = aLabelDataArr[nOffset+i];
- aWndSelect.AddField( rData.maName, i );
+ aWndSelect.AddField(rData.getDisplayName(), i);
aSelectArr[i].reset( new ScDPFuncData( rData.mnCol, rData.mnFuncMask ) );
}
for ( ; i<aSelectArr.size(); i++ )
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 33caccaed815..4042154b9a52 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -1234,7 +1234,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,
@@ -1278,7 +1278,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/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index 4827366d3924..3ab36ce131ad 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -2145,15 +2145,20 @@ void ScDocShell::Print( SfxProgress& rProgress, PrintDialog* pPrintDialog,
}
}
- if ( n+1 < nCollateCopies && pPrinter->GetDuplexMode() == DUPLEX_ON && ( nPrinted % 2 ) == 1 )
+ if ( n+1 < nCollateCopies &&
+ (pPrinter->GetDuplexMode() == DUPLEX_SHORTEDGE || pPrinter->GetDuplexMode() == DUPLEX_LONGEDGE) &&
+ ( nPrinted % 2 ) == 1 )
{
// #105584# when several collated copies are printed in duplex mode, and there is
// an odd number of pages, print an empty page between copies, so the first page of
// the second copy isn't printed on the back of the last page of the first copy.
// (same as in Writer ViewShell::Prt)
+ // FIXME: needs to be adapted to XRenderable interface
+ #if 0
pPrinter->StartPage();
pPrinter->EndPage();
+ #endif
}
}
}
diff --git a/sc/source/ui/inc/AccessibleContextBase.hxx b/sc/source/ui/inc/AccessibleContextBase.hxx
index 98f2afc8e88d..4c79c4388e44 100644
--- a/sc/source/ui/inc/AccessibleContextBase.hxx
+++ b/sc/source/ui/inc/AccessibleContextBase.hxx
@@ -319,6 +319,8 @@ protected:
/// Use this method to set initial Description without notification
void SetDescription(const rtl::OUString& rDesc) { msDescription = rDesc; }
+ void SetRole(sal_Int16 nRole);
+
/// Reference to the parent object.
::com::sun::star::uno::Reference<
::com::sun::star::accessibility::XAccessible> mxParent;
diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx
index 82739bfdd274..875576a22889 100644
--- a/sc/source/ui/inc/dbfunc.hxx
+++ b/sc/source/ui/inc/dbfunc.hxx
@@ -80,7 +80,7 @@ public:
void GotoDBArea( const String& rDBName );
// DB-Bereich vom Cursor
- ScDBData* GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE );
+ ScDBData* GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bShrinkToData = false );
void NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList );
@@ -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..2275b601c17a
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hrc
@@ -0,0 +1,43 @@
+/*************************************************************************
+ *
+ * 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
+#define STR_BTN_TOGGLE_ALL 4
+#define STR_BTN_SELECT_CURRENT 5
+#define STR_BTN_UNSELECT_CURRENT 6
+
+#endif
diff --git a/sc/source/ui/inc/dpcontrol.hxx b/sc/source/ui/inc/dpcontrol.hxx
new file mode 100644
index 000000000000..1b99f6a38842
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hxx
@@ -0,0 +1,366 @@
+/*************************************************************************
+ *
+ * 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 "tools/fract.hxx"
+#include "vcl/popupmenuwindow.hxx"
+#include "vcl/button.hxx"
+#include "vcl/scrbar.hxx"
+#include "vcl/timer.hxx"
+#include "svx/checklbx.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <hash_map>
+
+namespace com { namespace sun { namespace star {
+
+ namespace accessibility {
+ class XAccessible;
+ }
+
+}}}
+
+class OutputDevice;
+class Point;
+class Size;
+class StyleSettings;
+class Window;
+class ScDocument;
+class ScAccessibleFilterMenu;
+
+/**
+ * This class takes care of physically drawing field button controls inside
+ * data pilot tables.
+ */
+class ScDPFieldButton
+{
+public:
+ ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomX = NULL, const Fraction* pZoomY = NULL);
+ ~ScDPFieldButton();
+
+ void setText(const ::rtl::OUString& rText);
+ void setBoundingBox(const Point& rPos, const Size& rSize);
+ void setDrawBaseButton(bool b);
+ void setDrawPopupButton(bool b);
+ void setHasHiddenMember(bool b);
+ void setPopupPressed(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;
+ Fraction maZoomX;
+ Fraction maZoomY;
+ OutputDevice* mpOutDev;
+ const StyleSettings* mpStyle;
+ bool mbBaseButton;
+ bool mbPopupButton;
+ bool mbHasHiddenMember;
+ bool mbPopupPressed;
+};
+
+// ============================================================================
+
+class ScMenuFloatingWindow : public PopupMenuFloatingWindow
+{
+public:
+ static size_t MENU_NOT_SELECTED;
+ /**
+ * 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, ScDocument* pDoc, USHORT nMenuStackLevel = 0);
+ 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);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
+
+ void addMenuItem(const ::rtl::OUString& rText, bool bEnabled, Action* pAction);
+ ScMenuFloatingWindow* addSubMenuItem(const ::rtl::OUString& rText, bool bEnabled);
+ void setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu);
+ void selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer);
+ void clearSelectedMenuItem();
+ ScMenuFloatingWindow* getSubMenuWindow(size_t nPos) const;
+ size_t getMenuItemCount() const;
+ ::rtl::OUString getMenuItemName(size_t nPos) const;
+ bool isMenuItemEnabled(size_t nPos) const;
+ bool isMenuItemSelected(size_t nPos) const;
+ size_t getSelectedMenuItem() const;
+
+ void setName(const ::rtl::OUString& rName);
+ const ::rtl::OUString& getName() const;
+
+ void executeMenuItem(size_t nPos);
+ void getMenuItemPosSize(size_t nPos, Point& rPos, Size& rSize) const;
+ ScMenuFloatingWindow* getParentMenuWindow() const;
+
+protected:
+
+ void drawMenuItem(size_t nPos);
+ void drawAllMenuItems();
+ const Font& getLabelFont() const;
+
+ void queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu);
+ void queueCloseSubMenu();
+ void launchSubMenu(bool bSetMenuPos);
+ void endSubMenu(ScMenuFloatingWindow* pSubMenu);
+
+ void fillMenuItemsToAccessible(ScAccessibleFilterMenu* pAccMenu) const;
+
+ ScDocument* getDoc();
+
+protected:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > mxAccessible;
+
+private:
+ struct SubMenuItemData;
+ void handleMenuTimeout(SubMenuItemData* pTimer);
+
+ void resizeToFitMenuItems();
+ void highlightMenuItem(size_t nPos, bool bSelected);
+
+ size_t getEnclosingMenuItem(const Point& rPos) const;
+ size_t getSubMenuPos(ScMenuFloatingWindow* pSubMenu);
+
+ /**
+ * Fire a menu highlight event since the accessibility framework needs
+ * this to track focus on menu items.
+ */
+ void fireMenuHighlightedEvent();
+
+ /**
+ * Make sure that the specified submenu is permanently up, the submenu
+ * close timer is not active, and the correct menu item associated with
+ * the submenu is highlighted.
+ */
+ void setSubMenuFocused(ScMenuFloatingWindow* pSubMenu);
+
+ /**
+ * When a menu item of an invisible submenu is selected, we need to make
+ * sure that all its parent menu(s) are visible, with the right menu item
+ * highlighted in each of the parents. Calling this method ensures it.
+ */
+ void ensureSubMenuVisible(ScMenuFloatingWindow* pSubMenu);
+
+ /**
+ * Dismiss any visible child submenus when a menu item of a parent menu is
+ * selected.
+ */
+ void ensureSubMenuNotVisible();
+
+ /**
+ * Dismiss all visible popup menus and set focus back to the application
+ * window. This method is called e.g. when a menu action is fired.
+ */
+ void terminateAllPopupMenus();
+
+ DECL_LINK( PopupEndHdl, void* );
+
+private:
+
+ struct MenuItemData
+ {
+ ::rtl::OUString maText;
+ bool mbEnabled;
+
+ ::boost::shared_ptr<Action> mpAction;
+ ::boost::shared_ptr<ScMenuFloatingWindow> mpSubMenuWin;
+
+ MenuItemData();
+ };
+
+ ::std::vector<MenuItemData> maMenuItems;
+
+ struct SubMenuItemData
+ {
+ Timer maTimer;
+ ScMenuFloatingWindow* mpSubMenu;
+ size_t mnMenuPos;
+
+ DECL_LINK( TimeoutHdl, void* );
+
+ SubMenuItemData(ScMenuFloatingWindow* pParent);
+ void reset();
+
+ private:
+ ScMenuFloatingWindow* mpParent;
+ };
+ SubMenuItemData maOpenTimer;
+ SubMenuItemData maCloseTimer;
+
+ Font maLabelFont;
+
+ // Name of this menu window, taken from the menu item of the parent window
+ // that launches it (if this is a sub menu). If this is a top-level menu
+ // window, then this name can be anything.
+ ::rtl::OUString maName;
+
+ size_t mnSelectedMenu;
+ size_t mnClickedMenu;
+
+ ScDocument* mpDoc;
+
+ ScMenuFloatingWindow* mpParentMenu;
+ ScMenuFloatingWindow* mpActiveSubMenu;
+};
+
+// ============================================================================
+
+/**
+ * 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, ScDocument* pDoc);
+ virtual ~ScDPFieldPopupWindow();
+
+ virtual void MouseMove(const MouseEvent& rMEvt);
+ virtual long Notify(NotifyEvent& rNEvt);
+ virtual void Paint(const Rectangle& rRect);
+ virtual Window* GetPreferredKeyInputWindow();
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
+
+ void setMemberSize(size_t n);
+ void addMember(const ::rtl::OUString& rName, bool bVisible);
+ void initMembers();
+
+ const Size& getWindowSize() const;
+
+ 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;
+ };
+
+ enum SectionType {
+ WHOLE, // entire window
+ LISTBOX_AREA_OUTER, // box enclosing the check box items.
+ LISTBOX_AREA_INNER, // box enclosing the check box items.
+ SINGLE_BTN_AREA, // box enclosing the single-action buttons.
+ CHECK_TOGGLE_ALL, // check box for toggling all items.
+ BTN_SINGLE_SELECT,
+ BTN_SINGLE_UNSELECT,
+ BTN_OK, // OK button
+ BTN_CANCEL, // Cancel button
+ };
+ void getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const;
+
+ void setAllMemberState(bool bSet);
+ void selectCurrentMemberOnly(bool bSet);
+ void cycleFocus(bool bReverse = false);
+
+ DECL_LINK( ButtonHdl, Button* );
+ DECL_LINK( TriStateHdl, TriStateBox* );
+ DECL_LINK( CheckHdl, SvTreeListBox* );
+
+private:
+ SvxCheckListBox maChecks;
+
+ TriStateBox maChkToggleAll;
+ ImageButton maBtnSelectSingle;
+ ImageButton maBtnUnselectSingle;
+
+ OKButton maBtnOk;
+ CancelButton maBtnCancel;
+
+ ::std::vector<Window*> maTabStopCtrls;
+ size_t mnCurTabStop;
+
+ ::std::vector<Member> maMembers;
+ ::std::auto_ptr<ExtendedData> mpExtendedData;
+ ::std::auto_ptr<Action> mpOKAction;
+
+ const Size maWndSize; /// hard-coded window size.
+ TriState mePrevToggleAllState;
+};
+
+#endif
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 8b680daad6cb..68f7ece9a249 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -37,15 +37,19 @@
#include "viewdata.hxx"
#include "cbutton.hxx"
#include <svx/sdr/overlay/overlayobject.hxx>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <vector>
+#include <memory>
// ---------------------------------------------------------------------------
struct ScTableInfo;
class ScViewSelectionEngine;
class ScDPObject;
+class ScDPFieldPopupWindow;
+class ScDPFieldButton;
class ScOutputData;
class ScFilterListBox;
class AutoFilterPopup;
@@ -121,6 +125,8 @@ private:
ScFilterListBox* pFilterBox;
FloatingWindow* pFilterFloat;
+ ::std::auto_ptr<ScDPFieldPopupWindow> mpDPFieldPopup;
+ ::std::auto_ptr<ScDPFieldButton> mpFilterButton;
USHORT nCursorHideCount;
@@ -187,12 +193,23 @@ private:
BOOL TestMouse( const MouseEvent& rMEvt, BOOL bAction );
BOOL DoPageFieldSelection( SCCOL nCol, SCROW nRow );
+ bool DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt );
void DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt );
void DPMouseMove( const MouseEvent& rMEvt );
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& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj);
+
void RFMouseMove( const MouseEvent& rMEvt, BOOL bUp );
void PagebreakMove( const MouseEvent& rMEvt, BOOL bUp );
@@ -315,9 +332,11 @@ public:
void DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect );
void DoScenarioMenue( const ScRange& rScenRange );
- void DoPageFieldMenue( SCCOL nCol, SCROW nRow );
- BOOL HasPageFieldData( SCCOL nCol, SCROW nRow ) const;
+ void LaunchPageFieldMenu( SCCOL nCol, SCROW nRow );
+ void LaunchDPFieldMenu( SCCOL nCol, SCROW nRow );
+
+ ::com::sun::star::sheet::DataPilotFieldOrientation GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const;
void DrawButtons( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
ScTableInfo& rTabInfo, OutputDevice* pContentDev );
@@ -357,6 +376,8 @@ public:
void CheckNeedsRepaint();
+ void UpdateDPFromFieldPopupMenu();
+
// #114409#
void CursorChanged();
void DrawLayerCreated();
diff --git a/sc/source/ui/inc/pfuncache.hxx b/sc/source/ui/inc/pfuncache.hxx
index 93ff22fad0a8..a35084d453d6 100644
--- a/sc/source/ui/inc/pfuncache.hxx
+++ b/sc/source/ui/inc/pfuncache.hxx
@@ -34,6 +34,7 @@
#include <vector>
#include <tools/gen.hxx>
#include "rangelst.hxx"
+#include "printopt.hxx"
class ScDocShell;
class ScMarkData;
@@ -58,6 +59,7 @@ class ScPrintSelectionStatus
{
ScPrintSelectionMode eMode;
ScRangeList aRanges;
+ ScPrintOptions aOptions;
public:
ScPrintSelectionStatus() : eMode(SC_PRINTSEL_INVALID) {}
@@ -65,11 +67,13 @@ public:
void SetMode(ScPrintSelectionMode eNew) { eMode = eNew; }
void SetRanges(const ScRangeList& rNew) { aRanges = rNew; }
+ void SetOptions(const ScPrintOptions& rNew) { aOptions = rNew; }
BOOL operator==(const ScPrintSelectionStatus& rOther) const
- { return eMode == rOther.eMode && aRanges == rOther.aRanges; }
+ { return eMode == rOther.eMode && aRanges == rOther.aRanges && aOptions == rOther.aOptions; }
ScPrintSelectionMode GetMode() const { return eMode; }
+ const ScPrintOptions& GetOptions() const { return aOptions; }
};
diff --git a/sc/source/ui/inc/pvfundlg.hxx b/sc/source/ui/inc/pvfundlg.hxx
index eeeb9c4094c4..6b9aa62c37a3 100644
--- a/sc/source/ui/inc/pvfundlg.hxx
+++ b/sc/source/ui/inc/pvfundlg.hxx
@@ -55,6 +55,8 @@
#include <sfx2/itemconnect.hxx>
#include "pivot.hxx"
+#include <hash_map>
+
// ============================================================================
typedef sfx::ListBoxWrapper< sal_Int32 > ScDPListBoxWrapper;
@@ -217,6 +219,11 @@ public:
virtual short Execute();
+ /**
+ * @return String internal name of the selected field. Note that this may
+ * be different from the name displayed in the dialog if the field
+ * has a layout name.
+ */
String GetDimensionName() const;
private:
@@ -228,6 +235,10 @@ private:
OKButton maBtnOk;
CancelButton maBtnCancel;
HelpButton maBtnHelp;
+
+ typedef ::std::hash_map<String, long, ScStringHashCode> DimNameIndexMap;
+ DimNameIndexMap maNameIndexMap;
+ ScDPObject& mrDPObj;
};
// ============================================================================
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/src/scstring.src b/sc/source/ui/src/scstring.src
index efe9a0312b02..2dfcd84a4726 100644
--- a/sc/source/ui/src/scstring.src
+++ b/sc/source/ui/src/scstring.src
@@ -738,3 +738,29 @@ String SCSTR_MOREBTN_FEWEROPTIONS
Text [ en-US ] = "Fewer ~Options";
};
+StringArray SCSTR_PRINT_OPTIONS
+{
+ ItemList [en-US] =
+ {
+ < "Pages"; >;
+ < "~Include output of empty pages"; >;
+ < "If checked empty pages that have no cell contents or draw objects are not printed."; >;
+ < "Sheets"; >;
+ < "Print ~only selected sheets"; >;
+ < "If checked only contents from selected sheets are printed, even if you specify a wider range in the Format - Print Ranges dialog. Content from sheets that are not selected will not be printed."; >;
+ < "Print content"; >;
+ < "~All sheets"; >;
+ < "The printout will be created from all sheets in the document."; >;
+ < "~Selected sheets"; >;
+ < "The printout will be created only from the currently selected sheets."; >;
+ < "Selected cells"; >;
+ < "The printout will be created only from the currently selected cells."; >;
+ < "Thereof print"; >;
+ < "All ~pages"; >;
+ < "Print all pages of the printable content."; >;
+ < "Pa~ges"; >;
+ < "Print only some pages of the printable content."; >;
+ < "%PRODUCTNAME %s"; >;
+ };
+};
+
diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx
index 7ab321ac0c1d..5c929ec7a11b 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/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx
index ed40d2f5c96a..a7836b43f740 100644
--- a/sc/source/ui/unoobj/dapiuno.cxx
+++ b/sc/source/ui/unoobj/dapiuno.cxx
@@ -1626,8 +1626,13 @@ OUString SAL_CALL ScDataPilotFieldObj::getName() throw(RuntimeException)
if( pDim->IsDataLayout() )
aName = OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) );
else
- aName = pDim->GetLayoutName();
- }
+ {
+ const rtl::OUString* pLayoutName = pDim->GetLayoutName();
+ if (pLayoutName)
+ aName = *pLayoutName;
+ else
+ aName = pDim->GetName();
+ } }
return aName;
}
@@ -1639,7 +1644,7 @@ void SAL_CALL ScDataPilotFieldObj::setName( const OUString& rName ) throw(Runtim
if( pDim && !pDim->IsDataLayout() )
{
String aName( rName );
- pDim->SetLayoutName( &aName );
+ pDim->SetLayoutName(aName);
SetDPObject( pDPObj );
}
}
@@ -3069,7 +3074,7 @@ Sequence<OUString> SAL_CALL ScDataPilotItemsObj::getElementNames()
ScUnoGuard aGuard;
Sequence< OUString > aSeq;
if( ScDPObject* pDPObj = GetDPObject() )
- pDPObj->GetMembers( lcl_GetObjectIndex( pDPObj, maFieldId ), aSeq );
+ pDPObj->GetMemberNames( lcl_GetObjectIndex( pDPObj, maFieldId ), aSeq );
return aSeq;
}
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 5f4f1a7aa93f..71f4706085d8 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -43,12 +43,14 @@
#include <svl/numuno.hxx>
#include <svl/smplhint.hxx>
#include <unotools/undoopt.hxx>
+#include <unotools/moduleoptions.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/bindings.hxx>
#include <vcl/pdfextoutdevdata.hxx>
#include <vcl/waitobj.hxx>
#include <unotools/charclass.hxx>
#include <tools/multisel.hxx>
+#include <tools/resary.hxx>
#include <toolkit/awt/vclxdevice.hxx>
#include <ctype.h>
#include <float.h> // DBL_MAX
@@ -90,11 +92,15 @@
#include "unoguard.hxx"
#include "unonames.hxx"
#include "shapeuno.hxx"
+#include "viewuno.hxx"
+#include "tabvwsh.hxx"
#include "printfun.hxx"
#include "pfuncache.hxx"
#include "scmod.hxx"
#include "rangeutl.hxx"
#include "ViewSettingsSequenceDefines.hxx"
+#include "sc.hrc"
+#include "scresid.hxx"
#ifndef _SVX_UNOSHAPE_HXX
#include <svx/unoshape.hxx>
@@ -209,6 +215,147 @@ SC_SIMPLE_SERVICE_INFO( ScTableSheetsObj, "ScTableSheetsObj", "com.sun.star.shee
//------------------------------------------------------------------------
+class ScPrintUIOptions : public vcl::PrinterOptionsHelper
+{
+public:
+ ScPrintUIOptions();
+ void SetDefaults();
+};
+
+ScPrintUIOptions::ScPrintUIOptions()
+{
+ const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
+ sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
+ sal_Bool bSuppress = rPrintOpt.GetSkipEmpty();
+
+ ResStringArray aStrings( ScResId( SCSTR_PRINT_OPTIONS ) );
+ DBG_ASSERT( aStrings.Count() >= 19, "resource incomplete" );
+ if( aStrings.Count() < 19 ) // bad resource ?
+ return;
+
+ m_aUIProperties.realloc( 8 );
+
+ // create Section for spreadsheet (results in an extra tab page in dialog)
+ SvtModuleOptions aOpt;
+ String aAppGroupname( aStrings.GetString( 18 ) );
+ aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ),
+ aOpt.GetModuleName( SvtModuleOptions::E_SCALC ) );
+ m_aUIProperties[0].Value = getGroupControlOpt( aAppGroupname, rtl::OUString() );
+
+ // create subgroup for pages
+ m_aUIProperties[1].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 0 ) ), rtl::OUString() );
+
+ // create a bool option for empty pages
+ m_aUIProperties[2].Value = getBoolControlOpt( rtl::OUString( aStrings.GetString( 1 ) ),
+ rtl::OUString( aStrings.GetString( 2 ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsIncludeEmptyPages" ) ),
+ ! bSuppress
+ );
+ // create Subgroup for print content
+ vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt;
+ aPrintRangeOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) );
+ m_aUIProperties[3].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 6 ) ),
+ rtl::OUString(),
+ aPrintRangeOpt
+ );
+
+ // create a choice for the content to create
+ uno::Sequence< rtl::OUString > aChoices( 3 ), aHelpTexts( 3 );
+ aChoices[0] = aStrings.GetString( 7 );
+ aHelpTexts[0] = aStrings.GetString( 8 );
+ aChoices[1] = aStrings.GetString( 9 );
+ aHelpTexts[1] = aStrings.GetString( 10 );
+ aChoices[2] = aStrings.GetString( 11 );
+ aHelpTexts[2] = aStrings.GetString( 12 );
+ m_aUIProperties[4].Value = getChoiceControlOpt( rtl::OUString(),
+ aHelpTexts,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ),
+ aChoices,
+ nContent );
+
+ // create Subgroup for print range
+ aPrintRangeOpt.mbInternalOnly = sal_True;
+ m_aUIProperties[5].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 13 ) ),
+ rtl::OUString(),
+ aPrintRangeOpt
+ );
+
+ // create a choice for the range to print
+ rtl::OUString aPrintRangeName( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) );
+ aChoices.realloc( 2 );
+ aHelpTexts.realloc( 2 );
+ aChoices[0] = aStrings.GetString( 14 );
+ aHelpTexts[0] = aStrings.GetString( 15 );
+ aChoices[1] = aStrings.GetString( 16 );
+ aHelpTexts[1] = aStrings.GetString( 17 );
+ m_aUIProperties[6].Value = getChoiceControlOpt( rtl::OUString(),
+ aHelpTexts,
+ aPrintRangeName,
+ aChoices,
+ 0 );
+
+ // create a an Edit dependent on "Pages" selected
+ vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, sal_True );
+ m_aUIProperties[7].Value = getEditControlOpt( rtl::OUString(),
+ rtl::OUString(),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ),
+ rtl::OUString(),
+ aPageRangeOpt
+ );
+
+ // "Print only selected sheets" isn't needed because of the "Selected Sheets" choice in "Print content"
+#if 0
+ // create subgroup for sheets
+ m_aUIProperties[8].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 3 ) ), rtl::OUString() );
+
+ // create a bool option for selected pages only
+ m_aUIProperties[9].Value = getBoolControlOpt( rtl::OUString( aStrings.GetString( 4 ) ),
+ rtl::OUString( aStrings.GetString( 5 ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsOnlySelectedSheets" ) ),
+ i_bSelectedOnly
+ );
+#endif
+}
+
+void ScPrintUIOptions::SetDefaults()
+{
+ // re-initialize the default values from print options
+
+ const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
+ sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
+ sal_Bool bSuppress = rPrintOpt.GetSkipEmpty();
+
+ for (sal_Int32 nUIPos=0; nUIPos<m_aUIProperties.getLength(); ++nUIPos)
+ {
+ uno::Sequence<beans::PropertyValue> aUIProp;
+ if ( m_aUIProperties[nUIPos].Value >>= aUIProp )
+ {
+ for (sal_Int32 nPropPos=0; nPropPos<aUIProp.getLength(); ++nPropPos)
+ {
+ rtl::OUString aName = aUIProp[nPropPos].Name;
+ if ( aName.equalsAscii("Property") )
+ {
+ beans::PropertyValue aPropertyValue;
+ if ( aUIProp[nPropPos].Value >>= aPropertyValue )
+ {
+ if ( aPropertyValue.Name.equalsAscii( "PrintContent" ) )
+ {
+ aPropertyValue.Value <<= nContent;
+ aUIProp[nPropPos].Value <<= aPropertyValue;
+ }
+ else if ( aPropertyValue.Name.equalsAscii( "IsIncludeEmptyPages" ) )
+ {
+ ScUnoHelpFunctions::SetBoolInAny( aPropertyValue.Value, ! bSuppress );
+ aUIProp[nPropPos].Value <<= aPropertyValue;
+ }
+ }
+ }
+ }
+ m_aUIProperties[nUIPos].Value <<= aUIProp;
+ }
+ }
+}
+
// static
void ScModelObj::CreateAndSet(ScDocShell* pDocSh)
{
@@ -221,6 +368,7 @@ ScModelObj::ScModelObj( ScDocShell* pDocSh ) :
aPropSet( lcl_GetDocOptPropertyMap() ),
pDocShell( pDocSh ),
pPrintFuncCache( NULL ),
+ pPrinterOptions( NULL ),
maChangesListeners( m_aMutex ),
mnXlsWriteProtPass( 0 )
{
@@ -240,6 +388,7 @@ ScModelObj::~ScModelObj()
xNumberAgg->setDelegator(uno::Reference<uno::XInterface>());
delete pPrintFuncCache;
+ delete pPrinterOptions;
}
uno::Reference< uno::XAggregation> ScModelObj::GetFormatter()
@@ -599,20 +748,65 @@ bool lcl_ParseTarget( const String& rTarget, ScRange& rTargetRange, Rectangle& r
return bRangeValid;
}
-BOOL ScModelObj::FillRenderMarkData( const uno::Any& aSelection, ScMarkData& rMark,
- ScPrintSelectionStatus& rStatus ) const
+BOOL ScModelObj::FillRenderMarkData( const uno::Any& aSelection,
+ const uno::Sequence< beans::PropertyValue >& rOptions,
+ ScMarkData& rMark,
+ ScPrintSelectionStatus& rStatus, String& rPagesStr ) const
{
DBG_ASSERT( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" );
DBG_ASSERT( pDocShell, "FillRenderMarkData: DocShell must be set" );
BOOL bDone = FALSE;
+ uno::Reference<frame::XController> xView;
+
+ // defaults when no options are passed: all sheets, include empty pages
+ sal_Bool bSelectedSheetsOnly = sal_False;
+ sal_Bool bIncludeEmptyPages = sal_True;
+
+ bool bHasPrintContent = false;
+ sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells
+ sal_Int32 nPrintRange = 0; // all pages / pages
+ rtl::OUString aPageRange; // "pages" edit value
+
+ for( sal_Int32 i = 0, nLen = rOptions.getLength(); i < nLen; i++ )
+ {
+ if( rOptions[i].Name.equalsAscii( "IsOnlySelectedSheets" ) )
+ {
+ rOptions[i].Value >>= bSelectedSheetsOnly;
+ }
+ else if( rOptions[i].Name.equalsAscii( "IsIncludeEmptyPages" ) )
+ {
+ rOptions[i].Value >>= bIncludeEmptyPages;
+ }
+ else if( rOptions[i].Name.equalsAscii( "PageRange" ) )
+ {
+ rOptions[i].Value >>= aPageRange;
+ }
+ else if( rOptions[i].Name.equalsAscii( "PrintRange" ) )
+ {
+ rOptions[i].Value >>= nPrintRange;
+ }
+ else if( rOptions[i].Name.equalsAscii( "PrintContent" ) )
+ {
+ bHasPrintContent = true;
+ rOptions[i].Value >>= nPrintContent;
+ }
+ else if( rOptions[i].Name.equalsAscii( "View" ) )
+ {
+ rOptions[i].Value >>= xView;
+ }
+ }
+
+ // "Print Content" selection wins over "Selected Sheets" option
+ if ( bHasPrintContent )
+ bSelectedSheetsOnly = ( nPrintContent != 0 );
+
uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
if ( xInterface.is() )
{
ScCellRangesBase* pSelObj = ScCellRangesBase::getImplementation( xInterface );
uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY );
-
if ( pSelObj && pSelObj->GetDocShell() == pDocShell )
{
BOOL bSheet = ( ScTableSheetObj::getImplementation( xInterface ) != NULL );
@@ -685,12 +879,41 @@ BOOL ScModelObj::FillRenderMarkData( const uno::Any& aSelection, ScMarkData& rMa
// other selection types aren't supported
}
+ // restrict to selected sheets if a view is available
+ if ( bSelectedSheetsOnly && xView.is() )
+ {
+ ScTabViewObj* pViewObj = ScTabViewObj::getImplementation( xView );
+ if (pViewObj)
+ {
+ ScTabViewShell* pViewSh = pViewObj->GetViewShell();
+ if (pViewSh)
+ {
+ const ScMarkData& rViewMark = pViewSh->GetViewData()->GetMarkData();
+ SCTAB nTabCount = pDocShell->GetDocument()->GetTableCount();
+ for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
+ if (!rViewMark.GetTableSelect(nTab))
+ rMark.SelectTable( nTab, FALSE );
+ }
+ }
+ }
+
+ ScPrintOptions aNewOptions;
+ aNewOptions.SetSkipEmpty( !bIncludeEmptyPages );
+ aNewOptions.SetAllSheets( !bSelectedSheetsOnly );
+ rStatus.SetOptions( aNewOptions );
+
+ // "PrintRange" enables (1) or disables (0) the "PageRange" edit
+ if ( nPrintRange == 1 )
+ rPagesStr = aPageRange;
+ else
+ rPagesStr.Erase();
+
return bDone;
}
sal_Int32 SAL_CALL ScModelObj::getRendererCount( const uno::Any& aSelection,
- const uno::Sequence<beans::PropertyValue>& /* xOptions */ )
+ const uno::Sequence<beans::PropertyValue>& rOptions )
throw (lang::IllegalArgumentException, uno::RuntimeException)
{
ScUnoGuard aGuard;
@@ -699,7 +922,8 @@ sal_Int32 SAL_CALL ScModelObj::getRendererCount( const uno::Any& aSelection,
ScMarkData aMark;
ScPrintSelectionStatus aStatus;
- if ( !FillRenderMarkData( aSelection, aMark, aStatus ) )
+ String aPagesStr;
+ if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) )
return 0;
// The same ScPrintFuncCache object in pPrintFuncCache is used as long as
@@ -711,11 +935,37 @@ sal_Int32 SAL_CALL ScModelObj::getRendererCount( const uno::Any& aSelection,
delete pPrintFuncCache;
pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus );
}
- return pPrintFuncCache->GetPageCount();
+ sal_Int32 nPages = pPrintFuncCache->GetPageCount();
+
+ sal_Int32 nSelectCount = nPages;
+ if ( aPagesStr.Len() )
+ {
+ MultiSelection aPageRanges( aPagesStr );
+ aPageRanges.SetTotalRange( Range( 1, nPages ) );
+ nSelectCount = aPageRanges.GetSelectCount();
+ }
+ return nSelectCount;
}
-uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nRenderer,
- const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& /* xOptions */ )
+sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, const String& rPagesStr, sal_Int32 nTotalPages )
+{
+ if ( !rPagesStr.Len() )
+ return nSelRenderer;
+
+ MultiSelection aPageRanges( rPagesStr );
+ aPageRanges.SetTotalRange( Range( 1, nTotalPages ) );
+
+ sal_Int32 nSelected = aPageRanges.FirstSelected();
+ while ( nSelRenderer > 0 )
+ {
+ nSelected = aPageRanges.NextSelected();
+ --nSelRenderer;
+ }
+ return nSelected - 1; // selection is 1-based
+}
+
+uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer,
+ const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions )
throw (lang::IllegalArgumentException, uno::RuntimeException)
{
ScUnoGuard aGuard;
@@ -724,7 +974,8 @@ uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32
ScMarkData aMark;
ScPrintSelectionStatus aStatus;
- if ( !FillRenderMarkData( aSelection, aMark, aStatus ) )
+ String aPagesStr;
+ if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) )
throw lang::IllegalArgumentException();
if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
@@ -733,8 +984,33 @@ uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32
pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus );
}
long nTotalPages = pPrintFuncCache->GetPageCount();
+ sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
if ( nRenderer >= nTotalPages )
- throw lang::IllegalArgumentException();
+ {
+ if ( nSelRenderer == 0 )
+ {
+ // getRenderer(0) is used to query the settings, so it must always return something
+
+ SCTAB nCurTab = 0; //! use current sheet from view?
+ ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab );
+ Size aTwips = aDefaultFunc.GetPageSize();
+ awt::Size aPageSize( TwipsToHMM( aTwips.Width() ), TwipsToHMM( aTwips.Height() ) );
+
+ uno::Sequence<beans::PropertyValue> aSequence(1);
+ beans::PropertyValue* pArray = aSequence.getArray();
+ pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_PAGESIZE );
+ pArray[0].Value <<= aPageSize;
+
+ if( ! pPrinterOptions )
+ pPrinterOptions = new ScPrintUIOptions;
+ else
+ pPrinterOptions->SetDefaults();
+ pPrinterOptions->appendPrintUIOptions( aSequence );
+ return aSequence;
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
// printer is used as device (just for page layout), draw view is not needed
@@ -748,7 +1024,7 @@ uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32
pSelRange = &aRange;
}
ScPrintFunc aFunc( pDocShell, pDocShell->GetPrinter(), nTab,
- pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange );
+ pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions() );
aFunc.SetRenderFlag( TRUE );
Range aPageRange( nRenderer+1, nRenderer+1 );
@@ -779,10 +1055,21 @@ uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32
pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_SOURCERANGE );
pArray[1].Value <<= aRangeAddress;
}
+
+ #if 0
+ const ScPrintOptions& rPrintOpt =
+ #endif
+ // FIXME: is this for side effects ?
+ SC_MOD()->GetPrintOptions();
+ if( ! pPrinterOptions )
+ pPrinterOptions = new ScPrintUIOptions;
+ else
+ pPrinterOptions->SetDefaults();
+ pPrinterOptions->appendPrintUIOptions( aSequence );
return aSequence;
}
-void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelection,
+void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection,
const uno::Sequence<beans::PropertyValue>& rOptions )
throw(lang::IllegalArgumentException, uno::RuntimeException)
{
@@ -792,7 +1079,8 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
ScMarkData aMark;
ScPrintSelectionStatus aStatus;
- if ( !FillRenderMarkData( aSelection, aMark, aStatus ) )
+ String aPagesStr;
+ if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) )
throw lang::IllegalArgumentException();
if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
@@ -801,6 +1089,7 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus );
}
long nTotalPages = pPrintFuncCache->GetPageCount();
+ sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
if ( nRenderer >= nTotalPages )
throw lang::IllegalArgumentException();
@@ -835,7 +1124,7 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
// to increase performance, ScPrintState might be used here for subsequent
// pages of the same sheet
- ScPrintFunc aFunc( pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange );
+ ScPrintFunc aFunc( pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions() );
aFunc.SetDrawView( pDrawView );
aFunc.SetRenderFlag( TRUE );
if( aStatus.GetMode() == SC_PRINTSEL_RANGE_EXCLUSIVELY_OLE_AND_DRAW_OBJECTS )
@@ -849,11 +1138,11 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
long nTabStart = pPrintFuncCache->GetTabStart( nTab );
+ vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
if ( nRenderer == nTabStart )
{
// first page of a sheet: add outline item for the sheet name
- vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
if ( pPDFData && pPDFData->GetIsExportBookmarks() )
{
// the sheet starts at the top of the page
@@ -866,7 +1155,7 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
}
//--->i56629
// add the named destination stuff
- if( pPDFData->GetIsExportNamedDestinations() )
+ if( pPDFData && pPDFData->GetIsExportNamedDestinations() )
{
Rectangle aArea( pDev->PixelToLogic( Rectangle( 0,0,0,0 ) ) );
String aTabName;
@@ -881,7 +1170,6 @@ void SAL_CALL ScModelObj::render( sal_Int32 nRenderer, const uno::Any& aSelectio
// resolve the hyperlinks for PDF export
- vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
if ( pPDFData )
{
// iterate over the hyperlinks that were output for this page
diff --git a/sc/source/ui/unoobj/miscuno.cxx b/sc/source/ui/unoobj/miscuno.cxx
index 3d41da907016..ee2a64bd8c78 100644
--- a/sc/source/ui/unoobj/miscuno.cxx
+++ b/sc/source/ui/unoobj/miscuno.cxx
@@ -39,6 +39,9 @@
#include "unoguard.hxx"
using namespace com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::rtl::OUString;
//------------------------------------------------------------------------
@@ -137,6 +140,26 @@ sal_Int32 ScUnoHelpFunctions::GetEnumProperty( const uno::Reference<beans::XProp
return nRet;
}
+// static
+OUString ScUnoHelpFunctions::GetStringProperty(
+ const Reference<beans::XPropertySet>& xProp, const OUString& rName, const OUString& rDefault )
+{
+ OUString aRet = rDefault;
+ if (!xProp.is())
+ return aRet;
+
+ try
+ {
+ Any any = xProp->getPropertyValue(rName);
+ any >>= aRet;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ return aRet;
+}
+
// static
sal_Bool ScUnoHelpFunctions::GetBoolFromAny( const uno::Any& aAny )
{
@@ -180,6 +203,20 @@ void ScUnoHelpFunctions::SetBoolInAny( uno::Any& rAny, sal_Bool bValue )
rAny.setValue( &bValue, getBooleanCppuType() );
}
+// static
+void ScUnoHelpFunctions::SetOptionalPropertyValue(
+ Reference<beans::XPropertySet>& rPropSet, const sal_Char* pPropName, const Any& rVal )
+{
+ try
+ {
+ rPropSet->setPropertyValue(OUString::createFromAscii(pPropName), rVal);
+ }
+ catch (const beans::UnknownPropertyException&)
+ {
+ // ignored - not supported.
+ }
+}
+
//------------------------------------------------------------------------
ScIndexEnumeration::ScIndexEnumeration(const uno::Reference<container::XIndexAccess>& rInd,
diff --git a/sc/source/ui/unoobj/viewuno.cxx b/sc/source/ui/unoobj/viewuno.cxx
index c1af5ac9bb99..0883c24a14f0 100644
--- a/sc/source/ui/unoobj/viewuno.cxx
+++ b/sc/source/ui/unoobj/viewuno.cxx
@@ -337,11 +337,11 @@ namespace
}
// XFormLayerAccess
-uno::Reference< form::XFormController > SAL_CALL ScViewPaneBase::getFormController( const uno::Reference< form::XForm >& _Form ) throw (uno::RuntimeException)
+uno::Reference< form::runtime::XFormController > SAL_CALL ScViewPaneBase::getFormController( const uno::Reference< form::XForm >& _Form ) throw (uno::RuntimeException)
{
ScUnoGuard aGuard;
- uno::Reference< form::XFormController > xController;
+ uno::Reference< form::runtime::XFormController > xController;
Window* pWindow( NULL );
SdrView* pSdrView( NULL );
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index cf64a07a2d95..47c55350f278 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -762,7 +762,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
{
// select database range or data
pTabViewShell->GetDBData( TRUE, SC_DB_OLD );
- const ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
pTabViewShell->MarkDataArea( FALSE );
@@ -828,6 +828,19 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
ScMarkType eType = GetViewData()->GetSimpleArea(aRange);
if ( (eType & SC_MARK_SIMPLE) == SC_MARK_SIMPLE )
{
+ // Shrink the range to the data area.
+ SCCOL nStartCol = aRange.aStart.Col(), nEndCol = aRange.aEnd.Col();
+ SCROW nStartRow = aRange.aStart.Row(), nEndRow = aRange.aEnd.Row();
+ if (pDoc->ShrinkToDataArea(aRange.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow))
+ {
+ aRange.aStart.SetCol(nStartCol);
+ aRange.aStart.SetRow(nStartRow);
+ aRange.aEnd.SetCol(nEndCol);
+ aRange.aEnd.SetRow(nEndRow);
+ rMark.SetMarkArea(aRange);
+ pTabViewShell->MarkRange(aRange);
+ }
+
BOOL bOK = TRUE;
if ( pDoc->HasSubTotalCells( aRange ) )
{
diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx
index 0d44603b64f8..48b6d3ba11f7 100644
--- a/sc/source/ui/view/dbfunc.cxx
+++ b/sc/source/ui/view/dbfunc.cxx
@@ -107,14 +107,30 @@ void ScDBFunc::GotoDBArea( const String& rDBName )
// aktuellen Datenbereich fuer Sortieren / Filtern suchen
-ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode )
+ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bShrinkToData )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDBData* pData = NULL;
ScRange aRange;
ScMarkType eMarkType = GetViewData()->GetSimpleArea(aRange);
if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
+ {
+ if (bShrinkToData)
+ {
+ // Shrink the range to only include data area.
+ ScDocument* pDoc = pDocSh->GetDocument();
+ SCCOL nCol1 = aRange.aStart.Col(), nCol2 = aRange.aEnd.Col();
+ SCROW nRow1 = aRange.aStart.Row(), nRow2 = aRange.aEnd.Row();
+ if (pDoc->ShrinkToDataArea(aRange.aStart.Tab(), nCol1, nRow1, nCol2, nRow2))
+ {
+ aRange.aStart.SetCol(nCol1);
+ aRange.aEnd.SetCol(nCol2);
+ aRange.aStart.SetRow(nRow1);
+ aRange.aEnd.SetRow(nRow2);
+ }
+ }
pData = pDocSh->GetDBData( aRange, eMode, FALSE );
+ }
else if ( eMode != SC_DB_OLD )
pData = pDocSh->GetDBData(
ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index 5fd4a5f470f5..41a959409727 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -44,19 +44,17 @@
#include <vcl/waitobj.hxx>
#include <svl/zforlist.hxx>
#include <sfx2/app.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
-#include <com/sun/star/sheet/MemberResultFlags.hpp>
-
-#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
+#include <com/sun/star/sheet/GeneralFunction.hpp>
#include <com/sun/star/sheet/MemberResultFlags.hpp>
-#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
-#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
-#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
-#include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
#include "global.hxx"
#include "globstr.hrc"
@@ -81,9 +79,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;
@@ -91,7 +93,16 @@ using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
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 -----------------------------------------------------------
@@ -1351,123 +1362,323 @@ void ScDBFunc::UngroupDataPilot()
}
}
+static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName)
+{
+ sal_Int32 n = rSubtotal.getLength();
+ const sal_Unicode* p = rSubtotal.getStr();
+ OUStringBuffer aBuf, aWordBuf;
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ sal_Unicode c = p[i];
+ if (c == sal_Unicode(' '))
+ {
+ OUString aWord = aWordBuf.makeStringAndClear();
+ if (aWord.equals(rMemberName))
+ aBuf.append(sal_Unicode('?'));
+ else
+ aBuf.append(aWord);
+ aBuf.append(c);
+ }
+ else if (c == sal_Unicode('\\'))
+ {
+ // Escape a backslash character.
+ aWordBuf.append(c);
+ aWordBuf.append(c);
+ }
+ else if (c == sal_Unicode('?'))
+ {
+ // A literal '?' must be escaped with a backslash ('\');
+ aWordBuf.append(sal_Unicode('\\'));
+ aWordBuf.append(c);
+ }
+ else
+ aWordBuf.append(c);
+ }
+
+ if (aWordBuf.getLength() > 0)
+ {
+ OUString aWord = aWordBuf.makeStringAndClear();
+ if (aWord.equals(rMemberName))
+ aBuf.append(sal_Unicode('?'));
+ else
+ aBuf.append(aWord);
+ }
+
+ return aBuf.makeStringAndClear();
+}
+
void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString )
{
+ using namespace ::com::sun::star::sheet;
+
String aNewName( rString );
ScDocument* pDoc = GetViewData()->GetDocument();
ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
- if ( pDPObj )
+ if (!pDPObj)
+ return;
+
+ String aOldText;
+ pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
+
+ if ( aOldText == rString )
{
- String aOldText;
- pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
+ // nothing to do: silently exit
+ return;
+ }
+
+ USHORT nErrorId = 0;
+
+ pDPObj->BuildAllDimensionMembers();
+ ScDPSaveData aData( *pDPObj->GetSaveData() );
+ BOOL bChange = FALSE;
- if ( aOldText == rString )
+ USHORT nOrient = DataPilotFieldOrientation_HIDDEN;
+ long nField = pDPObj->GetHeaderDim( rPos, nOrient );
+ if ( nField >= 0 )
+ {
+ // changing a field title
+ if ( aData.GetExistingDimensionData() )
{
- // nothing to do: silently exit
- return;
- }
+ // only group dimensions can be renamed
- USHORT nErrorId = 0;
+ ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
+ ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
+ if ( pGroupDim )
+ {
+ // valid name: not empty, no existing dimension (group or other)
+ if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) )
+ {
+ pGroupDim->Rename( aNewName );
- ScDPSaveData aData( *pDPObj->GetSaveData() );
- BOOL bChange = FALSE;
+ // also rename in SaveData to preserve the field settings
+ ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
+ pSaveDim->SetName( aNewName );
- USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
- long nField = pDPObj->GetHeaderDim( rPos, nOrient );
- if ( nField >= 0 )
+ bChange = TRUE;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ }
+ else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
+ {
+ BOOL bDataLayout = false;
+ String aDimName = pDPObj->GetDimName(nField, bDataLayout);
+ ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
+ if (pDim)
+ {
+ if (rString.Len())
+ {
+ if (rString.EqualsIgnoreCaseAscii(aDimName))
+ {
+ pDim->RemoveLayoutName();
+ bChange = true;
+ }
+ else if (!pDPObj->IsDimNameInUse(rString))
+ {
+ pDim->SetLayoutName(rString);
+ bChange = true;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ }
+ }
+ else if (pDPObj->IsDataDescriptionCell(rPos))
+ {
+ // There is only one data dimension.
+ ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
+ if (pDim)
{
- // changing a field title
+ if (rString.Len())
+ {
+ if (rString.EqualsIgnoreCaseAscii(pDim->GetName()))
+ {
+ pDim->RemoveLayoutName();
+ bChange = true;
+ }
+ else if (!pDPObj->IsDimNameInUse(rString))
+ {
+ pDim->SetLayoutName(rString);
+ bChange = true;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ }
+ else
+ {
+ // This is not a field header.
+ sheet::DataPilotTableHeaderData aPosData;
+ pDPObj->GetHeaderPositionData(rPos, aPosData);
- if ( aData.GetExistingDimensionData() )
+ if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() )
+ {
+ if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
{
- // only group dimensions can be renamed
+ BOOL bIsDataLayout;
+ String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
- ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
+ ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
if ( pGroupDim )
{
- // valid name: not empty, no existing dimension (group or other)
- if ( aNewName.Len() && !pDPObj->IsDimNameInUse( aNewName ) )
+ // valid name: not empty, no existing group in this dimension
+ //! ignore case?
+ if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
{
- pGroupDim->Rename( aNewName );
+ ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
+ if ( pGroup )
+ pGroup->Rename( aNewName ); // rename the existing group
+ else
+ {
+ // create a new group to replace the automatic group
+ ScDPSaveGroupItem aGroup( aNewName );
+ aGroup.AddElement( aOldText );
+ pGroupDim->AddGroupItem( aGroup );
+ }
- // also rename in SaveData to preserve the field settings
- ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
- pSaveDim->SetName( aNewName );
+ // in both cases also adjust savedata, to preserve member settings (show details)
+ ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
+ ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
+ if ( pSaveMember )
+ pSaveMember->SetName( aNewName );
bChange = TRUE;
}
else
nErrorId = STR_INVALIDNAME;
- }
+ }
}
- }
- else
- {
- // renaming a group (item)?
- // allow only on the item name itself - not on empty cells, not on subtotals
-
- sheet::DataPilotTableHeaderData aPosData;
- pDPObj->GetHeaderPositionData(rPos, aPosData);
- if ( ( aPosData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
- ! ( aPosData.Flags & sheet::MemberResultFlags::SUBTOTAL ) &&
- aOldText.Len() )
+ else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL))
{
- if ( aData.GetExistingDimensionData() )
+ aData.SetGrandTotalName(rString);
+ bChange = true;
+ }
+ else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0)
+ {
+ BOOL bDataLayout = false;
+ String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout);
+ if (bDataLayout)
{
- BOOL bIsDataLayout;
- String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
+ // data dimension
+ do
+ {
+ if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
+ break;
+
+ ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
+ if (!pDim)
+ break;
+
+ if (!rString.Len())
+ {
+ nErrorId = STR_INVALIDNAME;
+ break;
+ }
- ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
- ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
- if ( pGroupDim )
+ if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
+ {
+ pDim->RemoveLayoutName();
+ bChange = true;
+ }
+ else if (!pDPObj->IsDimNameInUse(rString))
+ {
+ pDim->SetLayoutName(rString);
+ bChange = true;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ while (false);
+ }
+ else
+ {
+ // field member
+ do
{
- // valid name: not empty, no existing group in this dimension
- //! ignore case?
- if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
+ ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
+ if (!pDim)
+ break;
+
+ ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
+ if (!pMem)
+ break;
+
+ if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
{
- ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
- if ( pGroup )
- pGroup->Rename( aNewName ); // rename the existing group
- else
- {
- // create a new group to replace the automatic group
- ScDPSaveGroupItem aGroup( aNewName );
- aGroup.AddElement( aOldText );
- pGroupDim->AddGroupItem( aGroup );
- }
+ // Change subtotal only when the table has one data dimension.
+ if (aData.GetDataDimensionCount() > 1)
+ break;
+
+ // display name for subtotal is allowed only if the subtotal type is 'Automatic'.
+ if (pDim->GetSubTotalsCount() != 1)
+ break;
- // in both cases also adjust savedata, to preserve member settings (show details)
- ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
- ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
- if ( pSaveMember )
- pSaveMember->SetName( aNewName );
+ if (pDim->GetSubTotalFunc(0) != sheet::GeneralFunction_AUTO)
+ break;
- bChange = TRUE;
+ const OUString* pLayoutName = pMem->GetLayoutName();
+ String aMemberName;
+ if (pLayoutName)
+ aMemberName = *pLayoutName;
+ else
+ aMemberName = aPosData.MemberName;
+
+ String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
+ pDim->SetSubtotalName(aNew);
+ bChange = true;
}
else
- nErrorId = STR_INVALIDNAME;
+ {
+ // Check to make sure the member name isn't
+ // already used.
+ if (rString.Len())
+ {
+ if (rString.EqualsIgnoreCaseAscii(pMem->GetName()))
+ {
+ pMem->RemoveLayoutName();
+ bChange = true;
+ }
+ else if (!pDim->IsMemberNameInUse(rString))
+ {
+ pMem->SetLayoutName(rString);
+ bChange = true;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
+ else
+ nErrorId = STR_INVALIDNAME;
+ }
}
+ while (false);
}
}
}
+ }
- if ( bChange )
- {
- // apply changes
- ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
- ScDPObject* pNewObj = new ScDPObject( *pDPObj );
- pNewObj->SetSaveData( aData );
- aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE );
- delete pNewObj;
- }
- else
- {
- if ( !nErrorId )
- nErrorId = STR_ERR_DATAPILOT_INPUT;
- ErrorMessage( nErrorId );
- }
+ if ( bChange )
+ {
+ // apply changes
+ ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
+ ScDPObject* pNewObj = new ScDPObject( *pDPObj );
+ pNewObj->SetSaveData( aData );
+ aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE );
+ delete pNewObj;
+ }
+ else
+ {
+ if ( !nErrorId )
+ nErrorId = STR_ERR_DATAPILOT_INPUT;
+ ErrorMessage( nErrorId );
}
}
@@ -1484,6 +1695,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 = static_cast< sal_uInt16 >( 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;
@@ -1529,7 +1868,7 @@ BOOL ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
// get all member names in source order
uno::Sequence<rtl::OUString> aMemberNames;
- pDPObj->GetMembers( aDestData.Dimension, aMemberNames );
+ pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames );
bool bInserted = false;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index aca88c554317..7f78461aedb0 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -121,6 +121,7 @@
#include "validat.hxx"
#include "tabprotection.hxx"
#include "postit.hxx"
+#include "dpcontrol.hxx"
#include "drawview.hxx"
#include <svx/sdrpagewindow.hxx>
@@ -369,6 +370,8 @@ ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhic
pNoteMarker( NULL ),
pFilterBox( NULL ),
pFilterFloat( NULL ),
+ mpDPFieldPopup(NULL),
+ mpFilterButton(NULL),
nCursorHideCount( 0 ),
bMarking( FALSE ),
nButtonDown( 0 ),
@@ -445,14 +448,26 @@ void __EXPORT ScGridWindow::Resize( const Size& )
void ScGridWindow::ClickExtern()
{
- // #i81298# don't delete the filter box when called from its select handler
- // (possible through row header size update)
- // #i84277# when initializing the filter box, a Basic error can deactivate the view
- if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
- return;
+ do
+ {
+ // #i81298# don't delete the filter box when called from its select handler
+ // (possible through row header size update)
+ // #i84277# when initializing the filter box, a Basic error can deactivate the view
+ if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
+ {
+ break;
+ }
- DELETEZ(pFilterBox);
- DELETEZ(pFilterFloat);
+ DELETEZ(pFilterBox);
+ DELETEZ(pFilterFloat);
+ }
+ while (false);
+
+ if (mpDPFieldPopup.get())
+ {
+ mpDPFieldPopup->close(false);
+ mpDPFieldPopup.reset();
+ }
}
IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
@@ -507,7 +522,7 @@ void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, BOOL bHasSelecti
}
}
-void ScGridWindow::DoPageFieldMenue( SCCOL nCol, SCROW nRow )
+void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
{
//! merge position/size handling with DoAutoFilterMenue
@@ -658,6 +673,22 @@ void ScGridWindow::DoPageFieldMenue( SCCOL nCol, SCROW nRow )
CaptureMouse();
}
+void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
+{
+ SCTAB nTab = pViewData->GetTabNo();
+ ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
+ if (!pDPObj)
+ return;
+
+ // Get the geometry of the cell.
+ Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
+ long nSizeX, nSizeY;
+ pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
+ Size aScrSize(nSizeX-1, nSizeY-1);
+
+ DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
+}
+
void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
{
delete pFilterBox;
@@ -1619,52 +1650,8 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
if (pAttr->HasAutoFilter())
{
- Point aScrPos = pViewData->GetScrPos(nPosX,nPosY,eWhich);
- long nSizeX;
- long nSizeY;
- Point aDiffPix = aPos;
-
- aDiffPix -= aScrPos;
- BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
- if ( bLayoutRTL )
- aDiffPix.X() = -aDiffPix.X();
-
- pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
-
- // Breite des Buttons ist nicht von der Zellhoehe abhaengig
- Size aButSize = aComboButton.GetSizePixel();
- long nButWidth = Min( aButSize.Width(), nSizeX );
- long nButHeight = Min( aButSize.Height(), nSizeY );
-
- if ( aDiffPix.X() >= nSizeX - nButWidth &&
- aDiffPix.Y() >= nSizeY - nButHeight )
- {
- if ( DoPageFieldSelection( nPosX, nPosY ) )
- return;
-
- BOOL bFilterActive = IsAutoFilterActive( nPosX, nPosY,
- pViewData->GetTabNo() );
-
- aComboButton.SetOptSizePixel();
- DrawComboButton( aScrPos, nSizeX, nSizeY, bFilterActive, TRUE );
-
-#if 0
- if ( bWasFilterBox
- && (SCsCOL)nOldColFBox == nPosX
- && (SCsROW)nOldRowFBox == nPosY )
- {
- // Verhindern, dass an gleicher Stelle eine
- // FilterBox geoeffnet wird, wenn diese gerade
- // geloescht wurde
-
- nMouseStatus = SC_GM_FILTER; // fuer ButtonDraw im MouseButtonUp();
- return;
- }
-#endif
- DoAutoFilterMenue( nPosX, nPosY, FALSE );
-
+ if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
return;
- }
}
if (pAttr->HasButton())
{
@@ -1794,11 +1781,17 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
{
if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
{
- BOOL bFilterActive = IsAutoFilterActive( pFilterBox->GetCol(), pFilterBox->GetRow(),
- pViewData->GetTabNo() );
- HideCursor();
- aComboButton.Draw( bFilterActive );
- ShowCursor();
+ if (mpFilterButton.get())
+ {
+ bool bFilterActive = IsAutoFilterActive(
+ pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
+
+ mpFilterButton->setHasHiddenMember(bFilterActive);
+ mpFilterButton->setPopupPressed(false);
+ HideCursor();
+ mpFilterButton->draw();
+ ShowCursor();
+ }
}
nMouseStatus = SC_GM_NONE;
ReleaseMouse();
@@ -2218,9 +2211,14 @@ void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
nMouseStatus = SC_GM_NONE;
if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
{
- HideCursor();
- aComboButton.Draw( FALSE );
- ShowCursor();
+ if (mpFilterButton.get())
+ {
+ mpFilterButton->setHasHiddenMember(false);
+ mpFilterButton->setPopupPressed(false);
+ HideCursor();
+ mpFilterButton->draw();
+ ShowCursor();
+ }
}
ReleaseMouse();
pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx
index 643928a7c8aa..e0dd63ff090e 100644
--- a/sc/source/ui/view/gridwin2.cxx
+++ b/sc/source/ui/view/gridwin2.cxx
@@ -55,48 +55,124 @@
#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 ::com::sun::star::sheet::DataPilotFieldOrientation;
+using ::std::vector;
+using ::std::auto_ptr;
+using ::std::hash_map;
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
// STATIC DATA -----------------------------------------------------------
// -----------------------------------------------------------------------
-BOOL ScGridWindow::HasPageFieldData( SCCOL nCol, SCROW nRow ) const
+DataPilotFieldOrientation ScGridWindow::GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const
{
+ using namespace ::com::sun::star::sheet;
+
ScDocument* pDoc = pViewData->GetDocument();
SCTAB nTab = pViewData->GetTabNo();
ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
- if ( pDPObj && nCol > 0 )
+ if (!pDPObj)
+ return DataPilotFieldOrientation_HIDDEN;
+
+ USHORT nOrient = DataPilotFieldOrientation_HIDDEN;
+
+ // Check for page field first.
+ if (nCol > 0)
{
// look for the dimension header left of the drop-down arrow
- USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
- if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
+ if ( nField >= 0 && nOrient == DataPilotFieldOrientation_PAGE )
{
BOOL bIsDataLayout = FALSE;
String aFieldName = pDPObj->GetDimName( nField, bIsDataLayout );
if ( aFieldName.Len() && !bIsDataLayout )
- return TRUE;
+ return DataPilotFieldOrientation_PAGE;
}
}
- return FALSE;
+
+ nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
+
+ // Now, check for row/column field.
+ long nField = pDPObj->GetHeaderDim(ScAddress(nCol, nRow, nTab), nOrient);
+ if (nField >= 0 && (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) )
+ {
+ BOOL bIsDataLayout = FALSE;
+ String aFieldName = pDPObj->GetDimName(nField, bIsDataLayout);
+ if (aFieldName.Len() && !bIsDataLayout)
+ return static_cast<DataPilotFieldOrientation>(nOrient);
+ }
+
+ return DataPilotFieldOrientation_HIDDEN;
}
// private method for mouse button handling
BOOL ScGridWindow::DoPageFieldSelection( SCCOL nCol, SCROW nRow )
{
- if ( HasPageFieldData( nCol, nRow ) )
+ if (GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE)
{
- DoPageFieldMenue( nCol, nRow );
+ LaunchPageFieldMenu( nCol, nRow );
return TRUE;
}
return FALSE;
}
+bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
+{
+ ScDocument* pDoc = pViewData->GetDocument();
+ SCTAB nTab = pViewData->GetTabNo();
+ Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
+ Point aDiffPix = rMEvt.GetPosPixel();
+
+ aDiffPix -= aScrPos;
+ BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
+ if ( bLayoutRTL )
+ aDiffPix.X() = -aDiffPix.X();
+
+ long nSizeX, nSizeY;
+ pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
+ Size aScrSize(nSizeX-1, nSizeY-1);
+
+ // Check if the mouse cursor is clicking on the popup arrow box.
+ mpFilterButton.reset(new ScDPFieldButton(this, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY()));
+ mpFilterButton->setBoundingBox(aScrPos, aScrSize);
+ Point aPopupPos;
+ Size aPopupSize;
+ mpFilterButton->getPopupBoundingBox(aPopupPos, aPopupSize);
+ Rectangle aRec(aPopupPos, aPopupSize);
+ if (aRec.IsInside(rMEvt.GetPosPixel()))
+ {
+ if ( DoPageFieldSelection( nCol, nRow ) )
+ return true;
+
+ bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab);
+ mpFilterButton->setHasHiddenMember(bFilterActive);
+ mpFilterButton->setDrawBaseButton(false);
+ mpFilterButton->setDrawPopupButton(true);
+ mpFilterButton->setPopupPressed(true);
+ HideCursor();
+ mpFilterButton->draw();
+ ShowCursor();
+ DoAutoFilterMenue(nCol, nRow, false);
+ return true;
+ }
+
+ return false;
+}
+
void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
{
ScDocument* pDoc = pViewData->GetDocument();
@@ -114,6 +190,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();
}
@@ -282,6 +367,223 @@ 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 aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich);
+ long nSizeX, nSizeY;
+ pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
+ Size aScrSize(nSizeX-1, nSizeY-1);
+
+ // Check if the mouse cursor is clicking on the popup arrow box.
+ ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings());
+ aBtn.setBoundingBox(aScrPos, aScrSize);
+ 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(aScrPos), aScrSize, 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& rScrPos, const Size& rScrSize, 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, pViewData->GetDocument()));
+ mpDPFieldPopup->setName(OUString::createFromAscii("DataPilot field member popup"));
+ mpDPFieldPopup->setExtendedData(pDPData.release());
+ mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this));
+ {
+ // Populate field members.
+ size_t n = rLabelData.maMembers.size();
+ mpDPFieldPopup->setMemberSize(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ const ScDPLabelData::Member& rMem = rLabelData.maMembers[i];
+ mpDPFieldPopup->addMember(rMem.getDisplayName(), rMem.mbVisible);
+ }
+ 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, static_cast<sal_uInt16>(i), pViewShell));
+ }
+ }
+
+ Rectangle aCellRect(rScrPos, rScrSize);
+ const Size& rPopupSize = mpDPFieldPopup->getWindowSize();
+ if (rScrSize.getWidth() > rPopupSize.getWidth())
+ {
+ // If the cell width is larger than the popup window width, launch it
+ // right-aligned with the cell.
+ long nXOffset = rScrSize.getWidth() - rPopupSize.getWidth();
+ aCellRect.SetPos(Point(rScrPos.X() + nXOffset, rScrPos.Y()));
+ }
+ mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) );
+ mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
+}
+
+void ScGridWindow::UpdateDPFromFieldPopupMenu()
+{
+ typedef hash_map<OUString, OUString, OUStringHash> MemNameMapType;
+ typedef hash_map<OUString, bool, OUStringHash> MemVisibilityType;
+
+ 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;
+
+ // Build a map of layout names to original names.
+ const ScDPLabelData& rLabelData = *pDPData->maDPParam.maLabelArray[pDPData->mnDim];
+ MemNameMapType aMemNameMap;
+ for (vector<ScDPLabelData::Member>::const_iterator itr = rLabelData.maMembers.begin(), itrEnd = rLabelData.maMembers.end();
+ itr != itrEnd; ++itr)
+ aMemNameMap.insert(MemNameMapType::value_type(itr->maLayoutName, itr->maName));
+
+ // The raw result may contain a mixture of layout names and original names.
+ MemVisibilityType aRawResult;
+ mpDPFieldPopup->getResult(aRawResult);
+
+ MemVisibilityType aResult;
+ for (MemVisibilityType::const_iterator itr = aRawResult.begin(), itrEnd = aRawResult.end(); itr != itrEnd; ++itr)
+ {
+ MemNameMapType::const_iterator itrNameMap = aMemNameMap.find(itr->first);
+ if (itrNameMap == aMemNameMap.end())
+ // This is an original member name. Use it as-is.
+ aResult.insert(MemVisibilityType::value_type(itr->first, itr->second));
+ else
+ {
+ // This is a layout name. Get the original member name and use it.
+ aResult.insert(MemVisibilityType::value_type(itrNameMap->second, itr->second));
+ }
+ }
+ 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/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx
index 6683a75e777b..fbff54b1408f 100644..100755
--- a/sc/source/ui/view/gridwin3.cxx
+++ b/sc/source/ui/view/gridwin3.cxx
@@ -215,6 +215,7 @@ void ScGridWindow::DrawRedraw( ScOutputData& rOutputData, ScUpdateMode eMode, UL
pDrView->setHideOle(!bDrawOle);
pDrView->setHideChart(!bDrawChart);
pDrView->setHideDraw(!bDrawDraw);
+ pDrView->setHideFormControl(!bDrawDraw);
}
if(SC_UPDATE_CHANGED == eMode)
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index d700ee606731..7719dfcc5474 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 aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY());
+
SCCOL nCol;
SCROW nRow;
SCSIZE nArrY;
@@ -1284,14 +1287,14 @@ void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2
bool bArrowState = bSimpleQuery && bColumnFound;
long nSizeX;
long nSizeY;
-
pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
- aComboButton.SetOptSizePixel();
- DrawComboButton( pViewData->GetScrPos( nCol, nRow, eWhich ),
- nSizeX, nSizeY, bArrowState );
+ Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
- aComboButton.SetPosPixel( aOldPos ); // alten Zustand
- aComboButton.SetSizePixel( aOldSize ); // fuer MouseUp/Down
+ aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1));
+ aCellBtn.setDrawBaseButton(false);
+ aCellBtn.setDrawPopupButton(true);
+ aCellBtn.setHasHiddenMember(bArrowState);
+ aCellBtn.draw();
}
}
}
@@ -1318,13 +1321,14 @@ 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);
+ aCellBtn.setText(aStr);
+ aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1));
+ aCellBtn.setDrawBaseButton(true);
+ aCellBtn.setDrawPopupButton(pInfo->bPopupButton);
+ aCellBtn.setHasHiddenMember(pInfo->bFilterActive);
+ aCellBtn.draw();
}
}
}
diff --git a/sc/source/ui/view/makefile.mk b/sc/source/ui/view/makefile.mk
index d8f45c8a754f..ed50324f68be 100644
--- a/sc/source/ui/view/makefile.mk
+++ b/sc/source/ui/view/makefile.mk
@@ -140,7 +140,6 @@ SLOFILES = \
$(SLO)$/dbfunc2.obj \
$(SLO)$/tabvwsh2.obj
.ELSE
-
NOOPTFILES=\
$(SLO)$/drawview.obj \
$(SLO)$/dbfunc2.obj \
@@ -157,7 +156,8 @@ EXCEPTIONSFILES= \
$(SLO)$/cellsh1.obj \
$(SLO)$/drawvie4.obj \
$(SLO)$/formatsh.obj \
- $(SLO)$/scextopt.obj \
+ $(SLO)$/gridwin2.obj \
+ $(SLO)$/scextopt.obj \
$(SLO)$/tabvwshb.obj \
$(SLO)$/viewdata.obj \
$(SLO)$/viewfun5.obj \
diff --git a/sc/source/ui/view/olkact.cxx b/sc/source/ui/view/olkact.cxx
index 31f5297e92fe..3feb69044f43 100644
--- a/sc/source/ui/view/olkact.cxx
+++ b/sc/source/ui/view/olkact.cxx
@@ -229,7 +229,7 @@
//#define _SVDLAYER_HXX
//#define _SVDRAG_HXX
#define _SVINCVW_HXX
-#define _SV_MULTISEL_HXX
+//#define _SV_MULTISEL_HXX
#define _SVRTV_HXX
#define _SVTABBX_HXX
diff --git a/sc/source/ui/view/output3.cxx b/sc/source/ui/view/output3.cxx
index c4c51fb3f02a..ffc1112667f2 100644..100755
--- a/sc/source/ui/view/output3.cxx
+++ b/sc/source/ui/view/output3.cxx
@@ -166,7 +166,8 @@ void ScOutputData::PrintDrawingLayer(const sal_uInt16 nLayer, const Point& rMMOf
if(pLocalDrawView)
{
- bHideAllDrawingLayer = pLocalDrawView->getHideOle() && pLocalDrawView->getHideChart() && pLocalDrawView->getHideDraw();
+ bHideAllDrawingLayer = pLocalDrawView->getHideOle() && pLocalDrawView->getHideChart()
+ && pLocalDrawView->getHideDraw() && pLocalDrawView->getHideFormControl();
}
}
diff --git a/sc/source/ui/view/pfuncache.cxx b/sc/source/ui/view/pfuncache.cxx
index 4712b6a3cf85..ef014bd90f79 100644
--- a/sc/source/ui/view/pfuncache.cxx
+++ b/sc/source/ui/view/pfuncache.cxx
@@ -75,7 +75,7 @@ ScPrintFuncCache::ScPrintFuncCache( ScDocShell* pD, const ScMarkData& rMark,
long nThisTab = 0;
if ( rMark.GetTableSelect( nTab ) )
{
- ScPrintFunc aFunc( pDocSh, pPrinter, nTab, nAttrPage, 0, pSelRange );
+ ScPrintFunc aFunc( pDocSh, pPrinter, nTab, nAttrPage, 0, pSelRange, &aSelection.GetOptions() );
nThisTab = aFunc.GetTotalPages();
nFirstAttr[nTab] = aFunc.GetFirstPageNo(); // from page style or previous sheet
}
@@ -113,7 +113,7 @@ void ScPrintFuncCache::InitLocations( const ScMarkData& rMark, OutputDevice* pDe
{
if ( rMark.GetTableSelect( nTab ) )
{
- ScPrintFunc aFunc( pDev, pDocSh, nTab, nFirstAttr[nTab], nTotalPages, pSelRange );
+ ScPrintFunc aFunc( pDev, pDocSh, nTab, nFirstAttr[nTab], nTotalPages, pSelRange, &aSelection.GetOptions() );
aFunc.SetRenderFlag( TRUE );
long nDisplayStart = GetDisplayStart( nTab );
diff --git a/sc/source/ui/view/prevwsh2.cxx b/sc/source/ui/view/prevwsh2.cxx
index 58dc2d913c58..d37d0c85046d 100644
--- a/sc/source/ui/view/prevwsh2.cxx
+++ b/sc/source/ui/view/prevwsh2.cxx
@@ -67,7 +67,7 @@
//#define _FSYS_HXX
//#define _STREAM_HXX
#define _CACHESTR_HXX
-#define _SV_MULTISEL_HXX
+//#define _SV_MULTISEL_HXX
//SV
//#define _CLIP_HXX ***
diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx
index b7b8b9fbadf6..9c8b1f1d4ce6 100644..100755
--- a/sc/source/ui/view/printfun.cxx
+++ b/sc/source/ui/view/printfun.cxx
@@ -1648,7 +1648,8 @@ void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
// test if all paint parts are hidden, then a paint is not necessary at all
const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
- const bool bHideAllDrawingLayer(pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart() && pDrawView->getHideDraw());
+ const bool bHideAllDrawingLayer( pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart()
+ && pDrawView->getHideDraw() && pDrawView->getHideFormControl() );
if(!bHideAllDrawingLayer)
{
@@ -2043,7 +2044,10 @@ long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, BOOL bDoPrint, ScPr
}
if ( pPrinter && bDoPrint )
- pPrinter->StartPage();
+ {
+ DBG_ERROR( "StartPage does not exist anymore" );
+ // pPrinter->StartPage();
+ }
if ( bDoPrint || pLocationData )
{
@@ -2064,7 +2068,10 @@ long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, BOOL bDoPrint, ScPr
long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
if ( pPrinter && bDoPrint )
- pPrinter->EndPage();
+ {
+ DBG_ERROR( "EndPage does not exist anymore" );
+ // pPrinter->EndPage();
+ }
return nCount;
}
@@ -2123,10 +2130,14 @@ void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCRO
pDrawView->setHideOle(!aTableParam.bObjects);
pDrawView->setHideChart(!aTableParam.bCharts);
pDrawView->setHideDraw(!aTableParam.bDrawings);
+ pDrawView->setHideFormControl(!aTableParam.bDrawings);
}
if ( pPrinter && bDoPrint )
- pPrinter->StartPage();
+ {
+ DBG_ERROR( "StartPage does not exist anymore" );
+ // pPrinter->StartPage();
+ }
// Kopf- und Fusszeilen (ohne Zentrierung)
@@ -2408,7 +2419,10 @@ void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCRO
}
if ( pPrinter && bDoPrint )
- pPrinter->EndPage();
+ {
+ DBG_ERROR( "EndPage does not exist anymore" );
+ // pPrinter->EndPage();
+ }
aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
bSourceRangeValid = TRUE;
diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 3077e852dbaf..c076575d4e6d 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -200,6 +200,8 @@
#include "AccessibilityHints.hxx"
#include "appoptio.hxx"
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+
#include <string>
#include <algorithm>
@@ -212,6 +214,8 @@
// fuer Rad-Maus
#define SC_DELTA_ZOOM 10
+using namespace ::com::sun::star;
+
// STATIC DATA -----------------------------------------------------------
@@ -2476,7 +2480,7 @@ sal_Bool ScTabView::HasPageFieldDataAtCursor() const
SCCOL nCol = aViewData.GetCurX();
SCROW nRow = aViewData.GetCurY();
if (pWin)
- return pWin->HasPageFieldData( nCol, nRow );
+ return pWin->GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE;
return sal_False;
}
@@ -2486,15 +2490,23 @@ void ScTabView::StartDataSelect()
ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];
SCCOL nCol = aViewData.GetCurX();
SCROW nRow = aViewData.GetCurY();
- if (pWin)
- {
- // #i36598# If the cursor is on a page field's data cell,
- // no meaningful input is possible anyway, so this function
- // can be used to select a page field entry.
- if ( pWin->HasPageFieldData( nCol, nRow ) )
- pWin->DoPageFieldMenue( nCol, nRow );
- else
+ if (!pWin)
+ return;
+
+ switch (pWin->GetDPFieldOrientation(nCol, nRow))
+ {
+ case sheet::DataPilotFieldOrientation_PAGE:
+ // #i36598# If the cursor is on a page field's data cell,
+ // no meaningful input is possible anyway, so this function
+ // can be used to select a page field entry.
+ pWin->LaunchPageFieldMenu( nCol, nRow );
+ break;
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ case sheet::DataPilotFieldOrientation_ROW:
+ pWin->LaunchDPFieldMenu( nCol, nRow );
+ break;
+ default:
pWin->DoAutoFilterMenue( nCol, nRow, TRUE );
}
}
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index 3327ea3fe88d..6c0408c8c33f 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -142,7 +142,7 @@
#define _SVDRAG_HXX
#define _SVINCVW_HXX
-#define _SV_MULTISEL_HXX
+//#define _SV_MULTISEL_HXX
#define _SVRTV_HXX
#define _SVTABBX_HXX
#define _SVTREEBOX_HXX