1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: LabelPositionHelper.cxx,v $
10 * $Revision: 1.7.44.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 #include "LabelPositionHelper.hxx"
35 #include "PlottingPositionHelper.hxx"
36 #include "CommonConverters.hxx"
37 #include "PropertyMapper.hxx"
38 #include "ShapeFactory.hxx"
40 #include "RelativeSizeHelper.hxx"
41 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
42 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
44 //.............................................................................
47 //.............................................................................
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::chart2
;
51 LabelPositionHelper::LabelPositionHelper(
52 PlottingPositionHelper
* pPosHelper
53 , sal_Int32 nDimensionCount
54 , const uno::Reference
< drawing::XShapes
>& xLogicTarget
55 , ShapeFactory
* pShapeFactory
)
56 : m_pPosHelper(pPosHelper
)
57 , m_nDimensionCount(nDimensionCount
)
58 , m_xLogicTarget(xLogicTarget
)
59 , m_pShapeFactory(pShapeFactory
)
63 LabelPositionHelper::~LabelPositionHelper()
67 awt::Point
LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D
& rScenePosition3D
) const
69 return PlottingPositionHelper::transformSceneToScreenPosition(
70 rScenePosition3D
, m_xLogicTarget
, m_pShapeFactory
, m_nDimensionCount
);
74 void LabelPositionHelper::changeTextAdjustment( tAnySequence
& rPropValues
, const tNameSequence
& rPropNames
, LabelAlignment eAlignment
)
76 //HorizontalAdjustment
78 drawing::TextHorizontalAdjust eHorizontalAdjust
= drawing::TextHorizontalAdjust_CENTER
;
79 if( LABEL_ALIGN_RIGHT
==eAlignment
|| LABEL_ALIGN_RIGHT_TOP
==eAlignment
|| LABEL_ALIGN_RIGHT_BOTTOM
==eAlignment
)
80 eHorizontalAdjust
= drawing::TextHorizontalAdjust_LEFT
;
81 else if( LABEL_ALIGN_LEFT
==eAlignment
|| LABEL_ALIGN_LEFT_TOP
==eAlignment
|| LABEL_ALIGN_LEFT_BOTTOM
==eAlignment
)
82 eHorizontalAdjust
= drawing::TextHorizontalAdjust_RIGHT
;
83 uno::Any
* pHorizontalAdjustAny
= PropertyMapper::getValuePointer(rPropValues
,rPropNames
,C2U("TextHorizontalAdjust"));
84 if(pHorizontalAdjustAny
)
85 *pHorizontalAdjustAny
= uno::makeAny(eHorizontalAdjust
);
90 drawing::TextVerticalAdjust eVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
91 if( LABEL_ALIGN_TOP
==eAlignment
|| LABEL_ALIGN_RIGHT_TOP
==eAlignment
|| LABEL_ALIGN_LEFT_TOP
==eAlignment
)
92 eVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
93 else if( LABEL_ALIGN_BOTTOM
==eAlignment
|| LABEL_ALIGN_RIGHT_BOTTOM
==eAlignment
|| LABEL_ALIGN_LEFT_BOTTOM
==eAlignment
)
94 eVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
95 uno::Any
* pVerticalAdjustAny
= PropertyMapper::getValuePointer(rPropValues
,rPropNames
,C2U("TextVerticalAdjust"));
96 if(pVerticalAdjustAny
)
97 *pVerticalAdjustAny
= uno::makeAny(eVerticalAdjust
);
101 void lcl_doDynamicFontResize( uno::Any
* pAOldAndNewFontHeightAny
102 , const awt::Size
& rOldReferenceSize
103 , const awt::Size
& rNewReferenceSize
)
105 double fOldFontHeight
= 0, fNewFontHeight
;
106 if( pAOldAndNewFontHeightAny
&& ( *pAOldAndNewFontHeightAny
>>= fOldFontHeight
) )
108 fNewFontHeight
= RelativeSizeHelper::calculate( fOldFontHeight
, rOldReferenceSize
, rNewReferenceSize
);
109 *pAOldAndNewFontHeightAny
= uno::makeAny(fNewFontHeight
);
114 void LabelPositionHelper::doDynamicFontResize( tAnySequence
& rPropValues
115 , const tNameSequence
& rPropNames
116 , const uno::Reference
< beans::XPropertySet
>& xAxisModelProps
117 , const awt::Size
& rNewReferenceSize
120 //-------------------------
121 //handle dynamic font resize:
122 awt::Size aOldReferenceSize
;
123 if( xAxisModelProps
->getPropertyValue( C2U("ReferencePageSize")) >>= aOldReferenceSize
)
125 uno::Any
* pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, C2U("CharHeight") );
126 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
127 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, C2U("CharHeightAsian") );
128 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
129 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, C2U("CharHeightComplex") );
130 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
137 void lcl_correctRotation_Left( double& rfXCorrection
, double& rfYCorrection
138 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
140 //correct label positions for labels on a left side of something with a right centered alignment
141 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
142 if( fAnglePositiveDegree
==0.0 )
145 else if( fAnglePositiveDegree
<= 90.0 )
147 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
148 if( bRotateAroundCenter
)
149 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
151 else if( fAnglePositiveDegree
<= 180.0 )
153 double beta
= fAnglePi
-F_PI
/2.0;
154 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
)
155 -aSize
.Height
*rtl::math::cos( beta
)/2.0;
156 if( bRotateAroundCenter
)
157 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0;
159 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
);
161 else if( fAnglePositiveDegree
<= 270.0 )
163 double beta
= fAnglePi
- F_PI
;
164 rfXCorrection
= -aSize
.Width
*rtl::math::cos( beta
)
165 -aSize
.Height
*rtl::math::sin( beta
)/2.0;
166 if( bRotateAroundCenter
)
167 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
169 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
);
173 double beta
= 2*F_PI
- fAnglePi
;
174 rfXCorrection
= -aSize
.Height
*rtl::math::sin( beta
)/2.0;
175 if( bRotateAroundCenter
)
176 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
180 void lcl_correctRotation_Right( double& rfXCorrection
, double& rfYCorrection
181 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
183 //correct label positions for labels on a right side of something with a left centered alignment
184 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
185 if( fAnglePositiveDegree
== 0.0 )
188 else if( fAnglePositiveDegree
<= 90.0 )
190 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
191 if( bRotateAroundCenter
)
192 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
194 else if( fAnglePositiveDegree
<= 180.0 )
196 double beta
= F_PI
- fAnglePi
;
197 rfXCorrection
= aSize
.Width
*rtl::math::cos( beta
)
198 + aSize
.Height
*rtl::math::sin( beta
)/2.0;
199 if( bRotateAroundCenter
)
200 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
202 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
);
204 else if( fAnglePositiveDegree
<= 270.0 )
206 double beta
= 3*F_PI
/2.0 - fAnglePi
;
207 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
)
208 +aSize
.Height
*rtl::math::cos( beta
)/2.0;
209 if( bRotateAroundCenter
)
210 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0;
212 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
);
216 rfXCorrection
= aSize
.Height
*rtl::math::sin( 2*F_PI
- fAnglePi
)/2.0;
217 if( bRotateAroundCenter
)
218 rfYCorrection
= -aSize
.Width
*rtl::math::sin( 2*F_PI
- fAnglePi
)/2.0;
222 void lcl_correctRotation_Top( double& rfXCorrection
, double& rfYCorrection
223 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
225 //correct label positions for labels on top of something with a bottom centered alignment
226 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
227 if( fAnglePositiveDegree
== 0.0 )
230 else if( fAnglePositiveDegree
<= 90.0 )
232 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
233 if( !bRotateAroundCenter
)
234 rfXCorrection
+= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
235 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
237 else if( fAnglePositiveDegree
<= 180.0 )
239 double beta
= fAnglePi
- F_PI
/2.0;
240 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)/2.0;
241 if( !bRotateAroundCenter
)
242 rfXCorrection
-= aSize
.Width
*rtl::math::sin( beta
)/2.0;
243 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0
244 - aSize
.Height
*rtl::math::sin( beta
);
246 else if( fAnglePositiveDegree
<= 270.0 )
248 double beta
= fAnglePi
- F_PI
;
249 rfXCorrection
= -aSize
.Height
*rtl::math::sin( beta
)/2.0;
250 if( !bRotateAroundCenter
)
251 rfXCorrection
+= aSize
.Width
*rtl::math::cos( beta
)/2.0;
252 rfYCorrection
= -aSize
.Width
*rtl::math::sin( beta
)/2.0
253 -aSize
.Height
*rtl::math::cos( beta
);
257 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
258 if( !bRotateAroundCenter
)
259 rfXCorrection
-= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
260 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
264 void lcl_correctRotation_Bottom( double& rfXCorrection
, double& rfYCorrection
265 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
267 //correct label positions for labels below something with a top centered alignment
268 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
269 if( fAnglePositiveDegree
==0.0 )
272 else if( fAnglePositiveDegree
<= 90.0 )
274 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
275 if( !bRotateAroundCenter
)
276 rfXCorrection
-= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
277 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
279 else if( fAnglePositiveDegree
<= 180.0 )
281 double beta
= fAnglePi
-F_PI
/2.0;
282 rfXCorrection
= -aSize
.Height
*rtl::math::cos( beta
)/2.0;
283 if( !bRotateAroundCenter
)
284 rfXCorrection
+= aSize
.Width
*rtl::math::sin( beta
)/2.0;
285 rfYCorrection
= aSize
.Width
*rtl::math::cos( beta
)/2.0
286 +aSize
.Height
*rtl::math::sin( beta
);
288 else if( fAnglePositiveDegree
<= 270.0 )
290 double beta
= 3*F_PI
/2.0 - fAnglePi
;
291 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)/2.0;
292 if( !bRotateAroundCenter
)
293 rfXCorrection
-= aSize
.Width
*rtl::math::sin( beta
)/2.0;
294 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
)
295 +aSize
.Width
*rtl::math::cos( beta
)/2.0;
299 double beta
= 2*F_PI
- fAnglePi
;
300 rfXCorrection
= aSize
.Height
*rtl::math::sin( beta
)/2.0;
301 if( !bRotateAroundCenter
)
302 rfXCorrection
+= aSize
.Width
*rtl::math::cos( beta
)/2.0;
303 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
307 void lcl_correctRotation_Left_Top( double& rfXCorrection
, double& rfYCorrection
308 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
310 //correct position for labels at the left top corner of something with a bottom right alignment
311 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
312 if( fAnglePositiveDegree
==0.0 )
315 else if( fAnglePositiveDegree
<= 90.0 )
317 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
);
319 else if( fAnglePositiveDegree
<= 180.0 )
321 double beta
= fAnglePi
-F_PI
/2.0;
322 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
);
323 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
)
324 -aSize
.Width
*rtl::math::cos( beta
);
326 else if( fAnglePositiveDegree
<= 270.0 )
328 double beta
= 3*F_PI
/2.0 - fAnglePi
;
329 rfXCorrection
= -aSize
.Height
*rtl::math::cos( beta
)
330 -aSize
.Width
*rtl::math::sin( beta
);
331 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
);
335 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
);
339 void lcl_correctRotation_Left_Bottom( double& rfXCorrection
, double& rfYCorrection
340 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
342 //correct position for labels at the left bottom corner of something with a top right alignment
343 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
344 if( fAnglePositiveDegree
==0.0 )
347 else if( fAnglePositiveDegree
<= 90.0 )
349 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
);
351 else if( fAnglePositiveDegree
<= 180.0 )
353 double beta
= fAnglePi
-F_PI
/2.0;
354 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
)
355 -aSize
.Height
*rtl::math::cos( beta
);;
356 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
);
358 else if( fAnglePositiveDegree
<= 270.0 )
360 double beta
= 3*F_PI
/2.0 - fAnglePi
;
361 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
);
362 rfYCorrection
= aSize
.Width
*rtl::math::cos( beta
)
363 +aSize
.Height
*rtl::math::sin( beta
);
367 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
);
371 void lcl_correctRotation_Right_Top( double& rfXCorrection
, double& rfYCorrection
372 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
374 //correct position for labels at the right top corner of something with a bottom left alignment
375 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
376 if( fAnglePositiveDegree
==0.0 )
379 else if( fAnglePositiveDegree
<= 90.0 )
381 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
);
383 else if( fAnglePositiveDegree
<= 180.0 )
385 double beta
= fAnglePi
-F_PI
/2.0;
386 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
)
387 +aSize
.Height
*rtl::math::cos( beta
);
388 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
);
390 else if( fAnglePositiveDegree
<= 270.0 )
392 double beta
= 3*F_PI
/2.0 - fAnglePi
;
393 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
);
394 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)
395 -aSize
.Height
*rtl::math::sin( beta
);
399 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
);
403 void lcl_correctRotation_Right_Bottom( double& rfXCorrection
, double& rfYCorrection
404 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
406 //correct position for labels at the right bottom corner of something with a top left alignment
407 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
408 if( fAnglePositiveDegree
==0.0 )
411 else if( fAnglePositiveDegree
<= 90.0 )
413 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
);
415 else if( fAnglePositiveDegree
<= 180.0 )
417 double beta
= fAnglePi
-F_PI
/2.0;
418 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
);
419 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
)
420 +aSize
.Width
*rtl::math::cos( beta
);
422 else if( fAnglePositiveDegree
<= 270.0 )
424 double beta
= 3*F_PI
/2.0 - fAnglePi
;
425 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)
426 +aSize
.Width
*rtl::math::sin( beta
);
427 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
);
431 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
);
435 }//end anonymous namespace
438 void LabelPositionHelper::correctPositionForRotation( const uno::Reference
< drawing::XShape
>& xShape2DText
439 , LabelAlignment eLabelAlignment
, const double fRotationAngle
, bool bRotateAroundCenter
)
441 if( !xShape2DText
.is() )
444 awt::Point aOldPos
= xShape2DText
->getPosition();
445 awt::Size aSize
= xShape2DText
->getSize();
447 double fYCorrection
= 0.0;
448 double fXCorrection
= 0.0;
450 double fAnglePositiveDegree
= fRotationAngle
;
451 while(fAnglePositiveDegree
<0.0)
452 fAnglePositiveDegree
+=360.0;
454 switch(eLabelAlignment
)
456 case LABEL_ALIGN_LEFT
:
457 lcl_correctRotation_Left( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
459 case LABEL_ALIGN_RIGHT
:
460 lcl_correctRotation_Right( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
462 case LABEL_ALIGN_TOP
:
463 lcl_correctRotation_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
465 case LABEL_ALIGN_BOTTOM
:
466 lcl_correctRotation_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
468 case LABEL_ALIGN_LEFT_TOP
:
469 lcl_correctRotation_Left_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
471 case LABEL_ALIGN_LEFT_BOTTOM
:
472 lcl_correctRotation_Left_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
474 case LABEL_ALIGN_RIGHT_TOP
:
475 lcl_correctRotation_Right_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
477 case LABEL_ALIGN_RIGHT_BOTTOM
:
478 lcl_correctRotation_Right_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
480 default: //LABEL_ALIGN_CENTER
484 xShape2DText
->setPosition( awt::Point(
485 static_cast<sal_Int32
>(aOldPos
.X
+ fXCorrection
)
486 , static_cast<sal_Int32
>(aOldPos
.Y
+ fYCorrection
) ) );
489 //.............................................................................
491 //.............................................................................