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 "xechart.hxx"
22 :
23 : #include <com/sun/star/i18n/XBreakIterator.hpp>
24 : #include <com/sun/star/i18n/ScriptType.hpp>
25 : #include <com/sun/star/drawing/FillStyle.hpp>
26 : #include <com/sun/star/drawing/XShapes.hpp>
27 : #include <com/sun/star/chart/XChartDocument.hpp>
28 : #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
29 : #include <com/sun/star/chart/ChartAxisPosition.hpp>
30 : #include <com/sun/star/chart/ChartLegendExpansion.hpp>
31 : #include <com/sun/star/chart/DataLabelPlacement.hpp>
32 : #include <com/sun/star/chart/ErrorBarStyle.hpp>
33 : #include <com/sun/star/chart/MissingValueTreatment.hpp>
34 : #include <com/sun/star/chart/TimeInterval.hpp>
35 : #include <com/sun/star/chart/TimeUnit.hpp>
36 : #include <com/sun/star/chart/XAxisSupplier.hpp>
37 : #include <com/sun/star/chart/XDiagramPositioning.hpp>
38 : #include <com/sun/star/chart2/XChartDocument.hpp>
39 : #include <com/sun/star/chart2/XDiagram.hpp>
40 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
41 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
42 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
43 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
44 : #include <com/sun/star/chart2/XTitled.hpp>
45 : #include <com/sun/star/chart2/XColorScheme.hpp>
46 : #include <com/sun/star/chart2/data/XDataSource.hpp>
47 : #include <com/sun/star/chart2/AxisType.hpp>
48 : #include <com/sun/star/chart2/CurveStyle.hpp>
49 : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
50 : #include <com/sun/star/chart2/DataPointLabel.hpp>
51 : #include <com/sun/star/chart2/LegendPosition.hpp>
52 : #include <com/sun/star/chart2/RelativePosition.hpp>
53 : #include <com/sun/star/chart2/RelativeSize.hpp>
54 : #include <com/sun/star/chart2/StackingDirection.hpp>
55 : #include <com/sun/star/chart2/TickmarkStyle.hpp>
56 :
57 : #include <tools/gen.hxx>
58 : #include <vcl/outdev.hxx>
59 : #include <filter/msfilter/escherex.hxx>
60 :
61 : #include "document.hxx"
62 : #include "rangelst.hxx"
63 : #include "rangeutl.hxx"
64 : #include "compiler.hxx"
65 : #include "tokenarray.hxx"
66 : #include "token.hxx"
67 : #include "xeescher.hxx"
68 : #include "xeformula.hxx"
69 : #include "xehelper.hxx"
70 : #include "xepage.hxx"
71 : #include "xestyle.hxx"
72 :
73 : #include <boost/scoped_ptr.hpp>
74 :
75 : using ::com::sun::star::uno::Any;
76 : using ::com::sun::star::uno::Reference;
77 : using ::com::sun::star::uno::Sequence;
78 : using ::com::sun::star::uno::UNO_QUERY;
79 : using ::com::sun::star::uno::UNO_QUERY_THROW;
80 : using ::com::sun::star::uno::UNO_SET_THROW;
81 : using ::com::sun::star::uno::Exception;
82 : using ::com::sun::star::beans::XPropertySet;
83 : using ::com::sun::star::i18n::XBreakIterator;
84 : using ::com::sun::star::frame::XModel;
85 : using ::com::sun::star::drawing::XShape;
86 : using ::com::sun::star::drawing::XShapes;
87 :
88 : using ::com::sun::star::chart2::IncrementData;
89 : using ::com::sun::star::chart2::RelativePosition;
90 : using ::com::sun::star::chart2::RelativeSize;
91 : using ::com::sun::star::chart2::ScaleData;
92 : using ::com::sun::star::chart2::SubIncrement;
93 : using ::com::sun::star::chart2::XAxis;
94 : using ::com::sun::star::chart2::XChartDocument;
95 : using ::com::sun::star::chart2::XChartTypeContainer;
96 : using ::com::sun::star::chart2::XColorScheme;
97 : using ::com::sun::star::chart2::XCoordinateSystem;
98 : using ::com::sun::star::chart2::XCoordinateSystemContainer;
99 : using ::com::sun::star::chart2::XChartType;
100 : using ::com::sun::star::chart2::XDataSeries;
101 : using ::com::sun::star::chart2::XDataSeriesContainer;
102 : using ::com::sun::star::chart2::XDiagram;
103 : using ::com::sun::star::chart2::XFormattedString;
104 : using ::com::sun::star::chart2::XLegend;
105 : using ::com::sun::star::chart2::XRegressionCurve;
106 : using ::com::sun::star::chart2::XRegressionCurveContainer;
107 : using ::com::sun::star::chart2::XScaling;
108 : using ::com::sun::star::chart2::XTitle;
109 : using ::com::sun::star::chart2::XTitled;
110 :
111 : using ::com::sun::star::chart2::data::XDataSequence;
112 : using ::com::sun::star::chart2::data::XDataSource;
113 : using ::com::sun::star::chart2::data::XLabeledDataSequence;
114 :
115 : using ::formula::FormulaGrammar;
116 : using ::formula::FormulaToken;
117 :
118 : namespace cssc = ::com::sun::star::chart;
119 : namespace cssc2 = ::com::sun::star::chart2;
120 :
121 : // Helpers ====================================================================
122 :
123 : namespace {
124 :
125 0 : XclExpStream& operator<<( XclExpStream& rStrm, const XclChRectangle& rRect )
126 : {
127 0 : return rStrm << rRect.mnX << rRect.mnY << rRect.mnWidth << rRect.mnHeight;
128 : }
129 :
130 0 : inline void lclSaveRecord( XclExpStream& rStrm, XclExpRecordRef xRec )
131 : {
132 0 : if( xRec )
133 0 : xRec->Save( rStrm );
134 0 : }
135 :
136 : /** Saves the passed record (group) together with a leading value record. */
137 : template< typename Type >
138 0 : void lclSaveRecord( XclExpStream& rStrm, XclExpRecordRef xRec, sal_uInt16 nRecId, Type nValue )
139 : {
140 0 : if( xRec )
141 : {
142 0 : XclExpValueRecord< Type >( nRecId, nValue ).Save( rStrm );
143 0 : xRec->Save( rStrm );
144 : }
145 0 : }
146 :
147 : template<typename ValueType, typename KeyType>
148 0 : void lclSaveRecord(XclExpStream& rStrm, ValueType* pRec, sal_uInt16 nRecId, KeyType nValue)
149 : {
150 0 : if (pRec)
151 : {
152 0 : XclExpValueRecord<KeyType>(nRecId, nValue).Save(rStrm);
153 0 : pRec->Save(rStrm);
154 : }
155 0 : }
156 :
157 0 : void lclWriteChFrBlockRecord( XclExpStream& rStrm, const XclChFrBlock& rFrBlock, bool bBegin )
158 : {
159 0 : sal_uInt16 nRecId = bBegin ? EXC_ID_CHFRBLOCKBEGIN : EXC_ID_CHFRBLOCKEND;
160 0 : rStrm.StartRecord( nRecId, 12 );
161 0 : rStrm << nRecId << EXC_FUTUREREC_EMPTYFLAGS << rFrBlock.mnType << rFrBlock.mnContext << rFrBlock.mnValue1 << rFrBlock.mnValue2;
162 0 : rStrm.EndRecord();
163 0 : }
164 :
165 : template< typename Type >
166 0 : inline bool lclIsAutoAnyOrGetValue( Type& rValue, const Any& rAny )
167 : {
168 0 : return !rAny.hasValue() || !(rAny >>= rValue);
169 : }
170 :
171 0 : bool lclIsAutoAnyOrGetScaledValue( double& rfValue, const Any& rAny, bool bLogScale )
172 : {
173 0 : bool bIsAuto = lclIsAutoAnyOrGetValue( rfValue, rAny );
174 0 : if( !bIsAuto && bLogScale )
175 0 : rfValue = log( rfValue ) / log( 10.0 );
176 0 : return bIsAuto;
177 : }
178 :
179 0 : sal_uInt16 lclGetTimeValue( const XclExpRoot& rRoot, double fSerialDate, sal_uInt16 nTimeUnit )
180 : {
181 0 : DateTime aDateTime = rRoot.GetDateTimeFromDouble( fSerialDate );
182 0 : switch( nTimeUnit )
183 : {
184 : case EXC_CHDATERANGE_DAYS:
185 0 : return ::limit_cast< sal_uInt16, double >( fSerialDate, 0, SAL_MAX_UINT16 );
186 : case EXC_CHDATERANGE_MONTHS:
187 0 : return ::limit_cast< sal_uInt16, sal_uInt16 >( 12 * (aDateTime.GetYear() - rRoot.GetBaseYear()) + aDateTime.GetMonth() - 1, 0, SAL_MAX_INT16 );
188 : case EXC_CHDATERANGE_YEARS:
189 0 : return ::limit_cast< sal_uInt16, sal_uInt16 >( aDateTime.GetYear() - rRoot.GetBaseYear(), 0, SAL_MAX_INT16 );
190 : default:
191 : OSL_ENSURE( false, "lclGetTimeValue - unexpected time unit" );
192 : }
193 0 : return ::limit_cast< sal_uInt16, double >( fSerialDate, 0, SAL_MAX_UINT16 );
194 : }
195 :
196 0 : bool lclConvertTimeValue( const XclExpRoot& rRoot, sal_uInt16& rnValue, const Any& rAny, sal_uInt16 nTimeUnit )
197 : {
198 0 : double fSerialDate = 0;
199 0 : bool bAuto = lclIsAutoAnyOrGetValue( fSerialDate, rAny );
200 0 : if( !bAuto )
201 0 : rnValue = lclGetTimeValue( rRoot, fSerialDate, nTimeUnit );
202 0 : return bAuto;
203 : }
204 :
205 0 : sal_uInt16 lclGetTimeUnit( sal_Int32 nApiTimeUnit )
206 : {
207 0 : switch( nApiTimeUnit )
208 : {
209 0 : case cssc::TimeUnit::DAY: return EXC_CHDATERANGE_DAYS;
210 0 : case cssc::TimeUnit::MONTH: return EXC_CHDATERANGE_MONTHS;
211 0 : case cssc::TimeUnit::YEAR: return EXC_CHDATERANGE_YEARS;
212 : default: OSL_ENSURE( false, "lclGetTimeUnit - unexpected time unit" );
213 : }
214 0 : return EXC_CHDATERANGE_DAYS;
215 : }
216 :
217 0 : bool lclConvertTimeInterval( sal_uInt16& rnValue, sal_uInt16& rnTimeUnit, const Any& rAny )
218 : {
219 0 : cssc::TimeInterval aInterval;
220 0 : bool bAuto = lclIsAutoAnyOrGetValue( aInterval, rAny );
221 0 : if( !bAuto )
222 : {
223 0 : rnValue = ::limit_cast< sal_uInt16, sal_Int32 >( aInterval.Number, 1, SAL_MAX_UINT16 );
224 0 : rnTimeUnit = lclGetTimeUnit( aInterval.TimeUnit );
225 : }
226 0 : return bAuto;
227 : }
228 :
229 : } // namespace
230 :
231 : // Common =====================================================================
232 :
233 : /** Stores global data needed in various classes of the Chart export filter. */
234 0 : struct XclExpChRootData : public XclChRootData
235 : {
236 : typedef ::std::vector< XclChFrBlock > XclChFrBlockVector;
237 :
238 : XclExpChChart& mrChartData; /// The chart data object.
239 : XclChFrBlockVector maWrittenFrBlocks; /// Stack of future record levels already written out.
240 : XclChFrBlockVector maUnwrittenFrBlocks; /// Stack of future record levels not yet written out.
241 :
242 0 : inline explicit XclExpChRootData( XclExpChChart& rChartData ) : mrChartData( rChartData ) {}
243 :
244 : /** Registers a new future record level. */
245 : void RegisterFutureRecBlock( const XclChFrBlock& rFrBlock );
246 : /** Initializes the current future record level (writes all unwritten CHFRBLOCKBEGIN records). */
247 : void InitializeFutureRecBlock( XclExpStream& rStrm );
248 : /** Finalizes the current future record level (writes CHFRBLOCKEND record if needed). */
249 : void FinalizeFutureRecBlock( XclExpStream& rStrm );
250 : };
251 :
252 0 : void XclExpChRootData::RegisterFutureRecBlock( const XclChFrBlock& rFrBlock )
253 : {
254 0 : maUnwrittenFrBlocks.push_back( rFrBlock );
255 0 : }
256 :
257 0 : void XclExpChRootData::InitializeFutureRecBlock( XclExpStream& rStrm )
258 : {
259 : // first call from a future record writes all missing CHFRBLOCKBEGIN records
260 0 : if( !maUnwrittenFrBlocks.empty() )
261 : {
262 : // write the leading CHFRINFO record
263 0 : if( maWrittenFrBlocks.empty() )
264 : {
265 0 : rStrm.StartRecord( EXC_ID_CHFRINFO, 20 );
266 0 : rStrm << EXC_ID_CHFRINFO << EXC_FUTUREREC_EMPTYFLAGS << EXC_CHFRINFO_EXCELXP2003 << EXC_CHFRINFO_EXCELXP2003 << sal_uInt16( 3 );
267 0 : rStrm << sal_uInt16( 0x0850 ) << sal_uInt16( 0x085A ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x0861 ) << sal_uInt16( 0x086A ) << sal_uInt16( 0x086B );
268 0 : rStrm.EndRecord();
269 : }
270 : // write all unwritten CHFRBLOCKBEGIN records
271 0 : for( XclChFrBlockVector::const_iterator aIt = maUnwrittenFrBlocks.begin(), aEnd = maUnwrittenFrBlocks.end(); aIt != aEnd; ++aIt )
272 : {
273 : OSL_ENSURE( aIt->mnType != EXC_CHFRBLOCK_TYPE_UNKNOWN, "XclExpChRootData::InitializeFutureRecBlock - unknown future record block type" );
274 0 : lclWriteChFrBlockRecord( rStrm, *aIt, true );
275 : }
276 : // move all record infos to vector of written blocks
277 0 : maWrittenFrBlocks.insert( maWrittenFrBlocks.end(), maUnwrittenFrBlocks.begin(), maUnwrittenFrBlocks.end() );
278 0 : maUnwrittenFrBlocks.clear();
279 : }
280 0 : }
281 :
282 0 : void XclExpChRootData::FinalizeFutureRecBlock( XclExpStream& rStrm )
283 : {
284 : OSL_ENSURE( !maUnwrittenFrBlocks.empty() || !maWrittenFrBlocks.empty(), "XclExpChRootData::FinalizeFutureRecBlock - no future record level found" );
285 0 : if( !maUnwrittenFrBlocks.empty() )
286 : {
287 : // no future record has been written, just forget the topmost level
288 0 : maUnwrittenFrBlocks.pop_back();
289 : }
290 0 : else if( !maWrittenFrBlocks.empty() )
291 : {
292 : // write the CHFRBLOCKEND record for the topmost block and delete it
293 0 : lclWriteChFrBlockRecord( rStrm, maWrittenFrBlocks.back(), false );
294 0 : maWrittenFrBlocks.pop_back();
295 : }
296 0 : }
297 :
298 0 : XclExpChRoot::XclExpChRoot( const XclExpRoot& rRoot, XclExpChChart& rChartData ) :
299 : XclExpRoot( rRoot ),
300 0 : mxChData( new XclExpChRootData( rChartData ) )
301 : {
302 0 : }
303 :
304 0 : XclExpChRoot::~XclExpChRoot()
305 : {
306 0 : }
307 :
308 0 : Reference< XChartDocument > XclExpChRoot::GetChartDocument() const
309 : {
310 0 : return mxChData->mxChartDoc;
311 : }
312 :
313 0 : XclExpChChart& XclExpChRoot::GetChartData() const
314 : {
315 0 : return mxChData->mrChartData;
316 : }
317 :
318 0 : const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
319 : {
320 0 : return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
321 : }
322 :
323 0 : const XclChTypeInfo& XclExpChRoot::GetChartTypeInfo( const OUString& rServiceName ) const
324 : {
325 0 : return mxChData->mxTypeInfoProv->GetTypeInfoFromService( rServiceName );
326 : }
327 :
328 0 : const XclChFormatInfo& XclExpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
329 : {
330 0 : return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
331 : }
332 :
333 0 : void XclExpChRoot::InitConversion( XChartDocRef xChartDoc, const Rectangle& rChartRect ) const
334 : {
335 0 : mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
336 0 : }
337 :
338 0 : void XclExpChRoot::FinishConversion() const
339 : {
340 0 : mxChData->FinishConversion();
341 0 : }
342 :
343 0 : bool XclExpChRoot::IsSystemColor( const Color& rColor, sal_uInt16 nSysColorIdx ) const
344 : {
345 0 : XclExpPalette& rPal = GetPalette();
346 0 : return rPal.IsSystemColor( nSysColorIdx ) && (rColor == rPal.GetDefColor( nSysColorIdx ));
347 : }
348 :
349 0 : void XclExpChRoot::SetSystemColor( Color& rColor, sal_uInt32& rnColorId, sal_uInt16 nSysColorIdx ) const
350 : {
351 : OSL_ENSURE( GetPalette().IsSystemColor( nSysColorIdx ), "XclExpChRoot::SetSystemColor - invalid color index" );
352 0 : rColor = GetPalette().GetDefColor( nSysColorIdx );
353 0 : rnColorId = XclExpPalette::GetColorIdFromIndex( nSysColorIdx );
354 0 : }
355 :
356 0 : sal_Int32 XclExpChRoot::CalcChartXFromHmm( sal_Int32 nPosX ) const
357 : {
358 0 : return ::limit_cast< sal_Int32, double >( (nPosX - mxChData->mnBorderGapX) / mxChData->mfUnitSizeX, 0, EXC_CHART_TOTALUNITS );
359 : }
360 :
361 0 : sal_Int32 XclExpChRoot::CalcChartYFromHmm( sal_Int32 nPosY ) const
362 : {
363 0 : return ::limit_cast< sal_Int32, double >( (nPosY - mxChData->mnBorderGapY) / mxChData->mfUnitSizeY, 0, EXC_CHART_TOTALUNITS );
364 : }
365 :
366 0 : XclChRectangle XclExpChRoot::CalcChartRectFromHmm( const ::com::sun::star::awt::Rectangle& rRect ) const
367 : {
368 0 : XclChRectangle aRect;
369 0 : aRect.mnX = CalcChartXFromHmm( rRect.X );
370 0 : aRect.mnY = CalcChartYFromHmm( rRect.Y );
371 0 : aRect.mnWidth = CalcChartXFromHmm( rRect.Width );
372 0 : aRect.mnHeight = CalcChartYFromHmm( rRect.Height );
373 0 : return aRect;
374 : }
375 :
376 0 : void XclExpChRoot::ConvertLineFormat( XclChLineFormat& rLineFmt,
377 : const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const
378 : {
379 0 : GetChartPropSetHelper().ReadLineProperties(
380 0 : rLineFmt, *mxChData->mxLineDashTable, rPropSet, ePropMode );
381 0 : }
382 :
383 0 : bool XclExpChRoot::ConvertAreaFormat( XclChAreaFormat& rAreaFmt,
384 : const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const
385 : {
386 0 : return GetChartPropSetHelper().ReadAreaProperties( rAreaFmt, rPropSet, ePropMode );
387 : }
388 :
389 0 : void XclExpChRoot::ConvertEscherFormat(
390 : XclChEscherFormat& rEscherFmt, XclChPicFormat& rPicFmt,
391 : const ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const
392 : {
393 0 : GetChartPropSetHelper().ReadEscherProperties( rEscherFmt, rPicFmt,
394 0 : *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable, rPropSet, ePropMode );
395 0 : }
396 :
397 0 : sal_uInt16 XclExpChRoot::ConvertFont( const ScfPropertySet& rPropSet, sal_Int16 nScript ) const
398 : {
399 0 : XclFontData aFontData;
400 0 : GetFontPropSetHelper().ReadFontProperties( aFontData, rPropSet, EXC_FONTPROPSET_CHART, nScript );
401 0 : return GetFontBuffer().Insert( aFontData, EXC_COLOR_CHARTTEXT );
402 : }
403 :
404 0 : sal_uInt16 XclExpChRoot::ConvertPieRotation( const ScfPropertySet& rPropSet )
405 : {
406 0 : sal_Int32 nApiRot = 0;
407 0 : rPropSet.GetProperty( nApiRot, EXC_CHPROP_STARTINGANGLE );
408 0 : return static_cast< sal_uInt16 >( (450 - (nApiRot % 360)) % 360 );
409 : }
410 :
411 0 : void XclExpChRoot::RegisterFutureRecBlock( const XclChFrBlock& rFrBlock )
412 : {
413 0 : mxChData->RegisterFutureRecBlock( rFrBlock );
414 0 : }
415 :
416 0 : void XclExpChRoot::InitializeFutureRecBlock( XclExpStream& rStrm )
417 : {
418 0 : mxChData->InitializeFutureRecBlock( rStrm );
419 0 : }
420 :
421 0 : void XclExpChRoot::FinalizeFutureRecBlock( XclExpStream& rStrm )
422 : {
423 0 : mxChData->FinalizeFutureRecBlock( rStrm );
424 0 : }
425 :
426 0 : XclExpChGroupBase::XclExpChGroupBase( const XclExpChRoot& rRoot,
427 : sal_uInt16 nFrType, sal_uInt16 nRecId, sal_Size nRecSize ) :
428 : XclExpRecord( nRecId, nRecSize ),
429 : XclExpChRoot( rRoot ),
430 0 : maFrBlock( nFrType )
431 : {
432 0 : }
433 :
434 0 : XclExpChGroupBase::~XclExpChGroupBase()
435 : {
436 0 : }
437 :
438 0 : void XclExpChGroupBase::Save( XclExpStream& rStrm )
439 : {
440 : // header record
441 0 : XclExpRecord::Save( rStrm );
442 : // group records
443 0 : if( HasSubRecords() )
444 : {
445 : // register the future record context corresponding to this record group
446 0 : RegisterFutureRecBlock( maFrBlock );
447 : // CHBEGIN record
448 0 : XclExpEmptyRecord( EXC_ID_CHBEGIN ).Save( rStrm );
449 : // embedded records
450 0 : WriteSubRecords( rStrm );
451 : // finalize the future records, must be done before the closing CHEND
452 0 : FinalizeFutureRecBlock( rStrm );
453 : // CHEND record
454 0 : XclExpEmptyRecord( EXC_ID_CHEND ).Save( rStrm );
455 : }
456 0 : }
457 :
458 0 : bool XclExpChGroupBase::HasSubRecords() const
459 : {
460 0 : return true;
461 : }
462 :
463 0 : void XclExpChGroupBase::SetFutureRecordContext( sal_uInt16 nFrContext, sal_uInt16 nFrValue1, sal_uInt16 nFrValue2 )
464 : {
465 0 : maFrBlock.mnContext = nFrContext;
466 0 : maFrBlock.mnValue1 = nFrValue1;
467 0 : maFrBlock.mnValue2 = nFrValue2;
468 0 : }
469 :
470 0 : XclExpChFutureRecordBase::XclExpChFutureRecordBase( const XclExpChRoot& rRoot,
471 : XclFutureRecType eRecType, sal_uInt16 nRecId, sal_Size nRecSize ) :
472 : XclExpFutureRecord( eRecType, nRecId, nRecSize ),
473 0 : XclExpChRoot( rRoot )
474 : {
475 0 : }
476 :
477 0 : void XclExpChFutureRecordBase::Save( XclExpStream& rStrm )
478 : {
479 0 : InitializeFutureRecBlock( rStrm );
480 0 : XclExpFutureRecord::Save( rStrm );
481 0 : }
482 :
483 : // Frame formatting ===========================================================
484 :
485 0 : XclExpChFramePos::XclExpChFramePos( sal_uInt16 nTLMode, sal_uInt16 nBRMode ) :
486 0 : XclExpRecord( EXC_ID_CHFRAMEPOS, 20 )
487 : {
488 0 : maData.mnTLMode = nTLMode;
489 0 : maData.mnBRMode = nBRMode;
490 0 : }
491 :
492 0 : void XclExpChFramePos::WriteBody( XclExpStream& rStrm )
493 : {
494 0 : rStrm << maData.mnTLMode << maData.mnBRMode << maData.maRect;
495 0 : }
496 :
497 0 : XclExpChLineFormat::XclExpChLineFormat( const XclExpChRoot& rRoot ) :
498 0 : XclExpRecord( EXC_ID_CHLINEFORMAT, (rRoot.GetBiff() == EXC_BIFF8) ? 12 : 10 ),
499 0 : mnColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) )
500 : {
501 0 : }
502 :
503 0 : void XclExpChLineFormat::SetDefault( XclChFrameType eDefFrameType )
504 : {
505 0 : switch( eDefFrameType )
506 : {
507 : case EXC_CHFRAMETYPE_AUTO:
508 0 : SetAuto( true );
509 0 : break;
510 : case EXC_CHFRAMETYPE_INVISIBLE:
511 0 : SetAuto( false );
512 0 : maData.mnPattern = EXC_CHLINEFORMAT_NONE;
513 0 : break;
514 : default:
515 : OSL_FAIL( "XclExpChLineFormat::SetDefault - unknown frame type" );
516 : }
517 0 : }
518 :
519 0 : void XclExpChLineFormat::Convert( const XclExpChRoot& rRoot,
520 : const ScfPropertySet& rPropSet, XclChObjectType eObjType )
521 : {
522 0 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
523 0 : rRoot.ConvertLineFormat( maData, rPropSet, rFmtInfo.mePropMode );
524 0 : if( HasLine() )
525 : {
526 : // detect system color, set color identifier (TODO: detect automatic series line)
527 0 : if( (eObjType != EXC_CHOBJTYPE_LINEARSERIES) && rRoot.IsSystemColor( maData.maColor, rFmtInfo.mnAutoLineColorIdx ) )
528 : {
529 : // store color index from automatic format data
530 0 : mnColorId = XclExpPalette::GetColorIdFromIndex( rFmtInfo.mnAutoLineColorIdx );
531 : // try to set automatic mode
532 0 : bool bAuto = (maData.mnPattern == EXC_CHLINEFORMAT_SOLID) && (maData.mnWeight == rFmtInfo.mnAutoLineWeight);
533 0 : ::set_flag( maData.mnFlags, EXC_CHLINEFORMAT_AUTO, bAuto );
534 : }
535 : else
536 : {
537 : // user defined color - register in palette
538 0 : mnColorId = rRoot.GetPalette().InsertColor( maData.maColor, EXC_COLOR_CHARTLINE );
539 : }
540 : }
541 : else
542 : {
543 : // no line - set default system color
544 0 : rRoot.SetSystemColor( maData.maColor, mnColorId, EXC_COLOR_CHWINDOWTEXT );
545 : }
546 0 : }
547 :
548 0 : bool XclExpChLineFormat::IsDefault( XclChFrameType eDefFrameType ) const
549 : {
550 : return
551 0 : ((eDefFrameType == EXC_CHFRAMETYPE_INVISIBLE) && !HasLine()) ||
552 0 : ((eDefFrameType == EXC_CHFRAMETYPE_AUTO) && IsAuto());
553 : }
554 :
555 0 : void XclExpChLineFormat::WriteBody( XclExpStream& rStrm )
556 : {
557 0 : rStrm << maData.maColor << maData.mnPattern << maData.mnWeight << maData.mnFlags;
558 0 : if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
559 0 : rStrm << rStrm.GetRoot().GetPalette().GetColorIndex( mnColorId );
560 0 : }
561 :
562 : namespace {
563 :
564 : /** Creates a CHLINEFORMAT record from the passed property set. */
565 0 : XclExpChLineFormatRef lclCreateLineFormat( const XclExpChRoot& rRoot,
566 : const ScfPropertySet& rPropSet, XclChObjectType eObjType )
567 : {
568 0 : XclExpChLineFormatRef xLineFmt( new XclExpChLineFormat( rRoot ) );
569 0 : xLineFmt->Convert( rRoot, rPropSet, eObjType );
570 0 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
571 0 : if( rFmtInfo.mbDeleteDefFrame && xLineFmt->IsDefault( rFmtInfo.meDefFrameType ) )
572 0 : xLineFmt.reset();
573 0 : return xLineFmt;
574 : }
575 :
576 : } // namespace
577 :
578 0 : XclExpChAreaFormat::XclExpChAreaFormat( const XclExpChRoot& rRoot ) :
579 0 : XclExpRecord( EXC_ID_CHAREAFORMAT, (rRoot.GetBiff() == EXC_BIFF8) ? 16 : 12 ),
580 0 : mnPattColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK ) ),
581 0 : mnBackColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) )
582 : {
583 0 : }
584 :
585 0 : bool XclExpChAreaFormat::Convert( const XclExpChRoot& rRoot,
586 : const ScfPropertySet& rPropSet, XclChObjectType eObjType )
587 : {
588 0 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
589 0 : bool bComplexFill = rRoot.ConvertAreaFormat( maData, rPropSet, rFmtInfo.mePropMode );
590 0 : if( HasArea() )
591 : {
592 0 : bool bSolid = maData.mnPattern == EXC_PATT_SOLID;
593 : // detect system color, set color identifier (TODO: detect automatic series area)
594 0 : if( (eObjType != EXC_CHOBJTYPE_FILLEDSERIES) && rRoot.IsSystemColor( maData.maPattColor, rFmtInfo.mnAutoPattColorIdx ) )
595 : {
596 : // store color index from automatic format data
597 0 : mnPattColorId = XclExpPalette::GetColorIdFromIndex( rFmtInfo.mnAutoPattColorIdx );
598 : // set automatic mode
599 0 : ::set_flag( maData.mnFlags, EXC_CHAREAFORMAT_AUTO, bSolid );
600 : }
601 : else
602 : {
603 : // user defined color - register color in palette
604 0 : mnPattColorId = rRoot.GetPalette().InsertColor( maData.maPattColor, EXC_COLOR_CHARTAREA );
605 : }
606 : // background color (default system color for solid fills)
607 0 : if( bSolid )
608 0 : rRoot.SetSystemColor( maData.maBackColor, mnBackColorId, EXC_COLOR_CHWINDOWTEXT );
609 : else
610 0 : mnBackColorId = rRoot.GetPalette().InsertColor( maData.maBackColor, EXC_COLOR_CHARTAREA );
611 : }
612 : else
613 : {
614 : // no area - set default system colors
615 0 : rRoot.SetSystemColor( maData.maPattColor, mnPattColorId, EXC_COLOR_CHWINDOWBACK );
616 0 : rRoot.SetSystemColor( maData.maBackColor, mnBackColorId, EXC_COLOR_CHWINDOWTEXT );
617 : }
618 0 : return bComplexFill;
619 : }
620 :
621 0 : void XclExpChAreaFormat::SetDefault( XclChFrameType eDefFrameType )
622 : {
623 0 : switch( eDefFrameType )
624 : {
625 : case EXC_CHFRAMETYPE_AUTO:
626 0 : SetAuto( true );
627 0 : break;
628 : case EXC_CHFRAMETYPE_INVISIBLE:
629 0 : SetAuto( false );
630 0 : maData.mnPattern = EXC_PATT_NONE;
631 0 : break;
632 : default:
633 : OSL_FAIL( "XclExpChAreaFormat::SetDefault - unknown frame type" );
634 : }
635 0 : }
636 :
637 0 : bool XclExpChAreaFormat::IsDefault( XclChFrameType eDefFrameType ) const
638 : {
639 : return
640 0 : ((eDefFrameType == EXC_CHFRAMETYPE_INVISIBLE) && !HasArea()) ||
641 0 : ((eDefFrameType == EXC_CHFRAMETYPE_AUTO) && IsAuto());
642 : }
643 :
644 0 : void XclExpChAreaFormat::WriteBody( XclExpStream& rStrm )
645 : {
646 0 : rStrm << maData.maPattColor << maData.maBackColor << maData.mnPattern << maData.mnFlags;
647 0 : if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
648 : {
649 0 : const XclExpPalette& rPal = rStrm.GetRoot().GetPalette();
650 0 : rStrm << rPal.GetColorIndex( mnPattColorId ) << rPal.GetColorIndex( mnBackColorId );
651 : }
652 0 : }
653 :
654 0 : XclExpChEscherFormat::XclExpChEscherFormat( const XclExpChRoot& rRoot ) :
655 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_UNKNOWN, EXC_ID_CHESCHERFORMAT ),
656 0 : mnColor1Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK ) ),
657 0 : mnColor2Id( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK ) )
658 : {
659 : OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
660 0 : }
661 :
662 0 : void XclExpChEscherFormat::Convert( const ScfPropertySet& rPropSet, XclChObjectType eObjType )
663 : {
664 0 : const XclChFormatInfo& rFmtInfo = GetFormatInfo( eObjType );
665 0 : ConvertEscherFormat( maData, maPicFmt, rPropSet, rFmtInfo.mePropMode );
666 : // register colors in palette
667 0 : mnColor1Id = RegisterColor( ESCHER_Prop_fillColor );
668 0 : mnColor2Id = RegisterColor( ESCHER_Prop_fillBackColor );
669 0 : }
670 :
671 0 : bool XclExpChEscherFormat::IsValid() const
672 : {
673 0 : return static_cast< bool >(maData.mxEscherSet);
674 : }
675 :
676 0 : void XclExpChEscherFormat::Save( XclExpStream& rStrm )
677 : {
678 0 : if( maData.mxEscherSet )
679 : {
680 : // replace RGB colors with palette indexes in the Escher container
681 0 : const XclExpPalette& rPal = GetPalette();
682 0 : maData.mxEscherSet->AddOpt( ESCHER_Prop_fillColor, 0x08000000 | rPal.GetColorIndex( mnColor1Id ) );
683 0 : maData.mxEscherSet->AddOpt( ESCHER_Prop_fillBackColor, 0x08000000 | rPal.GetColorIndex( mnColor2Id ) );
684 :
685 : // save the record group
686 0 : XclExpChGroupBase::Save( rStrm );
687 : }
688 0 : }
689 :
690 0 : bool XclExpChEscherFormat::HasSubRecords() const
691 : {
692 : // no subrecords for gradients
693 0 : return maPicFmt.mnBmpMode != EXC_CHPICFORMAT_NONE;
694 : }
695 :
696 0 : void XclExpChEscherFormat::WriteSubRecords( XclExpStream& rStrm )
697 : {
698 0 : rStrm.StartRecord( EXC_ID_CHPICFORMAT, 14 );
699 0 : rStrm << maPicFmt.mnBmpMode << sal_uInt16( 0 ) << maPicFmt.mnFlags << maPicFmt.mfScale;
700 0 : rStrm.EndRecord();
701 0 : }
702 :
703 0 : sal_uInt32 XclExpChEscherFormat::RegisterColor( sal_uInt16 nPropId )
704 : {
705 : sal_uInt32 nBGRValue;
706 0 : if( maData.mxEscherSet && maData.mxEscherSet->GetOpt( nPropId, nBGRValue ) )
707 : {
708 : // swap red and blue
709 0 : Color aColor( RGB_COLORDATA(
710 : COLORDATA_BLUE( nBGRValue ),
711 : COLORDATA_GREEN( nBGRValue ),
712 0 : COLORDATA_RED( nBGRValue ) ) );
713 0 : return GetPalette().InsertColor( aColor, EXC_COLOR_CHARTAREA );
714 : }
715 0 : return XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK );
716 : }
717 :
718 0 : void XclExpChEscherFormat::WriteBody( XclExpStream& rStrm )
719 : {
720 : OSL_ENSURE( maData.mxEscherSet, "XclExpChEscherFormat::WriteBody - missing property container" );
721 : // write Escher property container via temporary memory stream
722 0 : SvMemoryStream aMemStrm;
723 0 : maData.mxEscherSet->Commit( aMemStrm );
724 0 : aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
725 0 : rStrm.CopyFromStream( aMemStrm );
726 0 : }
727 :
728 0 : XclExpChFrameBase::XclExpChFrameBase()
729 : {
730 0 : }
731 :
732 0 : XclExpChFrameBase::~XclExpChFrameBase()
733 : {
734 0 : }
735 :
736 0 : void XclExpChFrameBase::ConvertFrameBase( const XclExpChRoot& rRoot,
737 : const ScfPropertySet& rPropSet, XclChObjectType eObjType )
738 : {
739 : // line format
740 0 : mxLineFmt.reset( new XclExpChLineFormat( rRoot ) );
741 0 : mxLineFmt->Convert( rRoot, rPropSet, eObjType );
742 : // area format (only for frame objects)
743 0 : if( rRoot.GetFormatInfo( eObjType ).mbIsFrame )
744 : {
745 0 : mxAreaFmt.reset( new XclExpChAreaFormat( rRoot ) );
746 0 : bool bComplexFill = mxAreaFmt->Convert( rRoot, rPropSet, eObjType );
747 0 : if( (rRoot.GetBiff() == EXC_BIFF8) && bComplexFill )
748 : {
749 0 : mxEscherFmt.reset( new XclExpChEscherFormat( rRoot ) );
750 0 : mxEscherFmt->Convert( rPropSet, eObjType );
751 0 : if( mxEscherFmt->IsValid() )
752 0 : mxAreaFmt->SetAuto( false );
753 : else
754 0 : mxEscherFmt.reset();
755 : }
756 : }
757 0 : }
758 :
759 0 : void XclExpChFrameBase::SetDefaultFrameBase( const XclExpChRoot& rRoot,
760 : XclChFrameType eDefFrameType, bool bIsFrame )
761 : {
762 : // line format
763 0 : mxLineFmt.reset( new XclExpChLineFormat( rRoot ) );
764 0 : mxLineFmt->SetDefault( eDefFrameType );
765 : // area format (only for frame objects)
766 0 : if( bIsFrame )
767 : {
768 0 : mxAreaFmt.reset( new XclExpChAreaFormat( rRoot ) );
769 0 : mxAreaFmt->SetDefault( eDefFrameType );
770 0 : mxEscherFmt.reset();
771 : }
772 0 : }
773 :
774 0 : bool XclExpChFrameBase::IsDefaultFrameBase( XclChFrameType eDefFrameType ) const
775 : {
776 : return
777 0 : (!mxLineFmt || mxLineFmt->IsDefault( eDefFrameType )) &&
778 0 : (!mxAreaFmt || mxAreaFmt->IsDefault( eDefFrameType ));
779 : }
780 :
781 0 : void XclExpChFrameBase::WriteFrameRecords( XclExpStream& rStrm )
782 : {
783 0 : lclSaveRecord( rStrm, mxLineFmt );
784 0 : lclSaveRecord( rStrm, mxAreaFmt );
785 0 : lclSaveRecord( rStrm, mxEscherFmt );
786 0 : }
787 :
788 0 : XclExpChFrame::XclExpChFrame( const XclExpChRoot& rRoot, XclChObjectType eObjType ) :
789 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_FRAME, EXC_ID_CHFRAME, 4 ),
790 0 : meObjType( eObjType )
791 : {
792 0 : }
793 :
794 0 : void XclExpChFrame::Convert( const ScfPropertySet& rPropSet )
795 : {
796 0 : ConvertFrameBase( GetChRoot(), rPropSet, meObjType );
797 0 : }
798 :
799 0 : void XclExpChFrame::SetAutoFlags( bool bAutoPos, bool bAutoSize )
800 : {
801 0 : ::set_flag( maData.mnFlags, EXC_CHFRAME_AUTOPOS, bAutoPos );
802 0 : ::set_flag( maData.mnFlags, EXC_CHFRAME_AUTOSIZE, bAutoSize );
803 0 : }
804 :
805 0 : bool XclExpChFrame::IsDefault() const
806 : {
807 0 : return IsDefaultFrameBase( GetFormatInfo( meObjType ).meDefFrameType );
808 : }
809 :
810 0 : bool XclExpChFrame::IsDeleteable() const
811 : {
812 0 : return IsDefault() && GetFormatInfo( meObjType ).mbDeleteDefFrame;
813 : }
814 :
815 0 : void XclExpChFrame::Save( XclExpStream& rStrm )
816 : {
817 0 : switch( meObjType )
818 : {
819 : // wall/floor frame without CHFRAME header record
820 : case EXC_CHOBJTYPE_WALL3D:
821 : case EXC_CHOBJTYPE_FLOOR3D:
822 0 : WriteFrameRecords( rStrm );
823 0 : break;
824 : default:
825 0 : XclExpChGroupBase::Save( rStrm );
826 : }
827 0 : }
828 :
829 0 : void XclExpChFrame::WriteSubRecords( XclExpStream& rStrm )
830 : {
831 0 : WriteFrameRecords( rStrm );
832 0 : }
833 :
834 0 : void XclExpChFrame::WriteBody( XclExpStream& rStrm )
835 : {
836 0 : rStrm << maData.mnFormat << maData.mnFlags;
837 0 : }
838 :
839 : namespace {
840 :
841 : /** Creates a CHFRAME record from the passed property set. */
842 0 : XclExpChFrameRef lclCreateFrame( const XclExpChRoot& rRoot,
843 : const ScfPropertySet& rPropSet, XclChObjectType eObjType )
844 : {
845 0 : XclExpChFrameRef xFrame( new XclExpChFrame( rRoot, eObjType ) );
846 0 : xFrame->Convert( rPropSet );
847 0 : if( xFrame->IsDeleteable() )
848 0 : xFrame.reset();
849 0 : return xFrame;
850 : }
851 :
852 : } // namespace
853 :
854 : // Source links ===============================================================
855 :
856 : namespace {
857 :
858 0 : void lclAddDoubleRefData(
859 : ScTokenArray& orArray, const FormulaToken& rToken,
860 : SCsTAB nScTab1, SCsCOL nScCol1, SCsROW nScRow1,
861 : SCsTAB nScTab2, SCsCOL nScCol2, SCsROW nScRow2 )
862 : {
863 : ScComplexRefData aComplexRef;
864 0 : aComplexRef.InitRange(ScRange(nScCol1,nScRow1,nScTab1,nScCol2,nScRow2,nScTab2));
865 0 : aComplexRef.Ref1.SetFlag3D( true );
866 :
867 0 : if( orArray.GetLen() > 0 )
868 0 : orArray.AddOpCode( ocUnion );
869 :
870 : OSL_ENSURE( (rToken.GetType() == ::formula::svDoubleRef) || (rToken.GetType() == ::formula::svExternalDoubleRef),
871 : "lclAddDoubleRefData - double reference token expected");
872 0 : if( rToken.GetType() == ::formula::svExternalDoubleRef )
873 : orArray.AddExternalDoubleReference(
874 0 : rToken.GetIndex(), rToken.GetString().getString(), aComplexRef);
875 : else
876 0 : orArray.AddDoubleReference( aComplexRef );
877 0 : }
878 :
879 : } // namespace
880 :
881 0 : XclExpChSourceLink::XclExpChSourceLink( const XclExpChRoot& rRoot, sal_uInt8 nDestType ) :
882 : XclExpRecord( EXC_ID_CHSOURCELINK ),
883 0 : XclExpChRoot( rRoot )
884 : {
885 0 : maData.mnDestType = nDestType;
886 0 : maData.mnLinkType = EXC_CHSRCLINK_DIRECTLY;
887 0 : }
888 :
889 0 : sal_uInt16 XclExpChSourceLink::ConvertDataSequence( Reference< XDataSequence > xDataSeq, bool bSplitToColumns, sal_uInt16 nDefCount )
890 : {
891 0 : mxLinkFmla.reset();
892 0 : maData.mnLinkType = EXC_CHSRCLINK_DEFAULT;
893 :
894 0 : if( !xDataSeq.is() )
895 0 : return nDefCount;
896 :
897 : // Compile the range representation string into token array. Note that the
898 : // source range text depends on the current grammar.
899 0 : OUString aRangeRepr = xDataSeq->getSourceRangeRepresentation();
900 0 : ScCompiler aComp( GetDocPtr(), ScAddress() );
901 0 : aComp.SetGrammar( GetDocPtr()->GetGrammar() );
902 0 : boost::scoped_ptr<ScTokenArray> pArray(aComp.CompileString(aRangeRepr));
903 0 : if( !pArray )
904 0 : return nDefCount;
905 :
906 0 : ScTokenArray aArray;
907 0 : sal_uInt32 nValueCount = 0;
908 0 : pArray->Reset();
909 0 : for( const FormulaToken* pToken = pArray->First(); pToken; pToken = pArray->Next() )
910 : {
911 0 : switch( pToken->GetType() )
912 : {
913 : case ::formula::svSingleRef:
914 : case ::formula::svExternalSingleRef:
915 : // for a single ref token, just add it to the new token array as is
916 0 : if( aArray.GetLen() > 0 )
917 0 : aArray.AddOpCode( ocUnion );
918 0 : aArray.AddToken( *pToken );
919 0 : ++nValueCount;
920 0 : break;
921 :
922 : case ::formula::svDoubleRef:
923 : case ::formula::svExternalDoubleRef:
924 : {
925 : // split 3-dimensional ranges into single sheets
926 0 : const ScComplexRefData& rComplexRef = static_cast< const ScToken* >( pToken )->GetDoubleRef();
927 0 : ScAddress aAbs1 = rComplexRef.Ref1.toAbs(ScAddress());
928 0 : ScAddress aAbs2 = rComplexRef.Ref2.toAbs(ScAddress());
929 0 : for (SCsTAB nScTab = aAbs1.Tab(); nScTab <= aAbs2.Tab(); ++nScTab)
930 : {
931 : // split 2-dimensional ranges into single columns
932 0 : if (bSplitToColumns && (aAbs1.Col() < aAbs2.Col()) && (aAbs1.Row() < aAbs2.Row()))
933 0 : for (SCCOL nScCol = aAbs1.Col(); nScCol <= aAbs2.Col(); ++nScCol)
934 0 : lclAddDoubleRefData(aArray, *pToken, nScTab, nScCol, aAbs1.Row(), nScTab, nScCol, aAbs2.Row());
935 : else
936 0 : lclAddDoubleRefData(aArray, *pToken, nScTab, aAbs1.Col(), aAbs1.Row(), nScTab, aAbs2.Col(), aAbs2.Row());
937 : }
938 0 : sal_uInt32 nTabs = static_cast<sal_uInt32>(aAbs2.Tab() - aAbs1.Tab() + 1);
939 0 : sal_uInt32 nCols = static_cast<sal_uInt32>(aAbs2.Col() - aAbs1.Col() + 1);
940 0 : sal_uInt32 nRows = static_cast<sal_uInt32>(aAbs2.Row() - aAbs1.Row() + 1);
941 0 : nValueCount += nCols * nRows * nTabs;
942 : }
943 0 : break;
944 :
945 : default:;
946 : }
947 : }
948 :
949 0 : const ScAddress aBaseCell;
950 0 : mxLinkFmla = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aArray, &aBaseCell );
951 0 : maData.mnLinkType = EXC_CHSRCLINK_WORKSHEET;
952 0 : return ulimit_cast< sal_uInt16 >( nValueCount, EXC_CHDATAFORMAT_MAXPOINTCOUNT );
953 : }
954 :
955 0 : void XclExpChSourceLink::ConvertString( const OUString& aString )
956 : {
957 0 : mxString = XclExpStringHelper::CreateString( GetRoot(), aString, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH | EXC_STR_SEPARATEFORMATS );
958 0 : }
959 :
960 0 : sal_uInt16 XclExpChSourceLink::ConvertStringSequence( const Sequence< Reference< XFormattedString > >& rStringSeq )
961 : {
962 0 : mxString.reset();
963 0 : sal_uInt16 nFontIdx = EXC_FONT_APP;
964 0 : if( rStringSeq.hasElements() )
965 : {
966 0 : mxString = XclExpStringHelper::CreateString( GetRoot(), OUString(), EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH | EXC_STR_SEPARATEFORMATS );
967 0 : Reference< XBreakIterator > xBreakIt = GetDoc().GetBreakIterator();
968 : namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
969 :
970 : // convert all formatted string entries from the sequence
971 0 : const Reference< XFormattedString >* pBeg = rStringSeq.getConstArray();
972 0 : const Reference< XFormattedString >* pEnd = pBeg + rStringSeq.getLength();
973 0 : for( const Reference< XFormattedString >* pIt = pBeg; pIt != pEnd; ++pIt )
974 : {
975 0 : if( pIt->is() )
976 : {
977 0 : sal_uInt16 nWstrnFontIdx = EXC_FONT_NOTFOUND;
978 0 : sal_uInt16 nAsianFontIdx = EXC_FONT_NOTFOUND;
979 0 : sal_uInt16 nCmplxFontIdx = EXC_FONT_NOTFOUND;
980 0 : OUString aText = (*pIt)->getString();
981 0 : ScfPropertySet aStrProp( *pIt );
982 :
983 : // #i63255# get script type for leading weak characters
984 0 : sal_Int16 nLastScript = XclExpStringHelper::GetLeadingScriptType( GetRoot(), aText );
985 :
986 : // process all script portions
987 0 : sal_Int32 nPortionPos = 0;
988 0 : sal_Int32 nTextLen = aText.getLength();
989 0 : while( nPortionPos < nTextLen )
990 : {
991 : // get script type and end position of next script portion
992 0 : sal_Int16 nScript = xBreakIt->getScriptType( aText, nPortionPos );
993 0 : sal_Int32 nPortionEnd = xBreakIt->endOfScript( aText, nPortionPos, nScript );
994 :
995 : // reuse previous script for following weak portions
996 0 : if( nScript == ApiScriptType::WEAK )
997 0 : nScript = nLastScript;
998 :
999 : // Excel start position of this portion
1000 0 : sal_uInt16 nXclPortionStart = mxString->Len();
1001 : // add portion text to Excel string
1002 0 : XclExpStringHelper::AppendString( *mxString, GetRoot(), aText.copy( nPortionPos, nPortionEnd - nPortionPos ) );
1003 0 : if( nXclPortionStart < mxString->Len() )
1004 : {
1005 : // find font index variable dependent on script type
1006 : sal_uInt16& rnFontIdx = (nScript == ApiScriptType::COMPLEX) ? nCmplxFontIdx :
1007 0 : ((nScript == ApiScriptType::ASIAN) ? nAsianFontIdx : nWstrnFontIdx);
1008 :
1009 : // insert font into buffer (if not yet done)
1010 0 : if( rnFontIdx == EXC_FONT_NOTFOUND )
1011 0 : rnFontIdx = ConvertFont( aStrProp, nScript );
1012 :
1013 : // insert font index into format run vector
1014 0 : mxString->AppendFormat( nXclPortionStart, rnFontIdx );
1015 : }
1016 :
1017 : // go to next script portion
1018 0 : nLastScript = nScript;
1019 0 : nPortionPos = nPortionEnd;
1020 0 : }
1021 : }
1022 : }
1023 0 : if( !mxString->IsEmpty() )
1024 : {
1025 : // get leading font index
1026 0 : const XclFormatRunVec& rFormats = mxString->GetFormats();
1027 : OSL_ENSURE( !rFormats.empty() && (rFormats.front().mnChar == 0),
1028 : "XclExpChSourceLink::ConvertStringSequenc - missing leading format" );
1029 : // remove leading format run, if entire string is equally formatted
1030 0 : if( rFormats.size() == 1 )
1031 0 : nFontIdx = mxString->RemoveLeadingFont();
1032 0 : else if( !rFormats.empty() )
1033 0 : nFontIdx = rFormats.front().mnFontIdx;
1034 : // add trailing format run, if string is rich-formatted
1035 0 : if( mxString->IsRich() )
1036 0 : mxString->AppendTrailingFormat( EXC_FONT_APP );
1037 0 : }
1038 : }
1039 0 : return nFontIdx;
1040 : }
1041 :
1042 0 : void XclExpChSourceLink::ConvertNumFmt( const ScfPropertySet& rPropSet, bool bPercent )
1043 : {
1044 0 : sal_Int32 nApiNumFmt = 0;
1045 0 : if( bPercent ? rPropSet.GetProperty( nApiNumFmt, EXC_CHPROP_PERCENTAGENUMFMT ) : rPropSet.GetProperty( nApiNumFmt, EXC_CHPROP_NUMBERFORMAT ) )
1046 : {
1047 0 : ::set_flag( maData.mnFlags, EXC_CHSRCLINK_NUMFMT );
1048 0 : maData.mnNumFmtIdx = GetNumFmtBuffer().Insert( static_cast< sal_uInt32 >( nApiNumFmt ) );
1049 : }
1050 0 : }
1051 :
1052 0 : void XclExpChSourceLink::AppendString( const OUString& rStr )
1053 : {
1054 0 : if (!mxString)
1055 0 : return;
1056 0 : XclExpStringHelper::AppendString( *mxString, GetRoot(), rStr );
1057 : }
1058 :
1059 0 : void XclExpChSourceLink::Save( XclExpStream& rStrm )
1060 : {
1061 : // CHFORMATRUNS record
1062 0 : if( mxString && mxString->IsRich() )
1063 : {
1064 0 : sal_Size nRecSize = (1 + mxString->GetFormatsCount()) * ((GetBiff() == EXC_BIFF8) ? 2 : 1);
1065 0 : rStrm.StartRecord( EXC_ID_CHFORMATRUNS, nRecSize );
1066 0 : mxString->WriteFormats( rStrm, true );
1067 0 : rStrm.EndRecord();
1068 : }
1069 : // CHSOURCELINK record
1070 0 : XclExpRecord::Save( rStrm );
1071 : // CHSTRING record
1072 0 : if( mxString && !mxString->IsEmpty() )
1073 : {
1074 0 : rStrm.StartRecord( EXC_ID_CHSTRING, 2 + mxString->GetSize() );
1075 0 : rStrm << sal_uInt16( 0 ) << *mxString;
1076 0 : rStrm.EndRecord();
1077 : }
1078 0 : }
1079 :
1080 0 : void XclExpChSourceLink::WriteBody( XclExpStream& rStrm )
1081 : {
1082 0 : rStrm << maData.mnDestType
1083 0 : << maData.mnLinkType
1084 0 : << maData.mnFlags
1085 0 : << maData.mnNumFmtIdx
1086 0 : << mxLinkFmla;
1087 0 : }
1088 :
1089 : // Text =======================================================================
1090 :
1091 0 : XclExpChFont::XclExpChFont( sal_uInt16 nFontIdx ) :
1092 0 : XclExpUInt16Record( EXC_ID_CHFONT, nFontIdx )
1093 : {
1094 0 : }
1095 :
1096 0 : XclExpChObjectLink::XclExpChObjectLink( sal_uInt16 nLinkTarget, const XclChDataPointPos& rPointPos ) :
1097 0 : XclExpRecord( EXC_ID_CHOBJECTLINK, 6 )
1098 : {
1099 0 : maData.mnTarget = nLinkTarget;
1100 0 : maData.maPointPos = rPointPos;
1101 0 : }
1102 :
1103 0 : void XclExpChObjectLink::WriteBody( XclExpStream& rStrm )
1104 : {
1105 0 : rStrm << maData.mnTarget << maData.maPointPos.mnSeriesIdx << maData.maPointPos.mnPointIdx;
1106 0 : }
1107 :
1108 0 : XclExpChFrLabelProps::XclExpChFrLabelProps( const XclExpChRoot& rRoot ) :
1109 0 : XclExpChFutureRecordBase( rRoot, EXC_FUTUREREC_UNUSEDREF, EXC_ID_CHFRLABELPROPS, 4 )
1110 : {
1111 0 : }
1112 :
1113 0 : void XclExpChFrLabelProps::Convert( const ScfPropertySet& rPropSet, bool bShowSeries,
1114 : bool bShowCateg, bool bShowValue, bool bShowPercent, bool bShowBubble )
1115 : {
1116 : // label value flags
1117 0 : ::set_flag( maData.mnFlags, EXC_CHFRLABELPROPS_SHOWSERIES, bShowSeries );
1118 0 : ::set_flag( maData.mnFlags, EXC_CHFRLABELPROPS_SHOWCATEG, bShowCateg );
1119 0 : ::set_flag( maData.mnFlags, EXC_CHFRLABELPROPS_SHOWVALUE, bShowValue );
1120 0 : ::set_flag( maData.mnFlags, EXC_CHFRLABELPROPS_SHOWPERCENT, bShowPercent );
1121 0 : ::set_flag( maData.mnFlags, EXC_CHFRLABELPROPS_SHOWBUBBLE, bShowBubble );
1122 :
1123 : // label value separator
1124 0 : maData.maSeparator = rPropSet.GetStringProperty( EXC_CHPROP_LABELSEPARATOR );
1125 0 : if( maData.maSeparator.isEmpty() )
1126 0 : maData.maSeparator = OUString(' ');
1127 0 : }
1128 :
1129 0 : void XclExpChFrLabelProps::WriteBody( XclExpStream& rStrm )
1130 : {
1131 0 : XclExpString aXclSep( maData.maSeparator, EXC_STR_FORCEUNICODE | EXC_STR_SMARTFLAGS );
1132 0 : rStrm << maData.mnFlags << aXclSep;
1133 0 : }
1134 :
1135 0 : XclExpChFontBase::~XclExpChFontBase()
1136 : {
1137 0 : }
1138 :
1139 0 : void XclExpChFontBase::ConvertFontBase( const XclExpChRoot& rRoot, sal_uInt16 nFontIdx )
1140 : {
1141 0 : if( const XclExpFont* pFont = rRoot.GetFontBuffer().GetFont( nFontIdx ) )
1142 : {
1143 0 : XclExpChFontRef xFont( new XclExpChFont( nFontIdx ) );
1144 0 : SetFont( xFont, pFont->GetFontData().maColor, pFont->GetFontColorId() );
1145 : }
1146 0 : }
1147 :
1148 0 : void XclExpChFontBase::ConvertFontBase( const XclExpChRoot& rRoot, const ScfPropertySet& rPropSet )
1149 : {
1150 0 : ConvertFontBase( rRoot, rRoot.ConvertFont( rPropSet, rRoot.GetDefApiScript() ) );
1151 0 : }
1152 :
1153 0 : void XclExpChFontBase::ConvertRotationBase(
1154 : const XclExpChRoot& rRoot, const ScfPropertySet& rPropSet, bool bSupportsStacked )
1155 : {
1156 0 : sal_uInt16 nRotation = rRoot.GetChartPropSetHelper().ReadRotationProperties( rPropSet, bSupportsStacked );
1157 0 : SetRotation( nRotation );
1158 0 : }
1159 :
1160 0 : XclExpChText::XclExpChText( const XclExpChRoot& rRoot ) :
1161 0 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_TEXT, EXC_ID_CHTEXT, (rRoot.GetBiff() == EXC_BIFF8) ? 32 : 26 ),
1162 0 : mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) )
1163 : {
1164 0 : }
1165 :
1166 0 : void XclExpChText::SetFont( XclExpChFontRef xFont, const Color& rColor, sal_uInt32 nColorId )
1167 : {
1168 0 : mxFont = xFont;
1169 0 : maData.maTextColor = rColor;
1170 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR, rColor == COL_AUTO );
1171 0 : mnTextColorId = nColorId;
1172 0 : }
1173 :
1174 0 : void XclExpChText::SetRotation( sal_uInt16 nRotation )
1175 : {
1176 0 : maData.mnRotation = nRotation;
1177 0 : ::insert_value( maData.mnFlags, XclTools::GetXclOrientFromRot( nRotation ), 8, 3 );
1178 0 : }
1179 :
1180 0 : void XclExpChText::ConvertTitle( Reference< XTitle > xTitle, sal_uInt16 nTarget, const OUString* pSubTitle )
1181 : {
1182 0 : switch( nTarget )
1183 : {
1184 0 : case EXC_CHOBJLINK_TITLE: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_TITLE ); break;
1185 0 : case EXC_CHOBJLINK_YAXIS: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE, 1 ); break;
1186 0 : case EXC_CHOBJLINK_XAXIS: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE, 0 ); break;
1187 0 : case EXC_CHOBJLINK_ZAXIS: SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_AXISTITLE, 2 ); break;
1188 : }
1189 :
1190 0 : mxSrcLink.reset();
1191 0 : mxObjLink.reset( new XclExpChObjectLink( nTarget, XclChDataPointPos( 0, 0 ) ) );
1192 :
1193 0 : if( xTitle.is() )
1194 : {
1195 : // title frame formatting
1196 0 : ScfPropertySet aTitleProp( xTitle );
1197 0 : mxFrame = lclCreateFrame( GetChRoot(), aTitleProp, EXC_CHOBJTYPE_TEXT );
1198 :
1199 : // string sequence
1200 0 : mxSrcLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) );
1201 0 : sal_uInt16 nFontIdx = mxSrcLink->ConvertStringSequence( xTitle->getText() );
1202 0 : if (pSubTitle)
1203 : {
1204 : // append subtitle as the 2nd line of the title.
1205 0 : OUString aSubTitle("\n");
1206 0 : aSubTitle += *pSubTitle;
1207 0 : mxSrcLink->AppendString(aSubTitle);
1208 : }
1209 :
1210 0 : ConvertFontBase( GetChRoot(), nFontIdx );
1211 :
1212 : // rotation
1213 0 : ConvertRotationBase( GetChRoot(), aTitleProp, true );
1214 :
1215 : // manual text position - only for main title
1216 0 : mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) );
1217 0 : if( nTarget == EXC_CHOBJLINK_TITLE )
1218 : {
1219 0 : Any aRelPos;
1220 0 : if( aTitleProp.GetAnyProperty( aRelPos, EXC_CHPROP_RELATIVEPOSITION ) && aRelPos.has< RelativePosition >() ) try
1221 : {
1222 : // calculate absolute position for CHTEXT record
1223 0 : Reference< cssc::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
1224 0 : Reference< XShape > xTitleShape( xChart1Doc->getTitle(), UNO_SET_THROW );
1225 0 : ::com::sun::star::awt::Point aPos = xTitleShape->getPosition();
1226 0 : ::com::sun::star::awt::Size aSize = xTitleShape->getSize();
1227 0 : ::com::sun::star::awt::Rectangle aRect( aPos.X, aPos.Y, aSize.Width, aSize.Height );
1228 0 : maData.maRect = CalcChartRectFromHmm( aRect );
1229 0 : ::insert_value( maData.mnFlags2, EXC_CHTEXT_POS_MOVED, 0, 4 );
1230 : // manual title position implies manual plot area
1231 0 : GetChartData().SetManualPlotArea();
1232 : // calculate the default title position in chart units
1233 0 : sal_Int32 nDefPosX = ::std::max< sal_Int32 >( (EXC_CHART_TOTALUNITS - maData.maRect.mnWidth) / 2, 0 );
1234 0 : sal_Int32 nDefPosY = 85;
1235 : // set the position relative to the standard position
1236 0 : XclChRectangle& rFrameRect = mxFramePos->GetFramePosData().maRect;
1237 0 : rFrameRect.mnX = maData.maRect.mnX - nDefPosX;
1238 0 : rFrameRect.mnY = maData.maRect.mnY - nDefPosY;
1239 : }
1240 0 : catch( Exception& )
1241 : {
1242 0 : }
1243 0 : }
1244 : }
1245 : else
1246 : {
1247 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED );
1248 : }
1249 0 : }
1250 :
1251 0 : void XclExpChText::ConvertLegend( const ScfPropertySet& rPropSet )
1252 : {
1253 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOTEXT );
1254 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOGEN );
1255 0 : ConvertFontBase( GetChRoot(), rPropSet );
1256 0 : }
1257 :
1258 0 : bool XclExpChText::ConvertDataLabel( const ScfPropertySet& rPropSet,
1259 : const XclChTypeInfo& rTypeInfo, const XclChDataPointPos& rPointPos )
1260 : {
1261 0 : SetFutureRecordContext( EXC_CHFRBLOCK_TEXT_DATALABEL, rPointPos.mnPointIdx, rPointPos.mnSeriesIdx );
1262 :
1263 0 : cssc2::DataPointLabel aPointLabel;
1264 0 : if( !rPropSet.GetProperty( aPointLabel, EXC_CHPROP_LABEL ) )
1265 0 : return false;
1266 :
1267 : // percentage only allowed in pie and donut charts
1268 0 : bool bIsPie = rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE;
1269 : // bubble sizes only allowed in bubble charts
1270 0 : bool bIsBubble = rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES;
1271 : OSL_ENSURE( (GetBiff() == EXC_BIFF8) || !bIsBubble, "XclExpChText::ConvertDataLabel - bubble charts only in BIFF8" );
1272 :
1273 : // raw show flags
1274 0 : bool bShowValue = !bIsBubble && aPointLabel.ShowNumber; // Chart2 uses 'ShowNumber' for bubble size
1275 0 : bool bShowPercent = bIsPie && aPointLabel.ShowNumberInPercent; // percentage only in pie/donut charts
1276 0 : bool bShowCateg = aPointLabel.ShowCategoryName;
1277 0 : bool bShowBubble = bIsBubble && aPointLabel.ShowNumber; // Chart2 uses 'ShowNumber' for bubble size
1278 0 : bool bShowAny = bShowValue || bShowPercent || bShowCateg || bShowBubble;
1279 :
1280 : // create the CHFRLABELPROPS record for extended settings in BIFF8
1281 0 : if( bShowAny && (GetBiff() == EXC_BIFF8) )
1282 : {
1283 0 : mxLabelProps.reset( new XclExpChFrLabelProps( GetChRoot() ) );
1284 0 : mxLabelProps->Convert( rPropSet, false, bShowCateg, bShowValue, bShowPercent, bShowBubble );
1285 : }
1286 :
1287 : // restrict to combinations allowed in CHTEXT
1288 0 : if( bShowPercent ) bShowValue = false; // percent wins over value
1289 0 : if( bShowValue ) bShowCateg = false; // value wins over category
1290 0 : if( bShowValue || bShowCateg ) bShowBubble = false; // value or category wins over bubble size
1291 :
1292 : // set all flags
1293 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOTEXT );
1294 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWVALUE, bShowValue );
1295 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWPERCENT, bShowPercent );
1296 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG, bShowCateg );
1297 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC, bShowPercent && bShowCateg );
1298 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWBUBBLE, bShowBubble );
1299 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL, bShowAny && aPointLabel.ShowLegendSymbol );
1300 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED, !bShowAny );
1301 :
1302 0 : if( bShowAny )
1303 : {
1304 : // font settings
1305 0 : ConvertFontBase( GetChRoot(), rPropSet );
1306 0 : ConvertRotationBase( GetChRoot(), rPropSet, false );
1307 : // label placement
1308 0 : sal_Int32 nPlacement = 0;
1309 0 : sal_uInt16 nLabelPos = EXC_CHTEXT_POS_AUTO;
1310 0 : if( rPropSet.GetProperty( nPlacement, EXC_CHPROP_LABELPLACEMENT ) )
1311 : {
1312 : using namespace cssc::DataLabelPlacement;
1313 0 : if( nPlacement == rTypeInfo.mnDefaultLabelPos )
1314 : {
1315 0 : nLabelPos = EXC_CHTEXT_POS_DEFAULT;
1316 : }
1317 0 : else switch( nPlacement )
1318 : {
1319 0 : case AVOID_OVERLAP: nLabelPos = EXC_CHTEXT_POS_AUTO; break;
1320 0 : case CENTER: nLabelPos = EXC_CHTEXT_POS_CENTER; break;
1321 0 : case TOP: nLabelPos = EXC_CHTEXT_POS_ABOVE; break;
1322 0 : case TOP_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
1323 0 : case LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
1324 0 : case BOTTOM_LEFT: nLabelPos = EXC_CHTEXT_POS_LEFT; break;
1325 0 : case BOTTOM: nLabelPos = EXC_CHTEXT_POS_BELOW; break;
1326 0 : case BOTTOM_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
1327 0 : case RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
1328 0 : case TOP_RIGHT: nLabelPos = EXC_CHTEXT_POS_RIGHT; break;
1329 0 : case INSIDE: nLabelPos = EXC_CHTEXT_POS_INSIDE; break;
1330 0 : case OUTSIDE: nLabelPos = EXC_CHTEXT_POS_OUTSIDE; break;
1331 0 : case NEAR_ORIGIN: nLabelPos = EXC_CHTEXT_POS_AXIS; break;
1332 : default: OSL_FAIL( "XclExpChText::ConvertDataLabel - unknown label placement type" );
1333 : }
1334 : }
1335 0 : ::insert_value( maData.mnFlags2, nLabelPos, 0, 4 );
1336 : // source link (contains number format)
1337 0 : mxSrcLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) );
1338 0 : if( bShowValue || bShowPercent )
1339 : // percentage format wins over value format
1340 0 : mxSrcLink->ConvertNumFmt( rPropSet, bShowPercent );
1341 : // object link
1342 0 : mxObjLink.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA, rPointPos ) );
1343 : }
1344 :
1345 : /* Return true to indicate valid label settings:
1346 : - for existing labels at entire series
1347 : - for any settings at single data point (to be able to delete a point label) */
1348 0 : return bShowAny || (rPointPos.mnPointIdx != EXC_CHDATAFORMAT_ALLPOINTS);
1349 : }
1350 :
1351 0 : void XclExpChText::ConvertTrendLineEquation( const ScfPropertySet& rPropSet, const XclChDataPointPos& rPointPos )
1352 : {
1353 : // required flags
1354 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOTEXT );
1355 0 : if( GetBiff() == EXC_BIFF8 )
1356 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG ); // must set this to make equation visible in Excel
1357 : // frame formatting
1358 0 : mxFrame = lclCreateFrame( GetChRoot(), rPropSet, EXC_CHOBJTYPE_TEXT );
1359 : // font settings
1360 0 : maData.mnHAlign = EXC_CHTEXT_ALIGN_TOPLEFT;
1361 0 : maData.mnVAlign = EXC_CHTEXT_ALIGN_TOPLEFT;
1362 0 : ConvertFontBase( GetChRoot(), rPropSet );
1363 : // source link (contains number format)
1364 0 : mxSrcLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) );
1365 0 : mxSrcLink->ConvertNumFmt( rPropSet, false );
1366 : // object link
1367 0 : mxObjLink.reset( new XclExpChObjectLink( EXC_CHOBJLINK_DATA, rPointPos ) );
1368 0 : }
1369 :
1370 0 : sal_uInt16 XclExpChText::GetAttLabelFlags() const
1371 : {
1372 0 : sal_uInt16 nFlags = 0;
1373 0 : ::set_flag( nFlags, EXC_CHATTLABEL_SHOWVALUE, ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWVALUE ) );
1374 0 : ::set_flag( nFlags, EXC_CHATTLABEL_SHOWPERCENT, ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWPERCENT ) );
1375 0 : ::set_flag( nFlags, EXC_CHATTLABEL_SHOWCATEGPERC, ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC ) );
1376 0 : ::set_flag( nFlags, EXC_CHATTLABEL_SHOWCATEG, ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG ) );
1377 0 : return nFlags;
1378 : }
1379 :
1380 0 : void XclExpChText::WriteSubRecords( XclExpStream& rStrm )
1381 : {
1382 : // CHFRAMEPOS record
1383 0 : lclSaveRecord( rStrm, mxFramePos );
1384 : // CHFONT record
1385 0 : lclSaveRecord( rStrm, mxFont );
1386 : // CHSOURCELINK group
1387 0 : lclSaveRecord( rStrm, mxSrcLink );
1388 : // CHFRAME group
1389 0 : lclSaveRecord( rStrm, mxFrame );
1390 : // CHOBJECTLINK record
1391 0 : lclSaveRecord( rStrm, mxObjLink );
1392 : // CHFRLABELPROPS record
1393 0 : lclSaveRecord( rStrm, mxLabelProps );
1394 0 : }
1395 :
1396 0 : void XclExpChText::WriteBody( XclExpStream& rStrm )
1397 : {
1398 0 : rStrm << maData.mnHAlign
1399 0 : << maData.mnVAlign
1400 0 : << maData.mnBackMode
1401 0 : << maData.maTextColor
1402 0 : << maData.maRect
1403 0 : << maData.mnFlags;
1404 :
1405 0 : if( GetBiff() == EXC_BIFF8 )
1406 : {
1407 0 : rStrm << GetPalette().GetColorIndex( mnTextColorId )
1408 0 : << maData.mnFlags2
1409 0 : << maData.mnRotation;
1410 : }
1411 0 : }
1412 :
1413 : namespace {
1414 :
1415 : /** Creates and returns an Excel text object from the passed title. */
1416 0 : XclExpChTextRef lclCreateTitle( const XclExpChRoot& rRoot, Reference< XTitled > xTitled, sal_uInt16 nTarget,
1417 : const OUString* pSubTitle = NULL )
1418 : {
1419 0 : Reference< XTitle > xTitle;
1420 0 : if( xTitled.is() )
1421 0 : xTitle = xTitled->getTitleObject();
1422 :
1423 0 : XclExpChTextRef xText( new XclExpChText( rRoot ) );
1424 0 : xText->ConvertTitle( xTitle, nTarget, pSubTitle );
1425 : /* Do not delete the CHTEXT group for the main title. A missing CHTEXT
1426 : will be interpreted as auto-generated title showing the series title in
1427 : charts that contain exactly one data series. */
1428 0 : if( (nTarget != EXC_CHOBJLINK_TITLE) && !xText->HasString() )
1429 0 : xText.reset();
1430 :
1431 0 : return xText;
1432 : }
1433 :
1434 : }
1435 :
1436 : // Data series ================================================================
1437 :
1438 0 : XclExpChMarkerFormat::XclExpChMarkerFormat( const XclExpChRoot& rRoot ) :
1439 0 : XclExpRecord( EXC_ID_CHMARKERFORMAT, (rRoot.GetBiff() == EXC_BIFF8) ? 20 : 12 ),
1440 0 : mnLineColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) ),
1441 0 : mnFillColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWBACK ) )
1442 : {
1443 0 : }
1444 :
1445 0 : void XclExpChMarkerFormat::Convert( const XclExpChRoot& rRoot,
1446 : const ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx )
1447 : {
1448 0 : rRoot.GetChartPropSetHelper().ReadMarkerProperties( maData, rPropSet, nFormatIdx );
1449 : /* Set marker line/fill color to series line color.
1450 : TODO: remove this if OOChart supports own colors in markers. */
1451 0 : Color aLineColor;
1452 0 : if( rPropSet.GetColorProperty( aLineColor, EXC_CHPROP_COLOR ) )
1453 0 : maData.maLineColor = maData.maFillColor = aLineColor;
1454 : // register colors in palette
1455 0 : RegisterColors( rRoot );
1456 0 : }
1457 :
1458 0 : void XclExpChMarkerFormat::ConvertStockSymbol( const XclExpChRoot& rRoot,
1459 : const ScfPropertySet& rPropSet, bool bCloseSymbol )
1460 : {
1461 : // clear the automatic flag
1462 0 : ::set_flag( maData.mnFlags, EXC_CHMARKERFORMAT_AUTO, false );
1463 : // symbol type and color
1464 0 : if( bCloseSymbol )
1465 : {
1466 : // set symbol type for the 'close' data series
1467 0 : maData.mnMarkerType = EXC_CHMARKERFORMAT_DOWJ;
1468 0 : maData.mnMarkerSize = EXC_CHMARKERFORMAT_DOUBLESIZE;
1469 : // set symbol line/fill color to series line color
1470 0 : Color aLineColor;
1471 0 : if( rPropSet.GetColorProperty( aLineColor, EXC_CHPROP_COLOR ) )
1472 : {
1473 0 : maData.maLineColor = maData.maFillColor = aLineColor;
1474 0 : RegisterColors( rRoot );
1475 : }
1476 : }
1477 : else
1478 : {
1479 : // set invisible symbol
1480 0 : maData.mnMarkerType = EXC_CHMARKERFORMAT_NOSYMBOL;
1481 : }
1482 0 : }
1483 :
1484 0 : void XclExpChMarkerFormat::RegisterColors( const XclExpChRoot& rRoot )
1485 : {
1486 0 : if( HasMarker() )
1487 : {
1488 0 : if( HasLineColor() )
1489 0 : mnLineColorId = rRoot.GetPalette().InsertColor( maData.maLineColor, EXC_COLOR_CHARTLINE );
1490 0 : if( HasFillColor() )
1491 0 : mnFillColorId = rRoot.GetPalette().InsertColor( maData.maFillColor, EXC_COLOR_CHARTAREA );
1492 : }
1493 0 : }
1494 :
1495 0 : void XclExpChMarkerFormat::WriteBody( XclExpStream& rStrm )
1496 : {
1497 0 : rStrm << maData.maLineColor << maData.maFillColor << maData.mnMarkerType << maData.mnFlags;
1498 0 : if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
1499 : {
1500 0 : const XclExpPalette& rPal = rStrm.GetRoot().GetPalette();
1501 0 : rStrm << rPal.GetColorIndex( mnLineColorId ) << rPal.GetColorIndex( mnFillColorId ) << maData.mnMarkerSize;
1502 : }
1503 0 : }
1504 :
1505 0 : XclExpChPieFormat::XclExpChPieFormat() :
1506 0 : XclExpUInt16Record( EXC_ID_CHPIEFORMAT, 0 )
1507 : {
1508 0 : }
1509 :
1510 0 : void XclExpChPieFormat::Convert( const ScfPropertySet& rPropSet )
1511 : {
1512 0 : double fApiDist(0.0);
1513 0 : if( rPropSet.GetProperty( fApiDist, EXC_CHPROP_OFFSET ) )
1514 0 : SetValue( limit_cast< sal_uInt16 >( fApiDist * 100.0, 0, 100 ) );
1515 0 : }
1516 :
1517 0 : XclExpCh3dDataFormat::XclExpCh3dDataFormat() :
1518 0 : XclExpRecord( EXC_ID_CH3DDATAFORMAT, 2 )
1519 : {
1520 0 : }
1521 :
1522 0 : void XclExpCh3dDataFormat::Convert( const ScfPropertySet& rPropSet )
1523 : {
1524 0 : sal_Int32 nApiType(0);
1525 0 : if( rPropSet.GetProperty( nApiType, EXC_CHPROP_GEOMETRY3D ) )
1526 : {
1527 : using namespace cssc2::DataPointGeometry3D;
1528 0 : switch( nApiType )
1529 : {
1530 : case CUBOID:
1531 0 : maData.mnBase = EXC_CH3DDATAFORMAT_RECT;
1532 0 : maData.mnTop = EXC_CH3DDATAFORMAT_STRAIGHT;
1533 0 : break;
1534 : case PYRAMID:
1535 0 : maData.mnBase = EXC_CH3DDATAFORMAT_RECT;
1536 0 : maData.mnTop = EXC_CH3DDATAFORMAT_SHARP;
1537 0 : break;
1538 : case CYLINDER:
1539 0 : maData.mnBase = EXC_CH3DDATAFORMAT_CIRC;
1540 0 : maData.mnTop = EXC_CH3DDATAFORMAT_STRAIGHT;
1541 0 : break;
1542 : case CONE:
1543 0 : maData.mnBase = EXC_CH3DDATAFORMAT_CIRC;
1544 0 : maData.mnTop = EXC_CH3DDATAFORMAT_SHARP;
1545 0 : break;
1546 : default:
1547 : OSL_FAIL( "XclExpCh3dDataFormat::Convert - unknown 3D bar format" );
1548 : }
1549 : }
1550 0 : }
1551 :
1552 0 : void XclExpCh3dDataFormat::WriteBody( XclExpStream& rStrm )
1553 : {
1554 0 : rStrm << maData.mnBase << maData.mnTop;
1555 0 : }
1556 :
1557 0 : XclExpChAttachedLabel::XclExpChAttachedLabel( sal_uInt16 nFlags ) :
1558 0 : XclExpUInt16Record( EXC_ID_CHATTACHEDLABEL, nFlags )
1559 : {
1560 0 : }
1561 :
1562 0 : XclExpChDataFormat::XclExpChDataFormat( const XclExpChRoot& rRoot,
1563 : const XclChDataPointPos& rPointPos, sal_uInt16 nFormatIdx ) :
1564 0 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_DATAFORMAT, EXC_ID_CHDATAFORMAT, 8 )
1565 : {
1566 0 : maData.maPointPos = rPointPos;
1567 0 : maData.mnFormatIdx = nFormatIdx;
1568 0 : }
1569 :
1570 0 : void XclExpChDataFormat::ConvertDataSeries( const ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo )
1571 : {
1572 : // line and area formatting
1573 0 : ConvertFrameBase( GetChRoot(), rPropSet, rTypeInfo.GetSeriesObjectType() );
1574 :
1575 : // data point symbols
1576 0 : bool bIsFrame = rTypeInfo.IsSeriesFrameFormat();
1577 0 : if( !bIsFrame )
1578 : {
1579 0 : mxMarkerFmt.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1580 0 : mxMarkerFmt->Convert( GetChRoot(), rPropSet, maData.mnFormatIdx );
1581 : }
1582 :
1583 : // pie segments
1584 0 : if( rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE )
1585 : {
1586 0 : mxPieFmt.reset( new XclExpChPieFormat );
1587 0 : mxPieFmt->Convert( rPropSet );
1588 : }
1589 :
1590 : // 3D bars (only allowed for entire series in BIFF8)
1591 0 : if( IsSeriesFormat() && (GetBiff() == EXC_BIFF8) && rTypeInfo.mb3dChart && (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR) )
1592 : {
1593 0 : mx3dDataFmt.reset( new XclExpCh3dDataFormat );
1594 0 : mx3dDataFmt->Convert( rPropSet );
1595 : }
1596 :
1597 : // spline
1598 0 : if( IsSeriesFormat() && rTypeInfo.mbSpline && !bIsFrame )
1599 0 : mxSeriesFmt.reset( new XclExpUInt16Record( EXC_ID_CHSERIESFORMAT, EXC_CHSERIESFORMAT_SMOOTHED ) );
1600 :
1601 : // data point labels
1602 0 : XclExpChTextRef xLabel( new XclExpChText( GetChRoot() ) );
1603 0 : if( xLabel->ConvertDataLabel( rPropSet, rTypeInfo, maData.maPointPos ) )
1604 : {
1605 : // CHTEXT groups for data labels are stored in global CHCHART group
1606 0 : GetChartData().SetDataLabel( xLabel );
1607 0 : mxAttLabel.reset( new XclExpChAttachedLabel( xLabel->GetAttLabelFlags() ) );
1608 0 : }
1609 0 : }
1610 :
1611 0 : void XclExpChDataFormat::ConvertStockSeries( const ScfPropertySet& rPropSet, bool bCloseSymbol )
1612 : {
1613 : // set line format to invisible
1614 0 : SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE, false );
1615 : // set symbols to invisible or to 'close' series symbol
1616 0 : mxMarkerFmt.reset( new XclExpChMarkerFormat( GetChRoot() ) );
1617 0 : mxMarkerFmt->ConvertStockSymbol( GetChRoot(), rPropSet, bCloseSymbol );
1618 0 : }
1619 :
1620 0 : void XclExpChDataFormat::ConvertLine( const ScfPropertySet& rPropSet, XclChObjectType eObjType )
1621 : {
1622 0 : ConvertFrameBase( GetChRoot(), rPropSet, eObjType );
1623 0 : }
1624 :
1625 0 : void XclExpChDataFormat::WriteSubRecords( XclExpStream& rStrm )
1626 : {
1627 0 : lclSaveRecord( rStrm, mx3dDataFmt );
1628 0 : WriteFrameRecords( rStrm );
1629 0 : lclSaveRecord( rStrm, mxPieFmt );
1630 0 : lclSaveRecord( rStrm, mxMarkerFmt );
1631 0 : lclSaveRecord( rStrm, mxSeriesFmt );
1632 0 : lclSaveRecord( rStrm, mxAttLabel );
1633 0 : }
1634 :
1635 0 : void XclExpChDataFormat::WriteBody( XclExpStream& rStrm )
1636 : {
1637 0 : rStrm << maData.maPointPos.mnPointIdx
1638 0 : << maData.maPointPos.mnSeriesIdx
1639 0 : << maData.mnFormatIdx
1640 0 : << maData.mnFlags;
1641 0 : }
1642 :
1643 0 : XclExpChSerTrendLine::XclExpChSerTrendLine( const XclExpChRoot& rRoot ) :
1644 : XclExpRecord( EXC_ID_CHSERTRENDLINE, 28 ),
1645 0 : XclExpChRoot( rRoot )
1646 : {
1647 0 : }
1648 :
1649 0 : bool XclExpChSerTrendLine::Convert( Reference< XRegressionCurve > xRegCurve, sal_uInt16 nSeriesIdx )
1650 : {
1651 0 : if( !xRegCurve.is() )
1652 0 : return false;
1653 :
1654 : // trend line type
1655 0 : ScfPropertySet aCurveProp( xRegCurve );
1656 :
1657 0 : OUString aService = aCurveProp.GetServiceName();
1658 0 : if( aService == "com.sun.star.chart2.LinearRegressionCurve" )
1659 : {
1660 0 : maData.mnLineType = EXC_CHSERTREND_POLYNOMIAL;
1661 0 : maData.mnOrder = 1;
1662 : }
1663 0 : else if( aService == "com.sun.star.chart2.ExponentialRegressionCurve" )
1664 : {
1665 0 : maData.mnLineType = EXC_CHSERTREND_EXPONENTIAL;
1666 : }
1667 0 : else if( aService == "com.sun.star.chart2.LogarithmicRegressionCurve" )
1668 : {
1669 0 : maData.mnLineType = EXC_CHSERTREND_LOGARITHMIC;
1670 : }
1671 0 : else if( aService == "com.sun.star.chart2.PotentialRegressionCurve" )
1672 : {
1673 0 : maData.mnLineType = EXC_CHSERTREND_POWER;
1674 : }
1675 0 : else if( aService == "com.sun.star.chart2.PolynomialRegressionCurve" )
1676 : {
1677 0 : maData.mnLineType = EXC_CHSERTREND_POLYNOMIAL;
1678 : sal_Int32 aDegree;
1679 0 : aCurveProp.GetProperty(aDegree, EXC_CHPROP_POLYNOMIAL_DEGREE);
1680 0 : maData.mnOrder = static_cast<sal_uInt8> (aDegree);
1681 : }
1682 0 : else if( aService == "com.sun.star.chart2.MovingAverageRegressionCurve" )
1683 : {
1684 0 : maData.mnLineType = EXC_CHSERTREND_MOVING_AVG;
1685 : sal_Int32 aPeriod;
1686 0 : aCurveProp.GetProperty(aPeriod, EXC_CHPROP_MOVING_AVERAGE_PERIOD);
1687 0 : maData.mnOrder = static_cast<sal_uInt8> (aPeriod);
1688 : }
1689 : else
1690 : {
1691 0 : return false;
1692 : }
1693 :
1694 0 : aCurveProp.GetProperty(maData.mfForecastFor, EXC_CHPROP_EXTRAPOLATE_FORWARD);
1695 0 : aCurveProp.GetProperty(maData.mfForecastBack, EXC_CHPROP_EXTRAPOLATE_BACKWARD);
1696 0 : sal_Bool bIsForceIntercept = false;
1697 0 : aCurveProp.GetProperty(bIsForceIntercept, EXC_CHPROP_FORCE_INTERCEPT);
1698 0 : if (bIsForceIntercept)
1699 0 : aCurveProp.GetProperty(maData.mfIntercept, EXC_CHPROP_INTERCEPT_VALUE);
1700 :
1701 :
1702 : // line formatting
1703 0 : XclChDataPointPos aPointPos( nSeriesIdx );
1704 0 : mxDataFmt.reset( new XclExpChDataFormat( GetChRoot(), aPointPos, 0 ) );
1705 0 : mxDataFmt->ConvertLine( aCurveProp, EXC_CHOBJTYPE_TRENDLINE );
1706 :
1707 : // #i83100# show equation and correlation coefficient
1708 0 : ScfPropertySet aEquationProp( xRegCurve->getEquationProperties() );
1709 0 : maData.mnShowEquation = aEquationProp.GetBoolProperty( EXC_CHPROP_SHOWEQUATION ) ? 1 : 0;
1710 0 : maData.mnShowRSquared = aEquationProp.GetBoolProperty( EXC_CHPROP_SHOWCORRELATION ) ? 1 : 0;
1711 :
1712 : // #i83100# formatting of the equation text box
1713 0 : if( (maData.mnShowEquation != 0) || (maData.mnShowRSquared != 0) )
1714 : {
1715 0 : mxLabel.reset( new XclExpChText( GetChRoot() ) );
1716 0 : mxLabel->ConvertTrendLineEquation( aEquationProp, aPointPos );
1717 : }
1718 :
1719 : // missing features
1720 : // #i5085# manual trend line size
1721 : // #i34093# manual crossing point
1722 0 : return true;
1723 : }
1724 :
1725 0 : void XclExpChSerTrendLine::WriteBody( XclExpStream& rStrm )
1726 : {
1727 0 : rStrm << maData.mnLineType
1728 0 : << maData.mnOrder
1729 0 : << maData.mfIntercept
1730 0 : << maData.mnShowEquation
1731 0 : << maData.mnShowRSquared
1732 0 : << maData.mfForecastFor
1733 0 : << maData.mfForecastBack;
1734 0 : }
1735 :
1736 0 : XclExpChSerErrorBar::XclExpChSerErrorBar( const XclExpChRoot& rRoot, sal_uInt8 nBarType ) :
1737 : XclExpRecord( EXC_ID_CHSERERRORBAR, 14 ),
1738 0 : XclExpChRoot( rRoot )
1739 : {
1740 0 : maData.mnBarType = nBarType;
1741 0 : }
1742 :
1743 0 : bool XclExpChSerErrorBar::Convert( XclExpChSourceLink& rValueLink, sal_uInt16& rnValueCount, const ScfPropertySet& rPropSet )
1744 : {
1745 0 : sal_Int32 nBarStyle = 0;
1746 0 : bool bOk = rPropSet.GetProperty( nBarStyle, EXC_CHPROP_ERRORBARSTYLE );
1747 0 : if( bOk )
1748 : {
1749 0 : switch( nBarStyle )
1750 : {
1751 : case cssc::ErrorBarStyle::ABSOLUTE:
1752 0 : maData.mnSourceType = EXC_CHSERERR_FIXED;
1753 0 : rPropSet.GetProperty( maData.mfValue, EXC_CHPROP_POSITIVEERROR );
1754 0 : break;
1755 : case cssc::ErrorBarStyle::RELATIVE:
1756 0 : maData.mnSourceType = EXC_CHSERERR_PERCENT;
1757 0 : rPropSet.GetProperty( maData.mfValue, EXC_CHPROP_POSITIVEERROR );
1758 0 : break;
1759 : case cssc::ErrorBarStyle::STANDARD_DEVIATION:
1760 0 : maData.mnSourceType = EXC_CHSERERR_STDDEV;
1761 0 : rPropSet.GetProperty( maData.mfValue, EXC_CHPROP_WEIGHT );
1762 0 : break;
1763 : case cssc::ErrorBarStyle::STANDARD_ERROR:
1764 0 : maData.mnSourceType = EXC_CHSERERR_STDERR;
1765 0 : break;
1766 : case cssc::ErrorBarStyle::FROM_DATA:
1767 : {
1768 0 : bOk = false;
1769 0 : maData.mnSourceType = EXC_CHSERERR_CUSTOM;
1770 0 : Reference< XDataSource > xDataSource( rPropSet.GetApiPropertySet(), UNO_QUERY );
1771 0 : if( xDataSource.is() )
1772 : {
1773 : // find first sequence with current role
1774 0 : OUString aRole = XclChartHelper::GetErrorBarValuesRole( maData.mnBarType );
1775 0 : Reference< XDataSequence > xValueSeq;
1776 :
1777 0 : Sequence< Reference< XLabeledDataSequence > > aLabeledSeqVec = xDataSource->getDataSequences();
1778 0 : const Reference< XLabeledDataSequence >* pBeg = aLabeledSeqVec.getConstArray();
1779 0 : const Reference< XLabeledDataSequence >* pEnd = pBeg + aLabeledSeqVec.getLength();
1780 0 : for( const Reference< XLabeledDataSequence >* pIt = pBeg; !xValueSeq.is() && (pIt != pEnd); ++pIt )
1781 : {
1782 0 : Reference< XDataSequence > xTmpValueSeq = (*pIt)->getValues();
1783 0 : ScfPropertySet aValueProp( xTmpValueSeq );
1784 0 : OUString aCurrRole;
1785 0 : if( aValueProp.GetProperty( aCurrRole, EXC_CHPROP_ROLE ) && (aCurrRole == aRole) )
1786 0 : xValueSeq = xTmpValueSeq;
1787 0 : }
1788 0 : if( xValueSeq.is() )
1789 : {
1790 : // #i86465# pass value count back to series
1791 0 : rnValueCount = maData.mnValueCount = rValueLink.ConvertDataSequence( xValueSeq, true );
1792 0 : bOk = maData.mnValueCount > 0;
1793 0 : }
1794 0 : }
1795 : }
1796 0 : break;
1797 : default:
1798 0 : bOk = false;
1799 : }
1800 : }
1801 0 : return bOk;
1802 : }
1803 :
1804 0 : void XclExpChSerErrorBar::WriteBody( XclExpStream& rStrm )
1805 : {
1806 0 : rStrm << maData.mnBarType
1807 0 : << maData.mnSourceType
1808 0 : << maData.mnLineEnd
1809 0 : << sal_uInt8( 1 ) // must be 1 to make line visible
1810 0 : << maData.mfValue
1811 0 : << maData.mnValueCount;
1812 0 : }
1813 :
1814 : namespace {
1815 :
1816 : /** Returns the property set of the specified data point. */
1817 0 : ScfPropertySet lclGetPointPropSet( Reference< XDataSeries > xDataSeries, sal_Int32 nPointIdx )
1818 : {
1819 0 : ScfPropertySet aPropSet;
1820 : try
1821 : {
1822 0 : aPropSet.Set( xDataSeries->getDataPointByIndex( nPointIdx ) );
1823 : }
1824 0 : catch( Exception& )
1825 : {
1826 : OSL_FAIL( "lclGetPointPropSet - no data point property set" );
1827 : }
1828 0 : return aPropSet;
1829 : }
1830 :
1831 : } // namespace
1832 :
1833 0 : XclExpChSeries::XclExpChSeries( const XclExpChRoot& rRoot, sal_uInt16 nSeriesIdx ) :
1834 0 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_SERIES, EXC_ID_CHSERIES, (rRoot.GetBiff() == EXC_BIFF8) ? 12 : 8 ),
1835 : mnGroupIdx( EXC_CHSERGROUP_NONE ),
1836 : mnSeriesIdx( nSeriesIdx ),
1837 0 : mnParentIdx( EXC_CHSERIES_INVALID )
1838 : {
1839 : // CHSOURCELINK records are always required, even if unused
1840 0 : mxTitleLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_TITLE ) );
1841 0 : mxValueLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_VALUES ) );
1842 0 : mxCategLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_CATEGORY ) );
1843 0 : if( GetBiff() == EXC_BIFF8 )
1844 0 : mxBubbleLink.reset( new XclExpChSourceLink( GetChRoot(), EXC_CHSRCLINK_BUBBLES ) );
1845 0 : }
1846 :
1847 0 : bool XclExpChSeries::ConvertDataSeries(
1848 : Reference< XDiagram > xDiagram, Reference< XDataSeries > xDataSeries,
1849 : const XclChExtTypeInfo& rTypeInfo, sal_uInt16 nGroupIdx, sal_uInt16 nFormatIdx )
1850 : {
1851 0 : bool bOk = false;
1852 0 : Reference< XDataSource > xDataSource( xDataSeries, UNO_QUERY );
1853 0 : if( xDataSource.is() )
1854 : {
1855 0 : Reference< XDataSequence > xYValueSeq, xTitleSeq, xXValueSeq, xBubbleSeq;
1856 :
1857 : // find first sequence with role 'values-y'
1858 0 : Sequence< Reference< XLabeledDataSequence > > aLabeledSeqVec = xDataSource->getDataSequences();
1859 0 : const Reference< XLabeledDataSequence >* pBeg = aLabeledSeqVec.getConstArray();
1860 0 : const Reference< XLabeledDataSequence >* pEnd = pBeg + aLabeledSeqVec.getLength();
1861 0 : for( const Reference< XLabeledDataSequence >* pIt = pBeg; pIt != pEnd; ++pIt )
1862 : {
1863 0 : Reference< XDataSequence > xTmpValueSeq = (*pIt)->getValues();
1864 0 : ScfPropertySet aValueProp( xTmpValueSeq );
1865 0 : OUString aRole;
1866 0 : if( aValueProp.GetProperty( aRole, EXC_CHPROP_ROLE ) )
1867 : {
1868 0 : if( !xYValueSeq.is() && (aRole == EXC_CHPROP_ROLE_YVALUES) )
1869 : {
1870 0 : xYValueSeq = xTmpValueSeq;
1871 0 : if( !xTitleSeq.is() )
1872 0 : xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence
1873 : }
1874 0 : else if( !xXValueSeq.is() && !rTypeInfo.mbCategoryAxis && (aRole == EXC_CHPROP_ROLE_XVALUES) )
1875 : {
1876 0 : xXValueSeq = xTmpValueSeq;
1877 : }
1878 0 : else if( !xBubbleSeq.is() && (rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES) && (aRole == EXC_CHPROP_ROLE_SIZEVALUES) )
1879 : {
1880 0 : xBubbleSeq = xTmpValueSeq;
1881 0 : xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence
1882 : }
1883 : }
1884 0 : }
1885 :
1886 0 : bOk = xYValueSeq.is();
1887 0 : if( bOk )
1888 : {
1889 : // chart type group index
1890 0 : mnGroupIdx = nGroupIdx;
1891 :
1892 : // convert source links
1893 0 : maData.mnValueCount = mxValueLink->ConvertDataSequence( xYValueSeq, true );
1894 0 : mxTitleLink->ConvertDataSequence( xTitleSeq, true );
1895 :
1896 : // X values of XY charts
1897 0 : maData.mnCategCount = mxCategLink->ConvertDataSequence( xXValueSeq, false, maData.mnValueCount );
1898 :
1899 : // size values of bubble charts
1900 0 : if( mxBubbleLink )
1901 0 : mxBubbleLink->ConvertDataSequence( xBubbleSeq, false, maData.mnValueCount );
1902 :
1903 : // series formatting
1904 0 : XclChDataPointPos aPointPos( mnSeriesIdx );
1905 0 : ScfPropertySet aSeriesProp( xDataSeries );
1906 0 : mxSeriesFmt.reset( new XclExpChDataFormat( GetChRoot(), aPointPos, nFormatIdx ) );
1907 0 : mxSeriesFmt->ConvertDataSeries( aSeriesProp, rTypeInfo );
1908 :
1909 : // trend lines
1910 0 : CreateTrendLines( xDataSeries );
1911 :
1912 : // error bars
1913 0 : CreateErrorBars( aSeriesProp, EXC_CHPROP_ERRORBARX, EXC_CHSERERR_XPLUS, EXC_CHSERERR_XMINUS );
1914 0 : CreateErrorBars( aSeriesProp, EXC_CHPROP_ERRORBARY, EXC_CHSERERR_YPLUS, EXC_CHSERERR_YMINUS );
1915 :
1916 0 : if( maData.mnValueCount > 0 )
1917 : {
1918 0 : const sal_Int32 nMaxPointCount = maData.mnValueCount;
1919 :
1920 : /* #i91063# Create missing fill properties in pie/doughnut charts.
1921 : If freshly created (never saved to ODF), these charts show
1922 : varying point colors but do not return these points via API. */
1923 0 : if( xDiagram.is() && (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE) )
1924 : {
1925 0 : Reference< XColorScheme > xColorScheme = xDiagram->getDefaultColorScheme();
1926 0 : if( xColorScheme.is() )
1927 : {
1928 0 : const OUString aFillStyleName = "FillStyle";
1929 0 : const OUString aColorName = "Color";
1930 : namespace cssd = ::com::sun::star::drawing;
1931 0 : for( sal_Int32 nPointIdx = 0; nPointIdx < nMaxPointCount; ++nPointIdx )
1932 : {
1933 0 : aPointPos.mnPointIdx = static_cast< sal_uInt16 >( nPointIdx );
1934 0 : ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, nPointIdx );
1935 : // test that the point fill style is solid, but no color is set
1936 0 : cssd::FillStyle eFillStyle = cssd::FillStyle_NONE;
1937 0 : if( aPointProp.GetProperty( eFillStyle, aFillStyleName ) &&
1938 0 : (eFillStyle == cssd::FillStyle_SOLID) &&
1939 0 : !aPointProp.HasProperty( aColorName ) )
1940 : {
1941 0 : aPointProp.SetProperty( aColorName, xColorScheme->getColorByIndex( nPointIdx ) );
1942 : }
1943 0 : }
1944 0 : }
1945 : }
1946 :
1947 : // data point formatting
1948 0 : Sequence< sal_Int32 > aPointIndexes;
1949 0 : if( aSeriesProp.GetProperty( aPointIndexes, EXC_CHPROP_ATTRIBDATAPOINTS ) && aPointIndexes.hasElements() )
1950 : {
1951 0 : const sal_Int32* pnBeg = aPointIndexes.getConstArray();
1952 0 : const sal_Int32* pnEnd = pnBeg + aPointIndexes.getLength();
1953 0 : for( const sal_Int32* pnIt = pnBeg; (pnIt != pnEnd) && (*pnIt < nMaxPointCount); ++pnIt )
1954 : {
1955 0 : aPointPos.mnPointIdx = static_cast< sal_uInt16 >( *pnIt );
1956 0 : ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, *pnIt );
1957 0 : XclExpChDataFormatRef xPointFmt( new XclExpChDataFormat( GetChRoot(), aPointPos, nFormatIdx ) );
1958 0 : xPointFmt->ConvertDataSeries( aPointProp, rTypeInfo );
1959 0 : maPointFmts.AppendRecord( xPointFmt );
1960 0 : }
1961 0 : }
1962 0 : }
1963 0 : }
1964 : }
1965 0 : return bOk;
1966 : }
1967 :
1968 0 : bool XclExpChSeries::ConvertStockSeries( XDataSeriesRef xDataSeries,
1969 : const OUString& rValueRole, sal_uInt16 nGroupIdx, sal_uInt16 nFormatIdx, bool bCloseSymbol )
1970 : {
1971 0 : bool bOk = false;
1972 0 : Reference< XDataSource > xDataSource( xDataSeries, UNO_QUERY );
1973 0 : if( xDataSource.is() )
1974 : {
1975 0 : Reference< XDataSequence > xYValueSeq, xTitleSeq;
1976 :
1977 : // find first sequence with passed role
1978 0 : Sequence< Reference< XLabeledDataSequence > > aLabeledSeqVec = xDataSource->getDataSequences();
1979 0 : const Reference< XLabeledDataSequence >* pBeg = aLabeledSeqVec.getConstArray();
1980 0 : const Reference< XLabeledDataSequence >* pEnd = pBeg + aLabeledSeqVec.getLength();
1981 0 : for( const Reference< XLabeledDataSequence >* pIt = pBeg; !xYValueSeq.is() && (pIt != pEnd); ++pIt )
1982 : {
1983 0 : Reference< XDataSequence > xTmpValueSeq = (*pIt)->getValues();
1984 0 : ScfPropertySet aValueProp( xTmpValueSeq );
1985 0 : OUString aRole;
1986 0 : if( aValueProp.GetProperty( aRole, EXC_CHPROP_ROLE ) && (aRole == rValueRole) )
1987 : {
1988 0 : xYValueSeq = xTmpValueSeq;
1989 0 : xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence
1990 : }
1991 0 : }
1992 :
1993 0 : bOk = xYValueSeq.is();
1994 0 : if( bOk )
1995 : {
1996 : // chart type group index
1997 0 : mnGroupIdx = nGroupIdx;
1998 : // convert source links
1999 0 : maData.mnValueCount = mxValueLink->ConvertDataSequence( xYValueSeq, true );
2000 0 : mxTitleLink->ConvertDataSequence( xTitleSeq, true );
2001 : // series formatting
2002 0 : ScfPropertySet aSeriesProp( xDataSeries );
2003 0 : mxSeriesFmt.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx ), nFormatIdx ) );
2004 0 : mxSeriesFmt->ConvertStockSeries( aSeriesProp, bCloseSymbol );
2005 0 : }
2006 : }
2007 0 : return bOk;
2008 : }
2009 :
2010 0 : bool XclExpChSeries::ConvertTrendLine( const XclExpChSeries& rParent, Reference< XRegressionCurve > xRegCurve )
2011 : {
2012 0 : InitFromParent( rParent );
2013 :
2014 0 : mxTrendLine.reset( new XclExpChSerTrendLine( GetChRoot() ) );
2015 0 : bool bOk = mxTrendLine->Convert( xRegCurve, mnSeriesIdx );
2016 0 : if( bOk )
2017 : {
2018 0 : OUString aName;
2019 0 : ScfPropertySet aProperties( xRegCurve );
2020 0 : aProperties.GetProperty(aName, EXC_CHPROP_CURVENAME);
2021 0 : mxTitleLink->ConvertString(aName);
2022 :
2023 0 : mxSeriesFmt = mxTrendLine->GetDataFormat();
2024 0 : GetChartData().SetDataLabel( mxTrendLine->GetDataLabel() );
2025 : }
2026 0 : return bOk;
2027 : }
2028 :
2029 0 : bool XclExpChSeries::ConvertErrorBar( const XclExpChSeries& rParent, const ScfPropertySet& rPropSet, sal_uInt8 nBarId )
2030 : {
2031 0 : InitFromParent( rParent );
2032 : // error bar settings
2033 0 : mxErrorBar.reset( new XclExpChSerErrorBar( GetChRoot(), nBarId ) );
2034 0 : bool bOk = mxErrorBar->Convert( *mxValueLink, maData.mnValueCount, rPropSet );
2035 0 : if( bOk )
2036 : {
2037 : // error bar formatting
2038 0 : mxSeriesFmt.reset( new XclExpChDataFormat( GetChRoot(), XclChDataPointPos( mnSeriesIdx ), 0 ) );
2039 0 : mxSeriesFmt->ConvertLine( rPropSet, EXC_CHOBJTYPE_ERRORBAR );
2040 : }
2041 0 : return bOk;
2042 : }
2043 :
2044 0 : void XclExpChSeries::ConvertCategSequence( Reference< XLabeledDataSequence > xCategSeq )
2045 : {
2046 0 : if( xCategSeq.is() )
2047 0 : maData.mnCategCount = mxCategLink->ConvertDataSequence( xCategSeq->getValues(), false );
2048 0 : }
2049 :
2050 0 : void XclExpChSeries::WriteSubRecords( XclExpStream& rStrm )
2051 : {
2052 0 : lclSaveRecord( rStrm, mxTitleLink );
2053 0 : lclSaveRecord( rStrm, mxValueLink );
2054 0 : lclSaveRecord( rStrm, mxCategLink );
2055 0 : lclSaveRecord( rStrm, mxBubbleLink );
2056 0 : lclSaveRecord( rStrm, mxSeriesFmt );
2057 0 : maPointFmts.Save( rStrm );
2058 0 : if( mnGroupIdx != EXC_CHSERGROUP_NONE )
2059 0 : XclExpUInt16Record( EXC_ID_CHSERGROUP, mnGroupIdx ).Save( rStrm );
2060 0 : if( mnParentIdx != EXC_CHSERIES_INVALID )
2061 0 : XclExpUInt16Record( EXC_ID_CHSERPARENT, mnParentIdx ).Save( rStrm );
2062 0 : lclSaveRecord( rStrm, mxTrendLine );
2063 0 : lclSaveRecord( rStrm, mxErrorBar );
2064 0 : }
2065 :
2066 0 : void XclExpChSeries::InitFromParent( const XclExpChSeries& rParent )
2067 : {
2068 : // index to parent series is stored 1-based
2069 0 : mnParentIdx = rParent.mnSeriesIdx + 1;
2070 : /* #i86465# MSO2007 SP1 expects correct point counts in child series
2071 : (there was no problem in Excel2003 or Excel2007 without SP1...) */
2072 0 : maData.mnCategCount = rParent.maData.mnCategCount;
2073 0 : maData.mnValueCount = rParent.maData.mnValueCount;
2074 0 : }
2075 :
2076 0 : void XclExpChSeries::CreateTrendLines( XDataSeriesRef xDataSeries )
2077 : {
2078 0 : Reference< XRegressionCurveContainer > xRegCurveCont( xDataSeries, UNO_QUERY );
2079 0 : if( xRegCurveCont.is() )
2080 : {
2081 0 : Sequence< Reference< XRegressionCurve > > aRegCurveSeq = xRegCurveCont->getRegressionCurves();
2082 0 : const Reference< XRegressionCurve >* pBeg = aRegCurveSeq.getConstArray();
2083 0 : const Reference< XRegressionCurve >* pEnd = pBeg + aRegCurveSeq.getLength();
2084 0 : for( const Reference< XRegressionCurve >* pIt = pBeg; pIt != pEnd; ++pIt )
2085 : {
2086 0 : XclExpChSeriesRef xSeries = GetChartData().CreateSeries();
2087 0 : if( xSeries && !xSeries->ConvertTrendLine( *this, *pIt ) )
2088 0 : GetChartData().RemoveLastSeries();
2089 0 : }
2090 0 : }
2091 0 : }
2092 :
2093 0 : void XclExpChSeries::CreateErrorBars( const ScfPropertySet& rPropSet,
2094 : const OUString& rBarPropName, sal_uInt8 nPosBarId, sal_uInt8 nNegBarId )
2095 : {
2096 0 : Reference< XPropertySet > xErrorBar;
2097 0 : if( rPropSet.GetProperty( xErrorBar, rBarPropName ) && xErrorBar.is() )
2098 : {
2099 0 : ScfPropertySet aErrorProp( xErrorBar );
2100 0 : CreateErrorBar( aErrorProp, EXC_CHPROP_SHOWPOSITIVEERROR, nPosBarId );
2101 0 : CreateErrorBar( aErrorProp, EXC_CHPROP_SHOWNEGATIVEERROR, nNegBarId );
2102 0 : }
2103 0 : }
2104 :
2105 0 : void XclExpChSeries::CreateErrorBar( const ScfPropertySet& rPropSet,
2106 : const OUString& rShowPropName, sal_uInt8 nBarId )
2107 : {
2108 0 : if( rPropSet.GetBoolProperty( rShowPropName ) )
2109 : {
2110 0 : XclExpChSeriesRef xSeries = GetChartData().CreateSeries();
2111 0 : if( xSeries && !xSeries->ConvertErrorBar( *this, rPropSet, nBarId ) )
2112 0 : GetChartData().RemoveLastSeries();
2113 : }
2114 0 : }
2115 :
2116 0 : void XclExpChSeries::WriteBody( XclExpStream& rStrm )
2117 : {
2118 0 : rStrm << maData.mnCategType << maData.mnValueType << maData.mnCategCount << maData.mnValueCount;
2119 0 : if( GetBiff() == EXC_BIFF8 )
2120 0 : rStrm << maData.mnBubbleType << maData.mnBubbleCount;
2121 0 : }
2122 :
2123 : // Chart type groups ==========================================================
2124 :
2125 0 : XclExpChType::XclExpChType( const XclExpChRoot& rRoot ) :
2126 : XclExpRecord( EXC_ID_CHUNKNOWN ),
2127 : XclExpChRoot( rRoot ),
2128 0 : maTypeInfo( rRoot.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN ) )
2129 : {
2130 0 : }
2131 :
2132 0 : void XclExpChType::Convert( Reference< XDiagram > xDiagram, Reference< XChartType > xChartType,
2133 : sal_Int32 nApiAxesSetIdx, bool bSwappedAxesSet, bool bHasXLabels )
2134 : {
2135 0 : if( xChartType.is() )
2136 : {
2137 0 : maTypeInfo = GetChartTypeInfo( xChartType->getChartType() );
2138 : // special handling for some chart types
2139 0 : switch( maTypeInfo.meTypeCateg )
2140 : {
2141 : case EXC_CHTYPECATEG_BAR:
2142 : {
2143 0 : maTypeInfo = GetChartTypeInfo( bSwappedAxesSet ? EXC_CHTYPEID_HORBAR : EXC_CHTYPEID_BAR );
2144 0 : ::set_flag( maData.mnFlags, EXC_CHBAR_HORIZONTAL, bSwappedAxesSet );
2145 0 : ScfPropertySet aTypeProp( xChartType );
2146 0 : Sequence< sal_Int32 > aInt32Seq;
2147 0 : maData.mnOverlap = 0;
2148 0 : if( aTypeProp.GetProperty( aInt32Seq, EXC_CHPROP_OVERLAPSEQ ) && (nApiAxesSetIdx < aInt32Seq.getLength()) )
2149 0 : maData.mnOverlap = limit_cast< sal_Int16 >( -aInt32Seq[ nApiAxesSetIdx ], -100, 100 );
2150 0 : maData.mnGap = 150;
2151 0 : if( aTypeProp.GetProperty( aInt32Seq, EXC_CHPROP_GAPWIDTHSEQ ) && (nApiAxesSetIdx < aInt32Seq.getLength()) )
2152 0 : maData.mnGap = limit_cast< sal_uInt16 >( aInt32Seq[ nApiAxesSetIdx ], 0, 500 );
2153 : }
2154 0 : break;
2155 : case EXC_CHTYPECATEG_RADAR:
2156 0 : ::set_flag( maData.mnFlags, EXC_CHRADAR_AXISLABELS, bHasXLabels );
2157 0 : break;
2158 : case EXC_CHTYPECATEG_PIE:
2159 : {
2160 0 : ScfPropertySet aTypeProp( xChartType );
2161 0 : bool bDonut = aTypeProp.GetBoolProperty( EXC_CHPROP_USERINGS );
2162 0 : maTypeInfo = GetChartTypeInfo( bDonut ? EXC_CHTYPEID_DONUT : EXC_CHTYPEID_PIE );
2163 0 : maData.mnPieHole = bDonut ? 50 : 0;
2164 : // #i85166# starting angle of first pie slice
2165 0 : ScfPropertySet aDiaProp( xDiagram );
2166 0 : maData.mnRotation = XclExpChRoot::ConvertPieRotation( aDiaProp );
2167 : }
2168 0 : break;
2169 : case EXC_CHTYPECATEG_SCATTER:
2170 0 : if( GetBiff() == EXC_BIFF8 )
2171 0 : ::set_flag( maData.mnFlags, EXC_CHSCATTER_BUBBLES, maTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES );
2172 0 : break;
2173 : default:;
2174 : }
2175 0 : SetRecId( maTypeInfo.mnRecId );
2176 : }
2177 0 : }
2178 :
2179 0 : void XclExpChType::SetStacked( bool bPercent )
2180 : {
2181 0 : switch( maTypeInfo.meTypeCateg )
2182 : {
2183 : case EXC_CHTYPECATEG_LINE:
2184 0 : ::set_flag( maData.mnFlags, EXC_CHLINE_STACKED );
2185 0 : ::set_flag( maData.mnFlags, EXC_CHLINE_PERCENT, bPercent );
2186 0 : break;
2187 : case EXC_CHTYPECATEG_BAR:
2188 0 : ::set_flag( maData.mnFlags, EXC_CHBAR_STACKED );
2189 0 : ::set_flag( maData.mnFlags, EXC_CHBAR_PERCENT, bPercent );
2190 0 : maData.mnOverlap = -100;
2191 0 : break;
2192 : default:;
2193 : }
2194 0 : }
2195 :
2196 0 : void XclExpChType::WriteBody( XclExpStream& rStrm )
2197 : {
2198 0 : switch( GetRecId() )
2199 : {
2200 : case EXC_ID_CHBAR:
2201 0 : rStrm << maData.mnOverlap << maData.mnGap << maData.mnFlags;
2202 0 : break;
2203 :
2204 : case EXC_ID_CHLINE:
2205 : case EXC_ID_CHAREA:
2206 : case EXC_ID_CHRADARLINE:
2207 : case EXC_ID_CHRADARAREA:
2208 0 : rStrm << maData.mnFlags;
2209 0 : break;
2210 :
2211 : case EXC_ID_CHPIE:
2212 0 : rStrm << maData.mnRotation << maData.mnPieHole;
2213 0 : if( GetBiff() == EXC_BIFF8 )
2214 0 : rStrm << maData.mnFlags;
2215 0 : break;
2216 :
2217 : case EXC_ID_CHSCATTER:
2218 0 : if( GetBiff() == EXC_BIFF8 )
2219 0 : rStrm << maData.mnBubbleSize << maData.mnBubbleType << maData.mnFlags;
2220 0 : break;
2221 :
2222 : default:
2223 : OSL_FAIL( "XclExpChType::WriteBody - unknown chart type" );
2224 : }
2225 0 : }
2226 :
2227 0 : XclExpChChart3d::XclExpChChart3d() :
2228 0 : XclExpRecord( EXC_ID_CHCHART3D, 14 )
2229 : {
2230 0 : }
2231 :
2232 0 : void XclExpChChart3d::Convert( const ScfPropertySet& rPropSet, bool b3dWallChart )
2233 : {
2234 0 : sal_Int32 nRotationY = 0;
2235 0 : rPropSet.GetProperty( nRotationY, EXC_CHPROP_ROTATIONVERTICAL );
2236 0 : sal_Int32 nRotationX = 0;
2237 0 : rPropSet.GetProperty( nRotationX, EXC_CHPROP_ROTATIONHORIZONTAL );
2238 0 : sal_Int32 nPerspective = 15;
2239 0 : rPropSet.GetProperty( nPerspective, EXC_CHPROP_PERSPECTIVE );
2240 :
2241 0 : if( b3dWallChart )
2242 : {
2243 : // Y rotation (Excel [0..359], Chart2 [-179,180])
2244 0 : if( nRotationY < 0 ) nRotationY += 360;
2245 0 : maData.mnRotation = static_cast< sal_uInt16 >( nRotationY );
2246 : // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2247 0 : maData.mnElevation = limit_cast< sal_Int16 >( nRotationX, -90, 90 );
2248 : // perspective (Excel and Chart2 [0,100])
2249 0 : maData.mnEyeDist = limit_cast< sal_uInt16 >( nPerspective, 0, 100 );
2250 : // flags
2251 0 : maData.mnFlags = 0;
2252 0 : ::set_flag( maData.mnFlags, EXC_CHCHART3D_REAL3D, !rPropSet.GetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES ) );
2253 0 : ::set_flag( maData.mnFlags, EXC_CHCHART3D_AUTOHEIGHT );
2254 0 : ::set_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS );
2255 : }
2256 : else
2257 : {
2258 : // Y rotation not used in pie charts, but 'first pie slice angle'
2259 0 : maData.mnRotation = XclExpChRoot::ConvertPieRotation( rPropSet );
2260 : // X rotation a.k.a. elevation (map Chart2 [-80,-10] to Excel [10..80])
2261 0 : maData.mnElevation = limit_cast< sal_Int16 >( (nRotationX + 270) % 180, 10, 80 );
2262 : // perspective (Excel and Chart2 [0,100])
2263 0 : maData.mnEyeDist = limit_cast< sal_uInt16 >( nPerspective, 0, 100 );
2264 : // flags
2265 0 : maData.mnFlags = 0;
2266 : }
2267 0 : }
2268 :
2269 0 : void XclExpChChart3d::WriteBody( XclExpStream& rStrm )
2270 : {
2271 0 : rStrm << maData.mnRotation
2272 0 : << maData.mnElevation
2273 0 : << maData.mnEyeDist
2274 0 : << maData.mnRelHeight
2275 0 : << maData.mnRelDepth
2276 0 : << maData.mnDepthGap
2277 0 : << maData.mnFlags;
2278 0 : }
2279 :
2280 0 : XclExpChLegend::XclExpChLegend( const XclExpChRoot& rRoot ) :
2281 0 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_LEGEND, EXC_ID_CHLEGEND, 20 )
2282 : {
2283 0 : }
2284 :
2285 0 : void XclExpChLegend::Convert( const ScfPropertySet& rPropSet )
2286 : {
2287 : // frame properties
2288 0 : mxFrame = lclCreateFrame( GetChRoot(), rPropSet, EXC_CHOBJTYPE_LEGEND );
2289 : // text properties
2290 0 : mxText.reset( new XclExpChText( GetChRoot() ) );
2291 0 : mxText->ConvertLegend( rPropSet );
2292 :
2293 : // legend position and size
2294 0 : Any aRelPosAny, aRelSizeAny;
2295 0 : rPropSet.GetAnyProperty( aRelPosAny, EXC_CHPROP_RELATIVEPOSITION );
2296 0 : rPropSet.GetAnyProperty( aRelSizeAny, EXC_CHPROP_RELATIVESIZE );
2297 0 : cssc::ChartLegendExpansion eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2298 0 : rPropSet.GetProperty( eApiExpand, EXC_CHPROP_EXPANSION );
2299 0 : if( aRelPosAny.has< RelativePosition >() || ((eApiExpand == cssc::ChartLegendExpansion_CUSTOM) && aRelSizeAny.has< RelativeSize >()) )
2300 : {
2301 : try
2302 : {
2303 : /* The 'RelativePosition' or 'RelativeSize' properties are used as
2304 : indicator of manually changed legend position/size, but due to
2305 : the different anchor modes used by this property (in the
2306 : RelativePosition.Anchor member) it cannot be used to calculate
2307 : the position easily. For this, the Chart1 API will be used
2308 : instead. */
2309 0 : Reference< cssc::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
2310 0 : Reference< XShape > xChart1Legend( xChart1Doc->getLegend(), UNO_SET_THROW );
2311 : // coordinates in CHLEGEND record written but not used by Excel
2312 0 : mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_CHARTSIZE, EXC_CHFRAMEPOS_PARENT ) );
2313 0 : XclChFramePos& rFramePos = mxFramePos->GetFramePosData();
2314 0 : rFramePos.mnTLMode = EXC_CHFRAMEPOS_CHARTSIZE;
2315 0 : ::com::sun::star::awt::Point aLegendPos = xChart1Legend->getPosition();
2316 0 : rFramePos.maRect.mnX = maData.maRect.mnX = CalcChartXFromHmm( aLegendPos.X );
2317 0 : rFramePos.maRect.mnY = maData.maRect.mnY = CalcChartYFromHmm( aLegendPos.Y );
2318 : // legend size, Excel expects points in CHFRAMEPOS record
2319 0 : rFramePos.mnBRMode = EXC_CHFRAMEPOS_ABSSIZE_POINTS;
2320 0 : ::com::sun::star::awt::Size aLegendSize = xChart1Legend->getSize();
2321 0 : rFramePos.maRect.mnWidth = static_cast< sal_uInt16 >( aLegendSize.Width * EXC_POINTS_PER_HMM + 0.5 );
2322 0 : rFramePos.maRect.mnHeight = static_cast< sal_uInt16 >( aLegendSize.Height * EXC_POINTS_PER_HMM + 0.5 );
2323 0 : maData.maRect.mnWidth = CalcChartXFromHmm( aLegendSize.Width );
2324 0 : maData.maRect.mnHeight = CalcChartYFromHmm( aLegendSize.Height );
2325 0 : eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2326 : // manual legend position implies manual plot area
2327 0 : GetChartData().SetManualPlotArea();
2328 0 : maData.mnDockMode = EXC_CHLEGEND_NOTDOCKED;
2329 : // a CHFRAME record with cleared auto flags is needed
2330 0 : if( !mxFrame )
2331 0 : mxFrame.reset( new XclExpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
2332 0 : mxFrame->SetAutoFlags( false, false );
2333 : }
2334 0 : catch( Exception& )
2335 : {
2336 : OSL_FAIL( "XclExpChLegend::Convert - cannot get legend shape" );
2337 0 : maData.mnDockMode = EXC_CHLEGEND_RIGHT;
2338 0 : eApiExpand = cssc::ChartLegendExpansion_HIGH;
2339 : }
2340 : }
2341 : else
2342 : {
2343 0 : cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM;
2344 0 : rPropSet.GetProperty( eApiPos, EXC_CHPROP_ANCHORPOSITION );
2345 0 : switch( eApiPos )
2346 : {
2347 0 : case cssc2::LegendPosition_LINE_START: maData.mnDockMode = EXC_CHLEGEND_LEFT; break;
2348 0 : case cssc2::LegendPosition_LINE_END: maData.mnDockMode = EXC_CHLEGEND_RIGHT; break;
2349 0 : case cssc2::LegendPosition_PAGE_START: maData.mnDockMode = EXC_CHLEGEND_TOP; break;
2350 0 : case cssc2::LegendPosition_PAGE_END: maData.mnDockMode = EXC_CHLEGEND_BOTTOM; break;
2351 : default:
2352 : OSL_FAIL( "XclExpChLegend::Convert - unrecognized legend position" );
2353 0 : maData.mnDockMode = EXC_CHLEGEND_RIGHT;
2354 0 : eApiExpand = cssc::ChartLegendExpansion_HIGH;
2355 : }
2356 : }
2357 0 : ::set_flag( maData.mnFlags, EXC_CHLEGEND_STACKED, eApiExpand == cssc::ChartLegendExpansion_HIGH );
2358 :
2359 : // other flags
2360 0 : ::set_flag( maData.mnFlags, EXC_CHLEGEND_AUTOSERIES );
2361 0 : const sal_uInt16 nAutoFlags = EXC_CHLEGEND_DOCKED | EXC_CHLEGEND_AUTOPOSX | EXC_CHLEGEND_AUTOPOSY;
2362 0 : ::set_flag( maData.mnFlags, nAutoFlags, maData.mnDockMode != EXC_CHLEGEND_NOTDOCKED );
2363 0 : }
2364 :
2365 0 : void XclExpChLegend::WriteSubRecords( XclExpStream& rStrm )
2366 : {
2367 0 : lclSaveRecord( rStrm, mxFramePos );
2368 0 : lclSaveRecord( rStrm, mxText );
2369 0 : lclSaveRecord( rStrm, mxFrame );
2370 0 : }
2371 :
2372 0 : void XclExpChLegend::WriteBody( XclExpStream& rStrm )
2373 : {
2374 0 : rStrm << maData.maRect << maData.mnDockMode << maData.mnSpacing << maData.mnFlags;
2375 0 : }
2376 :
2377 0 : XclExpChDropBar::XclExpChDropBar( const XclExpChRoot& rRoot, XclChObjectType eObjType ) :
2378 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_DROPBAR, EXC_ID_CHDROPBAR, 2 ),
2379 : meObjType( eObjType ),
2380 0 : mnBarDist( 100 )
2381 : {
2382 0 : }
2383 :
2384 0 : void XclExpChDropBar::Convert( const ScfPropertySet& rPropSet )
2385 : {
2386 0 : if( rPropSet.Is() )
2387 0 : ConvertFrameBase( GetChRoot(), rPropSet, meObjType );
2388 : else
2389 0 : SetDefaultFrameBase( GetChRoot(), EXC_CHFRAMETYPE_INVISIBLE, true );
2390 0 : }
2391 :
2392 0 : void XclExpChDropBar::WriteSubRecords( XclExpStream& rStrm )
2393 : {
2394 0 : WriteFrameRecords( rStrm );
2395 0 : }
2396 :
2397 0 : void XclExpChDropBar::WriteBody( XclExpStream& rStrm )
2398 : {
2399 0 : rStrm << mnBarDist;
2400 0 : }
2401 :
2402 0 : XclExpChTypeGroup::XclExpChTypeGroup( const XclExpChRoot& rRoot, sal_uInt16 nGroupIdx ) :
2403 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_TYPEGROUP, EXC_ID_CHTYPEGROUP, 20 ),
2404 : maType( rRoot ),
2405 0 : maTypeInfo( maType.GetTypeInfo() )
2406 : {
2407 0 : maData.mnGroupIdx = nGroupIdx;
2408 0 : }
2409 :
2410 0 : void XclExpChTypeGroup::ConvertType(
2411 : Reference< XDiagram > xDiagram, Reference< XChartType > xChartType,
2412 : sal_Int32 nApiAxesSetIdx, bool b3dChart, bool bSwappedAxesSet, bool bHasXLabels )
2413 : {
2414 : // chart type settings
2415 0 : maType.Convert( xDiagram, xChartType, nApiAxesSetIdx, bSwappedAxesSet, bHasXLabels );
2416 :
2417 : // spline - TODO: get from single series (#i66858#)
2418 0 : ScfPropertySet aTypeProp( xChartType );
2419 : cssc2::CurveStyle eCurveStyle;
2420 0 : bool bSpline = aTypeProp.GetProperty( eCurveStyle, EXC_CHPROP_CURVESTYLE ) &&
2421 0 : (eCurveStyle != cssc2::CurveStyle_LINES);
2422 :
2423 : // extended type info
2424 0 : maTypeInfo.Set( maType.GetTypeInfo(), b3dChart, bSpline );
2425 :
2426 : // 3d chart settings
2427 0 : if( maTypeInfo.mb3dChart ) // only true, if Excel chart supports 3d mode
2428 : {
2429 0 : mxChart3d.reset( new XclExpChChart3d );
2430 0 : ScfPropertySet aDiaProp( xDiagram );
2431 0 : mxChart3d->Convert( aDiaProp, Is3dWallChart() );
2432 0 : }
2433 0 : }
2434 :
2435 0 : void XclExpChTypeGroup::ConvertSeries(
2436 : Reference< XDiagram > xDiagram, Reference< XChartType > xChartType,
2437 : sal_Int32 nGroupAxesSetIdx, bool bPercent, bool bConnectBars )
2438 : {
2439 0 : Reference< XDataSeriesContainer > xSeriesCont( xChartType, UNO_QUERY );
2440 0 : if( xSeriesCont.is() )
2441 : {
2442 : typedef ::std::vector< Reference< XDataSeries > > XDataSeriesVec;
2443 0 : XDataSeriesVec aSeriesVec;
2444 :
2445 : // copy data series attached to the current axes set to the vector
2446 0 : Sequence< Reference< XDataSeries > > aSeriesSeq = xSeriesCont->getDataSeries();
2447 0 : const Reference< XDataSeries >* pBeg = aSeriesSeq.getConstArray();
2448 0 : const Reference< XDataSeries >* pEnd = pBeg + aSeriesSeq.getLength();
2449 0 : for( const Reference< XDataSeries >* pIt = pBeg; pIt != pEnd; ++pIt )
2450 : {
2451 0 : ScfPropertySet aSeriesProp( *pIt );
2452 0 : sal_Int32 nSeriesAxesSetIdx(0);
2453 0 : if( aSeriesProp.GetProperty( nSeriesAxesSetIdx, EXC_CHPROP_ATTAXISINDEX ) && (nSeriesAxesSetIdx == nGroupAxesSetIdx) )
2454 0 : aSeriesVec.push_back( *pIt );
2455 0 : }
2456 :
2457 : // Are there any series in the current axes set?
2458 0 : if( !aSeriesVec.empty() )
2459 : {
2460 : // stacking direction (stacked/percent/deep 3d) from first series
2461 0 : ScfPropertySet aSeriesProp( aSeriesVec.front() );
2462 : cssc2::StackingDirection eStacking;
2463 0 : if( !aSeriesProp.GetProperty( eStacking, EXC_CHPROP_STACKINGDIR ) )
2464 0 : eStacking = cssc2::StackingDirection_NO_STACKING;
2465 :
2466 : // stacked or percent chart
2467 0 : if( maTypeInfo.mbSupportsStacking && (eStacking == cssc2::StackingDirection_Y_STACKING) )
2468 : {
2469 : // percent overrides simple stacking
2470 0 : maType.SetStacked( bPercent );
2471 :
2472 : // connected data points (only in stacked bar charts)
2473 0 : if (bConnectBars && (maTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR))
2474 : {
2475 0 : sal_uInt16 nKey = EXC_CHCHARTLINE_CONNECT;
2476 0 : maChartLines.insert(nKey, new XclExpChLineFormat(GetChRoot()));
2477 0 : }
2478 : }
2479 : else
2480 : {
2481 : // reverse series order for some unstacked 2D chart types
2482 0 : if( maTypeInfo.mbReverseSeries && !Is3dChart() )
2483 0 : ::std::reverse( aSeriesVec.begin(), aSeriesVec.end() );
2484 : }
2485 :
2486 : // deep 3d chart or clustered 3d chart (stacked is not clustered)
2487 0 : if( (eStacking == cssc2::StackingDirection_NO_STACKING) && Is3dWallChart() )
2488 0 : mxChart3d->SetClustered();
2489 :
2490 : // varied point colors
2491 0 : ::set_flag( maData.mnFlags, EXC_CHTYPEGROUP_VARIEDCOLORS, aSeriesProp.GetBoolProperty( EXC_CHPROP_VARYCOLORSBY ) );
2492 :
2493 : // process all series
2494 0 : for( XDataSeriesVec::const_iterator aIt = aSeriesVec.begin(), aEnd = aSeriesVec.end(); aIt != aEnd; ++aIt )
2495 : {
2496 : // create Excel series object, stock charts need special processing
2497 0 : if( maTypeInfo.meTypeId == EXC_CHTYPEID_STOCK )
2498 0 : CreateAllStockSeries( xChartType, *aIt );
2499 : else
2500 0 : CreateDataSeries( xDiagram, *aIt );
2501 0 : }
2502 0 : }
2503 0 : }
2504 0 : }
2505 :
2506 0 : void XclExpChTypeGroup::ConvertCategSequence( Reference< XLabeledDataSequence > xCategSeq )
2507 : {
2508 0 : for( size_t nIdx = 0, nSize = maSeries.GetSize(); nIdx < nSize; ++nIdx )
2509 0 : maSeries.GetRecord( nIdx )->ConvertCategSequence( xCategSeq );
2510 0 : }
2511 :
2512 0 : void XclExpChTypeGroup::ConvertLegend( const ScfPropertySet& rPropSet )
2513 : {
2514 0 : if( rPropSet.GetBoolProperty( EXC_CHPROP_SHOW ) )
2515 : {
2516 0 : mxLegend.reset( new XclExpChLegend( GetChRoot() ) );
2517 0 : mxLegend->Convert( rPropSet );
2518 : }
2519 0 : }
2520 :
2521 0 : void XclExpChTypeGroup::WriteSubRecords( XclExpStream& rStrm )
2522 : {
2523 0 : maType.Save( rStrm );
2524 0 : lclSaveRecord( rStrm, mxChart3d );
2525 0 : lclSaveRecord( rStrm, mxLegend );
2526 0 : lclSaveRecord( rStrm, mxUpBar );
2527 0 : lclSaveRecord( rStrm, mxDownBar );
2528 0 : for( XclExpChLineFormatMap::iterator aLIt = maChartLines.begin(), aLEnd = maChartLines.end(); aLIt != aLEnd; ++aLIt )
2529 0 : lclSaveRecord( rStrm, aLIt->second, EXC_ID_CHCHARTLINE, aLIt->first );
2530 0 : }
2531 :
2532 0 : sal_uInt16 XclExpChTypeGroup::GetFreeFormatIdx() const
2533 : {
2534 0 : return static_cast< sal_uInt16 >( maSeries.GetSize() );
2535 : }
2536 :
2537 0 : void XclExpChTypeGroup::CreateDataSeries(
2538 : Reference< XDiagram > xDiagram, Reference< XDataSeries > xDataSeries )
2539 : {
2540 : // let chart create series object with correct series index
2541 0 : XclExpChSeriesRef xSeries = GetChartData().CreateSeries();
2542 0 : if( xSeries )
2543 : {
2544 0 : if( xSeries->ConvertDataSeries( xDiagram, xDataSeries, maTypeInfo, GetGroupIdx(), GetFreeFormatIdx() ) )
2545 0 : maSeries.AppendRecord( xSeries );
2546 : else
2547 0 : GetChartData().RemoveLastSeries();
2548 0 : }
2549 0 : }
2550 :
2551 0 : void XclExpChTypeGroup::CreateAllStockSeries(
2552 : Reference< XChartType > xChartType, Reference< XDataSeries > xDataSeries )
2553 : {
2554 : // create existing series objects
2555 0 : bool bHasOpen = CreateStockSeries( xDataSeries, EXC_CHPROP_ROLE_OPENVALUES, false );
2556 0 : bool bHasHigh = CreateStockSeries( xDataSeries, EXC_CHPROP_ROLE_HIGHVALUES, false );
2557 0 : bool bHasLow = CreateStockSeries( xDataSeries, EXC_CHPROP_ROLE_LOWVALUES, false );
2558 0 : bool bHasClose = CreateStockSeries( xDataSeries, EXC_CHPROP_ROLE_CLOSEVALUES, !bHasOpen );
2559 :
2560 : // formatting of special stock chart elements
2561 0 : ScfPropertySet aTypeProp( xChartType );
2562 : // hi-lo lines
2563 0 : if( bHasHigh && bHasLow && aTypeProp.GetBoolProperty( EXC_CHPROP_SHOWHIGHLOW ) )
2564 : {
2565 0 : ScfPropertySet aSeriesProp( xDataSeries );
2566 0 : XclExpChLineFormatRef xLineFmt( new XclExpChLineFormat( GetChRoot() ) );
2567 0 : xLineFmt->Convert( GetChRoot(), aSeriesProp, EXC_CHOBJTYPE_HILOLINE );
2568 0 : sal_uInt16 nKey = EXC_CHCHARTLINE_HILO;
2569 0 : maChartLines.insert(nKey, new XclExpChLineFormat(GetChRoot()));
2570 : }
2571 : // dropbars
2572 0 : if( bHasOpen && bHasClose )
2573 : {
2574 : // dropbar type is dependent on position in the file - always create both
2575 0 : Reference< XPropertySet > xWhitePropSet, xBlackPropSet;
2576 : // white dropbar format
2577 0 : aTypeProp.GetProperty( xWhitePropSet, EXC_CHPROP_WHITEDAY );
2578 0 : ScfPropertySet aWhiteProp( xWhitePropSet );
2579 0 : mxUpBar.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_WHITEDROPBAR ) );
2580 0 : mxUpBar->Convert( aWhiteProp );
2581 : // black dropbar format
2582 0 : aTypeProp.GetProperty( xBlackPropSet, EXC_CHPROP_BLACKDAY );
2583 0 : ScfPropertySet aBlackProp( xBlackPropSet );
2584 0 : mxDownBar.reset( new XclExpChDropBar( GetChRoot(), EXC_CHOBJTYPE_BLACKDROPBAR ) );
2585 0 : mxDownBar->Convert( aBlackProp );
2586 0 : }
2587 0 : }
2588 :
2589 0 : bool XclExpChTypeGroup::CreateStockSeries( Reference< XDataSeries > xDataSeries,
2590 : const OUString& rValueRole, bool bCloseSymbol )
2591 : {
2592 0 : bool bOk = false;
2593 : // let chart create series object with correct series index
2594 0 : XclExpChSeriesRef xSeries = GetChartData().CreateSeries();
2595 0 : if( xSeries )
2596 : {
2597 : bOk = xSeries->ConvertStockSeries( xDataSeries,
2598 0 : rValueRole, GetGroupIdx(), GetFreeFormatIdx(), bCloseSymbol );
2599 0 : if( bOk )
2600 0 : maSeries.AppendRecord( xSeries );
2601 : else
2602 0 : GetChartData().RemoveLastSeries();
2603 : }
2604 0 : return bOk;
2605 : }
2606 :
2607 0 : void XclExpChTypeGroup::WriteBody( XclExpStream& rStrm )
2608 : {
2609 0 : rStrm.WriteZeroBytes( 16 );
2610 0 : rStrm << maData.mnFlags << maData.mnGroupIdx;
2611 0 : }
2612 :
2613 : // Axes =======================================================================
2614 :
2615 0 : XclExpChLabelRange::XclExpChLabelRange( const XclExpChRoot& rRoot ) :
2616 : XclExpRecord( EXC_ID_CHLABELRANGE, 8 ),
2617 0 : XclExpChRoot( rRoot )
2618 : {
2619 0 : }
2620 :
2621 0 : void XclExpChLabelRange::Convert( const ScaleData& rScaleData, const ScfPropertySet& rChart1Axis, bool bMirrorOrient )
2622 : {
2623 : /* Base time unit (using the property 'ExplicitTimeIncrement' from the old
2624 : chart API allows to detect axis type (date axis, if property exists),
2625 : and to receive the base time unit currently used in case the base time
2626 : unit is set to 'automatic'. */
2627 0 : cssc::TimeIncrement aTimeIncrement;
2628 0 : if( rChart1Axis.GetProperty( aTimeIncrement, EXC_CHPROP_EXPTIMEINCREMENT ) )
2629 : {
2630 : // property exists -> this is a date axis currently
2631 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS );
2632 :
2633 : // automatic base time unit, if the UNO Any 'rScaleData.TimeIncrement.TimeResolution' does not contain a valid value...
2634 0 : bool bAutoBase = !rScaleData.TimeIncrement.TimeResolution.has< cssc::TimeIncrement >();
2635 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOBASE, bAutoBase );
2636 :
2637 : // ...but get the current base time unit from the property of the old chart API
2638 0 : sal_Int32 nApiTimeUnit = 0;
2639 0 : bool bValidBaseUnit = aTimeIncrement.TimeResolution >>= nApiTimeUnit;
2640 : OSL_ENSURE( bValidBaseUnit, "XclExpChLabelRange::Convert - cannot ghet base time unit" );
2641 0 : maDateData.mnBaseUnit = bValidBaseUnit ? lclGetTimeUnit( nApiTimeUnit ) : EXC_CHDATERANGE_DAYS;
2642 :
2643 : /* Min/max values depend on base time unit, they specify the number of
2644 : days, months, or years starting from null date. */
2645 0 : bool bAutoMin = lclConvertTimeValue( GetRoot(), maDateData.mnMinDate, rScaleData.Minimum, maDateData.mnBaseUnit );
2646 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMIN, bAutoMin );
2647 0 : bool bAutoMax = lclConvertTimeValue( GetRoot(), maDateData.mnMaxDate, rScaleData.Maximum, maDateData.mnBaseUnit );
2648 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAX, bAutoMax );
2649 : }
2650 :
2651 : // automatic axis type detection
2652 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTODATE, rScaleData.AutoDateAxis );
2653 :
2654 : // increment
2655 0 : bool bAutoMajor = lclConvertTimeInterval( maDateData.mnMajorStep, maDateData.mnMajorUnit, rScaleData.TimeIncrement.MajorTimeInterval );
2656 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAJOR, bAutoMajor );
2657 0 : bool bAutoMinor = lclConvertTimeInterval( maDateData.mnMinorStep, maDateData.mnMinorUnit, rScaleData.TimeIncrement.MinorTimeInterval );
2658 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMINOR, bAutoMinor );
2659 :
2660 : // origin
2661 0 : double fOrigin = 0.0;
2662 0 : if( !lclIsAutoAnyOrGetValue( fOrigin, rScaleData.Origin ) )
2663 0 : maLabelData.mnCross = limit_cast< sal_uInt16 >( fOrigin, 1, 31999 );
2664 :
2665 : // reverse order
2666 0 : if( (rScaleData.Orientation == cssc2::AxisOrientation_REVERSE) != bMirrorOrient )
2667 0 : ::set_flag( maLabelData.mnFlags, EXC_CHLABELRANGE_REVERSE );
2668 0 : }
2669 :
2670 0 : void XclExpChLabelRange::ConvertAxisPosition( const ScfPropertySet& rPropSet )
2671 : {
2672 0 : cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE;
2673 0 : rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION );
2674 0 : double fCrossingPos = 1.0;
2675 0 : rPropSet.GetProperty( fCrossingPos, EXC_CHPROP_CROSSOVERVALUE );
2676 :
2677 0 : bool bDateAxis = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS );
2678 0 : switch( eAxisPos )
2679 : {
2680 : case cssc::ChartAxisPosition_ZERO:
2681 : case cssc::ChartAxisPosition_START:
2682 0 : maLabelData.mnCross = 1;
2683 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOCROSS );
2684 0 : break;
2685 : case cssc::ChartAxisPosition_END:
2686 0 : ::set_flag( maLabelData.mnFlags, EXC_CHLABELRANGE_MAXCROSS );
2687 0 : break;
2688 : case cssc::ChartAxisPosition_VALUE:
2689 0 : maLabelData.mnCross = limit_cast< sal_uInt16 >( fCrossingPos, 1, 31999 );
2690 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOCROSS, false );
2691 0 : if( bDateAxis )
2692 0 : maDateData.mnCross = lclGetTimeValue( GetRoot(), fCrossingPos, maDateData.mnBaseUnit );
2693 0 : break;
2694 : default:
2695 0 : maLabelData.mnCross = 1;
2696 0 : ::set_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOCROSS );
2697 : }
2698 0 : }
2699 :
2700 0 : void XclExpChLabelRange::Save( XclExpStream& rStrm )
2701 : {
2702 : // the CHLABELRANGE record
2703 0 : XclExpRecord::Save( rStrm );
2704 :
2705 : // the CHDATERANGE record with date axis settings (BIFF8 only)
2706 0 : if( GetBiff() == EXC_BIFF8 )
2707 : {
2708 0 : rStrm.StartRecord( EXC_ID_CHDATERANGE, 18 );
2709 0 : rStrm << maDateData.mnMinDate
2710 0 : << maDateData.mnMaxDate
2711 0 : << maDateData.mnMajorStep
2712 0 : << maDateData.mnMajorUnit
2713 0 : << maDateData.mnMinorStep
2714 0 : << maDateData.mnMinorUnit
2715 0 : << maDateData.mnBaseUnit
2716 0 : << maDateData.mnCross
2717 0 : << maDateData.mnFlags;
2718 0 : rStrm.EndRecord();
2719 : }
2720 0 : }
2721 :
2722 0 : void XclExpChLabelRange::WriteBody( XclExpStream& rStrm )
2723 : {
2724 0 : rStrm << maLabelData.mnCross << maLabelData.mnLabelFreq << maLabelData.mnTickFreq << maLabelData.mnFlags;
2725 0 : }
2726 :
2727 0 : XclExpChValueRange::XclExpChValueRange( const XclExpChRoot& rRoot ) :
2728 : XclExpRecord( EXC_ID_CHVALUERANGE, 42 ),
2729 0 : XclExpChRoot( rRoot )
2730 : {
2731 0 : }
2732 :
2733 0 : void XclExpChValueRange::Convert( const ScaleData& rScaleData )
2734 : {
2735 : // scaling algorithm
2736 0 : bool bLogScale = ScfApiHelper::GetServiceName( rScaleData.Scaling ) == "com.sun.star.chart2.LogarithmicScaling";
2737 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE, bLogScale );
2738 :
2739 : // min/max
2740 0 : bool bAutoMin = lclIsAutoAnyOrGetScaledValue( maData.mfMin, rScaleData.Minimum, bLogScale );
2741 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN, bAutoMin );
2742 0 : bool bAutoMax = lclIsAutoAnyOrGetScaledValue( maData.mfMax, rScaleData.Maximum, bLogScale );
2743 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX, bAutoMax );
2744 :
2745 : // origin
2746 0 : bool bAutoCross = lclIsAutoAnyOrGetScaledValue( maData.mfCross, rScaleData.Origin, bLogScale );
2747 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS, bAutoCross );
2748 :
2749 : // major increment
2750 0 : const IncrementData& rIncrementData = rScaleData.IncrementData;
2751 0 : bool bAutoMajor = lclIsAutoAnyOrGetValue( maData.mfMajorStep, rIncrementData.Distance ) || (maData.mfMajorStep <= 0.0);
2752 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR, bAutoMajor );
2753 : // minor increment
2754 0 : const Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
2755 0 : sal_Int32 nCount = 0;
2756 0 : bool bAutoMinor = bLogScale || bAutoMajor || (rSubIncrementSeq.getLength() < 1) ||
2757 0 : lclIsAutoAnyOrGetValue( nCount, rSubIncrementSeq[ 0 ].IntervalCount ) || (nCount < 1);
2758 0 : if( !bAutoMinor )
2759 0 : maData.mfMinorStep = maData.mfMajorStep / nCount;
2760 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR, bAutoMinor );
2761 :
2762 : // reverse order
2763 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE, rScaleData.Orientation == cssc2::AxisOrientation_REVERSE );
2764 0 : }
2765 :
2766 0 : void XclExpChValueRange::ConvertAxisPosition( const ScfPropertySet& rPropSet )
2767 : {
2768 0 : cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE;
2769 0 : double fCrossingPos = 0.0;
2770 0 : if( rPropSet.GetProperty( eAxisPos, EXC_CHPROP_CROSSOVERPOSITION ) && rPropSet.GetProperty( fCrossingPos, EXC_CHPROP_CROSSOVERVALUE ) )
2771 : {
2772 0 : switch( eAxisPos )
2773 : {
2774 : case cssc::ChartAxisPosition_ZERO:
2775 : case cssc::ChartAxisPosition_START:
2776 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
2777 0 : break;
2778 : case cssc::ChartAxisPosition_END:
2779 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_MAXCROSS );
2780 0 : break;
2781 : case cssc::ChartAxisPosition_VALUE:
2782 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS, false );
2783 0 : maData.mfCross = ::get_flagvalue< double >( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE, log( fCrossingPos ) / log( 10.0 ), fCrossingPos );
2784 0 : break;
2785 : default:
2786 0 : ::set_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
2787 : }
2788 : }
2789 0 : }
2790 :
2791 0 : void XclExpChValueRange::WriteBody( XclExpStream& rStrm )
2792 : {
2793 0 : rStrm << maData.mfMin
2794 0 : << maData.mfMax
2795 0 : << maData.mfMajorStep
2796 0 : << maData.mfMinorStep
2797 0 : << maData.mfCross
2798 0 : << maData.mnFlags;
2799 0 : }
2800 :
2801 : namespace {
2802 :
2803 0 : sal_uInt8 lclGetXclTickPos( sal_Int32 nApiTickmarks )
2804 : {
2805 : using namespace cssc2::TickmarkStyle;
2806 0 : sal_uInt8 nXclTickPos = 0;
2807 0 : ::set_flag( nXclTickPos, EXC_CHTICK_INSIDE, ::get_flag( nApiTickmarks, INNER ) );
2808 0 : ::set_flag( nXclTickPos, EXC_CHTICK_OUTSIDE, ::get_flag( nApiTickmarks, OUTER ) );
2809 0 : return nXclTickPos;
2810 : }
2811 :
2812 : } // namespace
2813 :
2814 0 : XclExpChTick::XclExpChTick( const XclExpChRoot& rRoot ) :
2815 0 : XclExpRecord( EXC_ID_CHTICK, (rRoot.GetBiff() == EXC_BIFF8) ? 30 : 26 ),
2816 : XclExpChRoot( rRoot ),
2817 0 : mnTextColorId( XclExpPalette::GetColorIdFromIndex( EXC_COLOR_CHWINDOWTEXT ) )
2818 : {
2819 0 : }
2820 :
2821 0 : void XclExpChTick::Convert( const ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo, sal_uInt16 nAxisType )
2822 : {
2823 : // tick mark style
2824 0 : sal_Int32 nApiTickmarks = 0;
2825 0 : if( rPropSet.GetProperty( nApiTickmarks, EXC_CHPROP_MAJORTICKS ) )
2826 0 : maData.mnMajor = lclGetXclTickPos( nApiTickmarks );
2827 0 : if( rPropSet.GetProperty( nApiTickmarks, EXC_CHPROP_MINORTICKS ) )
2828 0 : maData.mnMinor = lclGetXclTickPos( nApiTickmarks );
2829 :
2830 : // axis labels
2831 0 : if( (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR) && (nAxisType == EXC_CHAXIS_X) )
2832 : {
2833 : /* Radar charts disable their category labels via chart type, not via
2834 : axis, and axis labels are always 'near axis'. */
2835 0 : maData.mnLabelPos = EXC_CHTICK_NEXT;
2836 : }
2837 0 : else if( !rPropSet.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS ) )
2838 : {
2839 : // no labels
2840 0 : maData.mnLabelPos = EXC_CHTICK_NOLABEL;
2841 : }
2842 0 : else if( rTypeInfo.mb3dChart && (nAxisType == EXC_CHAXIS_Y) )
2843 : {
2844 : // Excel expects 'near axis' at Y axes in 3D charts
2845 0 : maData.mnLabelPos = EXC_CHTICK_NEXT;
2846 : }
2847 : else
2848 : {
2849 0 : cssc::ChartAxisLabelPosition eApiLabelPos = cssc::ChartAxisLabelPosition_NEAR_AXIS;
2850 0 : rPropSet.GetProperty( eApiLabelPos, EXC_CHPROP_LABELPOSITION );
2851 0 : switch( eApiLabelPos )
2852 : {
2853 : case cssc::ChartAxisLabelPosition_NEAR_AXIS:
2854 0 : case cssc::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE: maData.mnLabelPos = EXC_CHTICK_NEXT; break;
2855 0 : case cssc::ChartAxisLabelPosition_OUTSIDE_START: maData.mnLabelPos = EXC_CHTICK_LOW; break;
2856 0 : case cssc::ChartAxisLabelPosition_OUTSIDE_END: maData.mnLabelPos = EXC_CHTICK_HIGH; break;
2857 0 : default: maData.mnLabelPos = EXC_CHTICK_NEXT;
2858 : }
2859 : }
2860 0 : }
2861 :
2862 0 : void XclExpChTick::SetFontColor( const Color& rColor, sal_uInt32 nColorId )
2863 : {
2864 0 : maData.maTextColor = rColor;
2865 0 : ::set_flag( maData.mnFlags, EXC_CHTICK_AUTOCOLOR, rColor == COL_AUTO );
2866 0 : mnTextColorId = nColorId;
2867 0 : }
2868 :
2869 0 : void XclExpChTick::SetRotation( sal_uInt16 nRotation )
2870 : {
2871 0 : maData.mnRotation = nRotation;
2872 0 : ::set_flag( maData.mnFlags, EXC_CHTICK_AUTOROT, false );
2873 0 : ::insert_value( maData.mnFlags, XclTools::GetXclOrientFromRot( nRotation ), 2, 3 );
2874 0 : }
2875 :
2876 0 : void XclExpChTick::WriteBody( XclExpStream& rStrm )
2877 : {
2878 0 : rStrm << maData.mnMajor
2879 0 : << maData.mnMinor
2880 0 : << maData.mnLabelPos
2881 0 : << maData.mnBackMode;
2882 0 : rStrm.WriteZeroBytes( 16 );
2883 0 : rStrm << maData.maTextColor
2884 0 : << maData.mnFlags;
2885 0 : if( GetBiff() == EXC_BIFF8 )
2886 0 : rStrm << GetPalette().GetColorIndex( mnTextColorId ) << maData.mnRotation;
2887 0 : }
2888 :
2889 : namespace {
2890 :
2891 : /** Returns an API axis object from the passed coordinate system. */
2892 0 : Reference< XAxis > lclGetApiAxis( Reference< XCoordinateSystem > xCoordSystem,
2893 : sal_Int32 nApiAxisDim, sal_Int32 nApiAxesSetIdx )
2894 : {
2895 0 : Reference< XAxis > xAxis;
2896 0 : if( (nApiAxisDim >= 0) && xCoordSystem.is() ) try
2897 : {
2898 0 : xAxis = xCoordSystem->getAxisByDimension( nApiAxisDim, nApiAxesSetIdx );
2899 : }
2900 0 : catch( Exception& )
2901 : {
2902 : }
2903 0 : return xAxis;
2904 : }
2905 :
2906 0 : Reference< cssc::XAxis > lclGetApiChart1Axis( Reference< XChartDocument > xChartDoc,
2907 : sal_Int32 nApiAxisDim, sal_Int32 nApiAxesSetIdx )
2908 : {
2909 0 : Reference< cssc::XAxis > xChart1Axis;
2910 : try
2911 : {
2912 0 : Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY_THROW );
2913 0 : Reference< cssc::XAxisSupplier > xChart1AxisSupp( xChart1Doc->getDiagram(), UNO_QUERY_THROW );
2914 0 : switch( nApiAxesSetIdx )
2915 : {
2916 : case EXC_CHART_AXESSET_PRIMARY:
2917 0 : xChart1Axis = xChart1AxisSupp->getAxis( nApiAxisDim );
2918 0 : break;
2919 : case EXC_CHART_AXESSET_SECONDARY:
2920 0 : xChart1Axis = xChart1AxisSupp->getSecondaryAxis( nApiAxisDim );
2921 0 : break;
2922 0 : }
2923 : }
2924 0 : catch( Exception& )
2925 : {
2926 : }
2927 0 : return xChart1Axis;
2928 : }
2929 :
2930 : } // namespace
2931 :
2932 0 : XclExpChAxis::XclExpChAxis( const XclExpChRoot& rRoot, sal_uInt16 nAxisType ) :
2933 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_AXIS, EXC_ID_CHAXIS, 18 ),
2934 0 : mnNumFmtIdx( EXC_FORMAT_NOTFOUND )
2935 : {
2936 0 : maData.mnType = nAxisType;
2937 0 : }
2938 :
2939 0 : void XclExpChAxis::SetFont( XclExpChFontRef xFont, const Color& rColor, sal_uInt32 nColorId )
2940 : {
2941 0 : mxFont = xFont;
2942 0 : if( mxTick )
2943 0 : mxTick->SetFontColor( rColor, nColorId );
2944 0 : }
2945 :
2946 0 : void XclExpChAxis::SetRotation( sal_uInt16 nRotation )
2947 : {
2948 0 : if( mxTick )
2949 0 : mxTick->SetRotation( nRotation );
2950 0 : }
2951 :
2952 0 : void XclExpChAxis::Convert( Reference< XAxis > xAxis, Reference< XAxis > xCrossingAxis,
2953 : Reference< cssc::XAxis > xChart1Axis, const XclChExtTypeInfo& rTypeInfo )
2954 : {
2955 0 : ScfPropertySet aAxisProp( xAxis );
2956 0 : bool bCategoryAxis = ((GetAxisType() == EXC_CHAXIS_X) && rTypeInfo.mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z);
2957 :
2958 : // axis line format -------------------------------------------------------
2959 :
2960 0 : mxAxisLine.reset( new XclExpChLineFormat( GetChRoot() ) );
2961 0 : mxAxisLine->Convert( GetChRoot(), aAxisProp, EXC_CHOBJTYPE_AXISLINE );
2962 : // #i58688# axis enabled
2963 0 : mxAxisLine->SetShowAxis( aAxisProp.GetBoolProperty( EXC_CHPROP_SHOW ) );
2964 :
2965 : // axis scaling and increment ---------------------------------------------
2966 :
2967 0 : ScfPropertySet aCrossingProp( xCrossingAxis );
2968 0 : if( bCategoryAxis )
2969 : {
2970 0 : mxLabelRange.reset( new XclExpChLabelRange( GetChRoot() ) );
2971 0 : mxLabelRange->SetTicksBetweenCateg( rTypeInfo.mbTicksBetweenCateg );
2972 0 : if( xAxis.is() )
2973 : {
2974 0 : ScfPropertySet aChart1AxisProp( xChart1Axis );
2975 : // #i71684# radar charts have reversed rotation direction
2976 0 : mxLabelRange->Convert( xAxis->getScaleData(), aChart1AxisProp, (GetAxisType() == EXC_CHAXIS_X) && (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR) );
2977 : }
2978 : // get position of crossing axis on this axis from passed axis object
2979 0 : if( aCrossingProp.Is() )
2980 0 : mxLabelRange->ConvertAxisPosition( aCrossingProp );
2981 : }
2982 : else
2983 : {
2984 0 : mxValueRange.reset( new XclExpChValueRange( GetChRoot() ) );
2985 0 : if( xAxis.is() )
2986 0 : mxValueRange->Convert( xAxis->getScaleData() );
2987 : // get position of crossing axis on this axis from passed axis object
2988 0 : if( aCrossingProp.Is() )
2989 0 : mxValueRange->ConvertAxisPosition( aCrossingProp );
2990 : }
2991 :
2992 : // axis caption text ------------------------------------------------------
2993 :
2994 : // axis ticks properties
2995 0 : mxTick.reset( new XclExpChTick( GetChRoot() ) );
2996 0 : mxTick->Convert( aAxisProp, rTypeInfo, GetAxisType() );
2997 :
2998 : // axis label formatting and rotation
2999 0 : ConvertFontBase( GetChRoot(), aAxisProp );
3000 0 : ConvertRotationBase( GetChRoot(), aAxisProp, true );
3001 :
3002 : // axis number format
3003 0 : sal_Int32 nApiNumFmt = 0;
3004 0 : if( !bCategoryAxis && aAxisProp.GetProperty( nApiNumFmt, EXC_CHPROP_NUMBERFORMAT ) )
3005 0 : mnNumFmtIdx = GetNumFmtBuffer().Insert( static_cast< sal_uInt32 >( nApiNumFmt ) );
3006 :
3007 : // grid -------------------------------------------------------------------
3008 :
3009 0 : if( xAxis.is() )
3010 : {
3011 : // main grid
3012 0 : ScfPropertySet aGridProp( xAxis->getGridProperties() );
3013 0 : if( aGridProp.GetBoolProperty( EXC_CHPROP_SHOW ) )
3014 0 : mxMajorGrid = lclCreateLineFormat( GetChRoot(), aGridProp, EXC_CHOBJTYPE_GRIDLINE );
3015 : // sub grid
3016 0 : Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
3017 0 : if( aSubGridPropSeq.hasElements() )
3018 : {
3019 0 : ScfPropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
3020 0 : if( aSubGridProp.GetBoolProperty( EXC_CHPROP_SHOW ) )
3021 0 : mxMinorGrid = lclCreateLineFormat( GetChRoot(), aSubGridProp, EXC_CHOBJTYPE_GRIDLINE );
3022 0 : }
3023 0 : }
3024 0 : }
3025 :
3026 0 : void XclExpChAxis::ConvertWall( XDiagramRef xDiagram )
3027 : {
3028 0 : if( xDiagram.is() ) switch( GetAxisType() )
3029 : {
3030 : case EXC_CHAXIS_X:
3031 : {
3032 0 : ScfPropertySet aWallProp( xDiagram->getWall() );
3033 0 : mxWallFrame = lclCreateFrame( GetChRoot(), aWallProp, EXC_CHOBJTYPE_WALL3D );
3034 : }
3035 0 : break;
3036 : case EXC_CHAXIS_Y:
3037 : {
3038 0 : ScfPropertySet aFloorProp( xDiagram->getFloor() );
3039 0 : mxWallFrame = lclCreateFrame( GetChRoot(), aFloorProp, EXC_CHOBJTYPE_FLOOR3D );
3040 : }
3041 0 : break;
3042 : default:
3043 0 : mxWallFrame.reset();
3044 : }
3045 0 : }
3046 :
3047 0 : void XclExpChAxis::WriteSubRecords( XclExpStream& rStrm )
3048 : {
3049 0 : lclSaveRecord( rStrm, mxLabelRange );
3050 0 : lclSaveRecord( rStrm, mxValueRange );
3051 0 : if( mnNumFmtIdx != EXC_FORMAT_NOTFOUND )
3052 0 : XclExpUInt16Record( EXC_ID_CHFORMAT, mnNumFmtIdx ).Save( rStrm );
3053 0 : lclSaveRecord( rStrm, mxTick );
3054 0 : lclSaveRecord( rStrm, mxFont );
3055 0 : lclSaveRecord( rStrm, mxAxisLine, EXC_ID_CHAXISLINE, EXC_CHAXISLINE_AXISLINE );
3056 0 : lclSaveRecord( rStrm, mxMajorGrid, EXC_ID_CHAXISLINE, EXC_CHAXISLINE_MAJORGRID );
3057 0 : lclSaveRecord( rStrm, mxMinorGrid, EXC_ID_CHAXISLINE, EXC_CHAXISLINE_MINORGRID );
3058 0 : lclSaveRecord( rStrm, mxWallFrame, EXC_ID_CHAXISLINE, EXC_CHAXISLINE_WALLS );
3059 0 : }
3060 :
3061 0 : void XclExpChAxis::WriteBody( XclExpStream& rStrm )
3062 : {
3063 0 : rStrm << maData.mnType;
3064 0 : rStrm.WriteZeroBytes( 16 );
3065 0 : }
3066 :
3067 0 : XclExpChAxesSet::XclExpChAxesSet( const XclExpChRoot& rRoot, sal_uInt16 nAxesSetId ) :
3068 0 : XclExpChGroupBase( rRoot, EXC_CHFRBLOCK_TYPE_AXESSET, EXC_ID_CHAXESSET, 18 )
3069 : {
3070 0 : maData.mnAxesSetId = nAxesSetId;
3071 0 : SetFutureRecordContext( 0, nAxesSetId );
3072 :
3073 : /* Need to set a reasonable size for the plot area, otherwise Excel will
3074 : move away embedded shapes while auto-sizing the plot area. This is just
3075 : a wild guess, but will be fixed with implementing manual positioning of
3076 : chart elements. */
3077 0 : maData.maRect.mnX = 262;
3078 0 : maData.maRect.mnY = 626;
3079 0 : maData.maRect.mnWidth = 3187;
3080 0 : maData.maRect.mnHeight = 2633;
3081 0 : }
3082 :
3083 0 : sal_uInt16 XclExpChAxesSet::Convert( Reference< XDiagram > xDiagram, sal_uInt16 nFirstGroupIdx )
3084 : {
3085 : /* First unused chart type group index is passed to be able to continue
3086 : counting of chart type groups for secondary axes set. */
3087 0 : sal_uInt16 nGroupIdx = nFirstGroupIdx;
3088 0 : Reference< XCoordinateSystemContainer > xCoordSysCont( xDiagram, UNO_QUERY );
3089 0 : if( xCoordSysCont.is() )
3090 : {
3091 0 : Sequence< Reference< XCoordinateSystem > > aCoordSysSeq = xCoordSysCont->getCoordinateSystems();
3092 0 : if( aCoordSysSeq.getLength() > 0 )
3093 : {
3094 : /* Process first coordinate system only. Import filter puts all
3095 : chart types into one coordinate system. */
3096 0 : Reference< XCoordinateSystem > xCoordSystem = aCoordSysSeq[ 0 ];
3097 0 : sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3098 :
3099 : // 3d mode
3100 0 : bool b3dChart = xCoordSystem.is() && (xCoordSystem->getDimension() == 3);
3101 :
3102 : // percent charts
3103 : namespace ApiAxisType = cssc2::AxisType;
3104 0 : Reference< XAxis > xApiYAxis = lclGetApiAxis( xCoordSystem, EXC_CHART_AXIS_Y, nApiAxesSetIdx );
3105 0 : bool bPercent = xApiYAxis.is() && (xApiYAxis->getScaleData().AxisType == ApiAxisType::PERCENT);
3106 :
3107 : // connector lines in bar charts
3108 0 : ScfPropertySet aDiaProp( xDiagram );
3109 0 : bool bConnectBars = aDiaProp.GetBoolProperty( EXC_CHPROP_CONNECTBARS );
3110 :
3111 : // swapped axes sets
3112 0 : ScfPropertySet aCoordSysProp( xCoordSystem );
3113 0 : bool bSwappedAxesSet = aCoordSysProp.GetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS );
3114 :
3115 : // X axis for later use
3116 0 : Reference< XAxis > xApiXAxis = lclGetApiAxis( xCoordSystem, EXC_CHART_AXIS_X, nApiAxesSetIdx );
3117 : // X axis labels
3118 0 : ScfPropertySet aXAxisProp( xApiXAxis );
3119 0 : bool bHasXLabels = aXAxisProp.GetBoolProperty( EXC_CHPROP_DISPLAYLABELS );
3120 :
3121 : // process chart types
3122 0 : Reference< XChartTypeContainer > xChartTypeCont( xCoordSystem, UNO_QUERY );
3123 0 : if( xChartTypeCont.is() )
3124 : {
3125 0 : Sequence< Reference< XChartType > > aChartTypeSeq = xChartTypeCont->getChartTypes();
3126 0 : const Reference< XChartType >* pBeg = aChartTypeSeq.getConstArray();
3127 0 : const Reference< XChartType >* pEnd = pBeg + aChartTypeSeq.getLength();
3128 0 : for( const Reference< XChartType >* pIt = pBeg; pIt != pEnd; ++pIt )
3129 : {
3130 0 : XclExpChTypeGroupRef xTypeGroup( new XclExpChTypeGroup( GetChRoot(), nGroupIdx ) );
3131 0 : xTypeGroup->ConvertType( xDiagram, *pIt, nApiAxesSetIdx, b3dChart, bSwappedAxesSet, bHasXLabels );
3132 : /* If new chart type group cannot be inserted into a combination
3133 : chart with existing type groups, insert all series into last
3134 : contained chart type group instead of creating a new group. */
3135 0 : XclExpChTypeGroupRef xLastGroup = GetLastTypeGroup();
3136 0 : if( xLastGroup && !(xTypeGroup->IsCombinable2d() && xLastGroup->IsCombinable2d()) )
3137 : {
3138 0 : xLastGroup->ConvertSeries( xDiagram, *pIt, nApiAxesSetIdx, bPercent, bConnectBars );
3139 : }
3140 : else
3141 : {
3142 0 : xTypeGroup->ConvertSeries( xDiagram, *pIt, nApiAxesSetIdx, bPercent, bConnectBars );
3143 0 : if( xTypeGroup->IsValidGroup() )
3144 : {
3145 0 : maTypeGroups.AppendRecord( xTypeGroup );
3146 0 : ++nGroupIdx;
3147 : }
3148 : }
3149 0 : }
3150 : }
3151 :
3152 0 : if( XclExpChTypeGroup* pGroup = GetFirstTypeGroup().get() )
3153 : {
3154 0 : const XclChExtTypeInfo& rTypeInfo = pGroup->GetTypeInfo();
3155 :
3156 : // create axes according to chart type (no axes for pie and donut charts)
3157 0 : if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE )
3158 : {
3159 0 : ConvertAxis( mxXAxis, EXC_CHAXIS_X, mxXAxisTitle, EXC_CHOBJLINK_XAXIS, xCoordSystem, rTypeInfo, EXC_CHART_AXIS_Y );
3160 0 : ConvertAxis( mxYAxis, EXC_CHAXIS_Y, mxYAxisTitle, EXC_CHOBJLINK_YAXIS, xCoordSystem, rTypeInfo, EXC_CHART_AXIS_X );
3161 0 : if( pGroup->Is3dDeepChart() )
3162 0 : ConvertAxis( mxZAxis, EXC_CHAXIS_Z, mxZAxisTitle, EXC_CHOBJLINK_ZAXIS, xCoordSystem, rTypeInfo, EXC_CHART_AXIS_NONE );
3163 : }
3164 :
3165 : // X axis category ranges
3166 0 : if( rTypeInfo.mbCategoryAxis && xApiXAxis.is() )
3167 : {
3168 0 : const ScaleData aScaleData = xApiXAxis->getScaleData();
3169 0 : for( size_t nIdx = 0, nSize = maTypeGroups.GetSize(); nIdx < nSize; ++nIdx )
3170 0 : maTypeGroups.GetRecord( nIdx )->ConvertCategSequence( aScaleData.Categories );
3171 : }
3172 :
3173 : // legend
3174 0 : if( xDiagram.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY) )
3175 : {
3176 0 : Reference< XLegend > xLegend = xDiagram->getLegend();
3177 0 : if( xLegend.is() )
3178 : {
3179 0 : ScfPropertySet aLegendProp( xLegend );
3180 0 : pGroup->ConvertLegend( aLegendProp );
3181 0 : }
3182 : }
3183 0 : }
3184 0 : }
3185 : }
3186 :
3187 : // wall/floor/diagram frame formatting
3188 0 : if( xDiagram.is() && (GetAxesSetId() == EXC_CHAXESSET_PRIMARY) )
3189 : {
3190 0 : XclExpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3191 0 : if( xTypeGroup && xTypeGroup->Is3dWallChart() )
3192 : {
3193 : // wall/floor formatting (3D charts)
3194 0 : if( mxXAxis )
3195 0 : mxXAxis->ConvertWall( xDiagram );
3196 0 : if( mxYAxis )
3197 0 : mxYAxis->ConvertWall( xDiagram );
3198 : }
3199 : else
3200 : {
3201 : // diagram background formatting
3202 0 : ScfPropertySet aWallProp( xDiagram->getWall() );
3203 0 : mxPlotFrame = lclCreateFrame( GetChRoot(), aWallProp, EXC_CHOBJTYPE_PLOTFRAME );
3204 0 : }
3205 : }
3206 :
3207 : // inner and outer plot area position and size
3208 : try
3209 : {
3210 0 : Reference< cssc::XChartDocument > xChart1Doc( GetChartDocument(), UNO_QUERY_THROW );
3211 0 : Reference< cssc::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW );
3212 : // set manual flag in chart data
3213 0 : if( !xPositioning->isAutomaticDiagramPositioning() )
3214 0 : GetChartData().SetManualPlotArea();
3215 : // the CHAXESSET record contains the inner plot area
3216 0 : maData.maRect = CalcChartRectFromHmm( xPositioning->calculateDiagramPositionExcludingAxes() );
3217 : // the embedded CHFRAMEPOS record contains the outer plot area
3218 0 : mxFramePos.reset( new XclExpChFramePos( EXC_CHFRAMEPOS_PARENT, EXC_CHFRAMEPOS_PARENT ) );
3219 : // for pie charts, always use inner plot area size to exclude the data labels as Excel does
3220 0 : const XclExpChTypeGroup* pFirstTypeGroup = GetFirstTypeGroup().get();
3221 0 : bool bPieChart = pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE);
3222 0 : mxFramePos->GetFramePosData().maRect = bPieChart ? maData.maRect :
3223 0 : CalcChartRectFromHmm( xPositioning->calculateDiagramPositionIncludingAxes() );
3224 : }
3225 0 : catch( Exception& )
3226 : {
3227 : }
3228 :
3229 : // return first unused chart type group index for next axes set
3230 0 : return nGroupIdx;
3231 : }
3232 :
3233 0 : bool XclExpChAxesSet::Is3dChart() const
3234 : {
3235 0 : XclExpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3236 0 : return xTypeGroup && xTypeGroup->Is3dChart();
3237 : }
3238 :
3239 0 : void XclExpChAxesSet::WriteSubRecords( XclExpStream& rStrm )
3240 : {
3241 0 : lclSaveRecord( rStrm, mxFramePos );
3242 0 : lclSaveRecord( rStrm, mxXAxis );
3243 0 : lclSaveRecord( rStrm, mxYAxis );
3244 0 : lclSaveRecord( rStrm, mxZAxis );
3245 0 : lclSaveRecord( rStrm, mxXAxisTitle );
3246 0 : lclSaveRecord( rStrm, mxYAxisTitle );
3247 0 : lclSaveRecord( rStrm, mxZAxisTitle );
3248 0 : if( mxPlotFrame )
3249 : {
3250 0 : XclExpEmptyRecord( EXC_ID_CHPLOTFRAME ).Save( rStrm );
3251 0 : mxPlotFrame->Save( rStrm );
3252 : }
3253 0 : maTypeGroups.Save( rStrm );
3254 0 : }
3255 :
3256 0 : XclExpChTypeGroupRef XclExpChAxesSet::GetFirstTypeGroup() const
3257 : {
3258 0 : return maTypeGroups.GetFirstRecord();
3259 : }
3260 :
3261 0 : XclExpChTypeGroupRef XclExpChAxesSet::GetLastTypeGroup() const
3262 : {
3263 0 : return maTypeGroups.GetLastRecord();
3264 : }
3265 :
3266 0 : void XclExpChAxesSet::ConvertAxis(
3267 : XclExpChAxisRef& rxChAxis, sal_uInt16 nAxisType,
3268 : XclExpChTextRef& rxChAxisTitle, sal_uInt16 nTitleTarget,
3269 : Reference< XCoordinateSystem > xCoordSystem, const XclChExtTypeInfo& rTypeInfo,
3270 : sal_Int32 nCrossingAxisDim )
3271 : {
3272 : // create and convert axis object
3273 0 : rxChAxis.reset( new XclExpChAxis( GetChRoot(), nAxisType ) );
3274 0 : sal_Int32 nApiAxisDim = rxChAxis->GetApiAxisDimension();
3275 0 : sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3276 0 : Reference< XAxis > xAxis = lclGetApiAxis( xCoordSystem, nApiAxisDim, nApiAxesSetIdx );
3277 0 : Reference< XAxis > xCrossingAxis = lclGetApiAxis( xCoordSystem, nCrossingAxisDim, nApiAxesSetIdx );
3278 0 : Reference< cssc::XAxis > xChart1Axis = lclGetApiChart1Axis( GetChartDocument(), nApiAxisDim, nApiAxesSetIdx );
3279 0 : rxChAxis->Convert( xAxis, xCrossingAxis, xChart1Axis, rTypeInfo );
3280 :
3281 : // create and convert axis title
3282 0 : Reference< XTitled > xTitled( xAxis, UNO_QUERY );
3283 0 : rxChAxisTitle = lclCreateTitle( GetChRoot(), xTitled, nTitleTarget );
3284 0 : }
3285 :
3286 0 : void XclExpChAxesSet::WriteBody( XclExpStream& rStrm )
3287 : {
3288 0 : rStrm << maData.mnAxesSetId << maData.maRect;
3289 0 : }
3290 :
3291 : // The chart object ===========================================================
3292 :
3293 0 : static void lcl_getChartSubTitle(const Reference<XChartDocument>& xChartDoc,
3294 : OUString& rSubTitle)
3295 : {
3296 0 : Reference< ::com::sun::star::chart::XChartDocument > xChartDoc1(xChartDoc, UNO_QUERY);
3297 0 : if (!xChartDoc1.is())
3298 0 : return;
3299 :
3300 0 : Reference< XPropertySet > xProp(xChartDoc1->getSubTitle(), UNO_QUERY);
3301 0 : if (!xProp.is())
3302 0 : return;
3303 :
3304 0 : OUString aTitle;
3305 0 : Any any = xProp->getPropertyValue("String");
3306 0 : if (any >>= aTitle)
3307 0 : rSubTitle = aTitle;
3308 : }
3309 :
3310 0 : XclExpChChart::XclExpChChart( const XclExpRoot& rRoot,
3311 : Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) :
3312 0 : XclExpChGroupBase( XclExpChRoot( rRoot, *this ), EXC_CHFRBLOCK_TYPE_CHART, EXC_ID_CHCHART, 16 )
3313 : {
3314 0 : Size aPtSize = OutputDevice::LogicToLogic( rChartRect.GetSize(), MapMode( MAP_100TH_MM ), MapMode( MAP_POINT ) );
3315 : // rectangle is stored in 16.16 fixed-point format
3316 0 : maRect.mnX = maRect.mnY = 0;
3317 0 : maRect.mnWidth = static_cast< sal_Int32 >( aPtSize.Width() << 16 );
3318 0 : maRect.mnHeight = static_cast< sal_Int32 >( aPtSize.Height() << 16 );
3319 :
3320 : // global chart properties (default values)
3321 0 : ::set_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY, false );
3322 0 : ::set_flag( maProps.mnFlags, EXC_CHPROPS_MANPLOTAREA );
3323 0 : maProps.mnEmptyMode = EXC_CHPROPS_EMPTY_SKIP;
3324 :
3325 : // always create both axes set objects
3326 0 : mxPrimAxesSet.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) );
3327 0 : mxSecnAxesSet.reset( new XclExpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) );
3328 :
3329 0 : if( xChartDoc.is() )
3330 : {
3331 0 : Reference< XDiagram > xDiagram = xChartDoc->getFirstDiagram();
3332 :
3333 : // global chart properties (only 'include hidden cells' attribute for now)
3334 0 : ScfPropertySet aDiagramProp( xDiagram );
3335 0 : bool bIncludeHidden = aDiagramProp.GetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS );
3336 0 : ::set_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY, !bIncludeHidden );
3337 :
3338 : // initialize API conversion (remembers xChartDoc and rChartRect internally)
3339 0 : InitConversion( xChartDoc, rChartRect );
3340 :
3341 : // chart frame
3342 0 : ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
3343 0 : mxFrame = lclCreateFrame( GetChRoot(), aFrameProp, EXC_CHOBJTYPE_BACKGROUND );
3344 :
3345 : // chart title
3346 0 : Reference< XTitled > xTitled( xChartDoc, UNO_QUERY );
3347 0 : OUString aSubTitle;
3348 0 : lcl_getChartSubTitle(xChartDoc, aSubTitle);
3349 0 : mxTitle = lclCreateTitle( GetChRoot(), xTitled, EXC_CHOBJLINK_TITLE,
3350 0 : !aSubTitle.isEmpty() ? &aSubTitle : NULL );
3351 :
3352 : // diagrams (axes sets)
3353 0 : sal_uInt16 nFreeGroupIdx = mxPrimAxesSet->Convert( xDiagram, 0 );
3354 0 : if( !mxPrimAxesSet->Is3dChart() )
3355 0 : mxSecnAxesSet->Convert( xDiagram, nFreeGroupIdx );
3356 :
3357 : // treatment of missing values
3358 0 : ScfPropertySet aDiaProp( xDiagram );
3359 0 : sal_Int32 nMissingValues = 0;
3360 0 : if( aDiaProp.GetProperty( nMissingValues, EXC_CHPROP_MISSINGVALUETREATMENT ) )
3361 : {
3362 : using namespace cssc::MissingValueTreatment;
3363 0 : switch( nMissingValues )
3364 : {
3365 0 : case LEAVE_GAP: maProps.mnEmptyMode = EXC_CHPROPS_EMPTY_SKIP; break;
3366 0 : case USE_ZERO: maProps.mnEmptyMode = EXC_CHPROPS_EMPTY_ZERO; break;
3367 0 : case CONTINUE: maProps.mnEmptyMode = EXC_CHPROPS_EMPTY_INTERPOLATE; break;
3368 : }
3369 : }
3370 :
3371 : // finish API conversion
3372 0 : FinishConversion();
3373 : }
3374 0 : }
3375 :
3376 0 : XclExpChSeriesRef XclExpChChart::CreateSeries()
3377 : {
3378 0 : XclExpChSeriesRef xSeries;
3379 0 : sal_uInt16 nSeriesIdx = static_cast< sal_uInt16 >( maSeries.GetSize() );
3380 0 : if( nSeriesIdx <= EXC_CHSERIES_MAXSERIES )
3381 : {
3382 0 : xSeries.reset( new XclExpChSeries( GetChRoot(), nSeriesIdx ) );
3383 0 : maSeries.AppendRecord( xSeries );
3384 : }
3385 0 : return xSeries;
3386 : }
3387 :
3388 0 : void XclExpChChart::RemoveLastSeries()
3389 : {
3390 0 : if( !maSeries.IsEmpty() )
3391 0 : maSeries.RemoveRecord( maSeries.GetSize() - 1 );
3392 0 : }
3393 :
3394 0 : void XclExpChChart::SetDataLabel( XclExpChTextRef xText )
3395 : {
3396 0 : if( xText )
3397 0 : maLabels.AppendRecord( xText );
3398 0 : }
3399 :
3400 0 : void XclExpChChart::SetManualPlotArea()
3401 : {
3402 : // this flag does not exist in BIFF5
3403 0 : if( GetBiff() == EXC_BIFF8 )
3404 0 : ::set_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA );
3405 0 : }
3406 :
3407 0 : void XclExpChChart::WriteSubRecords( XclExpStream& rStrm )
3408 : {
3409 : // background format
3410 0 : lclSaveRecord( rStrm, mxFrame );
3411 :
3412 : // data series
3413 0 : maSeries.Save( rStrm );
3414 :
3415 : // CHPROPERTIES record
3416 0 : rStrm.StartRecord( EXC_ID_CHPROPERTIES, 4 );
3417 0 : rStrm << maProps.mnFlags << maProps.mnEmptyMode << sal_uInt8( 0 );
3418 0 : rStrm.EndRecord();
3419 :
3420 : // axes sets (always save primary axes set)
3421 0 : sal_uInt16 nUsedAxesSets = mxSecnAxesSet->IsValidAxesSet() ? 2 : 1;
3422 0 : XclExpUInt16Record( EXC_ID_CHUSEDAXESSETS, nUsedAxesSets ).Save( rStrm );
3423 0 : mxPrimAxesSet->Save( rStrm );
3424 0 : if( mxSecnAxesSet->IsValidAxesSet() )
3425 0 : mxSecnAxesSet->Save( rStrm );
3426 :
3427 : // chart title and data labels
3428 0 : lclSaveRecord( rStrm, mxTitle );
3429 0 : maLabels.Save( rStrm );
3430 0 : }
3431 :
3432 0 : void XclExpChChart::WriteBody( XclExpStream& rStrm )
3433 : {
3434 0 : rStrm << maRect;
3435 0 : }
3436 :
3437 0 : XclExpChartDrawing::XclExpChartDrawing( const XclExpRoot& rRoot,
3438 : const Reference< XModel >& rxModel, const Size& rChartSize ) :
3439 0 : XclExpRoot( rRoot )
3440 : {
3441 0 : if( (rChartSize.Width() > 0) && (rChartSize.Height() > 0) )
3442 : {
3443 0 : ScfPropertySet aPropSet( rxModel );
3444 0 : Reference< XShapes > xShapes;
3445 0 : if( aPropSet.GetProperty( xShapes, EXC_CHPROP_ADDITIONALSHAPES ) && xShapes.is() && (xShapes->getCount() > 0) )
3446 : {
3447 : /* Create a new independent object manager with own DFF stream for the
3448 : DGCONTAINER, pass global manager as parent for shared usage of
3449 : global DFF data (picture container etc.). */
3450 0 : mxObjMgr.reset( new XclExpEmbeddedObjectManager( GetObjectManager(), rChartSize, EXC_CHART_TOTALUNITS, EXC_CHART_TOTALUNITS ) );
3451 : // initialize the drawing object list
3452 0 : mxObjMgr->StartSheet();
3453 : // process the draw page (convert all shapes)
3454 0 : mxObjRecs = mxObjMgr->ProcessDrawing( xShapes );
3455 : // finalize the DFF stream
3456 0 : mxObjMgr->EndDocument();
3457 0 : }
3458 : }
3459 0 : }
3460 :
3461 0 : XclExpChartDrawing::~XclExpChartDrawing()
3462 : {
3463 0 : }
3464 :
3465 0 : void XclExpChartDrawing::Save( XclExpStream& rStrm )
3466 : {
3467 0 : if( mxObjRecs )
3468 0 : mxObjRecs->Save( rStrm );
3469 0 : }
3470 :
3471 0 : XclExpChart::XclExpChart( const XclExpRoot& rRoot, Reference< XModel > xModel, const Rectangle& rChartRect ) :
3472 : XclExpSubStream( EXC_BOF_CHART ),
3473 0 : XclExpRoot( rRoot )
3474 : {
3475 0 : AppendNewRecord( new XclExpChartPageSettings( rRoot ) );
3476 0 : AppendNewRecord( new XclExpBoolRecord( EXC_ID_PROTECT, false ) );
3477 0 : AppendNewRecord( new XclExpChartDrawing( rRoot, xModel, rChartRect.GetSize() ) );
3478 0 : AppendNewRecord( new XclExpUInt16Record( EXC_ID_CHUNITS, EXC_CHUNITS_TWIPS ) );
3479 :
3480 0 : Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
3481 0 : AppendNewRecord( new XclExpChChart( rRoot, xChartDoc, rChartRect ) );
3482 0 : }
3483 :
3484 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|