summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/documen8.cxx10
-rw-r--r--sc/source/core/data/dpobject.cxx63
-rw-r--r--sc/source/core/data/dpoutput.cxx44
-rw-r--r--sc/source/core/data/dpoutputgeometry.cxx211
-rw-r--r--sc/source/core/data/dpsave.cxx52
-rw-r--r--sc/source/core/data/dptabsrc.cxx8
-rw-r--r--sc/source/core/data/fillinfo.cxx8
-rw-r--r--sc/source/core/data/global2.cxx49
-rw-r--r--sc/source/core/data/makefile.mk2
-rw-r--r--sc/source/core/data/pivot2.cxx9
-rw-r--r--sc/source/filter/excel/xipivot.cxx74
-rw-r--r--sc/source/filter/inc/xipivot.hxx2
-rw-r--r--sc/source/filter/xml/xmldpimp.cxx83
-rw-r--r--sc/source/filter/xml/xmldpimp.hxx26
-rw-r--r--sc/source/ui/cctrl/dpcontrol.cxx1009
-rw-r--r--sc/source/ui/cctrl/dpcontrol.src49
-rw-r--r--sc/source/ui/cctrl/makefile.mk10
-rw-r--r--sc/source/ui/dbgui/pvlaydlg.cxx35
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx4
-rw-r--r--sc/source/ui/inc/dbfunc.hxx1
-rw-r--r--sc/source/ui/inc/dpcontrol.hrc40
-rw-r--r--sc/source/ui/inc/dpcontrol.hxx289
-rw-r--r--sc/source/ui/inc/gridwin.hxx15
-rw-r--r--sc/source/ui/inc/pvlaydlg.hxx2
-rw-r--r--sc/source/ui/undo/undodat.cxx4
-rw-r--r--sc/source/ui/view/dbfunc3.cxx137
-rw-r--r--sc/source/ui/view/gridwin.cxx2
-rw-r--r--sc/source/ui/view/gridwin2.cxx202
-rw-r--r--sc/source/ui/view/gridwin4.cxx17
29 files changed, 2330 insertions, 127 deletions
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 0d12c82dec87..0bb3f96b0ca3 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -95,6 +95,7 @@
#include "globstr.hrc"
#include "sc.hrc"
#include "charthelper.hxx"
+#include "dpobject.hxx"
#define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
@@ -712,8 +713,13 @@ BOOL ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpe
// skip everything left of rSpellPos:
while ( pCell && nRow == rSpellPos.Row() && nCol < rSpellPos.Col() )
pCell = aIter.GetNext( nCol, nRow );
- while ( pCell )
+
+ for (; pCell; pCell = aIter.GetNext(nCol, nRow))
{
+ if (pDPCollection && pDPCollection->HasDPTable(nCol, nRow, nTab))
+ // Don't spell check within datapilot table.
+ continue;
+
CellType eType = pCell->GetCellType();
if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
{
@@ -798,8 +804,6 @@ BOOL ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpe
if ( ++nCellCount >= SPELL_MAXCELLS ) // seen enough cells?
break;
-
- pCell = aIter.GetNext( nCol, nRow );
}
if ( pCell )
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index cd7d58964a96..9f009c455743 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -535,6 +535,9 @@ void ScDPObject::Output()
// aOutRange is always the range that was last output to the document
aOutRange = pOutput->GetOutputRange();
+ const ScAddress& s = aOutRange.aStart;
+ const ScAddress& e = aOutRange.aEnd;
+ pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
}
const ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
@@ -1801,7 +1804,7 @@ BOOL ScDPObject::FillOldParam(ScPivotParam& rParam, BOOL bForFile) const
return TRUE;
}
-void lcl_FillLabelData( LabelData& rData, const uno::Reference< beans::XPropertySet >& xDimProp )
+void lcl_FillLabelData( ScDPLabelData& rData, const uno::Reference< beans::XPropertySet >& xDimProp )
{
uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
if ( xDimProp.is() && xDimSupp.is() )
@@ -1847,6 +1850,8 @@ void lcl_FillLabelData( LabelData& rData, const uno::Reference< beans::XProperty
BOOL ScDPObject::FillLabelData(ScPivotParam& rParam)
{
+ rParam.maLabelArray.clear();
+
((ScDPObject*)this)->CreateObjects();
uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
@@ -1857,8 +1862,6 @@ BOOL ScDPObject::FillLabelData(ScPivotParam& rParam)
if (!nDimCount)
return FALSE;
- SCSIZE nOutCount = 0;
- LabelData** aLabelArr = new LabelData*[nDimCount];
for (long nDim=0; nDim < nDimCount; nDim++)
{
String aFieldName;
@@ -1893,24 +1896,15 @@ BOOL ScDPObject::FillLabelData(ScPivotParam& rParam)
SCsCOL nCol = static_cast< SCsCOL >( nDim ); //! ???
bool bIsValue = true; //! check
- aLabelArr[nOutCount] = new LabelData( aFieldName, nCol, bIsValue );
-
- LabelData& rLabelData = *aLabelArr[nOutCount];
- GetHierarchies( nDim, rLabelData.maHiers );
- GetMembers( nDim, rLabelData.maMembers, &rLabelData.maVisible, &rLabelData.maShowDet );
- lcl_FillLabelData( rLabelData, xDimProp );
-
- ++nOutCount;
+ ScDPLabelDataRef pNewLabel(new ScDPLabelData(aFieldName, nCol, bIsValue));
+ GetHierarchies(nDim, pNewLabel->maHiers);
+ GetMembers(nDim, pNewLabel->maMembers, &pNewLabel->maVisible, &pNewLabel->maShowDet);
+ lcl_FillLabelData(*pNewLabel, xDimProp);
+ rParam.maLabelArray.push_back(pNewLabel);
}
}
}
- rParam.SetLabelData( aLabelArr, nOutCount );
-
- for (SCSIZE i=0; i<nOutCount; i++)
- delete aLabelArr[i];
- delete[] aLabelArr;
-
return TRUE;
}
@@ -2489,7 +2483,7 @@ void ScDPCollection::WriteRefsTo( ScDPCollection& r ) const
ScDPObject* pDestObj = new ScDPObject( *pSourceObj );
pDestObj->SetAlive(TRUE);
- if ( !r.Insert(pDestObj) )
+ if ( !r.InsertNewTable(pDestObj) )
{
DBG_ERROR("cannot insert DPObject");
DELETEZ( pDestObj );
@@ -2524,6 +2518,39 @@ ScSimpleSharedString& ScDPCollection::GetSharedString()
return maSharedString;
}
+void ScDPCollection::FreeTable(ScDPObject* pDPObj)
+{
+ const ScRange& rOutRange = pDPObj->GetOutRange();
+ const ScAddress& s = rOutRange.aStart;
+ const ScAddress& e = rOutRange.aEnd;
+ pDoc->RemoveFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
+ Free(pDPObj);
+}
+
+bool ScDPCollection::InsertNewTable(ScDPObject* pDPObj)
+{
+ bool bSuccess = Insert(pDPObj);
+ if (bSuccess)
+ {
+ const ScRange& rOutRange = pDPObj->GetOutRange();
+ const ScAddress& s = rOutRange.aStart;
+ const ScAddress& e = rOutRange.aEnd;
+ pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
+ }
+ return bSuccess;
+}
+
+bool ScDPCollection::HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const
+{
+ const ScMergeFlagAttr* pMergeAttr = static_cast<const ScMergeFlagAttr*>(
+ pDoc->GetAttr(nCol, nRow, nTab, ATTR_MERGE_FLAG));
+
+ if (!pMergeAttr)
+ return false;
+
+ return pMergeAttr->HasDPTable();
+}
+
ScDPCacheCell* ScDPCollection::getCacheCellFromPool(const ScDPCacheCell& rCell)
{
ScDPCacheCell aCell(rCell);
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index d376ed3cd396..325943f8b094 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -121,8 +121,13 @@ struct ScDPOutLevelData
uno::Sequence<sheet::MemberResult> aResult;
String maName; /// Name is the internal field name.
String aCaption; /// Caption is the name visible in the output table.
+ bool mbHasHiddenMember;
- ScDPOutLevelData() { nDim = nHier = nLevel = nDimPos = -1; }
+ ScDPOutLevelData()
+ {
+ nDim = nHier = nLevel = nDimPos = -1;
+ mbHasHiddenMember = false;
+ }
BOOL operator<(const ScDPOutLevelData& r) const
{ return nDimPos<r.nDimPos || ( nDimPos==r.nDimPos && nHier<r.nHier ) ||
@@ -371,6 +376,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
aStartPos( rPos ),
bDoFilter( bFilter ),
bResultsError( FALSE ),
+ mbHasDataLayout(false),
pColNumFmt( NULL ),
pRowNumFmt( NULL ),
nColFmtCount( 0 ),
@@ -415,6 +421,8 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
BOOL bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(
xDimProp,
rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ bool bHasHiddenMember = ScUnoHelpFunctions::GetBoolProperty(
+ xDimProp, OUString::createFromAscii(SC_UNO_HAS_HIDDEN_MEMBER));
if ( eDimOrient != sheet::DataPilotFieldOrientation_HIDDEN )
{
@@ -454,6 +462,8 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
OUString::createFromAscii(SC_UNO_LAYOUTNAME));
any >>= aCaption;
}
+
+ bool bRowFieldHasMember = false;
switch ( eDimOrient )
{
case sheet::DataPilotFieldOrientation_COLUMN:
@@ -464,6 +474,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
pColFields[nColFieldCount].aResult = xLevRes->getResults();
pColFields[nColFieldCount].maName = aName;
pColFields[nColFieldCount].aCaption= aCaption;
+ pColFields[nColFieldCount].mbHasHiddenMember = bHasHiddenMember;
if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult))
++nColFieldCount;
break;
@@ -475,8 +486,12 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
pRowFields[nRowFieldCount].aResult = xLevRes->getResults();
pRowFields[nRowFieldCount].maName = aName;
pRowFields[nRowFieldCount].aCaption= aCaption;
+ pRowFields[nRowFieldCount].mbHasHiddenMember = bHasHiddenMember;
if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult))
+ {
++nRowFieldCount;
+ bRowFieldHasMember = true;
+ }
break;
case sheet::DataPilotFieldOrientation_PAGE:
pPageFields[nPageFieldCount].nDim = nDim;
@@ -486,6 +501,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
pPageFields[nPageFieldCount].aResult = lcl_GetSelectedPageAsResult(xDimProp);
pPageFields[nPageFieldCount].maName = aName;
pPageFields[nPageFieldCount].aCaption= aCaption;
+ pPageFields[nPageFieldCount].mbHasHiddenMember = bHasHiddenMember;
// no check on results for page fields
++nPageFieldCount;
break;
@@ -498,6 +514,9 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
// get number formats from data dimensions
if ( bIsDataLayout )
{
+ if (bRowFieldHasMember)
+ mbHasDataLayout = true;
+
DBG_ASSERT( nLevCount == 1, "data layout: multiple levels?" );
if ( eDimOrient == sheet::DataPilotFieldOrientation_COLUMN )
lcl_FillNumberFormats( pColNumFmt, nColFmtCount, xLevRes, xDims );
@@ -658,14 +677,20 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
}
}
-void ScDPOutput::FieldCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rCaption, BOOL bFrame )
+void ScDPOutput::FieldCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rCaption,
+ bool bInTable, bool bPopup, bool bHasHiddenMember )
{
pDoc->SetString( nCol, nRow, nTab, rCaption );
- if (bFrame)
+ if (bInTable)
lcl_SetFrame( pDoc,nTab, nCol,nRow, nCol,nRow, 20 );
// Button
- pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr(SC_MF_BUTTON) );
+ sal_uInt16 nMergeFlag = SC_MF_BUTTON;
+ if (bPopup)
+ nMergeFlag |= SC_MF_BUTTON_POPUP;
+ if (bHasHiddenMember)
+ nMergeFlag |= SC_MF_HIDDEN_MEMBER;
+ pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, nMergeFlag);
lcl_SetStyleById( pDoc,nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLE_FIELDNAME );
}
@@ -673,7 +698,7 @@ void ScDPOutput::FieldCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rC
void lcl_DoFilterButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
{
pDoc->SetString( nCol, nRow, nTab, ScGlobal::GetRscString(STR_CELL_FILTER) );
- pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr(SC_MF_BUTTON) );
+ pDoc->ApplyFlagsTab(nCol, nRow, nCol, nRow, nTab, SC_MF_BUTTON);
}
void ScDPOutput::CalcSizes()
@@ -799,7 +824,7 @@ void ScDPOutput::Output()
SCCOL nHdrCol = aStartPos.Col();
SCROW nHdrRow = aStartPos.Row() + nField + ( bDoFilter ? 1 : 0 );
// draw without frame for consistency with filter button:
- FieldCell( nHdrCol, nHdrRow, nTab, pPageFields[nField].aCaption, FALSE );
+ FieldCell( nHdrCol, nHdrRow, nTab, pPageFields[nField].aCaption, false, false, pPageFields[nField].mbHasHiddenMember );
SCCOL nFldCol = nHdrCol + 1;
String aPageValue;
@@ -838,7 +863,7 @@ void ScDPOutput::Output()
for (nField=0; nField<nColFieldCount; nField++)
{
SCCOL nHdrCol = nDataStartCol + (SCCOL)nField; //! check for overflow
- FieldCell( nHdrCol, nTabStartRow, nTab, pColFields[nField].aCaption );
+ FieldCell( nHdrCol, nTabStartRow, nTab, pColFields[nField].aCaption, true, true, pColFields[nField].mbHasHiddenMember );
SCROW nRowPos = nMemberStartRow + (SCROW)nField; //! check for overflow
const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
@@ -873,9 +898,12 @@ void ScDPOutput::Output()
for (nField=0; nField<nRowFieldCount; nField++)
{
+ bool bDataLayout = mbHasDataLayout && (nField == nRowFieldCount-1);
+
SCCOL nHdrCol = nTabStartCol + (SCCOL)nField; //! check for overflow
SCROW nHdrRow = nDataStartRow - 1;
- FieldCell( nHdrCol, nHdrRow, nTab, pRowFields[nField].aCaption );
+ FieldCell( nHdrCol, nHdrRow, nTab, pRowFields[nField].aCaption, true, !bDataLayout,
+ pRowFields[nField].mbHasHiddenMember );
SCCOL nColPos = nMemberStartCol + (SCCOL)nField; //! check for overflow
const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
diff --git a/sc/source/core/data/dpoutputgeometry.cxx b/sc/source/core/data/dpoutputgeometry.cxx
new file mode 100644
index 000000000000..1b8fc0b8435f
--- /dev/null
+++ b/sc/source/core/data/dpoutputgeometry.cxx
@@ -0,0 +1,211 @@
+/*************************************************************************
+ *
+ * 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: xmldpimp.cxx,v $
+ * $Revision: 1.27.134.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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "dpoutputgeometry.hxx"
+#include "address.hxx"
+
+#include <vector>
+
+using ::std::vector;
+
+ScDPOutputGeometry::ScDPOutputGeometry(const ScRange& rOutRange, bool bShowFilter) :
+ maOutRange(rOutRange),
+ mnRowFields(0),
+ mnColumnFields(0),
+ mnPageFields(0),
+ mnDataFields(0),
+ mbShowFilter(bShowFilter)
+{
+}
+
+ScDPOutputGeometry::~ScDPOutputGeometry()
+{
+}
+
+void ScDPOutputGeometry::setRowFieldCount(sal_uInt32 nCount)
+{
+ mnRowFields = nCount;
+}
+
+void ScDPOutputGeometry::setColumnFieldCount(sal_uInt32 nCount)
+{
+ mnColumnFields = nCount;
+}
+
+void ScDPOutputGeometry::setPageFieldCount(sal_uInt32 nCount)
+{
+ mnPageFields = nCount;
+}
+
+void ScDPOutputGeometry::setDataFieldCount(sal_uInt32 nCount)
+{
+ mnDataFields = nCount;
+}
+
+void ScDPOutputGeometry::getColumnFieldPositions(vector<ScAddress>& rAddrs) const
+{
+ vector<ScAddress> aAddrs;
+ if (!mnColumnFields)
+ {
+ rAddrs.swap(aAddrs);
+ return;
+ }
+
+ bool bDataLayout = mnDataFields > 1;
+
+ SCROW nCurRow = maOutRange.aStart.Row();
+
+ if (mnPageFields)
+ {
+ SCROW nRowStart = maOutRange.aStart.Row() + mbShowFilter;
+ SCROW nRowEnd = nRowStart + static_cast<SCCOL>(mnPageFields-1);
+ nCurRow = nRowEnd + 2;
+ }
+ else if (mbShowFilter)
+ nCurRow += 2;
+
+ SCROW nRow = nCurRow;
+ SCTAB nTab = maOutRange.aStart.Tab();
+ SCCOL nColStart = maOutRange.aStart.Col() + mnRowFields + bDataLayout;
+ SCCOL nColEnd = nColStart + static_cast<SCCOL>(mnColumnFields-1);
+
+ for (SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
+ aAddrs.push_back(ScAddress(nCol, nRow, nTab));
+ rAddrs.swap(aAddrs);
+}
+
+void ScDPOutputGeometry::getRowFieldPositions(vector<ScAddress>& rAddrs) const
+{
+ vector<ScAddress> aAddrs;
+ if (!mnRowFields)
+ {
+ rAddrs.swap(aAddrs);
+ return;
+ }
+
+ SCROW nCurRow = maOutRange.aStart.Row();
+
+ if (mnPageFields)
+ {
+ SCROW nRowStart = maOutRange.aStart.Row() + mbShowFilter;
+ SCROW nRowEnd = nRowStart + static_cast<SCCOL>(mnPageFields-1);
+ nCurRow = nRowEnd + 2;
+ }
+ else if (mbShowFilter)
+ nCurRow += 2;
+
+ if (mnColumnFields)
+ nCurRow += static_cast<SCROW>(mnColumnFields);
+ else
+ ++nCurRow;
+
+ SCROW nRow = nCurRow;
+ SCTAB nTab = maOutRange.aStart.Tab();
+ SCCOL nColStart = maOutRange.aStart.Col();
+ SCCOL nColEnd = nColStart + static_cast<SCCOL>(mnRowFields-1);
+
+ for (SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
+ aAddrs.push_back(ScAddress(nCol, nRow, nTab));
+ rAddrs.swap(aAddrs);
+}
+
+void ScDPOutputGeometry::getPageFieldPositions(vector<ScAddress>& rAddrs) const
+{
+ vector<ScAddress> aAddrs;
+ if (!mnPageFields)
+ {
+ rAddrs.swap(aAddrs);
+ return;
+ }
+
+ SCTAB nTab = maOutRange.aStart.Tab();
+ SCCOL nCol = maOutRange.aStart.Col();
+
+ SCROW nRowStart = maOutRange.aStart.Row() + mbShowFilter;
+ SCROW nRowEnd = nRowStart + static_cast<SCCOL>(mnPageFields-1);
+
+ for (SCROW nRow = nRowStart; nRow <= nRowEnd; ++nRow)
+ aAddrs.push_back(ScAddress(nCol, nRow, nTab));
+ rAddrs.swap(aAddrs);
+}
+
+ScDPOutputGeometry::FieldType ScDPOutputGeometry::getFieldButtonType(const ScAddress& rPos) const
+{
+ // We will ignore the table position for now.
+
+ bool bExtraTitleRow = (mnColumnFields == 0);
+ bool bDataLayout = mnDataFields > 1;
+
+ SCROW nCurRow = maOutRange.aStart.Row();
+
+ if (mnPageFields)
+ {
+ SCCOL nCol = maOutRange.aStart.Col();
+ SCROW nRowStart = maOutRange.aStart.Row() + mbShowFilter;
+ SCROW nRowEnd = nRowStart + static_cast<SCCOL>(mnPageFields-1);
+ if (rPos.Col() == nCol && nRowStart <= rPos.Row() && rPos.Row() <= nRowEnd)
+ return Page;
+
+ nCurRow = nRowEnd + 2;
+ }
+ else if (mbShowFilter)
+ nCurRow += 2;
+
+ if (mnColumnFields)
+ {
+ SCROW nRow = nCurRow;
+ SCCOL nColStart = maOutRange.aStart.Col() + mnRowFields + bDataLayout;
+ SCCOL nColEnd = nColStart + static_cast<SCCOL>(mnColumnFields-1);
+ if (rPos.Row() == nRow && nColStart <= rPos.Col() && rPos.Col() <= nColEnd)
+ return Column;
+
+ nCurRow += static_cast<SCROW>(mnColumnFields);
+ }
+
+ if (bExtraTitleRow)
+ ++nCurRow;
+
+ if (mnRowFields)
+ {
+ SCCOL nColStart = maOutRange.aStart.Col();
+ SCCOL nColEnd = nColStart + static_cast<SCCOL>(mnRowFields-1);
+ if (rPos.Row() == nCurRow && nColStart <= rPos.Col() && rPos.Col() <= nColEnd)
+ return Row;
+ }
+
+ return None;
+}
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index ba1acc97a83a..cc564457761f 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -62,6 +62,7 @@
using namespace com::sun::star;
using ::rtl::OUString;
+using ::rtl::OUStringHash;
using ::std::hash_map;
using ::std::auto_ptr;
@@ -642,6 +643,8 @@ void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xD
nHierCount = xHiers->getCount();
}
+ sal_Bool bHasHiddenMember = false;
+
for (long nHier=0; nHier<nHierCount; nHier++)
{
uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
@@ -734,12 +737,15 @@ void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xD
for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
{
- rtl::OUString aMemberName = (*i)->GetName();
+ ScDPSaveMember* pMember = *i;
+ if (!pMember->GetIsVisible())
+ bHasHiddenMember = true;
+ rtl::OUString aMemberName = pMember->GetName();
if ( xMembers->hasByName( aMemberName ) )
{
uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
xMembers->getByName( aMemberName ) );
- (*i)->WriteToSource( xMemberInt, nPosition );
+ pMember->WriteToSource( xMemberInt, nPosition );
if ( nPosition >= 0 )
++nPosition; // increase if initialized
@@ -751,6 +757,40 @@ void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xD
}
}
}
+
+ if (xDimProp.is())
+ {
+ uno::Any any;
+ any <<= bHasHiddenMember;
+ xDimProp->setPropertyValue(
+ OUString::createFromAscii(SC_UNO_HAS_HIDDEN_MEMBER), any);
+ }
+}
+
+void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
+{
+ typedef hash_map<OUString, bool, OUStringHash> DataMap;
+ MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
+ for (; itrMem != itrMemEnd; ++itrMem)
+ {
+ ScDPSaveMember* pMem = *itrMem;
+ const String& rMemName = pMem->GetName();
+ DataMap::const_iterator itr = rData.find(rMemName);
+ if (itr != rData.end())
+ pMem->SetIsVisible(itr->second);
+ }
+}
+
+bool ScDPSaveDimension::HasInvisibleMember() const
+{
+ MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
+ for (; itrMem != itrMemEnd; ++itrMem)
+ {
+ const ScDPSaveMember* pMem = *itrMem;
+ if (!pMem->GetIsVisible())
+ return true;
+ }
+ return false;
}
// -----------------------------------------------------------------------
@@ -1304,3 +1344,11 @@ void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
mbDimensionMembersBuilt = true;
}
+bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
+{
+ ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
+ if (!pDim)
+ return false;
+
+ return pDim->HasInvisibleMember();
+}
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index bc1394307f26..927035af62c9 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -1375,7 +1375,8 @@ ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
mpSubtotalName(NULL),
nSourceDim( -1 ),
bHasSelectedPage( FALSE ),
- pSelectedData( NULL )
+ pSelectedData( NULL ),
+ mbHasHiddenMember(false)
{
//! hold pSource
}
@@ -1571,6 +1572,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetIn
{MAP_CHAR_LEN(SC_UNO_USEDHIER), 0, &getCppuType((sal_Int32*)0), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_HAS_HIDDEN_MEMBER), 0, &getBooleanCppuType(), 0, 0 },
{0,0,0,0,0,0}
};
static uno::Reference<beans::XPropertySetInfo> aRef =
@@ -1653,6 +1655,8 @@ void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyNam
if (aValue >>= aTmpName)
mpSubtotalName.reset(new OUString(aTmpName));
}
+ else if (aNameStr.EqualsAscii(SC_UNO_HAS_HIDDEN_MEMBER))
+ aValue >>= mbHasHiddenMember;
else
{
DBG_ERROR("unknown property");
@@ -1716,6 +1720,8 @@ uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropert
aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString::createFromAscii("");
else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString::createFromAscii("");
+ else if (aNameStr.EqualsAscii(SC_UNO_HAS_HIDDEN_MEMBER))
+ aRet <<= mbHasHiddenMember;
else
{
DBG_ERROR("unknown property");
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index c8eba91d2cc1..ac4cb9908a3f 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -332,6 +332,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
pInfo->bVOverlapped = FALSE;
pInfo->bAutoFilter = FALSE;
pInfo->bPushButton = FALSE;
+ pInfo->bPopupButton = false;
+ pInfo->bFilterActive = false;
pInfo->nRotateDir = SC_ROTDIR_NONE;
pInfo->bPrinted = FALSE; // view-intern
@@ -458,6 +460,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
BOOL bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0);
BOOL bPushButton = ((nOverlap & SC_MF_BUTTON) != 0);
BOOL bScenario = ((nOverlap & SC_MF_SCENARIO) != 0);
+ bool bPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0);
+ bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0);
if (bMerged||bHOverlapped||bVOverlapped)
bAnyMerged = TRUE; // intern
@@ -498,6 +502,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
pInfo->bVOverlapped = bVOverlapped;
pInfo->bAutoFilter = bAutoFilter;
pInfo->bPushButton = bPushButton;
+ pInfo->bPopupButton = bPopupButton;
+ pInfo->bFilterActive = bFilterActive;
pInfo->pLinesAttr = pLinesAttr;
pInfo->mpTLBRLine = pTLBRLine;
pInfo->mpBLTRLine = pBLTRLine;
@@ -512,7 +518,7 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
nCurRow >= aEmbedRange.aStart.Row() &&
nCurRow <= aEmbedRange.aEnd.Row();
- if (bPushButton || bScenario)
+ if (bScenario)
{
pInfo->pBackground = ScGlobal::GetButtonBrushItem();
pThisRowInfo->bEmptyBack = FALSE;
diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx
index c352dbb550d6..a6122c274d0d 100644
--- a/sc/source/core/data/global2.cxx
+++ b/sc/source/core/data/global2.cxx
@@ -56,6 +56,7 @@
#include "sc.hrc"
#include "globstr.hrc"
+using ::std::vector;
// -----------------------------------------------------------------------
@@ -817,7 +818,6 @@ bool PivotField::operator==( const PivotField& r ) const
ScPivotParam::ScPivotParam()
: nCol(0), nRow(0), nTab(0),
- ppLabelArr( NULL ), nLabels(0),
nPageCount(0), nColCount(0), nRowCount(0), nDataCount(0),
bIgnoreEmptyRows(FALSE), bDetectCategories(FALSE),
bMakeTotalCol(TRUE), bMakeTotalRow(TRUE)
@@ -828,23 +828,22 @@ ScPivotParam::ScPivotParam()
ScPivotParam::ScPivotParam( const ScPivotParam& r )
: nCol( r.nCol ), nRow( r.nRow ), nTab( r.nTab ),
- ppLabelArr( NULL ), nLabels(0),
nPageCount(0), nColCount(0), nRowCount(0), nDataCount(0),
bIgnoreEmptyRows(r.bIgnoreEmptyRows),
bDetectCategories(r.bDetectCategories),
bMakeTotalCol(r.bMakeTotalCol),
bMakeTotalRow(r.bMakeTotalRow)
{
- SetLabelData ( r.ppLabelArr, r.nLabels );
SetPivotArrays ( r.aPageArr, r.aColArr, r.aRowArr, r.aDataArr,
r.nPageCount, r.nColCount, r.nRowCount, r.nDataCount );
+
+ SetLabelData(r.maLabelArray);
}
//------------------------------------------------------------------------
__EXPORT ScPivotParam::~ScPivotParam()
{
- ClearLabelData();
}
//------------------------------------------------------------------------
@@ -856,26 +855,10 @@ void __EXPORT ScPivotParam::Clear()
nTab = 0;
bIgnoreEmptyRows = bDetectCategories = FALSE;
bMakeTotalCol = bMakeTotalRow = TRUE;
- ClearLabelData();
ClearPivotArrays();
+ maLabelArray.clear();
}
-//------------------------------------------------------------------------
-
-void __EXPORT ScPivotParam::ClearLabelData()
-{
- if ( (nLabels > 0) && ppLabelArr )
- {
- for ( SCSIZE i=0; i<nLabels; i++ )
- delete ppLabelArr[i];
- delete [] ppLabelArr;
- ppLabelArr = NULL;
- nLabels = 0;
- }
-}
-
-//------------------------------------------------------------------------
-
void __EXPORT ScPivotParam::ClearPivotArrays()
{
memset( aPageArr, 0, PIVOT_MAXPAGEFIELD * sizeof(PivotField) );
@@ -888,20 +871,17 @@ void __EXPORT ScPivotParam::ClearPivotArrays()
nDataCount = 0;
}
-//------------------------------------------------------------------------
-
-void __EXPORT ScPivotParam::SetLabelData( LabelData** pLabArr,
- SCSIZE nLab )
+void ScPivotParam::SetLabelData(const vector<ScDPLabelDataRef>& r)
{
- ClearLabelData();
-
- if ( (nLab > 0) && pLabArr )
+ vector<ScDPLabelDataRef> aNewArray;
+ aNewArray.reserve(r.size());
+ for (vector<ScDPLabelDataRef>::const_iterator itr = r.begin(), itrEnd = r.end();
+ itr != itrEnd; ++itr)
{
- nLabels = (nLab>MAX_LABELS) ? MAX_LABELS : nLab;
- ppLabelArr = new LabelData*[nLabels];
- for ( SCSIZE i=0; i<nLabels; i++ )
- ppLabelArr[i] = new LabelData( *(pLabArr[i]) );
+ ScDPLabelDataRef p(new ScDPLabelData(**itr));
+ aNewArray.push_back(p);
}
+ maLabelArray.swap(aNewArray);
}
//------------------------------------------------------------------------
@@ -943,10 +923,9 @@ ScPivotParam& __EXPORT ScPivotParam::operator=( const ScPivotParam& r )
bMakeTotalCol = r.bMakeTotalCol;
bMakeTotalRow = r.bMakeTotalRow;
- SetLabelData ( r.ppLabelArr, r.nLabels );
SetPivotArrays ( r.aPageArr, r.aColArr, r.aRowArr, r.aDataArr,
r.nPageCount, r.nColCount, r.nRowCount, r.nDataCount );
-
+ SetLabelData(r.maLabelArray);
return *this;
}
@@ -961,7 +940,7 @@ BOOL __EXPORT ScPivotParam::operator==( const ScPivotParam& r ) const
&& (bDetectCategories == r.bDetectCategories)
&& (bMakeTotalCol == r.bMakeTotalCol)
&& (bMakeTotalRow == r.bMakeTotalRow)
- && (nLabels == r.nLabels)
+ && (maLabelArray.size() == r.maLabelArray.size())
&& (nPageCount == r.nPageCount)
&& (nColCount == r.nColCount)
&& (nRowCount == r.nRowCount)
diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk
index 7129198c204f..603d3b5832a4 100644
--- a/sc/source/core/data/makefile.mk
+++ b/sc/source/core/data/makefile.mk
@@ -78,6 +78,7 @@ SLOFILES = \
$(SLO)$/dpgroup.obj \
$(SLO)$/dpobject.obj \
$(SLO)$/dpoutput.obj \
+ $(SLO)$/dpoutputgeometry.obj \
$(SLO)$/dpsave.obj \
$(SLO)$/dpsdbtab.obj \
$(SLO)$/dpshttab.obj \
@@ -137,6 +138,7 @@ EXCEPTIONSFILES= \
$(SLO)$/dpsdbtab.obj \
$(SLO)$/dpobject.obj \
$(SLO)$/dpoutput.obj \
+ $(SLO)$/dpoutputgeometry.obj \
$(SLO)$/dpsave.obj \
$(SLO)$/dbdocutl.obj \
$(SLO)$/dptabsrc.obj \
diff --git a/sc/source/core/data/pivot2.cxx b/sc/source/core/data/pivot2.cxx
index 20303f848b72..e96bb25c011d 100644
--- a/sc/source/core/data/pivot2.cxx
+++ b/sc/source/core/data/pivot2.cxx
@@ -158,12 +158,7 @@ void ScPivot::SetJustifyRight(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
void ScPivot::SetButton(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
{
- if (pDoc->pTab[nDestTab])
- {
- ScPatternAttr aPattern( pDoc->GetPool() );
- aPattern.GetItemSet().Put( ScMergeFlagAttr(SC_MF_BUTTON) );
- pDoc->pTab[nDestTab]->ApplyPatternArea(nCol1, nRow1, nCol2, nRow2, aPattern);
- }
+ pDoc->ApplyFlagsTab(nCol1, nRow1, nCol2, nRow2, nDestTab, SC_MF_BUTTON);
}
void ScPivot::SetStyle(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USHORT nId)
@@ -492,7 +487,7 @@ ScDataObject* ScPivotCollection::Clone() const
// ============================================================================
-LabelData::LabelData( const String& rName, short nCol, bool bIsValue ) :
+ScDPLabelData::ScDPLabelData( const String& rName, short nCol, bool bIsValue ) :
maName( rName ),
mnCol( nCol ),
mnFuncMask( PIVOT_FUNC_NONE ),
diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx
index fd7622cce7c0..7ec0e5d2a694 100644
--- a/sc/source/filter/excel/xipivot.cxx
+++ b/sc/source/filter/excel/xipivot.cxx
@@ -48,7 +48,9 @@
#include "dpdimsave.hxx"
#include "dpobject.hxx"
#include "dpshttab.hxx"
+#include "dpoutputgeometry.hxx"
#include "scitems.hxx"
+#include "attrib.hxx"
#include "xltracer.hxx"
#include "xistream.hxx"
@@ -60,6 +62,8 @@
#include "excform.hxx"
#include "xltable.hxx"
+#include <vector>
+
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::sheet::DataPilotFieldOrientation;
@@ -68,6 +72,7 @@ using ::com::sun::star::sheet::DataPilotFieldSortInfo;
using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
using ::com::sun::star::sheet::DataPilotFieldReference;
+using ::std::vector;
// ============================================================================
// Pivot cache
@@ -1418,8 +1423,10 @@ void XclImpPivotTable::Convert()
pDPObj->SetAlive( TRUE );
pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 );
- GetDoc().GetDPCollection()->Insert( pDPObj );
+ GetDoc().GetDPCollection()->InsertNewTable(pDPObj);
mpDPObj = pDPObj;
+
+ ApplyMergeFlags(aOutRange, aSaveData);
}
void XclImpPivotTable::MaybeRefresh()
@@ -1432,6 +1439,71 @@ void XclImpPivotTable::MaybeRefresh()
}
}
+void XclImpPivotTable::ApplyMergeFlags(const ScRange& rOutRange, const ScDPSaveData& rSaveData)
+{
+ // Apply merge flags for varoius datapilot controls.
+
+ ScDPOutputGeometry aGeometry(rOutRange, false);
+ aGeometry.setColumnFieldCount(maPTInfo.mnColFields);
+ aGeometry.setPageFieldCount(maPTInfo.mnPageFields);
+ aGeometry.setDataFieldCount(maPTInfo.mnDataFields);
+
+ // Excel includes data layout field in the row field count. We need to
+ // subtract it.
+ bool bDataLayout = maPTInfo.mnDataFields > 1;
+ aGeometry.setRowFieldCount(maPTInfo.mnRowFields - static_cast<sal_uInt32>(bDataLayout));
+
+ ScDocument& rDoc = GetDoc();
+
+ vector<ScAddress> aPageBtns;
+ aGeometry.getPageFieldPositions(aPageBtns);
+ vector<ScAddress>::const_iterator itr = aPageBtns.begin(), itrEnd = aPageBtns.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ sal_uInt16 nMFlag = SC_MF_BUTTON;
+ String aName;
+ rDoc.GetString(itr->Col(), itr->Row(), itr->Tab(), aName);
+ if (rSaveData.HasInvisibleMember(aName))
+ nMFlag |= SC_MF_HIDDEN_MEMBER;
+
+ rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
+ rDoc.ApplyFlagsTab(itr->Col()+1, itr->Row(), itr->Col()+1, itr->Row(), itr->Tab(), SC_MF_AUTO);
+ }
+
+ vector<ScAddress> aColBtns;
+ aGeometry.getColumnFieldPositions(aColBtns);
+ itr = aColBtns.begin();
+ itrEnd = aColBtns.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ sal_Int16 nMFlag = SC_MF_BUTTON | SC_MF_BUTTON_POPUP;
+ String aName;
+ rDoc.GetString(itr->Col(), itr->Row(), itr->Tab(), aName);
+ if (rSaveData.HasInvisibleMember(aName))
+ nMFlag |= SC_MF_HIDDEN_MEMBER;
+ rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
+ }
+
+ vector<ScAddress> aRowBtns;
+ aGeometry.getRowFieldPositions(aRowBtns);
+ itr = aRowBtns.begin();
+ itrEnd = aRowBtns.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ sal_Int16 nMFlag = SC_MF_BUTTON | SC_MF_BUTTON_POPUP;
+ String aName;
+ rDoc.GetString(itr->Col(), itr->Row(), itr->Tab(), aName);
+ if (rSaveData.HasInvisibleMember(aName))
+ nMFlag |= SC_MF_HIDDEN_MEMBER;
+ rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), nMFlag);
+ }
+ if (bDataLayout)
+ {
+ --itr; // move back to the last row field position.
+ rDoc.ApplyFlagsTab(itr->Col(), itr->Row(), itr->Col(), itr->Row(), itr->Tab(), SC_MF_BUTTON);
+ }
+}
+
// ============================================================================
// ============================================================================
diff --git a/sc/source/filter/inc/xipivot.hxx b/sc/source/filter/inc/xipivot.hxx
index 15227b8fb1a3..9e0e577b1756 100644
--- a/sc/source/filter/inc/xipivot.hxx
+++ b/sc/source/filter/inc/xipivot.hxx
@@ -363,6 +363,8 @@ public:
void MaybeRefresh();
+ void ApplyMergeFlags(const ScRange& rOutRange, const ScDPSaveData& rSaveData);
+
// ------------------------------------------------------------------------
private:
typedef ::std::vector< XclImpPTFieldRef > XclImpPTFieldVec;
diff --git a/sc/source/filter/xml/xmldpimp.cxx b/sc/source/filter/xml/xmldpimp.cxx
index 9cdca232c25a..0a990416006e 100644
--- a/sc/source/filter/xml/xmldpimp.cxx
+++ b/sc/source/filter/xml/xmldpimp.cxx
@@ -48,6 +48,7 @@
#include "dpgroup.hxx"
#include "dpdimsave.hxx"
#include "rangeutl.hxx"
+#include "dpoutputgeometry.hxx"
#include <xmloff/xmltkmap.hxx>
#include <xmloff/nmspmap.hxx>
@@ -131,6 +132,10 @@ ScXMLDataPilotTableContext::ScXMLDataPilotTableContext( ScXMLImport& rImport,
sDataPilotTableName(),
sApplicationData(),
sGrandTotal(GetXMLToken(XML_BOTH)),
+ mnRowFieldCount(0),
+ mnColFieldCount(0),
+ mnPageFieldCount(0),
+ mnDataFieldCount(0),
bIsNative(sal_True),
bIgnoreEmptyRows(sal_False),
bIdentifyCategories(sal_False),
@@ -280,6 +285,12 @@ SvXMLImportContext *ScXMLDataPilotTableContext::CreateChildContext( USHORT nPref
void ScXMLDataPilotTableContext::SetButtons()
{
+ ScDPOutputGeometry aGeometry(aTargetRangeAddress, bShowFilter);
+ aGeometry.setColumnFieldCount(mnColFieldCount);
+ aGeometry.setRowFieldCount(mnRowFieldCount);
+ aGeometry.setPageFieldCount(mnPageFieldCount);
+ aGeometry.setDataFieldCount(mnDataFieldCount);
+
OUString sAddress;
sal_Int32 nOffset = 0;
while( nOffset >= 0 )
@@ -291,8 +302,21 @@ void ScXMLDataPilotTableContext::SetButtons()
sal_Int32 nAddrOffset(0);
if (pDoc && ScRangeStringConverter::GetAddressFromString( aScAddress, sAddress, pDoc, ::formula::FormulaGrammar::CONV_OOO, nAddrOffset ))
{
- ScMergeFlagAttr aAttr( SC_MF_BUTTON );
- pDoc->ApplyAttr( aScAddress.Col(), aScAddress.Row(), aScAddress.Tab(), aAttr );
+ ScDPOutputGeometry::FieldType eType = aGeometry.getFieldButtonType(aScAddress);
+
+ sal_Int16 nMFlag = SC_MF_BUTTON;
+ if (eType == ScDPOutputGeometry::Column || eType == ScDPOutputGeometry::Row)
+ nMFlag |= SC_MF_BUTTON_POPUP;
+
+ // Use the cell's string value to see if this field contains a
+ // hidden member. Isn't there a better way? GetString() is
+ // quite expensive...
+ String aCellStr;
+ pDoc->GetString(aScAddress.Col(), aScAddress.Row(), aScAddress.Tab(), aCellStr);
+ if (maHiddenMemberFields.count(aCellStr))
+ nMFlag |= SC_MF_HIDDEN_MEMBER;
+
+ pDoc->ApplyFlagsTab(aScAddress.Col(), aScAddress.Row(), aScAddress.Col(), aScAddress.Row(), aScAddress.Tab(), nMFlag);
}
}
}
@@ -301,7 +325,7 @@ void ScXMLDataPilotTableContext::SetButtons()
pDPObject->RefreshAfterLoad();
}
-void ScXMLDataPilotTableContext::AddDimension(ScDPSaveDimension* pDim)
+void ScXMLDataPilotTableContext::AddDimension(ScDPSaveDimension* pDim, bool bHasHiddenMember)
{
if (pDPSave)
{
@@ -311,6 +335,30 @@ void ScXMLDataPilotTableContext::AddDimension(ScDPSaveDimension* pDim)
pDPSave->GetExistingDimensionByName(pDim->GetName()) )
pDim->SetDupFlag( TRUE );
+ if (!pDim->IsDataLayout())
+ {
+ switch (pDim->GetOrientation())
+ {
+ case sheet::DataPilotFieldOrientation_ROW:
+ ++mnRowFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ ++mnColFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_PAGE:
+ ++mnPageFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_DATA:
+ ++mnDataFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_HIDDEN:
+ default:
+ ;
+ }
+
+ if (bHasHiddenMember)
+ maHiddenMemberFields.insert(pDim->GetName());
+ }
pDPSave->AddDimension(pDim);
}
}
@@ -405,7 +453,7 @@ void ScXMLDataPilotTableContext::EndElement()
{
ScDPCollection* pDPCollection = pDoc->GetDPCollection();
pDPObject->SetAlive(sal_True);
- pDPCollection->Insert(pDPObject);
+ pDPCollection->InsertNewTable(pDPObject);
}
SetButtons();
}
@@ -833,7 +881,8 @@ ScXMLDataPilotFieldContext::ScXMLDataPilotFieldContext( ScXMLImport& rImport,
bIsGroupField(sal_False),
bDateValue(sal_False),
bAutoStart(sal_False),
- bAutoEnd(sal_False)
+ bAutoEnd(sal_False),
+ mbHasHiddenMember(false)
{
sal_Bool bHasName(sal_False);
sal_Bool bDataLayout(sal_False);
@@ -928,6 +977,22 @@ SvXMLImportContext *ScXMLDataPilotFieldContext::CreateChildContext( USHORT nPref
return pContext;
}
+void ScXMLDataPilotFieldContext::AddMember(ScDPSaveMember* pMember)
+{
+ if (pDim)
+ pDim->AddMember(pMember);
+
+ if (!pMember->GetIsVisible())
+ // This member is hidden.
+ mbHasHiddenMember = true;
+}
+
+void ScXMLDataPilotFieldContext::SetSubTotalName(const OUString& rName)
+{
+ if (pDim)
+ pDim->SetSubtotalName(rName);
+}
+
void ScXMLDataPilotFieldContext::AddGroup(const ::std::vector<rtl::OUString>& rMembers, const rtl::OUString& rName)
{
ScXMLDataPilotGroup aGroup;
@@ -948,7 +1013,7 @@ void ScXMLDataPilotFieldContext::EndElement()
String sPage(sSelectedPage);
pDim->SetCurrentPage(&sPage);
}
- pDataPilotTable->AddDimension(pDim);
+ pDataPilotTable->AddDimension(pDim, mbHasHiddenMember);
if (bIsGroupField)
{
ScDPNumGroupInfo aInfo;
@@ -995,12 +1060,6 @@ void ScXMLDataPilotFieldContext::EndElement()
}
}
-void ScXMLDataPilotFieldContext::SetSubTotalName(const OUString& rName)
-{
- if (pDim)
- pDim->SetSubtotalName(rName);
-}
-
ScXMLDataPilotFieldReferenceContext::ScXMLDataPilotFieldReferenceContext( ScXMLImport& rImport, USHORT nPrfx,
const ::rtl::OUString& rLName,
const uno::Reference<xml::sax::XAttributeList>& xAttrList,
diff --git a/sc/source/filter/xml/xmldpimp.hxx b/sc/source/filter/xml/xmldpimp.hxx
index fee4e36c02e5..50dc7e6d9c0d 100644
--- a/sc/source/filter/xml/xmldpimp.hxx
+++ b/sc/source/filter/xml/xmldpimp.hxx
@@ -41,6 +41,8 @@
#include "dpobject.hxx"
#include "dpsave.hxx"
+#include <hash_set>
+
class ScXMLImport;
class ScDPSaveNumGroupDimension;
class ScDPSaveGroupDimension;
@@ -79,6 +81,9 @@ public:
class ScXMLDataPilotTableContext : public SvXMLImportContext
{
+ typedef ::std::hash_set< ::rtl::OUString, ::rtl::OUStringHash > StringSet;
+ StringSet maHiddenMemberFields;
+
struct GrandTotalItem
{
::rtl::OUString maDisplayName;
@@ -108,6 +113,10 @@ class ScXMLDataPilotTableContext : public SvXMLImportContext
ScAddress aFilterOutputPosition;
ScQueryParam aSourceQueryParam;
ScMySourceType nSourceType;
+ sal_uInt32 mnRowFieldCount;
+ sal_uInt32 mnColFieldCount;
+ sal_uInt32 mnPageFieldCount;
+ sal_uInt32 mnDataFieldCount;
sal_Bool bIsNative;
sal_Bool bIgnoreEmptyRows;
sal_Bool bIdentifyCategories;
@@ -156,7 +165,7 @@ public:
void SetFilterSourceRange(const ScRange& aValue) { aFilterSourceRange = aValue; }
// void SetFilterIsCaseSensitive(const sal_Bool bValue) { aSourceQueryParam.bCaseSens = bValue; }
// void SetFilterSkipDuplicates(const sal_Bool bValue) { aSourceQueryParam.bDuplicate = !bValue; }
- void AddDimension(ScDPSaveDimension* pDim);
+ void AddDimension(ScDPSaveDimension* pDim, bool bHasHiddenMember);
void AddGroupDim(const ScDPSaveNumGroupDimension& aNumGroupDim);
void AddGroupDim(const ScDPSaveGroupDimension& aGroupDim);
void SetButtons();
@@ -337,12 +346,13 @@ class ScXMLDataPilotFieldContext : public SvXMLImportContext
sal_Int32 nGroupPart;
sal_Int16 nFunction;
sal_Int16 nOrientation;
- sal_Bool bShowEmpty;
- sal_Bool bSelectedPage;
- sal_Bool bIsGroupField;
- sal_Bool bDateValue;
- sal_Bool bAutoStart;
- sal_Bool bAutoEnd;
+ sal_Bool bShowEmpty:1;
+ sal_Bool bSelectedPage:1;
+ sal_Bool bIsGroupField:1;
+ sal_Bool bDateValue:1;
+ sal_Bool bAutoStart:1;
+ sal_Bool bAutoEnd:1;
+ bool mbHasHiddenMember:1;
const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
@@ -366,8 +376,8 @@ public:
void SetShowEmpty(const sal_Bool bValue) { if (pDim) pDim->SetShowEmpty(bValue); }
void SetSubTotals(const sal_uInt16* pFunctions, const sal_Int16 nCount) { if(pDim) pDim->SetSubTotals(nCount, pFunctions); }
+ void AddMember(ScDPSaveMember* pMember);
void SetSubTotalName(const ::rtl::OUString& rName);
- void AddMember(ScDPSaveMember* pMember) { if (pDim) pDim->AddMember(pMember); }
void SetFieldReference(const com::sun::star::sheet::DataPilotFieldReference& aRef) { if (pDim) pDim->SetReferenceValue(&aRef); }
void SetAutoShowInfo(const com::sun::star::sheet::DataPilotFieldAutoShowInfo& aInfo) { if (pDim) pDim->SetAutoShowInfo(&aInfo); }
void SetSortInfo(const com::sun::star::sheet::DataPilotFieldSortInfo& aInfo) { if (pDim) pDim->SetSortInfo(&aInfo); }
diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx
new file mode 100644
index 000000000000..d6aa21ab79bb
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.cxx
@@ -0,0 +1,1009 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.hxx,v $
+ * $Revision: 1.115.36.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "dpcontrol.hxx"
+
+#include "vcl/outdev.hxx"
+#include "vcl/settings.hxx"
+#include "vcl/wintypes.hxx"
+#include "vcl/decoview.hxx"
+
+#define MENU_NOT_SELECTED 999
+
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
+using ::std::vector;
+using ::std::hash_map;
+
+ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle) :
+ mpOutDev(pOutDev),
+ mpStyle(pStyle),
+ mbPopupButton(false),
+ mbHasHiddenMember(false)
+{
+}
+
+ScDPFieldButton::~ScDPFieldButton()
+{
+}
+
+void ScDPFieldButton::setText(const OUString& rText)
+{
+ maText = rText;
+}
+
+void ScDPFieldButton::setBoundingBox(const Point& rPos, const Size& rSize)
+{
+ maPos = rPos;
+ maSize = rSize;
+}
+
+void ScDPFieldButton::setDrawPopupButton(bool b)
+{
+ mbPopupButton = b;
+}
+
+void ScDPFieldButton::setHasHiddenMember(bool b)
+{
+ mbHasHiddenMember = b;
+}
+
+void ScDPFieldButton::draw()
+{
+ const long nMargin = 2;
+
+ // Background
+ Rectangle aRect(maPos, maSize);
+ mpOutDev->SetLineColor(mpStyle->GetFaceColor());
+ mpOutDev->SetFillColor(mpStyle->GetFaceColor());
+ mpOutDev->DrawRect(aRect);
+
+ // Border lines
+ mpOutDev->SetLineColor(mpStyle->GetLightColor());
+ mpOutDev->DrawLine(Point(maPos), Point(maPos.X(), maPos.Y()+maSize.Height()-1));
+ mpOutDev->DrawLine(Point(maPos), Point(maPos.X()+maSize.Width()-1, maPos.Y()));
+
+ mpOutDev->SetLineColor(mpStyle->GetShadowColor());
+ mpOutDev->DrawLine(Point(maPos.X(), maPos.Y()+maSize.Height()-1),
+ Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
+ mpOutDev->DrawLine(Point(maPos.X()+maSize.Width()-1, maPos.Y()),
+ Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
+
+ // Field name
+ Font aTextFont( mpStyle->GetLabelFont() );
+ aTextFont.SetHeight(12);
+ mpOutDev->SetFont(aTextFont);
+
+ Point aTextPos = maPos;
+ long nTHeight = mpOutDev->GetTextHeight();
+ aTextPos.setX(maPos.getX() + nMargin);
+ aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
+ mpOutDev->DrawText(aTextPos, maText);
+
+ if (mbPopupButton)
+ drawPopupButton();
+}
+
+void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
+{
+ long nW = maSize.getWidth()*0.5;
+ long nH = maSize.getHeight();
+ if (nW > 16)
+ nW = 16;
+ if (nH > 18)
+ nH = 18;
+
+ rPos.setX(maPos.getX() + maSize.getWidth() - nW);
+ rPos.setY(maPos.getY() + maSize.getHeight() - nH);
+ rSize.setWidth(nW);
+ rSize.setHeight(nH);
+}
+
+bool ScDPFieldButton::isPopupButton() const
+{
+ return mbPopupButton;
+}
+
+void ScDPFieldButton::drawPopupButton()
+{
+ Point aPos;
+ Size aSize;
+ getPopupBoundingBox(aPos, aSize);
+
+ // border lines
+ mpOutDev->SetLineColor(mpStyle->GetLightColor());
+ mpOutDev->DrawLine(aPos, Point(aPos.X(), aPos.Y()+aSize.Height()-1));
+ mpOutDev->DrawLine(aPos, Point(aPos.X()+aSize.Width()-1, aPos.Y()));
+
+ mpOutDev->SetLineColor(mpStyle->GetShadowColor());
+ mpOutDev->DrawLine(Point(aPos.X(), aPos.Y()+aSize.Height()-1),
+ Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
+ mpOutDev->DrawLine(Point(aPos.X()+aSize.Width()-1, aPos.Y()),
+ Point(aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-1));
+
+ // the arrowhead
+ Color aArrowColor = mbHasHiddenMember ? mpStyle->GetHighlightLinkColor() : mpStyle->GetButtonTextColor();
+ mpOutDev->SetLineColor(aArrowColor);
+ mpOutDev->SetFillColor(aArrowColor);
+ Point aCenter(aPos.X() + (aSize.Width() >> 1), aPos.Y() + (aSize.Height() >> 1));
+ Point aPos1, aPos2;
+ aPos1.X() = aCenter.X() - 4;
+ aPos2.X() = aCenter.X() + 4;
+ aPos1.Y() = aCenter.Y() - 3;
+ aPos2.Y() = aCenter.Y() - 3;
+
+ do
+ {
+ ++aPos1.X();
+ --aPos2.X();
+ ++aPos1.Y();
+ ++aPos2.Y();
+ mpOutDev->DrawLine(aPos1, aPos2);
+ }
+ while (aPos1 != aPos2);
+
+ if (mbHasHiddenMember)
+ {
+ // tiny little box to display in presence of hidden member(s).
+ Point aBoxPos(aPos.X() + aSize.Width() - 5, aPos.Y() + aSize.Height() - 5);
+ Size aBoxSize(3, 3);
+ mpOutDev->DrawRect(Rectangle(aBoxPos, aBoxSize));
+ }
+}
+
+// ============================================================================
+
+ScMenuFloatingWindow::MenuItem::MenuItem() :
+ mbEnabled(true),
+ mpAction(static_cast<ScDPFieldPopupWindow::Action*>(NULL)),
+ mpSubMenuWin(static_cast<ScMenuFloatingWindow*>(NULL))
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::SubMenuItem::SubMenuItem(ScMenuFloatingWindow* pParent) :
+ mpSubMenu(NULL),
+ mnMenuPos(MENU_NOT_SELECTED),
+ mpParent(pParent)
+{
+ maTimer.SetTimeoutHdl( LINK(this, ScMenuFloatingWindow::SubMenuItem, TimeoutHdl) );
+ maTimer.SetTimeout(mpParent->GetSettings().GetMouseSettings().GetMenuDelay());
+}
+
+void ScMenuFloatingWindow::SubMenuItem::reset()
+{
+ mpSubMenu = NULL;
+ mnMenuPos = MENU_NOT_SELECTED;
+ maTimer.Stop();
+}
+
+IMPL_LINK( ScMenuFloatingWindow::SubMenuItem, TimeoutHdl, void*, EMPTYARG )
+{
+ mpParent->handleMenuTimeout(this);
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+ScMenuFloatingWindow::ScMenuFloatingWindow(Window* pParent) :
+ FloatingWindow(pParent, (WB_SYSTEMFLOATWIN|WB_SYSTEMWINDOW|WB_NOBORDER)),
+ maOpenTimer(this),
+ maCloseTimer(this),
+ mnSelectedMenu(MENU_NOT_SELECTED),
+ mnClickedMenu(MENU_NOT_SELECTED),
+ mpParentMenu(dynamic_cast<ScMenuFloatingWindow*>(pParent)),
+ mpActiveSubMenu(NULL),
+ mbActionFired(false)
+{
+ // TODO: How do we get the right font to use here ?
+ const sal_uInt16 nPopupFontHeight = 12;
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ maLabelFont = rStyle.GetLabelFont();
+ maLabelFont.SetHeight(nPopupFontHeight);
+ SetFont(maLabelFont);
+
+ SetPopupModeEndHdl( LINK(this, ScMenuFloatingWindow, EndPopupHdl) );
+}
+
+ScMenuFloatingWindow::~ScMenuFloatingWindow()
+{
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ size_t nSelectedMenu = getEnclosingMenuItem(rPos);
+ setSelectedMenuItem(nSelectedMenu);
+
+ Window::MouseMove(rMEvt);
+}
+
+void ScMenuFloatingWindow::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ const Point& rPos = rMEvt.GetPosPixel();
+ mnClickedMenu = getEnclosingMenuItem(rPos);
+ Window::MouseButtonDown(rMEvt);
+}
+
+void ScMenuFloatingWindow::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ executeMenu(mnClickedMenu);
+ mnClickedMenu = MENU_NOT_SELECTED;
+ Window::MouseButtonUp(rMEvt);
+}
+
+void ScMenuFloatingWindow::KeyInput(const KeyEvent& rKEvt)
+{
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ bool bHandled = true;
+ size_t nSelectedMenu = mnSelectedMenu;
+ size_t nLastMenuPos = maMenuItems.size() - 1;
+ switch (rKeyCode.GetCode())
+ {
+ case KEY_UP:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == 0)
+ nSelectedMenu = nLastMenuPos;
+ else
+ --nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false);
+ break;
+ case KEY_DOWN:
+ if (nSelectedMenu == MENU_NOT_SELECTED || nSelectedMenu == nLastMenuPos)
+ nSelectedMenu = 0;
+ else
+ ++nSelectedMenu;
+ setSelectedMenuItem(nSelectedMenu, false);
+ break;
+ case KEY_LEFT:
+ if (mpParentMenu)
+ mpParentMenu->endSubMenu();
+ break;
+ case KEY_RIGHT:
+ {
+ if (mnSelectedMenu >= maMenuItems.size() || mnSelectedMenu == MENU_NOT_SELECTED)
+ break;
+
+ const MenuItem& rMenu = maMenuItems[mnSelectedMenu];
+ if (!rMenu.mbEnabled || !rMenu.mpSubMenuWin)
+ break;
+
+ maOpenTimer.mnMenuPos = mnSelectedMenu;
+ maOpenTimer.mpSubMenu = rMenu.mpSubMenuWin.get();
+ launchSubMenu(true);
+ }
+ break;
+ case KEY_RETURN:
+ if (nSelectedMenu != MENU_NOT_SELECTED)
+ executeMenu(nSelectedMenu);
+ break;
+ default:
+ bHandled = false;
+ }
+
+ if (!bHandled)
+ Window::KeyInput(rKEvt);
+}
+
+void ScMenuFloatingWindow::Paint(const Rectangle& /*rRect*/)
+{
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ Color aBorderColor = rStyle.GetShadowColor();
+
+ Rectangle aCtrlRect(Point(0, 0), GetOutputSizePixel());
+
+ // Window background
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ SetClipRegion();
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ SetFillColor(aBackColor);
+ SetLineColor(aBorderColor);
+ DrawRect(aCtrlRect);
+ }
+
+ // Menu items
+ SetTextColor(rStyle.GetMenuTextColor());
+ drawAllMenuItems();
+}
+
+void ScMenuFloatingWindow::addMenuItem(const OUString& rText, bool bEnabled, Action* pAction)
+{
+ MenuItem aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpAction.reset(pAction);
+ maMenuItems.push_back(aItem);
+}
+
+ScMenuFloatingWindow* ScMenuFloatingWindow::addSubMenuItem(const OUString& rText, bool bEnabled)
+{
+ MenuItem aItem;
+ aItem.maText = rText;
+ aItem.mbEnabled = bEnabled;
+ aItem.mpSubMenuWin.reset(new ScMenuFloatingWindow(this));
+ maMenuItems.push_back(aItem);
+ return aItem.mpSubMenuWin.get();
+}
+
+void ScMenuFloatingWindow::drawMenuItem(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nPos);
+
+ DecorationView aDecoView(this);
+ long nXOffset = 5;
+ long nYOffset = (aSize.Height() - maLabelFont.GetHeight())/2;
+ DrawCtrlText(Point(aPos.X()+nXOffset, aPos.Y() + nYOffset), maMenuItems[nPos].maText, 0, STRING_LEN,
+ maMenuItems[nPos].mbEnabled ? TEXT_DRAW_MNEMONIC : TEXT_DRAW_DISABLE);
+
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ long nFontHeight = maLabelFont.GetHeight();
+ Point aMarkerPos = aPos;
+ aMarkerPos.Y() += aSize.Height()/2 - nFontHeight/4 + 1;
+ aMarkerPos.X() += aSize.Width() - nFontHeight + nFontHeight/4;
+ Size aMarkerSize(nFontHeight/2, nFontHeight/2);
+ aDecoView.DrawSymbol(Rectangle(aMarkerPos, aMarkerSize),
+ SYMBOL_SPIN_RIGHT, GetTextColor(), 0);
+ }
+}
+
+void ScMenuFloatingWindow::drawAllMenuItems()
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ highlightMenuItem(i, i == mnSelectedMenu);
+}
+
+const Font& ScMenuFloatingWindow::getLabelFont() const
+{
+ return maLabelFont;
+}
+
+void ScMenuFloatingWindow::executeMenu(size_t nPos)
+{
+ if (nPos >= maMenuItems.size())
+ return;
+
+ if (!maMenuItems[nPos].mpAction)
+ // no action is defined.
+ return;
+
+ maMenuItems[nPos].mpAction->execute();
+ mbActionFired = true;
+ EndPopupMode();
+}
+
+void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer)
+{
+ if (mnSelectedMenu != nPos)
+ {
+ selectMenuItem(mnSelectedMenu, false, bSubMenuTimer);
+ selectMenuItem(nPos, true, bSubMenuTimer);
+ mnSelectedMenu = nPos;
+ }
+}
+
+size_t ScMenuFloatingWindow::getSelectedMenuItem() const
+{
+ return mnSelectedMenu;
+}
+
+void ScMenuFloatingWindow::handleMenuTimeout(SubMenuItem* pTimer)
+{
+ if (pTimer == &maOpenTimer)
+ {
+ // Close any open submenu immediately.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+ maCloseTimer.maTimer.Stop();
+ }
+
+ launchSubMenu(false);
+ }
+ else if (pTimer == &maCloseTimer)
+ {
+ // end submenu.
+ if (maCloseTimer.mpSubMenu)
+ {
+ maOpenTimer.mpSubMenu = NULL;
+
+ maCloseTimer.mpSubMenu->EndPopupMode();
+ maCloseTimer.mpSubMenu = NULL;
+
+ highlightMenuItem(maOpenTimer.mnMenuPos, false);
+ maOpenTimer.mnMenuPos = MENU_NOT_SELECTED;
+ }
+ }
+}
+
+void ScMenuFloatingWindow::queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu)
+{
+ if (!pMenu)
+ return;
+
+ // Set the submenu on launch queue.
+ if (maOpenTimer.mpSubMenu)
+ {
+ if (maOpenTimer.mpSubMenu == pMenu)
+ {
+ if (pMenu == maCloseTimer.mpSubMenu)
+ maCloseTimer.reset();
+ return;
+ }
+
+ // new submenu is being requested.
+ queueCloseSubMenu();
+ }
+
+ maOpenTimer.mpSubMenu = pMenu;
+ maOpenTimer.mnMenuPos = nPos;
+ maOpenTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::queueCloseSubMenu()
+{
+ if (!maOpenTimer.mpSubMenu)
+ // There is no submenu to close.
+ return;
+
+ // Stop any submenu on queue for opening.
+ maOpenTimer.maTimer.Stop();
+
+ maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu;
+ maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos;
+ maCloseTimer.maTimer.Start();
+}
+
+void ScMenuFloatingWindow::launchSubMenu(bool bSetMenuPos)
+{
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, maOpenTimer.mnMenuPos);
+ ScMenuFloatingWindow* pSubMenu = maOpenTimer.mpSubMenu;
+
+ if (!pSubMenu)
+ return;
+
+ sal_uInt32 nOldFlags = GetPopupModeFlags();
+ SetPopupModeFlags(nOldFlags | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE);
+ pSubMenu->resetMenu(bSetMenuPos);
+ pSubMenu->StartPopupMode(
+ Rectangle(aPos,aSize), (FLOATWIN_POPUPMODE_RIGHT | FLOATWIN_POPUPMODE_GRABFOCUS));
+ pSubMenu->AddPopupModeWindow(this);
+ SetPopupModeFlags(nOldFlags);
+}
+
+void ScMenuFloatingWindow::endSubMenu()
+{
+ if (maOpenTimer.mpSubMenu)
+ {
+ maOpenTimer.mpSubMenu->EndPopupMode();
+ maOpenTimer.mpSubMenu = NULL;
+ highlightMenuItem(maOpenTimer.mnMenuPos, true);
+ }
+}
+
+void ScMenuFloatingWindow::notify(NotificationType eType)
+{
+ switch (eType)
+ {
+ case SUBMENU_FOCUSED:
+ // Cancel any request for ending submenu.
+ maCloseTimer.reset();
+ if (mnSelectedMenu != maOpenTimer.mnMenuPos)
+ {
+ highlightMenuItem(maOpenTimer.mnMenuPos, true);
+ mnSelectedMenu = maOpenTimer.mnMenuPos;
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void ScMenuFloatingWindow::resetMenu(bool bSetMenuPos)
+{
+ mnSelectedMenu = bSetMenuPos ? 0 : MENU_NOT_SELECTED;
+ resizeToFitMenuItems();
+}
+
+void ScMenuFloatingWindow::resizeToFitMenuItems()
+{
+ if (maMenuItems.empty())
+ return;
+
+ vector<MenuItem>::const_iterator itr = maMenuItems.begin(), itrEnd = maMenuItems.end();
+ long nTextWidth = 0;
+ for (; itr != itrEnd; ++itr)
+ nTextWidth = ::std::max(GetTextWidth(itr->maText), nTextWidth);
+
+ size_t nLastPos = maMenuItems.size()-1;
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nLastPos);
+ aPos.X() += nTextWidth + 15;
+ aPos.Y() += aSize.Height() + 5;
+ SetOutputSizePixel(Size(aPos.X(), aPos.Y()));
+}
+
+void ScMenuFloatingWindow::selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer)
+{
+ if (nPos >= maMenuItems.size() || nPos == MENU_NOT_SELECTED)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ if (!maMenuItems[nPos].mbEnabled)
+ {
+ queueCloseSubMenu();
+ return;
+ }
+
+ highlightMenuItem(nPos, bSelected);
+
+ if (bSelected)
+ {
+ if (mpParentMenu)
+ mpParentMenu->notify(SUBMENU_FOCUSED);
+
+ if (bSubMenuTimer)
+ {
+ if (maMenuItems[nPos].mpSubMenuWin)
+ {
+ ScMenuFloatingWindow* pSubMenu = maMenuItems[nPos].mpSubMenuWin.get();
+ queueLaunchSubMenu(nPos, pSubMenu);
+ }
+ else
+ queueCloseSubMenu();
+ }
+ }
+}
+
+void ScMenuFloatingWindow::highlightMenuItem(size_t nPos, bool bSelected)
+{
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aBackColor = rStyle.GetMenuColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, nPos);
+ Region aRegion(Rectangle(aPos,aSize));
+
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
+ {
+ Push(PUSH_CLIPREGION);
+ IntersectClipRegion(Rectangle(aPos, aSize));
+ Rectangle aCtrlRect(Point(0,0), GetOutputSizePixel());
+ DrawNativeControl(
+ CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, Region(aCtrlRect), CTRL_STATE_ENABLED,
+ ImplControlValue(), OUString());
+
+ Pop();
+ }
+
+ bool bNativeDrawn = true;
+ if (IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
+ {
+ ControlState nState = bSelected ? CTRL_STATE_SELECTED : 0;
+ if (maMenuItems[nPos].mbEnabled)
+ nState |= CTRL_STATE_ENABLED;
+ bNativeDrawn = DrawNativeControl(
+ CTRL_MENU_POPUP, PART_MENU_ITEM, aRegion, nState, ImplControlValue(), OUString());
+ }
+ else
+ bNativeDrawn = false;
+
+ if (!bNativeDrawn)
+ {
+ if (bSelected)
+ {
+ aBackColor = rStyle.GetMenuHighlightColor();
+ SetFillColor(aBackColor);
+ SetLineColor(aBackColor);
+ }
+ DrawRect(Rectangle(aPos,aSize));
+ }
+
+ Color aTextColor = bSelected ? rStyle.GetMenuHighlightTextColor() : rStyle.GetMenuTextColor();
+ SetTextColor(aTextColor);
+ drawMenuItem(nPos);
+}
+
+void ScMenuFloatingWindow::getMenuItemPosSize(Point& rPos, Size& rSize, size_t nPos) const
+{
+ const sal_uInt16 nLeftMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuItemHeight = maLabelFont.GetHeight()*1.8;
+
+ Size aWndSize = GetSizePixel();
+
+ Point aPos1(nLeftMargin, nTopMargin);
+ Size aSize1(aWndSize.Width() - nLeftMargin*2, nMenuItemHeight);
+
+ rPos = aPos1;
+ rPos.Y() += aSize1.Height()*nPos;
+ rSize = aSize1;
+}
+
+size_t ScMenuFloatingWindow::getEnclosingMenuItem(const Point& rPos) const
+{
+ size_t n = maMenuItems.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ Point aPos;
+ Size aSize;
+ getMenuItemPosSize(aPos, aSize, i);
+ Rectangle aRect(aPos, aSize);
+ if (aRect.IsInside(rPos))
+ return i;
+ }
+ return MENU_NOT_SELECTED;
+}
+
+IMPL_LINK( ScMenuFloatingWindow, EndPopupHdl, void*, EMPTYARG )
+{
+ if (mbActionFired && mpParentMenu)
+ mpParentMenu->EndPopupMode();
+
+ return 0;
+}
+
+// ============================================================================
+
+ScDPFieldPopupWindow::Member::Member() :
+ mbVisible(true)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScDPFieldPopupWindow::CancelButton::CancelButton(ScDPFieldPopupWindow* pParent) :
+ ::CancelButton(pParent), mpParent(pParent) {}
+
+void ScDPFieldPopupWindow::CancelButton::Click()
+{
+ mpParent->EndPopupMode();
+ ::CancelButton::Click();
+}
+
+// ----------------------------------------------------------------------------
+
+ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent) :
+ ScMenuFloatingWindow(pParent),
+ maCheck0(this, 0),
+ maCheck1(this, 0),
+ maCheck2(this, 0),
+ maCheck3(this, 0),
+ maCheck4(this, 0),
+ maCheck5(this, 0),
+ maCheck6(this, 0),
+ maCheck7(this, 0),
+ maCheck8(this, 0),
+ maCheck9(this, 0),
+ maScrollBar(this, WB_VERT),
+ maBtnOk(this),
+ maBtnCancel(this),
+ mpExtendedData(NULL),
+ mpOKAction(NULL),
+ mnScrollPos(0)
+{
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, WHOLE);
+ SetOutputSizePixel(aSize);
+ Size aOutSize = GetOutputSizePixel();
+
+ mpCheckPtr.reserve(10);
+ mpCheckPtr.push_back(&maCheck0);
+ mpCheckPtr.push_back(&maCheck1);
+ mpCheckPtr.push_back(&maCheck2);
+ mpCheckPtr.push_back(&maCheck3);
+ mpCheckPtr.push_back(&maCheck4);
+ mpCheckPtr.push_back(&maCheck5);
+ mpCheckPtr.push_back(&maCheck6);
+ mpCheckPtr.push_back(&maCheck7);
+ mpCheckPtr.push_back(&maCheck8);
+ mpCheckPtr.push_back(&maCheck9);
+
+ getSectionPosSize(aPos, aSize, FIRST_LISTITEM);
+ for (vector<CheckBox*>::iterator itr = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
+ itr != itrEnd; ++itr)
+ {
+ CheckBox* p = *itr;
+ p->SetPosSizePixel(aPos, aSize);
+ p->SetFont(getLabelFont());
+ p->SetClickHdl( LINK(this, ScDPFieldPopupWindow, CheckBoxHdl) );
+ aPos.Y() += aSize.Height() + 1;
+ }
+
+ getSectionPosSize(aPos, aSize, BTN_OK);
+ maBtnOk.SetPosSizePixel(aPos, aSize);
+ maBtnOk.SetFont(getLabelFont());
+ maBtnOk.SetClickHdl( LINK(this, ScDPFieldPopupWindow, OKButtonHdl) );
+ maBtnOk.Show();
+
+ getSectionPosSize(aPos, aSize, BTN_CANCEL);
+ maBtnCancel.SetPosSizePixel(aPos, aSize);
+ maBtnCancel.SetFont(getLabelFont());
+ maBtnCancel.Show();
+
+ getSectionPosSize(aPos, aSize, SCROLL_BAR_V);
+ maScrollBar.SetPosSizePixel(aPos, aSize);
+ maScrollBar.SetPageSize(mpCheckPtr.size());
+ maScrollBar.SetVisibleSize(mpCheckPtr.size());
+ maScrollBar.SetLineSize(1);
+ maScrollBar.SetScrollHdl( LINK(this, ScDPFieldPopupWindow, ScrollHdl) );
+ maScrollBar.EnableDrag(true);
+}
+
+ScDPFieldPopupWindow::~ScDPFieldPopupWindow()
+{
+}
+
+vector<ScDPFieldPopupWindow::Member>& ScDPFieldPopupWindow::getMembers()
+{
+ return maMembers;
+}
+
+void ScDPFieldPopupWindow::getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const
+{
+ const sal_uInt16 nListBoxMargin = 5;
+ const sal_uInt16 nTopMargin = 5;
+ const sal_uInt16 nMenuHeight = 60;
+ const sal_uInt16 nBottomBtnAreaHeight = 50;
+ const sal_uInt16 nInnerItemMargin = 5;
+ const sal_uInt16 nScrollBarWidth = 17;
+ const sal_uInt16 nBtnWidth = 60;
+ const sal_uInt16 nBtnHeight = getLabelFont().GetHeight()*2;
+ const sal_uInt16 nBottomMargin = 10;
+ const sal_uInt16 nMenuListMargin = 20;
+
+ Size aWndSize = Size(160, 330);
+
+ switch (eType)
+ {
+ case WHOLE:
+ {
+ rPos = Point(0, 0);
+ rSize = aWndSize;
+ }
+ break;
+ case LISTBOX_AREA:
+ {
+ rPos = Point(nListBoxMargin, nTopMargin + nMenuHeight + nMenuListMargin);
+ rSize = Size(
+ aWndSize.Width() - nListBoxMargin*2,
+ aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight);
+ }
+ break;
+ case FIRST_LISTITEM:
+ {
+ rPos = Point(nListBoxMargin + nInnerItemMargin,
+ nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin);
+ rSize = Size(
+ aWndSize.Width() - nListBoxMargin*2 - nInnerItemMargin - nScrollBarWidth - 10,
+ 17);
+ }
+ break;
+ case BTN_OK:
+ {
+ long x = (aWndSize.Width() - nBtnWidth*2)/3;
+ long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ case BTN_CANCEL:
+ {
+ long x = (aWndSize.Width() - nBtnWidth*2)/3*2 + nBtnWidth;
+ long y = aWndSize.Height() - nBottomMargin - nBtnHeight;
+ rPos = Point(x, y);
+ rSize = Size(nBtnWidth, nBtnHeight);
+ }
+ break;
+ case SCROLL_BAR_V:
+ {
+ long x = aWndSize.Width() - nListBoxMargin - nInnerItemMargin - nScrollBarWidth;
+ long y = nTopMargin + nMenuHeight + nMenuListMargin + nInnerItemMargin;
+ rPos = Point(x, y);
+ long h = aWndSize.Height() - nTopMargin - nMenuHeight - nMenuListMargin - nBottomBtnAreaHeight - nInnerItemMargin*2;
+ rSize = Size(nScrollBarWidth, h);
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void ScDPFieldPopupWindow::resetDisplayedItems()
+{
+ long nScrollPos = maScrollBar.GetThumbPos();
+ if (nScrollPos < 0)
+ return;
+
+ mnScrollPos = static_cast<size_t>(nScrollPos);
+ size_t nCheckCount = mpCheckPtr.size();
+ for (size_t i = 0; i < nCheckCount; ++i)
+ {
+ CheckBox* p = mpCheckPtr[i];
+ p->SetText(maMembers[i+mnScrollPos].maName);
+ TriState nNewState = maMembers[i+mnScrollPos].mbVisible ? STATE_CHECK : STATE_NOCHECK;
+ p->SetState(nNewState);
+ }
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, CheckBoxHdl, CheckBox*, pCheck )
+{
+ vector<CheckBox*>::const_iterator itr, itrBeg = mpCheckPtr.begin(), itrEnd = mpCheckPtr.end();
+ for (itr = itrBeg; itr != itrEnd; ++itr)
+ {
+ if (*itr == pCheck)
+ {
+ size_t nIndex = ::std::distance(itrBeg, itr);
+ maMembers[nIndex+mnScrollPos].mbVisible = !maMembers[nIndex+mnScrollPos].mbVisible;
+ }
+ }
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, OKButtonHdl, OKButton*, EMPTYARG )
+{
+ close(true);
+ return 0;
+}
+
+IMPL_LINK( ScDPFieldPopupWindow, ScrollHdl, ScrollBar*, EMPTYARG )
+{
+ resetDisplayedItems();
+ return 0;
+}
+
+void ScDPFieldPopupWindow::MouseMove(const MouseEvent& rMEvt)
+{
+ ScMenuFloatingWindow::MouseMove(rMEvt);
+
+ size_t nSelectedMenu = getSelectedMenuItem();
+ if (nSelectedMenu == MENU_NOT_SELECTED)
+ queueCloseSubMenu();
+}
+
+void ScDPFieldPopupWindow::Paint(const Rectangle& rRect)
+{
+ ScMenuFloatingWindow::Paint(rRect);
+
+ const StyleSettings& rStyle = GetSettings().GetStyleSettings();
+ Color aMemberBackColor = rStyle.GetFieldColor();
+
+ // Member list box background
+ SetFillColor(aMemberBackColor);
+ Point aPos;
+ Size aSize;
+ getSectionPosSize(aPos, aSize, LISTBOX_AREA);
+ DrawRect(Rectangle(aPos,aSize));
+}
+
+void ScDPFieldPopupWindow::setMemberSize(size_t n)
+{
+ maMembers.reserve(n);
+}
+
+void ScDPFieldPopupWindow::addMember(const OUString& rName, bool bVisible)
+{
+ Member aMember;
+ aMember.maName = rName;
+ aMember.mbVisible = bVisible;
+ maMembers.push_back(aMember);
+}
+
+void ScDPFieldPopupWindow::initMembers()
+{
+ size_t nMemCount = maMembers.size();
+ size_t nCheckCount = mpCheckPtr.size();
+ bool bNeedsScroll = false;
+ if (nMemCount > nCheckCount)
+ {
+ nMemCount = nCheckCount;
+ bNeedsScroll = true;
+ }
+
+ for (size_t i = 0; i < nMemCount; ++i)
+ {
+ CheckBox* p = mpCheckPtr[i];
+ p->SetText(maMembers[i].maName);
+ p->Show();
+ p->SetState(maMembers[i].mbVisible ? STATE_CHECK : STATE_NOCHECK);
+ }
+ if (bNeedsScroll)
+ {
+ maScrollBar.SetRange(Range(0, maMembers.size()));
+ maScrollBar.Show();
+ }
+}
+
+void ScDPFieldPopupWindow::getResult(hash_map<OUString, bool, OUStringHash>& rResult)
+{
+ typedef hash_map<OUString, bool, OUStringHash> ResultMap;
+ ResultMap aResult;
+ vector<Member>::const_iterator itr = maMembers.begin(), itrEnd = maMembers.end();
+ for (; itr != itrEnd; ++itr)
+ aResult.insert(ResultMap::value_type(itr->maName, itr->mbVisible));
+ rResult.swap(aResult);
+}
+
+void ScDPFieldPopupWindow::close(bool bOK)
+{
+ if (bOK && mpOKAction.get())
+ mpOKAction->execute();
+
+ EndPopupMode();
+}
+
+void ScDPFieldPopupWindow::setExtendedData(ExtendedData* p)
+{
+ mpExtendedData.reset(p);
+}
+
+ScDPFieldPopupWindow::ExtendedData* ScDPFieldPopupWindow::getExtendedData()
+{
+ return mpExtendedData.get();
+}
+
+void ScDPFieldPopupWindow::setOKAction(Action* p)
+{
+ mpOKAction.reset(p);
+}
+
diff --git a/sc/source/ui/cctrl/dpcontrol.src b/sc/source/ui/cctrl/dpcontrol.src
new file mode 100644
index 000000000000..5f7ab9a66a9f
--- /dev/null
+++ b/sc/source/ui/cctrl/dpcontrol.src
@@ -0,0 +1,49 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: globstr.src,v $
+ * $Revision: 1.74.96.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "dpcontrol.hrc"
+
+Resource RID_POPUP_FILTER
+{
+ String STR_MENU_SORT_ASC
+ {
+ Text [ en-US ] = "Sort Ascending" ;
+ };
+
+ String STR_MENU_SORT_DESC
+ {
+ Text [ en-US ] = "Sort Descending" ;
+ };
+
+ String STR_MENU_SORT_CUSTOM
+ {
+ Text [ en-US ] = "Custom Sort" ;
+ };
+};
diff --git a/sc/source/ui/cctrl/makefile.mk b/sc/source/ui/cctrl/makefile.mk
index e7b96afd7b9a..541a90cc4347 100644
--- a/sc/source/ui/cctrl/makefile.mk
+++ b/sc/source/ui/cctrl/makefile.mk
@@ -45,22 +45,30 @@ LIBTARGET=NO
# --- Files --------------------------------------------------------
EXCEPTIONSFILES= \
- $(SLO)$/tbzoomsliderctrl.obj
+ $(SLO)$/tbzoomsliderctrl.obj \
+ $(SLO)$/dpcontrol.obj
SLOFILES = \
$(SLO)$/popmenu.obj \
$(SLO)$/tbinsert.obj \
$(SLO)$/cbuttonw.obj \
+ $(SLO)$/dpcontrol.obj \
$(SLO)$/editfield.obj \
$(EXCEPTIONSFILES)
+SRS1NAME=$(TARGET)
+SRC1FILES = \
+ dpcontrol.src
+
LIB1TARGET=$(SLB)$/$(TARGET).lib
LIB1OBJFILES= \
$(SLO)$/popmenu.obj \
$(SLO)$/tbinsert.obj \
$(SLO)$/cbuttonw.obj \
+ $(SLO)$/dpcontrol.obj \
$(SLO)$/tbzoomsliderctrl.obj
+
# --- Tagets -------------------------------------------------------
.INCLUDE : target.mk
diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index c23068b82200..688c0d60f79e 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -64,6 +64,7 @@
#include "scabstdlg.hxx" //CHINA001
using namespace com::sun::star;
using ::rtl::OUString;
+using ::std::vector;
//----------------------------------------------------------------------------
@@ -379,24 +380,23 @@ void ScDPLayoutDlg::StateChanged( StateChangedType nStateChange )
//----------------------------------------------------------------------------
-void ScDPLayoutDlg::InitWndSelect( LabelData** ppLabelArr, long nLabels )
+void ScDPLayoutDlg::InitWndSelect( const vector<ScDPLabelDataRef>& rLabels )
{
- if ( ppLabelArr )
+ size_t nLabelCount = rLabels.size();
+ if (nLabelCount > MAX_LABELS)
+ nLabelCount = MAX_LABELS;
+ size_t nLast = (nLabelCount > PAGE_SIZE) ? (PAGE_SIZE - 1) : (nLabelCount - 1);
+
+ aLabelDataArr.clear();
+ aLabelDataArr.reserve( nLabelCount );
+ for ( size_t i=0; i < nLabelCount; i++ )
{
- size_t nLabelCount = static_cast< size_t >( (nLabels > MAX_LABELS) ? MAX_LABELS : nLabels );
- size_t nLast = (nLabelCount > PAGE_SIZE) ? (PAGE_SIZE - 1) : (nLabelCount - 1);
+ aLabelDataArr.push_back(*rLabels[i]);
- aLabelDataArr.clear();
- aLabelDataArr.reserve( nLabelCount );
- for ( size_t i=0; i < nLabelCount; i++ )
+ if ( i <= nLast )
{
- aLabelDataArr.push_back( *ppLabelArr[i] );
-
- if ( i <= nLast )
- {
- aWndSelect.AddField( aLabelDataArr[i].maName, i );
- aSelectArr[i].reset( new ScDPFuncData( aLabelDataArr[i].mnCol, aLabelDataArr[i].mnFuncMask ) );
- }
+ aWndSelect.AddField( aLabelDataArr[i].maName, i );
+ aSelectArr[i].reset( new ScDPFuncData( aLabelDataArr[i].mnCol, aLabelDataArr[i].mnFuncMask ) );
}
}
}
@@ -494,18 +494,19 @@ void ScDPLayoutDlg::InitFocus()
void ScDPLayoutDlg::InitFields()
{
- InitWndSelect( thePivotData.ppLabelArr, static_cast<long>(thePivotData.nLabels) );
+ InitWndSelect(thePivotData.maLabelArray);
InitWnd( thePivotData.aPageArr, static_cast<long>(thePivotData.nPageCount), TYPE_PAGE );
InitWnd( thePivotData.aColArr, static_cast<long>(thePivotData.nColCount), TYPE_COL );
InitWnd( thePivotData.aRowArr, static_cast<long>(thePivotData.nRowCount), TYPE_ROW );
InitWnd( thePivotData.aDataArr, static_cast<long>(thePivotData.nDataCount), TYPE_DATA );
+ size_t nLabels = thePivotData.maLabelArray.size();
aSlider.SetPageSize( PAGE_SIZE );
aSlider.SetVisibleSize( PAGE_SIZE );
aSlider.SetLineSize( LINE_SIZE );
- aSlider.SetRange( Range( 0, static_cast<long>(((thePivotData.nLabels+LINE_SIZE-1)/LINE_SIZE)*LINE_SIZE) ) );
+ aSlider.SetRange( Range( 0, static_cast<long>(((nLabels+LINE_SIZE-1)/LINE_SIZE)*LINE_SIZE) ) );
- if ( thePivotData.nLabels > PAGE_SIZE )
+ if ( nLabels > PAGE_SIZE )
{
aSlider.SetEndScrollHdl( LINK( this, ScDPLayoutDlg, ScrollHdl ) );
aSlider.Show();
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 1e85f3c01f3e..ebbdd6cfbae4 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -1233,7 +1233,7 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb
aRange.aEnd.Col(), aRange.aEnd.Row(),
nTab, SC_MF_AUTO );
- pDoc->GetDPCollection()->Free( pOldObj ); // object is deleted here
+ pDoc->GetDPCollection()->FreeTable( pOldObj ); // object is deleted here
rDocShell.PostPaintGridAll(); //! only necessary parts
rDocShell.PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), nTab,
@@ -1277,7 +1277,7 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb
pDestObj = new ScDPObject( *pNewObj );
pDestObj->SetAlive(TRUE);
- if ( !pDoc->GetDPCollection()->Insert(pDestObj) )
+ if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
{
DBG_ERROR("cannot insert DPObject");
DELETEZ( pDestObj );
diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx
index 82739bfdd274..afeb90df1a79 100644
--- a/sc/source/ui/inc/dbfunc.hxx
+++ b/sc/source/ui/inc/dbfunc.hxx
@@ -99,6 +99,7 @@ public:
void UngroupDataPilot();
void DataPilotInput( const ScAddress& rPos, const String& rString );
+ bool DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId = NULL );
BOOL DataPilotMove( const ScRange& rSource, const ScAddress& rDest );
BOOL HasSelectionForDrillDown( USHORT& rOrientation );
diff --git a/sc/source/ui/inc/dpcontrol.hrc b/sc/source/ui/inc/dpcontrol.hrc
new file mode 100644
index 000000000000..7ec03c5134ae
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hrc
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: protectiondlg.hrc,v $
+ * $Revision: 1.1.2.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __DPCONTROL_HRC__
+#define __DPCONTROL_HRC__
+
+#include <sc.hrc>
+
+#define STR_MENU_SORT_ASC 1
+#define STR_MENU_SORT_DESC 2
+#define STR_MENU_SORT_CUSTOM 3
+
+#endif
diff --git a/sc/source/ui/inc/dpcontrol.hxx b/sc/source/ui/inc/dpcontrol.hxx
new file mode 100644
index 000000000000..5c1e7a59aad2
--- /dev/null
+++ b/sc/source/ui/inc/dpcontrol.hxx
@@ -0,0 +1,289 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: document.hxx,v $
+ * $Revision: 1.115.36.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_DPCONTROL_HXX
+#define SC_DPCONTROL_HXX
+
+#include "rtl/ustring.hxx"
+#include "tools/gen.hxx"
+#include "vcl/floatwin.hxx"
+#include "vcl/button.hxx"
+#include "vcl/scrbar.hxx"
+#include "vcl/timer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <hash_map>
+
+class OutputDevice;
+class Point;
+class Size;
+class StyleSettings;
+class Window;
+
+/**
+ * This class takes care of physically drawing field button controls inside
+ * data pilot tables.
+ */
+class ScDPFieldButton
+{
+public:
+ ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle);
+ ~ScDPFieldButton();
+
+ void setText(const ::rtl::OUString& rText);
+ void setBoundingBox(const Point& rPos, const Size& rSize);
+ void setDrawPopupButton(bool b);
+ void setHasHiddenMember(bool b);
+ void draw();
+
+ void getPopupBoundingBox(Point& rPos, Size& rSize) const;
+ bool isPopupButton() const;
+
+private:
+ void drawPopupButton();
+
+private:
+ Point maPos;
+ Size maSize;
+ ::rtl::OUString maText;
+ OutputDevice* mpOutDev;
+ const StyleSettings* mpStyle;
+ bool mbPopupButton;
+ bool mbHasHiddenMember;
+};
+
+// ============================================================================
+
+class ScMenuFloatingWindow : public FloatingWindow
+{
+public:
+ /**
+ * Action to perform when an event takes place. Create a sub-class of
+ * this to implement the desired action.
+ */
+ class Action
+ {
+ public:
+ virtual void execute() = 0;
+ };
+
+ explicit ScMenuFloatingWindow(Window* pParent);
+ virtual ~ScMenuFloatingWindow();
+
+ virtual void MouseMove(const MouseEvent& rMEvt);
+ virtual void MouseButtonDown(const MouseEvent& rMEvt);
+ virtual void MouseButtonUp(const MouseEvent& rMEvt);
+ virtual void KeyInput(const KeyEvent& rKEvt);
+ virtual void Paint(const Rectangle& rRect);
+
+ void addMenuItem(const ::rtl::OUString& rText, bool bEnabled, Action* pAction);
+ ScMenuFloatingWindow* addSubMenuItem(const ::rtl::OUString& rText, bool bEnabled);
+
+protected:
+ void drawMenuItem(size_t nPos);
+ void drawAllMenuItems();
+ const Font& getLabelFont() const;
+
+ void executeMenu(size_t nPos);
+ void setSelectedMenuItem(size_t nPos, bool bSubMenuTimer = true);
+ size_t getSelectedMenuItem() const;
+ void queueLaunchSubMenu(size_t nPos, ScMenuFloatingWindow* pMenu);
+ void queueCloseSubMenu();
+ void launchSubMenu(bool bSetMenuPos);
+ void endSubMenu();
+
+private:
+ struct SubMenuItem;
+ void handleMenuTimeout(SubMenuItem* pTimer);
+
+ enum NotificationType { SUBMENU_FOCUSED };
+ void notify(NotificationType eType);
+
+ void resetMenu(bool bSetMenuPos);
+ void resizeToFitMenuItems();
+ void selectMenuItem(size_t nPos, bool bSelected, bool bSubMenuTimer);
+ void highlightMenuItem(size_t nPos, bool bSelected);
+
+ void getMenuItemPosSize(Point& rPos, Size& rSize, size_t nPos) const;
+ size_t getEnclosingMenuItem(const Point& rPos) const;
+
+ DECL_LINK( EndPopupHdl, void* );
+
+private:
+ struct MenuItem
+ {
+ ::rtl::OUString maText;
+ bool mbEnabled;
+
+ ::boost::shared_ptr<Action> mpAction;
+ ::boost::shared_ptr<ScMenuFloatingWindow> mpSubMenuWin;
+
+ MenuItem();
+ };
+
+ ::std::vector<MenuItem> maMenuItems;
+
+ struct SubMenuItem
+ {
+ Timer maTimer;
+ ScMenuFloatingWindow* mpSubMenu;
+ size_t mnMenuPos;
+
+ DECL_LINK( TimeoutHdl, void* );
+
+ SubMenuItem(ScMenuFloatingWindow* pParent);
+ void reset();
+
+ private:
+ ScMenuFloatingWindow* mpParent;
+ };
+ SubMenuItem maOpenTimer;
+ SubMenuItem maCloseTimer;
+
+ Font maLabelFont;
+
+ size_t mnSelectedMenu;
+ size_t mnClickedMenu;
+
+ ScMenuFloatingWindow* mpParentMenu;
+ ScMenuFloatingWindow* mpActiveSubMenu;
+
+ bool mbActionFired;
+};
+
+// ============================================================================
+
+/**
+ * This class implements a popup window for field button, for quick access
+ * of hide-item list, and possibly more stuff related to field options.
+ */
+class ScDPFieldPopupWindow : public ScMenuFloatingWindow
+{
+public:
+ /**
+ * Extended data that the client code may need to store. Create a
+ * sub-class of this and store data there.
+ */
+ struct ExtendedData {};
+
+ explicit ScDPFieldPopupWindow(Window* pParent);
+ virtual ~ScDPFieldPopupWindow();
+
+ virtual void MouseMove(const MouseEvent& rMEvt);
+ virtual void Paint(const Rectangle& rRect);
+
+ void setMemberSize(size_t n);
+ void addMember(const ::rtl::OUString& rName, bool bVisible);
+ void initMembers();
+
+ void getResult(::std::hash_map< ::rtl::OUString, bool, ::rtl::OUStringHash>& rResult);
+ void close(bool bOK);
+
+ /**
+ * Set auxiliary data that the client code might need. Note that this
+ * popup window class manages its life time; no explicit deletion of the
+ * instance is needed in the client code.
+ */
+ void setExtendedData(ExtendedData* p);
+
+ /**
+ * Get the store auxiliary data, or NULL if no such data is stored.
+ */
+ ExtendedData* getExtendedData();
+
+ void setOKAction(Action* p);
+
+private:
+ struct Member
+ {
+ ::rtl::OUString maName;
+ bool mbVisible;
+
+ Member();
+ };
+
+ class CancelButton : public ::CancelButton
+ {
+ public:
+ CancelButton(ScDPFieldPopupWindow* pParent);
+
+ virtual void Click();
+
+ private:
+ ScDPFieldPopupWindow* mpParent;
+ };
+
+ ::std::vector<Member>& getMembers();
+
+ enum SectionType {
+ WHOLE, // entire window
+ LISTBOX_AREA, // box enclosing the check box items.
+ FIRST_LISTITEM, // first list item at the top
+ BTN_OK, // OK button
+ BTN_CANCEL, // Cancel button
+ SCROLL_BAR_V, // vertical scroll bar along the right edge of the list box.
+ };
+ void getSectionPosSize(Point& rPos, Size& rSize, SectionType eType) const;
+
+ void resetDisplayedItems();
+
+ DECL_LINK( CheckBoxHdl, CheckBox* );
+ DECL_LINK( OKButtonHdl, OKButton* );
+ DECL_LINK( ScrollHdl, ScrollBar* );
+
+private:
+
+ CheckBox maCheck0;
+ CheckBox maCheck1;
+ CheckBox maCheck2;
+ CheckBox maCheck3;
+ CheckBox maCheck4;
+ CheckBox maCheck5;
+ CheckBox maCheck6;
+ CheckBox maCheck7;
+ CheckBox maCheck8;
+ CheckBox maCheck9;
+
+ ScrollBar maScrollBar;
+
+ OKButton maBtnOk;
+ CancelButton maBtnCancel;
+
+ ::std::vector<CheckBox*> mpCheckPtr;
+
+ ::std::vector<Member> maMembers;
+ ::std::auto_ptr<ExtendedData> mpExtendedData;
+ ::std::auto_ptr<Action> mpOKAction;
+
+ size_t mnScrollPos;
+};
+
+#endif
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 9b31289d13d0..32ecaf26cc56 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -39,6 +39,7 @@
#include <svx/sdr/overlay/overlayobject.hxx>
#include <vector>
+#include <memory>
// ---------------------------------------------------------------------------
@@ -48,6 +49,7 @@ class ScViewSelectionEngine;
class ScPivot;
#endif
class ScDPObject;
+class ScDPFieldPopupWindow;
class ScOutputData;
class ScFilterListBox;
class AutoFilterPopup;
@@ -159,6 +161,7 @@ private:
ScFilterListBox* pFilterBox;
FloatingWindow* pFilterFloat;
+ ::std::auto_ptr<ScDPFieldPopupWindow> mpDPFieldPopup;
USHORT nCursorHideCount;
@@ -245,6 +248,16 @@ private:
void DPMouseButtonUp( const MouseEvent& rMEvt );
void DPTestMouse( const MouseEvent& rMEvt, BOOL bMove );
+ /**
+ * Check if the mouse click is on a field popup button.
+ *
+ * @return bool true if the field popup menu has been launched and no
+ * further mouse event handling is necessary, false otherwise.
+ */
+ bool DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj);
+ void DPLaunchFieldPopupMenu(
+ const Point& rSrcPos, const Size& rSrcSize, const ScAddress& rPos, ScDPObject* pDPObj);
+
void RFMouseMove( const MouseEvent& rMEvt, BOOL bUp );
void PagebreakMove( const MouseEvent& rMEvt, BOOL bUp );
@@ -409,6 +422,8 @@ public:
void CheckNeedsRepaint();
+ void UpdateDPFromFieldPopupMenu();
+
// #114409#
void CursorChanged();
void DrawLayerCreated();
diff --git a/sc/source/ui/inc/pvlaydlg.hxx b/sc/source/ui/inc/pvlaydlg.hxx
index b7a71aebc1fe..c77364d3761f 100644
--- a/sc/source/ui/inc/pvlaydlg.hxx
+++ b/sc/source/ui/inc/pvlaydlg.hxx
@@ -193,7 +193,7 @@ private:
private:
ScDPFieldWindow& GetFieldWindow ( ScDPFieldType eType );
void Init ();
- void InitWndSelect ( LabelData** ppLabelArr, long nLabels );
+ void InitWndSelect ( const ::std::vector<ScDPLabelDataRef>& rLabels );
void InitWnd ( PivotField* pArr, long nCount, ScDPFieldType eType );
void InitFocus ();
void InitFields ();
diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx
index f16409b37239..ffc750a7ceb8 100644
--- a/sc/source/ui/undo/undodat.cxx
+++ b/sc/source/ui/undo/undodat.cxx
@@ -1876,7 +1876,7 @@ void __EXPORT ScUndoDataPilot::Undo()
else
{
// delete inserted object
- pDoc->GetDPCollection()->Free(pDocObj);
+ pDoc->GetDPCollection()->FreeTable(pDocObj);
}
}
}
@@ -1886,7 +1886,7 @@ void __EXPORT ScUndoDataPilot::Undo()
ScDPObject* pDestObj = new ScDPObject( *pOldDPObject );
pDestObj->SetAlive(TRUE);
- if ( !pDoc->GetDPCollection()->Insert(pDestObj) )
+ if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
{
DBG_ERROR("cannot insert DPObject");
DELETEZ( pDestObj );
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index c71bc31a1150..e0d6693b39ef 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -81,9 +81,13 @@
#include "patattr.hxx"
#include "unonames.hxx"
#include "cell.hxx"
+#include "userlist.hxx"
#include <hash_set>
+#include <hash_map>
#include <memory>
+#include <list>
+#include <vector>
using namespace com::sun::star;
using ::com::sun::star::uno::Any;
@@ -94,8 +98,13 @@ using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::container::XNameAccess;
using ::com::sun::star::sheet::XDimensionsSupplier;
using ::rtl::OUString;
+using ::rtl::OUStringHash;
using ::rtl::OUStringBuffer;
using ::std::auto_ptr;
+using ::std::list;
+using ::std::vector;
+using ::std::hash_map;
+using ::std::hash_set;
// STATIC DATA -----------------------------------------------------------
@@ -1681,6 +1690,134 @@ void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName )
// puts it to the end of the list even if it was in the list before.
}
+bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab());
+ if (!pDPObj)
+ return false;
+
+ // We need to run this to get all members later.
+ pDPObj->BuildAllDimensionMembers();
+
+ USHORT nOrientation;
+ long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation);
+ if (nDimIndex < 0)
+ // Invalid dimension index. Bail out.
+ return false;
+
+ BOOL bDataLayout;
+ ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+ if (!pSaveData)
+ return false;
+
+ ScDPSaveData aNewSaveData(*pSaveData);
+ String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
+ ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
+ if (!pSaveDim)
+ return false;
+
+ typedef ScDPSaveDimension::MemberList MemList;
+ const MemList& rDimMembers = pSaveDim->GetMembers();
+ list<OUString> aMembers;
+ hash_set<OUString, ::rtl::OUStringHash> aMemberSet;
+ size_t nMemberCount = 0;
+ for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end();
+ itr != itrEnd; ++itr)
+ {
+ ScDPSaveMember* pMem = *itr;
+ aMembers.push_back(pMem->GetName());
+ aMemberSet.insert(pMem->GetName());
+ ++nMemberCount;
+ }
+
+ // Sort the member list in ascending order.
+ aMembers.sort();
+
+ // Collect and rank those custom sort strings that also exist in the member name list.
+
+ typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap;
+ UserSortMap aSubStrs;
+ sal_uInt16 nSubCount = 0;
+ if (pUserListId)
+ {
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ if (!pUserList)
+ return false;
+
+ {
+ sal_uInt16 n = pUserList->GetCount();
+ if (!n || *pUserListId >= n)
+ return false;
+ }
+
+ ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]);
+ if (pData)
+ {
+ sal_uInt16 n = pData->GetSubCount();
+ for (sal_uInt16 i = 0; i < n; ++i)
+ {
+ OUString aSub = pData->GetSubStr(i);
+ if (!aMemberSet.count(aSub))
+ // This string doesn't exist in the member name set. Don't add this.
+ continue;
+
+ aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++));
+ }
+ }
+ }
+
+ // Rank all members.
+
+ vector<OUString> aRankedNames(nMemberCount);
+ sal_uInt16 nCurStrId = 0;
+ for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end();
+ itr != itrEnd; ++itr)
+ {
+ OUString aName = *itr;
+ sal_uInt16 nRank = 0;
+ UserSortMap::const_iterator itrSub = aSubStrs.find(aName);
+ if (itrSub == aSubStrs.end())
+ nRank = nSubCount + nCurStrId++;
+ else
+ nRank = itrSub->second;
+
+ if (!bAscending)
+ nRank = nMemberCount - nRank - 1;
+
+ aRankedNames[nRank] = aName;
+ }
+
+ // Re-order ScDPSaveMember instances with the new ranks.
+
+ for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end();
+ itr != itrEnd; ++itr)
+ {
+ const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr);
+ if (!pOldMem)
+ // All members are supposed to be present.
+ continue;
+
+ ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem);
+ pSaveDim->AddMember(pNewMem);
+ }
+
+ // Set the sorting mode to manual for now. We may introduce a new sorting
+ // mode later on.
+
+ sheet::DataPilotFieldSortInfo aSortInfo;
+ aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
+ pSaveDim->SetSortInfo(&aSortInfo);
+
+ // Update the datapilot with the newly sorted field members.
+
+ auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
+ pNewObj->SetSaveData(aNewSaveData);
+ ScDBDocFunc aFunc(*GetViewData()->GetDocShell());
+
+ return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
+}
+
BOOL ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
{
BOOL bRet = FALSE;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 5591a2a496be..8949d2bd29a9 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -119,6 +119,7 @@
#include "drwlayer.hxx"
#include "attrib.hxx"
#include "validat.hxx"
+#include "dpcontrol.hxx"
// #114409#
#include <vcl/salbtype.hxx> // FRound
@@ -370,6 +371,7 @@ ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhic
pNoteMarker( NULL ),
pFilterBox( NULL ),
pFilterFloat( NULL ),
+ mpDPFieldPopup(NULL),
nCursorHideCount( 0 ),
bMarking( FALSE ),
nButtonDown( 0 ),
diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx
index 92743ef65524..1cfb5bdf71c0 100644
--- a/sc/source/ui/view/gridwin2.cxx
+++ b/sc/source/ui/view/gridwin2.cxx
@@ -55,11 +55,23 @@
#include "dpoutput.hxx" // ScDPPositionData
#include "dpshttab.hxx"
#include "dbdocfun.hxx"
+#include "dpcontrol.hxx"
+#include "dpcontrol.hrc"
+#include "strload.hxx"
+#include "userlist.hxx"
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include "scabstdlg.hxx" //CHINA001
-using namespace com::sun::star;
+#include <vector>
+#include <hash_map>
+
+using namespace com::sun::star;
+using ::std::vector;
+using ::std::auto_ptr;
+using ::std::hash_map;
+using ::rtl::OUString;
+using ::rtl::OUStringHash;
// STATIC DATA -----------------------------------------------------------
@@ -199,6 +211,15 @@ void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt
bDPMouse = TRUE;
nDPField = nField;
pDragDPObj = pDPObj;
+
+ if (DPTestFieldPopupArrow(rMEvt, aPos, pDPObj))
+ {
+ // field name pop up menu has been launched. Don't activate
+ // field move.
+ bDPMouse = false;
+ return;
+ }
+
DPTestMouse( rMEvt, TRUE );
StartTracking();
}
@@ -726,6 +747,185 @@ void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, BOOL bMove )
pViewData->GetView()->ResetTimer();
}
+bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj)
+{
+ // Get the geometry of the cell.
+ Point aSrcPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich);
+ long nSizeX, nSizeY;
+ pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
+ Size aSrcSize(nSizeX-1, nSizeY-1);
+
+ // Check if the mouse cursor is clicking on the popup arrow box.
+ ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings());
+ aBtn.setBoundingBox(aSrcPos, aSrcSize);
+ Point aPopupPos;
+ Size aPopupSize;
+ aBtn.getPopupBoundingBox(aPopupPos, aPopupSize);
+ Rectangle aRec(aPopupPos, aPopupSize);
+ if (aRec.IsInside(rMEvt.GetPosPixel()))
+ {
+ // Mouse cursor inside the popup arrow box. Launch the field menu.
+ DPLaunchFieldPopupMenu(OutputToScreenPixel(aSrcPos), aSrcSize, rPos, pDPObj);
+ return true;
+ }
+
+ return false;
+}
+
+namespace {
+
+struct DPFieldPopupData : public ScDPFieldPopupWindow::ExtendedData
+{
+ ScPivotParam maDPParam;
+ ScDPObject* mpDPObj;
+ long mnDim;
+};
+
+class DPFieldPopupOKAction : public ScMenuFloatingWindow::Action
+{
+public:
+ explicit DPFieldPopupOKAction(ScGridWindow* p) :
+ mpGridWindow(p) {}
+
+ virtual void execute()
+ {
+ mpGridWindow->UpdateDPFromFieldPopupMenu();
+ }
+private:
+ ScGridWindow* mpGridWindow;
+};
+
+class PopupSortAction : public ScMenuFloatingWindow::Action
+{
+public:
+ enum SortType { ASCENDING, DESCENDING, CUSTOM };
+
+ explicit PopupSortAction(const ScAddress& rPos, SortType eType, sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell) :
+ maPos(rPos), meType(eType), mnUserListIndex(nUserListIndex), mpViewShell(pViewShell) {}
+
+ virtual void execute()
+ {
+ switch (meType)
+ {
+ case ASCENDING:
+ mpViewShell->DataPilotSort(maPos, true);
+ break;
+ case DESCENDING:
+ mpViewShell->DataPilotSort(maPos, false);
+ break;
+ case CUSTOM:
+ mpViewShell->DataPilotSort(maPos, true, &mnUserListIndex);
+ break;
+ default:
+ ;
+ }
+ }
+
+private:
+ ScAddress maPos;
+ SortType meType;
+ sal_uInt16 mnUserListIndex;
+ ScTabViewShell* mpViewShell;
+};
+
+}
+
+void ScGridWindow::DPLaunchFieldPopupMenu(
+ const Point& rSrcPos, const Size& rSrcSize, const ScAddress& rPos, ScDPObject* pDPObj)
+{
+ // We need to get the list of field members.
+ auto_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData);
+ pDPObj->FillLabelData(pDPData->maDPParam);
+ pDPData->mpDPObj = pDPObj;
+
+ USHORT nOrient;
+ pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient);
+
+ if (pDPData->maDPParam.maLabelArray.size() <= static_cast<size_t>(pDPData->mnDim))
+ // out-of-bound dimension ID. This should never happen!
+ return;
+
+ const ScDPLabelData& rLabelData = *pDPData->maDPParam.maLabelArray[pDPData->mnDim];
+
+ mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this));
+ mpDPFieldPopup->setExtendedData(pDPData.release());
+ mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this));
+ {
+ sal_Int32 n = rLabelData.maMembers.getLength();
+ mpDPFieldPopup->setMemberSize(n);
+ for (sal_Int32 i = 0; i < n; ++i)
+ mpDPFieldPopup->addMember(rLabelData.maMembers[i], rLabelData.maVisible[i]);
+ mpDPFieldPopup->initMembers();
+ }
+
+ vector<OUString> aUserSortNames;
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ if (pUserList)
+ {
+ sal_uInt16 n = pUserList->GetCount();
+ aUserSortNames.reserve(n);
+ for (sal_uInt16 i = 0; i < n; ++i)
+ {
+ ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[i]);
+ aUserSortNames.push_back(pData->GetString());
+ }
+ }
+
+ // Populate the menus.
+ ScTabViewShell* pViewShell = pViewData->GetViewShell();
+ mpDPFieldPopup->addMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(), true,
+ new PopupSortAction(rPos, PopupSortAction::ASCENDING, 0, pViewShell));
+ mpDPFieldPopup->addMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(), true,
+ new PopupSortAction(rPos, PopupSortAction::DESCENDING, 0, pViewShell));
+ ScMenuFloatingWindow* pSubMenu = mpDPFieldPopup->addSubMenuItem(
+ ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_CUSTOM).GetString(), !aUserSortNames.empty());
+
+ if (pSubMenu && !aUserSortNames.empty())
+ {
+ size_t n = aUserSortNames.size();
+ for (size_t i = 0; i < n; ++i)
+ {
+ pSubMenu->addMenuItem(
+ aUserSortNames[i], true,
+ new PopupSortAction(rPos, PopupSortAction::CUSTOM, i, pViewShell));
+ }
+ }
+
+ mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) );
+ Rectangle aCellRect(rSrcPos, rSrcSize);
+ mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
+}
+
+void ScGridWindow::UpdateDPFromFieldPopupMenu()
+{
+ if (!mpDPFieldPopup.get())
+ return;
+
+ DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData());
+ if (!pDPData)
+ return;
+
+ ScDPObject* pDPObj = pDPData->mpDPObj;
+ ScDPObject aNewDPObj(*pDPObj);
+ aNewDPObj.BuildAllDimensionMembers();
+ ScDPSaveData* pSaveData = aNewDPObj.GetSaveData();
+
+ BOOL bIsDataLayout;
+ String aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout);
+ ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName);
+ if (!pDim)
+ return;
+
+ hash_map<OUString, bool, OUStringHash> aResult;
+ mpDPFieldPopup->getResult(aResult);
+ pDim->UpdateMemberVisibility(aResult);
+
+ ScDBDocFunc aFunc(*pViewData->GetDocShell());
+ aFunc.DataPilotUpdate(pDPObj, &aNewDPObj, true, false);
+}
+
void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt )
{
DPTestMouse( rMEvt, TRUE );
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index b90e5d3e802e..e6466e7ba3b1 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -73,6 +73,7 @@
#include "editutil.hxx"
#include "inputopt.hxx"
#include "fillinfo.hxx"
+#include "dpcontrol.hxx"
#include "sc.hrc"
#include <vcl/virdev.hxx>
@@ -1203,6 +1204,8 @@ void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2
{
aComboButton.SetOutputDevice( pContentDev );
+ ScDPFieldButton aDPFieldBtn(pContentDev, &GetSettings().GetStyleSettings());
+
SCCOL nCol;
SCROW nRow;
SCSIZE nArrY;
@@ -1318,13 +1321,13 @@ void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2
nPosX -= nSizeX - 2;
}
- pContentDev->SetLineColor( GetSettings().GetStyleSettings().GetLightColor() );
- pContentDev->DrawLine( Point(nPosX,nPosY), Point(nPosX,nPosY+nSizeY-1) );
- pContentDev->DrawLine( Point(nPosX,nPosY), Point(nPosX+nSizeX-1,nPosY) );
- pContentDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
- pContentDev->DrawLine( Point(nPosX,nPosY+nSizeY-1), Point(nPosX+nSizeX-1,nPosY+nSizeY-1) );
- pContentDev->DrawLine( Point(nPosX+nSizeX-1,nPosY), Point(nPosX+nSizeX-1,nPosY+nSizeY-1) );
- pContentDev->SetLineColor( COL_BLACK );
+ String aStr;
+ pDoc->GetString(nCol, nRow, nTab, aStr);
+ aDPFieldBtn.setText(aStr);
+ aDPFieldBtn.setBoundingBox(Point(nPosX,nPosY), Size(nSizeX-1, nSizeY-1));
+ aDPFieldBtn.setDrawPopupButton(pInfo->bPopupButton);
+ aDPFieldBtn.setHasHiddenMember(pInfo->bFilterActive);
+ aDPFieldBtn.draw();
}
}
}