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