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