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 31 #include "LabelPositionHelper.hxx" 32 #include "PlottingPositionHelper.hxx" 33 #include "CommonConverters.hxx" 34 #include "PropertyMapper.hxx" 35 #include "ShapeFactory.hxx" 36 #include "macros.hxx" 37 #include "RelativeSizeHelper.hxx" 38 #include <com/sun/star/drawing/TextVerticalAdjust.hpp> 39 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> 40 41 //............................................................................. 42 namespace chart 43 { 44 //............................................................................. 45 using namespace ::com::sun::star; 46 using namespace ::com::sun::star::chart2; 47 48 LabelPositionHelper::LabelPositionHelper( 49 PlottingPositionHelper* pPosHelper 50 , sal_Int32 nDimensionCount 51 , const uno::Reference< drawing::XShapes >& xLogicTarget 52 , ShapeFactory* pShapeFactory ) 53 : m_pPosHelper(pPosHelper) 54 , m_nDimensionCount(nDimensionCount) 55 , m_xLogicTarget(xLogicTarget) 56 , m_pShapeFactory(pShapeFactory) 57 { 58 } 59 60 LabelPositionHelper::~LabelPositionHelper() 61 { 62 } 63 64 awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const 65 { 66 return PlottingPositionHelper::transformSceneToScreenPosition( 67 rScenePosition3D, m_xLogicTarget, m_pShapeFactory, m_nDimensionCount ); 68 } 69 70 void LabelPositionHelper::changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment) 71 { 72 //HorizontalAdjustment 73 { 74 drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER; 75 if( LABEL_ALIGN_RIGHT==eAlignment || LABEL_ALIGN_RIGHT_TOP==eAlignment || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment ) 76 eHorizontalAdjust = drawing::TextHorizontalAdjust_LEFT; 77 else if( LABEL_ALIGN_LEFT==eAlignment || LABEL_ALIGN_LEFT_TOP==eAlignment || LABEL_ALIGN_LEFT_BOTTOM==eAlignment ) 78 eHorizontalAdjust = drawing::TextHorizontalAdjust_RIGHT; 79 uno::Any* pHorizontalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,C2U("TextHorizontalAdjust")); 80 if(pHorizontalAdjustAny) 81 *pHorizontalAdjustAny = uno::makeAny(eHorizontalAdjust); 82 } 83 84 //VerticalAdjustment 85 { 86 drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER; 87 if( LABEL_ALIGN_TOP==eAlignment || LABEL_ALIGN_RIGHT_TOP==eAlignment || LABEL_ALIGN_LEFT_TOP==eAlignment ) 88 eVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM; 89 else if( LABEL_ALIGN_BOTTOM==eAlignment || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment || LABEL_ALIGN_LEFT_BOTTOM==eAlignment ) 90 eVerticalAdjust = drawing::TextVerticalAdjust_TOP; 91 uno::Any* pVerticalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,C2U("TextVerticalAdjust")); 92 if(pVerticalAdjustAny) 93 *pVerticalAdjustAny = uno::makeAny(eVerticalAdjust); 94 } 95 } 96 97 void lcl_doDynamicFontResize( uno::Any* pAOldAndNewFontHeightAny 98 , const awt::Size& rOldReferenceSize 99 , const awt::Size& rNewReferenceSize ) 100 { 101 double fOldFontHeight = 0, fNewFontHeight; 102 if( pAOldAndNewFontHeightAny && ( *pAOldAndNewFontHeightAny >>= fOldFontHeight ) ) 103 { 104 fNewFontHeight = RelativeSizeHelper::calculate( fOldFontHeight, rOldReferenceSize, rNewReferenceSize ); 105 *pAOldAndNewFontHeightAny = uno::makeAny(fNewFontHeight); 106 } 107 } 108 109 void LabelPositionHelper::doDynamicFontResize( tAnySequence& rPropValues 110 , const tNameSequence& rPropNames 111 , const uno::Reference< beans::XPropertySet >& xAxisModelProps 112 , const awt::Size& rNewReferenceSize 113 ) 114 { 115 //------------------------- 116 //handle dynamic font resize: 117 awt::Size aOldReferenceSize; 118 if( xAxisModelProps->getPropertyValue( C2U("ReferencePageSize")) >>= aOldReferenceSize ) 119 { 120 uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeight") ); 121 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); 122 pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeightAsian") ); 123 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); 124 pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, C2U("CharHeightComplex") ); 125 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); 126 } 127 } 128 129 namespace 130 { 131 132 void lcl_correctRotation_Left( double& rfXCorrection, double& rfYCorrection 133 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter ) 134 { 135 //correct label positions for labels on a left side of something with a right centered alignment 136 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 137 if( fAnglePositiveDegree==0.0 ) 138 { 139 } 140 else if( fAnglePositiveDegree<= 90.0 ) 141 { 142 rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0; 143 if( bRotateAroundCenter ) 144 rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; 145 } 146 else if( fAnglePositiveDegree<= 180.0 ) 147 { 148 double beta = fAnglePi-F_PI/2.0; 149 rfXCorrection = -aSize.Width *rtl::math::sin( beta ) 150 -aSize.Height *rtl::math::cos( beta )/2.0; 151 if( bRotateAroundCenter ) 152 rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; 153 else 154 rfYCorrection = -aSize.Width *rtl::math::cos( beta ); 155 } 156 else if( fAnglePositiveDegree<= 270.0 ) 157 { 158 double beta = fAnglePi - F_PI; 159 rfXCorrection = -aSize.Width *rtl::math::cos( beta ) 160 -aSize.Height*rtl::math::sin( beta )/2.0; 161 if( bRotateAroundCenter ) 162 rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; 163 else 164 rfYCorrection = aSize.Width *rtl::math::sin( beta ); 165 } 166 else 167 { 168 double beta = 2*F_PI - fAnglePi; 169 rfXCorrection = -aSize.Height*rtl::math::sin( beta )/2.0; 170 if( bRotateAroundCenter ) 171 rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0; 172 } 173 } 174 175 void lcl_correctRotation_Right( double& rfXCorrection, double& rfYCorrection 176 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter ) 177 { 178 //correct label positions for labels on a right side of something with a left centered alignment 179 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 180 if( fAnglePositiveDegree== 0.0 ) 181 { 182 } 183 else if( fAnglePositiveDegree<= 90.0 ) 184 { 185 rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; 186 if( bRotateAroundCenter ) 187 rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; 188 } 189 else if( fAnglePositiveDegree<= 180.0 ) 190 { 191 double beta = F_PI - fAnglePi; 192 rfXCorrection = aSize.Width *rtl::math::cos( beta ) 193 + aSize.Height*rtl::math::sin( beta )/2.0; 194 if( bRotateAroundCenter ) 195 rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; 196 else 197 rfYCorrection = aSize.Width *rtl::math::sin( beta ); 198 } 199 else if( fAnglePositiveDegree<= 270.0 ) 200 { 201 double beta = 3*F_PI/2.0 - fAnglePi; 202 rfXCorrection = aSize.Width *rtl::math::sin( beta ) 203 +aSize.Height*rtl::math::cos( beta )/2.0; 204 if( bRotateAroundCenter ) 205 rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; 206 else 207 rfYCorrection = -aSize.Width *rtl::math::cos( beta ); 208 } 209 else 210 { 211 rfXCorrection = aSize.Height*rtl::math::sin( 2*F_PI - fAnglePi )/2.0; 212 if( bRotateAroundCenter ) 213 rfYCorrection = -aSize.Width*rtl::math::sin( 2*F_PI - fAnglePi )/2.0; 214 } 215 } 216 217 void lcl_correctRotation_Top( double& rfXCorrection, double& rfYCorrection 218 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter ) 219 { 220 //correct label positions for labels on top of something with a bottom centered alignment 221 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 222 if( fAnglePositiveDegree== 0.0 ) 223 { 224 } 225 else if( fAnglePositiveDegree<= 90.0 ) 226 { 227 rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; 228 if( !bRotateAroundCenter ) 229 rfXCorrection += aSize.Width*rtl::math::cos( fAnglePi )/2.0; 230 rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; 231 } 232 else if( fAnglePositiveDegree<= 180.0 ) 233 { 234 double beta = fAnglePi - F_PI/2.0; 235 rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; 236 if( !bRotateAroundCenter ) 237 rfXCorrection -= aSize.Width*rtl::math::sin( beta )/2.0; 238 rfYCorrection = -aSize.Width*rtl::math::cos( beta )/2.0 239 - aSize.Height*rtl::math::sin( beta ); 240 } 241 else if( fAnglePositiveDegree<= 270.0 ) 242 { 243 double beta = fAnglePi - F_PI; 244 rfXCorrection = -aSize.Height *rtl::math::sin( beta )/2.0; 245 if( !bRotateAroundCenter ) 246 rfXCorrection += aSize.Width *rtl::math::cos( beta )/2.0; 247 rfYCorrection = -aSize.Width *rtl::math::sin( beta )/2.0 248 -aSize.Height *rtl::math::cos( beta ); 249 } 250 else 251 { 252 rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; 253 if( !bRotateAroundCenter ) 254 rfXCorrection -= aSize.Width*rtl::math::cos( fAnglePi )/2.0; 255 rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; 256 } 257 } 258 259 void lcl_correctRotation_Bottom( double& rfXCorrection, double& rfYCorrection 260 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter ) 261 { 262 //correct label positions for labels below something with a top centered alignment 263 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 264 if( fAnglePositiveDegree==0.0 ) 265 { 266 } 267 else if( fAnglePositiveDegree<= 90.0 ) 268 { 269 rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0; 270 if( !bRotateAroundCenter ) 271 rfXCorrection -= aSize.Width *rtl::math::cos( fAnglePi )/2.0; 272 rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; 273 } 274 else if( fAnglePositiveDegree<= 180.0 ) 275 { 276 double beta = fAnglePi-F_PI/2.0; 277 rfXCorrection = -aSize.Height*rtl::math::cos( beta )/2.0; 278 if( !bRotateAroundCenter ) 279 rfXCorrection += aSize.Width *rtl::math::sin( beta )/2.0; 280 rfYCorrection = aSize.Width *rtl::math::cos( beta )/2.0 281 +aSize.Height*rtl::math::sin( beta ); 282 } 283 else if( fAnglePositiveDegree<= 270.0 ) 284 { 285 double beta = 3*F_PI/2.0 - fAnglePi; 286 rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; 287 if( !bRotateAroundCenter ) 288 rfXCorrection -= aSize.Width *rtl::math::sin( beta )/2.0; 289 rfYCorrection = aSize.Height*rtl::math::sin( beta ) 290 +aSize.Width*rtl::math::cos( beta )/2.0; 291 } 292 else 293 { 294 double beta = 2*F_PI - fAnglePi; 295 rfXCorrection = aSize.Height*rtl::math::sin( beta )/2.0; 296 if( !bRotateAroundCenter ) 297 rfXCorrection += aSize.Width*rtl::math::cos( beta )/2.0; 298 rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0; 299 } 300 } 301 302 void lcl_correctRotation_Left_Top( double& rfXCorrection, double& rfYCorrection 303 , double fAnglePositiveDegree, const awt::Size& aSize ) 304 { 305 //correct position for labels at the left top corner of something with a bottom right alignment 306 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 307 if( fAnglePositiveDegree==0.0 ) 308 { 309 } 310 else if( fAnglePositiveDegree<= 90.0 ) 311 { 312 rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi ); 313 } 314 else if( fAnglePositiveDegree<= 180.0 ) 315 { 316 double beta = fAnglePi-F_PI/2.0; 317 rfXCorrection = -aSize.Width*rtl::math::sin( beta ); 318 rfYCorrection = -aSize.Height*rtl::math::sin( beta ) 319 -aSize.Width*rtl::math::cos( beta ); 320 } 321 else if( fAnglePositiveDegree<= 270.0 ) 322 { 323 double beta = 3*F_PI/2.0 - fAnglePi; 324 rfXCorrection = -aSize.Height*rtl::math::cos( beta ) 325 -aSize.Width*rtl::math::sin( beta ); 326 rfYCorrection = -aSize.Height*rtl::math::sin( beta ); 327 } 328 else 329 { 330 rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi ); 331 } 332 } 333 334 void lcl_correctRotation_Left_Bottom( double& rfXCorrection, double& rfYCorrection 335 , double fAnglePositiveDegree, const awt::Size& aSize ) 336 { 337 //correct position for labels at the left bottom corner of something with a top right alignment 338 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 339 if( fAnglePositiveDegree==0.0 ) 340 { 341 } 342 else if( fAnglePositiveDegree<= 90.0 ) 343 { 344 rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi ); 345 } 346 else if( fAnglePositiveDegree<= 180.0 ) 347 { 348 double beta = fAnglePi-F_PI/2.0; 349 rfXCorrection = -aSize.Width*rtl::math::sin( beta ) 350 -aSize.Height*rtl::math::cos( beta );; 351 rfYCorrection = aSize.Height*rtl::math::sin( beta ); 352 } 353 else if( fAnglePositiveDegree<= 270.0 ) 354 { 355 double beta = 3*F_PI/2.0 - fAnglePi; 356 rfXCorrection = -aSize.Width*rtl::math::sin( beta ); 357 rfYCorrection = aSize.Width*rtl::math::cos( beta ) 358 +aSize.Height*rtl::math::sin( beta ); 359 } 360 else 361 { 362 rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi ); 363 } 364 } 365 366 void lcl_correctRotation_Right_Top( double& rfXCorrection, double& rfYCorrection 367 , double fAnglePositiveDegree, const awt::Size& aSize ) 368 { 369 //correct position for labels at the right top corner of something with a bottom left alignment 370 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 371 if( fAnglePositiveDegree==0.0 ) 372 { 373 } 374 else if( fAnglePositiveDegree<= 90.0 ) 375 { 376 rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi ); 377 } 378 else if( fAnglePositiveDegree<= 180.0 ) 379 { 380 double beta = fAnglePi-F_PI/2.0; 381 rfXCorrection = aSize.Width*rtl::math::sin( beta ) 382 +aSize.Height*rtl::math::cos( beta ); 383 rfYCorrection = -aSize.Height*rtl::math::sin( beta ); 384 } 385 else if( fAnglePositiveDegree<= 270.0 ) 386 { 387 double beta = 3*F_PI/2.0 - fAnglePi; 388 rfXCorrection = aSize.Width*rtl::math::sin( beta ); 389 rfYCorrection = -aSize.Width*rtl::math::cos( beta ) 390 -aSize.Height*rtl::math::sin( beta ); 391 } 392 else 393 { 394 rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi ); 395 } 396 } 397 398 void lcl_correctRotation_Right_Bottom( double& rfXCorrection, double& rfYCorrection 399 , double fAnglePositiveDegree, const awt::Size& aSize ) 400 { 401 //correct position for labels at the right bottom corner of something with a top left alignment 402 double fAnglePi = fAnglePositiveDegree*F_PI/180.0; 403 if( fAnglePositiveDegree==0.0 ) 404 { 405 } 406 else if( fAnglePositiveDegree<= 90.0 ) 407 { 408 rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi ); 409 } 410 else if( fAnglePositiveDegree<= 180.0 ) 411 { 412 double beta = fAnglePi-F_PI/2.0; 413 rfXCorrection = aSize.Width*rtl::math::sin( beta ); 414 rfYCorrection = aSize.Height*rtl::math::sin( beta ) 415 +aSize.Width*rtl::math::cos( beta ); 416 } 417 else if( fAnglePositiveDegree<= 270.0 ) 418 { 419 double beta = 3*F_PI/2.0 - fAnglePi; 420 rfXCorrection = aSize.Height*rtl::math::cos( beta ) 421 +aSize.Width*rtl::math::sin( beta ); 422 rfYCorrection = aSize.Height*rtl::math::sin( beta ); 423 } 424 else 425 { 426 rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi ); 427 } 428 } 429 430 }//end anonymous namespace 431 432 void LabelPositionHelper::correctPositionForRotation( const uno::Reference< drawing::XShape >& xShape2DText 433 , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter ) 434 { 435 if( !xShape2DText.is() ) 436 return; 437 438 awt::Point aOldPos = xShape2DText->getPosition(); 439 awt::Size aSize = xShape2DText->getSize(); 440 441 double fYCorrection = 0.0; 442 double fXCorrection = 0.0; 443 444 double fAnglePositiveDegree = fRotationAngle; 445 while(fAnglePositiveDegree<0.0) 446 fAnglePositiveDegree+=360.0; 447 448 switch(eLabelAlignment) 449 { 450 case LABEL_ALIGN_LEFT: 451 lcl_correctRotation_Left( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter ); 452 break; 453 case LABEL_ALIGN_RIGHT: 454 lcl_correctRotation_Right( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter ); 455 break; 456 case LABEL_ALIGN_TOP: 457 lcl_correctRotation_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter ); 458 break; 459 case LABEL_ALIGN_BOTTOM: 460 lcl_correctRotation_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter ); 461 break; 462 case LABEL_ALIGN_LEFT_TOP: 463 lcl_correctRotation_Left_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize ); 464 break; 465 case LABEL_ALIGN_LEFT_BOTTOM: 466 lcl_correctRotation_Left_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize ); 467 break; 468 case LABEL_ALIGN_RIGHT_TOP: 469 lcl_correctRotation_Right_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize ); 470 break; 471 case LABEL_ALIGN_RIGHT_BOTTOM: 472 lcl_correctRotation_Right_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize ); 473 break; 474 default: //LABEL_ALIGN_CENTER 475 break; 476 } 477 478 xShape2DText->setPosition( awt::Point( 479 static_cast<sal_Int32>(aOldPos.X + fXCorrection ) 480 , static_cast<sal_Int32>(aOldPos.Y + fYCorrection ) ) ); 481 } 482 483 //............................................................................. 484 } //namespace chart 485 //............................................................................. 486