1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
31 #include "RelativePositionHelper.hxx"
32 #include <rtl/math.hxx>
34 using namespace ::com::sun::star
;
40 chart2::RelativePosition
RelativePositionHelper::getReanchoredPosition(
41 const chart2::RelativePosition
& rPosition
,
42 const chart2::RelativeSize
& rObjectSize
,
43 drawing::Alignment aNewAnchor
)
45 chart2::RelativePosition
aResult( rPosition
);
46 if( rPosition
.Anchor
!= aNewAnchor
)
48 sal_Int32 nShiftHalfWidths
= 0;
49 sal_Int32 nShiftHalfHeights
= 0;
51 // normalize to top-left
52 switch( rPosition
.Anchor
)
54 case drawing::Alignment_TOP_LEFT
:
56 case drawing::Alignment_LEFT
:
57 nShiftHalfHeights
-= 1;
59 case drawing::Alignment_BOTTOM_LEFT
:
60 nShiftHalfHeights
-= 2;
62 case drawing::Alignment_TOP
:
63 nShiftHalfWidths
-= 1;
65 case drawing::Alignment_CENTER
:
66 nShiftHalfWidths
-= 1;
67 nShiftHalfHeights
-= 1;
69 case drawing::Alignment_BOTTOM
:
70 nShiftHalfWidths
-= 1;
71 nShiftHalfHeights
-= 2;
73 case drawing::Alignment_TOP_RIGHT
:
74 nShiftHalfWidths
-= 2;
76 case drawing::Alignment_RIGHT
:
77 nShiftHalfWidths
-= 2;
78 nShiftHalfHeights
-= 1;
80 case drawing::Alignment_BOTTOM_RIGHT
:
81 nShiftHalfWidths
-= 2;
82 nShiftHalfHeights
-= 2;
84 case drawing::Alignment_MAKE_FIXED_SIZE
:
91 case drawing::Alignment_TOP_LEFT
:
93 case drawing::Alignment_LEFT
:
94 nShiftHalfHeights
+= 1;
96 case drawing::Alignment_BOTTOM_LEFT
:
97 nShiftHalfHeights
+= 2;
99 case drawing::Alignment_TOP
:
100 nShiftHalfWidths
+= 1;
102 case drawing::Alignment_CENTER
:
103 nShiftHalfWidths
+= 1;
104 nShiftHalfHeights
+= 1;
106 case drawing::Alignment_BOTTOM
:
107 nShiftHalfWidths
+= 1;
108 nShiftHalfHeights
+= 2;
110 case drawing::Alignment_TOP_RIGHT
:
111 nShiftHalfWidths
+= 2;
113 case drawing::Alignment_RIGHT
:
114 nShiftHalfWidths
+= 2;
115 nShiftHalfHeights
+= 1;
117 case drawing::Alignment_BOTTOM_RIGHT
:
118 nShiftHalfWidths
+= 2;
119 nShiftHalfHeights
+= 2;
121 case drawing::Alignment_MAKE_FIXED_SIZE
:
125 if( nShiftHalfWidths
!= 0 )
126 aResult
.Primary
+= (rObjectSize
.Primary
/ 2.0) * nShiftHalfWidths
;
127 if( nShiftHalfHeights
!= 0 )
128 aResult
.Secondary
+= (rObjectSize
.Secondary
/ 2.0) * nShiftHalfHeights
;
136 awt::Point
RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
138 , awt::Size aObjectSize
139 , drawing::Alignment aAnchor
)
141 awt::Point
aResult( aPoint
);
143 double fXDelta
= 0.0;
144 double fYDelta
= 0.0;
149 case drawing::Alignment_TOP
:
150 case drawing::Alignment_CENTER
:
151 case drawing::Alignment_BOTTOM
:
152 fXDelta
-= static_cast< double >( aObjectSize
.Width
) / 2.0;
154 case drawing::Alignment_TOP_RIGHT
:
155 case drawing::Alignment_RIGHT
:
156 case drawing::Alignment_BOTTOM_RIGHT
:
157 fXDelta
-= aObjectSize
.Width
;
159 case drawing::Alignment_TOP_LEFT
:
160 case drawing::Alignment_LEFT
:
161 case drawing::Alignment_BOTTOM_LEFT
:
170 case drawing::Alignment_LEFT
:
171 case drawing::Alignment_CENTER
:
172 case drawing::Alignment_RIGHT
:
173 fYDelta
-= static_cast< double >( aObjectSize
.Height
) / 2.0;
175 case drawing::Alignment_BOTTOM_LEFT
:
176 case drawing::Alignment_BOTTOM
:
177 case drawing::Alignment_BOTTOM_RIGHT
:
178 fYDelta
-= aObjectSize
.Height
;
180 case drawing::Alignment_TOP_LEFT
:
181 case drawing::Alignment_TOP
:
182 case drawing::Alignment_TOP_RIGHT
:
188 aResult
.X
+= static_cast< sal_Int32
>( ::rtl::math::round( fXDelta
));
189 aResult
.Y
+= static_cast< sal_Int32
>( ::rtl::math::round( fYDelta
));
195 awt::Point
RelativePositionHelper::getCenterOfAnchoredObject(
197 , awt::Size aUnrotatedObjectSize
198 , drawing::Alignment aAnchor
201 awt::Point
aResult( aPoint
);
203 double fXDelta
= 0.0;
204 double fYDelta
= 0.0;
209 case drawing::Alignment_TOP
:
210 case drawing::Alignment_CENTER
:
211 case drawing::Alignment_BOTTOM
:
214 case drawing::Alignment_TOP_RIGHT
:
215 case drawing::Alignment_RIGHT
:
216 case drawing::Alignment_BOTTOM_RIGHT
:
217 fXDelta
-= aUnrotatedObjectSize
.Width
/2;
219 case drawing::Alignment_TOP_LEFT
:
220 case drawing::Alignment_LEFT
:
221 case drawing::Alignment_BOTTOM_LEFT
:
223 fXDelta
+= aUnrotatedObjectSize
.Width
/2;
230 case drawing::Alignment_LEFT
:
231 case drawing::Alignment_CENTER
:
232 case drawing::Alignment_RIGHT
:
235 case drawing::Alignment_BOTTOM_LEFT
:
236 case drawing::Alignment_BOTTOM
:
237 case drawing::Alignment_BOTTOM_RIGHT
:
238 fYDelta
-= aUnrotatedObjectSize
.Height
/2;
240 case drawing::Alignment_TOP_LEFT
:
241 case drawing::Alignment_TOP
:
242 case drawing::Alignment_TOP_RIGHT
:
243 fYDelta
+= aUnrotatedObjectSize
.Height
/2;
249 //take rotation into account:
250 aResult
.X
+= static_cast< sal_Int32
>(
251 ::rtl::math::round( fXDelta
* rtl::math::cos( fAnglePi
) + fYDelta
* rtl::math::sin( fAnglePi
) ) );
252 aResult
.Y
+= static_cast< sal_Int32
>(
253 ::rtl::math::round( - fXDelta
* rtl::math::sin( fAnglePi
) + fYDelta
* rtl::math::cos( fAnglePi
) ) );
258 bool RelativePositionHelper::centerGrow(
259 chart2::RelativePosition
& rInOutPosition
,
260 chart2::RelativeSize
& rInOutSize
,
261 double fAmountX
, double fAmountY
,
262 bool bCheck
/* = true */ )
264 chart2::RelativePosition
aPos( rInOutPosition
);
265 chart2::RelativeSize
aSize( rInOutSize
);
266 const double fPosCheckThreshold
= 0.02;
267 const double fSizeCheckThreshold
= 0.1;
269 // grow/shrink, back to relaative
270 aSize
.Primary
+= fAmountX
;
271 aSize
.Secondary
+= fAmountY
;
273 double fShiftAmountX
= fAmountX
/ 2.0;
274 double fShiftAmountY
= fAmountY
/ 2.0;
277 switch( rInOutPosition
.Anchor
)
279 case drawing::Alignment_TOP_LEFT
:
280 case drawing::Alignment_LEFT
:
281 case drawing::Alignment_BOTTOM_LEFT
:
282 aPos
.Primary
-= fShiftAmountX
;
284 case drawing::Alignment_TOP
:
285 case drawing::Alignment_CENTER
:
286 case drawing::Alignment_BOTTOM
:
289 case drawing::Alignment_TOP_RIGHT
:
290 case drawing::Alignment_RIGHT
:
291 case drawing::Alignment_BOTTOM_RIGHT
:
292 aPos
.Primary
+= fShiftAmountX
;
294 case drawing::Alignment_MAKE_FIXED_SIZE
:
299 switch( rInOutPosition
.Anchor
)
301 case drawing::Alignment_TOP
:
302 case drawing::Alignment_TOP_LEFT
:
303 case drawing::Alignment_TOP_RIGHT
:
304 aPos
.Secondary
-= fShiftAmountY
;
306 case drawing::Alignment_CENTER
:
307 case drawing::Alignment_LEFT
:
308 case drawing::Alignment_RIGHT
:
311 case drawing::Alignment_BOTTOM
:
312 case drawing::Alignment_BOTTOM_LEFT
:
313 case drawing::Alignment_BOTTOM_RIGHT
:
314 aPos
.Secondary
+= fShiftAmountY
;
316 case drawing::Alignment_MAKE_FIXED_SIZE
:
320 // anchor must not be changed
321 OSL_ASSERT( rInOutPosition
.Anchor
== aPos
.Anchor
);
323 if( rInOutPosition
.Primary
== aPos
.Primary
&&
324 rInOutPosition
.Secondary
== aPos
.Secondary
&&
325 rInOutSize
.Primary
== aSize
.Primary
&&
326 rInOutSize
.Secondary
== aSize
.Secondary
)
332 // Note: this somewhat complicated check allows the output being
333 // out-of-bounds if the input was also out-of-bounds, and the change is
334 // for "advantage". E.g., you have a chart that laps out on the left
335 // side. If you shrink it, this should be possible, also if it still
336 // laps out on the left side afterwards. But you shouldn't be able to
339 chart2::RelativePosition
aUpperLeft(
340 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_TOP_LEFT
));
341 chart2::RelativePosition
aLowerRight(
342 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_BOTTOM_RIGHT
));
344 // Do not grow, if this leads to corners being off-screen
345 if( fAmountX
> 0.0 &&
346 ( (aUpperLeft
.Primary
< fPosCheckThreshold
) ||
347 (aLowerRight
.Primary
> (1.0 - fPosCheckThreshold
)) ))
349 if( fAmountY
> 0.0 &&
350 ( (aUpperLeft
.Secondary
< fPosCheckThreshold
) ||
351 (aLowerRight
.Secondary
> (1.0 - fPosCheckThreshold
)) ))
354 // Do not shrink, if this leads to a size too small
355 if( fAmountX
< 0.0 &&
356 ( aSize
.Primary
< fSizeCheckThreshold
))
358 if( fAmountY
< 0.0 &&
359 ( aSize
.Secondary
< fSizeCheckThreshold
))
363 rInOutPosition
= aPos
;
368 bool RelativePositionHelper::moveObject(
369 chart2::RelativePosition
& rInOutPosition
,
370 const chart2::RelativeSize
& rObjectSize
,
371 double fAmountX
, double fAmountY
,
372 bool bCheck
/* = true */ )
374 chart2::RelativePosition
aPos( rInOutPosition
);
375 aPos
.Primary
+= fAmountX
;
376 aPos
.Secondary
+= fAmountY
;
377 const double fPosCheckThreshold
= 0.02;
381 chart2::RelativePosition
aUpperLeft(
382 RelativePositionHelper::getReanchoredPosition( aPos
, rObjectSize
, drawing::Alignment_TOP_LEFT
));
383 chart2::RelativePosition
aLowerRight( aUpperLeft
);
384 aLowerRight
.Primary
+= rObjectSize
.Primary
;
385 aLowerRight
.Secondary
+= rObjectSize
.Secondary
;
387 const double fFarEdgeThreshold
= 1.0 - fPosCheckThreshold
;
388 if( ( fAmountX
> 0.0 && (aLowerRight
.Primary
> fFarEdgeThreshold
)) ||
389 ( fAmountX
< 0.0 && (aUpperLeft
.Primary
< fPosCheckThreshold
)) ||
390 ( fAmountY
> 0.0 && (aLowerRight
.Secondary
> fFarEdgeThreshold
)) ||
391 ( fAmountY
< 0.0 && (aUpperLeft
.Secondary
< fPosCheckThreshold
)) )
395 rInOutPosition
= aPos
;