Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "imivctl.hxx"
30 : :
31 : 0 : IcnCursor_Impl::IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner )
32 : : {
33 : 0 : pView = pOwner;
34 : 0 : pCurEntry = 0;
35 : 0 : nDeltaWidth = 0;
36 : 0 : nDeltaHeight= 0;
37 : 0 : nCols = 0;
38 : 0 : nRows = 0;
39 : 0 : }
40 : :
41 [ # # ]: 0 : IcnCursor_Impl::~IcnCursor_Impl()
42 : : {
43 : 0 : }
44 : :
45 : 0 : sal_uInt16 IcnCursor_Impl::GetSortListPos( SvxIconChoiceCtrlEntryPtrVec& rList, long nValue,
46 : : int bVertical )
47 : : {
48 : 0 : sal_uInt16 nCount = rList.size();
49 [ # # ]: 0 : if( !nCount )
50 : 0 : return 0;
51 : :
52 : 0 : sal_uInt16 nCurPos = 0;
53 : 0 : long nPrevValue = LONG_MIN;
54 [ # # ]: 0 : while( nCount )
55 : : {
56 : 0 : const Rectangle& rRect = pView->GetEntryBoundRect( rList[nCurPos] );
57 : : long nCurValue;
58 [ # # ]: 0 : if( bVertical )
59 : 0 : nCurValue = rRect.Top();
60 : : else
61 : 0 : nCurValue = rRect.Left();
62 [ # # ][ # # ]: 0 : if( nValue >= nPrevValue && nValue <= nCurValue )
63 : 0 : return (sal_uInt16)nCurPos;
64 : 0 : nPrevValue = nCurValue;
65 : 0 : nCount--;
66 : 0 : nCurPos++;
67 : : }
68 : 0 : return rList.size();
69 : : }
70 : :
71 : 0 : void IcnCursor_Impl::ImplCreate()
72 : : {
73 : 0 : pView->CheckBoundingRects();
74 : : DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
75 : :
76 : 0 : SetDeltas();
77 : :
78 [ # # ]: 0 : pColumns.reset(new IconChoiceMap);
79 [ # # ]: 0 : pRows.reset(new IconChoiceMap);
80 : :
81 : 0 : size_t nCount = pView->aEntries.size();
82 [ # # ]: 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
83 : : {
84 [ # # ]: 0 : SvxIconChoiceCtrlEntry* pEntry = pView->aEntries[ nCur ];
85 : : // const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
86 [ # # ]: 0 : Rectangle rRect( pView->CalcBmpRect( pEntry,0 ) );
87 : 0 : short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
88 : 0 : short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
89 : :
90 : : // capture rounding errors
91 [ # # ]: 0 : if( nY >= nRows )
92 : 0 : nY = sal::static_int_cast< short >(nRows - 1);
93 [ # # ]: 0 : if( nX >= nCols )
94 : 0 : nX = sal::static_int_cast< short >(nCols - 1);
95 : :
96 [ # # ]: 0 : SvxIconChoiceCtrlEntryPtrVec& rColEntry = (*pColumns)[nX];
97 [ # # ]: 0 : sal_uInt16 nIns = GetSortListPos( rColEntry, rRect.Top(), sal_True );
98 [ # # ][ # # ]: 0 : rColEntry.insert( rColEntry.begin() + nIns, pEntry );
99 : :
100 [ # # ]: 0 : SvxIconChoiceCtrlEntryPtrVec& rRowEntry = (*pRows)[nY];
101 [ # # ]: 0 : nIns = GetSortListPos( rRowEntry, rRect.Left(), sal_False );
102 [ # # ][ # # ]: 0 : rRowEntry.insert( rRowEntry.begin() + nIns, pEntry );
103 : :
104 : 0 : pEntry->nX = nX;
105 : 0 : pEntry->nY = nY;
106 : : }
107 : 0 : }
108 : :
109 : :
110 : :
111 : :
112 : 0 : void IcnCursor_Impl::Clear()
113 : : {
114 [ # # ]: 0 : if( pColumns )
115 : : {
116 : 0 : pColumns.reset();
117 : 0 : pRows.reset();
118 : 0 : pCurEntry = 0;
119 : 0 : nDeltaWidth = 0;
120 : 0 : nDeltaHeight = 0;
121 : : }
122 : 0 : }
123 : :
124 : 0 : SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchCol(sal_uInt16 nCol, sal_uInt16 nTop, sal_uInt16 nBottom,
125 : : sal_uInt16, bool bDown, bool bSimple )
126 : : {
127 : : DBG_ASSERT(pCurEntry, "SearchCol: No reference entry");
128 [ # # ]: 0 : IconChoiceMap::iterator mapIt = pColumns->find( nCol );
129 [ # # ]: 0 : if ( mapIt == pColumns->end() )
130 : 0 : return 0;
131 : 0 : SvxIconChoiceCtrlEntryPtrVec const & rList = mapIt->second;
132 : 0 : const sal_uInt16 nCount = rList.size();
133 [ # # ]: 0 : if( !nCount )
134 : 0 : return 0;
135 : :
136 [ # # ]: 0 : const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
137 : :
138 [ # # ]: 0 : if( bSimple )
139 : : {
140 [ # # ]: 0 : SvxIconChoiceCtrlEntryPtrVec::const_iterator it = std::find( rList.begin(), rList.end(), pCurEntry );
141 : : DBG_ASSERT( it != rList.end(), "Entry not in Col-List" );
142 [ # # ]: 0 : if( bDown )
143 : : {
144 [ # # ][ # # ]: 0 : while( ++it != rList.end() )
145 : : {
146 : 0 : SvxIconChoiceCtrlEntry* pEntry = *it;
147 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
148 [ # # ]: 0 : if( rRect.Top() > rRefRect.Top() )
149 : 0 : return pEntry;
150 : : }
151 : 0 : return 0;
152 : : }
153 : : else
154 : : {
155 : 0 : SvxIconChoiceCtrlEntryPtrVec::const_reverse_iterator it2(it);
156 [ # # ][ # # ]: 0 : while (it2 != rList.rend())
157 : : {
158 [ # # ]: 0 : SvxIconChoiceCtrlEntry* pEntry = *it2;
159 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
160 [ # # ]: 0 : if( rRect.Top() < rRefRect.Top() )
161 : 0 : return pEntry;
162 [ # # ]: 0 : ++it2;
163 : : }
164 : 0 : return 0;
165 : : }
166 : : }
167 : :
168 [ # # ]: 0 : if( nTop > nBottom )
169 : : {
170 : 0 : sal_uInt16 nTemp = nTop;
171 : 0 : nTop = nBottom;
172 : 0 : nBottom = nTemp;
173 : : }
174 : 0 : long nMinDistance = LONG_MAX;
175 : 0 : SvxIconChoiceCtrlEntry* pResult = 0;
176 [ # # ]: 0 : for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
177 : : {
178 : 0 : SvxIconChoiceCtrlEntry* pEntry = rList[ nCur ];
179 [ # # ]: 0 : if( pEntry != pCurEntry )
180 : : {
181 : 0 : sal_uInt16 nY = pEntry->nY;
182 [ # # ][ # # ]: 0 : if( nY >= nTop && nY <= nBottom )
183 : : {
184 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
185 : 0 : long nDistance = rRect.Top() - rRefRect.Top();
186 [ # # ]: 0 : if( nDistance < 0 )
187 : 0 : nDistance *= -1;
188 [ # # ][ # # ]: 0 : if( nDistance && nDistance < nMinDistance )
189 : : {
190 : 0 : nMinDistance = nDistance;
191 : 0 : pResult = pEntry;
192 : : }
193 : : }
194 : : }
195 : : }
196 : 0 : return pResult;
197 : : }
198 : :
199 : 0 : SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchRow(sal_uInt16 nRow, sal_uInt16 nLeft, sal_uInt16 nRight,
200 : : sal_uInt16, bool bRight, bool bSimple )
201 : : {
202 : : DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
203 [ # # ]: 0 : IconChoiceMap::iterator mapIt = pRows->find( nRow );
204 [ # # ]: 0 : if ( mapIt == pRows->end() )
205 : 0 : return 0;
206 : 0 : SvxIconChoiceCtrlEntryPtrVec const & rList = mapIt->second;
207 : 0 : const sal_uInt16 nCount = rList.size();
208 [ # # ]: 0 : if( !nCount )
209 : 0 : return 0;
210 : :
211 [ # # ]: 0 : const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
212 : :
213 [ # # ]: 0 : if( bSimple )
214 : : {
215 [ # # ]: 0 : SvxIconChoiceCtrlEntryPtrVec::const_iterator it = std::find( rList.begin(), rList.end(), pCurEntry );
216 : : DBG_ASSERT( it != rList.end(), "Entry not in Row-List" );
217 [ # # ]: 0 : if( bRight )
218 : : {
219 [ # # ][ # # ]: 0 : while( ++it != rList.end() )
220 : : {
221 : 0 : SvxIconChoiceCtrlEntry* pEntry = *it;
222 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
223 [ # # ]: 0 : if( rRect.Left() > rRefRect.Left() )
224 : 0 : return pEntry;
225 : : }
226 : 0 : return 0;
227 : : }
228 : : else
229 : : {
230 : 0 : SvxIconChoiceCtrlEntryPtrVec::const_reverse_iterator it2(it);
231 [ # # ][ # # ]: 0 : while (it2 != rList.rend())
232 : : {
233 [ # # ]: 0 : SvxIconChoiceCtrlEntry* pEntry = *it2;
234 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
235 [ # # ]: 0 : if( rRect.Left() < rRefRect.Left() )
236 : 0 : return pEntry;
237 [ # # ]: 0 : ++it2;
238 : : }
239 : 0 : return 0;
240 : : }
241 : :
242 : : }
243 [ # # ]: 0 : if( nRight < nLeft )
244 : : {
245 : 0 : sal_uInt16 nTemp = nRight;
246 : 0 : nRight = nLeft;
247 : 0 : nLeft = nTemp;
248 : : }
249 : 0 : long nMinDistance = LONG_MAX;
250 : 0 : SvxIconChoiceCtrlEntry* pResult = 0;
251 [ # # ]: 0 : for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
252 : : {
253 : 0 : SvxIconChoiceCtrlEntry* pEntry = rList[ nCur ];
254 [ # # ]: 0 : if( pEntry != pCurEntry )
255 : : {
256 : 0 : sal_uInt16 nX = pEntry->nX;
257 [ # # ][ # # ]: 0 : if( nX >= nLeft && nX <= nRight )
258 : : {
259 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
260 : 0 : long nDistance = rRect.Left() - rRefRect.Left();
261 [ # # ]: 0 : if( nDistance < 0 )
262 : 0 : nDistance *= -1;
263 [ # # ][ # # ]: 0 : if( nDistance && nDistance < nMinDistance )
264 : : {
265 : 0 : nMinDistance = nDistance;
266 : 0 : pResult = pEntry;
267 : : }
268 : : }
269 : : }
270 : : }
271 : 0 : return pResult;
272 : : }
273 : :
274 : :
275 : :
276 : : /*
277 : : Searches, starting from the passed value, the next entry to the left/to the
278 : : right. Example for bRight = sal_True:
279 : :
280 : : c
281 : : b c
282 : : a b c
283 : : S 1 1 1 ====> search direction
284 : : a b c
285 : : b c
286 : : c
287 : :
288 : : S : starting position
289 : : 1 : first searched rectangle
290 : : a,b,c : 2nd, 3rd, 4th searched rectangle
291 : : */
292 : :
293 : 0 : SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pCtrlEntry, sal_Bool bRight )
294 : : {
295 : : SvxIconChoiceCtrlEntry* pResult;
296 : 0 : pCurEntry = pCtrlEntry;
297 : 0 : Create();
298 : 0 : sal_uInt16 nY = pCtrlEntry->nY;
299 : 0 : sal_uInt16 nX = pCtrlEntry->nX;
300 : : DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
301 : : DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
302 : : // neighbor in same row?
303 [ # # ]: 0 : if( bRight )
304 : : pResult = SearchRow(
305 : 0 : nY, nX, sal::static_int_cast< sal_uInt16 >(nCols-1), nX, sal_True, sal_True );
306 : : else
307 : 0 : pResult = SearchRow( nY, nX ,0, nX, sal_False, sal_True );
308 [ # # ]: 0 : if( pResult )
309 : 0 : return pResult;
310 : :
311 : 0 : long nCurCol = nX;
312 : :
313 : : long nColOffs, nLastCol;
314 [ # # ]: 0 : if( bRight )
315 : : {
316 : 0 : nColOffs = 1;
317 : 0 : nLastCol = nCols;
318 : : }
319 : : else
320 : : {
321 : 0 : nColOffs = -1;
322 : 0 : nLastCol = -1; // 0-1
323 : : }
324 : :
325 : 0 : sal_uInt16 nRowMin = nY;
326 : 0 : sal_uInt16 nRowMax = nY;
327 [ # # ]: 0 : do
328 : : {
329 : 0 : SvxIconChoiceCtrlEntry* pEntry = SearchCol((sal_uInt16)nCurCol,nRowMin,nRowMax,nY,sal_True, sal_False);
330 [ # # ]: 0 : if( pEntry )
331 : 0 : return pEntry;
332 [ # # ]: 0 : if( nRowMin )
333 : 0 : nRowMin--;
334 [ # # ]: 0 : if( nRowMax < (nRows-1))
335 : 0 : nRowMax++;
336 : 0 : nCurCol += nColOffs;
337 : : } while( nCurCol != nLastCol );
338 : 0 : return 0;
339 : : }
340 : :
341 : 0 : SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoPageUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown)
342 : : {
343 [ # # ][ # # ]: 0 : if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
[ # # ]
344 : : {
345 : 0 : const long nPos = (long)pView->GetEntryListPos( pStart );
346 : 0 : long nEntriesInView = (pView->aOutputSize.Height() / pView->nGridDY);
347 : : nEntriesInView *=
348 : 0 : ((pView->aOutputSize.Width()+(pView->nGridDX/2)) / pView->nGridDX );
349 : 0 : long nNewPos = nPos;
350 [ # # ]: 0 : if( bDown )
351 : : {
352 : 0 : nNewPos += nEntriesInView;
353 [ # # ]: 0 : if( nNewPos >= (long)pView->aEntries.size() )
354 : 0 : nNewPos = pView->aEntries.size() - 1;
355 : : }
356 : : else
357 : : {
358 : 0 : nNewPos -= nEntriesInView;
359 [ # # ]: 0 : if( nNewPos < 0 )
360 : 0 : nNewPos = 0;
361 : : }
362 [ # # ]: 0 : if( nPos != nNewPos )
363 : 0 : return pView->aEntries[ (size_t)nNewPos ];
364 : 0 : return 0;
365 : : }
366 : 0 : long nOpt = pView->GetEntryBoundRect( pStart ).Top();
367 [ # # ]: 0 : if( bDown )
368 : : {
369 : 0 : nOpt += pView->aOutputSize.Height();
370 : 0 : nOpt -= pView->nGridDY;
371 : : }
372 : : else
373 : : {
374 : 0 : nOpt -= pView->aOutputSize.Height();
375 : 0 : nOpt += pView->nGridDY;
376 : : }
377 [ # # ]: 0 : if( nOpt < 0 )
378 : 0 : nOpt = 0;
379 : :
380 : 0 : long nPrevErr = LONG_MAX;
381 : :
382 : 0 : SvxIconChoiceCtrlEntry* pPrev = pStart;
383 : 0 : SvxIconChoiceCtrlEntry* pNext = GoUpDown( pStart, bDown );
384 [ # # ]: 0 : while( pNext )
385 : : {
386 : 0 : long nCur = pView->GetEntryBoundRect( pNext ).Top();
387 : 0 : long nErr = nOpt - nCur;
388 [ # # ]: 0 : if( nErr < 0 )
389 : 0 : nErr *= -1;
390 [ # # ]: 0 : if( nErr > nPrevErr )
391 : 0 : return pPrev;
392 : 0 : nPrevErr = nErr;
393 : 0 : pPrev = pNext;
394 : 0 : pNext = GoUpDown( pNext, bDown );
395 : : }
396 [ # # ]: 0 : if( pPrev != pStart )
397 : 0 : return pPrev;
398 : 0 : return 0;
399 : : }
400 : :
401 : 0 : SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pCtrlEntry, sal_Bool bDown)
402 : : {
403 [ # # ][ # # ]: 0 : if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
[ # # ]
404 : : {
405 : 0 : sal_uLong nPos = pView->GetEntryListPos( pCtrlEntry );
406 [ # # ][ # # ]: 0 : if( bDown && nPos < (pView->aEntries.size() - 1) )
[ # # ]
407 : 0 : return pView->aEntries[ nPos + 1 ];
408 [ # # ][ # # ]: 0 : else if( !bDown && nPos > 0 )
409 : 0 : return pView->aEntries[ nPos - 1 ];
410 : 0 : return 0;
411 : : }
412 : :
413 : : SvxIconChoiceCtrlEntry* pResult;
414 : 0 : pCurEntry = pCtrlEntry;
415 : 0 : Create();
416 : 0 : sal_uInt16 nY = pCtrlEntry->nY;
417 : 0 : sal_uInt16 nX = pCtrlEntry->nX;
418 : : DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
419 : : DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
420 : :
421 : : // neighbor in same column?
422 [ # # ]: 0 : if( bDown )
423 : : pResult = SearchCol(
424 : 0 : nX, nY, sal::static_int_cast< sal_uInt16 >(nRows-1), nY, sal_True, sal_True );
425 : : else
426 : 0 : pResult = SearchCol( nX, nY ,0, nY, sal_False, sal_True );
427 [ # # ]: 0 : if( pResult )
428 : 0 : return pResult;
429 : :
430 : 0 : long nCurRow = nY;
431 : :
432 : : long nRowOffs, nLastRow;
433 [ # # ]: 0 : if( bDown )
434 : : {
435 : 0 : nRowOffs = 1;
436 : 0 : nLastRow = nRows;
437 : : }
438 : : else
439 : : {
440 : 0 : nRowOffs = -1;
441 : 0 : nLastRow = -1; // 0-1
442 : : }
443 : :
444 : 0 : sal_uInt16 nColMin = nX;
445 : 0 : sal_uInt16 nColMax = nX;
446 [ # # ]: 0 : do
447 : : {
448 : 0 : SvxIconChoiceCtrlEntry* pEntry = SearchRow((sal_uInt16)nCurRow,nColMin,nColMax,nX,sal_True, sal_False);
449 [ # # ]: 0 : if( pEntry )
450 : 0 : return pEntry;
451 [ # # ]: 0 : if( nColMin )
452 : 0 : nColMin--;
453 [ # # ]: 0 : if( nColMax < (nCols-1))
454 : 0 : nColMax++;
455 : 0 : nCurRow += nRowOffs;
456 : : } while( nCurRow != nLastRow );
457 : 0 : return 0;
458 : : }
459 : :
460 : 0 : void IcnCursor_Impl::SetDeltas()
461 : : {
462 : 0 : const Size& rSize = pView->aVirtOutputSize;
463 : 0 : nCols = rSize.Width() / pView->nGridDX;
464 [ # # ]: 0 : if( !nCols )
465 : 0 : nCols = 1;
466 : 0 : nRows = rSize.Height() / pView->nGridDY;
467 [ # # ]: 0 : if( (nRows * pView->nGridDY) < rSize.Height() )
468 : 0 : nRows++;
469 [ # # ]: 0 : if( !nRows )
470 : 0 : nRows = 1;
471 : :
472 : 0 : nDeltaWidth = (short)(rSize.Width() / nCols);
473 : 0 : nDeltaHeight = (short)(rSize.Height() / nRows);
474 [ # # ]: 0 : if( !nDeltaHeight )
475 : : {
476 : 0 : nDeltaHeight = 1;
477 : : DBG_WARNING("SetDeltas:Bad height");
478 : : }
479 [ # # ]: 0 : if( !nDeltaWidth )
480 : : {
481 : 0 : nDeltaWidth = 1;
482 : : DBG_WARNING("SetDeltas:Bad width");
483 : : }
484 : 0 : }
485 : :
486 : 0 : void IcnCursor_Impl::CreateGridAjustData( IconChoiceMap& rLists, SvxIconChoiceCtrlEntry* pRefEntry)
487 : : {
488 [ # # ]: 0 : if( !pRefEntry )
489 : : {
490 : 0 : sal_uInt16 nGridRows = (sal_uInt16)(pView->aVirtOutputSize.Height() / pView->nGridDY);
491 : 0 : nGridRows++; // because we round down later!
492 : :
493 [ # # ]: 0 : if( !nGridRows )
494 : 0 : return;
495 : 0 : const size_t nCount = pView->aEntries.size();
496 [ # # ]: 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
497 : : {
498 [ # # ]: 0 : SvxIconChoiceCtrlEntry* pEntry = pView->aEntries[ nCur ];
499 [ # # ]: 0 : const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
500 : 0 : short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
501 [ # # ][ # # ]: 0 : sal_uInt16 nIns = GetSortListPos( rLists[nY], rRect.Left(), sal_False );
502 [ # # ][ # # ]: 0 : rLists[ nY ].insert( rLists[ nY ].begin() + nIns, pEntry );
[ # # ][ # # ]
503 : : }
504 : : }
505 : : else
506 : : {
507 : : // build a horizontal "tube" in the RefEntry line
508 : : // STOP AND THINK: maybe use bounding rectangle because of overlaps?
509 [ # # ]: 0 : Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
510 : : //const Rectangle& rRefRect = pView->GetEntryBoundRect( pRefEntry );
511 : 0 : short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
512 [ # # ]: 0 : SvxIconChoiceCtrlEntryPtrVec& rRow = rLists[0];
513 : 0 : size_t nCount = pView->aEntries.size();
514 [ # # ]: 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
515 : : {
516 [ # # ]: 0 : SvxIconChoiceCtrlEntry* pEntry = pView->aEntries[ nCur ];
517 [ # # ]: 0 : Rectangle rRect( pView->CalcBmpRect(pEntry) );
518 : : //const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
519 : 0 : short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
520 [ # # ]: 0 : if( nY == nRefRow )
521 : : {
522 [ # # ]: 0 : sal_uInt16 nIns = GetSortListPos( rRow, rRect.Left(), sal_False );
523 [ # # ][ # # ]: 0 : rRow.insert( rRow.begin() + nIns, pEntry );
524 : : }
525 : : }
526 : : }
527 : : }
528 : :
529 : : //static
530 : 0 : void IcnCursor_Impl::DestroyGridAdjustData( IconChoiceMap& rLists )
531 : : {
532 : 0 : rLists.clear();
533 : 0 : }
534 : :
535 : 0 : IcnGridMap_Impl::IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView)
536 : : {
537 : 0 : _pView = pView;
538 : 0 : _pGridMap = 0;
539 : 0 : _nGridCols = 0;
540 : 0 : _nGridRows = 0;
541 : 0 : }
542 : :
543 : 0 : IcnGridMap_Impl::~IcnGridMap_Impl()
544 : : {
545 [ # # ]: 0 : delete[] _pGridMap, _pGridMap=0;
546 : 0 : }
547 : :
548 : 0 : void IcnGridMap_Impl::Expand()
549 : : {
550 [ # # ]: 0 : if( !_pGridMap )
551 : 0 : Create_Impl();
552 : : else
553 : : {
554 : 0 : sal_uInt16 nNewGridRows = _nGridRows;
555 : 0 : sal_uInt16 nNewGridCols = _nGridCols;
556 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
557 : 0 : nNewGridRows += 50;
558 : : else
559 : 0 : nNewGridCols += 50;
560 : :
561 : 0 : sal_Bool* pNewGridMap = new sal_Bool[nNewGridRows*nNewGridCols];
562 : 0 : memset( pNewGridMap, 0, nNewGridRows * nNewGridCols * sizeof(sal_Bool) );
563 : 0 : memcpy( pNewGridMap, _pGridMap, _nGridRows * _nGridCols * sizeof(sal_Bool) );
564 [ # # ]: 0 : delete[] _pGridMap;
565 : 0 : _pGridMap = pNewGridMap;
566 : 0 : _nGridRows = nNewGridRows;
567 : 0 : _nGridCols = nNewGridCols;
568 : : }
569 : 0 : }
570 : :
571 : 0 : void IcnGridMap_Impl::Create_Impl()
572 : : {
573 : : DBG_ASSERT(!_pGridMap,"Unnecessary call to IcnGridMap_Impl::Create_Impl()");
574 [ # # ]: 0 : if( _pGridMap )
575 : 0 : return;
576 : 0 : GetMinMapSize( _nGridCols, _nGridRows );
577 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
578 : 0 : _nGridRows += 50; // avoid resize of gridmap too often
579 : : else
580 : 0 : _nGridCols += 50;
581 : :
582 : 0 : _pGridMap = new sal_Bool[ _nGridRows * _nGridCols];
583 : 0 : memset( (void*)_pGridMap, 0, _nGridRows * _nGridCols );
584 : :
585 : 0 : const size_t nCount = _pView->aEntries.size();
586 [ # # ]: 0 : for( size_t nCur=0; nCur < nCount; nCur++ )
587 : 0 : OccupyGrids( _pView->aEntries[ nCur ] );
588 : : }
589 : :
590 : 0 : void IcnGridMap_Impl::GetMinMapSize( sal_uInt16& rDX, sal_uInt16& rDY ) const
591 : : {
592 : : long nX, nY;
593 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
594 : : {
595 : : // The view grows in vertical direction. Its max. width is _pView->nMaxVirtWidth
596 : 0 : nX = _pView->nMaxVirtWidth;
597 [ # # ]: 0 : if( !nX )
598 : 0 : nX = _pView->pView->GetOutputSizePixel().Width();
599 [ # # ]: 0 : if( !(_pView->nFlags & F_ARRANGING) )
600 : 0 : nX -= _pView->nVerSBarWidth;
601 : :
602 : 0 : nY = _pView->aVirtOutputSize.Height();
603 : : }
604 : : else
605 : : {
606 : : // The view grows in horizontal direction. Its max. height is _pView->nMaxVirtHeight
607 : 0 : nY = _pView->nMaxVirtHeight;
608 [ # # ]: 0 : if( !nY )
609 : 0 : nY = _pView->pView->GetOutputSizePixel().Height();
610 [ # # ]: 0 : if( !(_pView->nFlags & F_ARRANGING) )
611 : 0 : nY -= _pView->nHorSBarHeight;
612 : 0 : nX = _pView->aVirtOutputSize.Width();
613 : : }
614 : :
615 [ # # ]: 0 : if( !nX )
616 : 0 : nX = DEFAULT_MAX_VIRT_WIDTH;
617 [ # # ]: 0 : if( !nY )
618 : 0 : nY = DEFAULT_MAX_VIRT_HEIGHT;
619 : :
620 : 0 : long nDX = nX / _pView->nGridDX;
621 : 0 : long nDY = nY / _pView->nGridDY;
622 : :
623 [ # # ]: 0 : if( !nDX )
624 : 0 : nDX++;
625 [ # # ]: 0 : if( !nDY )
626 : 0 : nDY++;
627 : :
628 : 0 : rDX = (sal_uInt16)nDX;
629 : 0 : rDY = (sal_uInt16)nDY;
630 : 0 : }
631 : :
632 : 0 : GridId IcnGridMap_Impl::GetGrid( sal_uInt16 nGridX, sal_uInt16 nGridY )
633 : : {
634 : 0 : Create();
635 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
636 : 0 : return nGridX + ( nGridY * _nGridCols );
637 : : else
638 : 0 : return nGridY + ( nGridX * _nGridRows );
639 : : }
640 : :
641 : 0 : GridId IcnGridMap_Impl::GetGrid( const Point& rDocPos, sal_Bool* pbClipped )
642 : : {
643 : 0 : Create();
644 : :
645 : 0 : long nX = rDocPos.X();
646 : 0 : long nY = rDocPos.Y();
647 : 0 : nX -= LROFFS_WINBORDER;
648 : 0 : nY -= TBOFFS_WINBORDER;
649 : 0 : nX /= _pView->nGridDX;
650 : 0 : nY /= _pView->nGridDY;
651 : 0 : sal_Bool bClipped = sal_False;
652 [ # # ]: 0 : if( nX >= _nGridCols )
653 : : {
654 : 0 : nX = _nGridCols - 1;
655 : 0 : bClipped = sal_True;
656 : : }
657 [ # # ]: 0 : if( nY >= _nGridRows )
658 : : {
659 : 0 : nY = _nGridRows - 1;
660 : 0 : bClipped = sal_True;
661 : : }
662 : 0 : GridId nId = GetGrid( (sal_uInt16)nX, (sal_uInt16)nY );
663 [ # # ]: 0 : if( pbClipped )
664 : 0 : *pbClipped = bClipped;
665 : : DBG_ASSERT(nId <(sal_uLong)(_nGridCols*_nGridRows),"GetGrid failed");
666 : 0 : return nId;
667 : : }
668 : :
669 : 0 : Rectangle IcnGridMap_Impl::GetGridRect( GridId nId )
670 : : {
671 [ # # ]: 0 : Create();
672 : : sal_uInt16 nGridX, nGridY;
673 [ # # ]: 0 : GetGridCoord( nId, nGridX, nGridY );
674 : 0 : const long nLeft = nGridX * _pView->nGridDX+ LROFFS_WINBORDER;
675 : 0 : const long nTop = nGridY * _pView->nGridDY + TBOFFS_WINBORDER;
676 : : return Rectangle(
677 : : nLeft, nTop,
678 : : nLeft + _pView->nGridDX,
679 [ # # ]: 0 : nTop + _pView->nGridDY );
680 : : }
681 : :
682 : 0 : GridId IcnGridMap_Impl::GetUnoccupiedGrid( sal_Bool bOccupyFound )
683 : : {
684 : 0 : Create();
685 : 0 : sal_uLong nStart = 0;
686 : 0 : sal_Bool bExpanded = sal_False;
687 : :
688 : 0 : while( 1 )
689 : : {
690 : 0 : const sal_uLong nCount = (sal_uInt16)(_nGridCols * _nGridRows);
691 [ # # ]: 0 : for( sal_uLong nCur = nStart; nCur < nCount; nCur++ )
692 : : {
693 [ # # ]: 0 : if( !_pGridMap[ nCur ] )
694 : : {
695 [ # # ]: 0 : if( bOccupyFound )
696 : 0 : _pGridMap[ nCur ] = sal_True;
697 : 0 : return (GridId)nCur;
698 : : }
699 : : }
700 : : DBG_ASSERT(!bExpanded,"ExpandGrid failed");
701 [ # # ]: 0 : if( bExpanded )
702 : 0 : return 0; // prevent never ending loop
703 : 0 : bExpanded = sal_True;
704 : 0 : Expand();
705 : 0 : nStart = nCount;
706 : : }
707 : : }
708 : :
709 : : // An entry only means that there's a GridRect lying under its center. This
710 : : // variant is much faster than allocating via the bounding rectangle but can
711 : : // lead to small overlaps.
712 : 0 : void IcnGridMap_Impl::OccupyGrids( const SvxIconChoiceCtrlEntry* pEntry, sal_Bool bOccupy )
713 : : {
714 [ # # ][ # # ]: 0 : if( !_pGridMap || !_pView->IsBoundingRectValid( pEntry->aRect ))
[ # # ]
715 : 0 : return;
716 [ # # ]: 0 : OccupyGrid( GetGrid( pEntry->aRect.Center()), bOccupy );
717 : : }
718 : :
719 : 0 : void IcnGridMap_Impl::Clear()
720 : : {
721 [ # # ]: 0 : if( _pGridMap )
722 : : {
723 [ # # ]: 0 : delete[] _pGridMap, _pGridMap=0;
724 : 0 : _nGridRows = 0;
725 : 0 : _nGridCols = 0;
726 : 0 : _aLastOccupiedGrid.SetEmpty();
727 : : }
728 : 0 : }
729 : :
730 : 0 : sal_uLong IcnGridMap_Impl::GetGridCount( const Size& rSizePixel, sal_uInt16 nDX, sal_uInt16 nDY)
731 : : {
732 : 0 : long ndx = (rSizePixel.Width() - LROFFS_WINBORDER) / nDX;
733 [ # # ]: 0 : if( ndx < 0 ) ndx *= -1;
734 : 0 : long ndy = (rSizePixel.Height() - TBOFFS_WINBORDER) / nDY;
735 [ # # ]: 0 : if( ndy < 0 ) ndy *= -1;
736 : 0 : return (sal_uLong)(ndx * ndy);
737 : : }
738 : :
739 : 0 : void IcnGridMap_Impl::OutputSizeChanged()
740 : : {
741 [ # # ]: 0 : if( _pGridMap )
742 : : {
743 : : sal_uInt16 nCols, nRows;
744 : 0 : GetMinMapSize( nCols, nRows );
745 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
746 : : {
747 [ # # ]: 0 : if( nCols != _nGridCols )
748 : 0 : Clear();
749 [ # # ]: 0 : else if( nRows >= _nGridRows )
750 [ # # ]: 0 : Expand();
751 : : }
752 : : else
753 : : {
754 [ # # ]: 0 : if( nRows != _nGridRows )
755 : 0 : Clear();
756 [ # # ]: 0 : else if( nCols >= _nGridCols )
757 [ # # ]: 0 : Expand();
758 : : }
759 : : }
760 : 0 : }
761 : :
762 : : // Independently of the view's alignment (TOP or LEFT), the gridmap
763 : : // should contain the data in a continuous region, to make it possible
764 : : // to copy the whole block if the gridmap needs to be expanded.
765 : 0 : void IcnGridMap_Impl::GetGridCoord( GridId nId, sal_uInt16& rGridX, sal_uInt16& rGridY )
766 : : {
767 : 0 : Create();
768 [ # # ]: 0 : if( _pView->nWinBits & WB_ALIGN_TOP )
769 : : {
770 : 0 : rGridX = (sal_uInt16)(nId % _nGridCols);
771 : 0 : rGridY = (sal_uInt16)(nId / _nGridCols);
772 : : }
773 : : else
774 : : {
775 : 0 : rGridX = (sal_uInt16)(nId / _nGridRows);
776 : 0 : rGridY = (sal_uInt16)(nId % _nGridRows);
777 : : }
778 : 0 : }
779 : :
780 : :
781 : :
782 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|