Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include "RelativePositionHelper.hxx"
22 : : #include <rtl/math.hxx>
23 : :
24 : : using namespace ::com::sun::star;
25 : :
26 : : namespace chart
27 : : {
28 : :
29 : 0 : chart2::RelativePosition RelativePositionHelper::getReanchoredPosition(
30 : : const chart2::RelativePosition & rPosition,
31 : : const chart2::RelativeSize & rObjectSize,
32 : : drawing::Alignment aNewAnchor )
33 : : {
34 : 0 : chart2::RelativePosition aResult( rPosition );
35 [ # # ]: 0 : if( rPosition.Anchor != aNewAnchor )
36 : : {
37 : 0 : sal_Int32 nShiftHalfWidths = 0;
38 : 0 : sal_Int32 nShiftHalfHeights = 0;
39 : :
40 : : // normalize to top-left
41 [ # # # # : 0 : switch( rPosition.Anchor )
# # # # #
# # ]
42 : : {
43 : : case drawing::Alignment_TOP_LEFT:
44 : 0 : break;
45 : : case drawing::Alignment_LEFT:
46 : 0 : nShiftHalfHeights -= 1;
47 : 0 : break;
48 : : case drawing::Alignment_BOTTOM_LEFT:
49 : 0 : nShiftHalfHeights -= 2;
50 : 0 : break;
51 : : case drawing::Alignment_TOP:
52 : 0 : nShiftHalfWidths -= 1;
53 : 0 : break;
54 : : case drawing::Alignment_CENTER:
55 : 0 : nShiftHalfWidths -= 1;
56 : 0 : nShiftHalfHeights -= 1;
57 : 0 : break;
58 : : case drawing::Alignment_BOTTOM:
59 : 0 : nShiftHalfWidths -= 1;
60 : 0 : nShiftHalfHeights -= 2;
61 : 0 : break;
62 : : case drawing::Alignment_TOP_RIGHT:
63 : 0 : nShiftHalfWidths -= 2;
64 : 0 : break;
65 : : case drawing::Alignment_RIGHT:
66 : 0 : nShiftHalfWidths -= 2;
67 : 0 : nShiftHalfHeights -= 1;
68 : 0 : break;
69 : : case drawing::Alignment_BOTTOM_RIGHT:
70 : 0 : nShiftHalfWidths -= 2;
71 : 0 : nShiftHalfHeights -= 2;
72 : 0 : break;
73 : : case drawing::Alignment_MAKE_FIXED_SIZE:
74 : 0 : break;
75 : : }
76 : :
77 : : // transform
78 [ # # # # : 0 : switch( aNewAnchor )
# # # # #
# # ]
79 : : {
80 : : case drawing::Alignment_TOP_LEFT:
81 : 0 : break;
82 : : case drawing::Alignment_LEFT:
83 : 0 : nShiftHalfHeights += 1;
84 : 0 : break;
85 : : case drawing::Alignment_BOTTOM_LEFT:
86 : 0 : nShiftHalfHeights += 2;
87 : 0 : break;
88 : : case drawing::Alignment_TOP:
89 : 0 : nShiftHalfWidths += 1;
90 : 0 : break;
91 : : case drawing::Alignment_CENTER:
92 : 0 : nShiftHalfWidths += 1;
93 : 0 : nShiftHalfHeights += 1;
94 : 0 : break;
95 : : case drawing::Alignment_BOTTOM:
96 : 0 : nShiftHalfWidths += 1;
97 : 0 : nShiftHalfHeights += 2;
98 : 0 : break;
99 : : case drawing::Alignment_TOP_RIGHT:
100 : 0 : nShiftHalfWidths += 2;
101 : 0 : break;
102 : : case drawing::Alignment_RIGHT:
103 : 0 : nShiftHalfWidths += 2;
104 : 0 : nShiftHalfHeights += 1;
105 : 0 : break;
106 : : case drawing::Alignment_BOTTOM_RIGHT:
107 : 0 : nShiftHalfWidths += 2;
108 : 0 : nShiftHalfHeights += 2;
109 : 0 : break;
110 : : case drawing::Alignment_MAKE_FIXED_SIZE:
111 : 0 : break;
112 : : }
113 : :
114 [ # # ]: 0 : if( nShiftHalfWidths != 0 )
115 : 0 : aResult.Primary += (rObjectSize.Primary / 2.0) * nShiftHalfWidths;
116 [ # # ]: 0 : if( nShiftHalfHeights != 0 )
117 : 0 : aResult.Secondary += (rObjectSize.Secondary / 2.0) * nShiftHalfHeights;
118 : : }
119 : :
120 : 0 : return aResult;
121 : : }
122 : :
123 : :
124 : 1676 : awt::Point RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
125 : : awt::Point aPoint
126 : : , awt::Size aObjectSize
127 : : , drawing::Alignment aAnchor )
128 : : {
129 : 1676 : awt::Point aResult( aPoint );
130 : :
131 : 1676 : double fXDelta = 0.0;
132 : 1676 : double fYDelta = 0.0;
133 : :
134 : : // adapt x-value
135 [ - + + ]: 1676 : switch( aAnchor )
136 : : {
137 : : case drawing::Alignment_TOP:
138 : : case drawing::Alignment_CENTER:
139 : : case drawing::Alignment_BOTTOM:
140 : 0 : fXDelta -= static_cast< double >( aObjectSize.Width ) / 2.0;
141 : 0 : break;
142 : : case drawing::Alignment_TOP_RIGHT:
143 : : case drawing::Alignment_RIGHT:
144 : : case drawing::Alignment_BOTTOM_RIGHT:
145 : 953 : fXDelta -= aObjectSize.Width;
146 : 953 : break;
147 : : case drawing::Alignment_TOP_LEFT:
148 : : case drawing::Alignment_LEFT:
149 : : case drawing::Alignment_BOTTOM_LEFT:
150 : : default:
151 : : // nothing to do
152 : 723 : break;
153 : : }
154 : :
155 : : // adapt y-value
156 [ + - + ]: 1676 : switch( aAnchor )
157 : : {
158 : : case drawing::Alignment_LEFT:
159 : : case drawing::Alignment_CENTER:
160 : : case drawing::Alignment_RIGHT:
161 : 953 : fYDelta -= static_cast< double >( aObjectSize.Height ) / 2.0;
162 : 953 : break;
163 : : case drawing::Alignment_BOTTOM_LEFT:
164 : : case drawing::Alignment_BOTTOM:
165 : : case drawing::Alignment_BOTTOM_RIGHT:
166 : 0 : fYDelta -= aObjectSize.Height;
167 : 0 : break;
168 : : case drawing::Alignment_TOP_LEFT:
169 : : case drawing::Alignment_TOP:
170 : : case drawing::Alignment_TOP_RIGHT:
171 : : default:
172 : : // nothing to do
173 : 723 : break;
174 : : }
175 : :
176 : 1676 : aResult.X += static_cast< sal_Int32 >( ::rtl::math::round( fXDelta ));
177 : 1676 : aResult.Y += static_cast< sal_Int32 >( ::rtl::math::round( fYDelta ));
178 : :
179 : 1676 : return aResult;
180 : : }
181 : :
182 : 712 : awt::Point RelativePositionHelper::getCenterOfAnchoredObject(
183 : : awt::Point aPoint
184 : : , awt::Size aUnrotatedObjectSize
185 : : , drawing::Alignment aAnchor
186 : : , double fAnglePi )
187 : : {
188 : 712 : awt::Point aResult( aPoint );
189 : :
190 : 712 : double fXDelta = 0.0;
191 : 712 : double fYDelta = 0.0;
192 : :
193 : : // adapt x-value
194 [ - - + ]: 712 : switch( aAnchor )
195 : : {
196 : : case drawing::Alignment_TOP:
197 : : case drawing::Alignment_CENTER:
198 : : case drawing::Alignment_BOTTOM:
199 : : // nothing to do
200 : 0 : break;
201 : : case drawing::Alignment_TOP_RIGHT:
202 : : case drawing::Alignment_RIGHT:
203 : : case drawing::Alignment_BOTTOM_RIGHT:
204 : 0 : fXDelta -= aUnrotatedObjectSize.Width/2;
205 : 0 : break;
206 : : case drawing::Alignment_TOP_LEFT:
207 : : case drawing::Alignment_LEFT:
208 : : case drawing::Alignment_BOTTOM_LEFT:
209 : : default:
210 : 712 : fXDelta += aUnrotatedObjectSize.Width/2;
211 : 712 : break;
212 : : }
213 : :
214 : : // adapt y-value
215 [ - - + - ]: 712 : switch( aAnchor )
216 : : {
217 : : case drawing::Alignment_LEFT:
218 : : case drawing::Alignment_CENTER:
219 : : case drawing::Alignment_RIGHT:
220 : : // nothing to do
221 : 0 : break;
222 : : case drawing::Alignment_BOTTOM_LEFT:
223 : : case drawing::Alignment_BOTTOM:
224 : : case drawing::Alignment_BOTTOM_RIGHT:
225 : 0 : fYDelta -= aUnrotatedObjectSize.Height/2;
226 : 0 : break;
227 : : case drawing::Alignment_TOP_LEFT:
228 : : case drawing::Alignment_TOP:
229 : : case drawing::Alignment_TOP_RIGHT:
230 : 712 : fYDelta += aUnrotatedObjectSize.Height/2;
231 : : default:
232 : : // nothing to do
233 : 712 : break;
234 : : }
235 : :
236 : : //take rotation into account:
237 : : aResult.X += static_cast< sal_Int32 >(
238 : 712 : ::rtl::math::round( fXDelta * rtl::math::cos( fAnglePi ) + fYDelta * rtl::math::sin( fAnglePi ) ) );
239 : : aResult.Y += static_cast< sal_Int32 >(
240 : 712 : ::rtl::math::round( - fXDelta * rtl::math::sin( fAnglePi ) + fYDelta * rtl::math::cos( fAnglePi ) ) );
241 : :
242 : 712 : return aResult;
243 : : }
244 : :
245 : 0 : bool RelativePositionHelper::centerGrow(
246 : : chart2::RelativePosition & rInOutPosition,
247 : : chart2::RelativeSize & rInOutSize,
248 : : double fAmountX, double fAmountY,
249 : : bool bCheck /* = true */ )
250 : : {
251 : 0 : chart2::RelativePosition aPos( rInOutPosition );
252 : 0 : chart2::RelativeSize aSize( rInOutSize );
253 : 0 : const double fPosCheckThreshold = 0.02;
254 : 0 : const double fSizeCheckThreshold = 0.1;
255 : :
256 : : // grow/shrink, back to relaative
257 : 0 : aSize.Primary += fAmountX;
258 : 0 : aSize.Secondary += fAmountY;
259 : :
260 : 0 : double fShiftAmountX = fAmountX / 2.0;
261 : 0 : double fShiftAmountY = fAmountY / 2.0;
262 : :
263 : : // shift X
264 [ # # # # : 0 : switch( rInOutPosition.Anchor )
# ]
265 : : {
266 : : case drawing::Alignment_TOP_LEFT:
267 : : case drawing::Alignment_LEFT:
268 : : case drawing::Alignment_BOTTOM_LEFT:
269 : 0 : aPos.Primary -= fShiftAmountX;
270 : 0 : break;
271 : : case drawing::Alignment_TOP:
272 : : case drawing::Alignment_CENTER:
273 : : case drawing::Alignment_BOTTOM:
274 : : // nothing
275 : 0 : break;
276 : : case drawing::Alignment_TOP_RIGHT:
277 : : case drawing::Alignment_RIGHT:
278 : : case drawing::Alignment_BOTTOM_RIGHT:
279 : 0 : aPos.Primary += fShiftAmountX;
280 : 0 : break;
281 : : case drawing::Alignment_MAKE_FIXED_SIZE:
282 : 0 : break;
283 : : }
284 : :
285 : : // shift Y
286 [ # # # # : 0 : switch( rInOutPosition.Anchor )
# ]
287 : : {
288 : : case drawing::Alignment_TOP:
289 : : case drawing::Alignment_TOP_LEFT:
290 : : case drawing::Alignment_TOP_RIGHT:
291 : 0 : aPos.Secondary -= fShiftAmountY;
292 : 0 : break;
293 : : case drawing::Alignment_CENTER:
294 : : case drawing::Alignment_LEFT:
295 : : case drawing::Alignment_RIGHT:
296 : : // nothing
297 : 0 : break;
298 : : case drawing::Alignment_BOTTOM:
299 : : case drawing::Alignment_BOTTOM_LEFT:
300 : : case drawing::Alignment_BOTTOM_RIGHT:
301 : 0 : aPos.Secondary += fShiftAmountY;
302 : 0 : break;
303 : : case drawing::Alignment_MAKE_FIXED_SIZE:
304 : 0 : break;
305 : : }
306 : :
307 : : // anchor must not be changed
308 : : OSL_ASSERT( rInOutPosition.Anchor == aPos.Anchor );
309 : :
310 [ # # ][ # # ]: 0 : if( rInOutPosition.Primary == aPos.Primary &&
[ # # ][ # # ]
311 : : rInOutPosition.Secondary == aPos.Secondary &&
312 : : rInOutSize.Primary == aSize.Primary &&
313 : : rInOutSize.Secondary == aSize.Secondary )
314 : 0 : return false;
315 : :
316 : : // check
317 [ # # ]: 0 : if( bCheck )
318 : : {
319 : : // Note: this somewhat complicated check allows the output being
320 : : // out-of-bounds if the input was also out-of-bounds, and the change is
321 : : // for "advantage". E.g., you have a chart that laps out on the left
322 : : // side. If you shrink it, this should be possible, also if it still
323 : : // laps out on the left side afterwards. But you shouldn't be able to
324 : : // grow it then.
325 : :
326 : : chart2::RelativePosition aUpperLeft(
327 : 0 : RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_TOP_LEFT ));
328 : : chart2::RelativePosition aLowerRight(
329 : 0 : RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_BOTTOM_RIGHT ));
330 : :
331 : : // Do not grow, if this leads to corners being off-screen
332 [ # # ][ # # ]: 0 : if( fAmountX > 0.0 &&
[ # # ]
333 : : ( (aUpperLeft.Primary < fPosCheckThreshold) ||
334 : : (aLowerRight.Primary > (1.0 - fPosCheckThreshold)) ))
335 : 0 : return false;
336 [ # # ][ # # ]: 0 : if( fAmountY > 0.0 &&
[ # # ]
337 : : ( (aUpperLeft.Secondary < fPosCheckThreshold) ||
338 : : (aLowerRight.Secondary > (1.0 - fPosCheckThreshold)) ))
339 : 0 : return false;
340 : :
341 : : // Do not shrink, if this leads to a size too small
342 [ # # ][ # # ]: 0 : if( fAmountX < 0.0 &&
343 : : ( aSize.Primary < fSizeCheckThreshold ))
344 : 0 : return false;
345 [ # # ][ # # ]: 0 : if( fAmountY < 0.0 &&
346 : : ( aSize.Secondary < fSizeCheckThreshold ))
347 : 0 : return false;
348 : : }
349 : :
350 : 0 : rInOutPosition = aPos;
351 : 0 : rInOutSize = aSize;
352 : 0 : return true;
353 : : }
354 : :
355 : 0 : bool RelativePositionHelper::moveObject(
356 : : chart2::RelativePosition & rInOutPosition,
357 : : const chart2::RelativeSize & rObjectSize,
358 : : double fAmountX, double fAmountY,
359 : : bool bCheck /* = true */ )
360 : : {
361 : 0 : chart2::RelativePosition aPos( rInOutPosition );
362 : 0 : aPos.Primary += fAmountX;
363 : 0 : aPos.Secondary += fAmountY;
364 : 0 : const double fPosCheckThreshold = 0.02;
365 : :
366 [ # # ]: 0 : if( bCheck )
367 : : {
368 : : chart2::RelativePosition aUpperLeft(
369 : 0 : RelativePositionHelper::getReanchoredPosition( aPos, rObjectSize, drawing::Alignment_TOP_LEFT ));
370 : 0 : chart2::RelativePosition aLowerRight( aUpperLeft );
371 : 0 : aLowerRight.Primary += rObjectSize.Primary;
372 : 0 : aLowerRight.Secondary += rObjectSize.Secondary;
373 : :
374 : 0 : const double fFarEdgeThreshold = 1.0 - fPosCheckThreshold;
375 [ # # ][ # # ]: 0 : if( ( fAmountX > 0.0 && (aLowerRight.Primary > fFarEdgeThreshold)) ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
376 : : ( fAmountX < 0.0 && (aUpperLeft.Primary < fPosCheckThreshold)) ||
377 : : ( fAmountY > 0.0 && (aLowerRight.Secondary > fFarEdgeThreshold)) ||
378 : : ( fAmountY < 0.0 && (aUpperLeft.Secondary < fPosCheckThreshold)) )
379 : 0 : return false;
380 : : }
381 : :
382 : 0 : rInOutPosition = aPos;
383 : 0 : return true;
384 : : }
385 : :
386 : : } // namespace chart
387 : :
388 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|