summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/dpobject.cxx11
-rw-r--r--sc/source/core/data/dpoutput.cxx12
-rw-r--r--sc/source/core/tool/hints.cxx10
-rw-r--r--sc/source/filter/xml/xmldpimp.cxx2
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx6
-rw-r--r--sc/source/ui/undo/undodat.cxx7
-rw-r--r--sc/source/ui/unoobj/chart2uno.cxx1714
-rw-r--r--sc/source/ui/unoobj/dapiuno.cxx247
8 files changed, 983 insertions, 1026 deletions
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 66ac3a4bedbb..7d1dd85c0a25 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -784,13 +784,10 @@ bool ScDPObject::IsDimNameInUse(const OUString& rName) const
if (!xPropSet.is())
continue;
- Any any = xPropSet->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME));
- OUString aLayoutName;
- if (any >>= aLayoutName)
- {
- if (aLayoutName.equalsIgnoreAsciiCase(rName))
- return true;
- }
+ OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty(
+ xPropSet, OUString::createFromAscii(SC_UNO_LAYOUTNAME), OUString());
+ if (aLayoutName.equalsIgnoreAsciiCase(rName))
+ return true;
}
return false;
}
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index 7ecdc3d34702..401d9b396bc0 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -451,14 +451,12 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
if ( xLevNam.is() && xLevRes.is() )
{
String aName = xLevNam->getName();
- OUString aCaption = aName; // Caption equals the field name by default.
Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY);
- if (xPropSet.is())
- {
- Any any = xPropSet->getPropertyValue(
- OUString::createFromAscii(SC_UNO_LAYOUTNAME));
- any >>= aCaption;
- }
+ // Caption equals the field name by default.
+ // #i108948# use ScUnoHelpFunctions::GetStringProperty, because
+ // LayoutName is new and may not be present in external implementation
+ OUString aCaption = ScUnoHelpFunctions::GetStringProperty( xPropSet,
+ OUString::createFromAscii(SC_UNO_LAYOUTNAME), aName );
bool bRowFieldHasMember = false;
switch ( eDimOrient )
diff --git a/sc/source/core/tool/hints.cxx b/sc/source/core/tool/hints.cxx
index e2bcb11fc573..b2a8266705c7 100644
--- a/sc/source/core/tool/hints.cxx
+++ b/sc/source/core/tool/hints.cxx
@@ -40,6 +40,7 @@ TYPEINIT1(ScPointerChangedHint, SfxHint);
TYPEINIT1(ScLinkRefreshedHint, SfxHint);
TYPEINIT1(ScAutoStyleHint, SfxHint);
TYPEINIT1(ScDBRangeRefreshedHint, SfxHint);
+TYPEINIT1(ScDataPilotModifiedHint, SfxHint);
// -----------------------------------------------------------------------
// ScPaintHint - Angabe, was neu gezeichnet werden muss
@@ -150,3 +151,12 @@ ScDBRangeRefreshedHint::~ScDBRangeRefreshedHint()
}
+ScDataPilotModifiedHint::ScDataPilotModifiedHint( const String& rName )
+ : maName(rName)
+{
+}
+ScDataPilotModifiedHint::~ScDataPilotModifiedHint()
+{
+}
+
+
diff --git a/sc/source/filter/xml/xmldpimp.cxx b/sc/source/filter/xml/xmldpimp.cxx
index 580dd2ee0791..01dae48f6d84 100644
--- a/sc/source/filter/xml/xmldpimp.cxx
+++ b/sc/source/filter/xml/xmldpimp.cxx
@@ -428,7 +428,7 @@ void ScXMLDataPilotTableContext::EndElement()
break;
case SERVICE :
{
- ScDPServiceDesc aServiceDesk(sServiceName, sServiceSourceObject, sServiceSourceName,
+ ScDPServiceDesc aServiceDesk(sServiceName, sServiceSourceName, sServiceSourceObject,
sServiceUsername, sServicePassword);
pDPObject->SetServiceData(aServiceDesk);
}
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 1633af000b51..2053cebc8ce5 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -56,6 +56,7 @@
#include "attrib.hxx"
#include "drwlayer.hxx"
#include "dpshttab.hxx"
+#include "hints.hxx"
// -----------------------------------------------------------------
@@ -1403,7 +1404,12 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb
delete pUndoDPObj;
if (bDone)
+ {
+ // notify API objects
+ if (pDestObj)
+ pDoc->BroadcastUno( ScDataPilotModifiedHint( pDestObj->GetName() ) );
aModificator.SetDocumentModified();
+ }
if ( nErrId && !bApi )
rDocShell.ErrorMessage( nErrId );
diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx
index 2ed65d5db6f5..d550d54f1aea 100644
--- a/sc/source/ui/undo/undodat.cxx
+++ b/sc/source/ui/undo/undodat.cxx
@@ -50,6 +50,7 @@
#include "olinefun.hxx"
#include "dpobject.hxx"
#include "attrib.hxx"
+#include "hints.hxx"
#include "sc.hrc"
// -----------------------------------------------------------------------
@@ -1902,6 +1903,12 @@ void __EXPORT ScUndoDataPilot::Undo()
//! set current sheet
}
+ if (pNewDPObject)
+ {
+ // notify API objects
+ pDoc->BroadcastUno( ScDataPilotModifiedHint( pNewDPObject->GetName() ) );
+ }
+
EndUndo();
}
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index b8a751669e6f..8654de8a429e 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -118,61 +118,6 @@ template< typename T >
return aResult;
}
-::std::vector< ::rtl::OUString > lcl_getRangeRepresentationsFromDataSource(
- const uno::Reference< chart2::data::XDataSource > & xDataSource )
-{
- ::std::vector< ::rtl::OUString > aResult;
- if( xDataSource.is())
- {
- uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
- xDataSource->getDataSequences());
- const sal_Int32 nCount( aSequences.getLength());
- for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
- {
- if( aSequences[nIdx].is() )
- {
- // first: label
- uno::Reference< chart2::data::XDataSequence > xSeq( aSequences[nIdx]->getLabel());
- if( xSeq.is())
- aResult.push_back( xSeq->getSourceRangeRepresentation());
- // then: values
- xSeq.set( aSequences[nIdx]->getValues());
- if( xSeq.is())
- aResult.push_back( xSeq->getSourceRangeRepresentation());
- }
- }
- }
- return aResult;
-}
-
-uno::Reference< chart2::data::XLabeledDataSequence > lcl_getCategoriesFromDataSource(
- const uno::Reference< chart2::data::XDataSource > & xDataSource )
-{
- uno::Reference< chart2::data::XLabeledDataSequence > xResult;
- if( xDataSource.is())
- {
- uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
- xDataSource->getDataSequences());
- const sal_Int32 nCount( aSequences.getLength());
- for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
- {
- if( aSequences[nIdx].is() )
- {
- uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY );
- ::rtl::OUString aRole;
- if( xSeqProp.is() &&
- (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) &&
- aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
- {
- xResult.set( aSequences[nIdx] );
- break;
- }
- }
- }
- }
- return xResult;
-}
-
struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void >
{
lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) :
@@ -214,173 +159,290 @@ uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocu
// ============================================================================
-class Chart2PositionMap
+namespace {
+
+struct DeleteInstance : public unary_function<FormulaToken*, void>
{
-public:
- Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
- bool bColAdd, bool bRowAdd, Table& rCols);
- ~Chart2PositionMap();
+ void operator() (FormulaToken* p) const
+ {
+ delete p;
+ }
+};
- SCCOL getColCount() const { return static_cast<SCCOL>(maColHeaders.size()); }
- SCROW getRowCount() const { return static_cast<SCROW>(maRowHeaders.size()); }
+}
- const FormulaToken* getColHeaderPosition(SCCOL nChartCol) const;
- const FormulaToken* getRowHeaderPosition(SCROW nChartRow) const;
+struct TokenTable
+{
+ SCROW mnRowCount;
+ SCCOL mnColCount;
+ vector<FormulaToken*> maTokens;
- vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const;
- vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const;
+ void init( SCCOL nColCount, SCROW nRowCount )
+ {
+ mnColCount = nColCount;
+ mnRowCount = nRowCount;
+ maTokens.reserve(mnColCount*mnRowCount);
+ }
+ void clear()
+ {
+ for_each(maTokens.begin(), maTokens.end(), DeleteInstance());
+ }
+ void push_back( FormulaToken* pToken )
+ {
+ maTokens.push_back( pToken );
+ DBG_ASSERT( maTokens.size()<= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too much tokens" );
+ }
-private:
sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const
{
- return static_cast<sal_uInt32>(nCol*getRowCount() + nRow);
+ DBG_ASSERT( nCol<mnColCount, "wrong column index" );
+ DBG_ASSERT( nRow<mnRowCount, "wrong row index" );
+ sal_uInt32 nRet = static_cast<sal_uInt32>(nCol*mnRowCount + nRow);
+ DBG_ASSERT( maTokens.size()>= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too few tokens" );
+ return nRet;
}
-private:
- vector<FormulaToken*> maRowHeaders;
- vector<FormulaToken*> maColHeaders;
- vector<FormulaToken*> maData;
+ vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const;
+ vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const;
+ vector<ScSharedTokenRef>* getAllRanges() const;
};
-Chart2PositionMap::Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
- bool bColAdd, bool bRowAdd, Table& rCols)
+vector<ScSharedTokenRef>* TokenTable::getColRanges(SCCOL nCol) const
{
- // bColAdd is true when the first column serves as a row header. Likewise,
- // when bRowAdd is true the first row serves as a column header.
+ if (nCol >= mnColCount)
+ return NULL;
+ if( mnRowCount<=0 )
+ return NULL;
- maColHeaders.reserve(nColCount);
- maRowHeaders.reserve(nRowCount);
- maData.reserve(nColCount*nRowCount);
+ auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
+ sal_uInt32 nLast = getIndex(nCol, mnRowCount-1);
+ for (sal_uInt32 i = getIndex(nCol, 0); i <= nLast; ++i)
+ {
+ FormulaToken* p = maTokens[i];
+ if (!p)
+ continue;
- Table* pCol = static_cast<Table*>(rCols.First());
- FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First());
+ ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone()));
+ ScRefTokenHelper::join(*pTokens, pCopy);
+ }
+ return pTokens.release();
+}
- if (bRowAdd)
- pPos = static_cast<FormulaToken*>(pCol->Next());
+vector<ScSharedTokenRef>* TokenTable::getRowRanges(SCROW nRow) const
+{
+ if (nRow >= mnRowCount)
+ return NULL;
+ if( mnColCount<=0 )
+ return NULL;
- if (bColAdd)
+ auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
+ sal_uInt32 nLast = getIndex(mnColCount-1, nRow);
+ for (sal_uInt32 i = getIndex(0, nRow); i <= nLast; i += mnRowCount)
{
- // 1st column as a row header.
- for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
- {
- maRowHeaders.push_back(pPos);
- pPos = static_cast<FormulaToken*>(pCol->Next());
- }
- pCol = static_cast<Table*>(rCols.Next()); // move to the next column.
+ FormulaToken* p = maTokens[i];
+ if (!p)
+ continue;
+
+ ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
+ ScRefTokenHelper::join(*pTokens, p2);
}
- else
+ return pTokens.release();
+}
+
+vector<ScSharedTokenRef>* TokenTable::getAllRanges() const
+{
+ auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
+ sal_uInt32 nStop = mnColCount*mnRowCount;
+ for (sal_uInt32 i = 0; i < nStop; i++)
{
- for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
- {
- // Make a copy.
- maRowHeaders.push_back(pPos ? pPos->Clone() : NULL);
- pPos = static_cast<FormulaToken*>(pCol->Next());
- }
+ FormulaToken* p = maTokens[i];
+ if (!p)
+ continue;
+
+ ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
+ ScRefTokenHelper::join(*pTokens, p2);
}
+ return pTokens.release();
+}
+
+// ============================================================================
+
+class Chart2PositionMap
+{
+public:
+ Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
+ bool bFillRowHeader, bool bFillColumnHeader, Table& rCols,
+ ScDocument* pDoc );
+ ~Chart2PositionMap();
+
+ SCCOL getDataColCount() const { return mnDataColCount; }
+ SCROW getDataRowCount() const { return mnDataRowCount; }
+
+ vector<ScSharedTokenRef>* getLeftUpperCornerRanges() const;
+ vector<ScSharedTokenRef>* getAllColHeaderRanges() const;
+ vector<ScSharedTokenRef>* getAllRowHeaderRanges() const;
+
+ vector<ScSharedTokenRef>* getColHeaderRanges(SCCOL nChartCol) const;
+ vector<ScSharedTokenRef>* getRowHeaderRanges(SCROW nChartRow) const;
+
+ vector<ScSharedTokenRef>* getDataColRanges(SCCOL nCol) const;
+ vector<ScSharedTokenRef>* getDataRowRanges(SCROW nRow) const;
- // Data in columns and in column headers.
- for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
+private:
+ SCCOL mnDataColCount;
+ SCROW mnDataRowCount;
+
+ TokenTable maLeftUpperCorner; //nHeaderColCount*nHeaderRowCount
+ TokenTable maColHeaders; //mnDataColCount*nHeaderRowCount
+ TokenTable maRowHeaders; //nHeaderColCount*mnDataRowCount
+ TokenTable maData;//mnDataColCount*mnDataRowCount
+};
+
+Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount, SCROW nAllRowCount,
+ bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, ScDocument* pDoc)
+{
+ // if bFillRowHeader is true, at least the first column serves as a row header.
+ // If more than one column is pure text all the first pure text columns are used as header.
+ // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header.
+ // If more than one row is pure text all the first pure text rows are used as header.
+
+ SCROW nHeaderRowCount = (bFillColumnHeader && nAllColCount && nAllRowCount) ? 1 : 0;
+ SCCOL nHeaderColCount = (bFillRowHeader && nAllColCount && nAllRowCount) ? 1 : 0;
+
+ if( nHeaderColCount || nHeaderRowCount )
{
- if (pCol)
+ const SCCOL nInitialHeaderColCount = nHeaderColCount;
+ //check whether there is more than one text column or row that should be added to the headers
+ SCROW nSmallestValueRowIndex = nAllRowCount;
+ bool bFoundValues = false;
+ bool bFoundAnything = false;
+ Table* pCol = static_cast<Table*>(rCols.First());
+ for (SCCOL nCol = 0; !bFoundValues && nCol < nAllColCount; ++nCol)
{
- pPos = static_cast<FormulaToken*>(pCol->First());
- if (bRowAdd)
- {
- // 1st row as a column header.
- maColHeaders.push_back(pPos);
- pPos = static_cast<FormulaToken*>(pCol->Next());
- }
- else
- // Duplicate the 1st cell as a column header.
- maColHeaders.push_back(pPos ? pPos->Clone() : NULL);
-
- for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
+ if (pCol && nCol>=nHeaderColCount)
{
- maData.push_back(pPos);
- pPos = static_cast<FormulaToken*>(pCol->Next());
+ ScToken* pToken = static_cast<ScToken*>(pCol->First());
+ for (SCROW nRow = 0; !bFoundValues && nRow < nSmallestValueRowIndex; ++nRow)
+ {
+ if (pToken && nRow>=nHeaderRowCount)
+ {
+ ScRange aRange;
+ bool bExternal = false;
+ StackVar eType = pToken->GetType();
+ if( eType==svExternal || eType==svExternalSingleRef || eType==svExternalDoubleRef || eType==svExternalName )
+ bExternal = true;//lllll todo correct?
+ ScSharedTokenRef pSharedToken(static_cast<ScToken*>(pToken->Clone()));
+ ScRefTokenHelper::getRangeFromToken(aRange, pSharedToken, bExternal );
+ SCCOL nCol1=0, nCol2=0;
+ SCROW nRow1=0, nRow2=0;
+ SCTAB nTab1=0, nTab2=0;
+ aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if (pDoc && pDoc->HasValueData( nCol1, nRow1, nTab1 ))
+ {
+ bFoundValues = bFoundAnything = true;
+ nSmallestValueRowIndex = std::min( nSmallestValueRowIndex, nRow );
+ }
+ if( !bFoundAnything )
+ {
+ if (pDoc && pDoc->HasData( nCol1, nRow1, nTab1 ) )
+ bFoundAnything = true;
+ }
+ }
+ pToken = static_cast<ScToken*>(pCol->Next());
+ }
+ if(!bFoundValues && nHeaderColCount>0)
+ nHeaderColCount++;
}
+ pCol = static_cast<Table*>(rCols.Next());
}
- else
+ if( bFoundAnything )
{
- // the entire column is empty.
- maColHeaders.push_back(NULL);
- for (SCROW nRow = 0; nRow < nRowCount; ++nRow)
- maData.push_back(NULL);
+ if(nHeaderRowCount>0)
+ {
+ if( bFoundValues )
+ nHeaderRowCount = nSmallestValueRowIndex;
+ else if( nAllRowCount>1 )
+ nHeaderRowCount = nAllRowCount-1;
+ }
}
- pCol = static_cast<Table*>(rCols.Next());
+ else //if the cells are completely empty, just use single header rows and columns
+ nHeaderColCount = nInitialHeaderColCount;
}
-}
-namespace {
+ mnDataColCount = nAllColCount - nHeaderColCount;
+ mnDataRowCount = nAllRowCount - nHeaderRowCount;
-struct DeleteInstance : public unary_function<FormulaToken*, void>
-{
- void operator() (FormulaToken* p) const
+ maLeftUpperCorner.init(nHeaderColCount,nHeaderRowCount);
+ maColHeaders.init(mnDataColCount,nHeaderRowCount);
+ maRowHeaders.init(nHeaderColCount,mnDataRowCount);
+ maData.init(mnDataColCount,mnDataRowCount);
+
+ Table* pCol = static_cast<Table*>(rCols.First());
+ FormulaToken* pToken = static_cast<FormulaToken*>(pCol->First());
+ for (SCCOL nCol = 0; nCol < nAllColCount; ++nCol)
{
- delete p;
- }
-};
+ if (pCol)
+ {
+ pToken = static_cast<FormulaToken*>(pCol->First());
+ for (SCROW nRow = 0; nRow < nAllRowCount; ++nRow)
+ {
+ if( nCol < nHeaderColCount )
+ {
+ if( nRow < nHeaderRowCount )
+ maLeftUpperCorner.push_back(pToken);
+ else
+ maRowHeaders.push_back(pToken);
+ }
+ else if( nRow < nHeaderRowCount )
+ maColHeaders.push_back(pToken);
+ else
+ maData.push_back(pToken);
+ pToken = static_cast<FormulaToken*>(pCol->Next());
+ }
+ }
+ pCol = static_cast<Table*>(rCols.Next());
+ }
}
Chart2PositionMap::~Chart2PositionMap()
{
- for_each(maColHeaders.begin(), maColHeaders.end(), DeleteInstance());
- for_each(maRowHeaders.begin(), maRowHeaders.end(), DeleteInstance());
- for_each(maData.begin(), maData.end(), DeleteInstance());
+ maLeftUpperCorner.clear();
+ maColHeaders.clear();
+ maRowHeaders.clear();
+ maData.clear();
}
-const FormulaToken* Chart2PositionMap::getColHeaderPosition(SCCOL nCol) const
+vector<ScSharedTokenRef>* Chart2PositionMap::getLeftUpperCornerRanges() const
{
- if (nCol < getColCount())
- return maColHeaders[nCol];
- return NULL;
+ return maLeftUpperCorner.getAllRanges();
}
-const FormulaToken* Chart2PositionMap::getRowHeaderPosition(SCROW nRow) const
+vector<ScSharedTokenRef>* Chart2PositionMap::getAllColHeaderRanges() const
{
- if (nRow < getRowCount())
- return maRowHeaders[nRow];
- return NULL;
+ return maColHeaders.getAllRanges();
}
-
-vector<ScSharedTokenRef>* Chart2PositionMap::getColRanges(SCCOL nCol) const
+vector<ScSharedTokenRef>* Chart2PositionMap::getAllRowHeaderRanges() const
{
- if (nCol >= getColCount())
- return NULL;
-
- auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
- sal_uInt32 nStop = getIndex(nCol, getRowCount());
- for (sal_uInt32 i = getIndex(nCol, 0); i < nStop; ++i)
- {
- FormulaToken* p = maData[i];
- if (!p)
- continue;
-
- ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone()));
- ScRefTokenHelper::join(*pTokens, pCopy);
- }
- return pTokens.release();
+ return maRowHeaders.getAllRanges();
}
-
-vector<ScSharedTokenRef>* Chart2PositionMap::getRowRanges(SCROW nRow) const
+vector<ScSharedTokenRef>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol) const
{
- SCROW nRowCount = getRowCount();
- if (nRow >= nRowCount)
- return NULL;
+ return maColHeaders.getColRanges( nCol);
+}
+vector<ScSharedTokenRef>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow) const
+{
+ return maRowHeaders.getRowRanges( nRow);
+}
- auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
- sal_uInt32 nStop = getIndex(getColCount(), nRow);
- for (sal_uInt32 i = getIndex(0, nRow); i < nStop; i += nRowCount)
- {
- FormulaToken* p = maData[i];
- if (!p)
- continue;
+vector<ScSharedTokenRef>* Chart2PositionMap::getDataColRanges(SCCOL nCol) const
+{
+ return maData.getColRanges( nCol);
+}
- ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
- ScRefTokenHelper::join(*pTokens, p2);
- }
- return pTokens.release();
+vector<ScSharedTokenRef>* Chart2PositionMap::getDataRowRanges(SCROW nRow) const
+{
+ return maData.getRowRanges( nRow);
}
// ----------------------------------------------------------------------------
@@ -730,55 +792,20 @@ void Chart2Positioner::createPositionMap()
pNewAddress.reset(NULL);
pNewRowTable.reset(NULL);
- bool bColAdd = mbRowHeaders;
- bool bRowAdd = mbColHeaders;
+ bool bFillRowHeader = mbRowHeaders;
+ bool bFillColumnHeader = mbColHeaders;
- SCSIZE nColCount = static_cast<SCSIZE>(pCols->Count());
- SCSIZE nRowCount = 0;
+ SCSIZE nAllColCount = static_cast<SCSIZE>(pCols->Count());
+ SCSIZE nAllRowCount = 0;
pCol = static_cast<Table*>(pCols->First());
if (pCol)
{
if (mbDummyUpperLeft)
pCol->Insert(0, NULL); // Dummy fuer Beschriftung
- nRowCount = static_cast<SCSIZE>(pCol->Count());
+ nAllRowCount = static_cast<SCSIZE>(pCol->Count());
}
- else
- nRowCount = 0;
- if (nColCount > 0 && bColAdd)
- nColCount -= 1;
- if (nRowCount > 0 && bRowAdd)
- nRowCount -= 1;
-
- if (nColCount == 0 || nRowCount == 0)
- {
- ScComplexRefData aData;
- ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front());
- if (pCols->Count() > 0)
- pCol = static_cast<Table*>(pCols->First());
- else
- {
- pCol = new Table;
- pCols->Insert(0, pCol);
- }
- nColCount = 1;
- if (pCol->Count() > 0)
- {
- FormulaToken* pPos = static_cast<FormulaToken*>(pCol->First());
- if (pPos)
- {
- delete pPos;
- pCol->Replace(pCol->GetCurKey(), NULL);
- }
- }
- else
- pCol->Insert(0, NULL);
-
- nRowCount = 1;
- bColAdd = false;
- bRowAdd = false;
- }
- else
+ if( nAllColCount!=0 && nAllRowCount!=0 )
{
if (bNoGlue)
{
@@ -796,8 +823,8 @@ void Chart2Positioner::createPositionMap()
}
mpPositionMap.reset(
new Chart2PositionMap(
- static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount),
- bColAdd, bRowAdd, *pCols));
+ static_cast<SCCOL>(nAllColCount), static_cast<SCROW>(nAllRowCount),
+ bFillRowHeader, bFillColumnHeader, *pCols, mpDoc));
// Destroy all column instances.
for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next()))
@@ -1021,639 +1048,44 @@ void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
return !aTokens.empty();
}
-namespace {
-
-class RemoveHeaderFromRanges : public unary_function<ScSharedTokenRef, void>
-{
-public:
- RemoveHeaderFromRanges(const ScSharedTokenRef& rHeaderCell, bool bOrientCol) :
- mpTokens(new vector<ScSharedTokenRef>),
- mpHeaderCell(rHeaderCell),
- mbOrientCol(bOrientCol)
- {
- }
-
- RemoveHeaderFromRanges(const RemoveHeaderFromRanges& r) :
- mpTokens(r.mpTokens),
- mpHeaderCell(r.mpHeaderCell),
- mbOrientCol(r.mbOrientCol)
- {
- }
-
- void operator() (const ScSharedTokenRef& pRange)
- {
- if (!isContained(pRange))
- {
- // header cell is not part of this range. Just add it to the
- // range list and move on.
- ScRefTokenHelper::join(*mpTokens, pRange);
- return;
- }
-
- // This range contains the header cell.
-
- ScComplexRefData aRange;
- ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
- const ScSingleRefData& s = aRange.Ref1;
- const ScSingleRefData& e = aRange.Ref2;
- const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
-
- if (equals(s, e))
- // This range *only* contains the header cell. Skip it.
- return;
-
- if (s.nTab != e.nTab)
- // 3D range has no business being here....
- return;
-
- if (mbOrientCol)
- {
- // column major
-
- if (s.nCol == e.nCol)
- {
- // single column range.
- splitSingleColRange(pRange, s, e);
- }
- else
- {
- if (s.nCol == h.nCol)
- {
- // header cell is in the first column.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(s.nCol, e.nRow, s.nTab);
- splitSingleColRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(s.nCol + 1, s.nRow, s.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- else if (e.nCol == h.nCol)
- {
- // header cell is in the last column.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(e.nCol, s.nRow, s.nTab);
- splitSingleColRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(e.nCol - 1, e.nRow, e.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- else
- {
- // header cell is somewhere between the first and last columns.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(h.nCol - 1, e.nRow, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(h.nCol, s.nRow, s.nTab);
- r.Ref2.InitAddress(h.nCol, e.nRow, e.nTab);
- splitSingleColRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(h.nCol + 1, s.nRow, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- }
- }
- else
- {
- // row major
-
- if (s.nRow == e.nRow)
- {
- // Single row range.
- splitSingleRowRange(pRange, s, e);
- }
- else
- {
- if (s.nRow == h.nRow)
- {
- // header cell is in the first row.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(e.nCol, s.nRow, s.nTab);
- splitSingleRowRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(s.nCol, s.nRow + 1, s.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- else if (e.nRow == h.nRow)
- {
- // header cell is in the last row.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(s.nCol, e.nRow, s.nTab);
- splitSingleRowRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(e.nCol, e.nRow - 1, e.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- else
- {
- // header cell is somewhere between the 1st and last rows.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(e.nCol, h.nRow - 1, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(s.nCol, h.nRow, s.nTab);
- r.Ref2.InitAddress(e.nCol, h.nRow, e.nTab);
- splitSingleRowRange(pNew, r.Ref1, r.Ref2);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(s.nCol, h.nRow + 1, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- }
- }
- }
-
- void getNewTokens(vector<ScSharedTokenRef>& rTokens)
- {
- mpTokens->swap(rTokens);
- }
-
-private:
-
- void splitSingleColRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
- {
- const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
-
- if (equals(s, h))
- {
- // header is at the top.
-
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.nRow += 1;
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- else if (equals(e, h))
- {
- // header is at the bottom.
-
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.nRow -= 1;
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- else
- {
- // header is somewhere in the middle.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(h.nCol, h.nRow - 1, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(h.nCol, h.nRow + 1, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- }
-
- void splitSingleRowRange(const ScSharedTokenRef& pRange, const ScSingleRefData& s, const ScSingleRefData& e)
- {
- const ScSingleRefData& h = mpHeaderCell->GetSingleRef();
-
- if (equals(s, h))
- {
- // header is at the top.
-
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.nCol += 1;
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- else if (equals(e, h))
- {
- // header is at the bottom.
-
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.nCol -= 1;
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- else
- {
- // header is somewhere in the middle.
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref2.InitAddress(h.nCol - 1, h.nRow, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
-
- {
- ScSharedTokenRef pNew(static_cast<ScToken*>(pRange->Clone()));
- ScComplexRefData& r = pNew->GetDoubleRef();
- r.Ref1.InitAddress(h.nCol + 1, h.nRow, h.nTab);
- ScRefTokenHelper::join(*mpTokens, pNew);
- }
- }
- }
-
- /**
- * Compare two single ref data for equality, but only compare their
- * absolute cell addresses while ignoring flags and relative addresses.
- */
- bool equals(const ScSingleRefData& r1, const ScSingleRefData& r2) const
- {
- return (r1.nCol == r2.nCol) && (r1.nRow == r2.nRow) && (r1.nTab == r2.nTab);
- }
-
- bool isContained(const ScSharedTokenRef& pRange)
- {
- bool bExternal = ScRefTokenHelper::isExternalRef(mpHeaderCell);
- if (bExternal != ScRefTokenHelper::isExternalRef(pRange))
- // internal vs external.
- return false;
-
- if (bExternal)
- {
- if (pRange->GetIndex() != mpHeaderCell->GetIndex())
- // different external files.
- return false;
-
- if (pRange->GetString() != mpHeaderCell->GetString())
- // different table.
- return false;
- }
-
- ScComplexRefData aRange;
- ScRefTokenHelper::getDoubleRefDataFromToken(aRange, pRange);
- const ScSingleRefData& rCell = mpHeaderCell->GetSingleRef();
-
- bool bRowContained = (aRange.Ref1.nRow <= rCell.nRow) && (rCell.nRow <= aRange.Ref2.nRow);
- bool bColContained = (aRange.Ref1.nCol <= rCell.nCol) && (rCell.nCol <= aRange.Ref2.nCol);
- bool bTabContained = (aRange.Ref1.nTab <= rCell.nTab) && (rCell.nTab <= aRange.Ref2.nTab);
-
- return (bRowContained && bColContained && bTabContained);
- }
-
-private:
- shared_ptr< vector<ScSharedTokenRef> > mpTokens;
-
- /**
- * Stores header cell position. Must be a single ref token i.e. either
- * ScSingleRefToken or ScExternalSingleRefToken.
- */
- ScSharedTokenRef mpHeaderCell;
-
- bool mbOrientCol;
-};
-
-}
-
-static void lcl_removeHeaderFromRanges(vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& rHeaderCell, bool bOrientCol)
-{
- RemoveHeaderFromRanges func(rHeaderCell, bOrientCol);
- func = for_each(rTokens.begin(), rTokens.end(), func);
- func.getNewTokens(rTokens);
-}
-
-uno::Reference< chart2::data::XDataSource> SAL_CALL
-ScChart2DataProvider::createDataSource(
- const uno::Sequence< beans::PropertyValue >& aArguments )
- throw( lang::IllegalArgumentException, uno::RuntimeException)
-{
- ScUnoGuard aGuard;
- if ( ! m_pDocument )
- throw uno::RuntimeException();
-
- uno::Reference< chart2::data::XDataSource> xResult;
- bool bLabel = true;
- bool bOrientCol = true;
- ::rtl::OUString aRangeRepresentation;
- uno::Sequence< sal_Int32 > aSequenceMapping;
- for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
- {
- rtl::OUString sName(aArguments[i].Name);
- if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
- {
- chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
- if( ! (aArguments[i].Value >>= eSource))
- {
- sal_Int32 nSource(0);
- if( aArguments[i].Value >>= nSource )
- eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
- }
- bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
- }
- else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
- {
- bLabel = ::cppu::any2bool(aArguments[i].Value);
- }
- else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
- {
- aArguments[i].Value >>= aRangeRepresentation;
- }
- else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
- {
- aArguments[i].Value >>= aSequenceMapping;
- }
- }
-
- vector<ScSharedTokenRef> aRefTokens;
- ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
- if (aRefTokens.empty())
- // Invalid range representation. Bail out.
- throw lang::IllegalArgumentException();
-
- if (bLabel)
- addUpperLeftCornerIfMissing(aRefTokens);
-
- bool bColHeaders = (bOrientCol ? bLabel : false );
- bool bRowHeaders = (bOrientCol ? false : bLabel );
-
- Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
- aChPositioner.setHeaders(bColHeaders, bRowHeaders);
-
- const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
- if (!pChartMap)
- // No chart position map instance. Bail out.
- return xResult;
-
- ScChart2DataSource* pDS = NULL;
- std::list < ScChart2LabeledDataSequence* > aSeqs;
-
- // Fill Categories
-
- ScChart2LabeledDataSequence* pHeader = NULL;
- if (bOrientCol ? aChPositioner.hasRowHeaders() : aChPositioner.hasColHeaders())
- {
- pHeader = new ScChart2LabeledDataSequence(m_pDocument);
- sal_Int32 nCount = static_cast< sal_Int32 >( bOrientCol ? pChartMap->getRowCount() : pChartMap->getColCount() );
- vector<ScSharedTokenRef> aRefTokens2;
- ScSharedTokenRef pLabelToken;
- for (sal_Int32 i = 0; i < nCount; ++i)
- {
- const FormulaToken* pPos = bOrientCol ?
- pChartMap->getRowHeaderPosition(static_cast<SCROW>(i)) :
- pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
- if (pPos)
- {
- ScSharedTokenRef p(static_cast<ScToken*>(pPos->Clone()));
- ScRefTokenHelper::join(aRefTokens2, p);
- if (!pLabelToken)
- {
- pLabelToken = p;
- StackVar eType = pLabelToken->GetType();
- if (eType == svSingleRef || eType == svExternalSingleRef)
- {
- ScSingleRefData& r = pLabelToken->GetSingleRef();
- if (bOrientCol)
- r.nRow -= 1;
- else
- r.nCol -= 1;
- }
- }
- }
- }
- if (pLabelToken)
- {
- if (bLabel)
- {
- auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
- pTokens->push_back(pLabelToken);
- Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
- Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
- if (xLabelProps.is())
- xLabelProps->setPropertyValue(
- OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)),
- uno::makeAny(OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
- pHeader->setLabel(xLabelSeq);
- }
- else
- ScRefTokenHelper::join(aRefTokens2, pLabelToken);
- }
- auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
- pTokens->swap(aRefTokens2);
- uno::Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells) );
- pHeader->setValues(xSeq);
- }
- if (pHeader)
- aSeqs.push_back(pHeader);
-
- // Fill Serieses with Labels
-
- sal_Int32 nCount = bOrientCol ? pChartMap->getColCount() : pChartMap->getRowCount();
- for (sal_Int32 i = 0; i < nCount; ++i)
- {
- ScChart2LabeledDataSequence* pLabeled = new ScChart2LabeledDataSequence(m_pDocument);
- uno::Reference < chart2::data::XDataSequence > xLabelSeq;
- auto_ptr< vector<ScSharedTokenRef> > pRanges(NULL);
- if (bOrientCol)
- pRanges.reset(pChartMap->getColRanges(static_cast<SCCOL>(i)));
- else
- pRanges.reset(pChartMap->getRowRanges(static_cast<SCROW>(i)));
-
- ScSharedTokenRef pHeaderCell;
- if (bOrientCol)
- {
- const FormulaToken* p = pChartMap->getColHeaderPosition(static_cast<SCCOL>(i));
- if (p)
- pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
- }
- else
- {
- const FormulaToken* p = pChartMap->getRowHeaderPosition(static_cast<SCROW>(i));
- if (p)
- pHeaderCell.reset(static_cast<ScToken*>(p->Clone()));
- }
-
- if (bLabel)
- {
- if (!pHeaderCell && pRanges.get() && !pRanges->empty())
- {
- const ScSharedTokenRef& p = pRanges->front();
- if (p && ScRefTokenHelper::isRef(p))
- {
- // Take the first cell in the range as the header position.
- ScSingleRefData aData = p->GetSingleRef();
- bool bExternal = ScRefTokenHelper::isExternalRef(p);
- if (bExternal)
- {
- sal_uInt16 nFileId = p->GetIndex();
- const String& rTabName = p->GetString();
- pHeaderCell.reset(new ScExternalSingleRefToken(nFileId, rTabName, aData));
- }
- else
- pHeaderCell.reset(new ScSingleRefToken(aData));
- }
- }
- if (pHeaderCell)
- {
- auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
- pTokens->reserve(1);
- pTokens->push_back(pHeaderCell);
- xLabelSeq.set(new ScChart2DataSequence(m_pDocument, this, pTokens.release(), m_bIncludeHiddenCells));
- uno::Reference< beans::XPropertySet > xLabelProps(xLabelSeq, uno::UNO_QUERY);
- if (xLabelProps.is())
- xLabelProps->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_ROLE)), uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("label"))));
-
- // remove Header from Ranges
- lcl_removeHeaderFromRanges(*pRanges, pHeaderCell, bOrientCol);
- }
- }
- else
- {
- if (pHeaderCell)
- ScRefTokenHelper::join(*pRanges, pHeaderCell);
- }
-
- // FIXME: if there are no labels the column or row name should be taken
-
- uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(m_pDocument, this, pRanges.release(), m_bIncludeHiddenCells));
-
- pLabeled->setValues(xSeq);
- pLabeled->setLabel(xLabelSeq);
-
- aSeqs.push_back(pLabeled);
- }
-
- pDS = new ScChart2DataSource(m_pDocument);
- std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin());
- std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end());
-
- //reorder labeled sequences according to aSequenceMapping
- std::vector< ScChart2LabeledDataSequence* > aSeqVector;
- while(aItr != aEndItr)
- {
- aSeqVector.push_back(*aItr);
- ++aItr;
- }
-
- std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap;
- for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
- {
- // note: assuming that the values in the sequence mapping are always non-negative
- std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ));
- if( nOldIndex < aSeqVector.size() )
- {
- pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
- aSeqVector[nOldIndex] = 0;
- }
-
- }
-
- std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin());
- std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end());
- while(aVectorItr != aVectorEndItr)
- {
- if(*aVectorItr)
- pDS->AddLabeledSequence(*aVectorItr);
- ++aVectorItr;
- }
-
- xResult.set( pDS );
- return xResult;
-}
-
namespace
{
-bool lcl_HasCategories(
- const uno::Reference< chart2::data::XDataSource >& xDataSource,
- bool & rOutHasCategories )
+ScChart2LabeledDataSequence* lcl_createScChart2DataSequenceFromTokens( auto_ptr< vector<ScSharedTokenRef> > pValueTokens, auto_ptr< vector<ScSharedTokenRef> > pLabelTokens,
+ ScDocument* pDoc, const uno::Reference < chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells )
{
- bool bResult = false;
- uno::Reference< chart2::data::XLabeledDataSequence > xCategories(
- lcl_getCategoriesFromDataSource( xDataSource ));
- if( xCategories.is())
+ ScChart2LabeledDataSequence* pRet = 0;
+ bool bHasValues = pValueTokens.get() && !pValueTokens->empty();
+ bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty();
+ if( bHasValues || bHasLabel )
{
- uno::Reference< lang::XServiceInfo > xValues( xCategories->getValues(), uno::UNO_QUERY );
- if (xValues.is())
+ pRet = new ScChart2LabeledDataSequence(pDoc);
+ if(bHasValues)
{
- rOutHasCategories = xValues->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
- bResult = true;
+ uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells));
+ pRet->setValues(xSeq);
}
- }
- return bResult;
-}
-
-bool lcl_HasFirstCellAsLabel(
- const uno::Reference< chart2::data::XDataSource >& xDataSource,
- bool & rOutHasFirstCellAsLabel )
-{
- bool bResult = false;
- if( xDataSource.is())
- {
- uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(
- xDataSource->getDataSequences());
- const sal_Int32 nCount( aSequences.getLength());
- if (nCount > 0 && aSequences[nCount - 1].is() )
+ if(bHasLabel)
{
- uno::Reference< lang::XServiceInfo > xLabel( aSequences[nCount - 1]->getLabel(), uno::UNO_QUERY ); // take the last sequence, because the first has no label if it is also created
- if (xLabel.is())
- {
- rOutHasFirstCellAsLabel = xLabel->getImplementationName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ScChart2DataSequence"));
- bResult = true;
- }
+ uno::Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells));
+ pRet->setLabel(xLabelSeq);
}
}
- return bResult;
+ return pRet;
}
-} // anonymous namespace
-
-bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens)
+//----------------------------------------------------
+/**
+ * Check the current list of reference tokens, and add the upper left
+ * corner of the minimum range that encloses all ranges if certain
+ * conditions are met.
+ *
+ * @param rRefTokens list of reference tokens
+ *
+ * @return true if the corner was added, false otherwise.
+ */
+bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens,
+ SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1)
{
using ::std::max;
using ::std::min;
@@ -1834,13 +1266,13 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>&
// The corner cell is contained.
return false;
- if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow)
+ if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow)
bRight = true;
- if (rData.nCol == nMinCol && rData.nRow == nMinRow+1)
+ if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount)
bBottom = true;
- if (rData.nCol == nMinCol+1 && rData.nRow == nMinRow+1)
+ if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount)
bDiagonal = true;
}
break;
@@ -1855,16 +1287,16 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>&
// The corner cell is contained.
return false;
- if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
+ if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
r1.nRow <= nMinRow && nMinRow <= r2.nRow)
bRight = true;
if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
- r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
+ r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
bBottom = true;
- if (r1.nCol <= nMinCol+1 && nMinCol+1 <= r2.nCol &&
- r1.nRow <= nMinRow+1 && nMinRow+1 <= r2.nRow)
+ if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
+ r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
bDiagonal = true;
}
break;
@@ -1934,22 +1366,194 @@ bool ScChart2DataProvider::addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>&
aData.nRow = nMinRow;
aData.nTab = nTab;
- if (bExternal)
+ if( nCornerRowCount==1 && nCornerColumnCount==1 )
{
- ScSharedTokenRef pCorner(
- new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
- ScRefTokenHelper::join(rRefTokens, pCorner);
+ if (bExternal)
+ {
+ ScSharedTokenRef pCorner(
+ new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
+ ScRefTokenHelper::join(rRefTokens, pCorner);
+ }
+ else
+ {
+ ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
+ ScRefTokenHelper::join(rRefTokens, pCorner);
+ }
}
else
{
- ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
- ScRefTokenHelper::join(rRefTokens, pCorner);
+ ScSingleRefData aDataEnd(aData);
+ aDataEnd.nCol += (nCornerColumnCount-1);
+ aDataEnd.nRow += (nCornerRowCount-1);
+ ScComplexRefData r;
+ r.Ref1=aData;
+ r.Ref2=aDataEnd;
+ if (bExternal)
+ {
+ ScSharedTokenRef pCorner(
+ new ScExternalDoubleRefToken(nFileId, aExtTabName, r));
+ ScRefTokenHelper::join(rRefTokens, pCorner);
+ }
+ else
+ {
+ ScSharedTokenRef pCorner(new ScDoubleRefToken(r));
+ ScRefTokenHelper::join(rRefTokens, pCorner);
+ }
}
return true;
}
-namespace {
+}
+
+uno::Reference< chart2::data::XDataSource> SAL_CALL
+ScChart2DataProvider::createDataSource(
+ const uno::Sequence< beans::PropertyValue >& aArguments )
+ throw( lang::IllegalArgumentException, uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if ( ! m_pDocument )
+ throw uno::RuntimeException();
+
+ uno::Reference< chart2::data::XDataSource> xResult;
+ bool bLabel = true;
+ bool bCategories = false;
+ bool bOrientCol = true;
+ ::rtl::OUString aRangeRepresentation;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+ for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
+ {
+ rtl::OUString sName(aArguments[i].Name);
+ if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
+ {
+ chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
+ if( ! (aArguments[i].Value >>= eSource))
+ {
+ sal_Int32 nSource(0);
+ if( aArguments[i].Value >>= nSource )
+ eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
+ }
+ bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
+ }
+ else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
+ {
+ bLabel = ::cppu::any2bool(aArguments[i].Value);
+ }
+ else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories")))
+ {
+ bCategories = ::cppu::any2bool(aArguments[i].Value);
+ }
+ else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
+ {
+ aArguments[i].Value >>= aRangeRepresentation;
+ }
+ else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
+ {
+ aArguments[i].Value >>= aSequenceMapping;
+ }
+ }
+
+ vector<ScSharedTokenRef> aRefTokens;
+ ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
+ if (aRefTokens.empty())
+ // Invalid range representation. Bail out.
+ throw lang::IllegalArgumentException();
+
+ if (bLabel)
+ lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669#
+
+ bool bColHeaders = (bOrientCol ? bLabel : bCategories );
+ bool bRowHeaders = (bOrientCol ? bCategories : bLabel );
+
+ Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
+ aChPositioner.setHeaders(bColHeaders, bRowHeaders);
+
+ const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
+ if (!pChartMap)
+ // No chart position map instance. Bail out.
+ return xResult;
+
+ ScChart2DataSource* pDS = NULL;
+ std::list < ScChart2LabeledDataSequence* > aSeqs;
+
+ // Fill Categories
+ if( bCategories )
+ {
+ auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
+ if (bOrientCol)
+ pValueTokens.reset(pChartMap->getAllRowHeaderRanges());
+ else
+ pValueTokens.reset(pChartMap->getAllColHeaderRanges());
+
+ auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
+ pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges());
+
+ ScChart2LabeledDataSequence* pCategories = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells );//ownership of pointers is transfered!
+ if( pCategories )
+ aSeqs.push_back(pCategories);
+ }
+
+ // Fill Serieses (values and label)
+ sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
+ auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
+ if (bOrientCol)
+ {
+ pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i)));
+ pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i)));
+ }
+ else
+ {
+ pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i)));
+ pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i)));
+ }
+ ScChart2LabeledDataSequence* pChartSeries = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered!
+ if( pChartSeries )
+ aSeqs.push_back(pChartSeries);
+ }
+
+ pDS = new ScChart2DataSource(m_pDocument);
+ std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin());
+ std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end());
+
+ //reorder labeled sequences according to aSequenceMapping
+ std::vector< ScChart2LabeledDataSequence* > aSeqVector;
+ while(aItr != aEndItr)
+ {
+ aSeqVector.push_back(*aItr);
+ ++aItr;
+ }
+
+ std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap;
+ for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
+ {
+ // note: assuming that the values in the sequence mapping are always non-negative
+ std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ));
+ if( nOldIndex < aSeqVector.size() )
+ {
+ pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
+ aSeqVector[nOldIndex] = 0;
+ }
+
+ }
+
+ std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin());
+ std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end());
+ while(aVectorItr != aVectorEndItr)
+ {
+ if(*aVectorItr)
+ pDS->AddLabeledSequence(*aVectorItr);
+ ++aVectorItr;
+ }
+
+ xResult.set( pDS );
+ return xResult;
+}
+
+namespace
+{
/**
* Function object to create a list of table numbers from a token list.
@@ -1984,8 +1588,134 @@ private:
shared_ptr< list<SCTAB> > mpTabNumList;
};
+class RangeAnalyzer
+{
+public:
+ RangeAnalyzer();
+ void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens );
+ void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols,
+ bool& rbRowSourceAmbiguous ) const;
+ bool inSameSingleRow( RangeAnalyzer& rOther );
+ bool inSameSingleColumn( RangeAnalyzer& rOther );
+ SCROW getRowCount() { return mnRowCount; }
+ SCCOL getColumnCount() { return mnColumnCount; }
+
+private:
+ bool mbEmpty;
+ bool mbAmbiguous;
+ SCROW mnRowCount;
+ SCCOL mnColumnCount;
+
+ SCCOL mnStartColumn;
+ SCROW mnStartRow;
+};
+
+RangeAnalyzer::RangeAnalyzer()
+ : mbEmpty(true)
+ , mbAmbiguous(false)
+ , mnRowCount(0)
+ , mnColumnCount(0)
+ , mnStartColumn(-1)
+ , mnStartRow(-1)
+{
}
+void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens )
+{
+ mnRowCount=0;
+ mnColumnCount=0;
+ mnStartColumn = -1;
+ mnStartRow = -1;
+ mbAmbiguous=false;
+ if( rTokens.empty() )
+ {
+ mbEmpty=true;
+ return;
+ }
+ mbEmpty=false;
+
+ vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end();
+ for (; itr != itrEnd ; ++itr)
+ {
+ ScSharedTokenRef aRefToken = *itr;
+ StackVar eVar = aRefToken->GetType();
+ if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
+ {
+ const ScComplexRefData& r = aRefToken->GetDoubleRef();
+ if (r.Ref1.nTab == r.Ref2.nTab)
+ {
+ mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) );
+ mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) );
+ if( mnStartColumn == -1 )
+ {
+ mnStartColumn = r.Ref1.nCol;
+ mnStartRow = r.Ref1.nRow;
+ }
+ else
+ {
+ if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow )
+ mbAmbiguous=true;
+ }
+ }
+ else
+ mbAmbiguous=true;
+ }
+ else if (eVar == svSingleRef || eVar == svExternalSingleRef)
+ {
+ const ScSingleRefData& r = aRefToken->GetSingleRef();
+ mnColumnCount = std::max<SCCOL>( mnColumnCount, 1);
+ mnRowCount = std::max<SCROW>( mnRowCount, 1);
+ if( mnStartColumn == -1 )
+ {
+ mnStartColumn = r.nCol;
+ mnStartRow = r.nRow;
+ }
+ else
+ {
+ if( mnStartColumn != r.nCol && mnStartRow != r.nRow )
+ mbAmbiguous=true;
+ }
+ }
+ else
+ mbAmbiguous=true;
+ }
+}
+
+void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows,
+ sal_Int32& rnDataInCols,
+ bool& rbRowSourceAmbiguous ) const
+{
+ if(!mbEmpty && !mbAmbiguous)
+ {
+ if( mnRowCount==1 && mnColumnCount>1 )
+ ++rnDataInRows;
+ else if( mnColumnCount==1 && mnRowCount>1 )
+ ++rnDataInCols;
+ else if( mnRowCount>1 && mnColumnCount>1 )
+ rbRowSourceAmbiguous = true;
+ }
+ else if( !mbEmpty )
+ rbRowSourceAmbiguous = true;
+}
+
+bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther )
+{
+ if( mnStartRow==rOther.mnStartRow &&
+ mnRowCount==1 && rOther.mnRowCount==1 )
+ return true;
+ return false;
+}
+
+bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther )
+{
+ if( mnStartColumn==rOther.mnStartColumn &&
+ mnColumnCount==1 && rOther.mnColumnCount==1 )
+ return true;
+ return false;
+}
+
+} //end anonymous namespace
+
uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments(
const uno::Reference< chart2::data::XDataSource >& xDataSource )
throw (uno::RuntimeException)
@@ -1993,28 +1723,137 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum
::std::vector< beans::PropertyValue > aResult;
bool bRowSourceDetected = false;
bool bFirstCellAsLabel = false;
- bool bHasCategories = true;
+ bool bHasCategories = false;
::rtl::OUString sRangeRep;
+ bool bHasCategoriesLabels = false;
+ vector<ScSharedTokenRef> aAllCategoriesValuesTokens;
+ vector<ScSharedTokenRef> aAllSeriesLabelTokens;
+
chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS;
- vector<ScSharedTokenRef> aTokens;
+ vector<ScSharedTokenRef> aAllTokens;
- // CellRangeRepresentation
+ // parse given data source and collect infos
{
ScUnoGuard aGuard;
DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" );
- if(!m_pDocument)
+ if(!m_pDocument ||!xDataSource.is())
return lcl_VectorToSequence( aResult );
- detectRangesFromDataSource(aTokens, eRowSource, bRowSourceDetected, xDataSource);
+ sal_Int32 nDataInRows = 0;
+ sal_Int32 nDataInCols = 0;
+ bool bRowSourceAmbiguous = false;
+
+ Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
+ const sal_Int32 nCount( aSequences.getLength());
+ RangeAnalyzer aPrevLabel,aPrevValues;
+ for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
+ {
+ Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]);
+ if( xLS.is() )
+ {
+ bool bThisIsCategories = false;
+ if(!bHasCategories)
+ {
+ Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY );
+ ::rtl::OUString aRole;
+ if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) &&
+ aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
+ bThisIsCategories = bHasCategories = true;
+ }
+
+ RangeAnalyzer aLabel,aValues;
+ // label
+ Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel());
+ if( xLabel.is())
+ {
+ bFirstCellAsLabel = true;
+ vector<ScSharedTokenRef> aTokens;
+ ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
+ aLabel.initRangeAnalyzer(aTokens);
+ vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ ScRefTokenHelper::join(aAllTokens, *itr);
+ if(!bThisIsCategories)
+ ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr);
+ }
+ if(bThisIsCategories)
+ bHasCategoriesLabels=true;
+ }
+ // values
+ Reference< chart2::data::XDataSequence > xValues( xLS->getValues());
+ if( xValues.is())
+ {
+ vector<ScSharedTokenRef> aTokens;
+ ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
+ aValues.initRangeAnalyzer(aTokens);
+ vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ ScRefTokenHelper::join(aAllTokens, *itr);
+ if(bThisIsCategories)
+ ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr);
+ }
+ }
+ //detect row source
+ if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available
+ {
+ if (!bRowSourceAmbiguous)
+ {
+ aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
+ aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
+ if (nDataInRows > 1 && nDataInCols > 1)
+ bRowSourceAmbiguous = true;
+ else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols )
+ {
+ if( aValues.inSameSingleColumn( aLabel ) )
+ nDataInCols++;
+ else if( aValues.inSameSingleRow( aLabel ) )
+ nDataInRows++;
+ else
+ {
+ //#i86188# also detect a single column split into rows correctly
+ if( aValues.inSameSingleColumn( aPrevValues ) )
+ nDataInRows++;
+ else if( aValues.inSameSingleRow( aPrevValues ) )
+ nDataInCols++;
+ else if( aLabel.inSameSingleColumn( aPrevLabel ) )
+ nDataInRows++;
+ else if( aLabel.inSameSingleRow( aPrevLabel ) )
+ nDataInCols++;
+ }
+ }
+ }
+ }
+ aPrevValues=aValues;
+ aPrevLabel=aLabel;
+ }
+ }
+
+ if (!bRowSourceAmbiguous)
+ {
+ bRowSourceDetected = true;
+ eRowSource = ( nDataInRows > 0
+ ? chart::ChartDataRowSource_ROWS
+ : chart::ChartDataRowSource_COLUMNS );
+ }
+ else
+ {
+ // set DataRowSource to the better of the two ambiguities
+ eRowSource = ( nDataInRows > nDataInCols
+ ? chart::ChartDataRowSource_ROWS
+ : chart::ChartDataRowSource_COLUMNS );
+ }
+
}
// TableNumberList
{
list<SCTAB> aTableNumList;
InsertTabNumber func;
- func = for_each(aTokens.begin(), aTokens.end(), func);
+ func = for_each(aAllTokens.begin(), aAllTokens.end(), func);
func.getList(aTableNumList);
aResult.push_back(
beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1,
@@ -2033,29 +1872,38 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum
// HasCategories
if( bRowSourceDetected )
{
- if( lcl_HasCategories( xDataSource, bHasCategories ))
- {
- aResult.push_back(
- beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
- uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
- }
+ aResult.push_back(
+ beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
+ uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
}
// FirstCellAsLabel
if( bRowSourceDetected )
{
- lcl_HasFirstCellAsLabel( xDataSource, bFirstCellAsLabel );
aResult.push_back(
beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ));
}
// Add the left upper corner to the range if it is missing.
- if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories)
- addUpperLeftCornerIfMissing(aTokens);
+ if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels )
+ {
+ RangeAnalyzer aTop,aLeft;
+ if( eRowSource==chart::ChartDataRowSource_COLUMNS )
+ {
+ aTop.initRangeAnalyzer(aAllSeriesLabelTokens);
+ aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens);
+ }
+ else
+ {
+ aTop.initRangeAnalyzer(aAllCategoriesValuesTokens);
+ aLeft.initRangeAnalyzer(aAllSeriesLabelTokens);
+ }
+ lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212#
+ }
// Get range string.
- lcl_convertTokensToString(sRangeRep, aTokens, m_pDocument);
+ lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument);
// add cell range property
aResult.push_back(
@@ -2270,91 +2118,6 @@ rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUS
return aRet;
}
-namespace {
-
-class CollectRefTokens : public ::std::unary_function<ScSharedTokenRef, void>
-{
-public:
- CollectRefTokens() :
- mpRefTokens(new vector<ScSharedTokenRef>()),
- mnDataInRows(0),
- mnDataInCols(0),
- mbRowSourceAmbiguous(false)
- {
- }
-
- CollectRefTokens(const CollectRefTokens& r) :
- mpRefTokens(r.mpRefTokens),
- mnDataInRows(r.mnDataInRows),
- mnDataInCols(r.mnDataInCols),
- mbRowSourceAmbiguous(r.mbRowSourceAmbiguous)
- {
- }
-
- void operator() (const ScSharedTokenRef& rRefToken)
- {
- if (!mbRowSourceAmbiguous)
- {
- StackVar eVar = rRefToken->GetType();
- if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
- {
- const ScComplexRefData& r = rRefToken->GetDoubleRef();
- mbRowSourceAmbiguous = r.Ref1.nTab != r.Ref2.nTab;
- if (!mbRowSourceAmbiguous)
- {
- bool bColDiff = (r.Ref2.nCol - r.Ref1.nCol) != 0;
- bool bRowDiff = (r.Ref2.nRow - r.Ref1.nRow) != 0;
-
- if (bColDiff && !bRowDiff)
- ++mnDataInRows;
- else if (bRowDiff && !bColDiff)
- ++mnDataInCols;
- else if (bRowDiff && bColDiff)
- mbRowSourceAmbiguous = true;
-
- if (mnDataInRows > 0 && mnDataInCols > 0)
- mbRowSourceAmbiguous = true;
- }
- }
- }
-
- mpRefTokens->push_back(rRefToken);
- }
-
- void appendTokens(vector<ScSharedTokenRef>& rTokens)
- {
- vector<ScSharedTokenRef> aNewTokens = rTokens;
- vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
- for (; itr != itrEnd; ++itr)
- ScRefTokenHelper::join(aNewTokens, *itr);
-
- rTokens.swap(aNewTokens);
- }
-
- bool isRowSourceAmbiguous() const
- {
- return mbRowSourceAmbiguous;
- }
-
- sal_uInt32 getDataInRows() const
- {
- return mnDataInRows;
- }
-
- sal_uInt32 getDataInCols() const
- {
- return mnDataInCols;
- }
-
-private:
- shared_ptr< vector<ScSharedTokenRef> > mpRefTokens;
- sal_uInt32 mnDataInRows;
- sal_uInt32 mnDataInCols;
- bool mbRowSourceAmbiguous;
-};
-
-}
-
// DataProvider XPropertySet -------------------------------------------------
uno::Reference< beans::XPropertySetInfo> SAL_CALL
@@ -2437,53 +2200,6 @@ void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener(
OSL_ENSURE( false, "Not yet implemented" );
}
-void ScChart2DataProvider::detectRangesFromDataSource(vector<ScSharedTokenRef>& rRefTokens,
- chart::ChartDataRowSource& rRowSource,
- bool& rRowSourceDetected,
- const Reference<chart2::data::XDataSource>& xDataSource)
-{
- if (!m_pDocument)
- return;
-
- sal_Int32 nDataInRows = 0;
- sal_Int32 nDataInCols = 0;
- bool bRowSourceAmbiguous = false;
-
- vector<OUString> aRangeReps = lcl_getRangeRepresentationsFromDataSource(xDataSource);
- for (vector<OUString>::const_iterator itr = aRangeReps.begin(), itrEnd = aRangeReps.end();
- itr != itrEnd; ++itr)
- {
- const OUString& rRangeRep = *itr;
- vector<ScSharedTokenRef> aTokens;
- ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument, m_pDocument->GetGrammar());
-
- CollectRefTokens func;
- func = for_each(aTokens.begin(), aTokens.end(), func);
- func.appendTokens(rRefTokens);
- bRowSourceAmbiguous = bRowSourceAmbiguous || func.isRowSourceAmbiguous();
- if (!bRowSourceAmbiguous)
- {
- nDataInRows += func.getDataInRows();
- nDataInCols += func.getDataInCols();
- }
- }
-
- if (!bRowSourceAmbiguous)
- {
- rRowSourceDetected = true;
- rRowSource = ( nDataInRows > 0
- ? chart::ChartDataRowSource_ROWS
- : chart::ChartDataRowSource_COLUMNS );
- }
- else
- {
- // set DataRowSource to the better of the two ambiguities
- rRowSource = ( nDataInRows > nDataInCols
- ? chart::ChartDataRowSource_ROWS
- : chart::ChartDataRowSource_COLUMNS );
- }
-}
-
// DataSource ================================================================
ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc)
diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx
index a921d1e125f2..ab94be3052e0 100644
--- a/sc/source/ui/unoobj/dapiuno.cxx
+++ b/sc/source/ui/unoobj/dapiuno.cxx
@@ -43,15 +43,19 @@
#include "unoguard.hxx"
#include "dpobject.hxx"
#include "dpshttab.hxx"
+#include "dpsdbtab.hxx"
#include "dpsave.hxx"
#include "dbdocfun.hxx"
#include "unonames.hxx"
#include "dpgroup.hxx"
#include "dpdimsave.hxx"
+#include "hints.hxx"
+
#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
#include <com/sun/star/sheet/XLevelsSupplier.hpp>
#include <com/sun/star/sheet/XMembersSupplier.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sheet/DataImportMode.hpp>
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
@@ -105,9 +109,12 @@ const SfxItemPropertyMapEntry* lcl_GetDataPilotDescriptorBaseMap()
{MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_DRILLDOWN), 0, &getBooleanCppuType(), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_IGNEMPROWS), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_IMPORTDESC), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_RPTEMPTY), 0, &getBooleanCppuType(), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_SERVICEARG), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
{MAP_CHAR_LEN(SC_UNO_SHOWFILT), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_SOURCESERV), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
{0,0,0,0,0,0}
};
return aDataPilotDescriptorBaseMap_Impl;
@@ -261,8 +268,7 @@ ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, SCTAB nTab, const String& rN
for (USHORT i=0; i<nCount; i++)
{
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() &&
- pDPObj->GetOutRange().aStart.Tab() == nTab &&
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
pDPObj->GetName() == rName )
return pDPObj;
}
@@ -344,7 +350,7 @@ ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nInd
for (USHORT i=0; i<nCount; i++)
{
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab )
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
{
if ( nFound == nIndex )
{
@@ -496,7 +502,7 @@ sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount() throw(RuntimeException)
for (USHORT i=0; i<nCount; i++)
{
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab )
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
++nFound;
}
return nFound;
@@ -560,7 +566,7 @@ Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames()
for (i=0; i<nCount; i++)
{
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab )
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
++nFound;
}
@@ -570,7 +576,7 @@ Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames()
for (i=0; i<nCount; i++)
{
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() && pDPObj->GetOutRange().aStart.Tab() == nTab )
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
pAry[nPos++] = pDPObj->GetName();
}
@@ -598,8 +604,7 @@ sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const OUString& aName )
//! allow all data sources!!!
ScDPObject* pDPObj = (*pColl)[i];
- if ( pDPObj->IsSheetData() &&
- pDPObj->GetOutRange().aStart.Tab() == nTab &&
+ if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
pDPObj->GetName() == aNamStr )
return TRUE;
}
@@ -696,11 +701,12 @@ CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange()
ScUnoGuard aGuard;
ScDPObject* pDPObject(GetDPObject());
- if (!pDPObject || !pDPObject->IsSheetData())
+ if (!pDPObject)
throw RuntimeException();
CellRangeAddress aRet;
- ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange );
+ if (pDPObject->IsSheetData())
+ ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange );
return aRet;
}
@@ -818,6 +824,99 @@ void SAL_CALL ScDataPilotDescriptorBase::setPropertyValue( const OUString& aProp
{
aNewData.SetDrillDown(::cppu::any2bool( aValue ));
}
+ else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
+ {
+ uno::Sequence<beans::PropertyValue> aArgSeq;
+ if ( aValue >>= aArgSeq )
+ {
+ ScImportSourceDesc aImportDesc;
+
+ const ScImportSourceDesc* pOldDesc = pDPObject->GetImportSourceDesc();
+ if (pOldDesc)
+ aImportDesc = *pOldDesc;
+
+ ScImportParam aParam;
+ ScImportDescriptor::FillImportParam( aParam, aArgSeq );
+
+ USHORT nNewType = sheet::DataImportMode_NONE;
+ if ( aParam.bImport )
+ {
+ if ( aParam.bSql )
+ nNewType = sheet::DataImportMode_SQL;
+ else if ( aParam.nType == ScDbQuery )
+ nNewType = sheet::DataImportMode_QUERY;
+ else
+ nNewType = sheet::DataImportMode_TABLE;
+ }
+ aImportDesc.nType = nNewType;
+ aImportDesc.aDBName = aParam.aDBName;
+ aImportDesc.aObject = aParam.aStatement;
+ aImportDesc.bNative = aParam.bNative;
+
+ pDPObject->SetImportDesc( aImportDesc );
+ }
+ }
+ else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
+ {
+ rtl::OUString aStrVal;
+ if ( aValue >>= aStrVal )
+ {
+ String aEmpty;
+ ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
+
+ const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
+ if (pOldDesc)
+ aServiceDesc = *pOldDesc;
+
+ aServiceDesc.aServiceName = aStrVal;
+
+ pDPObject->SetServiceData( aServiceDesc );
+ }
+ }
+ else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
+ {
+ uno::Sequence<beans::PropertyValue> aArgSeq;
+ if ( aValue >>= aArgSeq )
+ {
+ String aEmpty;
+ ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
+
+ const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
+ if (pOldDesc)
+ aServiceDesc = *pOldDesc;
+
+ rtl::OUString aStrVal;
+ sal_Int32 nArgs = aArgSeq.getLength();
+ for (sal_Int32 nArgPos=0; nArgPos<nArgs; ++nArgPos)
+ {
+ const beans::PropertyValue& rProp = aArgSeq[nArgPos];
+ String aPropName(rProp.Name);
+
+ if (aPropName.EqualsAscii( SC_UNO_SOURCENAME ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aServiceDesc.aParSource = aStrVal;
+ }
+ else if (aPropName.EqualsAscii( SC_UNO_OBJECTNAME ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aServiceDesc.aParName = aStrVal;
+ }
+ else if (aPropName.EqualsAscii( SC_UNO_USERNAME ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aServiceDesc.aParUser = aStrVal;
+ }
+ else if (aPropName.EqualsAscii( SC_UNO_PASSWORD ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aServiceDesc.aParPass = aStrVal;
+ }
+ }
+
+ pDPObject->SetServiceData( aServiceDesc );
+ }
+ }
else
throw UnknownPropertyException();
@@ -868,6 +967,63 @@ Any SAL_CALL ScDataPilotDescriptorBase::getPropertyValue( const OUString& aPrope
{
aRet = ::cppu::bool2any( aNewData.GetDrillDown() );
}
+ else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
+ {
+ const ScImportSourceDesc* pImportDesc = pDPObject->GetImportSourceDesc();
+ if ( pImportDesc )
+ {
+ // fill ScImportParam so ScImportDescriptor::FillProperties can be used
+ ScImportParam aParam;
+ aParam.bImport = ( pImportDesc->nType != sheet::DataImportMode_NONE );
+ aParam.aDBName = pImportDesc->aDBName;
+ aParam.aStatement = pImportDesc->aObject;
+ aParam.bNative = pImportDesc->bNative;
+ aParam.bSql = ( pImportDesc->nType == sheet::DataImportMode_SQL );
+ aParam.nType = static_cast<BYTE>(( pImportDesc->nType == sheet::DataImportMode_QUERY ) ? ScDbQuery : ScDbTable);
+
+ uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
+ ScImportDescriptor::FillProperties( aSeq, aParam );
+ aRet <<= aSeq;
+ }
+ else
+ {
+ // empty sequence
+ uno::Sequence<beans::PropertyValue> aEmpty(0);
+ aRet <<= aEmpty;
+ }
+ }
+ else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
+ {
+ rtl::OUString aServiceName;
+ const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
+ if (pServiceDesc)
+ aServiceName = pServiceDesc->aServiceName;
+ aRet <<= aServiceName; // empty string if no ServiceDesc set
+ }
+ else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
+ {
+ const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
+ if (pServiceDesc)
+ {
+ uno::Sequence<beans::PropertyValue> aSeq( 4 );
+ beans::PropertyValue* pArray = aSeq.getArray();
+ pArray[0].Name = rtl::OUString::createFromAscii( SC_UNO_SOURCENAME );
+ pArray[0].Value <<= rtl::OUString( pServiceDesc->aParSource );
+ pArray[1].Name = rtl::OUString::createFromAscii( SC_UNO_OBJECTNAME );
+ pArray[1].Value <<= rtl::OUString( pServiceDesc->aParName );
+ pArray[2].Name = rtl::OUString::createFromAscii( SC_UNO_USERNAME );
+ pArray[2].Value <<= rtl::OUString( pServiceDesc->aParUser );
+ pArray[3].Name = rtl::OUString::createFromAscii( SC_UNO_PASSWORD );
+ pArray[3].Value <<= rtl::OUString( pServiceDesc->aParPass );
+ aRet <<= aSeq;
+ }
+ else
+ {
+ // empty sequence
+ uno::Sequence<beans::PropertyValue> aEmpty(0);
+ aRet <<= aEmpty;
+ }
+ }
else
throw UnknownPropertyException();
}
@@ -966,7 +1122,8 @@ ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation(
ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) :
ScDataPilotDescriptorBase( pDocSh ),
nTab( nT ),
- aName( rN )
+ aName( rN ),
+ aModifyListeners( 0 )
{
}
@@ -981,6 +1138,7 @@ Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType )
// we also need to do the same for XDataPilotTable
SC_QUERYINTERFACE( XDataPilotTable )
SC_QUERYINTERFACE( XDataPilotTable2 )
+ SC_QUERYINTERFACE( XModifyBroadcaster )
return ScDataPilotDescriptorBase::queryInterface( rType );
}
@@ -1004,12 +1162,13 @@ Sequence< uno::Type > SAL_CALL ScDataPilotTableObj::getTypes() throw(RuntimeExce
sal_Int32 nParentLen = aParentTypes.getLength();
const uno::Type* pParentPtr = aParentTypes.getConstArray();
- aTypes.realloc( nParentLen + 1 );
+ aTypes.realloc( nParentLen + 2 );
uno::Type* pPtr = aTypes.getArray();
for (sal_Int32 i = 0; i < nParentLen; ++i)
pPtr[ i ] = pParentPtr[ i ]; // parent types first
pPtr[ nParentLen ] = getCppuType( (const Reference< XDataPilotTable2 >*)0 );
+ pPtr[ nParentLen+1 ] = getCppuType( (const Reference< XModifyBroadcaster >*)0 );
}
return aTypes;
}
@@ -1183,6 +1342,70 @@ CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 n
return aRet;
}
+void SAL_CALL ScDataPilotTableObj::addModifyListener( const uno::Reference<util::XModifyListener>& aListener )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ uno::Reference<util::XModifyListener> *pObj = new uno::Reference<util::XModifyListener>( aListener );
+ aModifyListeners.Insert( pObj, aModifyListeners.Count() );
+
+ if ( aModifyListeners.Count() == 1 )
+ {
+ acquire(); // don't lose this object (one ref for all listeners)
+ }
+}
+
+void SAL_CALL ScDataPilotTableObj::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ acquire(); // in case the listeners have the last ref - released below
+
+ USHORT nCount = aModifyListeners.Count();
+ for ( USHORT n=nCount; n--; )
+ {
+ uno::Reference<util::XModifyListener> *pObj = aModifyListeners[n];
+ if ( *pObj == aListener )
+ {
+ aModifyListeners.DeleteAndDestroy( n );
+
+ if ( aModifyListeners.Count() == 0 )
+ {
+ release(); // release the ref for the listeners
+ }
+
+ break;
+ }
+ }
+
+ release(); // might delete this object
+}
+
+void ScDataPilotTableObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.ISA(ScDataPilotModifiedHint) &&
+ static_cast<const ScDataPilotModifiedHint&>(rHint).GetName() == aName )
+ {
+ Refreshed_Impl();
+ }
+
+ ScDataPilotDescriptorBase::Notify( rBC, rHint );
+}
+
+void ScDataPilotTableObj::Refreshed_Impl()
+{
+ lang::EventObject aEvent;
+ aEvent.Source.set((cppu::OWeakObject*)this);
+
+ // the EventObject holds a Ref to this object until after the listener calls
+
+ ScDocument* pDoc = GetDocShell()->GetDocument();
+ for ( USHORT n=0; n<aModifyListeners.Count(); n++ )
+ pDoc->AddUnoListenerCall( *aModifyListeners[n], aEvent );
+}
+
// ============================================================================
ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) :