1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26
27 #include "SchXMLChartContext.hxx"
28 #include "SchXMLImport.hxx"
29 #include "SchXMLLegendContext.hxx"
30 #include "SchXMLPlotAreaContext.hxx"
31 #include "SchXMLParagraphContext.hxx"
32 #include "SchXMLTableContext.hxx"
33 #include "SchXMLSeriesHelper.hxx"
34 #include "SchXMLSeries2Context.hxx"
35 #include "SchXMLTools.hxx"
36 #include <comphelper/mediadescriptor.hxx>
37 #include <tools/debug.hxx>
38 // header for class ByteString
39 #include <tools/string.hxx>
40 #include "xmloff/xmlnmspe.hxx"
41 #include <xmloff/xmlement.hxx>
42 #include <xmloff/xmltoken.hxx>
43 #include <xmloff/nmspmap.hxx>
44 #include <xmloff/xmluconv.hxx>
45 #include <xmloff/xmlstyle.hxx>
46 #include <xmloff/prstylei.hxx>
47
48 #include "vector"
49 #include <com/sun/star/chart/XChartDocument.hpp>
50 #include <com/sun/star/chart/XDiagram.hpp>
51 #include <com/sun/star/xml/sax/XAttributeList.hpp>
52 #include <com/sun/star/util/XStringMapping.hpp>
53 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
54 #include <com/sun/star/drawing/XDrawPage.hpp>
55 #include <com/sun/star/chart/ChartDataRowSource.hpp>
56 #include <com/sun/star/awt/PosSize.hpp>
57 #include <com/sun/star/embed/Aspects.hpp>
58 #include <com/sun/star/embed/XVisualObject.hpp>
59
60 #include <com/sun/star/chart2/XChartDocument.hpp>
61 #include <com/sun/star/chart2/data/XDataSink.hpp>
62 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
63 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
64 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
65 #include <com/sun/star/chart2/XTitled.hpp>
66
67 using namespace com::sun::star;
68 using namespace ::xmloff::token;
69 using ::rtl::OUString;
70 using com::sun::star::uno::Reference;
71 using namespace ::SchXMLTools;
72
73 namespace
74 {
75
lcl_setRoleAtLabeledSequence(const uno::Reference<chart2::data::XLabeledDataSequence> & xLSeq,const::rtl::OUString & rRole)76 void lcl_setRoleAtLabeledSequence(
77 const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq,
78 const ::rtl::OUString &rRole )
79 {
80 // set role of sequence
81 uno::Reference< chart2::data::XDataSequence > xValues( xLSeq->getValues());
82 if( xValues.is())
83 {
84 uno::Reference< beans::XPropertySet > xProp( xValues, uno::UNO_QUERY );
85 if( xProp.is())
86 xProp->setPropertyValue(OUString::createFromAscii("Role"), uno::makeAny( rRole ));
87 }
88 }
89
lcl_MoveDataToCandleStickSeries(const uno::Reference<chart2::data::XDataSource> & xDataSource,const uno::Reference<chart2::XDataSeries> & xDestination,const OUString & rRole)90 void lcl_MoveDataToCandleStickSeries(
91 const uno::Reference< chart2::data::XDataSource > & xDataSource,
92 const uno::Reference< chart2::XDataSeries > & xDestination,
93 const OUString & rRole )
94 {
95 try
96 {
97 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq(
98 xDataSource->getDataSequences());
99 if( aLabeledSeq.getLength())
100 {
101 lcl_setRoleAtLabeledSequence( aLabeledSeq[0], rRole );
102
103 // add to data series
104 uno::Reference< chart2::data::XDataSource > xSource( xDestination, uno::UNO_QUERY_THROW );
105 // @todo: realloc only once outside this function
106 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
107 aData.realloc( aData.getLength() + 1);
108 aData[ aData.getLength() - 1 ] = aLabeledSeq[0];
109 uno::Reference< chart2::data::XDataSink > xSink( xDestination, uno::UNO_QUERY_THROW );
110 xSink->setData( aData );
111 }
112 }
113 catch( uno::Exception & )
114 {
115 OSL_ENSURE( false, "Exception caught while moving data to candlestick series" );
116 }
117 }
118
lcl_setRoleAtFirstSequence(const uno::Reference<chart2::XDataSeries> & xSeries,const::rtl::OUString & rRole)119 void lcl_setRoleAtFirstSequence(
120 const uno::Reference< chart2::XDataSeries > & xSeries,
121 const ::rtl::OUString & rRole )
122 {
123 uno::Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
124 if( xSource.is())
125 {
126 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
127 if( aSeq.getLength())
128 lcl_setRoleAtLabeledSequence( aSeq[0], rRole );
129 }
130 }
131
lcl_removeEmptyChartTypeGroups(const uno::Reference<chart2::XChartDocument> & xDoc)132 void lcl_removeEmptyChartTypeGroups( const uno::Reference< chart2::XChartDocument > & xDoc )
133 {
134 if( ! xDoc.is())
135 return;
136
137 uno::Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram());
138 if( ! xDia.is())
139 return;
140
141 try
142 {
143 // count all charttype groups to be able to leave at least one
144 sal_Int32 nRemainingGroups = 0;
145 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
146 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
147 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
148 for( sal_Int32 nI = aCooSysSeq.getLength(); nI--; )
149 {
150 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
151 nRemainingGroups += xCTCnt->getChartTypes().getLength();
152 }
153
154 // delete all empty groups, but leave at least group (empty or not)
155 for( sal_Int32 nI = aCooSysSeq.getLength(); nI-- && (nRemainingGroups > 1); )
156 {
157 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
158 uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
159 for( sal_Int32 nJ=aCTSeq.getLength(); nJ-- && (nRemainingGroups > 1); )
160 {
161 uno::Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nJ], uno::UNO_QUERY_THROW );
162 if( xDSCnt->getDataSeries().getLength() == 0 )
163 {
164 // note: iterator stays valid as we have a local sequence
165 xCTCnt->removeChartType( aCTSeq[nJ] );
166 --nRemainingGroups;
167 }
168 }
169 }
170 }
171 catch( uno::Exception & ex )
172 {
173 String aStr( ex.Message );
174 ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
175 DBG_ERROR1( "Exception caught while removing empty chart types: %s", aBStr.GetBuffer());
176 }
177 }
178
lcl_getNumberSequenceFromString(const::rtl::OUString & rStr,bool bAddOneToEachOldIndex)179 uno::Sequence< sal_Int32 > lcl_getNumberSequenceFromString( const ::rtl::OUString& rStr, bool bAddOneToEachOldIndex )
180 {
181 const sal_Unicode aSpace( ' ' );
182
183 // count number of entries
184 ::std::vector< sal_Int32 > aVec;
185 sal_Int32 nLastPos = 0;
186 sal_Int32 nPos = 0;
187 while( nPos != -1 )
188 {
189 nPos = rStr.indexOf( aSpace, nLastPos );
190 if( nPos > nLastPos )
191 {
192 aVec.push_back( rStr.copy( nLastPos, (nPos - nLastPos) ).toInt32() );
193 }
194 if( nPos != -1 )
195 nLastPos = nPos + 1;
196 }
197 // last entry
198 if( nLastPos != 0 &&
199 rStr.getLength() > nLastPos )
200 {
201 aVec.push_back( rStr.copy( nLastPos, (rStr.getLength() - nLastPos) ).toInt32() );
202 }
203
204 const sal_Int32 nVecSize = aVec.size();
205 uno::Sequence< sal_Int32 > aSeq( nVecSize );
206
207 if(!bAddOneToEachOldIndex)
208 {
209 sal_Int32* pSeqArr = aSeq.getArray();
210 for( nPos = 0; nPos < nVecSize; ++nPos )
211 {
212 pSeqArr[ nPos ] = aVec[ nPos ];
213 }
214 }
215 else if( bAddOneToEachOldIndex )
216 {
217 aSeq.realloc( nVecSize+1 );
218 aSeq[0]=0;
219
220 sal_Int32* pSeqArr = aSeq.getArray();
221 for( nPos = 0; nPos < nVecSize; ++nPos )
222 {
223 pSeqArr[ nPos+1 ] = aVec[ nPos ]+1;
224 }
225 }
226
227 return aSeq;
228 }
229
230 } // anonymous namespace
231
232 // ----------------------------------------
233
SchXMLChartContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,const rtl::OUString & rLocalName)234 SchXMLChartContext::SchXMLChartContext( SchXMLImportHelper& rImpHelper,
235 SvXMLImport& rImport, const rtl::OUString& rLocalName ) :
236 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
237 mrImportHelper( rImpHelper ),
238 m_bHasRangeAtPlotArea( false ),
239 m_bHasTableElement( false ),
240 mbAllRangeAddressesAvailable( sal_True ),
241 mbColHasLabels( sal_False ),
242 mbRowHasLabels( sal_False ),
243 meDataRowSource( chart::ChartDataRowSource_COLUMNS ),
244 mbIsStockChart( false )
245 {
246 }
247
~SchXMLChartContext()248 SchXMLChartContext::~SchXMLChartContext()
249 {}
250
StartElement(const uno::Reference<xml::sax::XAttributeList> & xAttrList)251 void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
252 {
253 // parse attributes
254 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
255 const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetChartAttrTokenMap();
256
257 uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
258 DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size");
259 if( xVisualObject.is() )
260 maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
261
262 // this flag is necessarry for pie charts in the core
263 sal_Bool bSetSwitchData = sal_False;
264
265 ::rtl::OUString sAutoStyleName;
266 ::rtl::OUString aOldChartTypeName;
267 bool bHasAddin = false;
268
269 for( sal_Int16 i = 0; i < nAttrCount; i++ )
270 {
271 rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
272 rtl::OUString aLocalName;
273 rtl::OUString aValue = xAttrList->getValueByIndex( i );
274 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
275
276 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
277 {
278 case XML_TOK_CHART_HREF:
279 m_aXLinkHRefAttributeToIndicateDataProvider = aValue;
280 break;
281
282 case XML_TOK_CHART_CLASS:
283 {
284 rtl::OUString sClassName;
285 sal_uInt16 nClassPrefix =
286 GetImport().GetNamespaceMap().GetKeyByAttrName(
287 aValue, &sClassName );
288 if( XML_NAMESPACE_CHART == nClassPrefix )
289 {
290 SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
291 if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
292 {
293 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
294 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
295 switch( eChartTypeEnum )
296 {
297 case XML_CHART_CLASS_CIRCLE:
298 bSetSwitchData = sal_True;
299 break;
300 case XML_CHART_CLASS_STOCK:
301 mbIsStockChart = true;
302 break;
303 default:
304 break;
305 }
306 }
307 }
308 else if( XML_NAMESPACE_OOO == nClassPrefix )
309 {
310 // service is taken from add-in-name attribute
311 bHasAddin = true;
312
313 aOldChartTypeName = sClassName;
314 maChartTypeServiceName = sClassName;
315 }
316 }
317 break;
318
319 case XML_TOK_CHART_WIDTH:
320 GetImport().GetMM100UnitConverter().convertMeasure( maChartSize.Width, aValue );
321 break;
322
323 case XML_TOK_CHART_HEIGHT:
324 GetImport().GetMM100UnitConverter().convertMeasure( maChartSize.Height, aValue );
325 break;
326
327 case XML_TOK_CHART_STYLE_NAME:
328 sAutoStyleName = aValue;
329 break;
330
331 case XML_TOK_CHART_COL_MAPPING:
332 msColTrans = aValue;
333 break;
334 case XML_TOK_CHART_ROW_MAPPING:
335 msRowTrans = aValue;
336 break;
337 }
338 }
339
340 if( aOldChartTypeName.getLength()<= 0 )
341 {
342 DBG_ERROR( "need a charttype to create a diagram" );
343 //set a fallback value:
344 ::rtl::OUString aChartClass_Bar( GetXMLToken(XML_BAR ) );
345 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
346 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
347 }
348
349 // Set the size of the draw page.
350 if( xVisualObject.is() )
351 xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
352
353 InitChart( aOldChartTypeName, bSetSwitchData);
354
355 if( bHasAddin )
356 {
357 //correct charttype serveice name when having an addin
358 //and don't refresh addin during load
359 uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
360 if( xDocProp.is() )
361 {
362 try
363 {
364 xDocProp->getPropertyValue( ::rtl::OUString::createFromAscii("BaseDiagram")) >>= aOldChartTypeName;
365 maChartTypeServiceName = SchXMLTools::GetNewChartTypeName( aOldChartTypeName );
366 xDocProp->setPropertyValue( rtl::OUString::createFromAscii( "RefreshAddInAllowed" ) , uno::makeAny( sal_False) );
367 }
368 catch( uno::Exception & )
369 {
370 DBG_ERROR( "Exception during import SchXMLChartContext::StartElement" );
371 }
372 }
373 }
374
375 // set auto-styles for Area
376 uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument()->getArea(), uno::UNO_QUERY );
377 if( xProp.is())
378 {
379 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
380 if( pStylesCtxt )
381 {
382 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
383 mrImportHelper.GetChartFamilyID(), sAutoStyleName );
384
385 if( pStyle && pStyle->ISA( XMLPropStyleContext ))
386 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
387 }
388 }
389 }
390
391 namespace
392 {
393
394 struct NewDonutSeries
395 {
396 ::com::sun::star::uno::Reference<
397 ::com::sun::star::chart2::XDataSeries > m_xSeries;
398 ::rtl::OUString msStyleName;
399 sal_Int32 mnAttachedAxis;
400
401 ::std::vector< ::rtl::OUString > m_aSeriesStyles;
402 ::std::vector< ::rtl::OUString > m_aPointStyles;
403
NewDonutSeries__anond7aea9fa0211::NewDonutSeries404 NewDonutSeries( const ::com::sun::star::uno::Reference<
405 ::com::sun::star::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
406 : m_xSeries( xSeries )
407 , mnAttachedAxis( 1 )
408 {
409 m_aPointStyles.resize(nPointCount);
410 m_aSeriesStyles.resize(nPointCount);
411 }
412
setSeriesStyleNameToPoint__anond7aea9fa0211::NewDonutSeries413 void setSeriesStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
414 {
415 DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()),"donut point <-> series count mismatch");
416 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
417 m_aSeriesStyles[nPointIndex]=rStyleName;
418 }
419
setPointStyleNameToPoint__anond7aea9fa0211::NewDonutSeries420 void setPointStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
421 {
422 DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()),"donut point <-> series count mismatch");
423 if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
424 m_aPointStyles[nPointIndex]=rStyleName;
425 }
426
creatStyleList__anond7aea9fa0211::NewDonutSeries427 ::std::list< DataRowPointStyle > creatStyleList()
428 {
429 ::std::list< DataRowPointStyle > aRet;
430
431 DataRowPointStyle aSeriesStyle( DataRowPointStyle::DATA_SERIES
432 , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
433 aRet.push_back( aSeriesStyle );
434
435 sal_Int32 nPointIndex=0;
436 ::std::vector< ::rtl::OUString >::iterator aPointIt( m_aPointStyles.begin() );
437 ::std::vector< ::rtl::OUString >::iterator aPointEnd( m_aPointStyles.end() );
438 while( aPointIt != aPointEnd )
439 {
440 DataRowPointStyle aPointStyle( DataRowPointStyle::DATA_POINT
441 , m_xSeries, nPointIndex, 1, *aPointIt, mnAttachedAxis );
442 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
443 {
444 aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
445 }
446 if( aPointStyle.msSeriesStyleNameForDonuts.getLength()
447 || aPointStyle.msStyleName.getLength() )
448 aRet.push_back( aPointStyle );
449 ++aPointIt;
450 ++nPointIndex;
451 }
452
453 return aRet;
454 }
455 };
456
lcl_swapPointAndSeriesStylesForDonutCharts(::std::list<DataRowPointStyle> & rStyleList,const::std::map<::com::sun::star::uno::Reference<::com::sun::star::chart2::XDataSeries>,sal_Int32> & rSeriesMap)457 void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::list< DataRowPointStyle >& rStyleList
458 , const ::std::map< ::com::sun::star::uno::Reference<
459 ::com::sun::star::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
460 {
461 ::std::list< DataRowPointStyle >::iterator aIt(rStyleList.begin());
462 ::std::list< DataRowPointStyle >::iterator aEnd(rStyleList.end());
463
464 //detect old series count
465 //and add old series to aSeriesMap
466 ::std::map< ::com::sun::star::uno::Reference<
467 ::com::sun::star::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
468 sal_Int32 nOldSeriesCount = 0;
469 {
470 sal_Int32 nMaxOldSeriesIndex = 0;
471 sal_Int32 nOldSeriesIndex = 0;
472 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
473 {
474 DataRowPointStyle aStyle(*aIt);
475 if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
476 aStyle.m_xSeries.is() )
477 {
478 nMaxOldSeriesIndex = nOldSeriesIndex;
479
480 if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
481 aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
482
483 nOldSeriesIndex++;
484 }
485 }
486 nOldSeriesCount = nMaxOldSeriesIndex+1;
487 }
488 /*
489 sal_Int32 nOldSeriesCount = 0;
490 {
491 sal_Int32 nMaxOldSeriesIndex = 0;
492 sal_Int32 nOldSeriesIndex = 0;
493 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
494 {
495 DataRowPointStyle aStyle(*aIt);
496 if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
497 {
498 nMaxOldSeriesIndex = nOldSeriesIndex;
499 nOldSeriesIndex++;
500 }
501 }
502 nOldSeriesCount = nMaxOldSeriesIndex+1;
503 }
504 */
505
506
507 //initialize new series styles
508 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapIt( aSeriesMap.begin() );
509 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
510
511 //sort by index
512 ::std::vector< NewDonutSeries > aNewSeriesVector;
513 {
514 ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
515 for( ; aSeriesMapIt != aSeriesMapEnd; ++aSeriesMapIt )
516 aIndexSeriesMap[aSeriesMapIt->second] = aSeriesMapIt->first;
517
518 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexIt( aIndexSeriesMap.begin() );
519 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexEnd( aIndexSeriesMap.end() );
520
521 for( ; aIndexIt != aIndexEnd; ++aIndexIt )
522 aNewSeriesVector.push_back( NewDonutSeries(aIndexIt->second,nOldSeriesCount) );
523 }
524
525 //overwrite attached axis information according to old series styles
526 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
527 {
528 DataRowPointStyle aStyle(*aIt);
529 if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
530 {
531 aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
532 if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
533 aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
534 }
535 }
536
537 //overwrite new series style names with old series style name information
538 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
539 {
540 DataRowPointStyle aStyle(*aIt);
541 if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
542 {
543 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
544 if( aSeriesMapEnd != aSeriesMapIt )
545 {
546 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
547
548 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
549 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
550
551 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
552 aNewSeriesIt->setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
553 }
554 }
555 }
556
557 //overwrite new series style names with point style name information
558 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
559 {
560 DataRowPointStyle aStyle(*aIt);
561 if( aStyle.meType == DataRowPointStyle::DATA_POINT )
562 {
563 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
564 if( aSeriesMapEnd != aSeriesMapIt )
565 {
566 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
567 sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
568 sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
569
570 while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
571 {
572 NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
573 rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
574
575 nRepeatCount--;
576 nNewSeriesIndex++;
577 }
578 }
579 }
580 }
581
582 //put information from aNewSeriesVector to output parameter rStyleList
583 rStyleList.clear();
584
585 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
586 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
587 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
588 {
589 ::std::list< DataRowPointStyle > aList( aNewSeriesIt->creatStyleList() );
590 rStyleList.insert(rStyleList.end(),aList.begin(),aList.end());
591 }
592 }
593
lcl_SpecialHandlingForDonutChartNeeded(const::rtl::OUString & rServiceName,const SvXMLImport & rImport)594 bool lcl_SpecialHandlingForDonutChartNeeded(
595 const ::rtl::OUString & rServiceName,
596 const SvXMLImport & rImport )
597 {
598 bool bResult = false;
599 if( rServiceName.equalsAsciiL(
600 RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.DonutChartType" )))
601 {
602 bResult = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( rImport.GetModel() );
603 }
604 return bResult;
605 }
606
607 } // anonymous namespace
608
609
lcl_ApplyDataFromRectangularRangeToDiagram(const uno::Reference<chart2::XChartDocument> & xNewDoc,const rtl::OUString & rRectangularRange,::com::sun::star::chart::ChartDataRowSource eDataRowSource,bool bRowHasLabels,bool bColHasLabels,bool bSwitchOnLabelsAndCategoriesForOwnData,const rtl::OUString & sColTrans,const rtl::OUString & sRowTrans)610 void lcl_ApplyDataFromRectangularRangeToDiagram(
611 const uno::Reference< chart2::XChartDocument >& xNewDoc
612 , const rtl::OUString& rRectangularRange
613 , ::com::sun::star::chart::ChartDataRowSource eDataRowSource
614 , bool bRowHasLabels, bool bColHasLabels
615 , bool bSwitchOnLabelsAndCategoriesForOwnData
616 , const rtl::OUString& sColTrans
617 , const rtl::OUString& sRowTrans )
618 {
619 if( !xNewDoc.is() )
620 return;
621
622 uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
623 uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
624 if( !xNewDia.is() || !xDataProvider.is() )
625 return;
626
627 sal_Bool bFirstCellAsLabel =
628 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
629 sal_Bool bHasCateories =
630 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
631
632 if( bSwitchOnLabelsAndCategoriesForOwnData )
633 {
634 bFirstCellAsLabel = true;
635 bHasCateories = true;
636 }
637
638 uno::Sequence< beans::PropertyValue > aArgs( 3 );
639 aArgs[0] = beans::PropertyValue(
640 ::rtl::OUString::createFromAscii("CellRangeRepresentation"),
641 -1, uno::makeAny( rRectangularRange ),
642 beans::PropertyState_DIRECT_VALUE );
643 aArgs[1] = beans::PropertyValue(
644 ::rtl::OUString::createFromAscii("DataRowSource"),
645 -1, uno::makeAny( eDataRowSource ),
646 beans::PropertyState_DIRECT_VALUE );
647 aArgs[2] = beans::PropertyValue(
648 ::rtl::OUString::createFromAscii("FirstCellAsLabel"),
649 -1, uno::makeAny( bFirstCellAsLabel ),
650 beans::PropertyState_DIRECT_VALUE );
651
652 if( sColTrans.getLength() || sRowTrans.getLength() )
653 {
654 aArgs.realloc( aArgs.getLength() + 1 );
655 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
656 ::rtl::OUString::createFromAscii("SequenceMapping"),
657 -1, uno::makeAny( sColTrans.getLength()
658 ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
659 : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
660 beans::PropertyState_DIRECT_VALUE );
661 }
662
663 //work around wrong writer ranges ( see Issue 58464 )
664 {
665 rtl::OUString aChartOleObjectName;
666 uno::Reference< frame::XModel > xModel(xNewDoc, uno::UNO_QUERY );
667 if( xModel.is() )
668 {
669 comphelper::MediaDescriptor aMediaDescriptor( xModel->getArgs() );
670
671 comphelper::MediaDescriptor::const_iterator aIt(
672 aMediaDescriptor.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HierarchicalDocumentName" ))));
673 if( aIt != aMediaDescriptor.end() )
674 {
675 aChartOleObjectName = (*aIt).second.get< ::rtl::OUString >();
676 }
677 }
678 if( aChartOleObjectName.getLength() )
679 {
680 aArgs.realloc( aArgs.getLength() + 1 );
681 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
682 ::rtl::OUString::createFromAscii("ChartOleObjectName"),
683 -1, uno::makeAny( aChartOleObjectName ),
684 beans::PropertyState_DIRECT_VALUE );
685 }
686 }
687
688
689 uno::Reference< chart2::data::XDataSource > xDataSource(
690 xDataProvider->createDataSource( aArgs ));
691
692 aArgs.realloc( aArgs.getLength() + 2 );
693 aArgs[ aArgs.getLength() - 2 ] = beans::PropertyValue(
694 ::rtl::OUString::createFromAscii("HasCategories"),
695 -1, uno::makeAny( bHasCateories ),
696 beans::PropertyState_DIRECT_VALUE );
697 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
698 ::rtl::OUString::createFromAscii("UseCategoriesAsX"),
699 -1, uno::makeAny( sal_False ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
700 beans::PropertyState_DIRECT_VALUE );
701
702 xNewDia->setDiagramData( xDataSource, aArgs );
703 }
704
EndElement()705 void SchXMLChartContext::EndElement()
706 {
707 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
708 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
709 uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
710
711 if( xProp.is())
712 {
713 if( maMainTitle.getLength())
714 {
715 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
716 if( xTitleProp.is())
717 {
718 try
719 {
720 uno::Any aAny;
721 aAny <<= maMainTitle;
722 xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
723 }
724 catch( beans::UnknownPropertyException )
725 {
726 DBG_ERROR( "Property String for Title not available" );
727 }
728 }
729 }
730 if( maSubTitle.getLength())
731 {
732 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
733 if( xTitleProp.is())
734 {
735 try
736 {
737 uno::Any aAny;
738 aAny <<= maSubTitle;
739 xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
740 }
741 catch( beans::UnknownPropertyException )
742 {
743 DBG_ERROR( "Property String for Title not available" );
744 }
745 }
746 }
747 }
748
749 // cleanup: remove empty chart type groups
750 lcl_removeEmptyChartTypeGroups( xNewDoc );
751
752 // set stack mode before a potential chart type detection (in case we have a rectangular range)
753 uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
754 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
755 if( xDiaProp.is())
756 {
757 if( maSeriesDefaultsAndStyles.maStackedDefault.hasValue())
758 xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Stacked")),maSeriesDefaultsAndStyles.maStackedDefault);
759 if( maSeriesDefaultsAndStyles.maPercentDefault.hasValue())
760 xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Percent")),maSeriesDefaultsAndStyles.maPercentDefault);
761 if( maSeriesDefaultsAndStyles.maDeepDefault.hasValue())
762 xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Deep")),maSeriesDefaultsAndStyles.maDeepDefault);
763 if( maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault.hasValue())
764 xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StackedBarsConnected")),maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
765 }
766
767 //the OOo 2.0 implementation and older has a bug with donuts
768 bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
769 maChartTypeServiceName, GetImport());
770
771 // apply data
772 if(!xNewDoc.is())
773 return;
774
775 bool bHasOwnData = false;
776 if( m_aXLinkHRefAttributeToIndicateDataProvider.equalsAscii( "." ) ) //data comes from the chart itself
777 bHasOwnData = true;
778 else if( m_aXLinkHRefAttributeToIndicateDataProvider.equalsAscii( ".." ) ) //data comes from the parent application
779 bHasOwnData = false;
780 else if( m_aXLinkHRefAttributeToIndicateDataProvider.getLength() ) //not supported so far to get the data by sibling objects -> fall back to chart itself if data are available
781 bHasOwnData = m_bHasTableElement;
782 else
783 bHasOwnData = !m_bHasRangeAtPlotArea;
784
785 if( xNewDoc->hasInternalDataProvider())
786 {
787 if( !m_bHasTableElement && !m_aXLinkHRefAttributeToIndicateDataProvider.equalsAscii( "." ) )
788 {
789 //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
790 bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
791 bHasOwnData = !bSwitchSuccessful;
792 }
793 else
794 bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
795 }
796 else if( bHasOwnData )
797 {
798 xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
799 }
800 if( bHasOwnData )
801 msChartAddress = ::rtl::OUString::createFromAscii("all");
802
803 bool bSwitchRangesFromOuterToInternalIfNecessary = false;
804 if( !bHasOwnData && mbAllRangeAddressesAvailable )
805 {
806 // special handling for stock chart (merge series together)
807 if( mbIsStockChart )
808 MergeSeriesForStockChart();
809 }
810 else if( msChartAddress.getLength() )
811 {
812 //own data or only rectangular range available
813
814 if( xNewDoc->hasInternalDataProvider() )
815 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
816
817 bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( Reference< frame::XModel >( xNewDoc, uno::UNO_QUERY ));
818 bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
819
820 if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
821 !bOldFileWithOwnDataFromRows )
822 {
823 //bHasOwnData is true in this case!
824 //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
825 bSwitchRangesFromOuterToInternalIfNecessary = true;
826 }
827 else
828 {
829 //apply data from rectangular range
830
831 // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
832 try
833 {
834 if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
835 xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IncludeHiddenCells")),uno::makeAny(false));
836
837 // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
838 // (analogously mbColHasLabels means we have "row-descriptions")
839 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
840 }
841 catch( uno::Exception & )
842 {
843 //try to fallback to internal data
844 DBG_ERROR( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
845 if(!bHasOwnData)
846 {
847 bHasOwnData = true;
848 msChartAddress = ::rtl::OUString::createFromAscii("all");
849 if( !xNewDoc->hasInternalDataProvider() )
850 {
851 xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
852 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
853 try
854 {
855 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
856 }
857 catch( uno::Exception & )
858 {
859 DBG_ERROR( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
860 }
861 }
862 }
863 }
864 }
865 }
866 else
867 {
868 DBG_ERROR( " Must not get here" );
869 }
870
871 // now all series and data point properties are available and can be set
872 {
873 if( bSpecialHandlingForDonutChart )
874 {
875 uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
876 lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleList
877 , SchXMLSeriesHelper::getDataSeriesIndexMapFromDiagram(xNewDiagram) );
878 }
879
880 SchXMLSeries2Context::initSeriesPropertySets( maSeriesDefaultsAndStyles, uno::Reference< frame::XModel >(xDoc, uno::UNO_QUERY ) );
881
882 //set defaults from diagram to the new series:
883 //check whether we need to remove lines from symbol only charts
884 bool bSwitchOffLinesForScatter = false;
885 {
886 bool bLinesOn = true;
887 if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
888 {
889 if( 0 == maChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) )
890 {
891 bSwitchOffLinesForScatter = true;
892 SchXMLSeries2Context::switchSeriesLinesOff( maSeriesDefaultsAndStyles.maSeriesStyleList );
893 }
894 }
895 }
896 SchXMLSeries2Context::setDefaultsToSeries( maSeriesDefaultsAndStyles );
897
898 // set autostyles for series and data points
899 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
900 const SvXMLStyleContext* pStyle = NULL;
901 ::rtl::OUString sCurrStyleName;
902
903 if( pStylesCtxt )
904 {
905 //iterate over data-series first
906 //don't set series styles for donut charts
907 if( !bSpecialHandlingForDonutChart )
908 {
909 SchXMLSeries2Context::setStylesToSeries( maSeriesDefaultsAndStyles
910 , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, maLSequencesPerIndex );
911 // ... then set attributes for statistics (after their existence was set in the series)
912 SchXMLSeries2Context::setStylesToStatisticsObjects( maSeriesDefaultsAndStyles
913 , pStylesCtxt, pStyle, sCurrStyleName );
914 }
915 }
916
917 //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
918 if( bSwitchRangesFromOuterToInternalIfNecessary )
919 {
920 if( xNewDoc->hasInternalDataProvider() )
921 SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary( maTable, maLSequencesPerIndex, xNewDoc, meDataRowSource );
922 }
923
924 if( pStylesCtxt )
925 {
926 // ... then iterate over data-point attributes, so the latter are not overwritten
927 SchXMLSeries2Context::setStylesToDataPoints( maSeriesDefaultsAndStyles
928 , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
929 }
930 }
931
932 if( xProp.is())
933 xProp->setPropertyValue( rtl::OUString::createFromAscii( "RefreshAddInAllowed" ) , uno::makeAny( sal_True) );
934 }
935
MergeSeriesForStockChart()936 void SchXMLChartContext::MergeSeriesForStockChart()
937 {
938 OSL_ASSERT( mbIsStockChart );
939 try
940 {
941 uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
942 uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
943 uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
944 if( ! xDiagram.is())
945 return;
946
947 bool bHasJapaneseCandlestick = true;
948 uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
949 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
950 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
951 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
952 {
953 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
954 uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
955 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
956 {
957 if( aChartTypes[nCTIdx]->getChartType().equalsAsciiL(
958 RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType")))
959 {
960 xDSContainer.set( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
961 uno::Reference< beans::XPropertySet > xCTProp( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
962 xCTProp->getPropertyValue( ::rtl::OUString::createFromAscii("Japanese")) >>= bHasJapaneseCandlestick;
963 break;
964 }
965 }
966 }
967
968 if( xDSContainer.is())
969 {
970 // with japanese candlesticks: open, low, high, close
971 // otherwise: low, high, close
972 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
973 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
974 const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
975 sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
976 OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
977 uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
978 for( sal_Int32 i=0; i<nCandleStickCount; ++i )
979 {
980 sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
981 if( bHasJapaneseCandlestick )
982 {
983 // open values
984 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString::createFromAscii("values-first"));
985 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
986 // low values
987 lcl_MoveDataToCandleStickSeries(
988 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
989 aNewSeries[i], OUString::createFromAscii("values-min"));
990 }
991 else
992 {
993 // low values
994 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString::createFromAscii("values-min"));
995 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
996 }
997 // high values
998 lcl_MoveDataToCandleStickSeries(
999 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1000 aNewSeries[i], OUString::createFromAscii("values-max"));
1001 // close values
1002 lcl_MoveDataToCandleStickSeries(
1003 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
1004 aNewSeries[i], OUString::createFromAscii("values-last"));
1005 }
1006 xDSContainer->setDataSeries( aNewSeries );
1007 }
1008 }
1009 catch( uno::Exception & )
1010 {
1011 DBG_ERROR( "Exception while merging series for stock chart" );
1012 }
1013 }
1014
CreateChildContext(sal_uInt16 nPrefix,const rtl::OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> & xAttrList)1015 SvXMLImportContext* SchXMLChartContext::CreateChildContext(
1016 sal_uInt16 nPrefix,
1017 const rtl::OUString& rLocalName,
1018 const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1019 {
1020 static const sal_Bool bTrue = sal_True;
1021 static const uno::Any aTrueBool( &bTrue, ::getBooleanCppuType());
1022
1023 SvXMLImportContext* pContext = 0;
1024 const SvXMLTokenMap& rTokenMap = mrImportHelper.GetChartElemTokenMap();
1025 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1026 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
1027
1028 switch( rTokenMap.Get( nPrefix, rLocalName ))
1029 {
1030 case XML_TOK_CHART_PLOT_AREA:
1031 pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName,
1032 m_aXLinkHRefAttributeToIndicateDataProvider,
1033 maSeriesAddresses, msCategoriesAddress,
1034 msChartAddress, m_bHasRangeAtPlotArea, mbAllRangeAddressesAvailable,
1035 mbColHasLabels, mbRowHasLabels,
1036 meDataRowSource,
1037 maSeriesDefaultsAndStyles,
1038 maChartTypeServiceName,
1039 maLSequencesPerIndex, maChartSize );
1040 break;
1041
1042 case XML_TOK_CHART_TITLE:
1043 if( xDoc.is())
1044 {
1045 if( xProp.is())
1046 {
1047 xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasMainTitle" ), aTrueBool );
1048 }
1049 uno::Reference< drawing::XShape > xTitleShape( xDoc->getTitle(), uno::UNO_QUERY );
1050 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1051 rLocalName, maMainTitle, xTitleShape );
1052 }
1053 break;
1054
1055 case XML_TOK_CHART_SUBTITLE:
1056 if( xDoc.is())
1057 {
1058 if( xProp.is())
1059 {
1060 xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasSubTitle" ), aTrueBool );
1061 }
1062 uno::Reference< drawing::XShape > xTitleShape( xDoc->getSubTitle(), uno::UNO_QUERY );
1063 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1064 rLocalName, maSubTitle, xTitleShape );
1065 }
1066 break;
1067
1068 case XML_TOK_CHART_LEGEND:
1069 pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName );
1070 break;
1071
1072 case XML_TOK_CHART_TABLE:
1073 {
1074 SchXMLTableContext * pTableContext =
1075 new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable );
1076 m_bHasTableElement = true;
1077 // #i85913# take into account column- and row- mapping for
1078 // charts with own data only for those which were not copied
1079 // from a place where they got data from the container. Note,
1080 // that this requires the plot-area been read before the table
1081 // (which is required in the ODF spec)
1082 // Note: For stock charts and donut charts with special handling
1083 // the mapping must not be applied!
1084 if( !msChartAddress.getLength() && !mbIsStockChart &&
1085 !lcl_SpecialHandlingForDonutChartNeeded(
1086 maChartTypeServiceName, GetImport()))
1087 {
1088 if( msColTrans.getLength() > 0 )
1089 {
1090 OSL_ASSERT( msRowTrans.getLength() == 0 );
1091 pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1092 msColTrans = OUString();
1093 }
1094 else if( msRowTrans.getLength() > 0 )
1095 {
1096 pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1097 msRowTrans = OUString();
1098 }
1099 }
1100 pContext = pTableContext;
1101 }
1102 break;
1103
1104 default:
1105 // try importing as an additional shape
1106 if( ! mxDrawPage.is())
1107 {
1108 uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1109 if( xSupp.is())
1110 mxDrawPage = uno::Reference< drawing::XShapes >( xSupp->getDrawPage(), uno::UNO_QUERY );
1111
1112 DBG_ASSERT( mxDrawPage.is(), "Invalid Chart Page" );
1113 }
1114 if( mxDrawPage.is())
1115 pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
1116 GetImport(), nPrefix, rLocalName, xAttrList, mxDrawPage );
1117 break;
1118 }
1119
1120 if( ! pContext )
1121 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1122
1123 return pContext;
1124 }
1125
1126
1127 /*
1128 With a locked controller the following is done here:
1129 1. Hide title, subtitle, and legend.
1130 2. Set the size of the draw page.
1131 3. Set a (logically) empty data set.
1132 4. Set the chart type.
1133 */
InitChart(const OUString & rChartTypeServiceName,sal_Bool)1134 void SchXMLChartContext::InitChart(
1135 const OUString & rChartTypeServiceName, // currently the old service name
1136 sal_Bool /* bSetSwitchData */ )
1137 {
1138 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1139 DBG_ASSERT( xDoc.is(), "No valid document!" );
1140 uno::Reference< frame::XModel > xModel (xDoc, uno::UNO_QUERY );
1141
1142 // Remove Title and Diagram ("De-InitNew")
1143 uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1144 if( xNewDoc.is())
1145 {
1146 xNewDoc->setFirstDiagram( 0 );
1147 uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1148 if( xTitled.is())
1149 xTitled->setTitleObject( 0 );
1150 }
1151
1152 // Set the chart type via setting the diagram.
1153 if( rChartTypeServiceName.getLength() &&
1154 xDoc.is())
1155 {
1156 uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1157 if( xFact.is())
1158 {
1159 uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1160 if( xDia.is())
1161 xDoc->setDiagram( xDia );
1162 }
1163 }
1164 }
1165
1166 // ----------------------------------------
1167
SchXMLTitleContext(SchXMLImportHelper & rImpHelper,SvXMLImport & rImport,const rtl::OUString & rLocalName,rtl::OUString & rTitle,uno::Reference<drawing::XShape> & xTitleShape)1168 SchXMLTitleContext::SchXMLTitleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
1169 const rtl::OUString& rLocalName,
1170 rtl::OUString& rTitle,
1171 uno::Reference< drawing::XShape >& xTitleShape ) :
1172 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
1173 mrImportHelper( rImpHelper ),
1174 mrTitle( rTitle ),
1175 mxTitleShape( xTitleShape )
1176 {
1177 }
1178
~SchXMLTitleContext()1179 SchXMLTitleContext::~SchXMLTitleContext()
1180 {}
1181
StartElement(const uno::Reference<xml::sax::XAttributeList> & xAttrList)1182 void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1183 {
1184 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
1185
1186 com::sun::star::awt::Point maPosition;
1187 bool bHasXPosition=false;
1188 bool bHasYPosition=false;
1189
1190 for( sal_Int16 i = 0; i < nAttrCount; i++ )
1191 {
1192 rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
1193 rtl::OUString aLocalName;
1194 rtl::OUString aValue = xAttrList->getValueByIndex( i );
1195 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
1196
1197 if( nPrefix == XML_NAMESPACE_SVG )
1198 {
1199 if( IsXMLToken( aLocalName, XML_X ) )
1200 {
1201 GetImport().GetMM100UnitConverter().convertMeasure( maPosition.X, aValue );
1202 bHasXPosition = true;
1203 }
1204 else if( IsXMLToken( aLocalName, XML_Y ) )
1205 {
1206 GetImport().GetMM100UnitConverter().convertMeasure( maPosition.Y, aValue );
1207 bHasYPosition = true;
1208 }
1209 }
1210 else if( nPrefix == XML_NAMESPACE_CHART )
1211 {
1212 if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
1213 msAutoStyleName = aValue;
1214 }
1215 }
1216
1217
1218 if( mxTitleShape.is())
1219 {
1220 if( bHasXPosition && bHasYPosition )
1221 mxTitleShape->setPosition( maPosition );
1222
1223 uno::Reference< beans::XPropertySet > xProp( mxTitleShape, uno::UNO_QUERY );
1224 if( xProp.is())
1225 {
1226 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
1227 if( pStylesCtxt )
1228 {
1229 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
1230 mrImportHelper.GetChartFamilyID(), msAutoStyleName );
1231
1232 if( pStyle && pStyle->ISA( XMLPropStyleContext ))
1233 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
1234 }
1235 }
1236 }
1237 }
1238
CreateChildContext(sal_uInt16 nPrefix,const rtl::OUString & rLocalName,const uno::Reference<xml::sax::XAttributeList> &)1239 SvXMLImportContext* SchXMLTitleContext::CreateChildContext(
1240 sal_uInt16 nPrefix,
1241 const rtl::OUString& rLocalName,
1242 const uno::Reference< xml::sax::XAttributeList >& )
1243 {
1244 SvXMLImportContext* pContext = 0;
1245
1246 if( nPrefix == XML_NAMESPACE_TEXT &&
1247 IsXMLToken( rLocalName, XML_P ) )
1248 {
1249 pContext = new SchXMLParagraphContext( GetImport(), rLocalName, mrTitle );
1250 }
1251 else
1252 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1253
1254 return pContext;
1255 }
1256
1257 // ----------------------------------------
1258