1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "RelativePositionHelper.hxx"
31 #include <rtl/math.hxx>
33 using namespace ::com::sun::star
;
38 chart2::RelativePosition
RelativePositionHelper::getReanchoredPosition(
39 const chart2::RelativePosition
& rPosition
,
40 const chart2::RelativeSize
& rObjectSize
,
41 drawing::Alignment aNewAnchor
)
43 chart2::RelativePosition
aResult( rPosition
);
44 if( rPosition
.Anchor
!= aNewAnchor
)
46 sal_Int32 nShiftHalfWidths
= 0;
47 sal_Int32 nShiftHalfHeights
= 0;
49 // normalize to top-left
50 switch( rPosition
.Anchor
)
52 case drawing::Alignment_TOP_LEFT
:
54 case drawing::Alignment_LEFT
:
55 nShiftHalfHeights
-= 1;
57 case drawing::Alignment_BOTTOM_LEFT
:
58 nShiftHalfHeights
-= 2;
60 case drawing::Alignment_TOP
:
61 nShiftHalfWidths
-= 1;
63 case drawing::Alignment_CENTER
:
64 nShiftHalfWidths
-= 1;
65 nShiftHalfHeights
-= 1;
67 case drawing::Alignment_BOTTOM
:
68 nShiftHalfWidths
-= 1;
69 nShiftHalfHeights
-= 2;
71 case drawing::Alignment_TOP_RIGHT
:
72 nShiftHalfWidths
-= 2;
74 case drawing::Alignment_RIGHT
:
75 nShiftHalfWidths
-= 2;
76 nShiftHalfHeights
-= 1;
78 case drawing::Alignment_BOTTOM_RIGHT
:
79 nShiftHalfWidths
-= 2;
80 nShiftHalfHeights
-= 2;
82 case drawing::Alignment_MAKE_FIXED_SIZE
:
89 case drawing::Alignment_TOP_LEFT
:
91 case drawing::Alignment_LEFT
:
92 nShiftHalfHeights
+= 1;
94 case drawing::Alignment_BOTTOM_LEFT
:
95 nShiftHalfHeights
+= 2;
97 case drawing::Alignment_TOP
:
98 nShiftHalfWidths
+= 1;
100 case drawing::Alignment_CENTER
:
101 nShiftHalfWidths
+= 1;
102 nShiftHalfHeights
+= 1;
104 case drawing::Alignment_BOTTOM
:
105 nShiftHalfWidths
+= 1;
106 nShiftHalfHeights
+= 2;
108 case drawing::Alignment_TOP_RIGHT
:
109 nShiftHalfWidths
+= 2;
111 case drawing::Alignment_RIGHT
:
112 nShiftHalfWidths
+= 2;
113 nShiftHalfHeights
+= 1;
115 case drawing::Alignment_BOTTOM_RIGHT
:
116 nShiftHalfWidths
+= 2;
117 nShiftHalfHeights
+= 2;
119 case drawing::Alignment_MAKE_FIXED_SIZE
:
123 if( nShiftHalfWidths
!= 0 )
124 aResult
.Primary
+= (rObjectSize
.Primary
/ 2.0) * nShiftHalfWidths
;
125 if( nShiftHalfHeights
!= 0 )
126 aResult
.Secondary
+= (rObjectSize
.Secondary
/ 2.0) * nShiftHalfHeights
;
133 awt::Point
RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
135 , awt::Size aObjectSize
136 , drawing::Alignment aAnchor
)
138 awt::Point
aResult( aPoint
);
140 double fXDelta
= 0.0;
141 double fYDelta
= 0.0;
146 case drawing::Alignment_TOP
:
147 case drawing::Alignment_CENTER
:
148 case drawing::Alignment_BOTTOM
:
149 fXDelta
-= static_cast< double >( aObjectSize
.Width
) / 2.0;
151 case drawing::Alignment_TOP_RIGHT
:
152 case drawing::Alignment_RIGHT
:
153 case drawing::Alignment_BOTTOM_RIGHT
:
154 fXDelta
-= aObjectSize
.Width
;
156 case drawing::Alignment_TOP_LEFT
:
157 case drawing::Alignment_LEFT
:
158 case drawing::Alignment_BOTTOM_LEFT
:
167 case drawing::Alignment_LEFT
:
168 case drawing::Alignment_CENTER
:
169 case drawing::Alignment_RIGHT
:
170 fYDelta
-= static_cast< double >( aObjectSize
.Height
) / 2.0;
172 case drawing::Alignment_BOTTOM_LEFT
:
173 case drawing::Alignment_BOTTOM
:
174 case drawing::Alignment_BOTTOM_RIGHT
:
175 fYDelta
-= aObjectSize
.Height
;
177 case drawing::Alignment_TOP_LEFT
:
178 case drawing::Alignment_TOP
:
179 case drawing::Alignment_TOP_RIGHT
:
185 aResult
.X
+= static_cast< sal_Int32
>( ::rtl::math::round( fXDelta
));
186 aResult
.Y
+= static_cast< sal_Int32
>( ::rtl::math::round( fYDelta
));
191 awt::Point
RelativePositionHelper::getCenterOfAnchoredObject(
193 , awt::Size aUnrotatedObjectSize
194 , drawing::Alignment aAnchor
197 awt::Point
aResult( aPoint
);
199 double fXDelta
= 0.0;
200 double fYDelta
= 0.0;
205 case drawing::Alignment_TOP
:
206 case drawing::Alignment_CENTER
:
207 case drawing::Alignment_BOTTOM
:
210 case drawing::Alignment_TOP_RIGHT
:
211 case drawing::Alignment_RIGHT
:
212 case drawing::Alignment_BOTTOM_RIGHT
:
213 fXDelta
-= aUnrotatedObjectSize
.Width
/2;
215 case drawing::Alignment_TOP_LEFT
:
216 case drawing::Alignment_LEFT
:
217 case drawing::Alignment_BOTTOM_LEFT
:
219 fXDelta
+= aUnrotatedObjectSize
.Width
/2;
226 case drawing::Alignment_LEFT
:
227 case drawing::Alignment_CENTER
:
228 case drawing::Alignment_RIGHT
:
231 case drawing::Alignment_BOTTOM_LEFT
:
232 case drawing::Alignment_BOTTOM
:
233 case drawing::Alignment_BOTTOM_RIGHT
:
234 fYDelta
-= aUnrotatedObjectSize
.Height
/2;
236 case drawing::Alignment_TOP_LEFT
:
237 case drawing::Alignment_TOP
:
238 case drawing::Alignment_TOP_RIGHT
:
239 fYDelta
+= aUnrotatedObjectSize
.Height
/2;
245 //take rotation into account:
246 aResult
.X
+= static_cast< sal_Int32
>(
247 ::rtl::math::round( fXDelta
* rtl::math::cos( fAnglePi
) + fYDelta
* rtl::math::sin( fAnglePi
) ) );
248 aResult
.Y
+= static_cast< sal_Int32
>(
249 ::rtl::math::round( - fXDelta
* rtl::math::sin( fAnglePi
) + fYDelta
* rtl::math::cos( fAnglePi
) ) );
254 bool RelativePositionHelper::centerGrow(
255 chart2::RelativePosition
& rInOutPosition
,
256 chart2::RelativeSize
& rInOutSize
,
257 double fAmountX
, double fAmountY
,
258 bool bCheck
/* = true */ )
260 chart2::RelativePosition
aPos( rInOutPosition
);
261 chart2::RelativeSize
aSize( rInOutSize
);
262 const double fPosCheckThreshold
= 0.02;
263 const double fSizeCheckThreshold
= 0.1;
265 // grow/shrink, back to relaative
266 aSize
.Primary
+= fAmountX
;
267 aSize
.Secondary
+= fAmountY
;
269 double fShiftAmountX
= fAmountX
/ 2.0;
270 double fShiftAmountY
= fAmountY
/ 2.0;
273 switch( rInOutPosition
.Anchor
)
275 case drawing::Alignment_TOP_LEFT
:
276 case drawing::Alignment_LEFT
:
277 case drawing::Alignment_BOTTOM_LEFT
:
278 aPos
.Primary
-= fShiftAmountX
;
280 case drawing::Alignment_TOP
:
281 case drawing::Alignment_CENTER
:
282 case drawing::Alignment_BOTTOM
:
285 case drawing::Alignment_TOP_RIGHT
:
286 case drawing::Alignment_RIGHT
:
287 case drawing::Alignment_BOTTOM_RIGHT
:
288 aPos
.Primary
+= fShiftAmountX
;
290 case drawing::Alignment_MAKE_FIXED_SIZE
:
295 switch( rInOutPosition
.Anchor
)
297 case drawing::Alignment_TOP
:
298 case drawing::Alignment_TOP_LEFT
:
299 case drawing::Alignment_TOP_RIGHT
:
300 aPos
.Secondary
-= fShiftAmountY
;
302 case drawing::Alignment_CENTER
:
303 case drawing::Alignment_LEFT
:
304 case drawing::Alignment_RIGHT
:
307 case drawing::Alignment_BOTTOM
:
308 case drawing::Alignment_BOTTOM_LEFT
:
309 case drawing::Alignment_BOTTOM_RIGHT
:
310 aPos
.Secondary
+= fShiftAmountY
;
312 case drawing::Alignment_MAKE_FIXED_SIZE
:
316 // anchor must not be changed
317 OSL_ASSERT( rInOutPosition
.Anchor
== aPos
.Anchor
);
319 if( rInOutPosition
.Primary
== aPos
.Primary
&&
320 rInOutPosition
.Secondary
== aPos
.Secondary
&&
321 rInOutSize
.Primary
== aSize
.Primary
&&
322 rInOutSize
.Secondary
== aSize
.Secondary
)
328 // Note: this somewhat complicated check allows the output being
329 // out-of-bounds if the input was also out-of-bounds, and the change is
330 // for "advantage". E.g., you have a chart that laps out on the left
331 // side. If you shrink it, this should be possible, also if it still
332 // laps out on the left side afterwards. But you shouldn't be able to
335 chart2::RelativePosition
aUpperLeft(
336 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_TOP_LEFT
));
337 chart2::RelativePosition
aLowerRight(
338 RelativePositionHelper::getReanchoredPosition( aPos
, aSize
, drawing::Alignment_BOTTOM_RIGHT
));
340 // Do not grow, if this leads to corners being off-screen
341 if( fAmountX
> 0.0 &&
342 ( (aUpperLeft
.Primary
< fPosCheckThreshold
) ||
343 (aLowerRight
.Primary
> (1.0 - fPosCheckThreshold
)) ))
345 if( fAmountY
> 0.0 &&
346 ( (aUpperLeft
.Secondary
< fPosCheckThreshold
) ||
347 (aLowerRight
.Secondary
> (1.0 - fPosCheckThreshold
)) ))
350 // Do not shrink, if this leads to a size too small
351 if( fAmountX
< 0.0 &&
352 ( aSize
.Primary
< fSizeCheckThreshold
))
354 if( fAmountY
< 0.0 &&
355 ( aSize
.Secondary
< fSizeCheckThreshold
))
359 rInOutPosition
= aPos
;
364 bool RelativePositionHelper::moveObject(
365 chart2::RelativePosition
& rInOutPosition
,
366 const chart2::RelativeSize
& rObjectSize
,
367 double fAmountX
, double fAmountY
,
368 bool bCheck
/* = true */ )
370 chart2::RelativePosition
aPos( rInOutPosition
);
371 aPos
.Primary
+= fAmountX
;
372 aPos
.Secondary
+= fAmountY
;
373 const double fPosCheckThreshold
= 0.02;
377 chart2::RelativePosition
aUpperLeft(
378 RelativePositionHelper::getReanchoredPosition( aPos
, rObjectSize
, drawing::Alignment_TOP_LEFT
));
379 chart2::RelativePosition
aLowerRight( aUpperLeft
);
380 aLowerRight
.Primary
+= rObjectSize
.Primary
;
381 aLowerRight
.Secondary
+= rObjectSize
.Secondary
;
383 const double fFarEdgeThreshold
= 1.0 - fPosCheckThreshold
;
384 if( ( fAmountX
> 0.0 && (aLowerRight
.Primary
> fFarEdgeThreshold
)) ||
385 ( fAmountX
< 0.0 && (aUpperLeft
.Primary
< fPosCheckThreshold
)) ||
386 ( fAmountY
> 0.0 && (aLowerRight
.Secondary
> fFarEdgeThreshold
)) ||
387 ( fAmountY
< 0.0 && (aUpperLeft
.Secondary
< fPosCheckThreshold
)) )
391 rInOutPosition
= aPos
;
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */