1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "ColumnLineChartTypeTemplate.hxx"
27 #include "macros.hxx"
28 #include "CommonConverters.hxx"
29 #include "DiagramHelper.hxx"
30 #include "DataSeriesHelper.hxx"
31 #include "servicenames_charttypes.hxx"
32 #include "ColumnLineDataInterpreter.hxx"
33 #include "ContainerHelper.hxx"
34 #include "PropertyHelper.hxx"
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
37 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
38 #include <com/sun/star/drawing/LineStyle.hpp>
39 
40 #include <algorithm>
41 
42 using namespace ::com::sun::star::chart2;
43 using namespace ::com::sun::star;
44 
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::Sequence;
47 using ::rtl::OUString;
48 using ::com::sun::star::beans::Property;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::Any;
51 using ::osl::MutexGuard;
52 
53 namespace
54 {
55 
56 static const ::rtl::OUString lcl_aServiceName(
57     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.ColumnLineChartTypeTemplate" ));
58 
59 enum
60 {
61     PROP_COL_LINE_NUMBER_OF_LINES
62 };
63 
lcl_AddPropertiesToVector(::std::vector<Property> & rOutProperties)64 void lcl_AddPropertiesToVector(
65     ::std::vector< Property > & rOutProperties )
66 {
67     rOutProperties.push_back(
68         Property( C2U( "NumberOfLines" ),
69                   PROP_COL_LINE_NUMBER_OF_LINES,
70                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)),
71                   beans::PropertyAttribute::BOUND
72                   | beans::PropertyAttribute::MAYBEDEFAULT ));
73 }
74 
75 struct StaticColumnLineChartTypeTemplateDefaults_Initializer
76 {
operator ()__anonea19145b0111::StaticColumnLineChartTypeTemplateDefaults_Initializer77     ::chart::tPropertyValueMap* operator()()
78     {
79         static ::chart::tPropertyValueMap aStaticDefaults;
80         lcl_AddDefaultsToMap( aStaticDefaults );
81         return &aStaticDefaults;
82     }
83 private:
lcl_AddDefaultsToMap__anonea19145b0111::StaticColumnLineChartTypeTemplateDefaults_Initializer84     void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
85     {
86         ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_COL_LINE_NUMBER_OF_LINES, 1 );
87     }
88 };
89 
90 struct StaticColumnLineChartTypeTemplateDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticColumnLineChartTypeTemplateDefaults_Initializer >
91 {
92 };
93 
94 struct StaticColumnLineChartTypeTemplateInfoHelper_Initializer
95 {
operator ()__anonea19145b0111::StaticColumnLineChartTypeTemplateInfoHelper_Initializer96     ::cppu::OPropertyArrayHelper* operator()()
97     {
98         static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() );
99         return &aPropHelper;
100     }
101 
102 private:
lcl_GetPropertySequence__anonea19145b0111::StaticColumnLineChartTypeTemplateInfoHelper_Initializer103     uno::Sequence< Property > lcl_GetPropertySequence()
104     {
105         ::std::vector< ::com::sun::star::beans::Property > aProperties;
106         lcl_AddPropertiesToVector( aProperties );
107 
108         ::std::sort( aProperties.begin(), aProperties.end(),
109                      ::chart::PropertyNameLess() );
110 
111         return ::chart::ContainerHelper::ContainerToSequence( aProperties );
112     }
113 
114 };
115 
116 struct StaticColumnLineChartTypeTemplateInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticColumnLineChartTypeTemplateInfoHelper_Initializer >
117 {
118 };
119 
120 struct StaticColumnLineChartTypeTemplateInfo_Initializer
121 {
operator ()__anonea19145b0111::StaticColumnLineChartTypeTemplateInfo_Initializer122     uno::Reference< beans::XPropertySetInfo >* operator()()
123     {
124         static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
125             ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticColumnLineChartTypeTemplateInfoHelper::get() ) );
126         return &xPropertySetInfo;
127     }
128 };
129 
130 struct StaticColumnLineChartTypeTemplateInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticColumnLineChartTypeTemplateInfo_Initializer >
131 {
132 };
133 
134 } // anonymous namespace
135 
136 namespace chart
137 {
138 
ColumnLineChartTypeTemplate(Reference<uno::XComponentContext> const & xContext,const::rtl::OUString & rServiceName,StackMode eStackMode,sal_Int32 nNumberOfLines)139 ColumnLineChartTypeTemplate::ColumnLineChartTypeTemplate(
140     Reference<
141         uno::XComponentContext > const & xContext,
142     const ::rtl::OUString & rServiceName,
143     StackMode eStackMode,
144     sal_Int32 nNumberOfLines ) :
145         ChartTypeTemplate( xContext, rServiceName ),
146         ::property::OPropertySet( m_aMutex ),
147         m_eStackMode( eStackMode )
148 {
149     setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::makeAny( nNumberOfLines ));
150 }
151 
~ColumnLineChartTypeTemplate()152 ColumnLineChartTypeTemplate::~ColumnLineChartTypeTemplate()
153 {}
154 
155 // ____ OPropertySet ____
GetDefaultValue(sal_Int32 nHandle) const156 uno::Any ColumnLineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const
157     throw(beans::UnknownPropertyException)
158 {
159     const tPropertyValueMap& rStaticDefaults = *StaticColumnLineChartTypeTemplateDefaults::get();
160     tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
161     if( aFound == rStaticDefaults.end() )
162         return uno::Any();
163     return (*aFound).second;
164 }
165 
getInfoHelper()166 ::cppu::IPropertyArrayHelper & SAL_CALL ColumnLineChartTypeTemplate::getInfoHelper()
167 {
168     return *StaticColumnLineChartTypeTemplateInfoHelper::get();
169 }
170 
171 // ____ XPropertySet ____
getPropertySetInfo()172 uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnLineChartTypeTemplate::getPropertySetInfo()
173     throw (uno::RuntimeException)
174 {
175     return *StaticColumnLineChartTypeTemplateInfo::get();
176 }
177 
createChartTypes(const Sequence<Sequence<Reference<XDataSeries>>> & aSeriesSeq,const Sequence<Reference<XCoordinateSystem>> & rCoordSys,const Sequence<Reference<XChartType>> & aOldChartTypesSeq)178 void ColumnLineChartTypeTemplate::createChartTypes(
179     const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq,
180     const Sequence< Reference< XCoordinateSystem > > & rCoordSys,
181     const Sequence< Reference< XChartType > >& aOldChartTypesSeq )
182 {
183     if( rCoordSys.getLength() == 0 ||
184         ! rCoordSys[0].is() )
185         return;
186 
187     try
188     {
189         Reference< lang::XMultiServiceFactory > xFact(
190             GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW );
191         Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
192         sal_Int32 nNumberOfSeries = aFlatSeriesSeq.getLength();
193         sal_Int32 nNumberOfLines = 0;
194         sal_Int32 nNumberOfColumns = 0;
195 
196         getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines;
197         OSL_ENSURE( nNumberOfLines>=0, "number of lines should be not negative" );
198         if( nNumberOfLines < 0 )
199             nNumberOfLines = 0;
200 
201         if( nNumberOfLines >= nNumberOfSeries )
202         {
203             if( nNumberOfSeries > 0 )
204             {
205                 nNumberOfLines = nNumberOfSeries - 1;
206                 nNumberOfColumns = 1;
207             }
208             else
209                 nNumberOfLines = 0;
210         }
211         else
212             nNumberOfColumns = nNumberOfSeries - nNumberOfLines;
213 
214         // Columns
215         // -------
216         Reference< XChartType > xCT(
217             xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY_THROW );
218 
219         ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem( aOldChartTypesSeq, xCT );
220 
221         Reference< XChartTypeContainer > xCTCnt( rCoordSys[ 0 ], uno::UNO_QUERY_THROW );
222         xCTCnt->setChartTypes( Sequence< Reference< chart2::XChartType > >( &xCT, 1 ));
223 
224         if( nNumberOfColumns > 0 )
225         {
226             Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
227             Sequence< Reference< XDataSeries > > aColumnSeq( nNumberOfColumns );
228             ::std::copy( aFlatSeriesSeq.getConstArray(),
229                          aFlatSeriesSeq.getConstArray() + nNumberOfColumns,
230                          aColumnSeq.getArray());
231             xDSCnt->setDataSeries( aColumnSeq );
232         }
233 
234         // Lines
235         // -----
236         xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW );
237         xCTCnt.set( rCoordSys[ 0 ], uno::UNO_QUERY_THROW );
238         xCTCnt->addChartType( xCT );
239 
240         if( nNumberOfLines > 0 )
241         {
242             Reference< XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
243             Sequence< Reference< XDataSeries > > aLineSeq( nNumberOfLines );
244             ::std::copy( aFlatSeriesSeq.getConstArray() + nNumberOfColumns,
245                          aFlatSeriesSeq.getConstArray() + aFlatSeriesSeq.getLength(),
246                          aLineSeq.getArray());
247             xDSCnt->setDataSeries( aLineSeq );
248         }
249     }
250     catch( uno::Exception & ex )
251     {
252         ASSERT_EXCEPTION( ex );
253     }
254 }
255 
applyStyle(const Reference<chart2::XDataSeries> & xSeries,::sal_Int32 nChartTypeIndex,::sal_Int32 nSeriesIndex,::sal_Int32 nSeriesCount)256 void SAL_CALL ColumnLineChartTypeTemplate::applyStyle(
257     const Reference< chart2::XDataSeries >& xSeries,
258     ::sal_Int32 nChartTypeIndex,
259     ::sal_Int32 nSeriesIndex,
260     ::sal_Int32 nSeriesCount )
261     throw (uno::RuntimeException)
262 {
263     ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
264 
265     if( nChartTypeIndex==0 ) // columns
266     {
267         DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "BorderStyle" ), uno::makeAny( drawing::LineStyle_NONE ) );
268     }
269     else if( nChartTypeIndex==1 ) // lines
270     {
271         Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
272         if( xProp.is() )
273         {
274             DataSeriesHelper::switchLinesOnOrOff( xProp, true );
275             DataSeriesHelper::switchSymbolsOnOrOff( xProp, false, nSeriesIndex );
276             DataSeriesHelper::makeLinesThickOrThin( xProp, true );
277         }
278     }
279 }
280 
getStackMode(sal_Int32 nChartTypeIndex) const281 StackMode ColumnLineChartTypeTemplate::getStackMode( sal_Int32 nChartTypeIndex ) const
282 {
283     if( nChartTypeIndex == 0 )
284         return m_eStackMode;
285     return StackMode_NONE;
286 }
287 
288 // ____ XChartTypeTemplate ____
matchesTemplate(const uno::Reference<XDiagram> & xDiagram,sal_Bool bAdaptProperties)289 sal_Bool SAL_CALL ColumnLineChartTypeTemplate::matchesTemplate(
290     const uno::Reference< XDiagram >& xDiagram,
291     sal_Bool bAdaptProperties )
292     throw (uno::RuntimeException)
293 {
294     sal_Bool bResult = sal_False;
295 
296     if( ! xDiagram.is())
297         return bResult;
298 
299     try
300     {
301         Reference< chart2::XChartType > xColumnChartType;
302         Reference< XCoordinateSystem > xColumnChartCooSys;
303         Reference< chart2::XChartType > xLineChartType;
304         sal_Int32 nNumberOfChartTypes = 0;
305 
306         Reference< XCoordinateSystemContainer > xCooSysCnt(
307             xDiagram, uno::UNO_QUERY_THROW );
308         Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
309             xCooSysCnt->getCoordinateSystems());
310         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
311         {
312             Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
313             Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
314             for( sal_Int32 j=0; j<aChartTypeSeq.getLength(); ++j )
315             {
316                 if( aChartTypeSeq[j].is())
317                 {
318                     ++nNumberOfChartTypes;
319                     if( nNumberOfChartTypes > 2 )
320                         break;
321                     OUString aCTService = aChartTypeSeq[j]->getChartType();
322                     if( aCTService.equals( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ))
323                     {
324                         xColumnChartType.set( aChartTypeSeq[j] );
325                         xColumnChartCooSys.set( aCooSysSeq[i] );
326                     }
327                     else if( aCTService.equals( CHART2_SERVICE_NAME_CHARTTYPE_LINE ))
328                         xLineChartType.set( aChartTypeSeq[j] );
329                 }
330             }
331             if( nNumberOfChartTypes > 2 )
332                 break;
333         }
334 
335         if( nNumberOfChartTypes == 2 &&
336             xColumnChartType.is() &&
337             xLineChartType.is())
338         {
339             OSL_ASSERT( xColumnChartCooSys.is());
340 
341             // check stackmode of bars
342             bResult = (xColumnChartCooSys->getDimension() == getDimension());
343             if( bResult )
344             {
345                 bool bFound=false;
346                 bool bAmbiguous=false;
347                 bResult = ( DiagramHelper::getStackModeFromChartType(
348                                 xColumnChartType, bFound, bAmbiguous,
349                                 xColumnChartCooSys )
350                             == getStackMode( 0 ) );
351 
352                 if( bResult && bAdaptProperties )
353                 {
354                     Reference< XDataSeriesContainer > xSeriesContainer( xLineChartType, uno::UNO_QUERY );
355                     if( xSeriesContainer.is() )
356                     {
357                         sal_Int32 nNumberOfLines = xSeriesContainer->getDataSeries().getLength();
358                         setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::makeAny( nNumberOfLines ));
359                     }
360                 }
361             }
362         }
363     }
364     catch( uno::Exception & ex )
365     {
366         ASSERT_EXCEPTION( ex );
367     }
368 
369     return bResult;
370 }
371 
getChartTypeForIndex(sal_Int32 nChartTypeIndex)372 Reference< chart2::XChartType > ColumnLineChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex )
373 {
374     Reference< chart2::XChartType > xCT;
375     Reference< lang::XMultiServiceFactory > xFact(
376             GetComponentContext()->getServiceManager(), uno::UNO_QUERY );
377     if(xFact.is())
378     {
379         if( nChartTypeIndex == 0 )
380             xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ), uno::UNO_QUERY );
381         else
382             xCT.set( xFact->createInstance( CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY );
383     }
384     return xCT;
385 }
386 
getChartTypeForNewSeries(const uno::Sequence<Reference<chart2::XChartType>> & aFormerlyUsedChartTypes)387 Reference< XChartType > SAL_CALL ColumnLineChartTypeTemplate::getChartTypeForNewSeries(
388         const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes )
389     throw (uno::RuntimeException)
390 {
391     Reference< chart2::XChartType > xResult;
392 
393     try
394     {
395         Reference< lang::XMultiServiceFactory > xFact(
396             GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW );
397         xResult.set( xFact->createInstance(
398                          CHART2_SERVICE_NAME_CHARTTYPE_LINE ), uno::UNO_QUERY_THROW );
399         ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem( aFormerlyUsedChartTypes, xResult );
400     }
401     catch( uno::Exception & ex )
402     {
403         ASSERT_EXCEPTION( ex );
404     }
405 
406     return xResult;
407 }
408 
getDataInterpreter()409 Reference< XDataInterpreter > SAL_CALL ColumnLineChartTypeTemplate::getDataInterpreter()
410     throw (uno::RuntimeException)
411 {
412     if( ! m_xDataInterpreter.is())
413     {
414         sal_Int32 nNumberOfLines = 1;
415         getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines;
416         m_xDataInterpreter.set( new ColumnLineDataInterpreter( nNumberOfLines, GetComponentContext() ) );
417     }
418     else
419     {
420         //todo...
421         OSL_ENSURE( false, "number of lines may not be valid anymore in the datainterpreter" );
422 
423     }
424 
425     return m_xDataInterpreter;
426 }
427 
428 // ----------------------------------------
429 
getSupportedServiceNames_Static()430 uno::Sequence< ::rtl::OUString > ColumnLineChartTypeTemplate::getSupportedServiceNames_Static()
431 {
432     uno::Sequence< ::rtl::OUString > aServices( 2 );
433     aServices[ 0 ] = lcl_aServiceName;
434     aServices[ 1 ] = C2U( "com.sun.star.chart2.ChartTypeTemplate" );
435     return aServices;
436 }
437 
438 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
439 APPHELPER_XSERVICEINFO_IMPL( ColumnLineChartTypeTemplate, lcl_aServiceName );
440 
441 IMPLEMENT_FORWARD_XINTERFACE2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
442 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
443 
444 } //  namespace chart
445