Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xichart.hxx"
21 :
22 : #include <algorithm>
23 : #include <memory>
24 :
25 : #include <com/sun/star/frame/XModel.hpp>
26 : #include <com/sun/star/drawing/Direction3D.hpp>
27 : #include <com/sun/star/drawing/ProjectionMode.hpp>
28 : #include <com/sun/star/drawing/ShadeMode.hpp>
29 : #include <com/sun/star/drawing/XShape.hpp>
30 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
31 : #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
32 : #include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
33 : #include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
34 : #include <com/sun/star/chart/ChartAxisPosition.hpp>
35 : #include <com/sun/star/chart/ChartLegendExpansion.hpp>
36 : #include <com/sun/star/chart/TimeInterval.hpp>
37 : #include <com/sun/star/chart/TimeUnit.hpp>
38 : #include <com/sun/star/chart/XChartDocument.hpp>
39 : #include <com/sun/star/chart/XDiagramPositioning.hpp>
40 : #include <com/sun/star/chart2/XChartDocument.hpp>
41 : #include <com/sun/star/chart2/XDiagram.hpp>
42 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
43 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
44 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
45 : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
46 : #include <com/sun/star/chart2/XTitled.hpp>
47 : #include <com/sun/star/chart2/data/XDataProvider.hpp>
48 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
49 : #include <com/sun/star/chart2/data/XDataSink.hpp>
50 : #include <com/sun/star/chart2/AxisType.hpp>
51 : #include <com/sun/star/chart2/CurveStyle.hpp>
52 : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
53 : #include <com/sun/star/chart2/DataPointLabel.hpp>
54 : #include <com/sun/star/chart2/LegendPosition.hpp>
55 : #include <com/sun/star/chart2/StackingDirection.hpp>
56 : #include <com/sun/star/chart2/TickmarkStyle.hpp>
57 : #include <com/sun/star/chart2/RelativePosition.hpp>
58 : #include <com/sun/star/chart2/RelativeSize.hpp>
59 : #include <com/sun/star/chart/DataLabelPlacement.hpp>
60 : #include <com/sun/star/chart/ErrorBarStyle.hpp>
61 : #include <com/sun/star/chart/MissingValueTreatment.hpp>
62 :
63 : #include <sfx2/objsh.hxx>
64 : #include <svx/svdpage.hxx>
65 : #include <svx/unoapi.hxx>
66 :
67 : #include "document.hxx"
68 : #include "drwlayer.hxx"
69 : #include "rangeutl.hxx"
70 : #include "tokenarray.hxx"
71 : #include "token.hxx"
72 : #include "compiler.hxx"
73 : #include "reftokenhelper.hxx"
74 : #include "chartlis.hxx"
75 : #include "fprogressbar.hxx"
76 : #include "xltracer.hxx"
77 : #include "xistream.hxx"
78 : #include "xiformula.hxx"
79 : #include "xistyle.hxx"
80 : #include "xipage.hxx"
81 : #include "xiview.hxx"
82 :
83 : using ::rtl::OUString;
84 : using ::rtl::OUStringBuffer;
85 : using ::com::sun::star::uno::Any;
86 : using ::com::sun::star::uno::Reference;
87 : using ::com::sun::star::uno::Sequence;
88 : using ::com::sun::star::uno::UNO_QUERY;
89 : using ::com::sun::star::uno::UNO_QUERY_THROW;
90 : using ::com::sun::star::uno::UNO_SET_THROW;
91 : using ::com::sun::star::uno::Exception;
92 : using ::com::sun::star::beans::XPropertySet;
93 : using ::com::sun::star::lang::XMultiServiceFactory;
94 : using ::com::sun::star::frame::XModel;
95 : using ::com::sun::star::util::XNumberFormatsSupplier;
96 : using ::com::sun::star::drawing::XDrawPage;
97 : using ::com::sun::star::drawing::XDrawPageSupplier;
98 : using ::com::sun::star::drawing::XShape;
99 :
100 : using ::com::sun::star::chart2::IncrementData;
101 : using ::com::sun::star::chart2::RelativePosition;
102 : using ::com::sun::star::chart2::RelativeSize;
103 : using ::com::sun::star::chart2::ScaleData;
104 : using ::com::sun::star::chart2::SubIncrement;
105 : using ::com::sun::star::chart2::XAxis;
106 : using ::com::sun::star::chart2::XChartDocument;
107 : using ::com::sun::star::chart2::XChartType;
108 : using ::com::sun::star::chart2::XChartTypeContainer;
109 : using ::com::sun::star::chart2::XCoordinateSystem;
110 : using ::com::sun::star::chart2::XCoordinateSystemContainer;
111 : using ::com::sun::star::chart2::XDataSeries;
112 : using ::com::sun::star::chart2::XDataSeriesContainer;
113 : using ::com::sun::star::chart2::XDiagram;
114 : using ::com::sun::star::chart2::XFormattedString;
115 : using ::com::sun::star::chart2::XLegend;
116 : using ::com::sun::star::chart2::XRegressionCurve;
117 : using ::com::sun::star::chart2::XRegressionCurveContainer;
118 : using ::com::sun::star::chart2::XScaling;
119 : using ::com::sun::star::chart2::XTitle;
120 : using ::com::sun::star::chart2::XTitled;
121 :
122 : using ::com::sun::star::chart2::data::XDataProvider;
123 : using ::com::sun::star::chart2::data::XDataReceiver;
124 : using ::com::sun::star::chart2::data::XDataSequence;
125 : using ::com::sun::star::chart2::data::XDataSink;
126 : using ::com::sun::star::chart2::data::XLabeledDataSequence;
127 :
128 : using ::formula::FormulaToken;
129 : using ::formula::StackVar;
130 : using ::boost::shared_ptr;
131 : using ::std::pair;
132 : using ::std::auto_ptr;
133 :
134 : namespace cssc = ::com::sun::star::chart;
135 : namespace cssc2 = ::com::sun::star::chart2;
136 :
137 : // Helpers ====================================================================
138 :
139 : namespace {
140 :
141 288 : XclImpStream& operator>>( XclImpStream& rStrm, XclChRectangle& rRect )
142 : {
143 288 : return rStrm >> rRect.mnX >> rRect.mnY >> rRect.mnWidth >> rRect.mnHeight;
144 : }
145 :
146 120 : inline void lclSetValueOrClearAny( Any& rAny, double fValue, bool bClear )
147 : {
148 120 : if( bClear )
149 120 : rAny.clear();
150 : else
151 0 : rAny <<= fValue;
152 120 : }
153 :
154 80 : void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bClear )
155 : {
156 80 : if( !bClear && bLogScale )
157 0 : fValue = pow( 10.0, fValue );
158 80 : lclSetValueOrClearAny( rAny, fValue, bClear );
159 80 : }
160 :
161 0 : double lclGetSerialDay( const XclImpRoot& rRoot, sal_uInt16 nValue, sal_uInt16 nTimeUnit )
162 : {
163 0 : switch( nTimeUnit )
164 : {
165 : case EXC_CHDATERANGE_DAYS:
166 0 : return nValue;
167 : case EXC_CHDATERANGE_MONTHS:
168 0 : return rRoot.GetDoubleFromDateTime( Date( 1, static_cast< sal_uInt16 >( 1 + nValue % 12 ), static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue / 12 ) ) );
169 : case EXC_CHDATERANGE_YEARS:
170 0 : return rRoot.GetDoubleFromDateTime( Date( 1, 1, static_cast< sal_uInt16 >( rRoot.GetBaseYear() + nValue ) ) );
171 : default:
172 : OSL_ENSURE( false, "lclGetSerialDay - unexpected time unit" );
173 : }
174 0 : return nValue;
175 : }
176 :
177 0 : void lclConvertTimeValue( const XclImpRoot& rRoot, Any& rAny, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
178 : {
179 0 : if( bAuto )
180 0 : rAny.clear();
181 : else
182 0 : rAny <<= lclGetSerialDay( rRoot, nValue, nTimeUnit );
183 0 : }
184 :
185 0 : sal_Int32 lclGetApiTimeUnit( sal_uInt16 nTimeUnit )
186 : {
187 0 : switch( nTimeUnit )
188 : {
189 0 : case EXC_CHDATERANGE_DAYS: return cssc::TimeUnit::DAY;
190 0 : case EXC_CHDATERANGE_MONTHS: return cssc::TimeUnit::MONTH;
191 0 : case EXC_CHDATERANGE_YEARS: return cssc::TimeUnit::YEAR;
192 : default: OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
193 : }
194 0 : return cssc::TimeUnit::DAY;
195 : }
196 :
197 0 : void lclConvertTimeInterval( Any& rInterval, sal_uInt16 nValue, bool bAuto, sal_uInt16 nTimeUnit )
198 : {
199 0 : if( bAuto || (nValue == 0) )
200 0 : rInterval.clear();
201 : else
202 0 : rInterval <<= cssc::TimeInterval( nValue, lclGetApiTimeUnit( nTimeUnit ) );
203 0 : }
204 :
205 : } // namespace
206 :
207 : // Common =====================================================================
208 :
209 : /** Stores global data needed in various classes of the Chart import filter. */
210 80 : struct XclImpChRootData : public XclChRootData
211 : {
212 : XclImpChChart& mrChartData; /// The chart data object.
213 :
214 40 : inline explicit XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {}
215 : };
216 :
217 : // ----------------------------------------------------------------------------
218 :
219 40 : XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ) :
220 : XclImpRoot( rRoot ),
221 40 : mxChData( new XclImpChRootData( rChartData ) )
222 : {
223 40 : }
224 :
225 1562 : XclImpChRoot::~XclImpChRoot()
226 : {
227 1562 : }
228 :
229 417 : XclImpChChart& XclImpChRoot::GetChartData() const
230 : {
231 417 : return mxChData->mrChartData;
232 : }
233 :
234 79 : const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const
235 : {
236 79 : return mxChData->mxTypeInfoProv->GetTypeInfo( eType );
237 : }
238 :
239 1 : const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const
240 : {
241 1 : return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId );
242 : }
243 :
244 1101 : const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const
245 : {
246 1101 : return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType );
247 : }
248 :
249 84 : Color XclImpChRoot::GetFontAutoColor() const
250 : {
251 84 : return GetPalette().GetColor( EXC_COLOR_CHWINDOWTEXT );
252 : }
253 :
254 2 : Color XclImpChRoot::GetSeriesLineAutoColor( sal_uInt16 nFormatIdx ) const
255 : {
256 2 : return GetPalette().GetColor( XclChartHelper::GetSeriesLineAutoColorIdx( nFormatIdx ) );
257 : }
258 :
259 1 : Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const
260 : {
261 1 : const XclImpPalette& rPal = GetPalette();
262 1 : Color aColor = rPal.GetColor( XclChartHelper::GetSeriesFillAutoColorIdx( nFormatIdx ) );
263 1 : sal_uInt8 nTrans = XclChartHelper::GetSeriesFillAutoTransp( nFormatIdx );
264 1 : return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans );
265 : }
266 :
267 40 : void XclImpChRoot::InitConversion( const Reference<XChartDocument>& xChartDoc, const Rectangle& rChartRect ) const
268 : {
269 : // create formatting object tables
270 40 : mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect );
271 :
272 : // lock the model to suppress any internal updates
273 40 : Reference< XModel > xModel( xChartDoc, UNO_QUERY );
274 40 : if( xModel.is() )
275 40 : xModel->lockControllers();
276 :
277 40 : SfxObjectShell* pDocShell = GetDocShell();
278 40 : Reference< XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
279 40 : if( pDocShell && xDataRec.is() )
280 : {
281 : // create and register a data provider
282 : Reference< XDataProvider > xDataProv(
283 40 : ScfApiHelper::CreateInstance( pDocShell, SERVICE_CHART2_DATAPROVIDER ), UNO_QUERY );
284 40 : if( xDataProv.is() )
285 40 : xDataRec->attachDataProvider( xDataProv );
286 : // attach the number formatter
287 40 : Reference< XNumberFormatsSupplier > xNumFmtSupp( pDocShell->GetModel(), UNO_QUERY );
288 40 : if( xNumFmtSupp.is() )
289 40 : xDataRec->attachNumberFormatsSupplier( xNumFmtSupp );
290 40 : }
291 40 : }
292 :
293 40 : void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const
294 : {
295 40 : rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
296 : // unlock the model
297 40 : Reference< XModel > xModel( mxChData->mxChartDoc, UNO_QUERY );
298 40 : if( xModel.is() )
299 40 : xModel->unlockControllers();
300 40 : rDffConv.Progress( EXC_CHART_PROGRESS_SIZE );
301 :
302 40 : mxChData->FinishConversion();
303 40 : }
304 :
305 120 : Reference< XDataProvider > XclImpChRoot::GetDataProvider() const
306 : {
307 120 : return mxChData->mxChartDoc->getDataProvider();
308 : }
309 :
310 20 : Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const
311 : {
312 20 : return mxChData->GetTitleShape( rTitleKey );
313 : }
314 :
315 118 : sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const
316 : {
317 118 : return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 );
318 : }
319 :
320 118 : sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const
321 : {
322 118 : return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 );
323 : }
324 :
325 39 : ::com::sun::star::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const
326 : {
327 : return ::com::sun::star::awt::Rectangle(
328 39 : CalcHmmFromChartX( rRect.mnX ),
329 39 : CalcHmmFromChartY( rRect.mnY ),
330 39 : CalcHmmFromChartX( rRect.mnWidth ),
331 156 : CalcHmmFromChartY( rRect.mnHeight ) );
332 : }
333 :
334 39 : double XclImpChRoot::CalcRelativeFromHmmX( sal_Int32 nPosX ) const
335 : {
336 39 : return static_cast< double >( nPosX ) / mxChData->maChartRect.GetWidth();
337 : }
338 :
339 39 : double XclImpChRoot::CalcRelativeFromHmmY( sal_Int32 nPosY ) const
340 : {
341 39 : return static_cast< double >( nPosY ) / mxChData->maChartRect.GetHeight();
342 : }
343 :
344 20 : double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const
345 : {
346 20 : return CalcRelativeFromHmmX( CalcHmmFromChartX( nPosX ) );
347 : }
348 :
349 20 : double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const
350 : {
351 20 : return CalcRelativeFromHmmY( CalcHmmFromChartY( nPosY ) );
352 : }
353 :
354 299 : void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet,
355 : const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const
356 : {
357 299 : GetChartPropSetHelper().WriteLineProperties(
358 598 : rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode );
359 299 : }
360 :
361 121 : void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet,
362 : const XclChAreaFormat& rAreaFmt, XclChPropertyMode ePropMode ) const
363 : {
364 121 : GetChartPropSetHelper().WriteAreaProperties( rPropSet, rAreaFmt, ePropMode );
365 121 : }
366 :
367 150 : void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet,
368 : const XclChEscherFormat& rEscherFmt, const XclChPicFormat* pPicFmt,
369 : sal_uInt32 nDffFillType, XclChPropertyMode ePropMode ) const
370 : {
371 150 : GetChartPropSetHelper().WriteEscherProperties( rPropSet,
372 150 : *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable,
373 150 : rEscherFmt, pPicFmt, nDffFillType, ePropMode );
374 150 : }
375 :
376 181 : void XclImpChRoot::ConvertFont( ScfPropertySet& rPropSet,
377 : sal_uInt16 nFontIdx, const Color* pFontColor ) const
378 : {
379 181 : GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CHART, nFontIdx, pFontColor );
380 181 : }
381 :
382 37 : void XclImpChRoot::ConvertPieRotation( ScfPropertySet& rPropSet, sal_uInt16 nAngle )
383 : {
384 37 : sal_Int32 nApiRot = (450 - (nAngle % 360)) % 360;
385 37 : rPropSet.SetProperty( EXC_CHPROP_STARTINGANGLE, nApiRot );
386 37 : }
387 :
388 : // ----------------------------------------------------------------------------
389 :
390 998 : XclImpChGroupBase::~XclImpChGroupBase()
391 : {
392 998 : }
393 :
394 722 : void XclImpChGroupBase::ReadRecordGroup( XclImpStream& rStrm )
395 : {
396 : // read contents of the header record
397 722 : ReadHeaderRecord( rStrm );
398 :
399 : // only read sub records, if the next record is a CHBEGIN
400 722 : if( rStrm.GetNextRecId() == EXC_ID_CHBEGIN )
401 : {
402 : // read the CHBEGIN record, may be used for special initial processing
403 627 : rStrm.StartNextRecord();
404 627 : ReadSubRecord( rStrm );
405 :
406 : // read the nested records
407 627 : bool bLoop = true;
408 6191 : while( bLoop && rStrm.StartNextRecord() )
409 : {
410 4937 : sal_uInt16 nRecId = rStrm.GetRecId();
411 4937 : bLoop = nRecId != EXC_ID_CHEND;
412 : // skip unsupported nested blocks
413 4937 : if( nRecId == EXC_ID_CHBEGIN )
414 30 : SkipBlock( rStrm );
415 : else
416 4907 : ReadSubRecord( rStrm );
417 : }
418 : }
419 : /* Returns with current CHEND record or unchanged stream, if no record
420 : group present. In every case another call to StartNextRecord() will go
421 : to next record of interest. */
422 722 : }
423 :
424 60 : void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm )
425 : {
426 : OSL_ENSURE( rStrm.GetRecId() == EXC_ID_CHBEGIN, "XclImpChGroupBase::SkipBlock - no CHBEGIN record" );
427 : // do nothing if current record is not CHBEGIN
428 60 : bool bLoop = rStrm.GetRecId() == EXC_ID_CHBEGIN;
429 420 : while( bLoop && rStrm.StartNextRecord() )
430 : {
431 300 : sal_uInt16 nRecId = rStrm.GetRecId();
432 300 : bLoop = nRecId != EXC_ID_CHEND;
433 : // skip nested record groups
434 300 : if( nRecId == EXC_ID_CHBEGIN )
435 30 : SkipBlock( rStrm );
436 : }
437 60 : }
438 :
439 : // Frame formatting ===========================================================
440 :
441 248 : void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm )
442 : {
443 248 : rStrm >> maData.mnTLMode >> maData.mnBRMode;
444 : /* According to the spec, the upper 16 bits of all members in the
445 : rectangle are unused and may contain garbage. */
446 248 : maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 );
447 248 : maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 );
448 248 : maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 );
449 248 : maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 );
450 248 : }
451 :
452 : // ----------------------------------------------------------------------------
453 :
454 255 : void XclImpChLineFormat::ReadChLineFormat( XclImpStream& rStrm )
455 : {
456 255 : rStrm >> maData.maColor >> maData.mnPattern >> maData.mnWeight >> maData.mnFlags;
457 :
458 255 : const XclImpRoot& rRoot = rStrm.GetRoot();
459 255 : if( rRoot.GetBiff() == EXC_BIFF8 )
460 : // BIFF8: index into palette used instead of RGB data
461 255 : maData.maColor = rRoot.GetPalette().GetColor( rStrm.ReaduInt16() );
462 255 : }
463 :
464 299 : void XclImpChLineFormat::Convert( const XclImpChRoot& rRoot,
465 : ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
466 : {
467 299 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
468 299 : if( IsAuto() )
469 : {
470 88 : XclChLineFormat aLineFmt;
471 : aLineFmt.maColor = (eObjType == EXC_CHOBJTYPE_LINEARSERIES) ?
472 1 : rRoot.GetSeriesLineAutoColor( nFormatIdx ) :
473 89 : rRoot.GetPalette().GetColor( rFmtInfo.mnAutoLineColorIdx );
474 88 : aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
475 88 : aLineFmt.mnWeight = rFmtInfo.mnAutoLineWeight;
476 88 : rRoot.ConvertLineFormat( rPropSet, aLineFmt, rFmtInfo.mePropMode );
477 : }
478 : else
479 : {
480 211 : rRoot.ConvertLineFormat( rPropSet, maData, rFmtInfo.mePropMode );
481 : }
482 299 : }
483 :
484 : // ----------------------------------------------------------------------------
485 :
486 253 : void XclImpChAreaFormat::ReadChAreaFormat( XclImpStream& rStrm )
487 : {
488 253 : rStrm >> maData.maPattColor >> maData.maBackColor >> maData.mnPattern >> maData.mnFlags;
489 :
490 253 : const XclImpRoot& rRoot = rStrm.GetRoot();
491 253 : if( rRoot.GetBiff() == EXC_BIFF8 )
492 : {
493 : // BIFF8: index into palette used instead of RGB data
494 253 : const XclImpPalette& rPal = rRoot.GetPalette();
495 253 : maData.maPattColor = rPal.GetColor( rStrm.ReaduInt16() );
496 253 : maData.maBackColor = rPal.GetColor( rStrm.ReaduInt16());
497 : }
498 253 : }
499 :
500 121 : void XclImpChAreaFormat::Convert( const XclImpChRoot& rRoot,
501 : ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
502 : {
503 121 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
504 121 : if( IsAuto() )
505 : {
506 5 : XclChAreaFormat aAreaFmt;
507 : aAreaFmt.maPattColor = (eObjType == EXC_CHOBJTYPE_FILLEDSERIES) ?
508 1 : rRoot.GetSeriesFillAutoColor( nFormatIdx ) :
509 6 : rRoot.GetPalette().GetColor( rFmtInfo.mnAutoPattColorIdx );
510 5 : aAreaFmt.mnPattern = EXC_PATT_SOLID;
511 5 : rRoot.ConvertAreaFormat( rPropSet, aAreaFmt, rFmtInfo.mePropMode );
512 : }
513 : else
514 : {
515 116 : rRoot.ConvertAreaFormat( rPropSet, maData, rFmtInfo.mePropMode );
516 : }
517 121 : }
518 :
519 : // ----------------------------------------------------------------------------
520 :
521 95 : XclImpChEscherFormat::XclImpChEscherFormat( const XclImpRoot& rRoot ) :
522 95 : mnDffFillType( mso_fillSolid )
523 : {
524 : maData.mxItemSet.reset(
525 95 : new SfxItemSet( rRoot.GetDoc().GetDrawLayer()->GetItemPool() ) );
526 95 : }
527 :
528 95 : void XclImpChEscherFormat::ReadHeaderRecord( XclImpStream& rStrm )
529 : {
530 : // read from stream - CHESCHERFORMAT uses own ID for record continuation
531 95 : XclImpDffPropSet aPropSet( rStrm.GetRoot() );
532 95 : rStrm.ResetRecord( true, rStrm.GetRecId() );
533 95 : rStrm >> aPropSet;
534 : // get the data
535 95 : aPropSet.FillToItemSet( *maData.mxItemSet );
536 : // get fill type from DFF property set
537 95 : mnDffFillType = aPropSet.GetPropertyValue( DFF_Prop_fillType, mso_fillSolid );
538 95 : }
539 :
540 0 : void XclImpChEscherFormat::ReadSubRecord( XclImpStream& rStrm )
541 : {
542 0 : switch( rStrm.GetRecId() )
543 : {
544 : case EXC_ID_CHPICFORMAT:
545 0 : rStrm >> maPicFmt.mnBmpMode;
546 0 : rStrm.Ignore( 2 );
547 0 : rStrm >> maPicFmt.mnFlags >> maPicFmt.mfScale;
548 0 : break;
549 : }
550 0 : }
551 :
552 150 : void XclImpChEscherFormat::Convert( const XclImpChRoot& rRoot,
553 : ScfPropertySet& rPropSet, XclChObjectType eObjType, bool bUsePicFmt ) const
554 : {
555 150 : const XclChFormatInfo& rFmtInfo = rRoot.GetFormatInfo( eObjType );
556 150 : rRoot.ConvertEscherFormat( rPropSet, maData, bUsePicFmt ? &maPicFmt : 0, mnDffFillType, rFmtInfo.mePropMode );
557 150 : }
558 :
559 : // ----------------------------------------------------------------------------
560 :
561 259 : XclImpChFrameBase::XclImpChFrameBase( const XclChFormatInfo& rFmtInfo )
562 : {
563 259 : if( rFmtInfo.mbCreateDefFrame ) switch( rFmtInfo.meDefFrameType )
564 : {
565 : case EXC_CHFRAMETYPE_AUTO:
566 101 : mxLineFmt.reset( new XclImpChLineFormat );
567 101 : if( rFmtInfo.mbIsFrame )
568 101 : mxAreaFmt.reset( new XclImpChAreaFormat );
569 101 : break;
570 : case EXC_CHFRAMETYPE_INVISIBLE:
571 : {
572 80 : XclChLineFormat aLineFmt;
573 80 : ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, false );
574 80 : aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE;
575 80 : mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
576 80 : if( rFmtInfo.mbIsFrame )
577 : {
578 80 : XclChAreaFormat aAreaFmt;
579 80 : ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, false );
580 80 : aAreaFmt.mnPattern = EXC_PATT_NONE;
581 80 : mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
582 : }
583 : }
584 80 : break;
585 : default:
586 : OSL_FAIL( "XclImpChFrameBase::XclImpChFrameBase - unknown frame type" );
587 : }
588 259 : }
589 :
590 2012 : void XclImpChFrameBase::ReadSubRecord( XclImpStream& rStrm )
591 : {
592 2012 : switch( rStrm.GetRecId() )
593 : {
594 : case EXC_ID_CHLINEFORMAT:
595 253 : mxLineFmt.reset( new XclImpChLineFormat );
596 253 : mxLineFmt->ReadChLineFormat( rStrm );
597 253 : break;
598 : case EXC_ID_CHAREAFORMAT:
599 253 : mxAreaFmt.reset( new XclImpChAreaFormat );
600 253 : mxAreaFmt->ReadChAreaFormat( rStrm );
601 253 : break;
602 : case EXC_ID_CHESCHERFORMAT:
603 95 : mxEscherFmt.reset( new XclImpChEscherFormat( rStrm.GetRoot() ) );
604 95 : mxEscherFmt->ReadRecordGroup( rStrm );
605 95 : break;
606 : }
607 2012 : }
608 :
609 217 : void XclImpChFrameBase::ConvertLineBase( const XclImpChRoot& rRoot,
610 : ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx ) const
611 : {
612 217 : if( mxLineFmt )
613 217 : mxLineFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
614 217 : }
615 :
616 272 : void XclImpChFrameBase::ConvertAreaBase( const XclImpChRoot& rRoot,
617 : ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
618 : {
619 272 : if( rRoot.GetFormatInfo( eObjType ).mbIsFrame )
620 : {
621 : // CHESCHERFORMAT overrides CHAREAFORMAT (even if it is auto)
622 271 : if( mxEscherFmt )
623 150 : mxEscherFmt->Convert( rRoot, rPropSet, eObjType, bUsePicFmt );
624 121 : else if( mxAreaFmt )
625 121 : mxAreaFmt->Convert( rRoot, rPropSet, eObjType, nFormatIdx );
626 : }
627 272 : }
628 :
629 217 : void XclImpChFrameBase::ConvertFrameBase( const XclImpChRoot& rRoot,
630 : ScfPropertySet& rPropSet, XclChObjectType eObjType, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
631 : {
632 217 : ConvertLineBase( rRoot, rPropSet, eObjType, nFormatIdx );
633 217 : ConvertAreaBase( rRoot, rPropSet, eObjType, nFormatIdx, bUsePicFmt );
634 217 : }
635 :
636 : // ----------------------------------------------------------------------------
637 :
638 259 : XclImpChFrame::XclImpChFrame( const XclImpChRoot& rRoot, XclChObjectType eObjType ) :
639 259 : XclImpChFrameBase( rRoot.GetFormatInfo( eObjType ) ),
640 : XclImpChRoot( rRoot ),
641 259 : meObjType( eObjType )
642 : {
643 259 : }
644 :
645 139 : void XclImpChFrame::ReadHeaderRecord( XclImpStream& rStrm )
646 : {
647 139 : rStrm >> maData.mnFormat >> maData.mnFlags;
648 139 : }
649 :
650 0 : void XclImpChFrame::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
651 : {
652 0 : const XclImpPalette& rPal = GetPalette();
653 :
654 0 : if( rLineData.IsVisible() && (!mxLineFmt || !mxLineFmt->HasLine()) )
655 : {
656 : // line formatting
657 0 : XclChLineFormat aLineFmt;
658 0 : aLineFmt.maColor = rPal.GetColor( rLineData.mnColorIdx );
659 0 : switch( rLineData.mnStyle )
660 : {
661 0 : case EXC_OBJ_LINE_SOLID: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID; break;
662 0 : case EXC_OBJ_LINE_DASH: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASH; break;
663 0 : case EXC_OBJ_LINE_DOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DOT; break;
664 0 : case EXC_OBJ_LINE_DASHDOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOT; break;
665 0 : case EXC_OBJ_LINE_DASHDOTDOT: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DASHDOTDOT; break;
666 0 : case EXC_OBJ_LINE_MEDTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_MEDTRANS; break;
667 0 : case EXC_OBJ_LINE_DARKTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_DARKTRANS; break;
668 0 : case EXC_OBJ_LINE_LIGHTTRANS: aLineFmt.mnPattern = EXC_CHLINEFORMAT_LIGHTTRANS; break;
669 0 : case EXC_OBJ_LINE_NONE: aLineFmt.mnPattern = EXC_CHLINEFORMAT_NONE; break;
670 0 : default: aLineFmt.mnPattern = EXC_CHLINEFORMAT_SOLID;
671 : }
672 0 : switch( rLineData.mnWidth )
673 : {
674 0 : case EXC_OBJ_LINE_HAIR: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR; break;
675 0 : case EXC_OBJ_LINE_THIN: aLineFmt.mnWeight = EXC_CHLINEFORMAT_SINGLE; break;
676 0 : case EXC_OBJ_LINE_MEDIUM: aLineFmt.mnWeight = EXC_CHLINEFORMAT_DOUBLE; break;
677 0 : case EXC_OBJ_LINE_THICK: aLineFmt.mnWeight = EXC_CHLINEFORMAT_TRIPLE; break;
678 0 : default: aLineFmt.mnWeight = EXC_CHLINEFORMAT_HAIR;
679 : }
680 0 : ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_AUTO, rLineData.IsAuto() );
681 0 : mxLineFmt.reset( new XclImpChLineFormat( aLineFmt ) );
682 : }
683 :
684 0 : if( rFillData.IsFilled() && (!mxAreaFmt || !mxAreaFmt->HasArea()) && !mxEscherFmt )
685 : {
686 : // area formatting
687 0 : XclChAreaFormat aAreaFmt;
688 0 : aAreaFmt.maPattColor = rPal.GetColor( rFillData.mnPattColorIdx );
689 0 : aAreaFmt.maBackColor = rPal.GetColor( rFillData.mnBackColorIdx );
690 0 : aAreaFmt.mnPattern = rFillData.mnPattern;
691 0 : ::set_flag( aAreaFmt.mnFlags, EXC_CHAREAFORMAT_AUTO, rFillData.IsAuto() );
692 0 : mxAreaFmt.reset( new XclImpChAreaFormat( aAreaFmt ) );
693 : }
694 0 : }
695 :
696 120 : void XclImpChFrame::Convert( ScfPropertySet& rPropSet, bool bUsePicFmt ) const
697 : {
698 120 : ConvertFrameBase( GetChRoot(), rPropSet, meObjType, EXC_CHDATAFORMAT_UNKNOWN, bUsePicFmt );
699 120 : }
700 :
701 : // Source links ===============================================================
702 :
703 : namespace {
704 :
705 : /** Creates a labeled data sequence object, adds link for series title if present. */
706 80 : Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
707 : const XclImpChSourceLinkRef& xValueLink, const OUString& rValueRole,
708 : const XclImpChSourceLink* pTitleLink = 0 )
709 : {
710 : // create data sequence for values and title
711 80 : Reference< XDataSequence > xValueSeq;
712 80 : if( xValueLink )
713 80 : xValueSeq = xValueLink->CreateDataSequence( rValueRole );
714 80 : Reference< XDataSequence > xTitleSeq;
715 80 : if( pTitleLink )
716 40 : xTitleSeq = pTitleLink->CreateDataSequence( EXC_CHPROP_ROLE_LABEL );
717 :
718 : // create the labeled data sequence, if values or title are present
719 80 : Reference< XLabeledDataSequence > xLabeledSeq;
720 80 : if( xValueSeq.is() || xTitleSeq.is() )
721 61 : xLabeledSeq.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_LABELEDDATASEQ ), UNO_QUERY );
722 80 : if( xLabeledSeq.is() )
723 : {
724 61 : if( xValueSeq.is() )
725 61 : xLabeledSeq->setValues( xValueSeq );
726 61 : if( xTitleSeq.is() )
727 21 : xLabeledSeq->setLabel( xTitleSeq );
728 : }
729 80 : return xLabeledSeq;
730 : }
731 :
732 : } // namespace
733 :
734 : // ----------------------------------------------------------------------------
735 :
736 347 : XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot& rRoot ) :
737 347 : XclImpChRoot( rRoot )
738 : {
739 347 : }
740 :
741 694 : XclImpChSourceLink::~XclImpChSourceLink()
742 : {
743 694 : }
744 :
745 347 : void XclImpChSourceLink::ReadChSourceLink( XclImpStream& rStrm )
746 : {
747 347 : rStrm >> maData.mnDestType
748 694 : >> maData.mnLinkType
749 694 : >> maData.mnFlags
750 694 : >> maData.mnNumFmtIdx;
751 :
752 347 : mxTokenArray.reset();
753 347 : if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET )
754 : {
755 : // read token array
756 82 : XclTokenArray aXclTokArr;
757 82 : rStrm >> aXclTokArr;
758 :
759 : // convert BIFF formula tokens to Calc token array
760 82 : if( const ScTokenArray* pTokens = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aXclTokArr ) )
761 82 : mxTokenArray.reset( pTokens->Clone() );
762 : }
763 :
764 : // try to read a following CHSTRING record
765 347 : if( (rStrm.GetNextRecId() == EXC_ID_CHSTRING) && rStrm.StartNextRecord() )
766 : {
767 36 : mxString.reset( new XclImpString );
768 36 : rStrm.Ignore( 2 );
769 36 : mxString->Read( rStrm, EXC_STR_8BITLENGTH | EXC_STR_SEPARATEFORMATS );
770 : }
771 347 : }
772 :
773 19 : void XclImpChSourceLink::SetString( const String& rString )
774 : {
775 19 : if( !mxString )
776 19 : mxString.reset( new XclImpString );
777 19 : mxString->SetText( rString );
778 19 : }
779 :
780 0 : void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec& rFormats )
781 : {
782 0 : if( mxString )
783 0 : mxString->SetFormats( rFormats );
784 0 : }
785 :
786 37 : sal_uInt16 XclImpChSourceLink::GetCellCount() const
787 : {
788 37 : sal_uInt32 nCellCount = 0;
789 37 : if( mxTokenArray )
790 : {
791 37 : mxTokenArray->Reset();
792 74 : for( const FormulaToken* pToken = mxTokenArray->First(); pToken; pToken = mxTokenArray->Next() )
793 : {
794 37 : switch( pToken->GetType() )
795 : {
796 : case ::formula::svSingleRef:
797 : case ::formula::svExternalSingleRef:
798 : // single cell
799 19 : ++nCellCount;
800 19 : break;
801 : case ::formula::svDoubleRef:
802 : case ::formula::svExternalDoubleRef:
803 : {
804 : // cell range
805 18 : const ScComplexRefData& rComplexRef = static_cast< const ScToken* >( pToken )->GetDoubleRef();
806 18 : const ScSingleRefData& rRef1 = rComplexRef.Ref1;
807 18 : const ScSingleRefData& rRef2 = rComplexRef.Ref2;
808 18 : sal_uInt32 nTabs = static_cast< sal_uInt32 >( rRef2.nTab - rRef1.nTab + 1 );
809 18 : sal_uInt32 nCols = static_cast< sal_uInt32 >( rRef2.nCol - rRef1.nCol + 1 );
810 18 : sal_uInt32 nRows = static_cast< sal_uInt32 >( rRef2.nRow - rRef1.nRow + 1 );
811 18 : nCellCount += nCols * nRows * nTabs;
812 : }
813 18 : break;
814 : default: ;
815 : }
816 : }
817 : }
818 37 : return limit_cast< sal_uInt16 >( nCellCount );
819 : }
820 :
821 46 : void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
822 : {
823 46 : bool bLinkToSource = ::get_flag( maData.mnFlags, EXC_CHSRCLINK_NUMFMT );
824 46 : sal_uInt32 nScNumFmt = bLinkToSource ? GetNumFmtBuffer().GetScFormat( maData.mnNumFmtIdx ) : NUMBERFORMAT_ENTRY_NOT_FOUND;
825 46 : OUString aPropName = bPercent ? OUString( EXC_CHPROP_PERCENTAGENUMFMT ) : OUString( EXC_CHPROP_NUMBERFORMAT );
826 46 : if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
827 0 : rPropSet.SetProperty( aPropName, static_cast< sal_Int32 >( nScNumFmt ) );
828 : else
829 : // restore 'link to source' at data point (series may contain manual number format)
830 46 : rPropSet.SetAnyProperty( aPropName, Any() );
831 46 : }
832 :
833 120 : Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUString& rRole ) const
834 : {
835 120 : Reference< XDataSequence > xDataSeq;
836 120 : Reference< XDataProvider > xDataProv = GetDataProvider();
837 120 : if( xDataProv.is() && mxTokenArray )
838 : {
839 82 : ScCompiler aComp( GetDocPtr(), ScAddress(), *mxTokenArray );
840 82 : aComp.SetGrammar(GetDoc().GetGrammar());
841 82 : OUStringBuffer aRangeRep;
842 82 : aComp.CreateStringFromTokenArray( aRangeRep );
843 : try
844 : {
845 82 : xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() );
846 : // set sequence role
847 82 : ScfPropertySet aSeqProp( xDataSeq );
848 82 : aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
849 : }
850 0 : catch( Exception& )
851 : {
852 : // OSL_FAIL( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" );
853 82 : }
854 : }
855 38 : else if( rRole == EXC_CHPROP_ROLE_LABEL && mxString && mxString->GetText().Len() )
856 : {
857 : try
858 : {
859 0 : OUString aString = OUString::createFromAscii("\"");
860 0 : xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aString + mxString->GetText() + aString );
861 : // set sequence role
862 0 : ScfPropertySet aSeqProp( xDataSeq );
863 0 : aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole );
864 : }
865 0 : catch( Exception& ) { }
866 : }
867 120 : return xDataSeq;
868 : }
869 :
870 21 : Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequence(
871 : const XclImpChRoot& rRoot, sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const
872 : {
873 21 : ::std::vector< Reference< XFormattedString > > aStringVec;
874 21 : if( mxString )
875 : {
876 42 : for( XclImpStringIterator aIt( *mxString ); aIt.Is(); ++aIt )
877 : {
878 : Reference< XFormattedString > xFmtStr(
879 21 : ScfApiHelper::CreateInstance( SERVICE_CHART2_FORMATTEDSTRING ), UNO_QUERY );
880 21 : if( xFmtStr.is() )
881 : {
882 : // set text data
883 21 : xFmtStr->setString( aIt.GetPortionText() );
884 :
885 : // set font formatting and font color
886 21 : ScfPropertySet aStringProp( xFmtStr );
887 21 : sal_uInt16 nFontIdx = aIt.GetPortionFont();
888 21 : if( (nFontIdx == EXC_FONT_NOTFOUND) && (aIt.GetPortionIndex() == 0) )
889 : // leading unformatted portion - use passed font settings
890 21 : rRoot.ConvertFont( aStringProp, nLeadFontIdx, &rLeadFontColor );
891 : else
892 0 : rRoot.ConvertFont( aStringProp, nFontIdx );
893 :
894 : // add string to vector of strings
895 21 : aStringVec.push_back( xFmtStr );
896 : }
897 21 : }
898 : }
899 21 : return ScfApiHelper::VectorToSequence( aStringVec );
900 : }
901 :
902 160 : void XclImpChSourceLink::FillSourceLink( ::std::vector< ScTokenRef >& rTokens ) const
903 : {
904 160 : if( !mxTokenArray )
905 : // no links to fill.
906 238 : return;
907 :
908 82 : mxTokenArray->Reset();
909 164 : for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
910 : {
911 82 : ScTokenRef pToken(static_cast<ScToken*>(p->Clone()));
912 82 : if (ScRefTokenHelper::isRef(pToken))
913 : // This is a reference token. Store it.
914 82 : ScRefTokenHelper::join(rTokens, pToken);
915 82 : }
916 : }
917 :
918 : // Text =======================================================================
919 :
920 267 : XclImpChFontBase::~XclImpChFontBase()
921 : {
922 267 : }
923 :
924 160 : void XclImpChFontBase::ConvertFontBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
925 : {
926 160 : Color aFontColor = GetFontColor();
927 160 : rRoot.ConvertFont( rPropSet, GetFontIndex(), &aFontColor );
928 160 : }
929 :
930 160 : void XclImpChFontBase::ConvertRotationBase( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet, bool bSupportsStacked ) const
931 : {
932 160 : rRoot.GetChartPropSetHelper().WriteRotationProperties( rPropSet, GetRotation(), bSupportsStacked );
933 160 : }
934 :
935 : // ----------------------------------------------------------------------------
936 :
937 181 : XclImpChFont::XclImpChFont() :
938 181 : mnFontIdx( EXC_FONT_NOTFOUND )
939 : {
940 181 : }
941 :
942 181 : void XclImpChFont::ReadChFont( XclImpStream& rStrm )
943 : {
944 181 : rStrm >> mnFontIdx;
945 181 : }
946 :
947 : // ----------------------------------------------------------------------------
948 :
949 187 : XclImpChText::XclImpChText( const XclImpChRoot& rRoot ) :
950 187 : XclImpChRoot( rRoot )
951 : {
952 187 : }
953 :
954 187 : void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm )
955 : {
956 187 : rStrm >> maData.mnHAlign
957 374 : >> maData.mnVAlign
958 374 : >> maData.mnBackMode
959 374 : >> maData.maTextColor
960 374 : >> maData.maRect
961 374 : >> maData.mnFlags;
962 :
963 187 : if( GetBiff() == EXC_BIFF8 )
964 : {
965 : // BIFF8: index into palette used instead of RGB data
966 187 : maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
967 : // placement and rotation
968 187 : rStrm >> maData.mnFlags2 >> maData.mnRotation;
969 : }
970 : else
971 : {
972 : // BIFF2-BIFF7: get rotation from text orientation
973 0 : sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 8, 3 );
974 0 : maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
975 : }
976 187 : }
977 :
978 1418 : void XclImpChText::ReadSubRecord( XclImpStream& rStrm )
979 : {
980 1418 : switch( rStrm.GetRecId() )
981 : {
982 : case EXC_ID_CHFRAMEPOS:
983 187 : mxFramePos.reset( new XclImpChFramePos );
984 187 : mxFramePos->ReadChFramePos( rStrm );
985 187 : break;
986 : case EXC_ID_CHFONT:
987 179 : mxFont.reset( new XclImpChFont );
988 179 : mxFont->ReadChFont( rStrm );
989 179 : break;
990 : case EXC_ID_CHFORMATRUNS:
991 0 : if( GetBiff() == EXC_BIFF8 )
992 0 : XclImpString::ReadFormats( rStrm, maFormats );
993 0 : break;
994 : case EXC_ID_CHSOURCELINK:
995 187 : mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
996 187 : mxSrcLink->ReadChSourceLink( rStrm );
997 187 : break;
998 : case EXC_ID_CHFRAME:
999 78 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_TEXT ) );
1000 78 : mxFrame->ReadRecordGroup( rStrm );
1001 78 : break;
1002 : case EXC_ID_CHOBJECTLINK:
1003 86 : rStrm >> maObjLink.mnTarget >> maObjLink.maPointPos.mnSeriesIdx >> maObjLink.maPointPos.mnPointIdx;
1004 86 : break;
1005 : case EXC_ID_CHFRLABELPROPS:
1006 0 : ReadChFrLabelProps( rStrm );
1007 0 : break;
1008 : case EXC_ID_CHEND:
1009 187 : if( mxSrcLink && !maFormats.empty() )
1010 0 : mxSrcLink->SetTextFormats( maFormats );
1011 187 : break;
1012 : }
1013 1418 : }
1014 :
1015 179 : sal_uInt16 XclImpChText::GetFontIndex() const
1016 : {
1017 179 : return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
1018 : }
1019 :
1020 179 : Color XclImpChText::GetFontColor() const
1021 : {
1022 179 : return ::get_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
1023 : }
1024 :
1025 100 : sal_uInt16 XclImpChText::GetRotation() const
1026 : {
1027 100 : return maData.mnRotation;
1028 : }
1029 :
1030 19 : void XclImpChText::SetString( const String& rString )
1031 : {
1032 19 : if( !mxSrcLink )
1033 0 : mxSrcLink.reset( new XclImpChSourceLink( GetChRoot() ) );
1034 19 : mxSrcLink->SetString( rString );
1035 19 : }
1036 :
1037 107 : void XclImpChText::UpdateText( const XclImpChText* pParentText )
1038 : {
1039 107 : if( pParentText )
1040 : {
1041 : // update missing members
1042 107 : if( !mxFrame )
1043 29 : mxFrame = pParentText->mxFrame;
1044 107 : if( !mxFont )
1045 : {
1046 8 : mxFont = pParentText->mxFont;
1047 : // text color is taken from CHTEXT record, not from font in CHFONT
1048 8 : ::set_flag( maData.mnFlags, EXC_CHTEXT_AUTOCOLOR, ::get_flag( pParentText->maData.mnFlags, EXC_CHTEXT_AUTOCOLOR ) );
1049 8 : maData.maTextColor = pParentText->maData.maTextColor;
1050 : }
1051 : }
1052 107 : }
1053 :
1054 0 : void XclImpChText::UpdateDataLabel( bool bCateg, bool bValue, bool bPercent )
1055 : {
1056 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEG, bCateg );
1057 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWVALUE, bValue );
1058 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWPERCENT, bPercent );
1059 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_SHOWCATEGPERC, bCateg && bPercent );
1060 0 : ::set_flag( maData.mnFlags, EXC_CHTEXT_DELETED, !bCateg && !bValue && !bPercent );
1061 0 : }
1062 :
1063 158 : void XclImpChText::ConvertFont( ScfPropertySet& rPropSet ) const
1064 : {
1065 158 : ConvertFontBase( GetChRoot(), rPropSet );
1066 158 : }
1067 :
1068 80 : void XclImpChText::ConvertRotation( ScfPropertySet& rPropSet, bool bSupportsStacked ) const
1069 : {
1070 80 : ConvertRotationBase( GetChRoot(), rPropSet, bSupportsStacked );
1071 80 : }
1072 :
1073 21 : void XclImpChText::ConvertFrame( ScfPropertySet& rPropSet ) const
1074 : {
1075 21 : if( mxFrame )
1076 19 : mxFrame->Convert( rPropSet );
1077 21 : }
1078 :
1079 46 : void XclImpChText::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const
1080 : {
1081 46 : if( mxSrcLink )
1082 46 : mxSrcLink->ConvertNumFmt( rPropSet, bPercent );
1083 46 : }
1084 :
1085 65 : void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeInfo& rTypeInfo ) const
1086 : {
1087 : // existing CHFRLABELPROPS record wins over flags from CHTEXT
1088 65 : sal_uInt16 nShowFlags = mxLabelProps ? mxLabelProps->mnFlags : maData.mnFlags;
1089 65 : sal_uInt16 SHOWANYCATEG = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWCATEG : (EXC_CHTEXT_SHOWCATEGPERC | EXC_CHTEXT_SHOWCATEG);
1090 65 : sal_uInt16 SHOWANYVALUE = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWVALUE : EXC_CHTEXT_SHOWVALUE;
1091 65 : sal_uInt16 SHOWANYPERCENT = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWPERCENT : (EXC_CHTEXT_SHOWPERCENT | EXC_CHTEXT_SHOWCATEGPERC);
1092 65 : sal_uInt16 SHOWANYBUBBLE = mxLabelProps ? EXC_CHFRLABELPROPS_SHOWBUBBLE : EXC_CHTEXT_SHOWBUBBLE;
1093 :
1094 : // get raw flags for label values
1095 65 : bool bShowNone = IsDeleted();
1096 65 : bool bShowCateg = !bShowNone && ::get_flag( nShowFlags, SHOWANYCATEG );
1097 65 : bool bShowPercent = !bShowNone && ::get_flag( nShowFlags, SHOWANYPERCENT );
1098 65 : bool bShowValue = !bShowNone && ::get_flag( nShowFlags, SHOWANYVALUE );
1099 65 : bool bShowBubble = !bShowNone && ::get_flag( nShowFlags, SHOWANYBUBBLE );
1100 :
1101 : // adjust to Chart2 behaviour
1102 65 : if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
1103 0 : bShowValue = bShowBubble; // Chart2 bubble charts show bubble size if 'ShowValue' is set
1104 :
1105 : // other flags
1106 65 : bool bShowAny = bShowValue || bShowPercent || bShowCateg;
1107 65 : bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL );
1108 :
1109 : // create API struct for label values, set API label separator
1110 65 : cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
1111 65 : rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel );
1112 65 : String aSep = mxLabelProps ? mxLabelProps->maSeparator : rtl::OUString('\n');
1113 65 : if( aSep.Len() == 0 )
1114 0 : aSep = CREATE_STRING( "; " );
1115 65 : rPropSet.SetStringProperty( EXC_CHPROP_LABELSEPARATOR, aSep );
1116 :
1117 : // text properties of attached label
1118 65 : if( bShowAny )
1119 : {
1120 59 : ConvertFont( rPropSet );
1121 59 : ConvertRotation( rPropSet, false );
1122 : // label placement
1123 : using namespace cssc::DataLabelPlacement;
1124 59 : sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos;
1125 59 : switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) )
1126 : {
1127 38 : case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break;
1128 0 : case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break;
1129 0 : case EXC_CHTEXT_POS_INSIDE: nPlacement = INSIDE; break;
1130 2 : case EXC_CHTEXT_POS_CENTER: nPlacement = CENTER; break;
1131 0 : case EXC_CHTEXT_POS_AXIS: nPlacement = NEAR_ORIGIN; break;
1132 0 : case EXC_CHTEXT_POS_ABOVE: nPlacement = TOP; break;
1133 0 : case EXC_CHTEXT_POS_BELOW: nPlacement = BOTTOM; break;
1134 0 : case EXC_CHTEXT_POS_LEFT: nPlacement = LEFT; break;
1135 0 : case EXC_CHTEXT_POS_RIGHT: nPlacement = RIGHT; break;
1136 0 : case EXC_CHTEXT_POS_AUTO: nPlacement = AVOID_OVERLAP; break;
1137 : }
1138 59 : rPropSet.SetProperty( EXC_CHPROP_LABELPLACEMENT, nPlacement );
1139 : // label number format (percentage format wins over value format)
1140 59 : if( bShowPercent || bShowValue )
1141 46 : ConvertNumFmt( rPropSet, bShowPercent );
1142 65 : }
1143 65 : }
1144 :
1145 21 : Reference< XTitle > XclImpChText::CreateTitle() const
1146 : {
1147 21 : Reference< XTitle > xTitle;
1148 21 : if( mxSrcLink && mxSrcLink->HasString() )
1149 : {
1150 : // create the formatted strings
1151 : Sequence< Reference< XFormattedString > > aStringSeq(
1152 21 : mxSrcLink->CreateStringSequence( GetChRoot(), GetFontIndex(), GetFontColor() ) );
1153 21 : if( aStringSeq.hasElements() )
1154 : {
1155 : // create the title object
1156 21 : xTitle.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_TITLE ), UNO_QUERY );
1157 21 : if( xTitle.is() )
1158 : {
1159 : // set the formatted strings
1160 21 : xTitle->setText( aStringSeq );
1161 : // more title formatting properties
1162 21 : ScfPropertySet aTitleProp( xTitle );
1163 21 : ConvertFrame( aTitleProp );
1164 21 : ConvertRotation( aTitleProp, true );
1165 : }
1166 21 : }
1167 : }
1168 21 : return xTitle;
1169 : }
1170 :
1171 21 : void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const
1172 : {
1173 42 : if( !mxFramePos ) return;
1174 :
1175 21 : const XclChFramePos& rPosData = mxFramePos->GetFramePosData();
1176 : OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT),
1177 : "XclImpChText::ConvertTitlePosition - unexpected frame position mode" );
1178 :
1179 : /* Check if title is moved manually. To get the actual position of the
1180 : title, we do some kind of hack and use the values from the CHTEXT
1181 : record, effectively ignoring the contents of the CHFRAMEPOS record
1182 : which contains the position relative to the default title position
1183 : (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record).
1184 : Especially when it comes to axis titles, things would become very
1185 : complicated here, because the relative title position is stored in a
1186 : measurement unit that is dependent on the size of the inner plot area,
1187 : the interpretation of the X and Y coordinate is dependent on the
1188 : direction of the axis, and in 3D charts, and the title default
1189 : positions are dependent on the 3D view settings (rotation, elevation,
1190 : and perspective). Thus, it is easier to assume that the creator has
1191 : written out the correct absolute position and size of the title in the
1192 : CHTEXT record. This is assured by checking that the shape size stored
1193 : in the CHTEXT record is non-zero. */
1194 21 : if( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) &&
1195 : ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) &&
1196 : (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0) ) try
1197 : {
1198 20 : Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW );
1199 : // the call to XShape.getSize() may recalc the chart view
1200 20 : ::com::sun::star::awt::Size aTitleSize = xTitleShape->getSize();
1201 : // rotated titles need special handling...
1202 20 : sal_Int32 nScRot = XclTools::GetScRotation( GetRotation(), 0 );
1203 20 : double fRad = nScRot * F_PI18000;
1204 20 : double fSin = fabs( sin( fRad ) );
1205 20 : double fCos = fabs( cos( fRad ) );
1206 : ::com::sun::star::awt::Size aBoundSize(
1207 : static_cast< sal_Int32 >( fCos * aTitleSize.Width + fSin * aTitleSize.Height + 0.5 ),
1208 20 : static_cast< sal_Int32 >( fSin * aTitleSize.Width + fCos * aTitleSize.Height + 0.5 ) );
1209 : // calculate the title position from the values in the CHTEXT record
1210 : ::com::sun::star::awt::Point aTitlePos(
1211 20 : CalcHmmFromChartX( maData.maRect.mnX ),
1212 40 : CalcHmmFromChartY( maData.maRect.mnY ) );
1213 : // add part of height to X direction, if title is rotated down (clockwise)
1214 20 : if( nScRot > 18000 )
1215 0 : aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 );
1216 : // add part of width to Y direction, if title is rotated up (counterclockwise)
1217 20 : else if( nScRot > 0 )
1218 0 : aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 );
1219 : // set the resulting position at the title shape
1220 20 : xTitleShape->setPosition( aTitlePos );
1221 : }
1222 0 : catch( Exception& )
1223 : {
1224 : }
1225 : }
1226 :
1227 0 : void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm )
1228 : {
1229 0 : if( GetBiff() == EXC_BIFF8 )
1230 : {
1231 0 : mxLabelProps.reset( new XclChFrLabelProps );
1232 : sal_uInt16 nSepLen;
1233 0 : rStrm.Ignore( 12 );
1234 0 : rStrm >> mxLabelProps->mnFlags >> nSepLen;
1235 0 : if( nSepLen > 0 )
1236 0 : mxLabelProps->maSeparator = rStrm.ReadUniString( nSepLen );
1237 : }
1238 0 : }
1239 :
1240 : namespace {
1241 :
1242 21 : void lclUpdateText( XclImpChTextRef& rxText, const XclImpChText* xDefText )
1243 : {
1244 21 : if( rxText )
1245 21 : rxText->UpdateText( xDefText );
1246 : else
1247 : {
1248 0 : XclImpChTextRef xNew(new XclImpChText(*xDefText));
1249 0 : rxText = xNew;
1250 : }
1251 21 : }
1252 :
1253 160 : void lclFinalizeTitle( XclImpChTextRef& rxTitle, const XclImpChText* pDefText, const String& rAutoTitle )
1254 : {
1255 : /* Do not update a title, if it is not visible (if rxTitle is null).
1256 : Existing reference indicates enabled title. */
1257 160 : if( rxTitle )
1258 : {
1259 21 : if( !rxTitle->HasString() )
1260 19 : rxTitle->SetString( rAutoTitle );
1261 21 : if( rxTitle->HasString() )
1262 21 : rxTitle->UpdateText(pDefText);
1263 : else
1264 0 : rxTitle.reset();
1265 : }
1266 160 : }
1267 :
1268 : } // namespace
1269 :
1270 : // Data series ================================================================
1271 :
1272 114 : void XclImpChMarkerFormat::ReadChMarkerFormat( XclImpStream& rStrm )
1273 : {
1274 114 : rStrm >> maData.maLineColor >> maData.maFillColor >> maData.mnMarkerType >> maData.mnFlags;
1275 :
1276 114 : const XclImpRoot& rRoot = rStrm.GetRoot();
1277 114 : if( rRoot.GetBiff() == EXC_BIFF8 )
1278 : {
1279 : // BIFF8: index into palette used instead of RGB data
1280 114 : const XclImpPalette& rPal = rRoot.GetPalette();
1281 114 : maData.maLineColor = rPal.GetColor( rStrm.ReaduInt16() );
1282 114 : maData.maFillColor = rPal.GetColor( rStrm.ReaduInt16() );
1283 : // marker size
1284 114 : rStrm >> maData.mnMarkerSize;
1285 : }
1286 114 : }
1287 :
1288 1 : void XclImpChMarkerFormat::Convert( const XclImpChRoot& rRoot,
1289 : ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, sal_Int16 nLineWeight ) const
1290 : {
1291 1 : if( IsAuto() )
1292 : {
1293 1 : XclChMarkerFormat aMarkerFmt;
1294 : // line and fill color of the symbol are equal to series line color
1295 : //! TODO: Excel sets no fill color for specific symbols (e.g. cross)
1296 1 : aMarkerFmt.maLineColor = aMarkerFmt.maFillColor = rRoot.GetSeriesLineAutoColor( nFormatIdx );
1297 1 : switch( nLineWeight )
1298 : {
1299 0 : case EXC_CHLINEFORMAT_HAIR: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_HAIRSIZE; break;
1300 1 : case EXC_CHLINEFORMAT_SINGLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE; break;
1301 0 : case EXC_CHLINEFORMAT_DOUBLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_DOUBLESIZE; break;
1302 0 : case EXC_CHLINEFORMAT_TRIPLE: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_TRIPLESIZE; break;
1303 0 : default: aMarkerFmt.mnMarkerSize = EXC_CHMARKERFORMAT_SINGLESIZE;
1304 : }
1305 1 : aMarkerFmt.mnMarkerType = XclChartHelper::GetAutoMarkerType( nFormatIdx );
1306 1 : rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, aMarkerFmt );
1307 : }
1308 : else
1309 : {
1310 0 : rRoot.GetChartPropSetHelper().WriteMarkerProperties( rPropSet, maData );
1311 : }
1312 1 : }
1313 :
1314 0 : void XclImpChMarkerFormat::ConvertColor( const XclImpChRoot& rRoot,
1315 : ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx ) const
1316 : {
1317 0 : Color aLineColor = IsAuto() ? rRoot.GetSeriesLineAutoColor( nFormatIdx ) : maData.maFillColor;
1318 0 : rPropSet.SetColorProperty( EXC_CHPROP_COLOR, aLineColor );
1319 0 : }
1320 :
1321 : // ----------------------------------------------------------------------------
1322 :
1323 114 : XclImpChPieFormat::XclImpChPieFormat() :
1324 114 : mnPieDist( 0 )
1325 : {
1326 114 : }
1327 :
1328 114 : void XclImpChPieFormat::ReadChPieFormat( XclImpStream& rStrm )
1329 : {
1330 114 : rStrm >> mnPieDist;
1331 114 : }
1332 :
1333 92 : void XclImpChPieFormat::Convert( ScfPropertySet& rPropSet ) const
1334 : {
1335 92 : double fApiDist = ::std::min< double >( mnPieDist / 100.0, 1.0 );
1336 92 : rPropSet.SetProperty( EXC_CHPROP_OFFSET, fApiDist );
1337 92 : }
1338 :
1339 : // ----------------------------------------------------------------------------
1340 :
1341 0 : XclImpChSeriesFormat::XclImpChSeriesFormat() :
1342 0 : mnFlags( 0 )
1343 : {
1344 0 : }
1345 :
1346 0 : void XclImpChSeriesFormat::ReadChSeriesFormat( XclImpStream& rStrm )
1347 : {
1348 0 : rStrm >> mnFlags;
1349 0 : }
1350 :
1351 : // ----------------------------------------------------------------------------
1352 :
1353 116 : void XclImpCh3dDataFormat::ReadCh3dDataFormat( XclImpStream& rStrm )
1354 : {
1355 116 : rStrm >> maData.mnBase >> maData.mnTop;
1356 116 : }
1357 :
1358 0 : void XclImpCh3dDataFormat::Convert( ScfPropertySet& rPropSet ) const
1359 : {
1360 : using namespace ::com::sun::star::chart2::DataPointGeometry3D;
1361 : sal_Int32 nApiType = (maData.mnBase == EXC_CH3DDATAFORMAT_RECT) ?
1362 : ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CUBOID : PYRAMID) :
1363 0 : ((maData.mnTop == EXC_CH3DDATAFORMAT_STRAIGHT) ? CYLINDER : CONE);
1364 0 : rPropSet.SetProperty( EXC_CHPROP_GEOMETRY3D, nApiType );
1365 0 : }
1366 :
1367 : // ----------------------------------------------------------------------------
1368 :
1369 32 : XclImpChAttachedLabel::XclImpChAttachedLabel( const XclImpChRoot& rRoot ) :
1370 : XclImpChRoot( rRoot ),
1371 32 : mnFlags( 0 )
1372 : {
1373 32 : }
1374 :
1375 32 : void XclImpChAttachedLabel::ReadChAttachedLabel( XclImpStream& rStrm )
1376 : {
1377 32 : rStrm >> mnFlags;
1378 32 : }
1379 :
1380 0 : XclImpChTextRef XclImpChAttachedLabel::CreateDataLabel( const XclImpChText* pParent ) const
1381 : {
1382 0 : const sal_uInt16 EXC_CHATTLABEL_SHOWANYVALUE = EXC_CHATTLABEL_SHOWVALUE;
1383 0 : const sal_uInt16 EXC_CHATTLABEL_SHOWANYPERCENT = EXC_CHATTLABEL_SHOWPERCENT | EXC_CHATTLABEL_SHOWCATEGPERC;
1384 0 : const sal_uInt16 EXC_CHATTLABEL_SHOWANYCATEG = EXC_CHATTLABEL_SHOWCATEG | EXC_CHATTLABEL_SHOWCATEGPERC;
1385 :
1386 0 : XclImpChTextRef xLabel( pParent ? new XclImpChText( *pParent ) : new XclImpChText( GetChRoot() ) );
1387 : xLabel->UpdateDataLabel(
1388 0 : ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYCATEG ),
1389 0 : ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYVALUE ),
1390 0 : ::get_flag( mnFlags, EXC_CHATTLABEL_SHOWANYPERCENT ) );
1391 0 : return xLabel;
1392 : }
1393 :
1394 : // ----------------------------------------------------------------------------
1395 :
1396 116 : XclImpChDataFormat::XclImpChDataFormat( const XclImpChRoot& rRoot ) :
1397 116 : XclImpChRoot( rRoot )
1398 : {
1399 116 : }
1400 :
1401 116 : void XclImpChDataFormat::ReadHeaderRecord( XclImpStream& rStrm )
1402 : {
1403 116 : rStrm >> maData.maPointPos.mnPointIdx
1404 232 : >> maData.maPointPos.mnSeriesIdx
1405 232 : >> maData.mnFormatIdx
1406 232 : >> maData.mnFlags;
1407 116 : }
1408 :
1409 1254 : void XclImpChDataFormat::ReadSubRecord( XclImpStream& rStrm )
1410 : {
1411 1254 : switch( rStrm.GetRecId() )
1412 : {
1413 : case EXC_ID_CHMARKERFORMAT:
1414 114 : mxMarkerFmt.reset( new XclImpChMarkerFormat );
1415 114 : mxMarkerFmt->ReadChMarkerFormat( rStrm );
1416 114 : break;
1417 : case EXC_ID_CHPIEFORMAT:
1418 114 : mxPieFmt.reset( new XclImpChPieFormat );
1419 114 : mxPieFmt->ReadChPieFormat( rStrm );
1420 114 : break;
1421 : case EXC_ID_CHSERIESFORMAT:
1422 0 : mxSeriesFmt.reset( new XclImpChSeriesFormat );
1423 0 : mxSeriesFmt->ReadChSeriesFormat( rStrm );
1424 0 : break;
1425 : case EXC_ID_CH3DDATAFORMAT:
1426 116 : mx3dDataFmt.reset( new XclImpCh3dDataFormat );
1427 116 : mx3dDataFmt->ReadCh3dDataFormat( rStrm );
1428 116 : break;
1429 : case EXC_ID_CHATTACHEDLABEL:
1430 32 : mxAttLabel.reset( new XclImpChAttachedLabel( GetChRoot() ) );
1431 32 : mxAttLabel->ReadChAttachedLabel( rStrm );
1432 32 : break;
1433 : default:
1434 878 : XclImpChFrameBase::ReadSubRecord( rStrm );
1435 : }
1436 1254 : }
1437 :
1438 0 : void XclImpChDataFormat::SetPointPos( const XclChDataPointPos& rPointPos, sal_uInt16 nFormatIdx )
1439 : {
1440 0 : maData.maPointPos = rPointPos;
1441 0 : maData.mnFormatIdx = nFormatIdx;
1442 0 : }
1443 :
1444 19 : void XclImpChDataFormat::UpdateGroupFormat( const XclChExtTypeInfo& rTypeInfo )
1445 : {
1446 : // remove formats not used for the current chart type
1447 19 : RemoveUnusedFormats( rTypeInfo );
1448 19 : }
1449 :
1450 40 : void XclImpChDataFormat::UpdateSeriesFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pGroupFmt )
1451 : {
1452 : // update missing formats from passed chart type group format
1453 40 : if( pGroupFmt )
1454 : {
1455 19 : if( !mxLineFmt )
1456 0 : mxLineFmt = pGroupFmt->mxLineFmt;
1457 19 : if( !mxAreaFmt && !mxEscherFmt )
1458 : {
1459 0 : mxAreaFmt = pGroupFmt->mxAreaFmt;
1460 0 : mxEscherFmt = pGroupFmt->mxEscherFmt;
1461 : }
1462 19 : if( !mxMarkerFmt )
1463 0 : mxMarkerFmt = pGroupFmt->mxMarkerFmt;
1464 19 : if( !mxPieFmt )
1465 0 : mxPieFmt = pGroupFmt->mxPieFmt;
1466 19 : if( !mxSeriesFmt )
1467 19 : mxSeriesFmt = pGroupFmt->mxSeriesFmt;
1468 19 : if( !mx3dDataFmt )
1469 0 : mx3dDataFmt = pGroupFmt->mx3dDataFmt;
1470 19 : if( !mxAttLabel )
1471 4 : mxAttLabel = pGroupFmt->mxAttLabel;
1472 : }
1473 :
1474 : /* Create missing but required formats. Existing line, area, and marker
1475 : format objects are needed to create automatic series formatting. */
1476 40 : if( !mxLineFmt )
1477 2 : mxLineFmt.reset( new XclImpChLineFormat );
1478 40 : if( !mxAreaFmt && !mxEscherFmt )
1479 2 : mxAreaFmt.reset( new XclImpChAreaFormat );
1480 40 : if( !mxMarkerFmt )
1481 2 : mxMarkerFmt.reset( new XclImpChMarkerFormat );
1482 :
1483 : // remove formats not used for the current chart type
1484 40 : RemoveUnusedFormats( rTypeInfo );
1485 : // update data label
1486 40 : UpdateDataLabel( pGroupFmt );
1487 40 : }
1488 :
1489 57 : void XclImpChDataFormat::UpdatePointFormat( const XclChExtTypeInfo& rTypeInfo, const XclImpChDataFormat* pSeriesFmt )
1490 : {
1491 : // remove formats if they are automatic in this and in the passed series format
1492 57 : if( pSeriesFmt )
1493 : {
1494 57 : if( IsAutoLine() && pSeriesFmt->IsAutoLine() )
1495 0 : mxLineFmt.reset();
1496 57 : if( IsAutoArea() && pSeriesFmt->IsAutoArea() )
1497 0 : mxAreaFmt.reset();
1498 57 : if( IsAutoMarker() && pSeriesFmt->IsAutoMarker() )
1499 57 : mxMarkerFmt.reset();
1500 57 : mxSeriesFmt.reset();
1501 : }
1502 :
1503 : // Excel ignores 3D bar format for single data points
1504 57 : mx3dDataFmt.reset();
1505 : // remove point line formats for linear chart types, TODO: implement in OOChart
1506 57 : if( !rTypeInfo.IsSeriesFrameFormat() )
1507 0 : mxLineFmt.reset();
1508 :
1509 : // remove formats not used for the current chart type
1510 57 : RemoveUnusedFormats( rTypeInfo );
1511 : // update data label
1512 57 : UpdateDataLabel( pSeriesFmt );
1513 57 : }
1514 :
1515 0 : void XclImpChDataFormat::UpdateTrendLineFormat()
1516 : {
1517 0 : if( !mxLineFmt )
1518 0 : mxLineFmt.reset( new XclImpChLineFormat );
1519 0 : mxAreaFmt.reset();
1520 0 : mxEscherFmt.reset();
1521 0 : mxMarkerFmt.reset();
1522 0 : mxPieFmt.reset();
1523 0 : mxSeriesFmt.reset();
1524 0 : mx3dDataFmt.reset();
1525 0 : mxAttLabel.reset();
1526 : // update data label
1527 0 : UpdateDataLabel( 0 );
1528 0 : }
1529 :
1530 97 : void XclImpChDataFormat::Convert( ScfPropertySet& rPropSet, const XclChExtTypeInfo& rTypeInfo ) const
1531 : {
1532 : /* Line and area format.
1533 : #i71810# If the data points are filled with bitmaps, textures, or
1534 : patterns, then only bar charts will use the CHPICFORMAT record to
1535 : determine stacking/streching mode. All other chart types ignore this
1536 : record and always use the property 'fill-type' from the DFF property
1537 : set (streched for bitmaps, and stacked for textures and patterns). */
1538 97 : bool bUsePicFmt = rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_BAR;
1539 97 : ConvertFrameBase( GetChRoot(), rPropSet, rTypeInfo.GetSeriesObjectType(), maData.mnFormatIdx, bUsePicFmt );
1540 :
1541 : #if EXC_CHART2_3DBAR_HAIRLINES_ONLY
1542 : // #i83151# only hair lines in 3D charts with filled data points
1543 97 : if( rTypeInfo.mb3dChart && rTypeInfo.IsSeriesFrameFormat() && mxLineFmt && mxLineFmt->HasLine() )
1544 0 : rPropSet.SetProperty< sal_Int32 >( "BorderWidth", 0 );
1545 : #endif
1546 :
1547 : // other formatting
1548 97 : if( mxMarkerFmt )
1549 1 : mxMarkerFmt->Convert( GetChRoot(), rPropSet, maData.mnFormatIdx, GetLineWeight() );
1550 97 : if( mxPieFmt )
1551 92 : mxPieFmt->Convert( rPropSet );
1552 97 : if( mx3dDataFmt )
1553 0 : mx3dDataFmt->Convert( rPropSet );
1554 97 : if( mxLabel )
1555 65 : mxLabel->ConvertDataLabel( rPropSet, rTypeInfo );
1556 :
1557 : // 3D settings
1558 97 : rPropSet.SetProperty< sal_Int16 >( EXC_CHPROP_PERCENTDIAGONAL, 0 );
1559 :
1560 : /* Special case: set marker color as line color, if series line is not
1561 : visible. This makes the color visible in the marker area.
1562 : TODO: remove this if OOChart supports own colors in markers. */
1563 97 : if( !rTypeInfo.IsSeriesFrameFormat() && !HasLine() && mxMarkerFmt )
1564 0 : mxMarkerFmt->ConvertColor( GetChRoot(), rPropSet, maData.mnFormatIdx );
1565 97 : }
1566 :
1567 0 : void XclImpChDataFormat::ConvertLine( ScfPropertySet& rPropSet, XclChObjectType eObjType ) const
1568 : {
1569 0 : ConvertLineBase( GetChRoot(), rPropSet, eObjType );
1570 0 : }
1571 :
1572 55 : void XclImpChDataFormat::ConvertArea( ScfPropertySet& rPropSet, sal_uInt16 nFormatIdx, bool bUsePicFmt ) const
1573 : {
1574 55 : ConvertAreaBase( GetChRoot(), rPropSet, EXC_CHOBJTYPE_FILLEDSERIES, nFormatIdx, bUsePicFmt );
1575 55 : }
1576 :
1577 116 : void XclImpChDataFormat::RemoveUnusedFormats( const XclChExtTypeInfo& rTypeInfo )
1578 : {
1579 : // data point marker only in linear 2D charts
1580 116 : if( rTypeInfo.IsSeriesFrameFormat() )
1581 115 : mxMarkerFmt.reset();
1582 : // pie format only in pie/donut charts
1583 116 : if( rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_PIE )
1584 6 : mxPieFmt.reset();
1585 : // 3D format only in 3D bar charts
1586 116 : if( !rTypeInfo.mb3dChart || (rTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
1587 116 : mx3dDataFmt.reset();
1588 116 : }
1589 :
1590 97 : void XclImpChDataFormat::UpdateDataLabel( const XclImpChDataFormat* pParentFmt )
1591 : {
1592 : /* CHTEXT groups linked to data labels override existing CHATTACHEDLABEL
1593 : records. Only if there is a CHATTACHEDLABEL record without a CHTEXT
1594 : group, the contents of the CHATTACHEDLABEL record are used. In this
1595 : case a new CHTEXT group is created and filled with the settings from
1596 : the CHATTACHEDLABEL record. */
1597 97 : const XclImpChText* pDefText = NULL;
1598 97 : if (pParentFmt)
1599 76 : pDefText = pParentFmt->GetDataLabel();
1600 97 : if (!pDefText)
1601 40 : pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_DATALABEL );
1602 97 : if (mxLabel)
1603 65 : mxLabel->UpdateText(pDefText);
1604 32 : else if (mxAttLabel)
1605 0 : mxLabel = mxAttLabel->CreateDataLabel( pDefText );
1606 97 : }
1607 :
1608 : // ----------------------------------------------------------------------------
1609 :
1610 0 : XclImpChSerTrendLine::XclImpChSerTrendLine( const XclImpChRoot& rRoot ) :
1611 0 : XclImpChRoot( rRoot )
1612 : {
1613 0 : }
1614 :
1615 0 : void XclImpChSerTrendLine::ReadChSerTrendLine( XclImpStream& rStrm )
1616 : {
1617 0 : rStrm >> maData.mnLineType
1618 0 : >> maData.mnOrder
1619 0 : >> maData.mfIntercept
1620 0 : >> maData.mnShowEquation
1621 0 : >> maData.mnShowRSquared
1622 0 : >> maData.mfForecastFor
1623 0 : >> maData.mfForecastBack;
1624 0 : }
1625 :
1626 0 : Reference< XRegressionCurve > XclImpChSerTrendLine::CreateRegressionCurve() const
1627 : {
1628 : // trend line type
1629 0 : OUString aService;
1630 0 : switch( maData.mnLineType )
1631 : {
1632 : case EXC_CHSERTREND_POLYNOMIAL:
1633 : // TODO: only linear trend lines are supported by OOChart (#i20819#)
1634 0 : if( maData.mnOrder == 1 )
1635 0 : aService = SERVICE_CHART2_LINEARREGCURVE;
1636 0 : break;
1637 : case EXC_CHSERTREND_EXPONENTIAL:
1638 0 : aService = SERVICE_CHART2_EXPREGCURVE;
1639 0 : break;
1640 : case EXC_CHSERTREND_LOGARITHMIC:
1641 0 : aService = SERVICE_CHART2_LOGREGCURVE;
1642 0 : break;
1643 : case EXC_CHSERTREND_POWER:
1644 0 : aService = SERVICE_CHART2_POTREGCURVE;
1645 0 : break;
1646 : }
1647 0 : Reference< XRegressionCurve > xRegCurve;
1648 0 : if( !aService.isEmpty() )
1649 0 : xRegCurve.set( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
1650 :
1651 : // trend line formatting
1652 0 : if( xRegCurve.is() && mxDataFmt )
1653 : {
1654 0 : ScfPropertySet aPropSet( xRegCurve );
1655 0 : mxDataFmt->ConvertLine( aPropSet, EXC_CHOBJTYPE_TRENDLINE );
1656 :
1657 : // #i83100# show equation and correlation coefficient
1658 0 : ScfPropertySet aLabelProp( xRegCurve->getEquationProperties() );
1659 0 : aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWEQUATION, maData.mnShowEquation != 0 );
1660 0 : aLabelProp.SetBoolProperty( EXC_CHPROP_SHOWCORRELATION, maData.mnShowRSquared != 0 );
1661 :
1662 : // #i83100# formatting of the equation text box
1663 0 : if (const XclImpChText* pLabel = mxDataFmt->GetDataLabel())
1664 : {
1665 0 : pLabel->ConvertFont( aLabelProp );
1666 0 : pLabel->ConvertFrame( aLabelProp );
1667 0 : pLabel->ConvertNumFmt( aLabelProp, false );
1668 0 : }
1669 : }
1670 :
1671 : // missing features
1672 : // #i20819# polynomial trend lines
1673 : // #i66819# moving average trend lines
1674 : // #i5085# manual trend line size
1675 : // #i34093# manual crossing point
1676 :
1677 0 : return xRegCurve;
1678 : }
1679 :
1680 : // ----------------------------------------------------------------------------
1681 :
1682 0 : XclImpChSerErrorBar::XclImpChSerErrorBar( const XclImpChRoot& rRoot ) :
1683 0 : XclImpChRoot( rRoot )
1684 : {
1685 0 : }
1686 :
1687 0 : void XclImpChSerErrorBar::ReadChSerErrorBar( XclImpStream& rStrm )
1688 : {
1689 0 : rStrm >> maData.mnBarType >> maData.mnSourceType >> maData.mnLineEnd;
1690 0 : rStrm.Ignore( 1 );
1691 0 : rStrm >> maData.mfValue >> maData.mnValueCount;
1692 0 : }
1693 :
1694 0 : void XclImpChSerErrorBar::SetSeriesData( XclImpChSourceLinkRef xValueLink, XclImpChDataFormatRef xDataFmt )
1695 : {
1696 0 : mxValueLink = xValueLink;
1697 0 : mxDataFmt = xDataFmt;
1698 0 : }
1699 :
1700 0 : Reference< XLabeledDataSequence > XclImpChSerErrorBar::CreateValueSequence() const
1701 : {
1702 0 : return lclCreateLabeledDataSequence( mxValueLink, XclChartHelper::GetErrorBarValuesRole( maData.mnBarType ) );
1703 : }
1704 :
1705 0 : Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSerErrorBar* pPosBar, const XclImpChSerErrorBar* pNegBar )
1706 : {
1707 0 : Reference< XPropertySet > xErrorBar;
1708 :
1709 0 : if( const XclImpChSerErrorBar* pPrimaryBar = pPosBar ? pPosBar : pNegBar )
1710 : {
1711 0 : xErrorBar.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_ERRORBAR ), UNO_QUERY );
1712 0 : ScfPropertySet aBarProp( xErrorBar );
1713 :
1714 : // plus/minus bars visible?
1715 0 : aBarProp.SetBoolProperty( EXC_CHPROP_SHOWPOSITIVEERROR, pPosBar != 0 );
1716 0 : aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 );
1717 :
1718 : // type of displayed error
1719 0 : switch( pPrimaryBar->maData.mnSourceType )
1720 : {
1721 : case EXC_CHSERERR_PERCENT:
1722 0 : aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::RELATIVE );
1723 0 : aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1724 0 : aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1725 0 : break;
1726 : case EXC_CHSERERR_FIXED:
1727 0 : aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::ABSOLUTE );
1728 0 : aBarProp.SetProperty( EXC_CHPROP_POSITIVEERROR, pPrimaryBar->maData.mfValue );
1729 0 : aBarProp.SetProperty( EXC_CHPROP_NEGATIVEERROR, pPrimaryBar->maData.mfValue );
1730 0 : break;
1731 : case EXC_CHSERERR_STDDEV:
1732 0 : aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_DEVIATION );
1733 0 : aBarProp.SetProperty( EXC_CHPROP_WEIGHT, pPrimaryBar->maData.mfValue );
1734 0 : break;
1735 : case EXC_CHSERERR_STDERR:
1736 0 : aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::STANDARD_ERROR );
1737 0 : break;
1738 : case EXC_CHSERERR_CUSTOM:
1739 : {
1740 0 : aBarProp.SetProperty( EXC_CHPROP_ERRORBARSTYLE, cssc::ErrorBarStyle::FROM_DATA );
1741 : // attach data sequences to erorr bar
1742 0 : Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
1743 0 : if( xDataSink.is() )
1744 : {
1745 : // create vector of all value sequences
1746 0 : ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
1747 : // add positive values
1748 0 : if( pPosBar )
1749 : {
1750 0 : Reference< XLabeledDataSequence > xValueSeq = pPosBar->CreateValueSequence();
1751 0 : if( xValueSeq.is() )
1752 0 : aLabeledSeqVec.push_back( xValueSeq );
1753 : }
1754 : // add negative values
1755 0 : if( pNegBar )
1756 : {
1757 0 : Reference< XLabeledDataSequence > xValueSeq = pNegBar->CreateValueSequence();
1758 0 : if( xValueSeq.is() )
1759 0 : aLabeledSeqVec.push_back( xValueSeq );
1760 : }
1761 : // attach labeled data sequences to series
1762 0 : if( aLabeledSeqVec.empty() )
1763 0 : xErrorBar.clear();
1764 : else
1765 0 : xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
1766 0 : }
1767 : }
1768 0 : break;
1769 : default:
1770 0 : xErrorBar.clear();
1771 : }
1772 :
1773 : // error bar formatting
1774 0 : if( pPrimaryBar->mxDataFmt && xErrorBar.is() )
1775 0 : pPrimaryBar->mxDataFmt->ConvertLine( aBarProp, EXC_CHOBJTYPE_ERRORBAR );
1776 : }
1777 :
1778 0 : return xErrorBar;
1779 : }
1780 :
1781 : // ----------------------------------------------------------------------------
1782 :
1783 40 : XclImpChSeries::XclImpChSeries( const XclImpChRoot& rRoot, sal_uInt16 nSeriesIdx ) :
1784 : XclImpChRoot( rRoot ),
1785 : mnGroupIdx( EXC_CHSERGROUP_NONE ),
1786 : mnSeriesIdx( nSeriesIdx ),
1787 40 : mnParentIdx( EXC_CHSERIES_INVALID )
1788 : {
1789 40 : }
1790 :
1791 40 : void XclImpChSeries::ReadHeaderRecord( XclImpStream& rStrm )
1792 : {
1793 40 : rStrm >> maData.mnCategType >> maData.mnValueType >> maData.mnCategCount >> maData.mnValueCount;
1794 40 : if( GetBiff() == EXC_BIFF8 )
1795 40 : rStrm >> maData.mnBubbleType >> maData.mnBubbleCount;
1796 40 : }
1797 :
1798 445 : void XclImpChSeries::ReadSubRecord( XclImpStream& rStrm )
1799 : {
1800 445 : switch( rStrm.GetRecId() )
1801 : {
1802 : case EXC_ID_CHSOURCELINK:
1803 160 : ReadChSourceLink( rStrm );
1804 160 : break;
1805 : case EXC_ID_CHDATAFORMAT:
1806 97 : ReadChDataFormat( rStrm );
1807 97 : break;
1808 : case EXC_ID_CHSERGROUP:
1809 40 : rStrm >> mnGroupIdx;
1810 40 : break;
1811 : case EXC_ID_CHSERPARENT:
1812 0 : ReadChSerParent( rStrm );
1813 0 : break;
1814 : case EXC_ID_CHSERTRENDLINE:
1815 0 : ReadChSerTrendLine( rStrm );
1816 0 : break;
1817 : case EXC_ID_CHSERERRORBAR:
1818 0 : ReadChSerErrorBar( rStrm );
1819 0 : break;
1820 : }
1821 445 : }
1822 :
1823 97 : void XclImpChSeries::SetDataFormat( const XclImpChDataFormatRef& xDataFmt )
1824 : {
1825 97 : if (!xDataFmt)
1826 : return;
1827 :
1828 97 : sal_uInt16 nPointIdx = xDataFmt->GetPointPos().mnPointIdx;
1829 97 : if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
1830 : {
1831 40 : if (mxSeriesFmt)
1832 : // Don't overwrite the existing format.
1833 : return;
1834 :
1835 40 : mxSeriesFmt = xDataFmt;
1836 40 : if (HasParentSeries())
1837 : return;
1838 :
1839 40 : XclImpChTypeGroupRef pTypeGroup = GetChartData().GetTypeGroup(mnGroupIdx);
1840 40 : if (pTypeGroup)
1841 40 : pTypeGroup->SetUsedFormatIndex(xDataFmt->GetFormatIdx());
1842 :
1843 40 : return;
1844 : }
1845 :
1846 57 : if (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT)
1847 : // Above the max point count. Bail out.
1848 : return;
1849 :
1850 57 : XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
1851 57 : if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
1852 : {
1853 : // No object exists at this point index position. Insert it.
1854 57 : itr = maPointFmts.insert(itr, XclImpChDataFormatMap::value_type(nPointIdx, xDataFmt));
1855 : }
1856 : }
1857 :
1858 65 : void XclImpChSeries::SetDataLabel( const XclImpChTextRef& xLabel )
1859 : {
1860 65 : if (!xLabel)
1861 : return;
1862 :
1863 65 : sal_uInt16 nPointIdx = xLabel->GetPointPos().mnPointIdx;
1864 65 : if ((nPointIdx != EXC_CHDATAFORMAT_ALLPOINTS) && (nPointIdx >= EXC_CHDATAFORMAT_MAXPOINTCOUNT))
1865 : // Above the maximum allowed data points. Bail out.
1866 : return;
1867 :
1868 65 : XclImpChTextMap::iterator itr = maLabels.lower_bound(nPointIdx);
1869 65 : if (itr == maLabels.end() || maLabels.key_comp()(nPointIdx, itr->first))
1870 : {
1871 : // No object exists at this point index position. Insert it.
1872 65 : itr = maLabels.insert(itr, XclImpChTextMap::value_type(nPointIdx, xLabel));
1873 : }
1874 : }
1875 :
1876 0 : void XclImpChSeries::AddChildSeries( const XclImpChSeries& rSeries )
1877 : {
1878 : OSL_ENSURE( !HasParentSeries(), "XclImpChSeries::AddChildSeries - not allowed for child series" );
1879 :
1880 : /* In Excel, trend lines and error bars are stored as own series. In Calc,
1881 : these are properties of the parent series. This function adds the
1882 : settings of the passed series to this series. */
1883 0 : maTrendLines.insert( maTrendLines.end(), rSeries.maTrendLines.begin(), rSeries.maTrendLines.end() );
1884 0 : maErrorBars.insert( rSeries.maErrorBars.begin(), rSeries.maErrorBars.end() );
1885 0 : }
1886 :
1887 40 : void XclImpChSeries::FinalizeDataFormats()
1888 : {
1889 40 : if( HasParentSeries() )
1890 : {
1891 : // *** series is a child series, e.g. trend line or error bar ***
1892 :
1893 : // create missing series format
1894 0 : if( !mxSeriesFmt )
1895 0 : mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, 0 );
1896 :
1897 0 : if( mxSeriesFmt )
1898 : {
1899 : // #i83100# set text label format, e.g. for trend line equations
1900 0 : XclImpChTextRef xLabel;
1901 0 : XclImpChTextMap::iterator itr = maLabels.find(EXC_CHDATAFORMAT_ALLPOINTS);
1902 0 : if (itr != maLabels.end())
1903 0 : xLabel = itr->second;
1904 0 : mxSeriesFmt->SetDataLabel(xLabel);
1905 : // create missing automatic formats
1906 0 : mxSeriesFmt->UpdateTrendLineFormat();
1907 : }
1908 :
1909 : // copy series formatting to child objects
1910 0 : for( XclImpChSerTrendLineList::iterator aLIt = maTrendLines.begin(), aLEnd = maTrendLines.end(); aLIt != aLEnd; ++aLIt )
1911 0 : (*aLIt)->SetDataFormat( mxSeriesFmt );
1912 0 : for( XclImpChSerErrorBarMap::iterator aMIt = maErrorBars.begin(), aMEnd = maErrorBars.end(); aMIt != aMEnd; ++aMIt )
1913 0 : aMIt->second->SetSeriesData( mxValueLink, mxSeriesFmt );
1914 : }
1915 40 : else if( XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1916 : {
1917 : // *** series is a regular data series ***
1918 :
1919 : // create missing series format
1920 40 : if( !mxSeriesFmt )
1921 : {
1922 : // #i51639# use a new unused format index to create series default format
1923 0 : sal_uInt16 nFormatIdx = pTypeGroup->PopUnusedFormatIndex();
1924 0 : mxSeriesFmt = CreateDataFormat( EXC_CHDATAFORMAT_ALLPOINTS, nFormatIdx );
1925 : }
1926 :
1927 : // set text labels to data formats
1928 105 : for( XclImpChTextMap::iterator aTIt = maLabels.begin(), aTEnd = maLabels.end(); aTIt != aTEnd; ++aTIt )
1929 : {
1930 65 : sal_uInt16 nPointIdx = aTIt->first;
1931 65 : if (nPointIdx == EXC_CHDATAFORMAT_ALLPOINTS)
1932 : {
1933 38 : if (!mxSeriesFmt)
1934 0 : mxSeriesFmt = CreateDataFormat(nPointIdx, EXC_CHDATAFORMAT_DEFAULT);
1935 38 : mxSeriesFmt->SetDataLabel(aTIt->second);
1936 : }
1937 27 : else if (nPointIdx < EXC_CHDATAFORMAT_MAXPOINTCOUNT)
1938 : {
1939 27 : XclImpChDataFormatRef p;
1940 27 : XclImpChDataFormatMap::iterator itr = maPointFmts.lower_bound(nPointIdx);
1941 27 : if (itr == maPointFmts.end() || maPointFmts.key_comp()(nPointIdx, itr->first))
1942 : {
1943 : // No object exists at this point index position. Insert
1944 : // a new one.
1945 0 : p = CreateDataFormat(nPointIdx, EXC_CHDATAFORMAT_DEFAULT);
1946 : itr = maPointFmts.insert(
1947 0 : itr, XclImpChDataFormatMap::value_type(nPointIdx, p));
1948 : }
1949 : else
1950 27 : p = itr->second;
1951 27 : p->SetDataLabel(aTIt->second);
1952 : }
1953 : }
1954 :
1955 : // update series format (copy missing formatting from group default format)
1956 40 : if( mxSeriesFmt )
1957 40 : mxSeriesFmt->UpdateSeriesFormat( pTypeGroup->GetTypeInfo(), pTypeGroup->GetGroupFormat().get() );
1958 :
1959 : // update data point formats (removes unchanged automatic formatting)
1960 97 : for( XclImpChDataFormatMap::iterator aFIt = maPointFmts.begin(), aFEnd = maPointFmts.end(); aFIt != aFEnd; ++aFIt )
1961 57 : aFIt->second->UpdatePointFormat( pTypeGroup->GetTypeInfo(), mxSeriesFmt.get() );
1962 : }
1963 40 : }
1964 :
1965 : namespace {
1966 :
1967 : /** Returns the property set of the specified data point. */
1968 112 : ScfPropertySet lclGetPointPropSet( Reference< XDataSeries > xDataSeries, sal_uInt16 nPointIdx )
1969 : {
1970 112 : ScfPropertySet aPropSet;
1971 : try
1972 : {
1973 112 : aPropSet.Set( xDataSeries->getDataPointByIndex( static_cast< sal_Int32 >( nPointIdx ) ) );
1974 : }
1975 0 : catch( Exception& )
1976 : {
1977 : OSL_FAIL( "lclGetPointPropSet - no data point property set" );
1978 : }
1979 112 : return aPropSet;
1980 : }
1981 :
1982 : } // namespace
1983 :
1984 40 : Reference< XLabeledDataSequence > XclImpChSeries::CreateValueSequence( const OUString& rValueRole ) const
1985 : {
1986 40 : return lclCreateLabeledDataSequence( mxValueLink, rValueRole, mxTitleLink.get() );
1987 : }
1988 :
1989 40 : Reference< XLabeledDataSequence > XclImpChSeries::CreateCategSequence( const OUString& rCategRole ) const
1990 : {
1991 40 : return lclCreateLabeledDataSequence( mxCategLink, rCategRole );
1992 : }
1993 :
1994 40 : Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
1995 : {
1996 40 : Reference< XDataSeries > xDataSeries;
1997 40 : if( const XclImpChTypeGroup* pTypeGroup = GetChartData().GetTypeGroup( mnGroupIdx ).get() )
1998 : {
1999 40 : const XclChExtTypeInfo& rTypeInfo = pTypeGroup->GetTypeInfo();
2000 :
2001 : // create the data series object
2002 40 : xDataSeries.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
2003 :
2004 : // attach data and title sequences to series
2005 40 : Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
2006 40 : if( xDataSink.is() )
2007 : {
2008 : // create vector of all value sequences
2009 40 : ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
2010 : // add Y values
2011 : Reference< XLabeledDataSequence > xYValueSeq =
2012 40 : CreateValueSequence( EXC_CHPROP_ROLE_YVALUES );
2013 40 : if( xYValueSeq.is() )
2014 40 : aLabeledSeqVec.push_back( xYValueSeq );
2015 : // add X values
2016 40 : if( !rTypeInfo.mbCategoryAxis )
2017 : {
2018 : Reference< XLabeledDataSequence > xXValueSeq =
2019 0 : CreateCategSequence( EXC_CHPROP_ROLE_XVALUES );
2020 0 : if( xXValueSeq.is() )
2021 0 : aLabeledSeqVec.push_back( xXValueSeq );
2022 : // add size values of bubble charts
2023 0 : if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES )
2024 : {
2025 : Reference< XLabeledDataSequence > xSizeValueSeq =
2026 0 : lclCreateLabeledDataSequence( mxBubbleLink, EXC_CHPROP_ROLE_SIZEVALUES, mxTitleLink.get() );
2027 0 : if( xSizeValueSeq.is() )
2028 0 : aLabeledSeqVec.push_back( xSizeValueSeq );
2029 0 : }
2030 : }
2031 : // attach labeled data sequences to series
2032 40 : if( !aLabeledSeqVec.empty() )
2033 40 : xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
2034 : }
2035 :
2036 : // series formatting
2037 40 : ScfPropertySet aSeriesProp( xDataSeries );
2038 40 : if( mxSeriesFmt )
2039 40 : mxSeriesFmt->Convert( aSeriesProp, rTypeInfo );
2040 :
2041 : // trend lines
2042 40 : ConvertTrendLines( xDataSeries );
2043 :
2044 : // error bars
2045 40 : Reference< XPropertySet > xErrorBarX = CreateErrorBar( EXC_CHSERERR_XPLUS, EXC_CHSERERR_XMINUS );
2046 40 : if( xErrorBarX.is() )
2047 0 : aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARX, xErrorBarX );
2048 40 : Reference< XPropertySet > xErrorBarY = CreateErrorBar( EXC_CHSERERR_YPLUS, EXC_CHSERERR_YMINUS );
2049 40 : if( xErrorBarY.is() )
2050 0 : aSeriesProp.SetProperty( EXC_CHPROP_ERRORBARY, xErrorBarY );
2051 :
2052 : // own area formatting for every data point (TODO: varying line color not supported)
2053 40 : bool bVarPointFmt = pTypeGroup->HasVarPointFormat() && rTypeInfo.IsSeriesFrameFormat();
2054 : #if EXC_CHART2_VARYCOLORSBY_PROP
2055 : aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, bVarPointFmt );
2056 : #else
2057 40 : aSeriesProp.SetBoolProperty( EXC_CHPROP_VARYCOLORSBY, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
2058 : #endif
2059 : // #i91271# always set area formatting for every point in pie/doughnut charts
2060 40 : if( mxSeriesFmt && ((bVarPointFmt && mxSeriesFmt->IsAutoArea()) || (rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE)) )
2061 : {
2062 92 : for( sal_uInt16 nPointIdx = 0, nPointCount = mxValueLink->GetCellCount(); nPointIdx < nPointCount; ++nPointIdx )
2063 : {
2064 55 : ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, nPointIdx );
2065 55 : mxSeriesFmt->ConvertArea( aPointProp, bVarPointFmt ? nPointIdx : mnSeriesIdx, false );
2066 55 : }
2067 : }
2068 :
2069 : // data point formatting
2070 97 : for( XclImpChDataFormatMap::const_iterator aIt = maPointFmts.begin(), aEnd = maPointFmts.end(); aIt != aEnd; ++aIt )
2071 : {
2072 57 : ScfPropertySet aPointProp = lclGetPointPropSet( xDataSeries, aIt->first );
2073 57 : aIt->second->Convert( aPointProp, rTypeInfo );
2074 97 : }
2075 : }
2076 40 : return xDataSeries;
2077 : }
2078 :
2079 40 : void XclImpChSeries::FillAllSourceLinks( ::std::vector< ScTokenRef >& rTokens ) const
2080 : {
2081 40 : if( mxValueLink )
2082 40 : mxValueLink->FillSourceLink( rTokens );
2083 40 : if( mxCategLink )
2084 40 : mxCategLink->FillSourceLink( rTokens );
2085 40 : if( mxTitleLink )
2086 40 : mxTitleLink->FillSourceLink( rTokens );
2087 40 : if( mxBubbleLink )
2088 40 : mxBubbleLink->FillSourceLink( rTokens );
2089 40 : }
2090 :
2091 160 : void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
2092 : {
2093 160 : XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
2094 160 : xSrcLink->ReadChSourceLink( rStrm );
2095 160 : switch( xSrcLink->GetDestType() )
2096 : {
2097 40 : case EXC_CHSRCLINK_TITLE: mxTitleLink = xSrcLink; break;
2098 40 : case EXC_CHSRCLINK_VALUES: mxValueLink = xSrcLink; break;
2099 40 : case EXC_CHSRCLINK_CATEGORY: mxCategLink = xSrcLink; break;
2100 40 : case EXC_CHSRCLINK_BUBBLES: mxBubbleLink = xSrcLink; break;
2101 160 : }
2102 160 : }
2103 :
2104 97 : void XclImpChSeries::ReadChDataFormat( XclImpStream& rStrm )
2105 : {
2106 : // #i51639# chart stores all data formats and assigns them later to the series
2107 97 : GetChartData().ReadChDataFormat( rStrm );
2108 97 : }
2109 :
2110 0 : void XclImpChSeries::ReadChSerParent( XclImpStream& rStrm )
2111 : {
2112 0 : rStrm >> mnParentIdx;
2113 : // index to parent series is 1-based, convert it to 0-based
2114 0 : if( mnParentIdx > 0 )
2115 0 : --mnParentIdx;
2116 : else
2117 0 : mnParentIdx = EXC_CHSERIES_INVALID;
2118 0 : }
2119 :
2120 0 : void XclImpChSeries::ReadChSerTrendLine( XclImpStream& rStrm )
2121 : {
2122 0 : XclImpChSerTrendLineRef xTrendLine( new XclImpChSerTrendLine( GetChRoot() ) );
2123 0 : xTrendLine->ReadChSerTrendLine( rStrm );
2124 0 : maTrendLines.push_back( xTrendLine );
2125 0 : }
2126 :
2127 0 : void XclImpChSeries::ReadChSerErrorBar( XclImpStream& rStrm )
2128 : {
2129 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2130 0 : auto_ptr<XclImpChSerErrorBar> pErrorBar(new XclImpChSerErrorBar(GetChRoot()));
2131 : SAL_WNODEPRECATED_DECLARATIONS_POP
2132 0 : pErrorBar->ReadChSerErrorBar(rStrm);
2133 0 : sal_uInt8 nBarType = pErrorBar->GetBarType();
2134 0 : maErrorBars.insert(nBarType, pErrorBar);
2135 0 : }
2136 :
2137 0 : XclImpChDataFormatRef XclImpChSeries::CreateDataFormat( sal_uInt16 nPointIdx, sal_uInt16 nFormatIdx )
2138 : {
2139 0 : XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2140 0 : xDataFmt->SetPointPos( XclChDataPointPos( mnSeriesIdx, nPointIdx ), nFormatIdx );
2141 0 : return xDataFmt;
2142 : }
2143 :
2144 40 : void XclImpChSeries::ConvertTrendLines( Reference< XDataSeries > xDataSeries ) const
2145 : {
2146 40 : Reference< XRegressionCurveContainer > xRegCurveCont( xDataSeries, UNO_QUERY );
2147 40 : if( xRegCurveCont.is() )
2148 : {
2149 40 : for( XclImpChSerTrendLineList::const_iterator aIt = maTrendLines.begin(), aEnd = maTrendLines.end(); aIt != aEnd; ++aIt )
2150 : {
2151 : try
2152 : {
2153 0 : Reference< XRegressionCurve > xRegCurve = (*aIt)->CreateRegressionCurve();
2154 0 : if( xRegCurve.is() )
2155 0 : xRegCurveCont->addRegressionCurve( xRegCurve );
2156 : }
2157 0 : catch( Exception& )
2158 : {
2159 : OSL_FAIL( "XclImpChSeries::ConvertTrendLines - cannot add regression curve" );
2160 : }
2161 : }
2162 40 : }
2163 40 : }
2164 :
2165 80 : Reference< XPropertySet > XclImpChSeries::CreateErrorBar( sal_uInt8 nPosBarId, sal_uInt8 nNegBarId ) const
2166 : {
2167 80 : XclImpChSerErrorBarMap::const_iterator itrPosBar = maErrorBars.find(nPosBarId);
2168 80 : XclImpChSerErrorBarMap::const_iterator itrNegBar = maErrorBars.find(nNegBarId);
2169 80 : XclImpChSerErrorBarMap::const_iterator itrEnd = maErrorBars.end();
2170 80 : if (itrPosBar == itrEnd || itrNegBar == itrEnd)
2171 80 : return Reference<XPropertySet>();
2172 :
2173 0 : return XclImpChSerErrorBar::CreateErrorBar(itrPosBar->second, itrNegBar->second);
2174 : }
2175 :
2176 : // Chart type groups ==========================================================
2177 :
2178 40 : XclImpChType::XclImpChType( const XclImpChRoot& rRoot ) :
2179 : XclImpChRoot( rRoot ),
2180 : mnRecId( EXC_ID_CHUNKNOWN ),
2181 40 : maTypeInfo( rRoot.GetChartTypeInfo( EXC_CHTYPEID_UNKNOWN ) )
2182 : {
2183 40 : }
2184 :
2185 179 : void XclImpChType::ReadChType( XclImpStream& rStrm )
2186 : {
2187 179 : sal_uInt16 nRecId = rStrm.GetRecId();
2188 179 : bool bKnownType = true;
2189 :
2190 179 : switch( nRecId )
2191 : {
2192 : case EXC_ID_CHBAR:
2193 1 : rStrm >> maData.mnOverlap >> maData.mnGap >> maData.mnFlags;
2194 1 : break;
2195 :
2196 : case EXC_ID_CHLINE:
2197 : case EXC_ID_CHAREA:
2198 : case EXC_ID_CHRADARLINE:
2199 : case EXC_ID_CHRADARAREA:
2200 1 : rStrm >> maData.mnFlags;
2201 1 : break;
2202 :
2203 : case EXC_ID_CHPIE:
2204 37 : rStrm >> maData.mnRotation >> maData.mnPieHole;
2205 37 : if( GetBiff() == EXC_BIFF8 )
2206 37 : rStrm >> maData.mnFlags;
2207 : else
2208 0 : maData.mnFlags = 0;
2209 37 : break;
2210 :
2211 : case EXC_ID_CHPIEEXT:
2212 0 : maData.mnRotation = 0;
2213 0 : maData.mnPieHole = 0;
2214 0 : maData.mnFlags = 0;
2215 0 : break;
2216 :
2217 : case EXC_ID_CHSCATTER:
2218 0 : if( GetBiff() == EXC_BIFF8 )
2219 0 : rStrm >> maData.mnBubbleSize >> maData.mnBubbleType >> maData.mnFlags;
2220 : else
2221 0 : maData.mnFlags = 0;
2222 0 : break;
2223 :
2224 : case EXC_ID_CHSURFACE:
2225 0 : rStrm >> maData.mnFlags;
2226 0 : break;
2227 :
2228 : default:
2229 140 : bKnownType = false;
2230 : }
2231 :
2232 179 : if( bKnownType )
2233 39 : mnRecId = nRecId;
2234 179 : }
2235 :
2236 40 : void XclImpChType::Finalize( bool bStockChart )
2237 : {
2238 40 : switch( mnRecId )
2239 : {
2240 : case EXC_ID_CHLINE:
2241 : maTypeInfo = GetChartTypeInfo( bStockChart ?
2242 1 : EXC_CHTYPEID_STOCK : EXC_CHTYPEID_LINE );
2243 1 : break;
2244 : case EXC_ID_CHBAR:
2245 : maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
2246 : maData.mnFlags, EXC_CHBAR_HORIZONTAL,
2247 1 : EXC_CHTYPEID_HORBAR, EXC_CHTYPEID_BAR ) );
2248 1 : break;
2249 : case EXC_ID_CHPIE:
2250 : maTypeInfo = GetChartTypeInfo( (maData.mnPieHole > 0) ?
2251 37 : EXC_CHTYPEID_DONUT : EXC_CHTYPEID_PIE );
2252 37 : break;
2253 : case EXC_ID_CHSCATTER:
2254 : maTypeInfo = GetChartTypeInfo( ::get_flagvalue(
2255 : maData.mnFlags, EXC_CHSCATTER_BUBBLES,
2256 0 : EXC_CHTYPEID_BUBBLES, EXC_CHTYPEID_SCATTER ) );
2257 0 : break;
2258 : default:
2259 1 : maTypeInfo = GetChartTypeInfo( mnRecId );
2260 : }
2261 :
2262 40 : switch( maTypeInfo.meTypeId )
2263 : {
2264 : case EXC_CHTYPEID_PIEEXT:
2265 : case EXC_CHTYPEID_BUBBLES:
2266 : case EXC_CHTYPEID_SURFACE:
2267 : case EXC_CHTYPEID_UNKNOWN:
2268 1 : GetTracer().TraceChartUnKnownType();
2269 1 : break;
2270 : default:;
2271 : }
2272 40 : }
2273 :
2274 80 : bool XclImpChType::IsStacked() const
2275 : {
2276 80 : bool bStacked = false;
2277 80 : if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
2278 : {
2279 : case EXC_CHTYPECATEG_LINE:
2280 : bStacked =
2281 2 : ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
2282 2 : !::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
2283 2 : break;
2284 : case EXC_CHTYPECATEG_BAR:
2285 : bStacked =
2286 4 : ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
2287 4 : !::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
2288 4 : break;
2289 : default:;
2290 : }
2291 80 : return bStacked;
2292 : }
2293 :
2294 118 : bool XclImpChType::IsPercent() const
2295 : {
2296 118 : bool bPercent = false;
2297 118 : if( maTypeInfo.mbSupportsStacking ) switch( maTypeInfo.meTypeCateg )
2298 : {
2299 : case EXC_CHTYPECATEG_LINE:
2300 : bPercent =
2301 1 : ::get_flag( maData.mnFlags, EXC_CHLINE_STACKED ) &&
2302 1 : ::get_flag( maData.mnFlags, EXC_CHLINE_PERCENT );
2303 1 : break;
2304 : case EXC_CHTYPECATEG_BAR:
2305 : bPercent =
2306 6 : ::get_flag( maData.mnFlags, EXC_CHBAR_STACKED ) &&
2307 6 : ::get_flag( maData.mnFlags, EXC_CHBAR_PERCENT );
2308 6 : break;
2309 : default:;
2310 : }
2311 118 : return bPercent;
2312 : }
2313 :
2314 40 : bool XclImpChType::HasCategoryLabels() const
2315 : {
2316 : // radar charts disable category labels in chart type, not in CHTICK of X axis
2317 40 : return (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) || ::get_flag( maData.mnFlags, EXC_CHRADAR_AXISLABELS );
2318 : }
2319 :
2320 40 : Reference< XCoordinateSystem > XclImpChType::CreateCoordSystem( bool b3dChart ) const
2321 : {
2322 : // service name
2323 40 : OUString aCoordSysService;
2324 40 : if( maTypeInfo.mbPolarCoordSystem )
2325 : {
2326 37 : if( b3dChart )
2327 0 : aCoordSysService = SERVICE_CHART2_POLARCOORDSYS3D;
2328 : else
2329 37 : aCoordSysService = SERVICE_CHART2_POLARCOORDSYS2D;
2330 : }
2331 : else
2332 : {
2333 3 : if( b3dChart )
2334 0 : aCoordSysService = SERVICE_CHART2_CARTESIANCOORDSYS3D;
2335 : else
2336 3 : aCoordSysService = SERVICE_CHART2_CARTESIANCOORDSYS2D;
2337 : }
2338 :
2339 : // create the coordinate system object
2340 40 : Reference< XCoordinateSystem > xCoordSystem( ScfApiHelper::CreateInstance( aCoordSysService ), UNO_QUERY );
2341 :
2342 : // swap X and Y axis
2343 40 : if( maTypeInfo.mbSwappedAxesSet )
2344 : {
2345 0 : ScfPropertySet aCoordSysProp( xCoordSystem );
2346 0 : aCoordSysProp.SetBoolProperty( EXC_CHPROP_SWAPXANDYAXIS, true );
2347 : }
2348 :
2349 40 : return xCoordSystem;
2350 : }
2351 :
2352 40 : Reference< XChartType > XclImpChType::CreateChartType( Reference< XDiagram > xDiagram, bool b3dChart ) const
2353 : {
2354 40 : OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName );
2355 40 : Reference< XChartType > xChartType( ScfApiHelper::CreateInstance( aService ), UNO_QUERY );
2356 :
2357 : // additional properties
2358 40 : switch( maTypeInfo.meTypeCateg )
2359 : {
2360 : case EXC_CHTYPECATEG_BAR:
2361 : {
2362 2 : ScfPropertySet aTypeProp( xChartType );
2363 2 : Sequence< sal_Int32 > aInt32Seq( 2 );
2364 2 : aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = -maData.mnOverlap;
2365 2 : aTypeProp.SetProperty( EXC_CHPROP_OVERLAPSEQ, aInt32Seq );
2366 2 : aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = maData.mnGap;
2367 2 : aTypeProp.SetProperty( EXC_CHPROP_GAPWIDTHSEQ, aInt32Seq );
2368 : }
2369 2 : break;
2370 : case EXC_CHTYPECATEG_PIE:
2371 : {
2372 37 : ScfPropertySet aTypeProp( xChartType );
2373 37 : aTypeProp.SetBoolProperty( EXC_CHPROP_USERINGS, maTypeInfo.meTypeId == EXC_CHTYPEID_DONUT );
2374 : /* #i85166# starting angle of first pie slice. 3D pie charts use Y
2375 : rotation setting in view3D element. Of-pie charts do not
2376 : support pie rotation. */
2377 37 : if( !b3dChart && (maTypeInfo.meTypeId != EXC_CHTYPEID_PIEEXT) )
2378 : {
2379 37 : ScfPropertySet aDiaProp( xDiagram );
2380 37 : XclImpChRoot::ConvertPieRotation( aDiaProp, maData.mnRotation );
2381 37 : }
2382 : }
2383 37 : break;
2384 : default:;
2385 : }
2386 :
2387 40 : return xChartType;
2388 : }
2389 :
2390 : // ----------------------------------------------------------------------------
2391 :
2392 0 : void XclImpChChart3d::ReadChChart3d( XclImpStream& rStrm )
2393 : {
2394 0 : rStrm >> maData.mnRotation
2395 0 : >> maData.mnElevation
2396 0 : >> maData.mnEyeDist
2397 0 : >> maData.mnRelHeight
2398 0 : >> maData.mnRelDepth
2399 0 : >> maData.mnDepthGap
2400 0 : >> maData.mnFlags;
2401 0 : }
2402 :
2403 0 : void XclImpChChart3d::Convert( ScfPropertySet& rPropSet, bool b3dWallChart ) const
2404 : {
2405 : namespace cssd = ::com::sun::star::drawing;
2406 :
2407 : // #i104057# do not assert this, written by broken external generators
2408 : // OSL_ENSURE( ::get_flag( maData.mnFlags, EXC_CHCHART3D_HASWALLS ) == b3dWallChart, "XclImpChChart3d::Convert - wrong wall flag" );
2409 :
2410 0 : sal_Int32 nRotationY = 0;
2411 0 : sal_Int32 nRotationX = 0;
2412 0 : sal_Int32 nPerspective = 15;
2413 0 : bool bRightAngled = false;
2414 0 : cssd::ProjectionMode eProjMode = cssd::ProjectionMode_PERSPECTIVE;
2415 0 : Color aAmbientColor, aLightColor;
2416 :
2417 0 : if( b3dWallChart )
2418 : {
2419 : // Y rotation (Excel [0..359], Chart2 [-179,180])
2420 0 : nRotationY = maData.mnRotation % 360;
2421 0 : if( nRotationY > 180 ) nRotationY -= 360;
2422 : // X rotation a.k.a. elevation (Excel [-90..90], Chart2 [-179,180])
2423 0 : nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, -90, 90 );
2424 : // perspective (Excel and Chart2 [0,100])
2425 0 : nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2426 : // right-angled axes
2427 0 : bRightAngled = !::get_flag( maData.mnFlags, EXC_CHCHART3D_REAL3D );
2428 : // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%)
2429 0 : bool bParallel = bRightAngled || (nPerspective == 0);
2430 0 : eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE;
2431 : // ambient color (Gray 20%)
2432 0 : aAmbientColor.SetColor( RGB_COLORDATA( 204, 204, 204 ) );
2433 : // light color (Gray 60%)
2434 0 : aLightColor.SetColor( RGB_COLORDATA( 102, 102, 102 ) );
2435 : }
2436 : else
2437 : {
2438 : // Y rotation not used in pie charts, but 'first pie slice angle'
2439 0 : nRotationY = 0;
2440 0 : XclImpChRoot::ConvertPieRotation( rPropSet, maData.mnRotation );
2441 : // X rotation a.k.a. elevation (map Excel [10..80] to Chart2 [-80,-10])
2442 0 : nRotationX = limit_cast< sal_Int32, sal_Int32 >( maData.mnElevation, 10, 80 ) - 90;
2443 : // perspective (Excel and Chart2 [0,100])
2444 0 : nPerspective = limit_cast< sal_Int32, sal_Int32 >( maData.mnEyeDist, 0, 100 );
2445 : // no right-angled axes in pie charts, but parallel projection
2446 0 : bRightAngled = false;
2447 0 : eProjMode = cssd::ProjectionMode_PARALLEL;
2448 : // ambient color (Gray 30%)
2449 0 : aAmbientColor.SetColor( RGB_COLORDATA( 179, 179, 179 ) );
2450 : // light color (Gray 70%)
2451 0 : aLightColor.SetColor( RGB_COLORDATA( 76, 76, 76 ) );
2452 : }
2453 :
2454 : // properties
2455 0 : rPropSet.SetProperty( EXC_CHPROP_ROTATIONVERTICAL, nRotationY );
2456 0 : rPropSet.SetProperty( EXC_CHPROP_ROTATIONHORIZONTAL, nRotationX );
2457 0 : rPropSet.SetProperty( EXC_CHPROP_PERSPECTIVE, nPerspective );
2458 0 : rPropSet.SetBoolProperty( EXC_CHPROP_RIGHTANGLEDAXES, bRightAngled );
2459 0 : rPropSet.SetProperty( EXC_CHPROP_D3DSCENEPERSPECTIVE, eProjMode );
2460 :
2461 : // light settings
2462 0 : rPropSet.SetProperty( EXC_CHPROP_D3DSCENESHADEMODE, cssd::ShadeMode_FLAT );
2463 0 : rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENEAMBIENTCOLOR, aAmbientColor );
2464 0 : rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON1, false );
2465 0 : rPropSet.SetBoolProperty( EXC_CHPROP_D3DSCENELIGHTON2, true );
2466 0 : rPropSet.SetColorProperty( EXC_CHPROP_D3DSCENELIGHTCOLOR2, aLightColor );
2467 0 : rPropSet.SetProperty( EXC_CHPROP_D3DSCENELIGHTDIR2, cssd::Direction3D( 0.2, 0.4, 1.0 ) );
2468 0 : }
2469 :
2470 : // ----------------------------------------------------------------------------
2471 :
2472 21 : XclImpChLegend::XclImpChLegend( const XclImpChRoot& rRoot ) :
2473 21 : XclImpChRoot( rRoot )
2474 : {
2475 21 : }
2476 :
2477 21 : void XclImpChLegend::ReadHeaderRecord( XclImpStream& rStrm )
2478 : {
2479 21 : rStrm >> maData.maRect >> maData.mnDockMode >> maData.mnSpacing >> maData.mnFlags;
2480 :
2481 : // trace unsupported features
2482 21 : if( GetTracer().IsEnabled() )
2483 : {
2484 0 : if( maData.mnDockMode == EXC_CHLEGEND_NOTDOCKED )
2485 0 : GetTracer().TraceChartLegendPosition();
2486 0 : if( ::get_flag( maData.mnFlags, EXC_CHLEGEND_DATATABLE ) )
2487 0 : GetTracer().TraceChartDataTable();
2488 : }
2489 21 : }
2490 :
2491 179 : void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm )
2492 : {
2493 179 : switch( rStrm.GetRecId() )
2494 : {
2495 : case EXC_ID_CHFRAMEPOS:
2496 21 : mxFramePos.reset( new XclImpChFramePos );
2497 21 : mxFramePos->ReadChFramePos( rStrm );
2498 21 : break;
2499 : case EXC_ID_CHTEXT:
2500 21 : mxText.reset( new XclImpChText( GetChRoot() ) );
2501 21 : mxText->ReadRecordGroup( rStrm );
2502 21 : break;
2503 : case EXC_ID_CHFRAME:
2504 19 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
2505 19 : mxFrame->ReadRecordGroup( rStrm );
2506 19 : break;
2507 : }
2508 179 : }
2509 :
2510 21 : void XclImpChLegend::Finalize()
2511 : {
2512 : // legend default formatting differs in OOChart and Excel, missing frame means automatic
2513 21 : if( !mxFrame )
2514 2 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_LEGEND ) );
2515 : // Update text formatting. If mxText is empty, the passed default text is used.
2516 21 : lclUpdateText( mxText, GetChartData().GetDefaultText( EXC_CHTEXTTYPE_LEGEND ) );
2517 21 : }
2518 :
2519 21 : Reference< XLegend > XclImpChLegend::CreateLegend() const
2520 : {
2521 21 : Reference< XLegend > xLegend( ScfApiHelper::CreateInstance( SERVICE_CHART2_LEGEND ), UNO_QUERY );
2522 21 : if( xLegend.is() )
2523 : {
2524 21 : ScfPropertySet aLegendProp( xLegend );
2525 21 : aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true );
2526 :
2527 : // frame properties
2528 21 : if( mxFrame )
2529 21 : mxFrame->Convert( aLegendProp );
2530 : // text properties
2531 21 : if( mxText )
2532 21 : mxText->ConvertFont( aLegendProp );
2533 :
2534 : /* Legend position and size. Default positions are used only if the
2535 : plot area is positioned automatically (Excel sets the plot area to
2536 : manual mode, if the legend is moved or resized). With manual plot
2537 : areas, Excel ignores the value in maData.mnDockMode completely. */
2538 21 : cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM;
2539 21 : cssc::ChartLegendExpansion eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2540 21 : if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode )
2541 : {
2542 : case EXC_CHLEGEND_LEFT:
2543 0 : eApiPos = cssc2::LegendPosition_LINE_START;
2544 0 : eApiExpand = cssc::ChartLegendExpansion_HIGH;
2545 0 : break;
2546 : case EXC_CHLEGEND_RIGHT:
2547 : // top-right not supported
2548 : case EXC_CHLEGEND_CORNER:
2549 1 : eApiPos = cssc2::LegendPosition_LINE_END;
2550 1 : eApiExpand = cssc::ChartLegendExpansion_HIGH;
2551 1 : break;
2552 : case EXC_CHLEGEND_TOP:
2553 0 : eApiPos = cssc2::LegendPosition_PAGE_START;
2554 0 : eApiExpand = cssc::ChartLegendExpansion_WIDE;
2555 0 : break;
2556 : case EXC_CHLEGEND_BOTTOM:
2557 0 : eApiPos = cssc2::LegendPosition_PAGE_END;
2558 0 : eApiExpand = cssc::ChartLegendExpansion_WIDE;
2559 0 : break;
2560 : }
2561 :
2562 : // no automatic position/size: try to find the correct position and size
2563 21 : if( eApiPos == cssc2::LegendPosition_CUSTOM )
2564 : {
2565 20 : const XclChFramePos* pFramePos = mxFramePos ? &mxFramePos->GetFramePosData() : 0;
2566 :
2567 : /* Legend position. Only the settings from the CHFRAMEPOS record
2568 : are used by Excel, the position in the CHLEGEND record will be
2569 : ignored. */
2570 20 : if( pFramePos )
2571 : {
2572 : RelativePosition aRelPos(
2573 20 : CalcRelativeFromChartX( pFramePos->maRect.mnX ),
2574 20 : CalcRelativeFromChartY( pFramePos->maRect.mnY ),
2575 60 : ::com::sun::star::drawing::Alignment_TOP_LEFT );
2576 20 : aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos );
2577 : }
2578 : else
2579 : {
2580 : // no manual position/size found, just go for the default
2581 0 : eApiPos = cssc2::LegendPosition_LINE_END;
2582 : }
2583 :
2584 : /* Legend size. The member mnBRMode specifies whether size is
2585 : automatic or changes manually. Manual size is given in points,
2586 : not in chart units. */
2587 20 : if( pFramePos && (pFramePos->mnBRMode == EXC_CHFRAMEPOS_ABSSIZE_POINTS) &&
2588 : (pFramePos->maRect.mnWidth > 0) && (pFramePos->maRect.mnHeight > 0) )
2589 : {
2590 19 : eApiExpand = cssc::ChartLegendExpansion_CUSTOM;
2591 19 : sal_Int32 nWidthHmm = static_cast< sal_Int32 >( pFramePos->maRect.mnWidth / EXC_POINTS_PER_HMM );
2592 19 : sal_Int32 nHeightHmm = static_cast< sal_Int32 >( pFramePos->maRect.mnHeight / EXC_POINTS_PER_HMM );
2593 19 : RelativeSize aRelSize( CalcRelativeFromHmmX( nWidthHmm ), CalcRelativeFromHmmY( nHeightHmm ) );
2594 19 : aLegendProp.SetProperty( EXC_CHPROP_RELATIVESIZE, aRelSize );
2595 : }
2596 : else
2597 : {
2598 : // automatic size: determine entry direction from flags
2599 : eApiExpand = ::get_flagvalue( maData.mnFlags, EXC_CHLEGEND_STACKED,
2600 1 : cssc::ChartLegendExpansion_HIGH, cssc::ChartLegendExpansion_WIDE );
2601 : }
2602 : }
2603 21 : aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos );
2604 21 : aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand );
2605 : }
2606 21 : return xLegend;
2607 : }
2608 :
2609 : // ----------------------------------------------------------------------------
2610 :
2611 0 : XclImpChDropBar::XclImpChDropBar( sal_uInt16 nDropBar ) :
2612 : mnDropBar( nDropBar ),
2613 0 : mnBarDist( 0 )
2614 : {
2615 0 : }
2616 :
2617 0 : void XclImpChDropBar::ReadHeaderRecord( XclImpStream& rStrm )
2618 : {
2619 0 : rStrm >> mnBarDist;
2620 0 : }
2621 :
2622 0 : void XclImpChDropBar::Convert( const XclImpChRoot& rRoot, ScfPropertySet& rPropSet ) const
2623 : {
2624 0 : XclChObjectType eObjType = EXC_CHOBJTYPE_BACKGROUND;
2625 0 : switch( mnDropBar )
2626 : {
2627 0 : case EXC_CHDROPBAR_UP: eObjType = EXC_CHOBJTYPE_WHITEDROPBAR; break;
2628 0 : case EXC_CHDROPBAR_DOWN: eObjType = EXC_CHOBJTYPE_BLACKDROPBAR; break;
2629 : }
2630 0 : ConvertFrameBase( rRoot, rPropSet, eObjType );
2631 0 : }
2632 :
2633 : // ----------------------------------------------------------------------------
2634 :
2635 40 : XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) :
2636 : XclImpChRoot( rRoot ),
2637 : maType( rRoot ),
2638 40 : maTypeInfo( maType.GetTypeInfo() )
2639 : {
2640 : // Initialize unused format indexes set. At this time, all formats are unused.
2641 10280 : for( sal_uInt16 nFormatIdx = 0; nFormatIdx <= EXC_CHSERIES_MAXSERIES; ++nFormatIdx )
2642 10240 : maUnusedFormats.insert( maUnusedFormats.end(), nFormatIdx );
2643 40 : }
2644 :
2645 40 : void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm )
2646 : {
2647 40 : rStrm.Ignore( 16 );
2648 40 : rStrm >> maData.mnFlags >> maData.mnGroupIdx;
2649 40 : }
2650 :
2651 219 : void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm )
2652 : {
2653 219 : switch( rStrm.GetRecId() )
2654 : {
2655 : case EXC_ID_CHCHART3D:
2656 0 : mxChart3d.reset( new XclImpChChart3d );
2657 0 : mxChart3d->ReadChChart3d( rStrm );
2658 0 : break;
2659 : case EXC_ID_CHLEGEND:
2660 21 : mxLegend.reset( new XclImpChLegend( GetChRoot() ) );
2661 21 : mxLegend->ReadRecordGroup( rStrm );
2662 21 : break;
2663 : case EXC_ID_CHDEFAULTTEXT:
2664 0 : GetChartData().ReadChDefaultText( rStrm );
2665 0 : break;
2666 : case EXC_ID_CHDROPBAR:
2667 0 : ReadChDropBar( rStrm );
2668 0 : break;
2669 : case EXC_ID_CHCHARTLINE:
2670 0 : ReadChChartLine( rStrm );
2671 0 : break;
2672 : case EXC_ID_CHDATAFORMAT:
2673 19 : ReadChDataFormat( rStrm );
2674 19 : break;
2675 : default:
2676 179 : maType.ReadChType( rStrm );
2677 : }
2678 219 : }
2679 :
2680 40 : void XclImpChTypeGroup::Finalize()
2681 : {
2682 : // check and set valid chart type
2683 : bool bStockChart =
2684 40 : (maType.GetRecId() == EXC_ID_CHLINE) && // must be a line chart
2685 1 : !mxChart3d && // must be a 2d chart
2686 1 : HasHiLoLine() && // must contain hi-lo lines
2687 42 : (maSeries.size() == static_cast<XclImpChSeriesVec::size_type>(HasDropBars() ? 4 : 3)); // correct series count
2688 40 : maType.Finalize( bStockChart );
2689 :
2690 : // extended type info
2691 40 : maTypeInfo.Set( maType.GetTypeInfo(), mxChart3d, false );
2692 :
2693 : // reverse series order for some unstacked 2D chart types
2694 40 : if( maTypeInfo.mbReverseSeries && !Is3dChart() && !maType.IsStacked() && !maType.IsPercent() )
2695 0 : ::std::reverse( maSeries.begin(), maSeries.end() );
2696 :
2697 : // update chart type group format, may depend on chart type finalized above
2698 40 : if( mxGroupFmt )
2699 19 : mxGroupFmt->UpdateGroupFormat( maTypeInfo );
2700 40 : }
2701 :
2702 40 : void XclImpChTypeGroup::AddSeries( XclImpChSeriesRef xSeries )
2703 : {
2704 40 : if( xSeries )
2705 40 : maSeries.push_back( xSeries );
2706 : // store first inserted series separately, series order may be reversed later
2707 40 : if( !mxFirstSeries )
2708 40 : mxFirstSeries = xSeries;
2709 40 : }
2710 :
2711 40 : void XclImpChTypeGroup::SetUsedFormatIndex( sal_uInt16 nFormatIdx )
2712 : {
2713 40 : maUnusedFormats.erase( nFormatIdx );
2714 40 : }
2715 :
2716 0 : sal_uInt16 XclImpChTypeGroup::PopUnusedFormatIndex()
2717 : {
2718 : OSL_ENSURE( !maUnusedFormats.empty(), "XclImpChTypeGroup::PopUnusedFormatIndex - no more format indexes available" );
2719 0 : sal_uInt16 nFormatIdx = maUnusedFormats.empty() ? 0 : *maUnusedFormats.begin();
2720 0 : SetUsedFormatIndex( nFormatIdx );
2721 0 : return nFormatIdx;
2722 : }
2723 :
2724 40 : bool XclImpChTypeGroup::HasVarPointFormat() const
2725 : {
2726 40 : return ::get_flag( maData.mnFlags, EXC_CHTYPEGROUP_VARIEDCOLORS ) &&
2727 : ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_MULTI) || // multiple series allowed
2728 : ((maTypeInfo.meVarPointMode == EXC_CHVARPOINT_SINGLE) && // or exactly 1 series?
2729 40 : (maSeries.size() == 1)));
2730 : }
2731 :
2732 40 : bool XclImpChTypeGroup::HasConnectorLines() const
2733 : {
2734 : // existence of connector lines (only in stacked bar charts)
2735 40 : if ( !(maType.IsStacked() || maType.IsPercent()) || (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_BAR) )
2736 40 : return false;
2737 0 : XclImpChLineFormatMap::const_iterator xConLine = maChartLines.find( EXC_CHCHARTLINE_CONNECT );
2738 0 : return ( xConLine != maChartLines.end() && xConLine->second->HasLine() );
2739 : }
2740 :
2741 38 : const String& XclImpChTypeGroup::GetSingleSeriesTitle() const
2742 : {
2743 : // no automatic title for series with trendlines or error bars
2744 : // pie charts always show an automatic title, even if more series exist
2745 77 : return (mxFirstSeries && !mxFirstSeries->HasChildSeries() && (maTypeInfo.mbSingleSeriesVis || (maSeries.size() == 1))) ?
2746 77 : mxFirstSeries->GetTitle() : String::EmptyString();
2747 : }
2748 :
2749 40 : void XclImpChTypeGroup::ConvertChart3d( ScfPropertySet& rPropSet ) const
2750 : {
2751 40 : if( mxChart3d )
2752 0 : mxChart3d->Convert( rPropSet, Is3dWallChart() );
2753 40 : }
2754 :
2755 40 : Reference< XCoordinateSystem > XclImpChTypeGroup::CreateCoordSystem() const
2756 : {
2757 40 : return maType.CreateCoordSystem( Is3dChart() );
2758 : }
2759 :
2760 40 : Reference< XChartType > XclImpChTypeGroup::CreateChartType( Reference< XDiagram > xDiagram, sal_Int32 nApiAxesSetIdx ) const
2761 : {
2762 : OSL_ENSURE( IsValidGroup(), "XclImpChTypeGroup::CreateChartType - type group without series" );
2763 :
2764 : // create the chart type object
2765 40 : Reference< XChartType > xChartType = maType.CreateChartType( xDiagram, Is3dChart() );
2766 :
2767 : // bar chart connector lines
2768 40 : if( HasConnectorLines() )
2769 : {
2770 0 : ScfPropertySet aDiaProp( xDiagram );
2771 0 : aDiaProp.SetBoolProperty( EXC_CHPROP_CONNECTBARS, true );
2772 : }
2773 :
2774 : /* Stock chart needs special processing. Create one 'big' series with
2775 : data sequences of different roles. */
2776 40 : if( maTypeInfo.meTypeId == EXC_CHTYPEID_STOCK )
2777 0 : CreateStockSeries( xChartType, nApiAxesSetIdx );
2778 : else
2779 40 : CreateDataSeries( xChartType, nApiAxesSetIdx );
2780 :
2781 40 : return xChartType;
2782 : }
2783 :
2784 40 : Reference< XLabeledDataSequence > XclImpChTypeGroup::CreateCategSequence() const
2785 : {
2786 40 : Reference< XLabeledDataSequence > xLabeledSeq;
2787 : // create category sequence from first visible series
2788 40 : if( mxFirstSeries )
2789 40 : xLabeledSeq = mxFirstSeries->CreateCategSequence( EXC_CHPROP_ROLE_CATEG );
2790 40 : return xLabeledSeq;
2791 : }
2792 :
2793 0 : void XclImpChTypeGroup::ReadChDropBar( XclImpStream& rStrm )
2794 : {
2795 0 : if (maDropBars.find(EXC_CHDROPBAR_UP) == maDropBars.end())
2796 : {
2797 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2798 0 : auto_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_UP));
2799 : SAL_WNODEPRECATED_DECLARATIONS_POP
2800 0 : p->ReadRecordGroup(rStrm);
2801 0 : maDropBars.insert(EXC_CHDROPBAR_UP, p);
2802 : }
2803 0 : else if(maDropBars.find(EXC_CHDROPBAR_DOWN) == maDropBars.end())
2804 : {
2805 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2806 0 : auto_ptr<XclImpChDropBar> p(new XclImpChDropBar(EXC_CHDROPBAR_DOWN));
2807 : SAL_WNODEPRECATED_DECLARATIONS_POP
2808 0 : p->ReadRecordGroup(rStrm);
2809 0 : maDropBars.insert(EXC_CHDROPBAR_DOWN, p);
2810 : }
2811 0 : }
2812 :
2813 0 : void XclImpChTypeGroup::ReadChChartLine( XclImpStream& rStrm )
2814 : {
2815 0 : sal_uInt16 nLineId = rStrm.ReaduInt16();
2816 0 : if( (rStrm.GetNextRecId() == EXC_ID_CHLINEFORMAT) && rStrm.StartNextRecord() )
2817 : {
2818 0 : XclImpChLineFormat xLineFmt;
2819 0 : xLineFmt.ReadChLineFormat( rStrm );
2820 0 : maChartLines[ nLineId ] = xLineFmt;
2821 : }
2822 0 : }
2823 :
2824 19 : void XclImpChTypeGroup::ReadChDataFormat( XclImpStream& rStrm )
2825 : {
2826 : // global series and data point format
2827 19 : XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
2828 19 : xDataFmt->ReadRecordGroup( rStrm );
2829 19 : const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
2830 38 : if( (rPos.mnSeriesIdx == 0) && (rPos.mnPointIdx == 0) &&
2831 19 : (xDataFmt->GetFormatIdx() == EXC_CHDATAFORMAT_DEFAULT) )
2832 19 : mxGroupFmt = xDataFmt;
2833 19 : }
2834 :
2835 :
2836 40 : void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType,
2837 : Reference< XDataSeries > xSeries, sal_Int32 nApiAxesSetIdx ) const
2838 : {
2839 40 : Reference< XDataSeriesContainer > xSeriesCont( xChartType, UNO_QUERY );
2840 40 : if( xSeriesCont.is() && xSeries.is() )
2841 : {
2842 : // series stacking mode
2843 40 : cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING;
2844 : // stacked overrides deep-3d
2845 40 : if( maType.IsStacked() || maType.IsPercent() )
2846 1 : eStacking = cssc2::StackingDirection_Y_STACKING;
2847 39 : else if( Is3dDeepChart() )
2848 0 : eStacking = cssc2::StackingDirection_Z_STACKING;
2849 :
2850 : // additional series properties
2851 40 : ScfPropertySet aSeriesProp( xSeries );
2852 40 : aSeriesProp.SetProperty( EXC_CHPROP_STACKINGDIR, eStacking );
2853 40 : aSeriesProp.SetProperty( EXC_CHPROP_ATTAXISINDEX, nApiAxesSetIdx );
2854 :
2855 : // insert series into container
2856 : try
2857 : {
2858 40 : xSeriesCont->addDataSeries( xSeries );
2859 : }
2860 0 : catch( Exception& )
2861 : {
2862 : OSL_FAIL( "XclImpChTypeGroup::InsertDataSeries - cannot add data series" );
2863 40 : }
2864 40 : }
2865 40 : }
2866 :
2867 40 : void XclImpChTypeGroup::CreateDataSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
2868 : {
2869 40 : bool bSpline = false;
2870 80 : for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end(); aIt != aEnd; ++aIt )
2871 : {
2872 40 : Reference< XDataSeries > xDataSeries = (*aIt)->CreateDataSeries();
2873 40 : InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2874 40 : bSpline |= (*aIt)->HasSpline();
2875 40 : }
2876 : // spline - TODO: set at single series (#i66858#)
2877 40 : if( bSpline && !maTypeInfo.IsSeriesFrameFormat() && (maTypeInfo.meTypeCateg != EXC_CHTYPECATEG_RADAR) )
2878 : {
2879 0 : ScfPropertySet aTypeProp( xChartType );
2880 0 : aTypeProp.SetProperty( EXC_CHPROP_CURVESTYLE, ::com::sun::star::chart2::CurveStyle_CUBIC_SPLINES );
2881 : }
2882 40 : }
2883 :
2884 0 : void XclImpChTypeGroup::CreateStockSeries( Reference< XChartType > xChartType, sal_Int32 nApiAxesSetIdx ) const
2885 : {
2886 : // create the data series object
2887 0 : Reference< XDataSeries > xDataSeries( ScfApiHelper::CreateInstance( SERVICE_CHART2_DATASERIES ), UNO_QUERY );
2888 0 : Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
2889 0 : if( xDataSink.is() )
2890 : {
2891 : // create a list of data sequences from all series
2892 0 : ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
2893 : OSL_ENSURE( maSeries.size() >= 3, "XclImpChTypeGroup::CreateChartType - missing stock series" );
2894 0 : int nRoleIdx = (maSeries.size() == 3) ? 1 : 0;
2895 0 : for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end();
2896 0 : (nRoleIdx < 4) && (aIt != aEnd); ++nRoleIdx, ++aIt )
2897 : {
2898 : // create a data sequence with a specific role
2899 0 : OUString aRole;
2900 0 : switch( nRoleIdx )
2901 : {
2902 0 : case 0: aRole = EXC_CHPROP_ROLE_OPENVALUES; break;
2903 0 : case 1: aRole = EXC_CHPROP_ROLE_HIGHVALUES; break;
2904 0 : case 2: aRole = EXC_CHPROP_ROLE_LOWVALUES; break;
2905 0 : case 3: aRole = EXC_CHPROP_ROLE_CLOSEVALUES; break;
2906 : }
2907 0 : Reference< XLabeledDataSequence > xDataSeq = (*aIt)->CreateValueSequence( aRole );
2908 0 : if( xDataSeq.is() )
2909 0 : aLabeledSeqVec.push_back( xDataSeq );
2910 0 : }
2911 :
2912 : // attach labeled data sequences to series and insert series into chart type
2913 0 : xDataSink->setData( ScfApiHelper::VectorToSequence( aLabeledSeqVec ) );
2914 :
2915 : // formatting of special stock chart elements
2916 0 : ScfPropertySet aTypeProp( xChartType );
2917 0 : aTypeProp.SetBoolProperty( EXC_CHPROP_JAPANESE, HasDropBars() );
2918 0 : aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWFIRST, HasDropBars() );
2919 0 : aTypeProp.SetBoolProperty( EXC_CHPROP_SHOWHIGHLOW, true );
2920 : // hi-lo line format
2921 0 : XclImpChLineFormatMap::const_iterator xHiLoLine = maChartLines.find( EXC_CHCHARTLINE_HILO );
2922 0 : if ( xHiLoLine != maChartLines.end() )
2923 : {
2924 0 : ScfPropertySet aSeriesProp( xDataSeries );
2925 0 : xHiLoLine->second->Convert( GetChRoot(), aSeriesProp, EXC_CHOBJTYPE_HILOLINE );
2926 : }
2927 : // white dropbar format
2928 0 : XclImpChDropBarMap::const_iterator itr = maDropBars.find(EXC_CHDROPBAR_UP);
2929 0 : Reference<XPropertySet> xWhitePropSet;
2930 0 : if (itr != maDropBars.end() && aTypeProp.GetProperty(xWhitePropSet, EXC_CHPROP_WHITEDAY))
2931 : {
2932 0 : ScfPropertySet aBarProp( xWhitePropSet );
2933 0 : itr->second->Convert(GetChRoot(), aBarProp);
2934 : }
2935 : // black dropbar format
2936 0 : itr = maDropBars.find(EXC_CHDROPBAR_DOWN);
2937 0 : Reference<XPropertySet> xBlackPropSet;
2938 0 : if (itr != maDropBars.end() && aTypeProp.GetProperty(xBlackPropSet, EXC_CHPROP_BLACKDAY))
2939 : {
2940 0 : ScfPropertySet aBarProp( xBlackPropSet );
2941 0 : itr->second->Convert(GetChRoot(), aBarProp);
2942 : }
2943 :
2944 : // insert the series into the chart type object
2945 0 : InsertDataSeries( xChartType, xDataSeries, nApiAxesSetIdx );
2946 0 : }
2947 0 : }
2948 :
2949 : // Axes =======================================================================
2950 :
2951 80 : XclImpChLabelRange::XclImpChLabelRange( const XclImpChRoot& rRoot ) :
2952 80 : XclImpChRoot( rRoot )
2953 : {
2954 80 : }
2955 :
2956 2 : void XclImpChLabelRange::ReadChLabelRange( XclImpStream& rStrm )
2957 : {
2958 2 : rStrm >> maLabelData.mnCross >> maLabelData.mnLabelFreq >> maLabelData.mnTickFreq >> maLabelData.mnFlags;
2959 2 : }
2960 :
2961 2 : void XclImpChLabelRange::ReadChDateRange( XclImpStream& rStrm )
2962 : {
2963 2 : rStrm >> maDateData.mnMinDate
2964 4 : >> maDateData.mnMaxDate
2965 4 : >> maDateData.mnMajorStep
2966 4 : >> maDateData.mnMajorUnit
2967 4 : >> maDateData.mnMinorStep
2968 4 : >> maDateData.mnMinorUnit
2969 4 : >> maDateData.mnBaseUnit
2970 4 : >> maDateData.mnCross
2971 4 : >> maDateData.mnFlags;
2972 2 : }
2973 :
2974 40 : void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleData, bool bMirrorOrient ) const
2975 : {
2976 : // automatic axis type detection
2977 40 : rScaleData.AutoDateAxis = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTODATE );
2978 :
2979 : // the flag EXC_CHDATERANGE_DATEAXIS specifies whether this is a date axis
2980 40 : if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS ) )
2981 : {
2982 : /* Chart2 requires axis type CATEGORY for automatic category/date axis
2983 : (even if it is a date axis currently). */
2984 0 : rScaleData.AxisType = rScaleData.AutoDateAxis ? cssc2::AxisType::CATEGORY : cssc2::AxisType::DATE;
2985 0 : rScaleData.Scaling.set( ScfApiHelper::CreateInstance( SERVICE_CHART2_LINEARSCALING ), UNO_QUERY );
2986 : /* Min/max values depend on base time unit, they specify the number of
2987 : days, months, or years starting from null date. */
2988 0 : lclConvertTimeValue( GetRoot(), rScaleData.Minimum, maDateData.mnMinDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMIN ), maDateData.mnBaseUnit );
2989 0 : lclConvertTimeValue( GetRoot(), rScaleData.Maximum, maDateData.mnMaxDate, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAX ), maDateData.mnBaseUnit );
2990 : // increment
2991 0 : cssc::TimeIncrement& rTimeIncrement = rScaleData.TimeIncrement;
2992 0 : lclConvertTimeInterval( rTimeIncrement.MajorTimeInterval, maDateData.mnMajorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMAJOR ), maDateData.mnMajorUnit );
2993 0 : lclConvertTimeInterval( rTimeIncrement.MinorTimeInterval, maDateData.mnMinorStep, ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOMINOR ), maDateData.mnMinorUnit );
2994 : // base unit
2995 0 : if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOBASE ) )
2996 0 : rTimeIncrement.TimeResolution.clear();
2997 : else
2998 0 : rTimeIncrement.TimeResolution <<= lclGetApiTimeUnit( maDateData.mnBaseUnit );
2999 : }
3000 : else
3001 : {
3002 : // do not overlap text unless all labels are visible
3003 40 : rPropSet.SetBoolProperty( EXC_CHPROP_TEXTOVERLAP, maLabelData.mnLabelFreq == 1 );
3004 : // do not break text into several lines unless all labels are visible
3005 40 : rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maLabelData.mnLabelFreq == 1 );
3006 : // do not stagger labels in two lines
3007 40 : rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
3008 : }
3009 :
3010 : // reverse order
3011 40 : bool bReverse = ::get_flag( maLabelData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient;
3012 40 : rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
3013 :
3014 : //! TODO #i58731# show n-th category
3015 40 : }
3016 :
3017 40 : void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3dChart ) const
3018 : {
3019 : /* Crossing mode (max-cross flag overrides other crossing settings). Excel
3020 : does not move the Y axis in 3D charts, regardless of actual settings.
3021 : But: the Y axis has to be moved to "end", if the X axis is mirrored,
3022 : to keep it at the left end of the chart. */
3023 40 : bool bMaxCross = ::get_flag( maLabelData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS );
3024 40 : cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
3025 40 : rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
3026 :
3027 : // crossing position (depending on axis type text/date)
3028 40 : if( ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_DATEAXIS ) )
3029 : {
3030 0 : bool bAutoCross = ::get_flag( maDateData.mnFlags, EXC_CHDATERANGE_AUTOCROSS );
3031 : /* Crossing position value depends on base time unit, it specifies the
3032 : number of days, months, or years from null date. Note that Excel
3033 : 2007/2010 write broken BIFF8 files, they always stores the number
3034 : of days cregardless of the base time unit (and they are reading it
3035 : the same way, thus wrongly displaying files written by Excel
3036 : 97-2003). This filter sticks to the correct behaviour of Excel
3037 : 97-2003. */
3038 0 : double fCrossingPos = bAutoCross ? 1.0 : lclGetSerialDay( GetRoot(), maDateData.mnCross, maDateData.mnBaseUnit );
3039 0 : rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3040 : }
3041 : else
3042 : {
3043 40 : double fCrossingPos = b3dChart ? 1.0 : maLabelData.mnCross;
3044 40 : rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3045 : }
3046 40 : }
3047 :
3048 : // ----------------------------------------------------------------------------
3049 :
3050 80 : XclImpChValueRange::XclImpChValueRange( const XclImpChRoot& rRoot ) :
3051 80 : XclImpChRoot( rRoot )
3052 : {
3053 80 : }
3054 :
3055 2 : void XclImpChValueRange::ReadChValueRange( XclImpStream& rStrm )
3056 : {
3057 2 : rStrm >> maData.mfMin
3058 4 : >> maData.mfMax
3059 4 : >> maData.mfMajorStep
3060 4 : >> maData.mfMinorStep
3061 4 : >> maData.mfCross
3062 4 : >> maData.mnFlags;
3063 2 : }
3064 :
3065 40 : void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) const
3066 : {
3067 : // scaling algorithm
3068 40 : bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
3069 40 : OUString aScalingService = bLogScale ? OUString( SERVICE_CHART2_LOGSCALING ) : OUString( SERVICE_CHART2_LINEARSCALING );
3070 40 : rScaleData.Scaling.set( ScfApiHelper::CreateInstance( aScalingService ), UNO_QUERY );
3071 :
3072 : // min/max
3073 40 : lclSetExpValueOrClearAny( rScaleData.Minimum, maData.mfMin, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMIN ) );
3074 40 : lclSetExpValueOrClearAny( rScaleData.Maximum, maData.mfMax, bLogScale, ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAX ) );
3075 :
3076 : // increment
3077 40 : bool bAutoMajor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMAJOR );
3078 40 : bool bAutoMinor = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOMINOR );
3079 : // major increment
3080 40 : IncrementData& rIncrementData = rScaleData.IncrementData;
3081 40 : lclSetValueOrClearAny( rIncrementData.Distance, maData.mfMajorStep, bAutoMajor );
3082 : // minor increment
3083 40 : Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
3084 40 : rSubIncrementSeq.realloc( 1 );
3085 40 : Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
3086 40 : rIntervalCount.clear();
3087 40 : if( bLogScale )
3088 : {
3089 0 : if( !bAutoMinor )
3090 0 : rIntervalCount <<= sal_Int32( 9 );
3091 : }
3092 : else
3093 : {
3094 40 : if( !bAutoMajor && !bAutoMinor && (0.0 < maData.mfMinorStep) && (maData.mfMinorStep <= maData.mfMajorStep) )
3095 : {
3096 0 : double fCount = maData.mfMajorStep / maData.mfMinorStep + 0.5;
3097 0 : if( (1.0 <= fCount) && (fCount < 1001.0) )
3098 0 : rIntervalCount <<= static_cast< sal_Int32 >( fCount );
3099 : }
3100 : }
3101 :
3102 : // reverse order
3103 40 : bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient;
3104 40 : rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL;
3105 40 : }
3106 :
3107 40 : void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const
3108 : {
3109 40 : bool bMaxCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_MAXCROSS );
3110 40 : bool bAutoCross = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_AUTOCROSS );
3111 40 : bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE );
3112 :
3113 : // crossing mode (max-cross flag overrides other crossing settings)
3114 40 : cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE;
3115 40 : rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos );
3116 :
3117 : // crossing position
3118 40 : double fCrossingPos = bAutoCross ? 0.0 : maData.mfCross;
3119 40 : if( bLogScale ) fCrossingPos = pow( 10.0, fCrossingPos );
3120 40 : rPropSet.SetProperty( EXC_CHPROP_CROSSOVERVALUE, fCrossingPos );
3121 40 : }
3122 :
3123 : // ----------------------------------------------------------------------------
3124 :
3125 : namespace {
3126 :
3127 160 : sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos )
3128 : {
3129 : using namespace ::com::sun::star::chart2::TickmarkStyle;
3130 160 : sal_Int32 nApiTickmarks = NONE;
3131 160 : ::set_flag( nApiTickmarks, INNER, ::get_flag( nXclTickPos, EXC_CHTICK_INSIDE ) );
3132 160 : ::set_flag( nApiTickmarks, OUTER, ::get_flag( nXclTickPos, EXC_CHTICK_OUTSIDE ) );
3133 160 : return nApiTickmarks;
3134 : }
3135 :
3136 80 : cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos )
3137 : {
3138 : using namespace ::com::sun::star::chart;
3139 80 : switch( nXclLabelPos )
3140 : {
3141 0 : case EXC_CHTICK_LOW: return ChartAxisLabelPosition_OUTSIDE_START;
3142 0 : case EXC_CHTICK_HIGH: return ChartAxisLabelPosition_OUTSIDE_END;
3143 80 : case EXC_CHTICK_NEXT: return ChartAxisLabelPosition_NEAR_AXIS;
3144 : }
3145 0 : return ChartAxisLabelPosition_NEAR_AXIS;
3146 : }
3147 :
3148 : } // namespace
3149 :
3150 80 : XclImpChTick::XclImpChTick( const XclImpChRoot& rRoot ) :
3151 80 : XclImpChRoot( rRoot )
3152 : {
3153 80 : }
3154 :
3155 4 : void XclImpChTick::ReadChTick( XclImpStream& rStrm )
3156 : {
3157 4 : rStrm >> maData.mnMajor
3158 8 : >> maData.mnMinor
3159 8 : >> maData.mnLabelPos
3160 8 : >> maData.mnBackMode;
3161 4 : rStrm.Ignore( 16 );
3162 4 : rStrm >> maData.maTextColor
3163 8 : >> maData.mnFlags;
3164 :
3165 4 : if( GetBiff() == EXC_BIFF8 )
3166 : {
3167 : // BIFF8: index into palette used instead of RGB data
3168 4 : maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() );
3169 : // rotation
3170 4 : rStrm >> maData.mnRotation;
3171 : }
3172 : else
3173 : {
3174 : // BIFF2-BIFF7: get rotation from text orientation
3175 0 : sal_uInt8 nOrient = ::extract_value< sal_uInt8 >( maData.mnFlags, 2, 3 );
3176 0 : maData.mnRotation = XclTools::GetXclRotFromOrient( nOrient );
3177 : }
3178 4 : }
3179 :
3180 2 : Color XclImpChTick::GetFontColor() const
3181 : {
3182 2 : return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOCOLOR ) ? GetFontAutoColor() : maData.maTextColor;
3183 : }
3184 :
3185 80 : sal_uInt16 XclImpChTick::GetRotation() const
3186 : {
3187 : /* n#720443: Ignore auto-rotation if there is a suggested rotation.
3188 : * Better fix would be to improve our axis auto rotation algorithm.
3189 : */
3190 80 : if( maData.mnRotation != EXC_ROT_NONE )
3191 2 : return maData.mnRotation;
3192 78 : return ::get_flag( maData.mnFlags, EXC_CHTICK_AUTOROT ) ? EXC_CHART_AUTOROTATION : maData.mnRotation;
3193 : }
3194 :
3195 80 : void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const
3196 : {
3197 80 : rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) );
3198 80 : rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) );
3199 80 : rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) );
3200 80 : rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS );
3201 80 : }
3202 :
3203 : // ----------------------------------------------------------------------------
3204 :
3205 80 : XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) :
3206 : XclImpChRoot( rRoot ),
3207 80 : mnNumFmtIdx( EXC_FORMAT_NOTFOUND )
3208 : {
3209 80 : maData.mnType = nAxisType;
3210 80 : }
3211 :
3212 4 : void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm )
3213 : {
3214 4 : rStrm >> maData.mnType;
3215 4 : }
3216 :
3217 22 : void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm )
3218 : {
3219 22 : switch( rStrm.GetRecId() )
3220 : {
3221 : case EXC_ID_CHLABELRANGE:
3222 2 : mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
3223 2 : mxLabelRange->ReadChLabelRange( rStrm );
3224 2 : break;
3225 : case EXC_ID_CHDATERANGE:
3226 2 : if( !mxLabelRange )
3227 0 : mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
3228 2 : mxLabelRange->ReadChDateRange( rStrm );
3229 2 : break;
3230 : case EXC_ID_CHVALUERANGE:
3231 2 : mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
3232 2 : mxValueRange->ReadChValueRange( rStrm );
3233 2 : break;
3234 : case EXC_ID_CHFORMAT:
3235 0 : rStrm >> mnNumFmtIdx;
3236 0 : break;
3237 : case EXC_ID_CHTICK:
3238 4 : mxTick.reset( new XclImpChTick( GetChRoot() ) );
3239 4 : mxTick->ReadChTick( rStrm );
3240 4 : break;
3241 : case EXC_ID_CHFONT:
3242 2 : mxFont.reset( new XclImpChFont );
3243 2 : mxFont->ReadChFont( rStrm );
3244 2 : break;
3245 : case EXC_ID_CHAXISLINE:
3246 2 : ReadChAxisLine( rStrm );
3247 2 : break;
3248 : }
3249 22 : }
3250 :
3251 80 : void XclImpChAxis::Finalize()
3252 : {
3253 : // add default scaling, needed e.g. to adjust rotation direction of pie and radar charts
3254 80 : if( !mxLabelRange )
3255 78 : mxLabelRange.reset( new XclImpChLabelRange( GetChRoot() ) );
3256 80 : if( !mxValueRange )
3257 78 : mxValueRange.reset( new XclImpChValueRange( GetChRoot() ) );
3258 : // remove invisible grid lines completely
3259 80 : if( mxMajorGrid && !mxMajorGrid->HasLine() )
3260 0 : mxMajorGrid.reset();
3261 80 : if( mxMinorGrid && !mxMinorGrid->HasLine() )
3262 0 : mxMinorGrid.reset();
3263 : // default tick settings different in OOChart and Excel
3264 80 : if( !mxTick )
3265 76 : mxTick.reset( new XclImpChTick( GetChRoot() ) );
3266 : // #i4140# different default axis line color
3267 80 : if( !mxAxisLine )
3268 : {
3269 80 : XclChLineFormat aLineFmt;
3270 : // set "show axis" flag, default if line format record is missing
3271 80 : ::set_flag( aLineFmt.mnFlags, EXC_CHLINEFORMAT_SHOWAXIS );
3272 80 : mxAxisLine.reset( new XclImpChLineFormat( aLineFmt ) );
3273 : }
3274 : // add wall/floor frame for 3d charts
3275 80 : if( !mxWallFrame )
3276 80 : CreateWallFrame();
3277 80 : }
3278 :
3279 2 : sal_uInt16 XclImpChAxis::GetFontIndex() const
3280 : {
3281 2 : return mxFont ? mxFont->GetFontIndex() : EXC_FONT_NOTFOUND;
3282 : }
3283 :
3284 2 : Color XclImpChAxis::GetFontColor() const
3285 : {
3286 2 : return mxTick ? mxTick->GetFontColor() : GetFontAutoColor();
3287 : }
3288 :
3289 80 : sal_uInt16 XclImpChAxis::GetRotation() const
3290 : {
3291 80 : return mxTick ? mxTick->GetRotation() : EXC_CHART_AUTOROTATION;
3292 : }
3293 :
3294 80 : Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const
3295 : {
3296 : // create the axis object (always)
3297 80 : Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY );
3298 80 : if( xAxis.is() )
3299 : {
3300 80 : ScfPropertySet aAxisProp( xAxis );
3301 : // #i58688# axis enabled
3302 80 : aAxisProp.SetBoolProperty( EXC_CHPROP_SHOW, IsActivated() );
3303 :
3304 : // axis line properties
3305 80 : if( mxAxisLine )
3306 80 : mxAxisLine->Convert( GetChRoot(), aAxisProp, EXC_CHOBJTYPE_AXISLINE );
3307 : // axis ticks properties
3308 80 : if( mxTick )
3309 80 : mxTick->Convert( aAxisProp );
3310 :
3311 : // axis caption text --------------------------------------------------
3312 :
3313 : // radar charts disable their category labels via chart type, not via axis
3314 80 : bool bHasLabels = HasLabels() &&
3315 80 : ((GetAxisType() != EXC_CHAXIS_X) || rTypeGroup.HasCategoryLabels());
3316 80 : aAxisProp.SetBoolProperty( EXC_CHPROP_DISPLAYLABELS, bHasLabels );
3317 80 : if( bHasLabels )
3318 : {
3319 : // font settings from CHFONT record or from default text
3320 80 : if( mxFont )
3321 2 : ConvertFontBase( GetChRoot(), aAxisProp );
3322 78 : else if( const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISLABEL ) )
3323 78 : pDefText->ConvertFont( aAxisProp );
3324 : // label text rotation
3325 80 : ConvertRotationBase( GetChRoot(), aAxisProp, true );
3326 : // number format
3327 80 : sal_uInt32 nScNumFmt = GetNumFmtBuffer().GetScFormat( mnNumFmtIdx );
3328 80 : if( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
3329 0 : aAxisProp.SetProperty( EXC_CHPROP_NUMBERFORMAT, static_cast< sal_Int32 >( nScNumFmt ) );
3330 : }
3331 :
3332 : // axis scaling and increment -----------------------------------------
3333 :
3334 80 : const XclChExtTypeInfo& rTypeInfo = rTypeGroup.GetTypeInfo();
3335 80 : ScaleData aScaleData = xAxis->getScaleData();
3336 : // set axis type
3337 80 : switch( GetAxisType() )
3338 : {
3339 : case EXC_CHAXIS_X:
3340 40 : if( rTypeInfo.mbCategoryAxis )
3341 : {
3342 40 : aScaleData.AxisType = cssc2::AxisType::CATEGORY;
3343 40 : aScaleData.Categories = rTypeGroup.CreateCategSequence();
3344 : }
3345 : else
3346 0 : aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
3347 40 : break;
3348 : case EXC_CHAXIS_Y:
3349 40 : aScaleData.AxisType = rTypeGroup.IsPercent() ?
3350 40 : cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER;
3351 40 : break;
3352 : case EXC_CHAXIS_Z:
3353 0 : aScaleData.AxisType = cssc2::AxisType::SERIES;
3354 0 : break;
3355 : }
3356 : // axis scaling settings, dependent on axis type
3357 80 : switch( aScaleData.AxisType )
3358 : {
3359 : case cssc2::AxisType::CATEGORY:
3360 : case cssc2::AxisType::SERIES:
3361 : OSL_ENSURE( mxLabelRange, "Missing Label Range" );
3362 : // #i71684# radar charts have reversed rotation direction
3363 40 : if (mxLabelRange)
3364 40 : mxLabelRange->Convert( aAxisProp, aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_RADAR );
3365 40 : break;
3366 : case cssc2::AxisType::REALNUMBER:
3367 : case cssc2::AxisType::PERCENT:
3368 : // #i85167# pie/donut charts have reversed rotation direction (at Y axis!)
3369 40 : mxValueRange->Convert( aScaleData, rTypeInfo.meTypeCateg == EXC_CHTYPECATEG_PIE );
3370 40 : break;
3371 : default:
3372 : OSL_FAIL( "XclImpChAxis::CreateAxis - unknown axis type" );
3373 : }
3374 :
3375 : /* Do not set a value to the Origin member anymore (will be done via
3376 : new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
3377 80 : aScaleData.Origin.clear();
3378 :
3379 : // write back
3380 80 : xAxis->setScaleData( aScaleData );
3381 :
3382 : // grid ---------------------------------------------------------------
3383 :
3384 : // main grid
3385 80 : ScfPropertySet aGridProp( xAxis->getGridProperties() );
3386 80 : aGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMajorGrid() );
3387 80 : if( mxMajorGrid )
3388 2 : mxMajorGrid->Convert( GetChRoot(), aGridProp, EXC_CHOBJTYPE_GRIDLINE );
3389 : // sub grid
3390 80 : Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties();
3391 80 : if( aSubGridPropSeq.hasElements() )
3392 : {
3393 80 : ScfPropertySet aSubGridProp( aSubGridPropSeq[ 0 ] );
3394 80 : aSubGridProp.SetBoolProperty( EXC_CHPROP_SHOW, HasMinorGrid() );
3395 80 : if( mxMinorGrid )
3396 0 : mxMinorGrid->Convert( GetChRoot(), aSubGridProp, EXC_CHOBJTYPE_GRIDLINE );
3397 : }
3398 :
3399 : // position of crossing axis ------------------------------------------
3400 :
3401 80 : if( pCrossingAxis )
3402 80 : pCrossingAxis->ConvertAxisPosition( aAxisProp, rTypeGroup );
3403 : }
3404 80 : return xAxis;
3405 : }
3406 :
3407 0 : void XclImpChAxis::ConvertWall( ScfPropertySet& rPropSet ) const
3408 : {
3409 : // #i71810# walls and floor in 3D charts use the CHPICFORMAT record for bitmap mode
3410 0 : if( mxWallFrame )
3411 0 : mxWallFrame->Convert( rPropSet, true );
3412 0 : }
3413 :
3414 80 : void XclImpChAxis::ConvertAxisPosition( ScfPropertySet& rPropSet, const XclImpChTypeGroup& rTypeGroup ) const
3415 : {
3416 80 : if( ((GetAxisType() == EXC_CHAXIS_X) && rTypeGroup.GetTypeInfo().mbCategoryAxis) || (GetAxisType() == EXC_CHAXIS_Z) )
3417 : {
3418 : OSL_ENSURE( mxLabelRange, "Missing Label Range" );
3419 40 : if (mxLabelRange)
3420 40 : mxLabelRange->ConvertAxisPosition( rPropSet, rTypeGroup.Is3dChart() );
3421 : }
3422 : else
3423 40 : mxValueRange->ConvertAxisPosition( rPropSet );
3424 80 : }
3425 :
3426 2 : void XclImpChAxis::ReadChAxisLine( XclImpStream& rStrm )
3427 : {
3428 2 : XclImpChLineFormatRef* pxLineFmt = 0;
3429 2 : bool bWallFrame = false;
3430 2 : switch( rStrm.ReaduInt16() )
3431 : {
3432 0 : case EXC_CHAXISLINE_AXISLINE: pxLineFmt = &mxAxisLine; break;
3433 2 : case EXC_CHAXISLINE_MAJORGRID: pxLineFmt = &mxMajorGrid; break;
3434 0 : case EXC_CHAXISLINE_MINORGRID: pxLineFmt = &mxMinorGrid; break;
3435 0 : case EXC_CHAXISLINE_WALLS: bWallFrame = true; break;
3436 : }
3437 2 : if( bWallFrame )
3438 0 : CreateWallFrame();
3439 :
3440 2 : bool bLoop = pxLineFmt || bWallFrame;
3441 8 : while( bLoop )
3442 : {
3443 4 : sal_uInt16 nRecId = rStrm.GetNextRecId();
3444 : bLoop = ((nRecId == EXC_ID_CHLINEFORMAT) ||
3445 : (nRecId == EXC_ID_CHAREAFORMAT) ||
3446 : (nRecId == EXC_ID_CHESCHERFORMAT))
3447 4 : && rStrm.StartNextRecord();
3448 4 : if( bLoop )
3449 : {
3450 2 : if( pxLineFmt && (nRecId == EXC_ID_CHLINEFORMAT) )
3451 : {
3452 2 : pxLineFmt->reset( new XclImpChLineFormat );
3453 2 : (*pxLineFmt)->ReadChLineFormat( rStrm );
3454 : }
3455 0 : else if( bWallFrame && mxWallFrame )
3456 : {
3457 0 : mxWallFrame->ReadSubRecord( rStrm );
3458 : }
3459 : }
3460 : }
3461 2 : }
3462 :
3463 80 : void XclImpChAxis::CreateWallFrame()
3464 : {
3465 80 : switch( GetAxisType() )
3466 : {
3467 : case EXC_CHAXIS_X:
3468 40 : mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_WALL3D ) );
3469 40 : break;
3470 : case EXC_CHAXIS_Y:
3471 40 : mxWallFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_FLOOR3D ) );
3472 40 : break;
3473 : default:
3474 0 : mxWallFrame.reset();
3475 : }
3476 80 : }
3477 :
3478 : // ----------------------------------------------------------------------------
3479 :
3480 120 : XclImpChAxesSet::XclImpChAxesSet( const XclImpChRoot& rRoot, sal_uInt16 nAxesSetId ) :
3481 120 : XclImpChRoot( rRoot )
3482 : {
3483 120 : maData.mnAxesSetId = nAxesSetId;
3484 120 : }
3485 :
3486 40 : void XclImpChAxesSet::ReadHeaderRecord( XclImpStream& rStrm )
3487 : {
3488 40 : rStrm >> maData.mnAxesSetId >> maData.maRect;
3489 40 : }
3490 :
3491 185 : void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm )
3492 : {
3493 185 : switch( rStrm.GetRecId() )
3494 : {
3495 : case EXC_ID_CHFRAMEPOS:
3496 40 : mxFramePos.reset( new XclImpChFramePos );
3497 40 : mxFramePos->ReadChFramePos( rStrm );
3498 40 : break;
3499 : case EXC_ID_CHAXIS:
3500 4 : ReadChAxis( rStrm );
3501 4 : break;
3502 : case EXC_ID_CHTEXT:
3503 0 : ReadChText( rStrm );
3504 0 : break;
3505 : case EXC_ID_CHPLOTFRAME:
3506 2 : ReadChPlotFrame( rStrm );
3507 2 : break;
3508 : case EXC_ID_CHTYPEGROUP:
3509 40 : ReadChTypeGroup( rStrm );
3510 40 : break;
3511 : }
3512 185 : }
3513 :
3514 80 : void XclImpChAxesSet::Finalize()
3515 : {
3516 80 : if( IsValidAxesSet() )
3517 : {
3518 : // finalize chart type groups, erase empty groups without series
3519 40 : XclImpChTypeGroupMap aValidGroups;
3520 80 : for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
3521 : {
3522 40 : XclImpChTypeGroupRef xTypeGroup = aIt->second;
3523 40 : xTypeGroup->Finalize();
3524 40 : if( xTypeGroup->IsValidGroup() )
3525 : aValidGroups.insert(
3526 40 : XclImpChTypeGroupMap::value_type(aIt->first, xTypeGroup));
3527 40 : }
3528 40 : maTypeGroups.swap( aValidGroups );
3529 : }
3530 :
3531 : // invalid chart type groups are deleted now, check again with IsValidAxesSet()
3532 80 : if( IsValidAxesSet() )
3533 : {
3534 : // always create missing axis objects
3535 40 : if( !mxXAxis )
3536 38 : mxXAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_X ) );
3537 40 : if( !mxYAxis )
3538 38 : mxYAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Y ) );
3539 40 : if( !mxZAxis && GetFirstTypeGroup()->Is3dDeepChart() )
3540 0 : mxZAxis.reset( new XclImpChAxis( GetChRoot(), EXC_CHAXIS_Z ) );
3541 :
3542 : // finalize axes
3543 40 : if( mxXAxis ) mxXAxis->Finalize();
3544 40 : if( mxYAxis ) mxYAxis->Finalize();
3545 40 : if( mxZAxis ) mxZAxis->Finalize();
3546 :
3547 : // finalize axis titles
3548 40 : const XclImpChText* pDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE );
3549 40 : String aAutoTitle = CREATE_STRING( "Axis Title" );
3550 40 : lclFinalizeTitle( mxXAxisTitle, pDefText, aAutoTitle );
3551 40 : lclFinalizeTitle( mxYAxisTitle, pDefText, aAutoTitle );
3552 40 : lclFinalizeTitle( mxZAxisTitle, pDefText, aAutoTitle );
3553 :
3554 : // #i47745# missing plot frame -> invisible border and area
3555 40 : if( !mxPlotFrame )
3556 38 : mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
3557 : }
3558 80 : }
3559 :
3560 160 : XclImpChTypeGroupRef XclImpChAxesSet::GetTypeGroup( sal_uInt16 nGroupIdx ) const
3561 : {
3562 160 : XclImpChTypeGroupMap::const_iterator itr = maTypeGroups.find(nGroupIdx);
3563 160 : return itr == maTypeGroups.end() ? XclImpChTypeGroupRef() : itr->second;
3564 : }
3565 :
3566 239 : XclImpChTypeGroupRef XclImpChAxesSet::GetFirstTypeGroup() const
3567 : {
3568 239 : XclImpChTypeGroupRef xTypeGroup;
3569 239 : if( !maTypeGroups.empty() )
3570 239 : xTypeGroup = maTypeGroups.begin()->second;
3571 239 : return xTypeGroup;
3572 : }
3573 :
3574 59 : XclImpChLegendRef XclImpChAxesSet::GetLegend() const
3575 : {
3576 59 : XclImpChLegendRef xLegend;
3577 99 : for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); !xLegend && (aIt != aEnd); ++aIt )
3578 40 : xLegend = aIt->second->GetLegend();
3579 59 : return xLegend;
3580 : }
3581 :
3582 38 : const String& XclImpChAxesSet::GetSingleSeriesTitle() const
3583 : {
3584 38 : return (maTypeGroups.size() == 1) ? maTypeGroups.begin()->second->GetSingleSeriesTitle() : String::EmptyString();
3585 : }
3586 :
3587 80 : void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const
3588 : {
3589 80 : if( IsValidAxesSet() && xDiagram.is() )
3590 : {
3591 : // diagram background formatting
3592 40 : if( GetAxesSetId() == EXC_CHAXESSET_PRIMARY )
3593 40 : ConvertBackground( xDiagram );
3594 :
3595 : // create the coordinate system, this inserts all chart types and series
3596 40 : Reference< XCoordinateSystem > xCoordSystem = CreateCoordSystem( xDiagram );
3597 40 : if( xCoordSystem.is() )
3598 : {
3599 : // insert coordinate system, if not already done
3600 : try
3601 : {
3602 40 : Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY_THROW );
3603 40 : Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3604 40 : if( aCoordSystems.getLength() == 0 )
3605 40 : xCoordSystemCont->addCoordinateSystem( xCoordSystem );
3606 : }
3607 0 : catch( Exception& )
3608 : {
3609 : OSL_FAIL( "XclImpChAxesSet::Convert - cannot insert coordinate system" );
3610 : }
3611 :
3612 : // create the axes with grids and axis titles and insert them into the diagram
3613 40 : ConvertAxis( mxXAxis, mxXAxisTitle, xCoordSystem, mxYAxis.get() );
3614 40 : ConvertAxis( mxYAxis, mxYAxisTitle, xCoordSystem, mxXAxis.get() );
3615 40 : ConvertAxis( mxZAxis, mxZAxisTitle, xCoordSystem, 0 );
3616 40 : }
3617 : }
3618 80 : }
3619 :
3620 80 : void XclImpChAxesSet::ConvertTitlePositions() const
3621 : {
3622 80 : if( mxXAxisTitle )
3623 0 : mxXAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_X ) );
3624 80 : if( mxYAxisTitle )
3625 0 : mxYAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Y ) );
3626 80 : if( mxZAxisTitle )
3627 0 : mxZAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Z ) );
3628 80 : }
3629 :
3630 4 : void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm )
3631 : {
3632 4 : XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) );
3633 4 : xAxis->ReadRecordGroup( rStrm );
3634 :
3635 4 : switch( xAxis->GetAxisType() )
3636 : {
3637 2 : case EXC_CHAXIS_X: mxXAxis = xAxis; break;
3638 2 : case EXC_CHAXIS_Y: mxYAxis = xAxis; break;
3639 0 : case EXC_CHAXIS_Z: mxZAxis = xAxis; break;
3640 4 : }
3641 4 : }
3642 :
3643 0 : void XclImpChAxesSet::ReadChText( XclImpStream& rStrm )
3644 : {
3645 0 : XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
3646 0 : xText->ReadRecordGroup( rStrm );
3647 :
3648 0 : switch( xText->GetLinkTarget() )
3649 : {
3650 0 : case EXC_CHOBJLINK_XAXIS: mxXAxisTitle = xText; break;
3651 0 : case EXC_CHOBJLINK_YAXIS: mxYAxisTitle = xText; break;
3652 0 : case EXC_CHOBJLINK_ZAXIS: mxZAxisTitle = xText; break;
3653 0 : }
3654 0 : }
3655 :
3656 2 : void XclImpChAxesSet::ReadChPlotFrame( XclImpStream& rStrm )
3657 : {
3658 2 : if( (rStrm.GetNextRecId() == EXC_ID_CHFRAME) && rStrm.StartNextRecord() )
3659 : {
3660 2 : mxPlotFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_PLOTFRAME ) );
3661 2 : mxPlotFrame->ReadRecordGroup( rStrm );
3662 : }
3663 2 : }
3664 :
3665 40 : void XclImpChAxesSet::ReadChTypeGroup( XclImpStream& rStrm )
3666 : {
3667 40 : XclImpChTypeGroupRef xTypeGroup( new XclImpChTypeGroup( GetChRoot() ) );
3668 40 : xTypeGroup->ReadRecordGroup( rStrm );
3669 40 : sal_uInt16 nGroupIdx = xTypeGroup->GetGroupIdx();
3670 40 : XclImpChTypeGroupMap::iterator itr = maTypeGroups.lower_bound(nGroupIdx);
3671 40 : if (itr != maTypeGroups.end() && !maTypeGroups.key_comp()(nGroupIdx, itr->first))
3672 : // Overwrite the existing element.
3673 0 : itr->second = xTypeGroup;
3674 : else
3675 : maTypeGroups.insert(
3676 40 : itr, XclImpChTypeGroupMap::value_type(nGroupIdx, xTypeGroup));
3677 40 : }
3678 :
3679 40 : Reference< XCoordinateSystem > XclImpChAxesSet::CreateCoordSystem( Reference< XDiagram > xDiagram ) const
3680 : {
3681 40 : Reference< XCoordinateSystem > xCoordSystem;
3682 :
3683 : /* Try to get existing ccordinate system. For now, all series from primary
3684 : and secondary axes sets are inserted into one coordinate system. Later,
3685 : this should be changed to use one coordinate system for each axes set. */
3686 40 : Reference< XCoordinateSystemContainer > xCoordSystemCont( xDiagram, UNO_QUERY );
3687 40 : if( xCoordSystemCont.is() )
3688 : {
3689 40 : Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems();
3690 : OSL_ENSURE( aCoordSystems.getLength() <= 1, "XclImpChAxesSet::CreateCoordSystem - too many existing coordinate systems" );
3691 40 : if( aCoordSystems.getLength() > 0 )
3692 0 : xCoordSystem = aCoordSystems[ 0 ];
3693 : }
3694 :
3695 : // create the coordinate system according to the first chart type
3696 40 : if( !xCoordSystem.is() )
3697 : {
3698 40 : XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3699 40 : if( xTypeGroup )
3700 : {
3701 40 : xCoordSystem = xTypeGroup->CreateCoordSystem();
3702 : // convert 3d chart settings
3703 40 : ScfPropertySet aDiaProp( xDiagram );
3704 40 : xTypeGroup->ConvertChart3d( aDiaProp );
3705 40 : }
3706 : }
3707 :
3708 : /* Create XChartType objects for all chart type groups. Each group will
3709 : add its series to the data provider attached to the chart document. */
3710 40 : Reference< XChartTypeContainer > xChartTypeCont( xCoordSystem, UNO_QUERY );
3711 40 : if( xChartTypeCont.is() )
3712 : {
3713 40 : sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3714 80 : for( XclImpChTypeGroupMap::const_iterator aIt = maTypeGroups.begin(), aEnd = maTypeGroups.end(); aIt != aEnd; ++aIt )
3715 : {
3716 : try
3717 : {
3718 40 : Reference< XChartType > xChartType = aIt->second->CreateChartType( xDiagram, nApiAxesSetIdx );
3719 40 : if( xChartType.is() )
3720 40 : xChartTypeCont->addChartType( xChartType );
3721 : }
3722 0 : catch( Exception& )
3723 : {
3724 : OSL_FAIL( "XclImpChAxesSet::CreateCoordSystem - cannot add chart type" );
3725 : }
3726 : }
3727 : }
3728 :
3729 40 : return xCoordSystem;
3730 : }
3731 :
3732 120 : void XclImpChAxesSet::ConvertAxis(
3733 : XclImpChAxisRef xChAxis, XclImpChTextRef xChAxisTitle,
3734 : Reference< XCoordinateSystem > xCoordSystem, const XclImpChAxis* pCrossingAxis ) const
3735 : {
3736 120 : if( xChAxis )
3737 : {
3738 : // create and attach the axis object
3739 80 : Reference< XAxis > xAxis = CreateAxis( *xChAxis, pCrossingAxis );
3740 80 : if( xAxis.is() )
3741 : {
3742 : // create and attach the axis title
3743 80 : if( xChAxisTitle ) try
3744 : {
3745 0 : Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW );
3746 0 : Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW );
3747 0 : xTitled->setTitleObject( xTitle );
3748 : }
3749 0 : catch( Exception& )
3750 : {
3751 : OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis title" );
3752 : }
3753 :
3754 : // insert axis into coordinate system
3755 : try
3756 : {
3757 80 : sal_Int32 nApiAxisDim = xChAxis->GetApiAxisDimension();
3758 80 : sal_Int32 nApiAxesSetIdx = GetApiAxesSetIndex();
3759 80 : xCoordSystem->setAxisByDimension( nApiAxisDim, xAxis, nApiAxesSetIdx );
3760 : }
3761 0 : catch( Exception& )
3762 : {
3763 : OSL_FAIL( "XclImpChAxesSet::ConvertAxis - cannot set axis" );
3764 : }
3765 80 : }
3766 : }
3767 120 : }
3768 :
3769 80 : Reference< XAxis > XclImpChAxesSet::CreateAxis( const XclImpChAxis& rChAxis, const XclImpChAxis* pCrossingAxis ) const
3770 : {
3771 80 : Reference< XAxis > xAxis;
3772 80 : if( const XclImpChTypeGroup* pTypeGroup = GetFirstTypeGroup().get() )
3773 80 : xAxis = rChAxis.CreateAxis( *pTypeGroup, pCrossingAxis );
3774 80 : return xAxis;
3775 : }
3776 :
3777 40 : void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const
3778 : {
3779 40 : XclImpChTypeGroupRef xTypeGroup = GetFirstTypeGroup();
3780 40 : if( xTypeGroup && xTypeGroup->Is3dWallChart() )
3781 : {
3782 : // wall/floor formatting (3D charts)
3783 0 : if( mxXAxis )
3784 : {
3785 0 : ScfPropertySet aWallProp( xDiagram->getWall() );
3786 0 : mxXAxis->ConvertWall( aWallProp );
3787 : }
3788 0 : if( mxYAxis )
3789 : {
3790 0 : ScfPropertySet aFloorProp( xDiagram->getFloor() );
3791 0 : mxYAxis->ConvertWall( aFloorProp );
3792 : }
3793 : }
3794 40 : else if( mxPlotFrame )
3795 : {
3796 : // diagram background formatting
3797 40 : ScfPropertySet aWallProp( xDiagram->getWall() );
3798 40 : mxPlotFrame->Convert( aWallProp );
3799 40 : }
3800 40 : }
3801 :
3802 : // The chart object ===========================================================
3803 :
3804 40 : XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) :
3805 40 : XclImpChRoot( rRoot, *this )
3806 : {
3807 40 : mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) );
3808 40 : mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) );
3809 40 : }
3810 :
3811 80 : XclImpChChart::~XclImpChChart()
3812 : {
3813 80 : }
3814 :
3815 40 : void XclImpChChart::ReadHeaderRecord( XclImpStream& rStrm )
3816 : {
3817 : // coordinates are stored as 16.16 fixed point
3818 40 : rStrm >> maRect;
3819 40 : }
3820 :
3821 678 : void XclImpChChart::ReadSubRecord( XclImpStream& rStrm )
3822 : {
3823 678 : switch( rStrm.GetRecId() )
3824 : {
3825 : case EXC_ID_CHFRAME:
3826 40 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
3827 40 : mxFrame->ReadRecordGroup( rStrm );
3828 40 : break;
3829 : case EXC_ID_CHSERIES:
3830 40 : ReadChSeries( rStrm );
3831 40 : break;
3832 : case EXC_ID_CHPROPERTIES:
3833 40 : ReadChProperties( rStrm );
3834 40 : break;
3835 : case EXC_ID_CHDEFAULTTEXT:
3836 80 : ReadChDefaultText( rStrm );
3837 80 : break;
3838 : case EXC_ID_CHAXESSET:
3839 40 : ReadChAxesSet( rStrm );
3840 40 : break;
3841 : case EXC_ID_CHTEXT:
3842 86 : ReadChText( rStrm );
3843 86 : break;
3844 : case EXC_ID_CHEND:
3845 40 : Finalize(); // finalize the entire chart object
3846 40 : break;
3847 : }
3848 678 : }
3849 :
3850 80 : void XclImpChChart::ReadChDefaultText( XclImpStream& rStrm )
3851 : {
3852 80 : sal_uInt16 nTextId = rStrm.ReaduInt16();
3853 80 : if( (rStrm.GetNextRecId() == EXC_ID_CHTEXT) && rStrm.StartNextRecord() )
3854 : {
3855 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
3856 80 : auto_ptr<XclImpChText> pText(new XclImpChText(GetChRoot()));
3857 : SAL_WNODEPRECATED_DECLARATIONS_POP
3858 80 : pText->ReadRecordGroup(rStrm);
3859 80 : maDefTexts.insert(nTextId, pText);
3860 : }
3861 80 : }
3862 :
3863 97 : void XclImpChChart::ReadChDataFormat( XclImpStream& rStrm )
3864 : {
3865 97 : XclImpChDataFormatRef xDataFmt( new XclImpChDataFormat( GetChRoot() ) );
3866 97 : xDataFmt->ReadRecordGroup( rStrm );
3867 97 : if( xDataFmt->GetPointPos().mnSeriesIdx <= EXC_CHSERIES_MAXSERIES )
3868 : {
3869 97 : const XclChDataPointPos& rPos = xDataFmt->GetPointPos();
3870 97 : XclImpChDataFormatMap::iterator itr = maDataFmts.lower_bound(rPos);
3871 97 : if (itr == maDataFmts.end() || maDataFmts.key_comp()(rPos, itr->first))
3872 : // No element exists for this data point. Insert it.
3873 : maDataFmts.insert(
3874 97 : itr, XclImpChDataFormatMap::value_type(rPos, xDataFmt));
3875 :
3876 : /* Do not overwrite existing data format group, Excel always uses the
3877 : first data format group occuring in any CHSERIES group. */
3878 97 : }
3879 97 : }
3880 :
3881 0 : void XclImpChChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
3882 : {
3883 0 : if( !mxFrame )
3884 0 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
3885 0 : mxFrame->UpdateObjFrame( rLineData, rFillData );
3886 0 : }
3887 :
3888 160 : XclImpChTypeGroupRef XclImpChChart::GetTypeGroup( sal_uInt16 nGroupIdx ) const
3889 : {
3890 160 : XclImpChTypeGroupRef xTypeGroup = mxPrimAxesSet->GetTypeGroup( nGroupIdx );
3891 160 : if( !xTypeGroup ) xTypeGroup = mxSecnAxesSet->GetTypeGroup( nGroupIdx );
3892 160 : if( !xTypeGroup ) xTypeGroup = mxPrimAxesSet->GetFirstTypeGroup();
3893 160 : return xTypeGroup;
3894 : }
3895 :
3896 219 : const XclImpChText* XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
3897 : {
3898 219 : sal_uInt16 nDefTextId = EXC_CHDEFTEXT_GLOBAL;
3899 219 : bool bBiff8 = GetBiff() == EXC_BIFF8;
3900 219 : switch( eTextType )
3901 : {
3902 40 : case EXC_CHTEXTTYPE_TITLE: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3903 21 : case EXC_CHTEXTTYPE_LEGEND: nDefTextId = EXC_CHDEFTEXT_GLOBAL; break;
3904 40 : case EXC_CHTEXTTYPE_AXISTITLE: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3905 78 : case EXC_CHTEXTTYPE_AXISLABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3906 40 : case EXC_CHTEXTTYPE_DATALABEL: nDefTextId = bBiff8 ? EXC_CHDEFTEXT_AXESSET : EXC_CHDEFTEXT_GLOBAL; break;
3907 : }
3908 :
3909 219 : XclImpChTextMap::const_iterator itr = maDefTexts.find(nDefTextId);
3910 219 : return itr == maDefTexts.end() ? NULL : itr->second;
3911 : }
3912 :
3913 61 : bool XclImpChChart::IsManualPlotArea() const
3914 : {
3915 : // there is no real automatic mode in BIFF5 charts
3916 61 : return (GetBiff() <= EXC_BIFF5) || ::get_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA );
3917 : }
3918 :
3919 40 : void XclImpChChart::Convert( const Reference<XChartDocument>& xChartDoc,
3920 : XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const
3921 : {
3922 : // initialize conversion (locks the model to suppress any internal updates)
3923 40 : InitConversion( xChartDoc, rChartRect );
3924 :
3925 : // chart frame formatting
3926 40 : if( mxFrame )
3927 : {
3928 40 : ScfPropertySet aFrameProp( xChartDoc->getPageBackground() );
3929 40 : mxFrame->Convert( aFrameProp );
3930 : }
3931 :
3932 : // chart title
3933 40 : if( mxTitle ) try
3934 : {
3935 21 : Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW );
3936 21 : Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW );
3937 21 : xTitled->setTitleObject( xTitle );
3938 : }
3939 0 : catch( Exception& )
3940 : {
3941 : }
3942 :
3943 : /* Create the diagram object and attach it to the chart document. Currently,
3944 : one diagram is used to carry all coordinate systems and data series. */
3945 40 : Reference< XDiagram > xDiagram = CreateDiagram();
3946 40 : xChartDoc->setFirstDiagram( xDiagram );
3947 :
3948 : // coordinate systems and chart types, convert axis settings
3949 40 : mxPrimAxesSet->Convert( xDiagram );
3950 40 : mxSecnAxesSet->Convert( xDiagram );
3951 :
3952 : // legend
3953 40 : if( xDiagram.is() && mxLegend )
3954 21 : xDiagram->setLegend( mxLegend->CreateLegend() );
3955 :
3956 : /* Following all conversions needing the old Chart1 API that involves full
3957 : initialization of the chart view. */
3958 40 : Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY );
3959 40 : if( xChart1Doc.is() )
3960 : {
3961 40 : Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram();
3962 :
3963 : /* Set the 'IncludeHiddenCells' property via the old API as only this
3964 : ensures that the data provider and all created sequences get this
3965 : flag correctly. */
3966 40 : ScfPropertySet aDiaProp( xDiagram1 );
3967 40 : bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY );
3968 40 : aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells );
3969 :
3970 : // plot area position and size (there is no real automatic mode in BIFF5 charts)
3971 40 : XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos();
3972 40 : if( IsManualPlotArea() && xPlotAreaPos ) try
3973 : {
3974 39 : const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData();
3975 39 : if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) )
3976 : {
3977 39 : Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW );
3978 39 : ::com::sun::star::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect );
3979 : // for pie charts, always set inner plot area size to exclude the data labels as Excel does
3980 39 : const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get();
3981 39 : if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) )
3982 37 : xPositioning->setDiagramPositionExcludingAxes( aDiagramRect );
3983 2 : else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() )
3984 0 : xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect );
3985 : else
3986 2 : xPositioning->setDiagramPositionIncludingAxes( aDiagramRect );
3987 : }
3988 : }
3989 0 : catch( Exception& )
3990 : {
3991 : }
3992 :
3993 : // positions of all title objects
3994 40 : if( mxTitle )
3995 21 : mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) );
3996 40 : mxPrimAxesSet->ConvertTitlePositions();
3997 40 : mxSecnAxesSet->ConvertTitlePositions();
3998 : }
3999 :
4000 : // unlock the model
4001 40 : FinishConversion( rDffConv );
4002 :
4003 : // start listening to this chart
4004 40 : ScDocument& rDoc = GetRoot().GetDoc();
4005 40 : if( ScChartListenerCollection* pChartCollection = rDoc.GetChartListenerCollection() )
4006 : {
4007 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
4008 40 : ::std::auto_ptr< ::std::vector< ScTokenRef > > xRefTokens( new ::std::vector< ScTokenRef > );
4009 : SAL_WNODEPRECATED_DECLARATIONS_POP
4010 80 : for( XclImpChSeriesVec::const_iterator aIt = maSeries.begin(), aEnd = maSeries.end(); aIt != aEnd; ++aIt )
4011 40 : (*aIt)->FillAllSourceLinks( *xRefTokens );
4012 40 : if( !xRefTokens->empty() )
4013 : {
4014 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
4015 40 : ::std::auto_ptr< ScChartListener > xListener( new ScChartListener( rObjName, &rDoc, xRefTokens.release() ) );
4016 : SAL_WNODEPRECATED_DECLARATIONS_POP
4017 40 : xListener->SetUsed( true );
4018 40 : xListener->StartListeningTo();
4019 40 : pChartCollection->insert( xListener.release() );
4020 40 : }
4021 40 : }
4022 40 : }
4023 :
4024 40 : void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
4025 : {
4026 40 : sal_uInt16 nNewSeriesIdx = static_cast< sal_uInt16 >( maSeries.size() );
4027 40 : XclImpChSeriesRef xSeries( new XclImpChSeries( GetChRoot(), nNewSeriesIdx ) );
4028 40 : xSeries->ReadRecordGroup( rStrm );
4029 40 : maSeries.push_back( xSeries );
4030 40 : }
4031 :
4032 40 : void XclImpChChart::ReadChProperties( XclImpStream& rStrm )
4033 : {
4034 40 : rStrm >> maProps.mnFlags >> maProps.mnEmptyMode;
4035 40 : }
4036 :
4037 40 : void XclImpChChart::ReadChAxesSet( XclImpStream& rStrm )
4038 : {
4039 40 : XclImpChAxesSetRef xAxesSet( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_NONE ) );
4040 40 : xAxesSet->ReadRecordGroup( rStrm );
4041 40 : switch( xAxesSet->GetAxesSetId() )
4042 : {
4043 40 : case EXC_CHAXESSET_PRIMARY: mxPrimAxesSet = xAxesSet; break;
4044 0 : case EXC_CHAXESSET_SECONDARY: mxSecnAxesSet = xAxesSet; break;
4045 40 : }
4046 40 : }
4047 :
4048 86 : void XclImpChChart::ReadChText( XclImpStream& rStrm )
4049 : {
4050 86 : XclImpChTextRef xText( new XclImpChText( GetChRoot() ) );
4051 86 : xText->ReadRecordGroup( rStrm );
4052 86 : switch( xText->GetLinkTarget() )
4053 : {
4054 : case EXC_CHOBJLINK_TITLE:
4055 21 : mxTitle = xText;
4056 21 : break;
4057 : case EXC_CHOBJLINK_DATA:
4058 : {
4059 65 : sal_uInt16 nSeriesIdx = xText->GetPointPos().mnSeriesIdx;
4060 65 : if( nSeriesIdx < maSeries.size() )
4061 65 : maSeries[ nSeriesIdx ]->SetDataLabel( xText );
4062 : }
4063 65 : break;
4064 86 : }
4065 86 : }
4066 :
4067 40 : void XclImpChChart::Finalize()
4068 : {
4069 : // finalize series (must be done first)
4070 40 : FinalizeSeries();
4071 : // #i49218# legend may be attached to primary or secondary axes set
4072 40 : mxLegend = mxPrimAxesSet->GetLegend();
4073 40 : if( !mxLegend )
4074 19 : mxLegend = mxSecnAxesSet->GetLegend();
4075 40 : if( mxLegend )
4076 21 : mxLegend->Finalize();
4077 : // axes sets, updates chart type group default formats -> must be called before FinalizeDataFormats()
4078 40 : mxPrimAxesSet->Finalize();
4079 40 : mxSecnAxesSet->Finalize();
4080 : // formatting of all series
4081 40 : FinalizeDataFormats();
4082 : // #i47745# missing frame -> invisible border and area
4083 40 : if( !mxFrame )
4084 0 : mxFrame.reset( new XclImpChFrame( GetChRoot(), EXC_CHOBJTYPE_BACKGROUND ) );
4085 : // chart title
4086 40 : FinalizeTitle();
4087 40 : }
4088 :
4089 40 : void XclImpChChart::FinalizeSeries()
4090 : {
4091 80 : for( XclImpChSeriesVec::iterator aSIt = maSeries.begin(), aSEnd = maSeries.end(); aSIt != aSEnd; ++aSIt )
4092 : {
4093 40 : XclImpChSeriesRef xSeries = *aSIt;
4094 40 : if( xSeries->HasParentSeries() )
4095 : {
4096 : /* Process child series (trend lines and error bars). Data of
4097 : child series will be set at the connected parent series. */
4098 0 : if( xSeries->GetParentIdx() < maSeries.size() )
4099 0 : maSeries[ xSeries->GetParentIdx() ]->AddChildSeries( *xSeries );
4100 : }
4101 : else
4102 : {
4103 : // insert the series into the related chart type group
4104 40 : if( XclImpChTypeGroup* pTypeGroup = GetTypeGroup( xSeries->GetGroupIdx() ).get() )
4105 40 : pTypeGroup->AddSeries( xSeries );
4106 : }
4107 40 : }
4108 40 : }
4109 :
4110 40 : void XclImpChChart::FinalizeDataFormats()
4111 : {
4112 : /* #i51639# (part 1): CHDATAFORMAT groups are part of CHSERIES groups.
4113 : Each CHDATAFORMAT group specifies the series and data point it is
4114 : assigned to. This makes it possible to have a data format that is
4115 : related to another series, e.g. a CHDATAFORMAT group for series 2 is
4116 : part of a CHSERIES group that describes series 1. Therefore the chart
4117 : itself has collected all CHDATAFORMAT groups to be able to store data
4118 : format groups for series that have not been imported at that time. This
4119 : loop finally assigns these groups to the related series. */
4120 137 : for( XclImpChDataFormatMap::const_iterator aMIt = maDataFmts.begin(), aMEnd = maDataFmts.end(); aMIt != aMEnd; ++aMIt )
4121 : {
4122 97 : sal_uInt16 nSeriesIdx = aMIt->first.mnSeriesIdx;
4123 97 : if( nSeriesIdx < maSeries.size() )
4124 97 : maSeries[ nSeriesIdx ]->SetDataFormat( aMIt->second );
4125 : }
4126 :
4127 : /* #i51639# (part 2): Finalize data formats of all series. This adds for
4128 : example missing CHDATAFORMAT groups for entire series that are needed
4129 : for automatic colors of lines and areas. */
4130 80 : for( XclImpChSeriesVec::iterator aVIt = maSeries.begin(), aVEnd = maSeries.end(); aVIt != aVEnd; ++aVIt )
4131 40 : (*aVIt)->FinalizeDataFormats();
4132 40 : }
4133 :
4134 40 : void XclImpChChart::FinalizeTitle()
4135 : {
4136 : // special handling for auto-generated title
4137 40 : String aAutoTitle;
4138 40 : if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) )
4139 : {
4140 : // automatic title from first series name (if there are no series on secondary axes set)
4141 38 : if( !mxSecnAxesSet->IsValidAxesSet() )
4142 38 : aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle();
4143 38 : if( mxTitle || (aAutoTitle.Len() > 0) )
4144 : {
4145 19 : if( !mxTitle )
4146 0 : mxTitle.reset( new XclImpChText( GetChRoot() ) );
4147 19 : if( aAutoTitle.Len() == 0 )
4148 0 : aAutoTitle = CREATE_STRING( "Chart Title" );
4149 : }
4150 : }
4151 :
4152 : // will reset mxTitle, if it does not contain a string and no auto title exists
4153 40 : lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle );
4154 40 : }
4155 :
4156 40 : Reference< XDiagram > XclImpChChart::CreateDiagram() const
4157 : {
4158 : // create a diagram object
4159 40 : Reference< XDiagram > xDiagram( ScfApiHelper::CreateInstance( SERVICE_CHART2_DIAGRAM ), UNO_QUERY );
4160 :
4161 : // convert global chart settings
4162 40 : ScfPropertySet aDiaProp( xDiagram );
4163 :
4164 : // treatment of missing values
4165 : using namespace cssc::MissingValueTreatment;
4166 40 : sal_Int32 nMissingValues = LEAVE_GAP;
4167 40 : switch( maProps.mnEmptyMode )
4168 : {
4169 2 : case EXC_CHPROPS_EMPTY_SKIP: nMissingValues = LEAVE_GAP; break;
4170 38 : case EXC_CHPROPS_EMPTY_ZERO: nMissingValues = USE_ZERO; break;
4171 0 : case EXC_CHPROPS_EMPTY_INTERPOLATE: nMissingValues = CONTINUE; break;
4172 : }
4173 40 : aDiaProp.SetProperty( EXC_CHPROP_MISSINGVALUETREATMENT, nMissingValues );
4174 :
4175 40 : return xDiagram;
4176 : }
4177 :
4178 : // ----------------------------------------------------------------------------
4179 :
4180 38 : XclImpChartDrawing::XclImpChartDrawing( const XclImpRoot& rRoot, bool bOwnTab ) :
4181 : XclImpDrawing( rRoot, bOwnTab ), // sheet charts may contain OLE objects
4182 38 : mnScTab( rRoot.GetCurrScTab() ),
4183 76 : mbOwnTab( bOwnTab )
4184 : {
4185 38 : }
4186 :
4187 38 : void XclImpChartDrawing::ConvertObjects( XclImpDffConverter& rDffConv,
4188 : const Reference< XModel >& rxModel, const Rectangle& rChartRect )
4189 : {
4190 38 : maChartRect = rChartRect; // needed in CalcAnchorRect() callback
4191 :
4192 38 : SdrModel* pSdrModel = 0;
4193 38 : SdrPage* pSdrPage = 0;
4194 38 : if( mbOwnTab )
4195 : {
4196 : // chart sheet: insert all shapes into the sheet, not into the chart object
4197 0 : pSdrModel = GetDoc().GetDrawLayer();
4198 0 : pSdrPage = GetSdrPage( mnScTab );
4199 : }
4200 : else
4201 : {
4202 : // embedded chart object: insert all shapes into the chart
4203 : try
4204 : {
4205 38 : Reference< XDrawPageSupplier > xDrawPageSupp( rxModel, UNO_QUERY_THROW );
4206 38 : Reference< XDrawPage > xDrawPage( xDrawPageSupp->getDrawPage(), UNO_SET_THROW );
4207 38 : pSdrPage = ::GetSdrPageFromXDrawPage( xDrawPage );
4208 38 : pSdrModel = pSdrPage ? pSdrPage->GetModel() : 0;
4209 : }
4210 0 : catch( Exception& )
4211 : {
4212 : }
4213 : }
4214 :
4215 38 : if( pSdrModel && pSdrPage )
4216 38 : ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4217 38 : }
4218 :
4219 0 : Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool bDffAnchor ) const
4220 : {
4221 : /* In objects with DFF client anchor, the position of the shape is stored
4222 : in the cell address components of the client anchor. In old BIFF3-BIFF5
4223 : objects, the position is stored in the offset components of the anchor. */
4224 : Rectangle aRect(
4225 0 : static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
4226 0 : static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ),
4227 0 : static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ),
4228 0 : static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) );
4229 0 : aRect.Justify();
4230 : // move shapes into chart area for sheet charts
4231 0 : if( mbOwnTab )
4232 0 : aRect.Move( maChartRect.Left(), maChartRect.Top() );
4233 0 : return aRect;
4234 : }
4235 :
4236 0 : void XclImpChartDrawing::OnObjectInserted( const XclImpDrawObjBase& )
4237 : {
4238 0 : }
4239 :
4240 : // ----------------------------------------------------------------------------
4241 :
4242 41 : XclImpChart::XclImpChart( const XclImpRoot& rRoot, bool bOwnTab ) :
4243 : XclImpRoot( rRoot ),
4244 : mbOwnTab( bOwnTab ),
4245 41 : mbIsPivotChart( false )
4246 : {
4247 41 : }
4248 :
4249 82 : XclImpChart::~XclImpChart()
4250 : {
4251 82 : }
4252 :
4253 41 : void XclImpChart::ReadChartSubStream( XclImpStream& rStrm )
4254 : {
4255 41 : XclImpPageSettings& rPageSett = GetPageSettings();
4256 41 : XclImpTabViewSettings& rTabViewSett = GetTabViewSettings();
4257 :
4258 41 : bool bLoop = true;
4259 1009 : while( bLoop && rStrm.StartNextRecord() )
4260 : {
4261 : // page settings - only for charts in entire sheet
4262 927 : if( mbOwnTab ) switch( rStrm.GetRecId() )
4263 : {
4264 : case EXC_ID_HORPAGEBREAKS:
4265 0 : case EXC_ID_VERPAGEBREAKS: rPageSett.ReadPageBreaks( rStrm ); break;
4266 : case EXC_ID_HEADER:
4267 0 : case EXC_ID_FOOTER: rPageSett.ReadHeaderFooter( rStrm ); break;
4268 : case EXC_ID_LEFTMARGIN:
4269 : case EXC_ID_RIGHTMARGIN:
4270 : case EXC_ID_TOPMARGIN:
4271 0 : case EXC_ID_BOTTOMMARGIN: rPageSett.ReadMargin( rStrm ); break;
4272 0 : case EXC_ID_PRINTHEADERS: rPageSett.ReadPrintHeaders( rStrm ); break;
4273 0 : case EXC_ID_PRINTGRIDLINES: rPageSett.ReadPrintGridLines( rStrm ); break;
4274 : case EXC_ID_HCENTER:
4275 0 : case EXC_ID_VCENTER: rPageSett.ReadCenter( rStrm ); break;
4276 0 : case EXC_ID_SETUP: rPageSett.ReadSetup( rStrm ); break;
4277 0 : case EXC_ID8_IMGDATA: rPageSett.ReadImgData( rStrm ); break;
4278 :
4279 0 : case EXC_ID_WINDOW2: rTabViewSett.ReadWindow2( rStrm, true );break;
4280 0 : case EXC_ID_SCL: rTabViewSett.ReadScl( rStrm ); break;
4281 :
4282 : case EXC_ID_SHEETEXT: //0x0862
4283 : {
4284 : // FIXME: do not need to pass palette, XclImpTabVieSettings is derived from root
4285 0 : XclImpPalette& rPal = GetPalette();
4286 0 : rTabViewSett.ReadTabBgColor( rStrm, rPal);
4287 : }
4288 0 : break;
4289 :
4290 0 : case EXC_ID_CODENAME: ReadCodeName( rStrm, false ); break;
4291 : }
4292 :
4293 : // common records
4294 927 : switch( rStrm.GetRecId() )
4295 : {
4296 41 : case EXC_ID_EOF: bLoop = false; break;
4297 :
4298 : // #i31882# ignore embedded chart objects
4299 : case EXC_ID2_BOF:
4300 : case EXC_ID3_BOF:
4301 : case EXC_ID4_BOF:
4302 0 : case EXC_ID5_BOF: XclTools::SkipSubStream( rStrm ); break;
4303 :
4304 40 : case EXC_ID_CHCHART: ReadChChart( rStrm ); break;
4305 :
4306 : case EXC_ID8_CHPIVOTREF:
4307 0 : GetTracer().TracePivotChartExists();
4308 0 : mbIsPivotChart = true;
4309 0 : break;
4310 :
4311 : // BIFF specific records
4312 846 : default: switch( GetBiff() )
4313 : {
4314 0 : case EXC_BIFF5: switch( rStrm.GetRecId() )
4315 : {
4316 0 : case EXC_ID_OBJ: GetChartDrawing().ReadObj( rStrm ); break;
4317 : }
4318 0 : break;
4319 846 : case EXC_BIFF8: switch( rStrm.GetRecId() )
4320 : {
4321 38 : case EXC_ID_MSODRAWING: GetChartDrawing().ReadMsoDrawing( rStrm ); break;
4322 : // #i61786# weird documents: OBJ without MSODRAWING -> read in BIFF5 format
4323 0 : case EXC_ID_OBJ: GetChartDrawing().ReadObj( rStrm ); break;
4324 : }
4325 846 : break;
4326 : default:;
4327 : }
4328 : }
4329 : }
4330 41 : }
4331 :
4332 0 : void XclImpChart::UpdateObjFrame( const XclObjLineData& rLineData, const XclObjFillData& rFillData )
4333 : {
4334 0 : if( !mxChartData )
4335 0 : mxChartData.reset( new XclImpChChart( GetRoot() ) );
4336 0 : mxChartData->UpdateObjFrame( rLineData, rFillData );
4337 0 : }
4338 :
4339 41 : sal_Size XclImpChart::GetProgressSize() const
4340 : {
4341 : return
4342 81 : (mxChartData ? mxChartData->GetProgressSize() : 0) +
4343 81 : (mxChartDrawing ? mxChartDrawing->GetProgressSize() : 0);
4344 : }
4345 :
4346 41 : void XclImpChart::Convert( Reference< XModel > xModel, XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const
4347 : {
4348 41 : Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
4349 41 : if( xChartDoc.is() )
4350 : {
4351 41 : if( mxChartData )
4352 40 : mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect );
4353 41 : if( mxChartDrawing )
4354 38 : mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect );
4355 41 : }
4356 41 : }
4357 :
4358 38 : XclImpChartDrawing& XclImpChart::GetChartDrawing()
4359 : {
4360 38 : if( !mxChartDrawing )
4361 38 : mxChartDrawing.reset( new XclImpChartDrawing( GetRoot(), mbOwnTab ) );
4362 38 : return *mxChartDrawing;
4363 : }
4364 :
4365 40 : void XclImpChart::ReadChChart( XclImpStream& rStrm )
4366 : {
4367 40 : mxChartData.reset( new XclImpChChart( GetRoot() ) );
4368 40 : mxChartData->ReadRecordGroup( rStrm );
4369 49 : }
4370 :
4371 : // ============================================================================
4372 :
4373 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|