1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef _CHART2_VSERIESPLOTTER_HXX
28 #define _CHART2_VSERIESPLOTTER_HXX
29 
30 #include "PlotterBase.hxx"
31 #include "VDataSeries.hxx"
32 #include "LabelAlignment.hxx"
33 #include "MinimumAndMaximumSupplier.hxx"
34 #include "LegendEntryProvider.hxx"
35 #include "ExplicitCategoriesProvider.hxx"
36 #include <com/sun/star/chart2/XChartType.hpp>
37 #include <com/sun/star/drawing/Direction3D.hpp>
38 
39 
40 namespace com { namespace sun { namespace star {
41     namespace util {
42         class XNumberFormatsSupplier;
43     }
44     namespace chart2 {
45         class XColorScheme;
46         class XRegressionCurveCalculator;
47     }
48 }}}
49 
50 //.............................................................................
51 namespace chart
52 {
53 //.............................................................................
54 
55 class NumberFormatterWrapper;
56 
57 class AxesNumberFormats
58 {
59 public:
60     AxesNumberFormats() {};
61 
62     void setFormat( sal_Int32 nFormatKey, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
63     {
64         m_aNumberFormatMap[tFullAxisIndex(nDimIndex,nAxisIndex)] = nFormatKey;
65     }
66     sal_Int32 hasFormat( sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) const
67     {
68         return (m_aNumberFormatMap.find(tFullAxisIndex(nDimIndex,nAxisIndex)) !=m_aNumberFormatMap.end());
69     }
70     sal_Int32 getFormat( sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) const
71     {
72         tNumberFormatMap::const_iterator aIt = m_aNumberFormatMap.find(tFullAxisIndex(nDimIndex,nAxisIndex));
73         if( aIt !=m_aNumberFormatMap.end() )
74             return aIt->second;
75         return 0;
76     }
77 
78 private:
79     typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex;
80     typedef std::map< tFullAxisIndex, sal_Int32 > tNumberFormatMap;
81     tNumberFormatMap m_aNumberFormatMap;
82 };
83 
84 //-----------------------------------------------------------------------------
85 /**
86 */
87 
88 //enum StackType { STACK_NORMAL, STACK_NONE, STACK_BESIDES, STACK_ONTOP, STACK_BEHIND };
89 
90 class VDataSeriesGroup
91 {
92     //a list of series that have the same CoordinateSystem
93     //they are used to be plotted maybe in a stacked manner by a plotter
94 
95 public:
96     VDataSeriesGroup();
97     VDataSeriesGroup( VDataSeries* pSeries );
98     virtual ~VDataSeriesGroup();
99 
100     void addSeries( VDataSeries* pSeries );//takes ownership of pSeries
101     sal_Int32 getSeriesCount() const;
102     void deleteSeries();
103 
104     sal_Int32    getPointCount() const;
105     sal_Int32    getAttachedAxisIndexForFirstSeries() const;
106 
107     void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const;
108     void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
109 
110     void calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
111                                             , bool bSeperateStackingForDifferentSigns
112                                             , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex );
113     void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
114                                                 , bool bSeperateStackingForDifferentSigns
115                                                 , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex );
116 
117     ::std::vector< VDataSeries* >   m_aSeriesVector;
118 
119 private:
120     //cached values
121     struct CachedYValues
122     {
123         CachedYValues();
124 
125         bool    m_bValuesDirty;
126         double  m_fMinimumY;
127         double  m_fMaximumY;
128     };
129 
130     mutable bool        m_bMaxPointCountDirty;
131     mutable sal_Int32   m_nMaxPointCount;
132     typedef std::map< sal_Int32, CachedYValues > tCachedYValuesPerAxisIndexMap;
133     mutable ::std::vector< tCachedYValuesPerAxisIndexMap >   m_aListOfCachedYValues;
134 };
135 
136 class VSeriesPlotter : public PlotterBase, public MinimumAndMaximumSupplier, public LegendEntryProvider
137 {
138 	//-------------------------------------------------------------------------
139 	// public methods
140 	//-------------------------------------------------------------------------
141 public:
142 	virtual ~VSeriesPlotter();
143 
144     /*
145     * A new series can be positioned relative to other series in a chart.
146     * This positioning has two dimensions. First a series can be placed
147     * next to each other on the category axis. This position is indicated by xSlot.
148     * Second a series can be stacked on top of another. This position is indicated by ySlot.
149     * The positions are counted from 0 on.
150     * xSlot < 0                     : append the series to already existing x series
151     * xSlot > occupied              : append the series to already existing x series
152     *
153     * If the xSlot is already occupied the given ySlot decides what should happen:
154     * ySlot < -1                    : move all existing series in the xSlot to next slot
155     * ySlot == -1                   : stack on top at given x position
156     * ySlot == already occupied     : insert at given y and x position
157     * ySlot > occupied              : stack on top at given x position
158     */
159     virtual void addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 );
160 
161     /** a value <= 0 for a directions means that this direction can be stretched arbitrary
162     */
163     virtual ::com::sun::star::drawing::Direction3D  getPreferredDiagramAspectRatio() const;
164     virtual bool keepAspectRatio() const;
165 
166     /** this enables you to handle series on the same x axis with different y axis
167     the property AttachedAxisIndex at a dataseries indicates which value scale is to use
168     (0==AttachedAxisIndex or a not set AttachedAxisIndex property indicates that this series should be scaled at the main y-axis;
169     1==AttachedAxisIndex indicates that the series should be scaled at the first secondary axis if there is any otherwise at the main y axis
170     and so on.
171     The parameter nAxisIndex matches this DataSereis property 'AttachedAxisIndex'.
172     nAxisIndex must be greater than 0. nAxisIndex==1 referres to the first secondary axis.
173     )
174     */
175 
176     virtual void addSecondaryValueScale( const ExplicitScaleData& rScale, sal_Int32 nAxisIndex )
177                 throw (::com::sun::star::uno::RuntimeException);
178 
179     //-------------------------------------------------------------------------
180 	// MinimumAndMaximumSupplier
181 	//-------------------------------------------------------------------------
182 
183     virtual double getMinimumX();
184     virtual double getMaximumX();
185 
186     virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
187     virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex );
188 
189     virtual double getMinimumZ();
190     virtual double getMaximumZ();
191 
192     virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex );
193     virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex );
194     virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex );
195     virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex );
196     virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex );
197 
198     virtual long calculateTimeResolutionOnXAxis();
199     virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate );
200 
201     //------
202 
203     void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const;
204     void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
205 
206     //-------------------------------------------------------------------------
207     //-------------------------------------------------------------------------
208 
209     virtual std::vector< ViewLegendEntry > createLegendEntries(
210             const ::com::sun::star::awt::Size& rEntryKeyAspectRatio,
211             ::com::sun::star::chart::ChartLegendExpansion eLegendExpansion,
212             const ::com::sun::star::uno::Reference<
213                 ::com::sun::star::beans::XPropertySet >& xTextProperties,
214             const ::com::sun::star::uno::Reference<
215                 ::com::sun::star::drawing::XShapes >& xTarget,
216             const ::com::sun::star::uno::Reference<
217                 ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
218             const ::com::sun::star::uno::Reference<
219                 ::com::sun::star::uno::XComponentContext >& xContext
220                 );
221 
222 
223     virtual LegendSymbolStyle getLegendSymbolStyle();
224     virtual com::sun::star::awt::Size getPreferredLegendKeyAspectRatio();
225 
226     virtual ::com::sun::star::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex=-1/*-1 for series symbol*/ );
227 
228     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createLegendSymbolForSeries(
229                   const ::com::sun::star::awt::Size& rEntryKeyAspectRatio
230                 , const VDataSeries& rSeries
231                 , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
232                 , const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory );
233 
234     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createLegendSymbolForPoint(
235                   const ::com::sun::star::awt::Size& rEntryKeyAspectRatio
236                 , const VDataSeries& rSeries
237                 , sal_Int32 nPointIndex
238                 , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
239                 , const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory );
240 
241     virtual std::vector< ViewLegendEntry > createLegendEntriesForSeries(
242             const ::com::sun::star::awt::Size& rEntryKeyAspectRatio,
243             const VDataSeries& rSeries,
244             const ::com::sun::star::uno::Reference<
245                 ::com::sun::star::beans::XPropertySet >& xTextProperties,
246             const ::com::sun::star::uno::Reference<
247                 ::com::sun::star::drawing::XShapes >& xTarget,
248             const ::com::sun::star::uno::Reference<
249                 ::com::sun::star::lang::XMultiServiceFactory >& xShapeFactory,
250             const ::com::sun::star::uno::Reference<
251                 ::com::sun::star::uno::XComponentContext >& xContext
252                 );
253 
254     ::std::vector< VDataSeries* > getAllSeries();
255 
256     //-------------------------------------------------------------------------
257     //-------------------------------------------------------------------------
258 
259     static VSeriesPlotter* createSeriesPlotter( const ::com::sun::star::uno::Reference<
260                                 ::com::sun::star::chart2::XChartType >& xChartTypeModel
261                                 , sal_Int32 nDimensionCount
262                                 , bool bExcludingPositioning = false /*for pie and donut charts labels and exploded segments are excluded from the given size*/);
263 
264     sal_Int32 getPointCount() const;
265 
266     void setNumberFormatsSupplier( const ::com::sun::star::uno::Reference<
267                         ::com::sun::star::util::XNumberFormatsSupplier > & xNumFmtSupplier );
268     void setAxesNumberFormats( const AxesNumberFormats& rAxesNumberFormats ) { m_aAxesNumberFormats = rAxesNumberFormats; };
269 
270     void setColorScheme( const ::com::sun::star::uno::Reference<
271                         ::com::sun::star::chart2::XColorScheme >& xColorScheme );
272 
273     void setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider );
274 
275     //get series names for the z axis labels
276     ::com::sun::star::uno::Sequence< rtl::OUString > getSeriesNames() const;
277 
278     void setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize );
279     //better performance for big data
280     void setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution );
281     bool PointsWereSkipped() const;
282 
283     //return the depth for a logic 1
284     double  getTransformedDepth() const;
285 
286     void    releaseShapes();
287 
288     virtual void rearrangeLabelToAvoidOverlapIfRequested( const ::com::sun::star::awt::Size& rPageSize );
289 
290     bool WantToPlotInFrontOfAxisLine();
291     virtual bool shouldSnapRectToUsedArea();
292 
293     //-------------------------------------------------------------------------
294     //-------------------------------------------------------------------------
295     //-------------------------------------------------------------------------
296 private: //methods
297 	//no default constructor
298 	VSeriesPlotter();
299 
300 protected: //methods
301 
302     VSeriesPlotter( const ::com::sun::star::uno::Reference<
303                 ::com::sun::star::chart2::XChartType >& xChartTypeModel
304                 , sal_Int32 nDimensionCount
305                 , bool bCategoryXAxis=true );
306 
307     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
308         getSeriesGroupShape( VDataSeries* pDataSeries
309             , const::com::sun::star:: uno::Reference<
310                 ::com::sun::star::drawing::XShapes >& xTarget );
311 
312     //the following group shapes will be created as children of SeriesGroupShape on demand
313     //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines)
314     //parameter xTarget will be used as parent for the series group shape
315     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
316         getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
317             , const::com::sun::star:: uno::Reference<
318                 ::com::sun::star::drawing::XShapes >& xTarget );
319     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
320         getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
321             , const::com::sun::star:: uno::Reference<
322                 ::com::sun::star::drawing::XShapes >& xTarget );
323 
324     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
325         getLabelsGroupShape( VDataSeries& rDataSeries
326             , const::com::sun::star:: uno::Reference<
327                 ::com::sun::star::drawing::XShapes >& xTarget );
328 
329     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >
330         getErrorBarsGroupShape( VDataSeries& rDataSeries
331             , const::com::sun::star:: uno::Reference<
332                 ::com::sun::star::drawing::XShapes >& xTarget );
333 
334     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
335         createDataLabel( const ::com::sun::star::uno::Reference<
336                     ::com::sun::star::drawing::XShapes >& xTarget
337                 , VDataSeries& rDataSeries
338                 , sal_Int32 nPointIndex
339                 , double fValue
340                 , double fSumValue
341                 , const ::com::sun::star::awt::Point& rScreenPosition2D
342                 , LabelAlignment eAlignment=LABEL_ALIGN_CENTER
343                 , sal_Int32 nOffset=0 );
344 
345     ::rtl::OUString getLabelTextForValue( VDataSeries& rDataSeries
346                 , sal_Int32 nPointIndex
347                 , double fValue
348                 , bool bAsPercentage );
349 
350     /** creates two T-shaped error bars in both directions (up/down or
351         left/right depending on the bVertical parameter)
352 
353         @param rPos
354             logic coordinates
355 
356         @param xErrorBarProperties
357             the XPropertySet returned by the DataPoint-property "ErrorBarX" or
358             "ErrorBarY".
359 
360         @param nIndex
361             the index of the data point in rData for which the calculation is
362             done.
363 
364         @param bVertical
365             for y-error bars this is true, for x-error-bars it is false.
366      */
367     virtual void createErrorBar(
368           const ::com::sun::star::uno::Reference<
369                 ::com::sun::star::drawing::XShapes >& xTarget
370         , const ::com::sun::star::drawing::Position3D & rPos
371         , const ::com::sun::star::uno::Reference<
372                 ::com::sun::star::beans::XPropertySet > & xErrorBarProperties
373         , const VDataSeries& rVDataSeries
374         , sal_Int32 nIndex
375         , bool bVertical
376         , double* pfScaledLogicX
377         );
378 
379     virtual void createErrorBar_Y( const ::com::sun::star::drawing::Position3D& rUnscaledLogicPosition
380         , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
381         , const ::com::sun::star::uno::Reference<
382                 ::com::sun::star::drawing::XShapes >& xTarget
383         , double* pfScaledLogicX=0 );
384 
385     virtual void createRegressionCurvesShapes( VDataSeries& rVDataSeries
386         , const ::com::sun::star::uno::Reference<
387                 ::com::sun::star::drawing::XShapes >& xTarget
388         , const ::com::sun::star::uno::Reference<
389                 ::com::sun::star::drawing::XShapes >& xEquationTarget
390         , bool bMaySkipPointsInRegressionCalculation );
391 
392     virtual void createRegressionCurveEquationShapes( const ::rtl::OUString & rEquationCID
393         , const ::com::sun::star::uno::Reference<
394             ::com::sun::star::beans::XPropertySet > & xEquationProperties
395         , const ::com::sun::star::uno::Reference<
396             ::com::sun::star::drawing::XShapes >& xEquationTarget
397         , const ::com::sun::star::uno::Reference<
398             ::com::sun::star::chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator
399         , ::com::sun::star::awt::Point aDefaultPos );
400 
401     virtual void setMappedProperties(
402           const ::com::sun::star::uno::Reference<
403                 ::com::sun::star::drawing::XShape >& xTarget
404         , const ::com::sun::star::uno::Reference<
405                 ::com::sun::star::beans::XPropertySet >& xSource
406         , const tPropertyNameMap& rMap
407         , tPropertyNameValueMap* pOverwriteMap=0 );
408 
409     virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const;//nAxisIndex indicates wether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 )
410 
411     VDataSeries* getFirstSeries() const;
412 
413 protected: //member
414     PlottingPositionHelper*    m_pMainPosHelper;
415 
416     ::com::sun::star::uno::Reference<
417             ::com::sun::star::chart2::XChartType >    m_xChartTypeModel;
418     ::com::sun::star::uno::Reference<
419             ::com::sun::star::beans::XPropertySet >           m_xChartTypeModelProps;
420 
421     ::std::vector< ::std::vector< VDataSeriesGroup > >  m_aZSlots;
422 
423     bool								m_bCategoryXAxis;//true->xvalues are indices (this would not be necessary if series for category chart wouldn't have x-values)
424     long m_nTimeResolution;
425     Date m_aNullDate;
426 
427     ::std::auto_ptr< NumberFormatterWrapper > m_apNumberFormatterWrapper;
428     AxesNumberFormats                         m_aAxesNumberFormats;//direct numberformats on axes, if empty ask the data series instead
429 
430     ::com::sun::star::uno::Reference<
431             ::com::sun::star::chart2::XColorScheme >    m_xColorScheme;
432 
433     ExplicitCategoriesProvider*    m_pExplicitCategoriesProvider;
434 
435     //better performance for big data
436     ::com::sun::star::uno::Sequence< sal_Int32 >    m_aCoordinateSystemResolution;
437     bool m_bPointsWereSkipped;
438 
439 private: //member
440     typedef std::map< sal_Int32 , ExplicitScaleData > tSecondaryValueScales;
441     tSecondaryValueScales   m_aSecondaryValueScales;
442 
443     typedef std::map< sal_Int32 , PlottingPositionHelper* > tSecondaryPosHelperMap;
444     mutable tSecondaryPosHelperMap   m_aSecondaryPosHelperMap;
445     ::com::sun::star::awt::Size      m_aPageReferenceSize;
446 };
447 
448 //.............................................................................
449 } //namespace chart
450 //.............................................................................
451 #endif
452