merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / contnr / imivctl2.cxx
blob5721258fc5173789e112c9d1ff1a476a2759a32a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: imivctl2.cxx,v $
10 * $Revision: 1.7 $
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_svtools.hxx"
33 #include "imivctl.hxx"
35 IcnCursor_Impl::IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner )
37 pView = pOwner;
38 pColumns = 0;
39 pRows = 0;
40 pCurEntry = 0;
41 nDeltaWidth = 0;
42 nDeltaHeight= 0;
43 nCols = 0;
44 nRows = 0;
47 IcnCursor_Impl::~IcnCursor_Impl()
49 delete[] pColumns;
50 delete[] pRows;
53 USHORT IcnCursor_Impl::GetSortListPos( SvPtrarr* pList, long nValue,
54 int bVertical )
56 USHORT nCount = (USHORT)pList->Count();
57 if( !nCount )
58 return 0;
60 USHORT nCurPos = 0;
61 long nPrevValue = LONG_MIN;
62 while( nCount )
64 const Rectangle& rRect=
65 pView->GetEntryBoundRect((SvxIconChoiceCtrlEntry*)(pList->GetObject(nCurPos)));
66 long nCurValue;
67 if( bVertical )
68 nCurValue = rRect.Top();
69 else
70 nCurValue = rRect.Left();
71 if( nValue >= nPrevValue && nValue <= nCurValue )
72 return (USHORT)nCurPos;
73 nPrevValue = nCurValue;
74 nCount--;
75 nCurPos++;
77 return pList->Count();
80 void IcnCursor_Impl::ImplCreate()
82 pView->CheckBoundingRects();
83 DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
85 SetDeltas();
87 pColumns = new SvPtrarr[ nCols ];
88 pRows = new SvPtrarr[ nRows ];
90 ULONG nCount = pView->aEntries.Count();
91 for( ULONG nCur = 0; nCur < nCount; nCur++ )
93 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
94 // const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
95 Rectangle rRect( pView->CalcBmpRect( pEntry,0 ) );
96 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
97 short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
99 // Rundungsfehler abfangen
100 if( nY >= nRows )
101 nY = sal::static_int_cast< short >(nRows - 1);
102 if( nX >= nCols )
103 nX = sal::static_int_cast< short >(nCols - 1);
105 USHORT nIns = GetSortListPos( &pColumns[nX], rRect.Top(), TRUE );
106 pColumns[ nX ].Insert( pEntry, nIns );
108 nIns = GetSortListPos( &pRows[nY], rRect.Left(), FALSE );
109 pRows[ nY ].Insert( pEntry, nIns );
111 pEntry->nX = nX;
112 pEntry->nY = nY;
119 void IcnCursor_Impl::Clear()
121 if( pColumns )
123 delete[] pColumns;
124 delete[] pRows;
125 pColumns = 0;
126 pRows = 0;
127 pCurEntry = 0;
128 nDeltaWidth = 0;
129 nDeltaHeight = 0;
133 SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,
134 USHORT, BOOL bDown, BOOL bSimple )
136 DBG_ASSERT(pCurEntry,"SearchCol: No reference entry");
137 SvPtrarr* pList = &(pColumns[ nCol ]);
138 const USHORT nCount = pList->Count();
139 if( !nCount )
140 return 0;
142 const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
144 if( bSimple )
146 USHORT nListPos = pList->GetPos( pCurEntry );
147 DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List");
148 if( bDown )
150 while( nListPos < nCount-1 )
152 nListPos++;
153 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
154 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
155 if( rRect.Top() > rRefRect.Top() )
156 return pEntry;
158 return 0;
160 else
162 while( nListPos )
164 nListPos--;
165 if( nListPos < nCount )
167 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
168 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
169 if( rRect.Top() < rRefRect.Top() )
170 return pEntry;
173 return 0;
177 if( nTop > nBottom )
179 USHORT nTemp = nTop;
180 nTop = nBottom;
181 nBottom = nTemp;
183 long nMinDistance = LONG_MAX;
184 SvxIconChoiceCtrlEntry* pResult = 0;
185 for( USHORT nCur = 0; nCur < nCount; nCur++ )
187 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur ));
188 if( pEntry != pCurEntry )
190 USHORT nY = pEntry->nY;
191 if( nY >= nTop && nY <= nBottom )
193 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
194 long nDistance = rRect.Top() - rRefRect.Top();
195 if( nDistance < 0 )
196 nDistance *= -1;
197 if( nDistance && nDistance < nMinDistance )
199 nMinDistance = nDistance;
200 pResult = pEntry;
205 return pResult;
208 SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchRow(USHORT nRow,USHORT nLeft,USHORT nRight,
209 USHORT, BOOL bRight, BOOL bSimple )
211 DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
212 SvPtrarr* pList = &(pRows[ nRow ]);
213 const USHORT nCount = pList->Count();
214 if( !nCount )
215 return 0;
217 const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry);
219 if( bSimple )
221 USHORT nListPos = pList->GetPos( pCurEntry );
222 DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List");
223 if( bRight )
225 while( nListPos < nCount-1 )
227 nListPos++;
228 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
229 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
230 if( rRect.Left() > rRefRect.Left() )
231 return pEntry;
233 return 0;
235 else
237 while( nListPos )
239 nListPos--;
240 if( nListPos < nCount )
242 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos );
243 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
244 if( rRect.Left() < rRefRect.Left() )
245 return pEntry;
248 return 0;
252 if( nRight < nLeft )
254 USHORT nTemp = nRight;
255 nRight = nLeft;
256 nLeft = nTemp;
258 long nMinDistance = LONG_MAX;
259 SvxIconChoiceCtrlEntry* pResult = 0;
260 for( USHORT nCur = 0; nCur < nCount; nCur++ )
262 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur ));
263 if( pEntry != pCurEntry )
265 USHORT nX = pEntry->nX;
266 if( nX >= nLeft && nX <= nRight )
268 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
269 long nDistance = rRect.Left() - rRefRect.Left();
270 if( nDistance < 0 )
271 nDistance *= -1;
272 if( nDistance && nDistance < nMinDistance )
274 nMinDistance = nDistance;
275 pResult = pEntry;
280 return pResult;
286 Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw.
287 linksstehenden. Suchverfahren am Beispiel bRight = TRUE:
291 a b c
292 S 1 1 1 ====> Suchrichtung
293 a b c
297 S : Startposition
298 1 : erstes Suchrechteck
299 a,b,c : 2., 3., 4. Suchrechteck
302 SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pCtrlEntry, BOOL bRight )
304 SvxIconChoiceCtrlEntry* pResult;
305 pCurEntry = pCtrlEntry;
306 Create();
307 USHORT nY = pCtrlEntry->nY;
308 USHORT nX = pCtrlEntry->nX;
309 DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
310 DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
311 // Nachbar auf gleicher Zeile ?
312 if( bRight )
313 pResult = SearchRow(
314 nY, nX, sal::static_int_cast< USHORT >(nCols-1), nX, TRUE, TRUE );
315 else
316 pResult = SearchRow( nY, nX ,0, nX, FALSE, TRUE );
317 if( pResult )
318 return pResult;
320 long nCurCol = nX;
322 long nColOffs, nLastCol;
323 if( bRight )
325 nColOffs = 1;
326 nLastCol = nCols;
328 else
330 nColOffs = -1;
331 nLastCol = -1; // 0-1
334 USHORT nRowMin = nY;
335 USHORT nRowMax = nY;
338 SvxIconChoiceCtrlEntry* pEntry = SearchCol((USHORT)nCurCol,nRowMin,nRowMax,nY,TRUE, FALSE);
339 if( pEntry )
340 return pEntry;
341 if( nRowMin )
342 nRowMin--;
343 if( nRowMax < (nRows-1))
344 nRowMax++;
345 nCurCol += nColOffs;
346 } while( nCurCol != nLastCol );
347 return 0;
350 SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoPageUpDown( SvxIconChoiceCtrlEntry* pStart, BOOL bDown)
352 if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
354 const long nPos = (long)pView->GetEntryListPos( pStart );
355 long nEntriesInView = (pView->aOutputSize.Height() / pView->nGridDY);
356 nEntriesInView *=
357 ((pView->aOutputSize.Width()+(pView->nGridDX/2)) / pView->nGridDX );
358 long nNewPos = nPos;
359 if( bDown )
361 nNewPos += nEntriesInView;
362 if( nNewPos >= (long)pView->aEntries.Count() )
363 nNewPos = pView->aEntries.Count() - 1;
365 else
367 nNewPos -= nEntriesInView;
368 if( nNewPos < 0 )
369 nNewPos = 0;
371 if( nPos != nNewPos )
372 return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( (ULONG)nNewPos );
373 return 0;
375 long nOpt = pView->GetEntryBoundRect( pStart ).Top();
376 if( bDown )
378 nOpt += pView->aOutputSize.Height();
379 nOpt -= pView->nGridDY;
381 else
383 nOpt -= pView->aOutputSize.Height();
384 nOpt += pView->nGridDY;
386 if( nOpt < 0 )
387 nOpt = 0;
389 long nPrevErr = LONG_MAX;
391 SvxIconChoiceCtrlEntry* pPrev = pStart;
392 SvxIconChoiceCtrlEntry* pNext = GoUpDown( pStart, bDown );
393 while( pNext )
395 long nCur = pView->GetEntryBoundRect( pNext ).Top();
396 long nErr = nOpt - nCur;
397 if( nErr < 0 )
398 nErr *= -1;
399 if( nErr > nPrevErr )
400 return pPrev;
401 nPrevErr = nErr;
402 pPrev = pNext;
403 pNext = GoUpDown( pNext, bDown );
405 if( pPrev != pStart )
406 return pPrev;
407 return 0;
410 SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pCtrlEntry, BOOL bDown)
412 if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) )
414 ULONG nPos = pView->GetEntryListPos( pCtrlEntry );
415 if( bDown && nPos < (pView->aEntries.Count() - 1) )
416 return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos + 1 );
417 else if( !bDown && nPos > 0 )
418 return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos - 1 );
419 return 0;
422 SvxIconChoiceCtrlEntry* pResult;
423 pCurEntry = pCtrlEntry;
424 Create();
425 USHORT nY = pCtrlEntry->nY;
426 USHORT nX = pCtrlEntry->nX;
427 DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
428 DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
430 // Nachbar in gleicher Spalte ?
431 if( bDown )
432 pResult = SearchCol(
433 nX, nY, sal::static_int_cast< USHORT >(nRows-1), nY, TRUE, TRUE );
434 else
435 pResult = SearchCol( nX, nY ,0, nY, FALSE, TRUE );
436 if( pResult )
437 return pResult;
439 long nCurRow = nY;
441 long nRowOffs, nLastRow;
442 if( bDown )
444 nRowOffs = 1;
445 nLastRow = nRows;
447 else
449 nRowOffs = -1;
450 nLastRow = -1; // 0-1
453 USHORT nColMin = nX;
454 USHORT nColMax = nX;
457 SvxIconChoiceCtrlEntry* pEntry = SearchRow((USHORT)nCurRow,nColMin,nColMax,nX,TRUE, FALSE);
458 if( pEntry )
459 return pEntry;
460 if( nColMin )
461 nColMin--;
462 if( nColMax < (nCols-1))
463 nColMax++;
464 nCurRow += nRowOffs;
465 } while( nCurRow != nLastRow );
466 return 0;
469 void IcnCursor_Impl::SetDeltas()
471 const Size& rSize = pView->aVirtOutputSize;
472 nCols = rSize.Width() / pView->nGridDX;
473 if( !nCols )
474 nCols = 1;
475 nRows = rSize.Height() / pView->nGridDY;
476 if( (nRows * pView->nGridDY) < rSize.Height() )
477 nRows++;
478 if( !nRows )
479 nRows = 1;
481 nDeltaWidth = (short)(rSize.Width() / nCols);
482 nDeltaHeight = (short)(rSize.Height() / nRows);
483 if( !nDeltaHeight )
485 nDeltaHeight = 1;
486 DBG_WARNING("SetDeltas:Bad height");
488 if( !nDeltaWidth )
490 nDeltaWidth = 1;
491 DBG_WARNING("SetDeltas:Bad width");
495 void IcnCursor_Impl::CreateGridAjustData( SvPtrarr& rLists, SvxIconChoiceCtrlEntry* pRefEntry)
497 if( !pRefEntry )
499 USHORT nGridRows = (USHORT)(pView->aVirtOutputSize.Height() / pView->nGridDY);
500 nGridRows++; // wg. Abrundung!
502 if( !nGridRows )
503 return;
504 for( USHORT nCurList = 0; nCurList < nGridRows; nCurList++ )
506 SvPtrarr* pRow = new SvPtrarr;
507 rLists.Insert( (void*)pRow, nCurList );
509 const ULONG nCount = pView->aEntries.Count();
510 for( ULONG nCur = 0; nCur < nCount; nCur++ )
512 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
513 const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
514 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
515 USHORT nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),FALSE);
516 ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns );
519 else
521 // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile
522 // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen???
523 Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
524 //const Rectangle& rRefRect = pView->GetEntryBoundRect( pRefEntry );
525 short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
526 SvPtrarr* pRow = new SvPtrarr;
527 rLists.Insert( (void*)pRow, 0 );
528 ULONG nCount = pView->aEntries.Count();
529 for( ULONG nCur = 0; nCur < nCount; nCur++ )
531 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur );
532 Rectangle rRect( pView->CalcBmpRect(pEntry) );
533 //const Rectangle& rRect = pView->GetEntryBoundRect( pEntry );
534 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
535 if( nY == nRefRow )
537 USHORT nIns = GetSortListPos( pRow, rRect.Left(), FALSE );
538 pRow->Insert( pEntry, nIns );
544 //static
545 void IcnCursor_Impl::DestroyGridAdjustData( SvPtrarr& rLists )
547 const USHORT nCount = rLists.Count();
548 for( USHORT nCur = 0; nCur < nCount; nCur++ )
550 SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ];
551 delete pArr;
553 rLists.Remove( 0, rLists.Count() );
556 IcnGridMap_Impl::IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView)
558 _pView = pView;
559 _pGridMap = 0;
560 _nGridCols = 0;
561 _nGridRows = 0;
564 IcnGridMap_Impl::~IcnGridMap_Impl()
566 delete[] _pGridMap, _pGridMap=0;
569 void IcnGridMap_Impl::Expand()
571 if( !_pGridMap )
572 Create_Impl();
573 else
575 USHORT nNewGridRows = _nGridRows;
576 USHORT nNewGridCols = _nGridCols;
577 if( _pView->nWinBits & WB_ALIGN_TOP )
578 nNewGridRows += 50;
579 else
580 nNewGridCols += 50;
582 BOOL* pNewGridMap = new BOOL[nNewGridRows*nNewGridCols];
583 memset( pNewGridMap, 0, nNewGridRows * nNewGridCols * sizeof(BOOL) );
584 memcpy( pNewGridMap, _pGridMap, _nGridRows * _nGridCols * sizeof(BOOL) );
585 delete[] _pGridMap;
586 _pGridMap = pNewGridMap;
587 _nGridRows = nNewGridRows;
588 _nGridCols = nNewGridCols;
592 void IcnGridMap_Impl::Create_Impl()
594 DBG_ASSERT(!_pGridMap,"Unnecessary call to IcnGridMap_Impl::Create_Impl()");
595 if( _pGridMap )
596 return;
597 GetMinMapSize( _nGridCols, _nGridRows );
598 if( _pView->nWinBits & WB_ALIGN_TOP )
599 _nGridRows += 50; // avoid resize of gridmap too often
600 else
601 _nGridCols += 50;
603 _pGridMap = new BOOL[ _nGridRows * _nGridCols];
604 memset( (void*)_pGridMap, 0, _nGridRows * _nGridCols );
606 const ULONG nCount = _pView->aEntries.Count();
607 for( ULONG nCur=0; nCur < nCount; nCur++ )
608 OccupyGrids( (SvxIconChoiceCtrlEntry*)_pView->aEntries.GetObject( nCur ));
611 void IcnGridMap_Impl::GetMinMapSize( USHORT& rDX, USHORT& rDY ) const
613 long nX, nY;
614 if( _pView->nWinBits & WB_ALIGN_TOP )
616 // The view grows in vertical direction. Its max. width is _pView->nMaxVirtWidth
617 nX = _pView->nMaxVirtWidth;
618 if( !nX )
619 nX = _pView->pView->GetOutputSizePixel().Width();
620 if( !(_pView->nFlags & F_ARRANGING) )
621 nX -= _pView->nVerSBarWidth;
623 nY = _pView->aVirtOutputSize.Height();
625 else
627 // The view grows in horizontal direction. Its max. height is _pView->nMaxVirtHeight
628 nY = _pView->nMaxVirtHeight;
629 if( !nY )
630 nY = _pView->pView->GetOutputSizePixel().Height();
631 if( !(_pView->nFlags & F_ARRANGING) )
632 nY -= _pView->nHorSBarHeight;
633 nX = _pView->aVirtOutputSize.Width();
636 if( !nX )
637 nX = DEFAULT_MAX_VIRT_WIDTH;
638 if( !nY )
639 nY = DEFAULT_MAX_VIRT_HEIGHT;
641 long nDX = nX / _pView->nGridDX;
642 long nDY = nY / _pView->nGridDY;
644 if( !nDX )
645 nDX++;
646 if( !nDY )
647 nDY++;
649 rDX = (USHORT)nDX;
650 rDY = (USHORT)nDY;
653 GridId IcnGridMap_Impl::GetGrid( USHORT nGridX, USHORT nGridY )
655 Create();
656 if( _pView->nWinBits & WB_ALIGN_TOP )
657 return nGridX + ( nGridY * _nGridCols );
658 else
659 return nGridY + ( nGridX * _nGridRows );
662 GridId IcnGridMap_Impl::GetGrid( const Point& rDocPos, BOOL* pbClipped )
664 Create();
666 long nX = rDocPos.X();
667 long nY = rDocPos.Y();
668 nX -= LROFFS_WINBORDER;
669 nY -= TBOFFS_WINBORDER;
670 nX /= _pView->nGridDX;
671 nY /= _pView->nGridDY;
672 BOOL bClipped = FALSE;
673 if( nX >= _nGridCols )
675 nX = _nGridCols - 1;
676 bClipped = TRUE;
678 if( nY >= _nGridRows )
680 nY = _nGridRows - 1;
681 bClipped = TRUE;
683 GridId nId = GetGrid( (USHORT)nX, (USHORT)nY );
684 if( pbClipped )
685 *pbClipped = bClipped;
686 DBG_ASSERT(nId <(ULONG)(_nGridCols*_nGridRows),"GetGrid failed");
687 return nId;
690 Rectangle IcnGridMap_Impl::GetGridRect( GridId nId )
692 Create();
693 USHORT nGridX, nGridY;
694 GetGridCoord( nId, nGridX, nGridY );
695 const long nLeft = nGridX * _pView->nGridDX+ LROFFS_WINBORDER;
696 const long nTop = nGridY * _pView->nGridDY + TBOFFS_WINBORDER;
697 return Rectangle(
698 nLeft, nTop,
699 nLeft + _pView->nGridDX,
700 nTop + _pView->nGridDY );
703 GridId IcnGridMap_Impl::GetUnoccupiedGrid( BOOL bOccupyFound )
705 Create();
706 ULONG nStart = 0;
707 BOOL bExpanded = FALSE;
709 while( 1 )
711 const ULONG nCount = (USHORT)(_nGridCols * _nGridRows);
712 for( ULONG nCur = nStart; nCur < nCount; nCur++ )
714 if( !_pGridMap[ nCur ] )
716 if( bOccupyFound )
717 _pGridMap[ nCur ] = TRUE;
718 return (GridId)nCur;
721 DBG_ASSERT(!bExpanded,"ExpandGrid failed");
722 if( bExpanded )
723 return 0; // prevent never ending loop
724 bExpanded = TRUE;
725 Expand();
726 nStart = nCount;
730 // ein Eintrag belegt nur das unter seinem Zentrum liegende GridRect
731 // diese Variante ist bedeutend schneller als die Belegung ueber das
732 // Bounding-Rect, kann aber zu kleinen Ueberlappungen fuehren
733 #define OCCUPY_CENTER
735 void IcnGridMap_Impl::OccupyGrids( const SvxIconChoiceCtrlEntry* pEntry, BOOL bOccupy )
737 if( !_pGridMap || !_pView->IsBoundingRectValid( pEntry->aRect ))
738 return;
739 #ifndef OCCUPY_CENTER
740 OccupyGrids( pEntry->aRect, bOccupy );
741 #else
742 OccupyGrid( GetGrid( pEntry->aRect.Center()), bOccupy );
743 #endif
747 void IcnGridMap_Impl::OccupyGrids( const Rectangle& rRect, BOOL bUsed )
749 if( !_pGridMap )
750 return;
752 if( bUsed )
754 if( _aLastOccupiedGrid == rRect )
755 return;
756 _aLastOccupiedGrid = rRect;
758 else
759 _aLastOccupiedGrid.SetEmpty();
761 BOOL bTopLeftClipped, bBottomRightClipped;
762 GridId nIdTL = GetGrid( rRect.TopLeft(), &bTopLeftClipped );
763 GridId nIdBR = GetGrid( rRect.BottomRight(), &bBottomRightClipped );
765 if( bTopLeftClipped && bBottomRightClipped )
766 return;
768 USHORT nX1,nX2,nY1,nY2;
769 GetGridCoord( nIdTL, nX1, nY1 );
770 GetGridCoord( nIdBR, nX2, nY2 );
771 USHORT nTemp;
772 if( nX1 > nX2 )
774 nTemp = nX1;
775 nX1 = nX2;
776 nX2 = nTemp;
778 if( nY1 > nY2 )
780 nTemp = nY1;
781 nY1 = nY2;
782 nY2 = nTemp;
784 for( ; nX1 <= nX2; nX1++ )
785 for( ; nY1 <= nY2; nY1++ )
786 OccupyGrid( GetGrid( nX1, nY1 ) );
789 void IcnGridMap_Impl::Clear()
791 if( _pGridMap )
793 delete[] _pGridMap, _pGridMap=0;
794 _nGridRows = 0;
795 _nGridCols = 0;
796 _aLastOccupiedGrid.SetEmpty();
800 ULONG IcnGridMap_Impl::GetGridCount( const Size& rSizePixel, USHORT nDX, USHORT nDY)
802 long ndx = (rSizePixel.Width() - LROFFS_WINBORDER) / nDX;
803 if( ndx < 0 ) ndx *= -1;
804 long ndy = (rSizePixel.Height() - TBOFFS_WINBORDER) / nDY;
805 if( ndy < 0 ) ndy *= -1;
806 return (ULONG)(ndx * ndy);
809 void IcnGridMap_Impl::OutputSizeChanged()
811 if( _pGridMap )
813 USHORT nCols, nRows;
814 GetMinMapSize( nCols, nRows );
815 if( _pView->nWinBits & WB_ALIGN_TOP )
817 if( nCols != _nGridCols )
818 Clear();
819 else if( nRows >= _nGridRows )
820 Expand();
822 else
824 if( nRows != _nGridRows )
825 Clear();
826 else if( nCols >= _nGridCols )
827 Expand();
832 // Independendly of the views alignment (TOP or LEFT) the gridmap
833 // should contain the data in a continues region, to make it possible
834 // to copy the whole block if the gridmap needs to be expanded.
835 void IcnGridMap_Impl::GetGridCoord( GridId nId, USHORT& rGridX, USHORT& rGridY )
837 Create();
838 if( _pView->nWinBits & WB_ALIGN_TOP )
840 rGridX = (USHORT)(nId % _nGridCols);
841 rGridY = (USHORT)(nId / _nGridCols);
843 else
845 rGridX = (USHORT)(nId / _nGridRows);
846 rGridY = (USHORT)(nId % _nGridRows);