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