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