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