1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/drawingml/chart/seriesconverter.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <com/sun/star/chart/DataLabelPlacement.hpp>
27cdf0e10cSrcweir #include <com/sun/star/chart/ErrorBarStyle.hpp>
28cdf0e10cSrcweir #include <com/sun/star/chart2/DataPointLabel.hpp>
29cdf0e10cSrcweir #include <com/sun/star/chart2/XDataSeries.hpp>
30cdf0e10cSrcweir #include <com/sun/star/chart2/XRegressionCurve.hpp>
31cdf0e10cSrcweir #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
32cdf0e10cSrcweir #include <com/sun/star/chart2/data/XDataSink.hpp>
33cdf0e10cSrcweir #include "oox/drawingml/chart/datasourceconverter.hxx"
34cdf0e10cSrcweir #include "oox/drawingml/chart/seriesmodel.hxx"
35cdf0e10cSrcweir #include "oox/drawingml/chart/titleconverter.hxx"
36cdf0e10cSrcweir #include "oox/drawingml/chart/typegroupconverter.hxx"
37cdf0e10cSrcweir #include "oox/drawingml/chart/typegroupmodel.hxx"
38cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir namespace oox {
41cdf0e10cSrcweir namespace drawingml {
42cdf0e10cSrcweir namespace chart {
43cdf0e10cSrcweir 
44cdf0e10cSrcweir // ============================================================================
45cdf0e10cSrcweir 
46cdf0e10cSrcweir using namespace ::com::sun::star::beans;
47cdf0e10cSrcweir using namespace ::com::sun::star::chart2;
48cdf0e10cSrcweir using namespace ::com::sun::star::chart2::data;
49cdf0e10cSrcweir using namespace ::com::sun::star::uno;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using ::rtl::OUString;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // ============================================================================
54cdf0e10cSrcweir 
55cdf0e10cSrcweir namespace {
56cdf0e10cSrcweir 
lclCreateLabeledDataSequence(const ConverterRoot & rParent,DataSourceModel * pValues,const OUString & rRole,TextModel * pTitle=0)57cdf0e10cSrcweir Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
58cdf0e10cSrcweir         const ConverterRoot& rParent,
59cdf0e10cSrcweir         DataSourceModel* pValues, const OUString& rRole,
60cdf0e10cSrcweir         TextModel* pTitle = 0 )
61cdf0e10cSrcweir {
62cdf0e10cSrcweir     // create data sequence for values
63cdf0e10cSrcweir     Reference< XDataSequence > xValueSeq;
64cdf0e10cSrcweir     if( pValues )
65cdf0e10cSrcweir     {
66cdf0e10cSrcweir         DataSourceConverter aSourceConv( rParent, *pValues );
67cdf0e10cSrcweir         xValueSeq = aSourceConv.createDataSequence( rRole );
68cdf0e10cSrcweir     }
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     // create data sequence for title
71cdf0e10cSrcweir     Reference< XDataSequence > xTitleSeq;
72cdf0e10cSrcweir     if( pTitle )
73cdf0e10cSrcweir     {
74cdf0e10cSrcweir         TextConverter aTextConv( rParent, *pTitle );
75cdf0e10cSrcweir         xTitleSeq = aTextConv.createDataSequence( CREATE_OUSTRING( "label" ) );
76cdf0e10cSrcweir     }
77cdf0e10cSrcweir 
78cdf0e10cSrcweir     // create the labeled data sequence, if values or title are present
79cdf0e10cSrcweir     Reference< XLabeledDataSequence > xLabeledSeq;
80cdf0e10cSrcweir     if( xValueSeq.is() || xTitleSeq.is() )
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         xLabeledSeq.set( rParent.createInstance( CREATE_OUSTRING( "com.sun.star.chart2.data.LabeledDataSequence" ) ), UNO_QUERY );
83cdf0e10cSrcweir         if( xLabeledSeq.is() )
84cdf0e10cSrcweir         {
85cdf0e10cSrcweir             xLabeledSeq->setValues( xValueSeq );
86cdf0e10cSrcweir             xLabeledSeq->setLabel( xTitleSeq );
87cdf0e10cSrcweir         }
88cdf0e10cSrcweir     }
89cdf0e10cSrcweir     return xLabeledSeq;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir 
lclConvertLabelFormatting(PropertySet & rPropSet,ObjectFormatter & rFormatter,const DataLabelModelBase & rDataLabel,const TypeGroupConverter & rTypeGroup,bool bDataSeriesLabel)92cdf0e10cSrcweir void lclConvertLabelFormatting( PropertySet& rPropSet, ObjectFormatter& rFormatter,
93cdf0e10cSrcweir         const DataLabelModelBase& rDataLabel, const TypeGroupConverter& rTypeGroup, bool bDataSeriesLabel )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir     const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     /*  Excel 2007 does not change the series setting for a single data point,
98cdf0e10cSrcweir         if none of some specific elements occur. But only one existing element
99cdf0e10cSrcweir         in a data point will reset most other of these elements from the series
100cdf0e10cSrcweir         (e.g.: series has <c:showVal>, data point has <c:showCatName>, this
101cdf0e10cSrcweir         will reset <c:showVal> for this point, unless <c:showVal> is repeated
102cdf0e10cSrcweir         in the data point). The elements <c:layout>, <c:numberFormat>,
103cdf0e10cSrcweir         <c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */
104cdf0e10cSrcweir     bool bHasAnyElement =
105cdf0e10cSrcweir         rDataLabel.moaSeparator.has() || rDataLabel.monLabelPos.has() ||
106cdf0e10cSrcweir         rDataLabel.mobShowCatName.has() || rDataLabel.mobShowLegendKey.has() ||
107cdf0e10cSrcweir         rDataLabel.mobShowPercent.has() || rDataLabel.mobShowSerName.has() ||
108cdf0e10cSrcweir         rDataLabel.mobShowVal.has();
109cdf0e10cSrcweir 
110cdf0e10cSrcweir     bool bShowValue   = !rDataLabel.mbDeleted && rDataLabel.mobShowVal.get( false );
111cdf0e10cSrcweir     bool bShowPercent = !rDataLabel.mbDeleted && rDataLabel.mobShowPercent.get( false ) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE);
112cdf0e10cSrcweir     bool bShowCateg   = !rDataLabel.mbDeleted && rDataLabel.mobShowCatName.get( false );
113cdf0e10cSrcweir     bool bShowSymbol  = !rDataLabel.mbDeleted && rDataLabel.mobShowLegendKey.get( false );
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     // type of attached label
116cdf0e10cSrcweir     if( bHasAnyElement || rDataLabel.mbDeleted )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
119cdf0e10cSrcweir         rPropSet.setProperty( PROP_Label, aPointLabel );
120cdf0e10cSrcweir     }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     if( !rDataLabel.mbDeleted )
123cdf0e10cSrcweir     {
124cdf0e10cSrcweir         // data label number format (percentage format wins over value format)
125cdf0e10cSrcweir         rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, bShowPercent );
126cdf0e10cSrcweir 
127cdf0e10cSrcweir         // data label text formatting (frame formatting not supported by Chart2)
128cdf0e10cSrcweir         rFormatter.convertTextFormatting( rPropSet, rDataLabel.mxTextProp, OBJECTTYPE_DATALABEL );
129cdf0e10cSrcweir         rFormatter.convertTextRotation( rPropSet, rDataLabel.mxTextProp, false );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir         // data label separator (do not overwrite series separator, if no explicit point separator is present)
132cdf0e10cSrcweir         if( bDataSeriesLabel || rDataLabel.moaSeparator.has() )
133cdf0e10cSrcweir             rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.get( CREATE_OUSTRING( "; " ) ) );
134cdf0e10cSrcweir 
135cdf0e10cSrcweir         // data label placement (do not overwrite series placement, if no explicit point placement is present)
136cdf0e10cSrcweir         if( bDataSeriesLabel || rDataLabel.monLabelPos.has() )
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
139cdf0e10cSrcweir             sal_Int32 nPlacement = rTypeInfo.mnDefLabelPos;
140cdf0e10cSrcweir             switch( rDataLabel.monLabelPos.get( XML_TOKEN_INVALID ) )
141cdf0e10cSrcweir             {
142cdf0e10cSrcweir                 case XML_outEnd:    nPlacement = csscd::OUTSIDE;        break;
143cdf0e10cSrcweir                 case XML_inEnd:     nPlacement = csscd::INSIDE;         break;
144cdf0e10cSrcweir                 case XML_ctr:       nPlacement = csscd::CENTER;         break;
145cdf0e10cSrcweir                 case XML_inBase:    nPlacement = csscd::NEAR_ORIGIN;    break;
146cdf0e10cSrcweir                 case XML_t:         nPlacement = csscd::TOP;            break;
147cdf0e10cSrcweir                 case XML_b:         nPlacement = csscd::BOTTOM;         break;
148cdf0e10cSrcweir                 case XML_l:         nPlacement = csscd::LEFT;           break;
149cdf0e10cSrcweir                 case XML_r:         nPlacement = csscd::RIGHT;          break;
150cdf0e10cSrcweir                 case XML_bestFit:   nPlacement = csscd::AVOID_OVERLAP;  break;
151cdf0e10cSrcweir             }
152cdf0e10cSrcweir             rPropSet.setProperty( PROP_LabelPlacement, nPlacement );
153cdf0e10cSrcweir         }
154cdf0e10cSrcweir     }
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir } // namespace
158cdf0e10cSrcweir 
159cdf0e10cSrcweir // ============================================================================
160cdf0e10cSrcweir 
DataLabelConverter(const ConverterRoot & rParent,DataLabelModel & rModel)161cdf0e10cSrcweir DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) :
162cdf0e10cSrcweir     ConverterBase< DataLabelModel >( rParent, rModel )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
~DataLabelConverter()166cdf0e10cSrcweir DataLabelConverter::~DataLabelConverter()
167cdf0e10cSrcweir {
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup)170cdf0e10cSrcweir void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     if( rxDataSeries.is() ) try
173cdf0e10cSrcweir     {
174cdf0e10cSrcweir         PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
175cdf0e10cSrcweir         lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, false );
176cdf0e10cSrcweir     }
177cdf0e10cSrcweir     catch( Exception& )
178cdf0e10cSrcweir     {
179cdf0e10cSrcweir     }
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir // ============================================================================
183cdf0e10cSrcweir 
DataLabelsConverter(const ConverterRoot & rParent,DataLabelsModel & rModel)184cdf0e10cSrcweir DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) :
185cdf0e10cSrcweir     ConverterBase< DataLabelsModel >( rParent, rModel )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir }
188cdf0e10cSrcweir 
~DataLabelsConverter()189cdf0e10cSrcweir DataLabelsConverter::~DataLabelsConverter()
190cdf0e10cSrcweir {
191cdf0e10cSrcweir }
192cdf0e10cSrcweir 
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup)193cdf0e10cSrcweir void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
194cdf0e10cSrcweir {
195cdf0e10cSrcweir     if( !mrModel.mbDeleted )
196cdf0e10cSrcweir     {
197cdf0e10cSrcweir         PropertySet aPropSet( rxDataSeries );
198cdf0e10cSrcweir         lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, true );
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir 
201cdf0e10cSrcweir     // data point label settings
202cdf0e10cSrcweir     for( DataLabelsModel::DataLabelVector::iterator aIt = mrModel.maPointLabels.begin(), aEnd = mrModel.maPointLabels.end(); aIt != aEnd; ++aIt )
203cdf0e10cSrcweir     {
204cdf0e10cSrcweir         DataLabelConverter aLabelConv( *this, **aIt );
205cdf0e10cSrcweir         aLabelConv.convertFromModel( rxDataSeries, rTypeGroup );
206cdf0e10cSrcweir     }
207cdf0e10cSrcweir }
208cdf0e10cSrcweir 
209cdf0e10cSrcweir // ============================================================================
210cdf0e10cSrcweir 
ErrorBarConverter(const ConverterRoot & rParent,ErrorBarModel & rModel)211cdf0e10cSrcweir ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) :
212cdf0e10cSrcweir     ConverterBase< ErrorBarModel >( rParent, rModel )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir }
215cdf0e10cSrcweir 
~ErrorBarConverter()216cdf0e10cSrcweir ErrorBarConverter::~ErrorBarConverter()
217cdf0e10cSrcweir {
218cdf0e10cSrcweir }
219cdf0e10cSrcweir 
convertFromModel(const Reference<XDataSeries> & rxDataSeries)220cdf0e10cSrcweir void ErrorBarConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir     bool bShowPos = (mrModel.mnTypeId == XML_plus) || (mrModel.mnTypeId == XML_both);
223cdf0e10cSrcweir     bool bShowNeg = (mrModel.mnTypeId == XML_minus) || (mrModel.mnTypeId == XML_both);
224cdf0e10cSrcweir     if( bShowPos || bShowNeg ) try
225cdf0e10cSrcweir     {
226cdf0e10cSrcweir         Reference< XPropertySet > xErrorBar( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.ErrorBar" ) ), UNO_QUERY_THROW );
227cdf0e10cSrcweir         PropertySet aBarProp( xErrorBar );
228cdf0e10cSrcweir 
229cdf0e10cSrcweir         // plus/minus bars
230cdf0e10cSrcweir         aBarProp.setProperty( PROP_ShowPositiveError, bShowPos );
231cdf0e10cSrcweir         aBarProp.setProperty( PROP_ShowNegativeError, bShowNeg );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir         // type of displayed error
234cdf0e10cSrcweir         namespace cssc = ::com::sun::star::chart;
235cdf0e10cSrcweir         switch( mrModel.mnValueType )
236cdf0e10cSrcweir         {
237cdf0e10cSrcweir             case XML_cust:
238cdf0e10cSrcweir             {
239cdf0e10cSrcweir                 // #i87806# manual error bars
240cdf0e10cSrcweir                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::FROM_DATA );
241cdf0e10cSrcweir                 // attach data sequences to erorr bar
242cdf0e10cSrcweir                 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
243cdf0e10cSrcweir                 if( xDataSink.is() )
244cdf0e10cSrcweir                 {
245cdf0e10cSrcweir                     // create vector of all value sequences
246cdf0e10cSrcweir                     ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
247cdf0e10cSrcweir                     // add positive values
248cdf0e10cSrcweir                     if( bShowPos )
249cdf0e10cSrcweir                     {
250cdf0e10cSrcweir                         Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::PLUS );
251cdf0e10cSrcweir                         if( xValueSeq.is() )
252cdf0e10cSrcweir                             aLabeledSeqVec.push_back( xValueSeq );
253cdf0e10cSrcweir                     }
254cdf0e10cSrcweir                     // add negative values
255cdf0e10cSrcweir                     if( bShowNeg )
256cdf0e10cSrcweir                     {
257cdf0e10cSrcweir                         Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::MINUS );
258cdf0e10cSrcweir                         if( xValueSeq.is() )
259cdf0e10cSrcweir                             aLabeledSeqVec.push_back( xValueSeq );
260cdf0e10cSrcweir                     }
261cdf0e10cSrcweir                     // attach labeled data sequences to series
262cdf0e10cSrcweir                     if( aLabeledSeqVec.empty() )
263cdf0e10cSrcweir                         xErrorBar.clear();
264cdf0e10cSrcweir                     else
265cdf0e10cSrcweir                         xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
266cdf0e10cSrcweir                 }
267cdf0e10cSrcweir             }
268cdf0e10cSrcweir             break;
269cdf0e10cSrcweir             case XML_fixedVal:
270cdf0e10cSrcweir                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::ABSOLUTE );
271cdf0e10cSrcweir                 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
272cdf0e10cSrcweir                 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
273cdf0e10cSrcweir             break;
274cdf0e10cSrcweir             case XML_percentage:
275cdf0e10cSrcweir                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::RELATIVE );
276cdf0e10cSrcweir                 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
277cdf0e10cSrcweir                 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
278cdf0e10cSrcweir             break;
279cdf0e10cSrcweir             case XML_stdDev:
280cdf0e10cSrcweir                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_DEVIATION );
281cdf0e10cSrcweir                 aBarProp.setProperty( PROP_Weight, mrModel.mfValue );
282cdf0e10cSrcweir             break;
283cdf0e10cSrcweir             case XML_stdErr:
284cdf0e10cSrcweir                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_ERROR );
285cdf0e10cSrcweir             break;
286cdf0e10cSrcweir             default:
287cdf0e10cSrcweir                 OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - unknown error bar type" );
288cdf0e10cSrcweir                 xErrorBar.clear();
289cdf0e10cSrcweir         }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir         // error bar formatting
292cdf0e10cSrcweir         getFormatter().convertFrameFormatting( aBarProp, mrModel.mxShapeProp, OBJECTTYPE_ERRORBAR );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir         if( xErrorBar.is() )
295cdf0e10cSrcweir         {
296cdf0e10cSrcweir             PropertySet aSeriesProp( rxDataSeries );
297cdf0e10cSrcweir             switch( mrModel.mnDirection )
298cdf0e10cSrcweir             {
299cdf0e10cSrcweir                 case XML_x: aSeriesProp.setProperty( PROP_ErrorBarX, xErrorBar );   break;
300cdf0e10cSrcweir                 case XML_y: aSeriesProp.setProperty( PROP_ErrorBarY, xErrorBar );   break;
301cdf0e10cSrcweir                 default:    OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - invalid error bar direction" );
302cdf0e10cSrcweir             }
303cdf0e10cSrcweir         }
304cdf0e10cSrcweir     }
305cdf0e10cSrcweir     catch( Exception& )
306cdf0e10cSrcweir     {
307cdf0e10cSrcweir         OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - error while creating error bars" );
308cdf0e10cSrcweir     }
309cdf0e10cSrcweir }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir // private --------------------------------------------------------------------
312cdf0e10cSrcweir 
createLabeledDataSequence(ErrorBarModel::SourceType eSourceType)313cdf0e10cSrcweir Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir     OUString aRole;
316cdf0e10cSrcweir     switch( eSourceType )
317cdf0e10cSrcweir     {
318cdf0e10cSrcweir         case ErrorBarModel::PLUS:
319cdf0e10cSrcweir             switch( mrModel.mnDirection )
320cdf0e10cSrcweir             {
321cdf0e10cSrcweir                 case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-positive" ); break;
322cdf0e10cSrcweir                 case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-positive" ); break;
323cdf0e10cSrcweir             }
324cdf0e10cSrcweir         break;
325cdf0e10cSrcweir         case ErrorBarModel::MINUS:
326cdf0e10cSrcweir             switch( mrModel.mnDirection )
327cdf0e10cSrcweir             {
328cdf0e10cSrcweir                 case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-negative" ); break;
329cdf0e10cSrcweir                 case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-negative" ); break;
330cdf0e10cSrcweir             }
331cdf0e10cSrcweir         break;
332cdf0e10cSrcweir     }
333cdf0e10cSrcweir     OSL_ENSURE( aRole.getLength() > 0, "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" );
334cdf0e10cSrcweir     return lclCreateLabeledDataSequence( *this, mrModel.maSources.get( eSourceType ).get(), aRole );
335cdf0e10cSrcweir }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir // ============================================================================
338cdf0e10cSrcweir 
TrendlineLabelConverter(const ConverterRoot & rParent,TrendlineLabelModel & rModel)339cdf0e10cSrcweir TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) :
340cdf0e10cSrcweir     ConverterBase< TrendlineLabelModel >( rParent, rModel )
341cdf0e10cSrcweir {
342cdf0e10cSrcweir }
343cdf0e10cSrcweir 
~TrendlineLabelConverter()344cdf0e10cSrcweir TrendlineLabelConverter::~TrendlineLabelConverter()
345cdf0e10cSrcweir {
346cdf0e10cSrcweir }
347cdf0e10cSrcweir 
convertFromModel(PropertySet & rPropSet)348cdf0e10cSrcweir void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet )
349cdf0e10cSrcweir {
350cdf0e10cSrcweir     // formatting
351cdf0e10cSrcweir     getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL );
352cdf0e10cSrcweir }
353cdf0e10cSrcweir 
354cdf0e10cSrcweir // ============================================================================
355cdf0e10cSrcweir 
TrendlineConverter(const ConverterRoot & rParent,TrendlineModel & rModel)356cdf0e10cSrcweir TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) :
357cdf0e10cSrcweir     ConverterBase< TrendlineModel >( rParent, rModel )
358cdf0e10cSrcweir {
359cdf0e10cSrcweir }
360cdf0e10cSrcweir 
~TrendlineConverter()361cdf0e10cSrcweir TrendlineConverter::~TrendlineConverter()
362cdf0e10cSrcweir {
363cdf0e10cSrcweir }
364cdf0e10cSrcweir 
convertFromModel(const Reference<XDataSeries> & rxDataSeries)365cdf0e10cSrcweir void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
366cdf0e10cSrcweir {
367cdf0e10cSrcweir     try
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         // trend line type
370cdf0e10cSrcweir         OUString aServiceName;
371cdf0e10cSrcweir         switch( mrModel.mnTypeId )
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             case XML_exp:       aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.ExponentialRegressionCurve" ); break;
374cdf0e10cSrcweir             case XML_linear:    aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LinearRegressionCurve" );      break;
375cdf0e10cSrcweir             case XML_log:       aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LogarithmicRegressionCurve" ); break;
376cdf0e10cSrcweir             case XML_movingAvg: /* #i66819# moving average trendlines not supported */                              break;
377cdf0e10cSrcweir             case XML_poly:      /* #i20819# polynomial trendlines not supported */                                  break;
378cdf0e10cSrcweir             case XML_power:     aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.PotentialRegressionCurve" );   break;
379cdf0e10cSrcweir             default:            OSL_ENSURE( false, "TrendlineConverter::convertFromModel - unknown trendline type" );
380cdf0e10cSrcweir         }
381cdf0e10cSrcweir         if( aServiceName.getLength() > 0 )
382cdf0e10cSrcweir         {
383cdf0e10cSrcweir             Reference< XRegressionCurve > xRegCurve( createInstance( aServiceName ), UNO_QUERY_THROW );
384cdf0e10cSrcweir             PropertySet aPropSet( xRegCurve );
385cdf0e10cSrcweir 
386cdf0e10cSrcweir             // trendline formatting
387cdf0e10cSrcweir             getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_TRENDLINE );
388cdf0e10cSrcweir 
389cdf0e10cSrcweir             // #i83100# show equation and correlation coefficient
390cdf0e10cSrcweir             PropertySet aLabelProp( xRegCurve->getEquationProperties() );
391cdf0e10cSrcweir             aLabelProp.setProperty( PROP_ShowEquation, mrModel.mbDispEquation );
392cdf0e10cSrcweir             aLabelProp.setProperty( PROP_ShowCorrelationCoefficient, mrModel.mbDispRSquared );
393cdf0e10cSrcweir 
394cdf0e10cSrcweir             // #i83100# formatting of the equation text box
395cdf0e10cSrcweir             if( mrModel.mbDispEquation || mrModel.mbDispRSquared )
396cdf0e10cSrcweir             {
397cdf0e10cSrcweir                 TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() );
398cdf0e10cSrcweir                 aLabelConv.convertFromModel( aLabelProp );
399cdf0e10cSrcweir             }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir             // unsupported: #i5085# manual trendline size
402cdf0e10cSrcweir             // unsupported: #i34093# manual crossing point
403cdf0e10cSrcweir 
404cdf0e10cSrcweir             Reference< XRegressionCurveContainer > xRegCurveCont( rxDataSeries, UNO_QUERY_THROW );
405cdf0e10cSrcweir             xRegCurveCont->addRegressionCurve( xRegCurve );
406cdf0e10cSrcweir         }
407cdf0e10cSrcweir     }
408cdf0e10cSrcweir     catch( Exception& )
409cdf0e10cSrcweir     {
410cdf0e10cSrcweir         OSL_ENSURE( false, "TrendlineConverter::convertFromModel - error while creating trendline" );
411cdf0e10cSrcweir     }
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir // ============================================================================
415cdf0e10cSrcweir 
DataPointConverter(const ConverterRoot & rParent,DataPointModel & rModel)416cdf0e10cSrcweir DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) :
417cdf0e10cSrcweir     ConverterBase< DataPointModel >( rParent, rModel )
418cdf0e10cSrcweir {
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
~DataPointConverter()421cdf0e10cSrcweir DataPointConverter::~DataPointConverter()
422cdf0e10cSrcweir {
423cdf0e10cSrcweir }
424cdf0e10cSrcweir 
convertFromModel(const Reference<XDataSeries> & rxDataSeries,const TypeGroupConverter & rTypeGroup,const SeriesModel & rSeries)425cdf0e10cSrcweir void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries,
426cdf0e10cSrcweir         const TypeGroupConverter& rTypeGroup, const SeriesModel& rSeries )
427cdf0e10cSrcweir {
428cdf0e10cSrcweir     try
429cdf0e10cSrcweir     {
430cdf0e10cSrcweir         PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
431cdf0e10cSrcweir 
432cdf0e10cSrcweir         // data point marker
433cdf0e10cSrcweir         if( mrModel.monMarkerSymbol.differsFrom( rSeries.mnMarkerSymbol ) || mrModel.monMarkerSize.differsFrom( rSeries.mnMarkerSize ) )
434cdf0e10cSrcweir             rTypeGroup.convertMarker( aPropSet, mrModel.monMarkerSymbol.get( rSeries.mnMarkerSymbol ), mrModel.monMarkerSize.get( rSeries.mnMarkerSize ) );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         // data point pie explosion
437cdf0e10cSrcweir         if( mrModel.monExplosion.differsFrom( rSeries.mnExplosion ) )
438cdf0e10cSrcweir             rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.get() );
439cdf0e10cSrcweir 
440cdf0e10cSrcweir         // point formatting
441cdf0e10cSrcweir         if( mrModel.mxShapeProp.is() )
442cdf0e10cSrcweir         {
443cdf0e10cSrcweir             if( rTypeGroup.getTypeInfo().mbPictureOptions )
444cdf0e10cSrcweir                 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
445cdf0e10cSrcweir             else
446cdf0e10cSrcweir                 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
447cdf0e10cSrcweir         }
448cdf0e10cSrcweir     }
449cdf0e10cSrcweir     catch( Exception& )
450cdf0e10cSrcweir     {
451cdf0e10cSrcweir     }
452cdf0e10cSrcweir }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir // ============================================================================
455cdf0e10cSrcweir 
SeriesConverter(const ConverterRoot & rParent,SeriesModel & rModel)456cdf0e10cSrcweir SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) :
457cdf0e10cSrcweir     ConverterBase< SeriesModel >( rParent, rModel )
458cdf0e10cSrcweir {
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
~SeriesConverter()461cdf0e10cSrcweir SeriesConverter::~SeriesConverter()
462cdf0e10cSrcweir {
463cdf0e10cSrcweir }
464cdf0e10cSrcweir 
createCategorySequence(const OUString & rRole)465cdf0e10cSrcweir Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole )
466cdf0e10cSrcweir {
467cdf0e10cSrcweir     return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false );
468cdf0e10cSrcweir }
469cdf0e10cSrcweir 
createValueSequence(const OUString & rRole)470cdf0e10cSrcweir Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole )
471cdf0e10cSrcweir {
472cdf0e10cSrcweir     return createLabeledDataSequence( SeriesModel::VALUES, rRole, true );
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
createDataSeries(const TypeGroupConverter & rTypeGroup,bool bVaryColorsByPoint)475cdf0e10cSrcweir Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint )
476cdf0e10cSrcweir {
477cdf0e10cSrcweir     const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
478cdf0e10cSrcweir 
479cdf0e10cSrcweir     // create the data series object
480cdf0e10cSrcweir     Reference< XDataSeries > xDataSeries( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.DataSeries" ) ), UNO_QUERY );
481cdf0e10cSrcweir     PropertySet aSeriesProp( xDataSeries );
482cdf0e10cSrcweir 
483cdf0e10cSrcweir     // attach data and title sequences to series
484cdf0e10cSrcweir     sal_Int32 nDataPointCount = 0;
485cdf0e10cSrcweir     Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
486cdf0e10cSrcweir     if( xDataSink.is() )
487cdf0e10cSrcweir     {
488cdf0e10cSrcweir         // create vector of all value sequences
489cdf0e10cSrcweir         ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
490cdf0e10cSrcweir         // add Y values
491cdf0e10cSrcweir         Reference< XLabeledDataSequence > xYValueSeq = createValueSequence( CREATE_OUSTRING( "values-y" ) );
492cdf0e10cSrcweir         if( xYValueSeq.is() )
493cdf0e10cSrcweir         {
494cdf0e10cSrcweir             aLabeledSeqVec.push_back( xYValueSeq );
495cdf0e10cSrcweir             Reference< XDataSequence > xValues = xYValueSeq->getValues();
496cdf0e10cSrcweir             if( xValues.is() )
497cdf0e10cSrcweir                 nDataPointCount = xValues->getData().getLength();
498cdf0e10cSrcweir         }
499cdf0e10cSrcweir         // add X values of scatter and bubble charts
500cdf0e10cSrcweir         if( !rTypeInfo.mbCategoryAxis )
501cdf0e10cSrcweir         {
502cdf0e10cSrcweir             Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( CREATE_OUSTRING( "values-x" ) );
503cdf0e10cSrcweir             if( xXValueSeq.is() )
504cdf0e10cSrcweir                 aLabeledSeqVec.push_back( xXValueSeq );
505cdf0e10cSrcweir             // add size values of bubble charts
506cdf0e10cSrcweir             if( rTypeInfo.meTypeId == TYPEID_BUBBLE )
507cdf0e10cSrcweir             {
508cdf0e10cSrcweir                 Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, CREATE_OUSTRING( "values-size" ), true );
509cdf0e10cSrcweir                 if( xSizeValueSeq.is() )
510cdf0e10cSrcweir                     aLabeledSeqVec.push_back( xSizeValueSeq );
511cdf0e10cSrcweir             }
512cdf0e10cSrcweir         }
513cdf0e10cSrcweir         // attach labeled data sequences to series
514cdf0e10cSrcweir         if( !aLabeledSeqVec.empty() )
515cdf0e10cSrcweir             xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
516cdf0e10cSrcweir     }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     // error bars
519cdf0e10cSrcweir     for( SeriesModel::ErrorBarVector::iterator aIt = mrModel.maErrorBars.begin(), aEnd = mrModel.maErrorBars.end(); aIt != aEnd; ++aIt )
520cdf0e10cSrcweir     {
521cdf0e10cSrcweir         ErrorBarConverter aErrorBarConv( *this, **aIt );
522cdf0e10cSrcweir         aErrorBarConv.convertFromModel( xDataSeries );
523cdf0e10cSrcweir     }
524cdf0e10cSrcweir 
525cdf0e10cSrcweir     // trendlines
526cdf0e10cSrcweir     for( SeriesModel::TrendlineVector::iterator aIt = mrModel.maTrendlines.begin(), aEnd = mrModel.maTrendlines.end(); aIt != aEnd; ++aIt )
527cdf0e10cSrcweir     {
528cdf0e10cSrcweir         TrendlineConverter aTrendlineConv( *this, **aIt );
529cdf0e10cSrcweir         aTrendlineConv.convertFromModel( xDataSeries );
530cdf0e10cSrcweir     }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir     // data point markers
533cdf0e10cSrcweir     rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize );
534cdf0e10cSrcweir #if OOX_CHART_SMOOTHED_PER_SERIES
535cdf0e10cSrcweir     // #i66858# smoothed series lines
536cdf0e10cSrcweir     rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth );
537cdf0e10cSrcweir #endif
538cdf0e10cSrcweir     // 3D bar style (not possible to set at chart type -> set at all series)
539cdf0e10cSrcweir     rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.get( rTypeGroup.getModel().mnShape ) );
540cdf0e10cSrcweir     // pie explosion (restricted to [0%,100%] in Chart2)
541cdf0e10cSrcweir     rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion );
542cdf0e10cSrcweir 
543cdf0e10cSrcweir     // series formatting
544cdf0e10cSrcweir     ObjectFormatter& rFormatter = getFormatter();
545cdf0e10cSrcweir     ObjectType eObjType = rTypeGroup.getSeriesObjectType();
546cdf0e10cSrcweir     if( rTypeInfo.mbPictureOptions )
547cdf0e10cSrcweir         rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex );
548cdf0e10cSrcweir     else
549cdf0e10cSrcweir         rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex );
550cdf0e10cSrcweir 
551cdf0e10cSrcweir     // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts)
552cdf0e10cSrcweir     bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE;
553cdf0e10cSrcweir     aSeriesProp.setProperty( PROP_VaryColorsByPoint, bIsPie );
554cdf0e10cSrcweir 
555cdf0e10cSrcweir     // own area formatting for every data point (TODO: varying line color not supported)
556cdf0e10cSrcweir     // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting
557cdf0e10cSrcweir     if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) )
558cdf0e10cSrcweir     {
559cdf0e10cSrcweir         /*  Set the series point number as color cycle size at the object
560cdf0e10cSrcweir             formatter to get correct start-shade/end-tint. TODO: in doughnut
561cdf0e10cSrcweir             charts, the sizes of the series may vary, need to use the maximum
562cdf0e10cSrcweir             point count of all series. */
563cdf0e10cSrcweir         sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex();
564cdf0e10cSrcweir         if( bVaryColorsByPoint )
565cdf0e10cSrcweir             rFormatter.setMaxSeriesIndex( nDataPointCount - 1 );
566cdf0e10cSrcweir         for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex )
567cdf0e10cSrcweir         {
568cdf0e10cSrcweir             try
569cdf0e10cSrcweir             {
570cdf0e10cSrcweir                 PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) );
571cdf0e10cSrcweir                 rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex );
572cdf0e10cSrcweir             }
573cdf0e10cSrcweir             catch( Exception& )
574cdf0e10cSrcweir             {
575cdf0e10cSrcweir             }
576cdf0e10cSrcweir         }
577cdf0e10cSrcweir         rFormatter.setMaxSeriesIndex( nOldMax );
578cdf0e10cSrcweir     }
579cdf0e10cSrcweir 
580cdf0e10cSrcweir     // data point settings
581cdf0e10cSrcweir     for( SeriesModel::DataPointVector::iterator aIt = mrModel.maPoints.begin(), aEnd = mrModel.maPoints.end(); aIt != aEnd; ++aIt )
582cdf0e10cSrcweir     {
583cdf0e10cSrcweir         DataPointConverter aPointConv( *this, **aIt );
584cdf0e10cSrcweir         aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel );
585cdf0e10cSrcweir     }
586cdf0e10cSrcweir 
587cdf0e10cSrcweir     /*  Series data label settings. If and only if the series does not contain
588cdf0e10cSrcweir         a c:dLbls element, then the c:dLbls element of the parent chart type is
589cdf0e10cSrcweir         used (data label settings of the parent chart type are *not* merged
590cdf0e10cSrcweir         into own existing data label settings). */
591cdf0e10cSrcweir     ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels;
592cdf0e10cSrcweir     if( xLabels.is() )
593cdf0e10cSrcweir     {
594cdf0e10cSrcweir         DataLabelsConverter aLabelsConv( *this, *xLabels );
595cdf0e10cSrcweir         aLabelsConv.convertFromModel( xDataSeries, rTypeGroup );
596cdf0e10cSrcweir     }
597cdf0e10cSrcweir 
598cdf0e10cSrcweir     return xDataSeries;
599cdf0e10cSrcweir }
600cdf0e10cSrcweir 
601cdf0e10cSrcweir // private --------------------------------------------------------------------
602cdf0e10cSrcweir 
createLabeledDataSequence(SeriesModel::SourceType eSourceType,const OUString & rRole,bool bUseTextLabel)603cdf0e10cSrcweir Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence(
604cdf0e10cSrcweir         SeriesModel::SourceType eSourceType, const OUString& rRole, bool bUseTextLabel )
605cdf0e10cSrcweir {
606cdf0e10cSrcweir     DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get();
607cdf0e10cSrcweir     TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : 0;
608cdf0e10cSrcweir     return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle );
609cdf0e10cSrcweir }
610cdf0e10cSrcweir 
611cdf0e10cSrcweir // ============================================================================
612cdf0e10cSrcweir 
613cdf0e10cSrcweir } // namespace chart
614cdf0e10cSrcweir } // namespace drawingml
615cdf0e10cSrcweir } // namespace oox
616