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