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: RelativePositionHelper.cxx,v $
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 "RelativePositionHelper.hxx"
35 #include <rtl/math.hxx>
37 using namespace ::com::sun::star
;
43 chart2::RelativePosition
RelativePositionHelper::getReanchoredPosition(
44 const chart2::RelativePosition
& rPosition
,
45 const chart2::RelativeSize
& rObjectSize
,
46 drawing::Alignment aNewAnchor
)
48 chart2::RelativePosition
aResult( rPosition
);
49 if( rPosition
.Anchor
!= aNewAnchor
)
51 sal_Int32 nShiftHalfWidths
= 0;
52 sal_Int32 nShiftHalfHeights
= 0;
54 // normalize to top-left
55 switch( rPosition
.Anchor
)
57 case drawing::Alignment_TOP_LEFT
:
59 case drawing::Alignment_LEFT
:
60 nShiftHalfHeights
-= 1;
62 case drawing::Alignment_BOTTOM_LEFT
:
63 nShiftHalfHeights
-= 2;
65 case drawing::Alignment_TOP
:
66 nShiftHalfWidths
-= 1;
68 case drawing::Alignment_CENTER
:
69 nShiftHalfWidths
-= 1;
70 nShiftHalfHeights
-= 1;
72 case drawing::Alignment_BOTTOM
:
73 nShiftHalfWidths
-= 1;
74 nShiftHalfHeights
-= 2;
76 case drawing::Alignment_TOP_RIGHT
:
77 nShiftHalfWidths
-= 2;
79 case drawing::Alignment_RIGHT
:
80 nShiftHalfWidths
-= 2;
81 nShiftHalfHeights
-= 1;
83 case drawing::Alignment_BOTTOM_RIGHT
:
84 nShiftHalfWidths
-= 2;
85 nShiftHalfHeights
-= 2;
87 case drawing::Alignment_MAKE_FIXED_SIZE
:
94 case drawing::Alignment_TOP_LEFT
:
96 case drawing::Alignment_LEFT
:
97 nShiftHalfHeights
+= 1;
99 case drawing::Alignment_BOTTOM_LEFT
:
100 nShiftHalfHeights
+= 2;
102 case drawing::Alignment_TOP
:
103 nShiftHalfWidths
+= 1;
105 case drawing::Alignment_CENTER
:
106 nShiftHalfWidths
+= 1;
107 nShiftHalfHeights
+= 1;
109 case drawing::Alignment_BOTTOM
:
110 nShiftHalfWidths
+= 1;
111 nShiftHalfHeights
+= 2;
113 case drawing::Alignment_TOP_RIGHT
:
114 nShiftHalfWidths
+= 2;
116 case drawing::Alignment_RIGHT
:
117 nShiftHalfWidths
+= 2;
118 nShiftHalfHeights
+= 1;
120 case drawing::Alignment_BOTTOM_RIGHT
:
121 nShiftHalfWidths
+= 2;
122 nShiftHalfHeights
+= 2;
124 case drawing::Alignment_MAKE_FIXED_SIZE
:
128 if( nShiftHalfWidths
!= 0 )
129 aResult
.Primary
+= (rObjectSize
.Primary
/ 2.0) * nShiftHalfWidths
;
130 if( nShiftHalfHeights
!= 0 )
131 aResult
.Secondary
+= (rObjectSize
.Secondary
/ 2.0) * nShiftHalfHeights
;
139 awt::Point
RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
141 , awt::Size aObjectSize
142 , drawing::Alignment aAnchor
)
144 awt::Point
aResult( aPoint
);
146 double fXDelta
= 0.0;
147 double fYDelta
= 0.0;
152 case drawing::Alignment_TOP
:
153 case drawing::Alignment_CENTER
:
154 case drawing::Alignment_BOTTOM
:
155 fXDelta
-= static_cast< double >( aObjectSize
.Width
) / 2.0;
157 case drawing::Alignment_TOP_RIGHT
:
158 case drawing::Alignment_RIGHT
:
159 case drawing::Alignment_BOTTOM_RIGHT
:
160 fXDelta
-= aObjectSize
.Width
;
162 case drawing::Alignment_TOP_LEFT
:
163 case drawing::Alignment_LEFT
:
164 case drawing::Alignment_BOTTOM_LEFT
:
173 case drawing::Alignment_LEFT
:
174 case drawing::Alignment_CENTER
:
175 case drawing::Alignment_RIGHT
:
176 fYDelta
-= static_cast< double >( aObjectSize
.Height
) / 2.0;
178 case drawing::Alignment_BOTTOM_LEFT
:
179 case drawing::Alignment_BOTTOM
:
180 case drawing::Alignment_BOTTOM_RIGHT
:
181 fYDelta
-= aObjectSize
.Height
;
183 case drawing::Alignment_TOP_LEFT
:
184 case drawing::Alignment_TOP
:
185 case drawing::Alignment_TOP_RIGHT
:
191 aResult
.X
+= static_cast< sal_Int32
>( ::rtl::math::round( fXDelta
));
192 aResult
.Y
+= static_cast< sal_Int32
>( ::rtl::math::round( fYDelta
));
198 awt::Point
RelativePositionHelper::getCenterOfAnchoredObject(
200 , awt::Size aUnrotatedObjectSize
201 , drawing::Alignment aAnchor
204 awt::Point
aResult( aPoint
);
206 double fXDelta
= 0.0;
207 double fYDelta
= 0.0;
212 case drawing::Alignment_TOP
:
213 case drawing::Alignment_CENTER
:
214 case drawing::Alignment_BOTTOM
:
217 case drawing::Alignment_TOP_RIGHT
:
218 case drawing::Alignment_RIGHT
:
219 case drawing::Alignment_BOTTOM_RIGHT
:
220 fXDelta
-= aUnrotatedObjectSize
.Width
/2;
222 case drawing::Alignment_TOP_LEFT
:
223 case drawing::Alignment_LEFT
:
224 case drawing::Alignment_BOTTOM_LEFT
:
226 fXDelta
+= aUnrotatedObjectSize
.Width
/2;
233 case drawing::Alignment_LEFT
:
234 case drawing::Alignment_CENTER
:
235 case drawing::Alignment_RIGHT
:
238 case drawing::Alignment_BOTTOM_LEFT
:
239 case drawing::Alignment_BOTTOM
:
240 case drawing::Alignment_BOTTOM_RIGHT
:
241 fYDelta
-= aUnrotatedObjectSize
.Height
/2;
243 case drawing::Alignment_TOP_LEFT
:
244 case drawing::Alignment_TOP
:
245 case drawing::Alignment_TOP_RIGHT
:
246 fYDelta
+= aUnrotatedObjectSize
.Height
/2;
252 //take rotation into account:
253 aResult
.X
+= static_cast< sal_Int32
>(
254 ::rtl::math::round( fXDelta
* rtl::math::cos( fAnglePi
) + fYDelta
* rtl::math::sin( fAnglePi
) ) );
255 aResult
.Y
+= static_cast< sal_Int32
>(
256 ::rtl::math::round( - fXDelta
* rtl::math::sin( fAnglePi
) + fYDelta
* rtl::math::cos( fAnglePi
) ) );
261 bool RelativePositionHelper::centerGrow(
262 chart2::RelativePosition
& rInOutPosition
,
263 chart2::RelativeSize
& rInOutSize
,
264 double fAmountX
, double fAmountY
,
265 bool bCheck
/* = true */ )
267 chart2::RelativePosition
aPos( rInOutPosition
);
268 chart2::RelativeSize
aSize( rInOutSize
);
269 const double fPosCheckThreshold
= 0.02;
270 const double fSizeCheckThreshold
= 0.1;
272 // grow/shrink, back to relaative
273 aSize
.Primary
+= fAmountX
;
274 aSize
.Secondary
+= fAmountY
;
276 double fShiftAmountX
= fAmountX
/ 2.0;
277 double fShiftAmountY
= fAmountY
/ 2.0;
280 switch( rInOutPosition
.Anchor
)
282 case drawing::Alignment_TOP_LEFT
:
283 case drawing::Alignment_LEFT
:
284 case drawing::Alignment_BOTTOM_LEFT
:
285 aPos
.Primary
-= fShiftAmountX
;
287 case drawing::Alignment_TOP
:
288 case drawing::Alignment_CENTER
:
289 case drawing::Alignment_BOTTOM
:
292 case drawing::Alignment_TOP_RIGHT
:
293 case drawing::Alignment_RIGHT
:
294 case drawing::Alignment_BOTTOM_RIGHT
:
295 aPos
.Primary
+= fShiftAmountX
;
297 case drawing::Alignment_MAKE_FIXED_SIZE
:
302 switch( rInOutPosition
.Anchor
)
304 case drawing::Alignment_TOP
:
305 case drawing::Alignment_TOP_LEFT
:
306 case drawing::Alignment_TOP_RIGHT
:
307 aPos
.Secondary
-= fShiftAmountY
;
309 case drawing::Alignment_CENTER
:
310 case drawing::Alignment_LEFT
:
311 case drawing::Alignment_RIGHT
:
314 case drawing::Alignment_BOTTOM
:
315 case drawing::Alignment_BOTTOM_LEFT
:
316 case drawing::Alignment_BOTTOM_RIGHT
:
317 aPos
.Secondary
+= fShiftAmountY
;
319 case drawing::Alignment_MAKE_FIXED_SIZE
:
323 // anchor must not be changed
324 OSL_ASSERT( rInOutPosition
.Anchor
== aPos
.Anchor
);
326 if( rInOutPosition
.Primary
== aPos
.Primary
&&
327 rInOutPosition
.Secondary
== aPos
.Secondary
&&
328 rInOutSize
.Primary
== aSize
.Primary
&&
329 rInOutSize
.Secondary
== aSize
.Secondary
)
335 // Note: this somewhat complicated check allows the output being
336 // out-of-bounds if the input was also out-of-bounds, and the change is
337 // for "advantage". E.g., you have a chart that laps out on the left
338 // side. If you shrink it, this should be possible, also if it still
339 // laps out on the left side afterwards. But you shouldn't be able to
342 chart2::RelativePosition
aUpperLeft(
343 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_TOP_LEFT
));
344 chart2::RelativePosition
aLowerRight(
345 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_BOTTOM_RIGHT
));
347 // Do not grow, if this leads to corners being off-screen
348 if( fAmountX
> 0.0 &&
349 ( (aUpperLeft
.Primary
< fPosCheckThreshold
) ||
350 (aLowerRight
.Primary
> (1.0 - fPosCheckThreshold
)) ))
352 if( fAmountY
> 0.0 &&
353 ( (aUpperLeft
.Secondary
< fPosCheckThreshold
) ||
354 (aLowerRight
.Secondary
> (1.0 - fPosCheckThreshold
)) ))
357 // Do not shrink, if this leads to a size too small
358 if( fAmountX
< 0.0 &&
359 ( aSize
.Primary
< fSizeCheckThreshold
))
361 if( fAmountY
< 0.0 &&
362 ( aSize
.Secondary
< fSizeCheckThreshold
))
366 rInOutPosition
= aPos
;
371 bool RelativePositionHelper::moveObject(
372 chart2::RelativePosition
& rInOutPosition
,
373 const chart2::RelativeSize
& rObjectSize
,
374 double fAmountX
, double fAmountY
,
375 bool bCheck
/* = true */ )
377 chart2::RelativePosition
aPos( rInOutPosition
);
378 aPos
.Primary
+= fAmountX
;
379 aPos
.Secondary
+= fAmountY
;
380 const double fPosCheckThreshold
= 0.02;
384 chart2::RelativePosition
aUpperLeft(
385 RelativePositionHelper::getReanchoredPosition( aPos
, rObjectSize
, drawing::Alignment_TOP_LEFT
));
386 chart2::RelativePosition
aLowerRight( aUpperLeft
);
387 aLowerRight
.Primary
+= rObjectSize
.Primary
;
388 aLowerRight
.Secondary
+= rObjectSize
.Secondary
;
390 const double fFarEdgeThreshold
= 1.0 - fPosCheckThreshold
;
391 if( ( fAmountX
> 0.0 && (aLowerRight
.Primary
> fFarEdgeThreshold
)) ||
392 ( fAmountX
< 0.0 && (aUpperLeft
.Primary
< fPosCheckThreshold
)) ||
393 ( fAmountY
> 0.0 && (aLowerRight
.Secondary
> fFarEdgeThreshold
)) ||
394 ( fAmountY
< 0.0 && (aUpperLeft
.Secondary
< fPosCheckThreshold
)) )
398 rInOutPosition
= aPos
;