diff options
Diffstat (limited to 'binfilter/bf_sc/source/ui/unoobj/sc_dapiuno.cxx')
-rw-r--r-- | binfilter/bf_sc/source/ui/unoobj/sc_dapiuno.cxx | 1855 |
1 files changed, 1855 insertions, 0 deletions
diff --git a/binfilter/bf_sc/source/ui/unoobj/sc_dapiuno.cxx b/binfilter/bf_sc/source/ui/unoobj/sc_dapiuno.cxx new file mode 100644 index 000000000000..f8514396a590 --- /dev/null +++ b/binfilter/bf_sc/source/ui/unoobj/sc_dapiuno.cxx @@ -0,0 +1,1855 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#include <rtl/uuid.h> + +#include "dapiuno.hxx" +#include "datauno.hxx" +#include "miscuno.hxx" +#include "docsh.hxx" +#include "pivot.hxx" +#include <vcl/svapp.hxx> +#include "dpobject.hxx" +#include "dpshttab.hxx" +#include "dpsave.hxx" +#include "dbdocfun.hxx" +#include "unonames.hxx" +namespace binfilter { + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +const SfxItemPropertyMap* lcl_GetDataPilotFieldMap() +{ + static SfxItemPropertyMap aDataPilotFieldMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_FUNCTION), 0, &getCppuType((sheet::GeneralFunction*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ORIENT), 0, &getCppuType((sheet::DataPilotFieldOrientation*)0), 0, 0 }, + {0,0,0,0} + }; + return aDataPilotFieldMap_Impl; +} + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScDataPilotDescriptor, "ScDataPilotDescriptor", "stardiv::one::sheet::DataPilotDescriptor" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldObj, "ScDataPilotFieldObj", "com.sun.star.sheet.DataPilotField" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldsObj, "ScDataPilotFieldsObj", "com.sun.star.sheet.DataPilotFields" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotTableObj, "ScDataPilotTableObj", "com.sun.star.sheet.DataPilotTable" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotTablesObj, "ScDataPilotTablesObj", "com.sun.star.sheet.DataPilotTables" ) + +//------------------------------------------------------------------------ + +//! irgendwann ueberall die neuen enum-Werte benutzen +#define DATA_PILOT_HIDDEN sheet::DataPilotFieldOrientation_HIDDEN +#define DATA_PILOT_COLUMN sheet::DataPilotFieldOrientation_COLUMN +#define DATA_PILOT_ROW sheet::DataPilotFieldOrientation_ROW +#define DATA_PILOT_PAGE sheet::DataPilotFieldOrientation_PAGE +#define DATA_PILOT_DATA sheet::DataPilotFieldOrientation_DATA + +//------------------------------------------------------------------------ + +USHORT lcl_BitCount( USHORT nBits ) +{ + if (!nBits) return 0; + + USHORT nCount = 0; + USHORT nMask = 1; + for (USHORT i=0; i<16; i++) + { + if ( nBits & nMask ) + ++nCount; + nMask <<= 1; + } + return nCount; +} + +USHORT lcl_DataCount( const ScPivotParam& rParam ) +{ + USHORT nRet = 0; + for ( USHORT i=0; i<rParam.nDataCount; i++ ) + nRet += lcl_BitCount( rParam.aDataArr[i].nFuncMask ); // nFuncCount stimmt nicht + return nRet; +} + +BOOL lcl_GetDataArrayPos( const ScPivotParam& rParam, USHORT nIndex, + USHORT& rArrayPos, USHORT& rFuncBit ) +{ + USHORT nPos = 0; + for ( USHORT i=0; i<rParam.nDataCount; i++ ) + { + USHORT nBits = rParam.aDataArr[i].nFuncMask; + USHORT nMask = 1; + for (USHORT nBP=0; nBP<16; nBP++) + { + if ( nBits & nMask ) + { + if ( nPos == nIndex ) + { + rArrayPos = i; // position in aDataArr + rFuncBit = nMask; + return TRUE; + } + ++nPos; + } + nMask <<= 1; + } + } + rArrayPos = 0; + rFuncBit = 0; + return FALSE; +} + +ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, USHORT nTab, const String& rName ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && + pDPObj->GetOutRange().aStart.Tab() == nTab && + pDPObj->GetName() == rName ) + return pDPObj; + } + } + } + return NULL; // nicht gefunden +} + +String lcl_ColumnTitle( ScDocument* pDoc, USHORT nCol, USHORT nRow, USHORT nTab ) +{ + // Spaltennamen, wie sie in der Pivottabelle angezeigt werden + String aStr; + pDoc->GetString(nCol, nRow, nTab, aStr); + if (aStr.Len() == 0) + aStr = ColToAlpha( nCol ); + return aStr; +} + +sheet::GeneralFunction ScDataPilotConversion::FirstFunc( USHORT nBits ) +{ + if ( nBits & PIVOT_FUNC_SUM ) return sheet::GeneralFunction_SUM; + if ( nBits & PIVOT_FUNC_COUNT ) return sheet::GeneralFunction_COUNT; + if ( nBits & PIVOT_FUNC_AVERAGE ) return sheet::GeneralFunction_AVERAGE; + if ( nBits & PIVOT_FUNC_MAX ) return sheet::GeneralFunction_MAX; + if ( nBits & PIVOT_FUNC_MIN ) return sheet::GeneralFunction_MIN; + if ( nBits & PIVOT_FUNC_PRODUCT ) return sheet::GeneralFunction_PRODUCT; + if ( nBits & PIVOT_FUNC_COUNT_NUM ) return sheet::GeneralFunction_COUNTNUMS; + if ( nBits & PIVOT_FUNC_STD_DEV ) return sheet::GeneralFunction_STDEV; + if ( nBits & PIVOT_FUNC_STD_DEVP ) return sheet::GeneralFunction_STDEVP; + if ( nBits & PIVOT_FUNC_STD_VAR ) return sheet::GeneralFunction_VAR; + if ( nBits & PIVOT_FUNC_STD_VARP ) return sheet::GeneralFunction_VARP; + if ( nBits & PIVOT_FUNC_AUTO ) return sheet::GeneralFunction_AUTO; + return sheet::GeneralFunction_NONE; +} + +USHORT ScDataPilotConversion::FunctionBit( sheet::GeneralFunction eFunc ) +{ + USHORT nRet = PIVOT_FUNC_NONE; // 0 + switch (eFunc) + { + case sheet::GeneralFunction_SUM: nRet = PIVOT_FUNC_SUM; break; + case sheet::GeneralFunction_COUNT: nRet = PIVOT_FUNC_COUNT; break; + case sheet::GeneralFunction_AVERAGE: nRet = PIVOT_FUNC_AVERAGE; break; + case sheet::GeneralFunction_MAX: nRet = PIVOT_FUNC_MAX; break; + case sheet::GeneralFunction_MIN: nRet = PIVOT_FUNC_MIN; break; + case sheet::GeneralFunction_PRODUCT: nRet = PIVOT_FUNC_PRODUCT; break; + case sheet::GeneralFunction_COUNTNUMS: nRet = PIVOT_FUNC_COUNT_NUM; break; + case sheet::GeneralFunction_STDEV: nRet = PIVOT_FUNC_STD_DEV; break; + case sheet::GeneralFunction_STDEVP: nRet = PIVOT_FUNC_STD_DEVP; break; + case sheet::GeneralFunction_VAR: nRet = PIVOT_FUNC_STD_VAR; break; + case sheet::GeneralFunction_VARP: nRet = PIVOT_FUNC_STD_VARP; break; + case sheet::GeneralFunction_AUTO: nRet = PIVOT_FUNC_AUTO; break; + } + return nRet; +} + +String lcl_CreatePivotName( ScDocShell* pDocShell ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + return pColl->CreateNewName(); + } + return String(); // sollte nicht vorkommen +} + +void lcl_SetLayoutNamesToObject( ScDocument* pDoc, + const ScPivotParam& rParam, const ScArea& rSrcArea, + ScDPObject& rObject ) +{ + // set layout names from LabelData to SaveData + + //! reset old names? (renamed columns) + + ScDPSaveData* pOldData = rObject.GetSaveData(); + if ( pOldData && rSrcArea.nColEnd >= rSrcArea.nColStart ) + { + ScDPSaveData aNewData( *pOldData ); + + USHORT nRow = rSrcArea.nRowStart; + USHORT nTab = rSrcArea.nTab; + USHORT nCount = rSrcArea.nColEnd - rSrcArea.nColStart + 1; + for (USHORT nField = 0; nField < nCount; nField++) + { + USHORT nCol = rSrcArea.nColStart + nField; + String aSourceName = lcl_ColumnTitle( pDoc, nCol, nRow, nTab ); + + if ( nField < rParam.nLabels && rParam.ppLabelArr && + rParam.ppLabelArr[nField] && + rParam.ppLabelArr[nField]->pStrColName && + rParam.ppLabelArr[nField]->pStrColName->Len() ) + { + String aLayoutName = *rParam.ppLabelArr[nField]->pStrColName; + + // create SaveDimension if not there + ScDPSaveDimension* pDim = aNewData.GetDimensionByName( aSourceName ); + if (pDim) + pDim->SetLayoutName( &aLayoutName ); + } + else + { + // reset layout name if one was set + ScDPSaveDimension* pDim = aNewData.GetExistingDimensionByName( aSourceName ); + if (pDim) + pDim->ResetLayoutName(); + } + } + + rObject.SetSaveData( aNewData ); + } +} + +void lcl_SetLayoutNamesToParam( ScPivotParam& rParam, ScDocument* pDoc, + const ScArea& rSrcArea, const ScDPObject& rObject ) +{ + // set layout names from SaveData to LabelData + + ScDPSaveData* pSaveData = rObject.GetSaveData(); + if ( pSaveData && rSrcArea.nColEnd >= rSrcArea.nColStart ) + { + BOOL bAnyFound = FALSE; + USHORT nNewCount = rSrcArea.nColEnd - rSrcArea.nColStart + 1; + LabelData** ppNewData = new LabelData*[nNewCount]; + + USHORT nRow = rSrcArea.nRowStart; + USHORT nTab = rSrcArea.nTab; + for (USHORT nField = 0; nField < nNewCount; nField++) + { + USHORT nCol = rSrcArea.nColStart + nField; + String aSourceName = lcl_ColumnTitle( pDoc, nCol, nRow, nTab ); + + String aLayoutName; + ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aSourceName ); + if ( pDim && pDim->HasLayoutName() ) + { + aLayoutName = pDim->GetLayoutName(); + if (aLayoutName.Len()) + bAnyFound = TRUE; + } + + ppNewData[nField] = new LabelData( aLayoutName, 0, FALSE ); + } + + if ( bAnyFound ) + rParam.SetLabelData( ppNewData, nNewCount ); + + // SetLabelData copies data - ppNewData must be deleted + for (USHORT i=0; i<nNewCount; i++) + delete ppNewData[i]; + delete[] ppNewData; + } +} + +//------------------------------------------------------------------------ + +ScDataPilotTablesObj::ScDataPilotTablesObj(ScDocShell* pDocSh, USHORT nT) : + pDocShell( pDocSh ), + nTab( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDataPilotTablesObj::~ScDataPilotTablesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDataPilotTablesObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + //! Referenz-Update + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDataPilotTables + +ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl(USHORT nIndex) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + USHORT nFound = 0; + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + { + if ( nFound == nIndex ) + { + String aName = pDPObj->GetName(); + return new ScDataPilotTableObj( pDocShell, nTab, aName ); + } + ++nFound; + } + } + } + } + return NULL; +} + +ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByName_Impl(const ::rtl::OUString& aName) +{ + if (hasByName(aName)) + { + String aNamStr = aName; + return new ScDataPilotTableObj( pDocShell, nTab, aNamStr ); + } + return NULL; +} + +uno::Reference<sheet::XDataPilotDescriptor> SAL_CALL ScDataPilotTablesObj::createDataPilotDescriptor() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (pDocShell) + return new ScDataPilotDescriptor(pDocShell); + return NULL; +} + +void SAL_CALL ScDataPilotTablesObj::insertNewByName( const ::rtl::OUString& aNewName, + const table::CellAddress& aOutputAddress, + const uno::Reference<sheet::XDataPilotDescriptor>& xDescriptor ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!xDescriptor.is()) return; + + // inserting with already existing name? + if ( aNewName.getLength() && hasByName( aNewName ) ) + throw uno::RuntimeException(); // no other exceptions specified + + BOOL bDone = FALSE; + ScDataPilotDescriptorBase* pImp = ScDataPilotDescriptorBase::getImplementation( xDescriptor ); + if ( pDocShell && pImp ) + { + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pImp->GetParam( aParam, aQuery, aSrcArea ); + + aParam.nCol = (USHORT)aOutputAddress.Column; + aParam.nRow = (USHORT)aOutputAddress.Row; + aParam.nTab = aOutputAddress.Sheet; + + // in den Uno-Objekten sind alle Fields in den Descriptoren innerhalb des Bereichs gezaehlt + + short nFieldStart = aSrcArea.nColStart; + USHORT i; + for ( i=0; i<aParam.nColCount; i++ ) + if ( aParam.aColArr[i].nCol != PIVOT_DATA_FIELD ) + aParam.aColArr[i].nCol += nFieldStart; + for ( i=0; i<aParam.nRowCount; i++ ) + if ( aParam.aRowArr[i].nCol != PIVOT_DATA_FIELD ) + aParam.aRowArr[i].nCol += nFieldStart; + for ( i=0; i<aParam.nDataCount; i++ ) + if ( aParam.aDataArr[i].nCol != PIVOT_DATA_FIELD ) + aParam.aDataArr[i].nCol += nFieldStart; + + // Daten-Eintrag hinzufuegen, wenn noch nicht vorhanden + + BOOL bDataFound = FALSE; + for ( i=0; i<aParam.nColCount; i++ ) + if ( aParam.aColArr[i].nCol == PIVOT_DATA_FIELD ) + bDataFound = TRUE; + for ( i=0; i<aParam.nRowCount; i++ ) + if ( aParam.aRowArr[i].nCol == PIVOT_DATA_FIELD ) + bDataFound = TRUE; + if (!bDataFound) + { + if ( aParam.nRowCount < PIVOT_MAXFIELD ) + aParam.aRowArr[aParam.nRowCount++].nCol = PIVOT_DATA_FIELD; + else if ( aParam.nColCount < PIVOT_MAXFIELD ) + aParam.aColArr[aParam.nColCount++].nCol = PIVOT_DATA_FIELD; + else + throw uno::RuntimeException(); // no space for data field + } + + String aName = aNewName; + if (!aName.Len()) + aName = lcl_CreatePivotName( pDocShell ); + String aTag = xDescriptor->getTag(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScPivot* pNewPivot = new ScPivot( pDoc ); + pNewPivot->SetName( aName ); + pNewPivot->SetTag( aTag ); + pNewPivot->SetParam( aParam, aQuery, aSrcArea ); + + ScDPObject* pNewObj = new ScDPObject( pDoc ); + pNewObj->InitFromOldPivot( *pNewPivot, pDoc, TRUE ); + lcl_SetLayoutNamesToObject( pDoc, aParam, aSrcArea, *pNewObj ); + + ScDBDocFunc aFunc(*pDocShell); + bDone = aFunc.DataPilotUpdate( NULL, pNewObj, TRUE, TRUE ); + + delete pNewObj; // DataPilotUpdate copies settings from "new" object + delete pNewPivot; + } + + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScDataPilotTablesObj::removeByName( const ::rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aNameStr = aName; + ScDPObject* pDPObj = lcl_GetDPObject( pDocShell, nTab, aNameStr ); + if (pDPObj && pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + aFunc.DataPilotUpdate( pDPObj, NULL, TRUE, TRUE ); // remove - incl. undo etc. + } + else + throw uno::RuntimeException(); // no other exceptions specified +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScDataPilotTablesObj::createEnumeration() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScIndexEnumeration(this, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotTablesEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + + USHORT nFound = 0; + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + ++nFound; + } + return nFound; + } + } + + return 0; +} + +uno::Any SAL_CALL ScDataPilotTablesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + uno::Reference<sheet::XDataPilotTable> xTable = GetObjectByIndex_Impl((USHORT)nIndex); + uno::Any aAny; + if (xTable.is()) + aAny <<= xTable; + else + throw lang::IndexOutOfBoundsException(); + return aAny; +} + +uno::Type SAL_CALL ScDataPilotTablesObj::getElementType() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return getCppuType((uno::Reference<sheet::XDataPilotTable>*)0); +} + +sal_Bool SAL_CALL ScDataPilotTablesObj::hasElements() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return ( getCount() != 0 ); +} + +// XNameAccess + +uno::Any SAL_CALL ScDataPilotTablesObj::getByName( const ::rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + uno::Reference<sheet::XDataPilotTable> xTable = GetObjectByName_Impl(aName); + uno::Any aAny; + if (xTable.is()) + aAny <<= xTable; + else + throw container::NoSuchElementException(); + return aAny; +} + +uno::Sequence< ::rtl::OUString> SAL_CALL ScDataPilotTablesObj::getElementNames() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + + USHORT nFound = 0; + USHORT nCount = pColl->GetCount(); + USHORT i; + for (i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + ++nFound; + } + + USHORT nPos = 0; + uno::Sequence< ::rtl::OUString> aSeq(nFound); + ::rtl::OUString* pAry = aSeq.getArray(); + for (i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab ) + pAry[nPos++] = pDPObj->GetName(); + } + + return aSeq; + } + } + return uno::Sequence< ::rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const ::rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + String aNamStr = aName; + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + // api only handles sheet data at this time + //! allow all data sources!!! + + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->IsSheetData() && + pDPObj->GetOutRange().aStart.Tab() == nTab && + pDPObj->GetName() == aNamStr ) + return TRUE; + } + } + } + return FALSE; +} + +//------------------------------------------------------------------------ + +ScDataPilotDescriptorBase::ScDataPilotDescriptorBase(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDataPilotDescriptorBase::~ScDataPilotDescriptorBase() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +uno::Any SAL_CALL ScDataPilotDescriptorBase::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XDataPilotDescriptor ) + SC_QUERYINTERFACE( container::XNamed ) // base of XDataPilotDescriptor + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( lang::XTypeProvider ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + + return OWeakObject::queryInterface( rType ); +} + +void SAL_CALL ScDataPilotDescriptorBase::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL ScDataPilotDescriptorBase::release() throw() +{ + OWeakObject::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScDataPilotDescriptorBase::getTypes() + throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + aTypes.realloc(4); + uno::Type* pPtr = aTypes.getArray(); + pPtr[0] = getCppuType((const uno::Reference<sheet::XDataPilotDescriptor>*)0); + pPtr[1] = getCppuType((const uno::Reference<lang::XUnoTunnel>*)0); + pPtr[2] = getCppuType((const uno::Reference<lang::XTypeProvider>*)0); + pPtr[3] = getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScDataPilotDescriptorBase::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +void ScDataPilotDescriptorBase::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + //! Referenz-Update? + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDataPilotDescriptor + +table::CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + GetParam( aParam, aQuery, aSrcArea ); + + table::CellRangeAddress aRet; + aRet.Sheet = aSrcArea.nTab; + aRet.StartColumn = aSrcArea.nColStart; + aRet.StartRow = aSrcArea.nRowStart; + aRet.EndColumn = aSrcArea.nColEnd; + aRet.EndRow = aSrcArea.nRowEnd; + return aRet; +} + +void SAL_CALL ScDataPilotDescriptorBase::setSourceRange( + const table::CellRangeAddress& aSourceRange ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + GetParam( aParam, aQuery, aSrcArea ); + + aSrcArea.nTab = aSourceRange.Sheet; + aSrcArea.nColStart = (USHORT)aSourceRange.StartColumn; + aSrcArea.nRowStart = (USHORT)aSourceRange.StartRow; + aSrcArea.nColEnd = (USHORT)aSourceRange.EndColumn; + aSrcArea.nRowEnd = (USHORT)aSourceRange.EndRow; + + SetParam( aParam, aQuery, aSrcArea ); +} + +uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScDataPilotDescriptorBase::getFilterDescriptor() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFilterDescriptor( pDocShell, this ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataPilotFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, SC_FIELDORIENT_ALL ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getColumnFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, DATA_PILOT_COLUMN ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getRowFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, DATA_PILOT_ROW ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getPageFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, DATA_PILOT_PAGE ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, DATA_PILOT_DATA ); +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getHiddenFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScDataPilotFieldsObj( this, DATA_PILOT_HIDDEN ); +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScDataPilotDescriptorBase::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return (sal_Int64)this; + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScDataPilotDescriptorBase::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation( + const uno::Reference<sheet::XDataPilotDescriptor> xObj ) +{ + ScDataPilotDescriptorBase* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = (ScDataPilotDescriptorBase*) xUT->getSomething( getUnoTunnelId() ); + return pRet; +} + +//------------------------------------------------------------------------ + +ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, USHORT nT, const String& rN) : + ScDataPilotDescriptorBase( pDocSh ), + nTab( nT ), + aName( rN ) +{ +} + +ScDataPilotTableObj::~ScDataPilotTableObj() +{ +} + +uno::Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XDataPilotTable ) + + return ScDataPilotDescriptorBase::queryInterface( rType ); +} + +void SAL_CALL ScDataPilotTableObj::acquire() throw() +{ + ScDataPilotDescriptorBase::acquire(); +} + +void SAL_CALL ScDataPilotTableObj::release() throw() +{ + ScDataPilotDescriptorBase::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScDataPilotTableObj::getTypes() + throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes = ScDataPilotDescriptorBase::getTypes(); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 1 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XDataPilotTable>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScDataPilotTableObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// --- + +void ScDataPilotTableObj::GetParam( ScPivotParam& rParam, ScQueryParam& rQuery, ScArea& rSrcArea ) const +{ + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + const ScSheetSourceDesc* pSheetDesc = pDPObj->GetSheetDesc(); + if ( pSheetDesc ) + { + // FALSE -> fields are counted within the source range + pDPObj->FillOldParam( rParam, FALSE ); + + rSrcArea = ScArea( pSheetDesc->aSourceRange.aStart.Tab(), + pSheetDesc->aSourceRange.aStart.Col(), + pSheetDesc->aSourceRange.aStart.Row(), + pSheetDesc->aSourceRange.aEnd.Col(), + pSheetDesc->aSourceRange.aEnd.Row() ); + rQuery = pSheetDesc->aQueryParam; + + // in the Uno objects all fields in descriptors are counted within the source range + // fields in ScPivotParam are correct (bForFile=FALSE in FillOldParam), + // ScQueryParam still has to be adjusted: + + short nFieldStart = rSrcArea.nColStart; + USHORT nQueryCount = rQuery.GetEntryCount(); + for ( USHORT i=0; i<nQueryCount; i++ ) + { + ScQueryEntry& rEntry = rQuery.GetEntry(i); + if (rEntry.bDoQuery && rEntry.nField >= nFieldStart) + rEntry.nField -= nFieldStart; + } + + lcl_SetLayoutNamesToParam( rParam, GetDocShell()->GetDocument(), rSrcArea, *pDPObj ); + } + } +} + +void ScDataPilotTableObj::SetParam( const ScPivotParam& rParam, + const ScQueryParam& rQuery, const ScArea& rSrcArea ) +{ + ScDocShell* pDocShell = GetDocShell(); + ScDPObject* pDPObj = lcl_GetDPObject(pDocShell, nTab, aName); + if ( pDPObj && pDocShell ) + { + // in den Uno-Objekten sind alle Fields in den Descriptoren innerhalb des Bereichs gezaehlt + + ScPivotParam aNewParam( rParam ); + short nFieldStart = rSrcArea.nColStart; + USHORT i; + for ( i=0; i<aNewParam.nColCount; i++ ) + if ( aNewParam.aColArr[i].nCol != PIVOT_DATA_FIELD ) + aNewParam.aColArr[i].nCol += nFieldStart; + for ( i=0; i<aNewParam.nRowCount; i++ ) + if ( aNewParam.aRowArr[i].nCol != PIVOT_DATA_FIELD ) + aNewParam.aRowArr[i].nCol += nFieldStart; + for ( i=0; i<aNewParam.nDataCount; i++ ) + if ( aNewParam.aDataArr[i].nCol != PIVOT_DATA_FIELD ) + aNewParam.aDataArr[i].nCol += nFieldStart; + + ScQueryParam aNewQuery( rQuery ); + USHORT nQueryCount = aNewQuery.GetEntryCount(); + for ( i=0; i<nQueryCount; i++ ) + { + ScQueryEntry& rEntry = aNewQuery.GetEntry(i); + if (rEntry.bDoQuery) + rEntry.nField += nFieldStart; + } + +// ScPivot* pNew = new ScPivot(*pPivot); //? behaelt falsche Groessenangaben bei... + + ScDocument* pDoc = pDocShell->GetDocument(); + ScPivot* pNew = new ScPivot( pDoc ); + pNew->SetName( pDPObj->GetName() ); + pNew->SetTag( pDPObj->GetTag() ); + pNew->SetParam( aNewParam, aNewQuery, rSrcArea ); + + ScDPObject* pNewObj = new ScDPObject( pDoc ); + pNewObj->InitFromOldPivot( *pNew, pDoc, TRUE ); + lcl_SetLayoutNamesToObject( pDoc, aNewParam, rSrcArea, *pNewObj ); + + ScDBDocFunc aFunc(*pDocShell); + aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, TRUE ); + + delete pNewObj; // DataPilotUpdate copies settings from "new" object + delete pNew; + } +} + +// "rest of XDataPilotDescriptor" + +::rtl::OUString SAL_CALL ScDataPilotTableObj::getName() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + return pDPObj->GetName(); + return ::rtl::OUString(); +} + +void SAL_CALL ScDataPilotTableObj::setName( const ::rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + //! test for existing names !!! + + String aString = aNewName; + pDPObj->SetName( aString ); //! Undo - DBDocFunc ??? + aName = aString; + + // DataPilotUpdate would do too much (output table is not changed) + GetDocShell()->SetDocumentModified(); + } +} + +::rtl::OUString SAL_CALL ScDataPilotTableObj::getTag() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + return pDPObj->GetTag(); + return ::rtl::OUString(); +} + +void SAL_CALL ScDataPilotTableObj::setTag( const ::rtl::OUString& aNewTag ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + String aString = aNewTag; + pDPObj->SetTag( aString ); //! Undo - DBDocFunc ??? + + // DataPilotUpdate would do too much (output table is not changed) + GetDocShell()->SetDocumentModified(); + } +} + +// XDataPilotTable + +table::CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRange() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + table::CellRangeAddress aRet; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + ScRange aRange = pDPObj->GetOutRange(); + aRet.Sheet = aRange.aStart.Tab(); + aRet.StartColumn = aRange.aStart.Col(); + aRet.StartRow = aRange.aStart.Row(); + aRet.EndColumn = aRange.aEnd.Col(); + aRet.EndRow = aRange.aEnd.Row(); + } + return aRet; +} + +void SAL_CALL ScDataPilotTableObj::refresh() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + ScDPObject* pNew = new ScDPObject(*pDPObj); + ScDBDocFunc aFunc(*GetDocShell()); + aFunc.DataPilotUpdate( pDPObj, pNew, TRUE, TRUE ); + delete pNew; // DataPilotUpdate copies settings from "new" object + } +} + +//------------------------------------------------------------------------ + +ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) : + ScDataPilotDescriptorBase( pDocSh ) +{ +} + +ScDataPilotDescriptor::~ScDataPilotDescriptor() +{ +} + +void ScDataPilotDescriptor::GetParam( ScPivotParam& rParam, ScQueryParam& rQuery, + ScArea& rSrcArea ) const +{ + // Fields sind und bleiben innerhalb des Bereichs + + rParam = aParam; + rQuery = aQuery; + rSrcArea = aSrcArea; +} + +void ScDataPilotDescriptor::SetParam( const ScPivotParam& rParam, + const ScQueryParam& rQuery, const ScArea& rSrcArea ) +{ + // Fields sind und bleiben innerhalb des Bereichs + + aParam = rParam; + aQuery = rQuery; + aSrcArea = rSrcArea; +} + +// "rest of XDataPilotDescriptor" + +::rtl::OUString SAL_CALL ScDataPilotDescriptor::getName() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return aNameStr; +} + +void SAL_CALL ScDataPilotDescriptor::setName( const ::rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + aNameStr = String( aNewName ); +} + +::rtl::OUString SAL_CALL ScDataPilotDescriptor::getTag() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return aTagStr; +} + +void SAL_CALL ScDataPilotDescriptor::setTag( const ::rtl::OUString& aNewTag ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + aTagStr = String( aNewTag ); +} + +//------------------------------------------------------------------------ + +ScDataPilotFieldsObj::ScDataPilotFieldsObj(ScDataPilotDescriptorBase* pPar, USHORT nTy) : + pParent( pPar ), + nType( nTy ) +{ + pParent->acquire(); +} + +ScDataPilotFieldsObj::~ScDataPilotFieldsObj() +{ + pParent->release(); +} + +USHORT lcl_GetFieldCount( const ScPivotParam& rParam, const ScArea& rSrcArea, USHORT nType ) +{ + USHORT nRet = 0; + + USHORT nDataCount = lcl_DataCount(rParam); + // Daten-Feld bei Spalten oder Zeile, wenn mehr als 1 Eintrag + + USHORT i; + switch (nType) + { + case SC_FIELDORIENT_ALL: + // Anzahl Spalten im Datenbereich + // plus eins fuer das Datenfeld (immer) + nRet = rSrcArea.nColEnd - rSrcArea.nColStart + 2; + break; + case DATA_PILOT_HIDDEN: + { + //! Datenfeld auch hier? + USHORT nColCount = rSrcArea.nColEnd - rSrcArea.nColStart + 1; + for (USHORT nSrcField=0; nSrcField<nColCount; nSrcField++) + { + BOOL bUsed = FALSE; + for (i=0; i<rParam.nColCount; i++) + if ( rParam.aColArr[i].nCol == nSrcField ) bUsed = TRUE; + for (i=0; i<rParam.nRowCount; i++) + if ( rParam.aRowArr[i].nCol == nSrcField ) bUsed = TRUE; + for (i=0; i<rParam.nDataCount; i++) + if ( rParam.aDataArr[i].nCol == nSrcField ) bUsed = TRUE; + if (!bUsed) + ++nRet; + } + } + break; + case DATA_PILOT_COLUMN: + for (i=0; i<rParam.nColCount; i++) + if ( rParam.aColArr[i].nCol != PIVOT_DATA_FIELD || nDataCount > 1 ) + ++nRet; + break; + case DATA_PILOT_ROW: + for (i=0; i<rParam.nRowCount; i++) + if ( rParam.aRowArr[i].nCol != PIVOT_DATA_FIELD || nDataCount > 1 ) + ++nRet; + break; + case DATA_PILOT_PAGE: + nRet = 0; // Page-Fields sind nicht implementiert + break; + case DATA_PILOT_DATA: + nRet = nDataCount; + break; + } + + return nRet; +} + +BOOL lcl_GetFieldDataByIndex( const ScPivotParam& rParam, const ScArea& rSrcArea, + USHORT nType, USHORT nIndex, USHORT& rField ) +{ + BOOL bOk = FALSE; + USHORT nPos = 0; + + USHORT nDataCount = lcl_DataCount(rParam); + // Daten-Feld bei Spalten oder Zeile, wenn mehr als 1 Eintrag + + USHORT i; + switch (nType) + { + case SC_FIELDORIENT_ALL: + { + USHORT nSourceCount = rSrcArea.nColEnd - rSrcArea.nColStart + 1; + if ( nIndex < nSourceCount ) + { + rField = nIndex; + bOk = TRUE; + } + else if ( nIndex == nSourceCount ) + { + rField = PIVOT_DATA_FIELD; + bOk = TRUE; + } + } + break; + case DATA_PILOT_HIDDEN: + { + //! Datenfeld auch hier? + USHORT nColCount = rSrcArea.nColEnd - rSrcArea.nColStart + 1; + for (USHORT nSrcField=0; nSrcField<nColCount; nSrcField++) + { + BOOL bUsed = FALSE; + for (i=0; i<rParam.nColCount; i++) + if ( rParam.aColArr[i].nCol == nSrcField ) bUsed = TRUE; + for (i=0; i<rParam.nRowCount; i++) + if ( rParam.aRowArr[i].nCol == nSrcField ) bUsed = TRUE; + for (i=0; i<rParam.nDataCount; i++) + if ( rParam.aDataArr[i].nCol == nSrcField ) bUsed = TRUE; + if (!bUsed) + { + if ( nPos == nIndex ) + { + rField = nSrcField; + bOk = TRUE; + } + ++nPos; + } + } + } + break; + case DATA_PILOT_COLUMN: + for (i=0; i<rParam.nColCount; i++) + if ( rParam.aColArr[i].nCol != PIVOT_DATA_FIELD || nDataCount > 1 ) + { + if ( nPos == nIndex ) + { + rField = rParam.aColArr[i].nCol; + bOk = TRUE; + } + ++nPos; + } + break; + case DATA_PILOT_ROW: + for (i=0; i<rParam.nRowCount; i++) + if ( rParam.aRowArr[i].nCol != PIVOT_DATA_FIELD || nDataCount > 1 ) + { + if ( nPos == nIndex ) + { + rField = rParam.aRowArr[i].nCol; + bOk = TRUE; + } + ++nPos; + } + break; + case DATA_PILOT_PAGE: + break; // Page-Fields sind nicht implementiert + case DATA_PILOT_DATA: + { + USHORT nArrayPos, nFuncBit; + if ( lcl_GetDataArrayPos( rParam, nIndex, nArrayPos, nFuncBit ) ) + { + rField = rParam.aDataArr[nArrayPos].nCol; + bOk = TRUE; + } + } + break; + } + return bOk; +} + +String lcl_FieldName( ScDocShell* pDocSh, const ScPivotParam& rParam, + const ScArea& rSrcArea, USHORT nField ) +{ + String aRet; + if ( nField == PIVOT_DATA_FIELD ) + aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Data")); //! ??? + else + { + USHORT nCol = rSrcArea.nColStart + nField; + if ( pDocSh && nCol <= rSrcArea.nColEnd ) + { + USHORT nRow = rSrcArea.nRowStart; + aRet = lcl_ColumnTitle( pDocSh->GetDocument(), nCol, nRow, rSrcArea.nTab ); + + // layout names from SaveData are in PivotParam LabelData + + if ( nField < rParam.nLabels && rParam.ppLabelArr && + rParam.ppLabelArr[nField] && + rParam.ppLabelArr[nField]->pStrColName && + rParam.ppLabelArr[nField]->pStrColName->Len() ) + aRet = *rParam.ppLabelArr[nField]->pStrColName; + } + } + return aRet; +} + +void lcl_SetFieldName( ScPivotParam& rParam, USHORT nField, const String& rNewName ) +{ + USHORT nNewCount = Max( rParam.nLabels, (USHORT)( nField + 1 ) ); + USHORT i; + + LabelData** ppNewData = new LabelData*[nNewCount]; + for (i=0; i<nNewCount; i++) + { + if ( i == nField ) + ppNewData[i] = new LabelData( rNewName, 0, FALSE ); + else if ( i < rParam.nLabels && rParam.ppLabelArr && rParam.ppLabelArr[i] ) + ppNewData[i] = new LabelData( *rParam.ppLabelArr[i] ); + else + ppNewData[i] = new LabelData( EMPTY_STRING, 0, FALSE ); + } + + rParam.SetLabelData( ppNewData, nNewCount ); + + // SetLabelData copies data - ppNewData must be deleted + for (i=0; i<nNewCount; i++) + delete ppNewData[i]; + delete[] ppNewData; +} + +// XDataPilotFields + +ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByIndex_Impl(USHORT nIndex) const +{ + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + USHORT nField = 0; + BOOL bOk = lcl_GetFieldDataByIndex( aParam, aSrcArea, nType, nIndex, nField ); + + if (bOk) + return new ScDataPilotFieldObj( pParent, nField, nType, nIndex ); + + return NULL; +} + +ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByName_Impl(const ::rtl::OUString& aName) const +{ + String aNameStr = aName; + + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + ScDocShell* pDocSh = pParent->GetDocShell(); + USHORT nCount = lcl_GetFieldCount( aParam, aSrcArea, nType ); + USHORT nField = 0; + for (USHORT i=0; i<nCount; i++) + { + if (lcl_GetFieldDataByIndex( aParam, aSrcArea, nType, i, nField )) + { + if ( aNameStr == lcl_FieldName( pDocSh, aParam, aSrcArea, nField ) ) + return new ScDataPilotFieldObj( pParent, nField, nType, i ); + } + } + return NULL; +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScDataPilotFieldsObj::createEnumeration() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScIndexEnumeration(this, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotFieldsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotFieldsObj::getCount() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + return lcl_GetFieldCount( aParam, aSrcArea, nType ); +} + +uno::Any SAL_CALL ScDataPilotFieldsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + uno::Reference<beans::XPropertySet> xField = GetObjectByIndex_Impl((USHORT)nIndex); + uno::Any aAny; + if (xField.is()) + aAny <<= xField; + else + throw lang::IndexOutOfBoundsException(); + return aAny; +} + +uno::Type SAL_CALL ScDataPilotFieldsObj::getElementType() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return getCppuType((uno::Reference<beans::XPropertySet>*)0); +} + +sal_Bool SAL_CALL ScDataPilotFieldsObj::hasElements() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScDataPilotFieldsObj::getByName( const ::rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + uno::Reference<beans::XPropertySet> xField = GetObjectByName_Impl(aName); + uno::Any aAny; + if (xField.is()) + aAny <<= xField; + else + throw container::NoSuchElementException(); + return aAny; +} + +uno::Sequence< ::rtl::OUString> SAL_CALL ScDataPilotFieldsObj::getElementNames() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + ScDocShell* pDocSh = pParent->GetDocShell(); + USHORT nCount = lcl_GetFieldCount( aParam, aSrcArea, nType ); + USHORT nField = 0; + + uno::Sequence< ::rtl::OUString> aSeq(nCount); + ::rtl::OUString* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + { + lcl_GetFieldDataByIndex( aParam, aSrcArea, nType, i, nField ); + String aName = lcl_FieldName( pDocSh, aParam, aSrcArea, nField ); + pAry[i] = aName; + } + return aSeq; +} + +sal_Bool SAL_CALL ScDataPilotFieldsObj::hasByName( const ::rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aNameStr = aName; + + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + ScDocShell* pDocSh = pParent->GetDocShell(); + USHORT nCount = lcl_GetFieldCount( aParam, aSrcArea, nType ); + USHORT nField = 0; + for (USHORT i=0; i<nCount; i++) + { + if (lcl_GetFieldDataByIndex( aParam, aSrcArea, nType, i, nField )) + { + if ( aNameStr == lcl_FieldName( pDocSh, aParam, aSrcArea, nField ) ) + return TRUE; + } + } + return FALSE; +} + +//------------------------------------------------------------------------ + +ScDataPilotFieldObj::ScDataPilotFieldObj( ScDataPilotDescriptorBase* pPar, + USHORT nF, USHORT nST, USHORT nSP ) : + aPropSet( lcl_GetDataPilotFieldMap() ), + pParent( pPar ), + nField( nF ), + nSourceType( nST ), + nSourcePos( nSP ), + nLastFunc( sheet::GeneralFunction_NONE ) +{ + pParent->acquire(); +} + +ScDataPilotFieldObj::~ScDataPilotFieldObj() +{ + pParent->release(); +} + +// XNamed + +::rtl::OUString SAL_CALL ScDataPilotFieldObj::getName() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + String aRet = lcl_FieldName( pParent->GetDocShell(), aParam, aSrcArea, nField ); + + return aRet; +} + +void SAL_CALL ScDataPilotFieldObj::setName( const ::rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + if ( nField == PIVOT_DATA_FIELD ) + { + //! ... ??? + } + else + lcl_SetFieldName( aParam, nField, aNewName ); + + pParent->SetParam( aParam, aQuery, aSrcArea ); +} + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDataPilotFieldObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ); + return aRef; +} + +void SAL_CALL ScDataPilotFieldObj::setPropertyValue( + const ::rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aNameString = aPropertyName; + if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) ) + { + //! test for correct enum type? + sheet::GeneralFunction eFunction = (sheet::GeneralFunction) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + setFunction( eFunction ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) ) + { + //! test for correct enum type? + sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + setOrientation( eOrient ); + } +} + +uno::Any SAL_CALL ScDataPilotFieldObj::getPropertyValue( const ::rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aNameString = aPropertyName; + uno::Any aRet; + + if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) ) + { + sheet::GeneralFunction eFunction = getFunction(); + aRet <<= eFunction; + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) ) + { + sheet::DataPilotFieldOrientation eOrient = getOrientation(); + aRet <<= eOrient; + } + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDataPilotFieldObj ) + +void lcl_FindUsage( const ScPivotParam& rParam, USHORT nField, USHORT& rType, USHORT& rPos ) +{ + USHORT i; + for (i=0; i<rParam.nColCount; i++) + if ( rParam.aColArr[i].nCol == nField ) + { + rType = DATA_PILOT_COLUMN; + rPos = i; + return; + } + for (i=0; i<rParam.nRowCount; i++) + if ( rParam.aRowArr[i].nCol == nField ) + { + rType = DATA_PILOT_ROW; + rPos = i; + return; + } + USHORT nBitCount = 0; + for (i=0; i<rParam.nDataCount; i++) + { + if ( rParam.aDataArr[i].nCol == nField ) + { + rType = DATA_PILOT_DATA; + rPos = nBitCount; // Uno-Index der ersten Funktion + return; + } + nBitCount += lcl_BitCount( rParam.aDataArr[i].nFuncMask ); + } + //! DATA_PILOT_HIDDEN zurueck - Position suchen +} + +sheet::DataPilotFieldOrientation ScDataPilotFieldObj::getOrientation(void) const +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + USHORT nType = nSourceType; + USHORT nPos = nSourcePos; + if ( nType == SC_FIELDORIENT_ALL ) + lcl_FindUsage( aParam, nField, nType, nPos ); + + if ( nType == SC_FIELDORIENT_ALL ) // bei FindUsage nicht gefunden + nType = DATA_PILOT_HIDDEN; // nicht verwendet + + return (sheet::DataPilotFieldOrientation)nType; +} + +void lcl_RemoveField( PivotField* pFields, USHORT& rCount, USHORT nField ) +{ + for (USHORT i=0; i<rCount; i++) + if (pFields[i].nCol == nField) + { + for (USHORT j=i; j+1<rCount; j++) + pFields[j] = pFields[j+1]; + --rCount; + return; // nicht weitersuchen + } +} + +void ScDataPilotFieldObj::setOrientation(sheet::DataPilotFieldOrientation eNew) +{ + SolarMutexGuard aGuard; + if ( eNew == nSourceType ) + return; // nix + + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + // aus altem Array entfernen + + switch (nSourceType) + { + case DATA_PILOT_COLUMN: + if ( nSourcePos < aParam.nColCount ) + { + for (USHORT i=nSourcePos; i+1<aParam.nColCount; i++) + aParam.aColArr[i] = aParam.aColArr[i+1]; + --aParam.nColCount; + } + break; + case DATA_PILOT_ROW: + if ( nSourcePos < aParam.nRowCount ) + { + for (USHORT i=nSourcePos; i+1<aParam.nRowCount; i++) + aParam.aRowArr[i] = aParam.aRowArr[i+1]; + --aParam.nRowCount; + } + break; + case DATA_PILOT_DATA: + { + USHORT nArrayPos, nFuncBit; + if ( lcl_GetDataArrayPos( aParam, nSourcePos, nArrayPos, nFuncBit ) ) + { + aParam.aDataArr[nArrayPos].nFuncMask &= ~nFuncBit; // Funktion weglassen + if (!aParam.aDataArr[nArrayPos].nFuncMask) // war's die letzte? + { + for (USHORT j=nArrayPos; j+1<aParam.nDataCount; j++) + aParam.aDataArr[j] = aParam.aDataArr[j+1]; + --aParam.nDataCount; + } + } + } + break; + + // SC_FIELDORIENT_ALL, DATA_PILOT_HIDDEN: nichts + } + + // if Function was set for this object, use that value; + // default otherwise (0 for SubTotals, SUM for data) + USHORT nNewBit = ScDataPilotConversion::FunctionBit( (sheet::GeneralFunction)nLastFunc ); + + // in neues Array eintragen + + switch (eNew) + { + case DATA_PILOT_COLUMN: + if ( aParam.nColCount < PIVOT_MAXFIELD ) + { + lcl_RemoveField( aParam.aColArr, aParam.nColCount, nField ); // nicht doppelt + lcl_RemoveField( aParam.aRowArr, aParam.nRowCount, nField ); + aParam.aColArr[aParam.nColCount].nCol = nField; + aParam.aColArr[aParam.nColCount].nFuncMask = nNewBit; + nSourceType = DATA_PILOT_COLUMN; + nSourcePos = aParam.nColCount; + ++aParam.nColCount; + } + break; + case DATA_PILOT_ROW: + if ( aParam.nRowCount < PIVOT_MAXFIELD ) + { + lcl_RemoveField( aParam.aColArr, aParam.nColCount, nField ); // nicht doppelt + lcl_RemoveField( aParam.aRowArr, aParam.nRowCount, nField ); + aParam.aRowArr[aParam.nRowCount].nCol = nField; + aParam.aRowArr[aParam.nRowCount].nFuncMask = nNewBit; + nSourceType = DATA_PILOT_ROW; + nSourcePos = aParam.nRowCount; + ++aParam.nRowCount; + } + break; + case DATA_PILOT_DATA: + if ( aParam.nDataCount < PIVOT_MAXFIELD ) + { + //! ggf. mit bestehendem Eintrag zusammenfassen (Funktionen verodern) ??? + aParam.aDataArr[aParam.nDataCount].nCol = nField; + if ( nNewBit == 0 ) + nNewBit = PIVOT_FUNC_SUM; + aParam.aDataArr[aParam.nDataCount].nFuncMask = nNewBit; + nSourceType = DATA_PILOT_DATA; + nSourcePos = aParam.nDataCount; + ++aParam.nDataCount; + } + break; + default: // PAGE or HIDDEN + nSourceType = eNew; + nSourcePos = 0; + break; + } + + pParent->SetParam( aParam, aQuery, aSrcArea ); +} + +sheet::GeneralFunction ScDataPilotFieldObj::getFunction(void) const +{ + SolarMutexGuard aGuard; + sheet::GeneralFunction eRet = sheet::GeneralFunction_NONE; + + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + USHORT nType = nSourceType; + USHORT nPos = nSourcePos; + if ( nType == SC_FIELDORIENT_ALL ) + lcl_FindUsage( aParam, nField, nType, nPos ); + + switch ( nType ) + { + case DATA_PILOT_COLUMN: + if ( nPos < aParam.nColCount ) + eRet = ScDataPilotConversion::FirstFunc( aParam.aColArr[nPos].nFuncMask ); + break; + case DATA_PILOT_ROW: + if ( nPos < aParam.nRowCount ) + eRet = ScDataPilotConversion::FirstFunc( aParam.aRowArr[nPos].nFuncMask ); + break; + case DATA_PILOT_DATA: // Bits zaehlen... + { + USHORT nArrayPos, nFuncBit; + if ( lcl_GetDataArrayPos( aParam, nPos, nArrayPos, nFuncBit ) ) + eRet = ScDataPilotConversion::FirstFunc( nFuncBit ); + } + break; + default: + // if Function has been set for this object, return that value + eRet = (sheet::GeneralFunction) nLastFunc; + } + return eRet; +} + +void ScDataPilotFieldObj::setFunction(sheet::GeneralFunction eNewFunc) +{ + SolarMutexGuard aGuard; + ScPivotParam aParam; + ScQueryParam aQuery; + ScArea aSrcArea; + pParent->GetParam( aParam, aQuery, aSrcArea ); + + USHORT nType = nSourceType; + USHORT nPos = nSourcePos; + if ( nType == SC_FIELDORIENT_ALL ) + lcl_FindUsage( aParam, nField, nType, nPos ); + + switch ( nType ) + { + case DATA_PILOT_COLUMN: + if ( nPos < aParam.nColCount ) + aParam.aColArr[nPos].nFuncMask = ScDataPilotConversion::FunctionBit(eNewFunc); + break; + case DATA_PILOT_ROW: + if ( nPos < aParam.nRowCount ) + aParam.aRowArr[nPos].nFuncMask = ScDataPilotConversion::FunctionBit(eNewFunc); + break; + case DATA_PILOT_DATA: // Bits zaehlen... + { + USHORT nArrayPos, nFuncBit; + if ( lcl_GetDataArrayPos( aParam, nPos, nArrayPos, nFuncBit ) ) + { + // alte Funktion weglassen, neue eintragen + aParam.aDataArr[nArrayPos].nFuncMask &= ~nFuncBit; + aParam.aDataArr[nArrayPos].nFuncMask |= ScDataPilotConversion::FunctionBit(eNewFunc); + } + } + break; + } + + pParent->SetParam( aParam, aQuery, aSrcArea ); + + nLastFunc = eNewFunc; // to allow setting Function before Orientation +} + + +//------------------------------------------------------------------------ + + + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |