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 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 #include "VAxisProperties.hxx" 31 #include "macros.hxx" 32 #include "ViewDefines.hxx" 33 #include "CommonConverters.hxx" 34 #include "AxisHelper.hxx" 35 #include "DiagramHelper.hxx" 36 #include "ChartModelHelper.hxx" 37 38 #include <tools/color.hxx> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> 41 #include <com/sun/star/drawing/LineStyle.hpp> 42 #include <com/sun/star/text/WritingMode2.hpp> 43 44 //............................................................................. 45 namespace chart 46 { 47 //............................................................................. 48 using namespace ::com::sun::star; 49 using namespace ::com::sun::star::chart2; 50 51 sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle) 52 { 53 sal_Int32 nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model 54 double fPercent = 1.0; 55 switch(nDepth) 56 { 57 case 0: 58 fPercent = 1.0; 59 break; 60 case 1: 61 fPercent = 0.75;//percentage like in the old chart 62 break; 63 case 2: 64 fPercent = 0.5; 65 break; 66 default: 67 fPercent = 0.3; 68 break; 69 } 70 if(nTickmarkStyle==3)//inner and outer tickmarks 71 fPercent*=2.0; 72 return static_cast<sal_Int32>(nWidth*fPercent); 73 } 74 75 double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle) 76 { 77 double fPercent = 0.0; //0<=fPercent<=1 78 //0.0: completly inner 79 //1.0: completly outer 80 //0.5: half and half 81 82 /* 83 nTickmarkStyle: 84 1: inner tickmarks 85 2: outer tickmarks 86 3: inner and outer tickmarks 87 */ 88 switch(nTickmarkStyle) 89 { 90 case 1: 91 fPercent = 0.0; 92 break; 93 case 2: 94 fPercent = 1.0; 95 break; 96 default: 97 fPercent = 0.5; 98 break; 99 } 100 return fPercent*nLength; 101 } 102 103 VLineProperties AxisProperties::makeLinePropertiesForDepth( sal_Int32 /* nDepth */ ) const 104 { 105 //@todo get this from somewhere; maybe for each subincrement 106 //so far the model does not offer different settings for each tick depth 107 return m_aLineProperties; 108 } 109 110 TickmarkProperties AxisProperties::makeTickmarkProperties( 111 sal_Int32 nDepth ) const 112 { 113 /* 114 nTickmarkStyle: 115 1: inner tickmarks 116 2: outer tickmarks 117 3: inner and outer tickmarks 118 */ 119 sal_Int32 nTickmarkStyle = 1; 120 if(nDepth==0) 121 { 122 nTickmarkStyle = m_nMajorTickmarks; 123 if(!nTickmarkStyle) 124 { 125 //create major tickmarks as if they were minor tickmarks 126 nDepth = 1; 127 nTickmarkStyle = m_nMinorTickmarks; 128 } 129 } 130 else if( nDepth==1) 131 { 132 nTickmarkStyle = m_nMinorTickmarks; 133 } 134 135 if( m_fInnerDirectionSign == 0.0 ) 136 { 137 if( nTickmarkStyle != 0 ) 138 nTickmarkStyle = 3; //inner and outer tickmarks 139 } 140 141 TickmarkProperties aTickmarkProperties; 142 aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle); 143 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle)); 144 aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( nDepth ); 145 return aTickmarkProperties; 146 } 147 148 TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories( 149 sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 /*nTextLevel*/ ) const 150 { 151 sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/; 152 153 TickmarkProperties aTickmarkProperties; 154 aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) ); 155 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle)); 156 aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 ); 157 return aTickmarkProperties; 158 } 159 160 TickmarkProperties AxisProperties::getBiggestTickmarkProperties() 161 { 162 TickmarkProperties aTickmarkProperties; 163 sal_Int32 nDepth = 0; 164 sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks 165 aTickmarkProperties.Length = lcl_calcTickLengthForDepth( nDepth,nTickmarkStyle ); 166 aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) ); 167 return aTickmarkProperties; 168 } 169 170 //-------------------------------------------------------------------------- 171 172 AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel 173 , ExplicitCategoriesProvider* pExplicitCategoriesProvider ) 174 : m_xAxisModel(xAxisModel) 175 , m_nDimensionIndex(0) 176 , m_bIsMainAxis(true) 177 , m_bSwapXAndY(false) 178 , m_eCrossoverType( ::com::sun::star::chart::ChartAxisPosition_ZERO ) 179 , m_eLabelPos( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS ) 180 , m_eTickmarkPos( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) 181 , m_pfMainLinePositionAtOtherAxis(NULL) 182 , m_pfExrtaLinePositionAtOtherAxis(NULL) 183 , m_bCrossingAxisHasReverseDirection(false) 184 , m_bCrossingAxisIsCategoryAxes(false) 185 , m_fLabelDirectionSign(1.0) 186 , m_fInnerDirectionSign(1.0) 187 , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP) 188 , m_bDisplayLabels( true ) 189 , m_nNumberFormatKey(0) 190 , m_nMajorTickmarks(1) 191 , m_nMinorTickmarks(1) 192 , m_aTickmarkPropertiesList() 193 , m_aLineProperties() 194 //for category axes 195 , m_nAxisType(AxisType::REALNUMBER) 196 , m_bComplexCategories(false) 197 , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider) 198 , m_xAxisTextProvider(0) 199 { 200 } 201 202 AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) 203 : m_xAxisModel( rAxisProperties.m_xAxisModel ) 204 , m_nDimensionIndex( m_nDimensionIndex ) 205 , m_bIsMainAxis( rAxisProperties.m_bIsMainAxis ) 206 , m_bSwapXAndY( rAxisProperties.m_bSwapXAndY ) 207 , m_eCrossoverType( rAxisProperties.m_eCrossoverType ) 208 , m_eLabelPos( rAxisProperties.m_eLabelPos ) 209 , m_eTickmarkPos( rAxisProperties.m_eTickmarkPos ) 210 , m_pfMainLinePositionAtOtherAxis( NULL ) 211 , m_pfExrtaLinePositionAtOtherAxis( NULL ) 212 , m_bCrossingAxisHasReverseDirection( rAxisProperties.m_bCrossingAxisHasReverseDirection ) 213 , m_bCrossingAxisIsCategoryAxes( rAxisProperties.m_bCrossingAxisIsCategoryAxes ) 214 , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign ) 215 , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign ) 216 , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment ) 217 , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels ) 218 , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey ) 219 , m_nMajorTickmarks( rAxisProperties.m_nMajorTickmarks ) 220 , m_nMinorTickmarks( rAxisProperties.m_nMinorTickmarks ) 221 , m_aTickmarkPropertiesList( rAxisProperties.m_aTickmarkPropertiesList ) 222 , m_aLineProperties( rAxisProperties.m_aLineProperties ) 223 //for category axes 224 , m_nAxisType( rAxisProperties.m_nAxisType ) 225 , m_bComplexCategories( rAxisProperties.m_bComplexCategories ) 226 , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider ) 227 , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider ) 228 { 229 if( rAxisProperties.m_pfMainLinePositionAtOtherAxis ) 230 m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis); 231 if( rAxisProperties.m_pfExrtaLinePositionAtOtherAxis ) 232 m_pfExrtaLinePositionAtOtherAxis = new double (*rAxisProperties.m_pfExrtaLinePositionAtOtherAxis); 233 } 234 235 AxisProperties::~AxisProperties() 236 { 237 delete m_pfMainLinePositionAtOtherAxis; 238 delete m_pfExrtaLinePositionAtOtherAxis; 239 } 240 241 LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties ) 242 { 243 LabelAlignment aRet( LABEL_ALIGN_RIGHT ); 244 if( rAxisProperties.m_fLabelDirectionSign<0 ) 245 aRet = LABEL_ALIGN_LEFT; 246 return aRet; 247 } 248 249 LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties ) 250 { 251 LabelAlignment aRet( LABEL_ALIGN_RIGHT ); 252 if( rAxisProperties.m_fLabelDirectionSign<0 ) 253 aRet = LABEL_ALIGN_LEFT; 254 return aRet; 255 } 256 257 LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties ) 258 { 259 LabelAlignment aRet( LABEL_ALIGN_BOTTOM ); 260 if( rAxisProperties.m_fLabelDirectionSign<0 ) 261 aRet = LABEL_ALIGN_TOP; 262 return aRet; 263 } 264 265 void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp ) 266 { 267 if( !xAxisProp.is() ) 268 return; 269 try 270 { 271 if( AxisHelper::isAxisPositioningEnabled() ) 272 { 273 xAxisProp->getPropertyValue(C2U( "CrossoverPosition" )) >>= m_eCrossoverType; 274 if( ::com::sun::star::chart::ChartAxisPosition_VALUE == m_eCrossoverType ) 275 { 276 double fValue = 0.0; 277 xAxisProp->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue; 278 279 if( m_bCrossingAxisIsCategoryAxes ) 280 fValue = ::rtl::math::round(fValue); 281 m_pfMainLinePositionAtOtherAxis = new double(fValue); 282 } 283 else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == m_eCrossoverType ) 284 m_pfMainLinePositionAtOtherAxis = new double(0.0); 285 286 xAxisProp->getPropertyValue(C2U( "LabelPosition" )) >>= m_eLabelPos; 287 xAxisProp->getPropertyValue(C2U( "MarkPosition" )) >>= m_eTickmarkPos; 288 } 289 else 290 { 291 m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_START; 292 if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection ) 293 m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_END; 294 m_eLabelPos = ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS; 295 m_eTickmarkPos = ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS; 296 } 297 } 298 catch( uno::Exception& e ) 299 { 300 ASSERT_EXCEPTION( e ); 301 } 302 } 303 304 void AxisProperties::init( bool bCartesian ) 305 { 306 uno::Reference< beans::XPropertySet > xProp = 307 uno::Reference<beans::XPropertySet>::query( this->m_xAxisModel ); 308 if( !xProp.is() ) 309 return; 310 311 if( m_nDimensionIndex<2 ) 312 initAxisPositioning( xProp ); 313 314 ScaleData aScaleData = m_xAxisModel->getScaleData(); 315 if( m_nDimensionIndex==0 ) 316 AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian ); 317 m_nAxisType = aScaleData.AxisType; 318 319 if( bCartesian ) 320 { 321 if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY 322 && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) 323 m_bComplexCategories = true; 324 325 if( ::com::sun::star::chart::ChartAxisPosition_END == m_eCrossoverType ) 326 m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1; 327 else 328 m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1; 329 330 if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS == m_eLabelPos ) 331 m_fLabelDirectionSign = m_fInnerDirectionSign; 332 else if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE == m_eLabelPos ) 333 m_fLabelDirectionSign = -m_fInnerDirectionSign; 334 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_eLabelPos ) 335 m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1; 336 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_eLabelPos ) 337 m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1; 338 339 if( m_nDimensionIndex==2 ) 340 m_aLabelAlignment = lcl_getLabelAlignmentForZAxis(*this); 341 else 342 { 343 bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY) 344 || (m_nDimensionIndex==0 && m_bSwapXAndY); 345 if( bIsYAxisPosition ) 346 { 347 m_fLabelDirectionSign*=-1; 348 m_fInnerDirectionSign*=-1; 349 } 350 351 if( bIsYAxisPosition ) 352 m_aLabelAlignment = lcl_getLabelAlignmentForYAxis(*this); 353 else 354 m_aLabelAlignment = lcl_getLabelAlignmentForXAxis(*this); 355 } 356 } 357 358 try 359 { 360 //init LineProperties 361 m_aLineProperties.initFromPropertySet( xProp ); 362 363 //init display labels 364 xProp->getPropertyValue( C2U( "DisplayLabels" ) ) >>= m_bDisplayLabels; 365 366 //init TickmarkProperties 367 xProp->getPropertyValue( C2U( "MajorTickmarks" ) ) >>= m_nMajorTickmarks; 368 xProp->getPropertyValue( C2U( "MinorTickmarks" ) ) >>= m_nMinorTickmarks; 369 370 sal_Int32 nMaxDepth = 0; 371 if(m_nMinorTickmarks!=0) 372 nMaxDepth=2; 373 else if(m_nMajorTickmarks!=0) 374 nMaxDepth=1; 375 376 this->m_aTickmarkPropertiesList.clear(); 377 for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ ) 378 { 379 TickmarkProperties aTickmarkProperties = this->makeTickmarkProperties( nDepth ); 380 this->m_aTickmarkPropertiesList.push_back( aTickmarkProperties ); 381 } 382 } 383 catch( uno::Exception& e ) 384 { 385 ASSERT_EXCEPTION( e ); 386 } 387 } 388 389 //----------------------------------------------------------------------------- 390 391 AxisLabelProperties::AxisLabelProperties() 392 : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() ) 393 , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height ) 394 , nNumberFormatKey(0) 395 , eStaggering( SIDE_BY_SIDE ) 396 , bLineBreakAllowed( false ) 397 , bOverlapAllowed( false ) 398 , bStackCharacters( false ) 399 , fRotationAngleDegree( 0.0 ) 400 , nRhythm( 1 ) 401 , bRhythmIsFix(false) 402 { 403 /* 404 aLocale.Language = C2U( "en" ); 405 aLocale.Country = C2U( "US" ); 406 407 //aLocale.Language = C2U( "ar" ); 408 //aLocale.Country = C2U( "IR" ); 409 410 //aLocale.Language = C2U( "ja" ); 411 //aLocale.Country = C2U( "JP" ); 412 */ 413 } 414 415 void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel ) 416 { 417 uno::Reference< beans::XPropertySet > xProp = 418 uno::Reference<beans::XPropertySet>::query( xAxisModel ); 419 if(xProp.is()) 420 { 421 try 422 { 423 xProp->getPropertyValue( C2U( "TextBreak" ) ) >>= this->bLineBreakAllowed; 424 xProp->getPropertyValue( C2U( "TextOverlap" ) ) >>= this->bOverlapAllowed; 425 xProp->getPropertyValue( C2U( "StackCharacters" ) ) >>= this->bStackCharacters; 426 xProp->getPropertyValue( C2U( "TextRotation" ) ) >>= this->fRotationAngleDegree; 427 428 ::com::sun::star::chart::ChartAxisArrangeOrderType eArrangeOrder; 429 xProp->getPropertyValue( C2U( "ArrangeOrder" ) ) >>= eArrangeOrder; 430 switch(eArrangeOrder) 431 { 432 case ::com::sun::star::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE: 433 this->eStaggering = SIDE_BY_SIDE; 434 break; 435 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_EVEN: 436 this->eStaggering = STAGGER_EVEN; 437 break; 438 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_ODD: 439 this->eStaggering = STAGGER_ODD; 440 break; 441 default: 442 this->eStaggering = STAGGER_AUTO; 443 break; 444 } 445 } 446 catch( uno::Exception& e ) 447 { 448 ASSERT_EXCEPTION( e ); 449 } 450 } 451 } 452 453 /* 454 sal_Int16 getSwappedWritingMode( sal_Int16 nWritingMode ) 455 { 456 //LR_TB == LT 457 //RL_TB == RT (Arabic, Hebrew) 458 //TB_RL == TR (Japanese, Chinese, Korean) 459 // ?? TL (Mongolian) see also text::WritingMode2 460 461 switch(nWritingMode) 462 { 463 case text::WritingMode2::RL_TB: 464 return text::WritingMode2::TB_RL; 465 case text::WritingMode2::TB_RL: 466 return text::WritingMode2::RL_TB; 467 case text::WritingMode2::LR_TB: 468 return text::WritingMode2::TB_LR; 469 default: 470 return text::WritingMode2::LR_TB; 471 } 472 } 473 */ 474 475 sal_Bool AxisLabelProperties::getIsStaggered() const 476 { 477 if( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering ) 478 return sal_True; 479 return sal_False; 480 } 481 482 //............................................................................. 483 } //namespace chart 484 //............................................................................. 485