diff options
Diffstat (limited to 'sc/source')
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(); } } } |