xref: /trunk/main/svtools/source/contnr/imivctl1.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <limits.h>
32 #include <tools/debug.hxx>
33 #include <vcl/wall.hxx>
34 #include <vcl/help.hxx>
35 #include <vcl/decoview.hxx>
36 #include <vcl/svapp.hxx>
37 #include <tools/poly.hxx>
38 #include <vcl/lineinfo.hxx>
39 #include <vcl/i18nhelp.hxx>
40 #include <vcl/mnemonic.hxx>
41 #include <vcl/controllayout.hxx>
42 
43 #include <svtools/ivctrl.hxx>
44 #include "imivctl.hxx"
45 #include <svtools/svmedit.hxx>
46 
47 #include <algorithm>
48 #include <memory>
49 
50 #define DD_SCROLL_PIXEL 24
51 #define IMPICNVIEW_ACC_RETURN 1
52 #define IMPICNVIEW_ACC_ESCAPE 2
53 
54 #define DRAWTEXT_FLAGS_ICON \
55     ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
56       TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
57 
58 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
59 
60 #define EVENTID_SHOW_CURSOR             ((void*)1)
61 #define EVENTID_ADJUST_SCROLLBARS       ((void*)2)
62 
63 struct SvxIconChoiceCtrlEntry_Impl
64 {
65     SvxIconChoiceCtrlEntry* _pEntry;
66     Point           _aPos;
67                     SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect )
68                     : _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {}
69 };
70 
71 static sal_Bool bEndScrollInvalidate = sal_True;
72 
73 // ----------------------------------------------------------------------------------------------
74 
75 class IcnViewEdit_Impl : public MultiLineEdit
76 {
77     Link            aCallBackHdl;
78     Accelerator     aAccReturn;
79     Accelerator     aAccEscape;
80     Timer           aTimer;
81     sal_Bool            bCanceled;
82     sal_Bool            bAlreadyInCallback;
83     sal_Bool            bGrabFocus;
84 
85     void            CallCallBackHdl_Impl();
86                     DECL_LINK( Timeout_Impl, Timer * );
87                     DECL_LINK( ReturnHdl_Impl, Accelerator * );
88                     DECL_LINK( EscapeHdl_Impl, Accelerator * );
89 
90 public:
91 
92                     IcnViewEdit_Impl(
93                         SvtIconChoiceCtrl* pParent,
94                         const Point& rPos,
95                         const Size& rSize,
96                         const XubString& rData,
97                         const Link& rNotifyEditEnd );
98 
99                     ~IcnViewEdit_Impl();
100     virtual void    KeyInput( const KeyEvent& rKEvt );
101     virtual long    PreNotify( NotifyEvent& rNEvt );
102     sal_Bool            EditingCanceled() const { return bCanceled; }
103     void            StopEditing( sal_Bool bCancel = sal_False );
104     sal_Bool            IsGrabFocus() const { return bGrabFocus; }
105 };
106 
107 // ----------------------------------------------------------------------------------------------
108 
109 // ----------------------------------------------------------------------------------------------
110 
111 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pCurView,
112     WinBits nWinStyle ) :
113     aEntries( this ),
114     aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
115     aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ),
116     aScrBarBox( pCurView ),
117     aImageSize( 32, 32 ),
118     pColumns( 0 )
119 {
120     bChooseWithCursor=sal_False;
121     pEntryPaintDev = 0;
122     pCurEditedEntry = 0;
123     pCurHighlightFrame = 0;
124     pEdit = 0;
125     pAnchor = 0;
126     pDraggedSelection = 0;
127     pPrevDropTarget = 0;
128     pHdlEntry = 0;
129     pHead = NULL;
130     pCursor = NULL;
131     bUpdateMode = sal_True;
132     bEntryEditingEnabled = sal_False;
133     bInDragDrop = sal_False;
134     bHighlightFramePressed = sal_False;
135     eSelectionMode = MULTIPLE_SELECTION;
136     pView = pCurView;
137     pZOrderList = new List; //SvPtrarr;
138     ePositionMode = IcnViewPositionModeFree;
139     SetStyle( nWinStyle );
140     nFlags = 0;
141     nUserEventAdjustScrBars = 0;
142     nUserEventShowCursor = 0;
143     nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
144     nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
145     pDDRefEntry = 0;
146     pDDDev = 0;
147     pDDBufDev = 0;
148     pDDTempDev = 0;
149     eTextMode = IcnShowTextShort;
150     pImpCursor = new IcnCursor_Impl( this );
151     pGridMap = new IcnGridMap_Impl( this );
152 
153     aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
154     aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
155     Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) );
156     aVerSBar.SetEndScrollHdl( aEndScrollHdl );
157     aHorSBar.SetEndScrollHdl( aEndScrollHdl );
158 
159     nHorSBarHeight = aHorSBar.GetSizePixel().Height();
160     nVerSBarWidth = aVerSBar.GetSizePixel().Width();
161 
162     aEditTimer.SetTimeout( 800 );
163     aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
164     aAutoArrangeTimer.SetTimeout( 100 );
165     aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
166     aCallSelectHdlTimer.SetTimeout( 500 );
167     aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
168 
169     aDocRectChangedTimer.SetTimeout( 50 );
170     aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
171     aVisRectChangedTimer.SetTimeout( 50 );
172     aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
173 
174     Clear( sal_True );
175 
176     SetGrid( Size(100, 70) );
177 }
178 
179 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
180 {
181     pCurEditedEntry = 0;
182     DELETEZ(pEdit);
183     Clear();
184     StopEditTimer();
185     CancelUserEvents();
186     delete pZOrderList;
187     delete pImpCursor;
188     delete pGridMap;
189     delete pDDDev;
190     delete pDDBufDev;
191     delete pDDTempDev;
192     delete pDraggedSelection;
193     delete pEntryPaintDev;
194     ClearSelectedRectList();
195     ClearColumnList();
196 }
197 
198 void SvxIconChoiceCtrl_Impl::Clear( sal_Bool bInCtor )
199 {
200     StopEntryEditing( sal_True );
201     nSelectionCount = 0;
202     DELETEZ(pDraggedSelection);
203     bInDragDrop = sal_False;
204     pCurHighlightFrame = 0;
205     StopEditTimer();
206     CancelUserEvents();
207     ShowCursor( sal_False );
208     bBoundRectsDirty = sal_False;
209     nMaxBoundHeight = 0;
210 
211     nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
212     pCursor = 0;
213     if( !bInCtor )
214     {
215         pImpCursor->Clear();
216         pGridMap->Clear();
217         aVirtOutputSize.Width() = 0;
218         aVirtOutputSize.Height() = 0;
219         Size aSize( pView->GetOutputSizePixel() );
220         nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
221         if( nMaxVirtWidth <= 0 )
222             nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
223         nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
224         if( nMaxVirtHeight <= 0 )
225             nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
226         pZOrderList->Clear(); //Remove(0,pZOrderList->Count());
227         SetOrigin( Point() );
228         if( bUpdateMode )
229             pView->Invalidate(INVALIDATE_NOCHILDREN);
230     }
231     AdjustScrollBars();
232     sal_uLong nCount = aEntries.Count();
233     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
234     {
235         SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
236         delete pCur;
237     }
238     aEntries.Clear();
239     DocRectChanged();
240     VisRectChanged();
241 }
242 
243 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
244 {
245     nWinBits = nWinStyle;
246     nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
247     if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
248         nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
249     if( nWinBits & WB_NOSELECTION )
250         eSelectionMode = NO_SELECTION;
251     if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
252         nWinBits |= WB_ALIGN_LEFT;
253     if( (nWinStyle & WB_DETAILS))
254     {
255         if( !pColumns  )
256             SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
257     }
258 }
259 
260 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
261 {
262     StopEntryEditing( sal_True );
263     // Pfeil hoch: delta=-1; Pfeil runter: delta=+1
264     Scroll( 0, pScrollBar->GetDelta(), sal_True );
265     bEndScrollInvalidate = sal_True;
266     return 0;
267 }
268 
269 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
270 {
271     StopEntryEditing( sal_True );
272     // Pfeil links: delta=-1; Pfeil rechts: delta=+1
273     Scroll( pScrollBar->GetDelta(), 0, sal_True );
274     bEndScrollInvalidate = sal_True;
275     return 0;
276 }
277 
278 IMPL_LINK( SvxIconChoiceCtrl_Impl, EndScrollHdl, void*, EMPTYARG )
279 {
280     if( pView->HasBackground() && !pView->GetBackground().IsScrollable() &&
281         bEndScrollInvalidate )
282     {
283         pView->Invalidate(INVALIDATE_NOCHILDREN);
284     }
285     return 0;
286 }
287 
288 void SvxIconChoiceCtrl_Impl::FontModified()
289 {
290     StopEditTimer();
291     DELETEZ(pDDDev);
292     DELETEZ(pDDBufDev);
293     DELETEZ(pDDTempDev);
294     DELETEZ(pEntryPaintDev);
295     SetDefaultTextSize();
296     ShowCursor( sal_False );
297     ShowCursor( sal_True );
298 }
299 
300 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos,
301     const Point* pPos )
302 {
303     StopEditTimer();
304     aEntries.Insert( pEntry, nPos );
305     if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.Count() - 1 )
306         pEntry->nPos = aEntries.Count() - 1;
307     else
308         nFlags &= ~F_ENTRYLISTPOS_VALID;
309 
310     pZOrderList->Insert( (void*)pEntry, LIST_APPEND ); //pZOrderList->Count() );
311     pImpCursor->Clear();
312 //  pGridMap->Clear();
313     if( pPos )
314     {
315         Size aSize( CalcBoundingSize( pEntry ) );
316         SetBoundingRect_Impl( pEntry, *pPos, aSize );
317         SetEntryPos( pEntry, *pPos, sal_False, sal_True, sal_True /*keep grid map*/ );
318         pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED;
319         SetEntriesMoved( sal_True );
320     }
321     else
322     {
323         // wenn der UpdateMode sal_True ist, wollen wir nicht pauschal alle
324         // BoundRects auf 'zu ueberpruefen' setzen, sondern nur das des
325         // neuen Eintrags. Deshalb kein InvalidateBoundingRect aufrufen!
326         pEntry->aRect.Right() = LONG_MAX;
327         if( bUpdateMode )
328         {
329             FindBoundingRect( pEntry );
330             Rectangle aOutputArea( GetOutputRect() );
331             pGridMap->OccupyGrids( pEntry );
332             if( !aOutputArea.IsOver( pEntry->aRect ) )
333                 return; // ist nicht sichtbar
334             pView->Invalidate( pEntry->aRect );
335         }
336         else
337             InvalidateBoundingRect( pEntry->aRect );
338     }
339 }
340 
341 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
342 {
343     ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
344     if ( !_pGenerator )
345     {
346         _pGenerator = new MnemonicGenerator;
347         pAutoDeleteOwnGenerator.reset( _pGenerator );
348     }
349 
350     sal_uLong   nEntryCount = GetEntryCount();
351     sal_uLong   i;
352 
353     // insert texts in generator
354     for( i = 0; i < nEntryCount; ++i )
355     {
356         DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
357 
358         _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
359     }
360 
361     // exchange texts with generated mnemonics
362     for( i = 0; i < nEntryCount; ++i )
363     {
364         SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
365         String                  aTxt = pEntry->GetText();
366 
367         if( _pGenerator->CreateMnemonic( aTxt ) )
368             pEntry->SetText( aTxt );
369     }
370 }
371 
372 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
373 {
374     Point aOrigin( pView->GetMapMode().GetOrigin() );
375     aOrigin *= -1;
376     return Rectangle( aOrigin, aOutputSize );
377 }
378 
379 void SvxIconChoiceCtrl_Impl::SetListPositions()
380 {
381     if( nFlags & F_ENTRYLISTPOS_VALID )
382         return;
383 
384     sal_uLong nCount = aEntries.Count();
385     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
386     {
387         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
388         pEntry->nPos = nCur;
389     }
390     nFlags |= F_ENTRYLISTPOS_VALID;
391 }
392 
393 void SvxIconChoiceCtrl_Impl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry )
394 {
395     sal_Bool bSyncSingleSelection;
396     // bei Single-Selection wird die Selektion beim Umsetzen des Cursors
397     // mitgefuehrt. Das soll aber nur erfolgen, wenn ueberhaupt ein
398     // Eintrag selektiert ist.
399     if( GetSelectionCount() )
400         bSyncSingleSelection = sal_True;
401     else
402         bSyncSingleSelection = sal_False;
403 
404     if( pEntry == pCurHighlightFrame )
405         pCurHighlightFrame = 0;
406 
407     if( bInDragDrop )
408     {
409         DELETEZ(pDraggedSelection);
410         bInDragDrop = sal_False;
411     }
412 
413     if( pEntry->IsSelected() )
414         CallSelectHandler( 0 );
415 
416     if( aEntries.Count() == 1 && aEntries.GetObject(0) == pEntry )
417     {
418         Clear();
419         return;
420     }
421 
422     StopEditTimer();
423     if( pEntry == pAnchor )
424         pAnchor = 0;
425     if( pEntry->IsSelected() )
426         nSelectionCount--;
427     sal_Bool bEntryBoundValid = IsBoundingRectValid( pEntry->aRect );
428     if( bEntryBoundValid )
429         pView->Invalidate( pEntry->aRect );
430 
431     sal_Bool bSetNewCursor = sal_False;
432     SvxIconChoiceCtrlEntry* pNewCursor = NULL;
433 
434     if( pEntry == pCursor )
435     {
436         bSetNewCursor = sal_True;
437         pNewCursor = FindNewCursor();
438         ShowCursor( sal_False );
439         pCursor = 0;
440     }
441 
442     sal_Bool bCurEntryPosValid = (nFlags & F_ENTRYLISTPOS_VALID) ? sal_True : sal_False;
443     if( bCurEntryPosValid && aEntries.GetObject(aEntries.Count()-1) != pEntry )
444         nFlags &= ~F_ENTRYLISTPOS_VALID;
445     sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry );
446     pZOrderList->Remove( nPos );
447     if( bCurEntryPosValid )
448     {
449         DBG_ASSERT(aEntries.GetObject(pEntry->nPos)==pEntry,"RemoveEntry: Wrong nPos in entry");
450         aEntries.Remove( pEntry->nPos );
451     }
452     else
453         aEntries.Remove( pEntry );
454     pImpCursor->Clear();
455     pGridMap->Clear();
456     delete pEntry;
457     if( IsAutoArrange() && aEntries.Count() )
458         aAutoArrangeTimer.Start();
459     if( bSetNewCursor )
460     {
461         // Fokusrechteck asynchron einblenden, um das Loeschen einer
462         // Multiselektion zu beschleunigen.
463         SetCursor( pNewCursor, bSyncSingleSelection, sal_True );
464     }
465 }
466 
467 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
468     sal_Bool bCallHdl, sal_Bool bAdd, sal_Bool bSyncPaint )
469 {
470     if( eSelectionMode == NO_SELECTION )
471         return;
472 
473     if( !bAdd )
474     {
475         if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
476         {
477             nFlags |= F_CLEARING_SELECTION;
478             DeselectAllBut( pEntry, sal_True );
479             nFlags &= ~F_CLEARING_SELECTION;
480         }
481     }
482     if( pEntry->IsSelected() != bSelect )
483     {
484         pHdlEntry = pEntry;
485         sal_uInt16 nEntryFlags = pEntry->GetFlags();
486         if( bSelect )
487         {
488             nEntryFlags |= ICNVIEW_FLAG_SELECTED;
489             pEntry->AssignFlags( nEntryFlags );
490             nSelectionCount++;
491             if( bCallHdl )
492                 CallSelectHandler( pEntry );
493         }
494         else
495         {
496             nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
497             pEntry->AssignFlags( nEntryFlags );
498             nSelectionCount--;
499             if( bCallHdl )
500                 CallSelectHandler( 0 );
501         }
502         EntrySelected( pEntry, bSelect, bSyncPaint );
503     }
504 }
505 
506 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
507     sal_Bool bSyncPaint )
508 {
509     // bei SingleSelection dafuer sorgen, dass der Cursor immer
510     // auf dem (einzigen) selektierten Eintrag steht. Aber nur,
511     // wenn es bereits einen Cursor gibt
512     if( bSelect && pCursor &&
513         eSelectionMode == SINGLE_SELECTION &&
514         pEntry != pCursor )
515     {
516         SetCursor( pEntry );
517         //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
518     }
519 
520     // beim Aufziehen nicht, da sonst die Schleife in SelectRect
521     // nicht richtig funktioniert!
522     if( !(nFlags & F_SELECTING_RECT) )
523         ToTop( pEntry );
524     if( bUpdateMode )
525     {
526         if( pEntry == pCursor )
527             ShowCursor( sal_False );
528         if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // beim Tracken immer synchron
529             PaintEntry( pEntry );
530         else if( bSyncPaint ) // synchron & mit virtuellem OutDev!
531             PaintEntryVirtOutDev( pEntry );
532         else
533         {
534             pView->Invalidate( CalcFocusRect( pEntry ) );
535         }
536         if( pEntry == pCursor )
537             ShowCursor( sal_True );
538     } // if( bUpdateMode )
539 
540     // --> OD 2009-05-27 #i101012#
541     // emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
542     if ( bSelect )
543     {
544         CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
545     }
546     // <--
547 }
548 
549 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
550 {
551     StopEditTimer();
552     aVirtOutputSize.Width() = 0;
553     aVirtOutputSize.Height() = 0;
554     sal_Bool bLockedEntryFound = sal_False;
555     const sal_uLong nCount = aEntries.Count();
556     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
557     {
558         SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
559         pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
560         if( pCur->IsPosLocked() )
561         {
562             // VirtSize u.a. anpassen
563             if( !IsBoundingRectValid( pCur->aRect ) )
564                 FindBoundingRect( pCur );
565             else
566                 AdjustVirtSize( pCur->aRect );
567             bLockedEntryFound = sal_True;
568         }
569         else
570             InvalidateBoundingRect( pCur->aRect );
571     }
572 
573     if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
574     {
575         Size aRealOutputSize( pView->GetOutputSizePixel() );
576         if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
577             aVirtOutputSize.Height() < aRealOutputSize.Height() )
578         {
579             sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
580                 aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
581             if( nGridCount < nCount )
582             {
583                 if( nWinBits & WB_ALIGN_TOP )
584                     nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
585                 else // WB_ALIGN_LEFT
586                     nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
587             }
588         }
589     }
590 
591     pImpCursor->Clear();
592     pGridMap->Clear();
593     VisRectChanged();
594 }
595 
596 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
597 {
598     long nHeightOffs = 0;
599     long nWidthOffs = 0;
600 
601     if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
602         nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
603 
604     if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
605         nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
606 
607     if( nWidthOffs || nHeightOffs )
608     {
609         Range aRange;
610         aVirtOutputSize.Width() += nWidthOffs;
611         aRange.Max() = aVirtOutputSize.Width();
612         aHorSBar.SetRange( aRange );
613 
614         aVirtOutputSize.Height() += nHeightOffs;
615         aRange.Max() = aVirtOutputSize.Height();
616         aVerSBar.SetRange( aRange );
617 
618         pImpCursor->Clear();
619         pGridMap->OutputSizeChanged();
620         AdjustScrollBars();
621         DocRectChanged();
622     }
623 }
624 
625 void SvxIconChoiceCtrl_Impl::InitPredecessors()
626 {
627     DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
628     sal_uLong nCount = aEntries.Count();
629     if( nCount )
630     {
631         SvxIconChoiceCtrlEntry* pPrev = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
632         for( sal_uLong nCur = 1; nCur <= nCount; nCur++ )
633         {
634             pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
635                                 ICNVIEW_FLAG_PRED_SET);
636 
637             SvxIconChoiceCtrlEntry* pNext;
638             if( nCur == nCount )
639                 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
640             else
641                 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
642             pPrev->pflink = pNext;
643             pNext->pblink = pPrev;
644             pPrev = pNext;
645         }
646         pHead = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
647     }
648     else
649         pHead = 0;
650     nFlags &= ~F_MOVED_ENTRIES;
651 }
652 
653 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
654 {
655     if( pHead )
656     {
657         sal_uLong nCount = aEntries.Count();
658         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
659         {
660             SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
661             pCur->pflink = 0;
662             pCur->pblink = 0;
663             pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
664         }
665         pHead = 0;
666     }
667 }
668 
669 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
670 {
671     if ( nSetMaxVirtWidth != 0 )
672         nMaxVirtWidth = nSetMaxVirtWidth;
673     else
674         nMaxVirtWidth = aOutputSize.Width();
675 
676     if ( nSetMaxVirtHeight != 0 )
677         nMaxVirtHeight = nSetMaxVirtHeight;
678     else
679         nMaxVirtHeight = aOutputSize.Height();
680 
681     ImpArrange( bKeepPredecessors );
682 }
683 
684 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors )
685 {
686     static Point aEmptyPoint;
687 
688     sal_Bool bOldUpdate = bUpdateMode;
689     Rectangle aCurOutputArea( GetOutputRect() );
690     if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
691         bUpdateMode = sal_False;
692     aAutoArrangeTimer.Stop();
693     nFlags &= ~F_MOVED_ENTRIES;
694     nFlags |= F_ARRANGING;
695     StopEditTimer();
696     ShowCursor( sal_False );
697     ResetVirtSize();
698     if( !bKeepPredecessors )
699         ClearPredecessors();
700     bBoundRectsDirty = sal_False;
701     SetOrigin( Point() );
702     VisRectChanged();
703     RecalcAllBoundingRectsSmart();
704     // in der Detailsview muss das Invalidieren intelligenter erfolgen
705     //if( !(nWinBits & WB_DETAILS ))
706         pView->Invalidate( INVALIDATE_NOCHILDREN );
707     nFlags &= ~F_ARRANGING;
708     if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
709     {
710         MakeVisible( aCurOutputArea );
711         SetUpdateMode( bOldUpdate );
712     }
713     ShowCursor( sal_True );
714 }
715 
716 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
717 {
718     bEndScrollInvalidate = sal_False;
719 
720 #if defined(OV_DRAWGRID)
721     Color aOldColor ( pView->GetLineColor() );
722     Color aColor( COL_BLACK );
723     pView->SetLineColor( aColor );
724     Point aOffs( pView->GetMapMode().GetOrigin());
725     Size aXSize( pView->GetOutputSizePixel() );
726 
727     {
728     Point aStart( LROFFS_WINBORDER, 0 );
729     Point aEnd( LROFFS_WINBORDER, aXSize.Height());
730     aStart -= aOffs;
731     aEnd -= aOffs;
732     pView->DrawLine( aStart, aEnd );
733     }
734     {
735     Point aStart( 0, TBOFFS_WINBORDER );
736     Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
737     aStart -= aOffs;
738     aEnd -= aOffs;
739     pView->DrawLine( aStart, aEnd );
740     }
741 
742     for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
743     {
744         Point aStart( nDX+LROFFS_WINBORDER, 0 );
745         Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
746         aStart -= aOffs;
747         aEnd -= aOffs;
748         pView->DrawLine( aStart, aEnd );
749     }
750     for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
751     {
752         Point aStart( 0, nDY+TBOFFS_WINBORDER );
753         Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
754         aStart -= aOffs;
755         aEnd -= aOffs;
756         pView->DrawLine( aStart, aEnd );
757     }
758     pView->SetLineColor( aOldColor );
759 #endif
760     nFlags |= F_PAINTED;
761 
762     if( !aEntries.Count() )
763         return;
764     if( !pCursor )
765     {
766         // set cursor to item with focus-flag
767         sal_Bool bfound = sal_False;
768         for ( sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++)
769         {
770             SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
771             if( pEntry->IsFocused() )
772             {
773                 pCursor = pEntry;
774                 bfound=sal_True;
775             }
776         }
777 
778         if( !bfound )
779             pCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
780     }
781 
782     // Show Focus at Init-Time
783     if ( pView->HasFocus() )
784         GetFocus();
785 
786     sal_uLong nCount = pZOrderList->Count();
787     if( !nCount )
788         return;
789 
790     sal_Bool bResetClipRegion = sal_False;
791     if( !pView->IsClipRegion() )
792     {
793         Rectangle aOutputArea( GetOutputRect() );
794         bResetClipRegion = sal_True;
795         pView->SetClipRegion( aOutputArea );
796     }
797 
798     const sal_uInt16 nListInitSize = aEntries.Count() > USHRT_MAX ?
799         USHRT_MAX : (sal_uInt16)aEntries.Count();
800     List* pNewZOrderList = new List( nListInitSize );
801     List* pPaintedEntries = new List( nListInitSize );
802 
803     sal_uLong nPos = 0;
804     while( nCount )
805     {
806         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
807         const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
808         if( rRect.IsOver( rBoundRect ) )
809         {
810             PaintEntry( pEntry, rBoundRect.TopLeft(), pView, sal_True );
811             // Eintraege, die neu gezeichnet werden, auf Top setzen
812             pPaintedEntries->Insert( pEntry, LIST_APPEND );
813         }
814         else
815             pNewZOrderList->Insert( pEntry, LIST_APPEND );
816 
817         nCount--;
818         nPos++;
819     }
820     delete pZOrderList;
821     pZOrderList = pNewZOrderList;
822     nCount = pPaintedEntries->Count();
823     if( nCount )
824     {
825         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
826             pZOrderList->Insert( pPaintedEntries->GetObject(nCur), LIST_APPEND);
827     }
828     delete pPaintedEntries;
829 
830     if( bResetClipRegion )
831         pView->SetClipRegion();
832 }
833 
834 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask )
835 {
836     const sal_uLong nCount = pZOrderList->Count();
837     if( !nCount )
838         return;
839 
840     sal_Bool bResetClipRegion = sal_False;
841     Rectangle aOutRect( GetOutputRect() );
842     if( !pView->IsClipRegion() )
843     {
844         bResetClipRegion = sal_True;
845         pView->SetClipRegion( aOutRect );
846     }
847     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
848     {
849         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
850         if( pEntry->GetFlags() & nEntryFlagsMask )
851         {
852             const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
853             if( aOutRect.IsOver( rBoundRect ) )
854                 PaintEntry( pEntry, rBoundRect.TopLeft() );
855         }
856     }
857     if( bResetClipRegion )
858         pView->SetClipRegion();
859 }
860 
861 
862 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
863 {
864     aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
865     Size aSize( pView->GetOutputSizePixel() );
866     aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
867 }
868 
869 IcnViewFieldType SvxIconChoiceCtrl_Impl::GetItem( SvxIconChoiceCtrlEntry* pEntry,
870     const Point& rAbsPos )
871 {
872     Rectangle aRect( CalcTextRect( pEntry ) );
873     if( aRect.IsInside( rAbsPos ) )
874         return IcnViewFieldTypeText;
875 
876     aRect = CalcBmpRect( pEntry );
877     if( aRect.IsInside( rAbsPos ) )
878         return IcnViewFieldTypeImage;
879 
880     return IcnViewFieldTypeDontknow;
881 }
882 
883 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
884 {
885     sal_Bool bHandled = sal_True;
886     bHighlightFramePressed = sal_False;
887     StopEditTimer();
888     sal_Bool bGotFocus = (sal_Bool)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
889     if( !(nWinBits & WB_NOPOINTERFOCUS) )
890         pView->GrabFocus();
891 
892     Point aDocPos( rMEvt.GetPosPixel() );
893     if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
894         return sal_False;
895     ToDocPos( aDocPos );
896     SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
897     if( pEntry )
898         MakeEntryVisible( pEntry, sal_False );
899 
900     if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
901     {
902         if( pEntry )
903             SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), sal_True);
904         return sal_True;
905     }
906 
907     if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // Tastaturselektion?
908     {
909         DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
910         if( rMEvt.IsMod1() )
911             nFlags |= F_ADD_MODE;
912 
913         if( rMEvt.IsShift() )
914         {
915             Rectangle aRect( GetEntryBoundRect( pAnchor ));
916             if( pEntry )
917                 aRect.Union( GetEntryBoundRect( pEntry ) );
918             else
919             {
920                 Rectangle aTempRect( aDocPos, Size(1,1));
921                 aRect.Union( aTempRect );
922             }
923             aCurSelectionRect = aRect;
924             SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
925         }
926         else if( rMEvt.IsMod1() )
927         {
928             AddSelectedRect( aCurSelectionRect );
929             pAnchor = 0;
930             aCurSelectionRect.SetPos( aDocPos );
931         }
932 
933         if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
934             pView->StartTracking( STARTTRACK_SCROLLREPEAT );
935         return sal_True;
936     }
937     else
938     {
939         if( !pEntry )
940         {
941             if( eSelectionMode == MULTIPLE_SELECTION )
942             {
943                 if( !rMEvt.IsMod1() )  // Ctrl
944                 {
945                     if( !bGotFocus )
946                     {
947                         SetNoSelection();
948                         ClearSelectedRectList();
949                     }
950                 }
951                 else
952                     nFlags |= F_ADD_MODE;
953                 aCurSelectionRect.SetPos( aDocPos );
954                 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
955             }
956             else
957                 bHandled = sal_False;
958             return bHandled;
959         }
960     }
961     sal_Bool bSelected = pEntry->IsSelected();
962     sal_Bool bEditingEnabled = IsEntryEditingEnabled();
963 
964     if( rMEvt.GetClicks() == 2 )
965     {
966         DeselectAllBut( pEntry );
967         SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
968         pHdlEntry = pEntry;
969         pView->ClickIcon();
970     }
971     else
972     {
973         // Inplace-Editing ?
974         if( rMEvt.IsMod2() )  // Alt?
975         {
976             if( bEntryEditingEnabled && pEntry &&
977                 pEntry->IsSelected())
978             {
979                 if( pView->EditingEntry( pEntry ))
980                     EditEntry( pEntry );
981             }
982         }
983         else if( eSelectionMode == SINGLE_SELECTION )
984         {
985             DeselectAllBut( pEntry );
986             SetCursor( pEntry );
987             if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
988                 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
989             {
990                 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
991             }
992         }
993         else if( eSelectionMode == NO_SELECTION )
994         {
995             if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
996             {
997                 pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
998                 bHighlightFramePressed = sal_True;
999                 SetEntryHighlightFrame( pEntry, sal_True );
1000             }
1001         }
1002         else
1003         {
1004             if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
1005             {
1006                 if( !bSelected )
1007                 {
1008                     DeselectAllBut( pEntry, sal_True /* Synchron painten */ );
1009                     SetCursor( pEntry );
1010                     SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
1011                 }
1012                 else
1013                 {
1014                     // erst im Up deselektieren, falls Move per D&D!
1015                     nFlags |= F_DOWN_DESELECT;
1016                     if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
1017                         rMEvt.IsLeft())
1018                     {
1019                         nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1020                     }
1021                 }
1022             }
1023             else if( rMEvt.IsMod1() )
1024                 nFlags |= F_DOWN_CTRL;
1025         }
1026     }
1027     return bHandled;
1028 }
1029 
1030 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
1031 {
1032     sal_Bool bHandled = sal_False;
1033     if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
1034     {
1035         nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1036         bHandled = sal_True;
1037     }
1038 
1039     Point aDocPos( rMEvt.GetPosPixel() );
1040     ToDocPos( aDocPos );
1041     SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
1042     if( pDocEntry )
1043     {
1044         if( nFlags & F_DOWN_CTRL )
1045         {
1046             // Ctrl & MultiSelection
1047             ToggleSelection( pDocEntry );
1048             SetCursor( pDocEntry );
1049             bHandled = sal_True;
1050         }
1051         else if( nFlags & F_DOWN_DESELECT )
1052         {
1053             DeselectAllBut( pDocEntry );
1054             SetCursor( pDocEntry );
1055             SelectEntry( pDocEntry, sal_True, sal_True, sal_False, sal_True );
1056             bHandled = sal_True;
1057         }
1058     }
1059 
1060     nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1061     if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
1062     {
1063         bHandled = sal_True;
1064         StartEditTimer();
1065         nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
1066     }
1067 
1068     if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
1069     {
1070         bHandled = sal_True;
1071         SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
1072         pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
1073         bHighlightFramePressed = sal_False;
1074         SetEntryHighlightFrame( pEntry, sal_True );
1075 #if 0
1076         CallSelectHandler( pCurHighlightFrame );
1077 #else
1078         pHdlEntry = pCurHighlightFrame;
1079         pView->ClickIcon();
1080 
1081         // set focus on Icon
1082         SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1083         SetCursor_Impl( pOldCursor, pHdlEntry, sal_False, sal_False, sal_True );
1084 #endif
1085         pHdlEntry = 0;
1086     }
1087     return bHandled;
1088 }
1089 
1090 sal_Bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
1091 {
1092     const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
1093 
1094     if( pView->IsTracking() )
1095         return sal_False;
1096     else if( nWinBits & WB_HIGHLIGHTFRAME )
1097     {
1098         SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
1099         SetEntryHighlightFrame( pEntry );
1100     }
1101     else
1102         return sal_False;
1103     return sal_True;
1104 }
1105 
1106 void SvxIconChoiceCtrl_Impl::Tracking( const TrackingEvent& rTEvt )
1107 {
1108     if ( rTEvt.IsTrackingEnded() )
1109     {
1110         // Das Rechteck darf nicht "justified" sein, da seine
1111         // TopLeft-Position u.U. zur Berechnung eines Ankers
1112         // benutzt wird.
1113         AddSelectedRect( aCurSelectionRect );
1114         pView->HideTracking();
1115         nFlags &= ~(F_ADD_MODE);
1116         if( rTEvt.IsTrackingCanceled() )
1117             SetNoSelection();
1118     }
1119     else
1120     {
1121         Point aPosPixel = rTEvt.GetMouseEvent().GetPosPixel();
1122         Point aDocPos( aPosPixel );
1123         ToDocPos( aDocPos );
1124 
1125         long nScrollDX, nScrollDY;
1126 
1127         CalcScrollOffsets( aPosPixel, nScrollDX, nScrollDY, sal_False );
1128         if( nScrollDX || nScrollDY )
1129         {
1130             pView->HideTracking();
1131             pView->Scroll( nScrollDX, nScrollDY );
1132         }
1133         Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
1134         if( aRect != aCurSelectionRect )
1135         {
1136             pView->HideTracking();
1137             sal_Bool bAdd = (nFlags & F_ADD_MODE) ? sal_True : sal_False;
1138             SelectRect( aRect, bAdd, &aSelectedRectList );
1139         }
1140         pView->ShowTracking( aRect, SHOWTRACK_SMALL | SHOWTRACK_CLIP );
1141     }
1142 }
1143 
1144 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
1145     SvxIconChoiceCtrlEntry* pNewCursor, sal_Bool bMod1, sal_Bool bShift, sal_Bool bPaintSync )
1146 {
1147     if( pNewCursor )
1148     {
1149         SvxIconChoiceCtrlEntry* pFilterEntry = 0;
1150         sal_Bool bDeselectAll = sal_False;
1151         if( eSelectionMode != SINGLE_SELECTION )
1152         {
1153             if( !bMod1 && !bShift )
1154                 bDeselectAll = sal_True;
1155             else if( bShift && !bMod1 && !pAnchor )
1156             {
1157                 bDeselectAll = sal_True;
1158                 pFilterEntry = pOldCursor;
1159             }
1160         }
1161         if( bDeselectAll )
1162             DeselectAllBut( pFilterEntry, bPaintSync );
1163         ShowCursor( sal_False );
1164         MakeEntryVisible( pNewCursor );
1165         SetCursor( pNewCursor );
1166         if( bMod1 && !bShift )
1167         {
1168             if( pAnchor )
1169             {
1170                 AddSelectedRect( pAnchor, pOldCursor );
1171                 pAnchor = 0;
1172             }
1173         }
1174         else if( bShift )
1175         {
1176             if( !pAnchor )
1177                 pAnchor = pOldCursor;
1178             if ( nWinBits & WB_ALIGN_LEFT )
1179                 SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
1180             else
1181                 SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
1182         }
1183         else
1184         {
1185             SelectEntry( pCursor, sal_True, sal_True,  sal_False, bPaintSync );
1186             aCurSelectionRect = GetEntryBoundRect( pCursor );
1187         }
1188     }
1189 }
1190 
1191 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1192 {
1193     StopEditTimer();
1194 
1195     sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2();
1196     sal_Unicode cChar = rKEvt.GetCharCode();
1197     sal_uLong nPos = (sal_uLong)-1;
1198     if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1199     {
1200         // shortcut is clicked
1201         SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1202         SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1203         if ( pNewCursor != pOldCursor )
1204             SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
1205         return sal_True;
1206     }
1207 
1208     if ( bMod2 )
1209         // no actions with <ALT>
1210         return sal_False;
1211 
1212     sal_Bool bKeyUsed = sal_True;
1213     sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1214     sal_Bool bShift = rKEvt.GetKeyCode().IsShift();
1215 
1216     if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1217     {
1218         bShift = sal_False;
1219         bMod1 = sal_False;
1220     }
1221 
1222     if( bMod1 )
1223         nFlags |= F_ADD_MODE;
1224     sal_Bool bDeselectAll = sal_False;
1225     if( eSelectionMode != SINGLE_SELECTION )
1226     {
1227         if( !bMod1 && !bShift )
1228             bDeselectAll = sal_True;
1229         if( bShift && !bMod1 && !pAnchor )
1230             bDeselectAll = sal_True;
1231     }
1232 
1233     SvxIconChoiceCtrlEntry* pNewCursor;
1234     SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1235 
1236     sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1237     switch( nCode )
1238     {
1239         case KEY_UP:
1240         case KEY_PAGEUP:
1241             if( pCursor )
1242             {
1243                 MakeEntryVisible( pCursor );
1244                 if( nCode == KEY_UP )
1245                     pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1246                 else
1247                     pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False);
1248                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1249                 if( !pNewCursor )
1250                 {
1251                     Rectangle aRect( GetEntryBoundRect( pCursor ) );
1252                     if( aRect.Top())
1253                     {
1254                         aRect.Bottom() -= aRect.Top();
1255                         aRect.Top() = 0;
1256                         MakeVisible( aRect );
1257                     }
1258                 }
1259 
1260                 if ( bChooseWithCursor && pNewCursor != NULL )
1261                 {
1262                     pHdlEntry = pNewCursor;//GetCurEntry();
1263                     pCurHighlightFrame = pHdlEntry;
1264                     pView->ClickIcon();
1265                     pCurHighlightFrame = NULL;
1266                 }
1267             }
1268             break;
1269 
1270         case KEY_DOWN:
1271         case KEY_PAGEDOWN:
1272             if( pCursor )
1273             {
1274                 if( nCode == KEY_DOWN )
1275                     pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1276                 else
1277                     pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True );
1278                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1279 
1280                 if ( bChooseWithCursor && pNewCursor != NULL)
1281                 {
1282                     pHdlEntry = pNewCursor;//GetCurEntry();
1283                     pCurHighlightFrame = pHdlEntry;
1284                     pView->ClickIcon();
1285                     pCurHighlightFrame = NULL;
1286                 }
1287             }
1288             break;
1289 
1290         case KEY_RIGHT:
1291             if( pCursor )
1292             {
1293                 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1294                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1295             }
1296             break;
1297 
1298         case KEY_LEFT:
1299             if( pCursor )
1300             {
1301                 MakeEntryVisible( pCursor );
1302                 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1303                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1304                 if( !pNewCursor )
1305                 {
1306                     Rectangle aRect( GetEntryBoundRect(pCursor));
1307                     if( aRect.Left() )
1308                     {
1309                         aRect.Right() -= aRect.Left();
1310                         aRect.Left() = 0;
1311                         MakeVisible( aRect );
1312                     }
1313                 }
1314             }
1315             break;
1316 
1317 // wird vom VCL-Tracking gesteuert
1318 #if 0
1319         case KEY_ESCAPE:
1320             if( pView->IsTracking() )
1321             {
1322                 HideSelectionRect();
1323                 //SelectAll( sal_False );
1324                 SetNoSelection();
1325                 ClearSelectedRectList();
1326                 nFlags &= ~F_TRACKING;
1327             }
1328             else
1329                 bKeyUsed = sal_False;
1330             break;
1331 #endif
1332 
1333 
1334         case KEY_F2:
1335             if( !bMod1 && !bShift )
1336                 EditTimeoutHdl( 0 );
1337             else
1338                 bKeyUsed = sal_False;
1339             break;
1340 
1341         case KEY_F8:
1342             if( rKEvt.GetKeyCode().IsShift() )
1343             {
1344                 if( nFlags & F_ADD_MODE )
1345                     nFlags &= (~F_ADD_MODE);
1346                 else
1347                     nFlags |= F_ADD_MODE;
1348             }
1349             else
1350                 bKeyUsed = sal_False;
1351             break;
1352 
1353         case KEY_SPACE:
1354             if( pCursor && eSelectionMode != SINGLE_SELECTION )
1355             {
1356                 if( !bMod1 )
1357                 {
1358                     //SelectAll( sal_False );
1359                     SetNoSelection();
1360                     ClearSelectedRectList();
1361 
1362                     // click Icon with spacebar
1363                     SetEntryHighlightFrame( GetCurEntry(), sal_True );
1364                     pView->ClickIcon();
1365                     pHdlEntry = pCurHighlightFrame;
1366                     pCurHighlightFrame=0;
1367                 }
1368                 else
1369                     ToggleSelection( pCursor );
1370             }
1371             break;
1372 
1373 #ifdef DBG_UTIL
1374         case KEY_F10:
1375             if( rKEvt.GetKeyCode().IsShift() )
1376             {
1377                 if( pCursor )
1378                     pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1379             }
1380             if( rKEvt.GetKeyCode().IsMod1() )
1381             {
1382                 if( pCursor )
1383                     pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1384             }
1385             break;
1386 #endif
1387 
1388         case KEY_ADD:
1389         case KEY_DIVIDE :
1390         case KEY_A:
1391             if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1392                 SelectAll( sal_True );
1393             else
1394                 bKeyUsed = sal_False;
1395             break;
1396 
1397         case KEY_SUBTRACT:
1398         case KEY_COMMA :
1399             if( bMod1 )
1400                 SetNoSelection();
1401             else
1402                 bKeyUsed = sal_False;
1403             break;
1404 
1405         case KEY_RETURN:
1406             if( bMod1 )
1407             {
1408                 if( pCursor && bEntryEditingEnabled )
1409                     /*pView->*/EditEntry( pCursor );
1410             }
1411             else
1412                 bKeyUsed = sal_False;
1413             break;
1414 
1415         case KEY_END:
1416             if( pCursor )
1417             {
1418                 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 );
1419                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1420             }
1421             break;
1422 
1423         case KEY_HOME:
1424             if( pCursor )
1425             {
1426                 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
1427                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1428             }
1429             break;
1430 
1431         default:
1432             bKeyUsed = sal_False;
1433 
1434     }
1435     return bKeyUsed;
1436 }
1437 
1438 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
1439 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1440 {
1441     // hor scrollbar
1442     Point aPos( 0, nRealHeight );
1443     aPos.Y() -= nHorSBarHeight;
1444 
1445     if( aHorSBar.GetPosPixel() != aPos )
1446         aHorSBar.SetPosPixel( aPos );
1447 
1448     // ver scrollbar
1449     aPos.X() = nRealWidth; aPos.Y() = 0;
1450     aPos.X() -= nVerSBarWidth;
1451     aPos.X()++;
1452     aPos.Y()--;
1453 
1454     if( aVerSBar.GetPosPixel() != aPos )
1455         aVerSBar.SetPosPixel( aPos );
1456 }
1457 
1458 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool )
1459 {
1460     Rectangle aOldOutRect( GetOutputRect() );
1461     long nVirtHeight = aVirtOutputSize.Height();
1462     long nVirtWidth = aVirtOutputSize.Width();
1463 
1464     Size aOSize( pView->Control::GetOutputSizePixel() );
1465     long nRealHeight = aOSize.Height();
1466     long nRealWidth = aOSize.Width();
1467 
1468     PositionScrollBars( nRealWidth, nRealHeight );
1469 
1470     const MapMode& rMapMode = pView->GetMapMode();
1471     Point aOrigin( rMapMode.GetOrigin() );
1472 
1473     long nVisibleWidth;
1474     if( nRealWidth > nVirtWidth )
1475         nVisibleWidth = nVirtWidth + aOrigin.X();
1476     else
1477         nVisibleWidth = nRealWidth;
1478 
1479     long nVisibleHeight;
1480     if( nRealHeight > nVirtHeight )
1481         nVisibleHeight = nVirtHeight + aOrigin.Y();
1482     else
1483         nVisibleHeight = nRealHeight;
1484 
1485     sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1486     sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1487     sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1488     sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1489 
1490     sal_uInt16 nResult = 0;
1491     if( nVirtHeight )
1492     {
1493         // activate ver scrollbar ?
1494         if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1495         {
1496             nResult = 0x0001;
1497             nRealWidth -= nVerSBarWidth;
1498 
1499             if( nRealWidth > nVirtWidth )
1500                 nVisibleWidth = nVirtWidth + aOrigin.X();
1501             else
1502                 nVisibleWidth = nRealWidth;
1503 
1504             nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1505         }
1506         // activate hor scrollbar ?
1507         if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1508         {
1509             nResult |= 0x0002;
1510             nRealHeight -= nHorSBarHeight;
1511 
1512             if( nRealHeight > nVirtHeight )
1513                 nVisibleHeight = nVirtHeight + aOrigin.Y();
1514             else
1515                 nVisibleHeight = nRealHeight;
1516 
1517             // brauchen wir jetzt doch eine senkrechte Scrollbar ?
1518             if( !(nResult & 0x0001) &&  // nur wenn nicht schon da
1519                 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1520             {
1521                 nResult = 3; // beide sind an
1522                 nRealWidth -= nVerSBarWidth;
1523 
1524                 if( nRealWidth > nVirtWidth )
1525                     nVisibleWidth = nVirtWidth + aOrigin.X();
1526                 else
1527                     nVisibleWidth = nRealWidth;
1528 
1529                 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1530             }
1531         }
1532     }
1533 
1534     // size ver scrollbar
1535     long nThumb = aVerSBar.GetThumbPos();
1536     Size aSize( nVerSBarWidth, nRealHeight );
1537     aSize.Height() += 2;
1538     if( aSize != aVerSBar.GetSizePixel() )
1539         aVerSBar.SetSizePixel( aSize );
1540     aVerSBar.SetVisibleSize( nVisibleHeight );
1541     aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1542 
1543     if( nResult & 0x0001 )
1544     {
1545         aVerSBar.SetThumbPos( nThumb );
1546         aVerSBar.Show();
1547     }
1548     else
1549     {
1550         aVerSBar.SetThumbPos( 0 );
1551         aVerSBar.Hide();
1552     }
1553 
1554     // size hor scrollbar
1555     nThumb = aHorSBar.GetThumbPos();
1556     aSize.Width() = nRealWidth;
1557     aSize.Height() = nHorSBarHeight;
1558     aSize.Width()++;
1559     if( nResult & 0x0001 ) // vertikale Scrollbar ?
1560     {
1561         aSize.Width()++;
1562         nRealWidth++;
1563     }
1564     if( aSize != aHorSBar.GetSizePixel() )
1565         aHorSBar.SetSizePixel( aSize );
1566     aHorSBar.SetVisibleSize( nVisibleWidth );
1567     aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1568     if( nResult & 0x0002 )
1569     {
1570         aHorSBar.SetThumbPos( nThumb );
1571         aHorSBar.Show();
1572     }
1573     else
1574     {
1575         aHorSBar.SetThumbPos( 0 );
1576         aHorSBar.Hide();
1577     }
1578 
1579     aOutputSize.Width() = nRealWidth;
1580     if( nResult & 0x0002 ) // hor scrollbar ?
1581         nRealHeight++; // weil unterer Rand geclippt wird
1582     aOutputSize.Height() = nRealHeight;
1583 
1584     Rectangle aNewOutRect( GetOutputRect() );
1585     if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1586     {
1587         Wallpaper aPaper( pView->GetBackground() );
1588         aPaper.SetRect( aNewOutRect );
1589         pView->SetBackground( aPaper );
1590     }
1591 
1592     if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1593         aScrBarBox.Show();
1594     else
1595         aScrBarBox.Hide();
1596 }
1597 
1598 void SvxIconChoiceCtrl_Impl::Resize()
1599 {
1600     StopEditTimer();
1601     InitScrollBarBox();
1602     aOutputSize = pView->GetOutputSizePixel();
1603     pImpCursor->Clear();
1604     pGridMap->OutputSizeChanged();
1605 
1606     const Size& rSize = pView->Control::GetOutputSizePixel();
1607     PositionScrollBars( rSize.Width(), rSize.Height() );
1608     // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1609     // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1610     // die ScrollBars aufblitzen
1611     // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden,
1612     // zumindest, solange es nur einen EventTypen gibt
1613     if ( ! nUserEventAdjustScrBars )
1614         nUserEventAdjustScrBars =
1615             Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1616                 EVENTID_ADJUST_SCROLLBARS);
1617 
1618     if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1619     {
1620         Rectangle aRect( GetOutputRect());
1621         Wallpaper aPaper( pView->GetBackground() );
1622         aPaper.SetRect( aRect );
1623         pView->SetBackground( aPaper );
1624     }
1625     VisRectChanged();
1626 }
1627 
1628 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1629 {
1630     if( !pZOrderList || !aHorSBar.IsVisible() )
1631         return sal_False;
1632     const MapMode& rMapMode = pView->GetMapMode();
1633     Point aOrigin( rMapMode.GetOrigin() );
1634     if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1635     {
1636         long nWidth = aOutputSize.Width();
1637         const sal_uLong nCount = pZOrderList->Count();
1638         long nMostRight = 0;
1639         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1640         {
1641             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1642             long nRight = GetEntryBoundRect(pEntry).Right();
1643             if( nRight > nWidth )
1644                 return sal_False;
1645             if( nRight > nMostRight )
1646                 nMostRight = nRight;
1647         }
1648         aHorSBar.Hide();
1649         aOutputSize.Height() += nHorSBarHeight;
1650         aVirtOutputSize.Width() = nMostRight;
1651         aHorSBar.SetThumbPos( 0 );
1652         Range aRange;
1653         aRange.Max() = nMostRight - 1;
1654         aHorSBar.SetRange( aRange  );
1655         if( aVerSBar.IsVisible() )
1656         {
1657             Size aSize( aVerSBar.GetSizePixel());
1658             aSize.Height() += nHorSBarHeight;
1659             aVerSBar.SetSizePixel( aSize );
1660         }
1661         return sal_True;
1662     }
1663     return sal_False;
1664 }
1665 
1666 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1667 {
1668     if( !pZOrderList || !aVerSBar.IsVisible() )
1669         return sal_False;
1670     const MapMode& rMapMode = pView->GetMapMode();
1671     Point aOrigin( rMapMode.GetOrigin() );
1672     if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1673     {
1674         long nDeepest = 0;
1675         long nHeight = aOutputSize.Height();
1676         const sal_uLong nCount = pZOrderList->Count();
1677         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1678         {
1679             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1680             long nBottom = GetEntryBoundRect(pEntry).Bottom();
1681             if( nBottom > nHeight )
1682                 return sal_False;
1683             if( nBottom > nDeepest )
1684                 nDeepest = nBottom;
1685         }
1686         aVerSBar.Hide();
1687         aOutputSize.Width() += nVerSBarWidth;
1688         aVirtOutputSize.Height() = nDeepest;
1689         aVerSBar.SetThumbPos( 0 );
1690         Range aRange;
1691         aRange.Max() = nDeepest - 1;
1692         aVerSBar.SetRange( aRange  );
1693         if( aHorSBar.IsVisible() )
1694         {
1695             Size aSize( aHorSBar.GetSizePixel());
1696             aSize.Width() += nVerSBarWidth;
1697             aHorSBar.SetSizePixel( aSize );
1698         }
1699         return sal_True;
1700     }
1701     return sal_False;
1702 }
1703 
1704 
1705 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1706 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1707 {
1708     CheckVerScrollBar();
1709     if( CheckHorScrollBar() )
1710         CheckVerScrollBar();
1711     if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1712         aScrBarBox.Show();
1713     else
1714         aScrBarBox.Hide();
1715 }
1716 
1717 
1718 void SvxIconChoiceCtrl_Impl::GetFocus()
1719 {
1720     RepaintEntries( ICNVIEW_FLAG_SELECTED );
1721     if( pCursor )
1722     {
1723         pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1724         ShowCursor( sal_True );
1725     }
1726 }
1727 
1728 void SvxIconChoiceCtrl_Impl::LoseFocus()
1729 {
1730     StopEditTimer();
1731     if( pCursor )
1732         pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1733     ShowCursor( sal_False );
1734 
1735 //  HideFocus ();
1736 //  pView->Invalidate ( aFocus.aRect );
1737 
1738     RepaintEntries( ICNVIEW_FLAG_SELECTED );
1739 }
1740 
1741 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate )
1742 {
1743     if( bUpdate != bUpdateMode )
1744     {
1745         bUpdateMode = bUpdate;
1746         if( bUpdate )
1747         {
1748             AdjustScrollBars();
1749             pImpCursor->Clear();
1750             pGridMap->Clear();
1751             pView->Invalidate(INVALIDATE_NOCHILDREN);
1752         }
1753     }
1754 }
1755 
1756 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted )
1757 {
1758     Point aPos( GetEntryPos( pEntry ) );
1759     PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1760 }
1761 
1762 // Prios der Emphasis:  bDropTarget => bCursored => bSelected
1763 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1764     const Rectangle& rTextRect, const Rectangle& rImageRect,
1765     sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut,
1766     sal_Bool bIsBackgroundPainted )
1767 {
1768     static Color aTransparent( COL_TRANSPARENT );
1769 
1770     if( !pOut )
1771         pOut = pView;
1772 
1773 #ifdef OV_CHECK_EMPH_RECTS
1774     {
1775         Color aXOld( pOut->GetFillColor() );
1776         pOut->SetFillColor( Color( COL_GREEN ));
1777         pOut->DrawRect( rTextRect );
1778         pOut->DrawRect( rImageRect );
1779         pOut->SetFillColor( aXOld );
1780     }
1781 #endif
1782 
1783     const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1784     Color aOldFillColor( pOut->GetFillColor() );
1785 
1786     sal_Bool bSolidTextRect = sal_False;
1787     sal_Bool bSolidImageRect = sal_False;
1788 
1789     if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1790     {
1791         pOut->SetFillColor( rSettings.GetHighlightColor() );
1792         bSolidTextRect = sal_True;
1793         bSolidImageRect = sal_True;
1794     }
1795     else
1796     {
1797         if ( !bSelected || bCursored )
1798         {
1799             if( !pView->HasFontFillColor() )
1800                 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1801             else
1802             {
1803                 const Color& rFillColor = pView->GetFont().GetFillColor();
1804                 pOut->SetFillColor( rFillColor );
1805                 if( rFillColor != aTransparent )
1806                     bSolidTextRect = sal_True;
1807             }
1808         }
1809     }
1810 
1811     // Textrechteck zeichnen
1812     if( !bSolidTextRect )
1813     {
1814         if( !bIsBackgroundPainted )
1815             pOut->Erase( rTextRect );
1816     }
1817     else
1818     {
1819         Color aOldLineColor;
1820         if( bCursored )
1821         {
1822             aOldLineColor = pOut->GetLineColor();
1823             pOut->SetLineColor( Color( COL_GRAY ) );
1824         }
1825         pOut->DrawRect( rTextRect );
1826         if( bCursored )
1827             pOut->SetLineColor( aOldLineColor );
1828     }
1829 
1830     // Bildrechteck zeichnen
1831     if( !bSolidImageRect )
1832     {
1833         if( !bIsBackgroundPainted )
1834             pOut->Erase( rImageRect );
1835     }
1836 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden
1837 // (in der virtuellen Funktion DrawEntryImage)
1838 //  else
1839 //      pOut->DrawRect( rImageRect );
1840 
1841     pOut->SetFillColor( aOldFillColor );
1842 }
1843 
1844 
1845 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1846     IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1847     OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1848 {
1849     if( eItem == IcnViewFieldTypeText )
1850     {
1851         String aText;
1852         if( !pStr )
1853             aText = pView->GetEntryText( pEntry, sal_False );
1854         else
1855             aText = *pStr;
1856 
1857         if ( _pLayoutData )
1858         {
1859             pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1860                 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1861         }
1862         else
1863         {
1864             Color aOldFontColor = pOut->GetTextColor();
1865             if ( pView->AutoFontColor() )
1866             {
1867                 Color aBkgColor( pOut->GetBackground().GetColor() );
1868                 Color aFontColor;
1869                 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1870                 if ( nColor > 127 )
1871                     aFontColor.SetColor ( COL_BLACK );
1872                 else
1873                     aFontColor.SetColor( COL_WHITE );
1874                 pOut->SetTextColor( aFontColor );
1875             }
1876 
1877             pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1878 
1879             if ( pView->AutoFontColor() )
1880                 pOut->SetTextColor( aOldFontColor );
1881 
1882             if( pEntry->IsFocused() )
1883             {
1884                 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1885                 /*pView->*/ShowFocus( aRect );
1886                 DrawFocusRect( pOut );
1887             }
1888         }
1889     }
1890     else
1891     {
1892         Point aPos( rRect.TopLeft() );
1893         if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1894             aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1895         if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1896             aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1897         pView->DrawEntryImage( pEntry, aPos, *pOut );
1898     }
1899 }
1900 
1901 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1902 {
1903 #ifdef OV_NO_VIRT_OUTDEV
1904     PaintEntry( pEntry );
1905 #else
1906     if( !pEntryPaintDev )
1907     {
1908         pEntryPaintDev = new VirtualDevice( *pView );
1909         pEntryPaintDev->SetFont( pView->GetFont() );
1910         pEntryPaintDev->SetLineColor();
1911         //pEntryPaintDev->SetBackground( pView->GetBackground() );
1912     }
1913     const Rectangle& rRect = GetEntryBoundRect( pEntry );
1914     Rectangle aOutRect( GetOutputRect() );
1915     if( !rRect.IsOver( aOutRect ) )
1916         return;
1917     Wallpaper aPaper( pView->GetBackground() );
1918     Rectangle aRect( aPaper.GetRect() );
1919 
1920     // Rechteck verschieben, so dass das Boundrect des Entries im
1921     // VirtOut-Dev bei 0,0 liegt.
1922     aRect.Move( -rRect.Left(), -rRect.Top() );
1923     aPaper.SetRect( aRect );
1924     pEntryPaintDev->SetBackground( aPaper );
1925     pEntryPaintDev->SetFont( pView->GetFont() );
1926     Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) );
1927 
1928 
1929     Size aSize( rRect.GetSize() );
1930     pEntryPaintDev->SetOutputSizePixel( aSize );
1931     pEntryPaintDev->DrawOutDev(
1932         Point(), aSize, rRect.TopLeft(), aSize, *pView );
1933 
1934     PaintEntry( pEntry, Point(), pEntryPaintDev );
1935 
1936     pView->DrawOutDev(
1937         rRect.TopLeft(),
1938         aSize,
1939         Point(),
1940         aSize,
1941         *pEntryPaintDev );
1942 #endif
1943 }
1944 
1945 
1946 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1947     OutputDevice* pOut, sal_Bool bIsBackgroundPainted )
1948 {
1949     if( !pOut )
1950         pOut = pView;
1951 
1952     sal_Bool bSelected = sal_False;
1953 
1954     if( eSelectionMode != NO_SELECTION )
1955         bSelected = pEntry->IsSelected();
1956 
1957     sal_Bool bCursored = pEntry->IsCursored();
1958     sal_Bool bDropTarget = pEntry->IsDropTarget();
1959     sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1960 
1961     Font aTempFont( pOut->GetFont() );
1962 
1963     // AutoFontColor
1964     /*
1965     if ( pView->AutoFontColor() )
1966     {
1967         aTempFont.SetColor ( aFontColor );
1968     }
1969     */
1970 
1971     String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
1972     Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText));
1973     Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1974 
1975     sal_Bool    bShowSelection =
1976         (   (   ( bSelected && !bCursored )
1977             ||  bDropTarget
1978             )
1979         &&  !bNoEmphasis
1980         &&  ( eSelectionMode != NO_SELECTION )
1981         );
1982     sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1983 
1984     if ( bShowSelection )
1985     {
1986         const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1987         Font aNewFont( aTempFont );
1988 
1989         // bei hart attributierter Font-Fuellcolor muessen wir diese
1990         // hart auf die Highlight-Color setzen
1991         if( pView->HasFontFillColor() )
1992         {
1993             if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1994                 aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1995             else
1996                 aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
1997         }
1998 
1999         Color aWinCol = rSettings.GetWindowTextColor();
2000         if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
2001             aNewFont.SetColor( rSettings.GetWindowTextColor() );
2002         else
2003             aNewFont.SetColor( rSettings.GetHighlightTextColor() );
2004 
2005         pOut->SetFont( aNewFont );
2006 
2007         pOut->SetFillColor( pOut->GetBackground().GetColor() );
2008         pOut->DrawRect( CalcFocusRect( pEntry ) );
2009         pOut->SetFillColor( );
2010     }
2011 
2012     sal_Bool bResetClipRegion = sal_False;
2013     if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
2014     {
2015         Rectangle aOutputArea( GetOutputRect() );
2016         if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
2017         {
2018             pView->SetClipRegion( aOutputArea );
2019             bResetClipRegion = sal_True;
2020         }
2021     }
2022 
2023 #ifdef OV_DRAWBOUNDRECT
2024     {
2025         Color aXOldColor = pOut->GetLineColor();
2026         pOut->SetLineColor( Color( COL_LIGHTRED ) );
2027         Rectangle aXRect( pEntry->aRect );
2028         aXRect.SetPos( rPos );
2029         pOut->DrawRect( aXRect );
2030         pOut->SetLineColor( aXOldColor );
2031     }
2032 #endif
2033 
2034     sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
2035     sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
2036     if ( bLargeIconMode )
2037         nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
2038     sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
2039 
2040     if( !bNoEmphasis )
2041         PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
2042 
2043     if ( bShowSelection )
2044         pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
2045         bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
2046 
2047     PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
2048 
2049     PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
2050         nTextPaintFlags, pOut );
2051 
2052     // Highlight-Frame zeichnen
2053     if( pEntry == pCurHighlightFrame && !bNoEmphasis )
2054         DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False );
2055 
2056     pOut->SetFont( aTempFont );
2057     if( bResetClipRegion )
2058         pView->SetClipRegion();
2059 }
2060 
2061 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2062     sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap )
2063 {
2064     ShowCursor( sal_False );
2065     Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
2066     pView->Invalidate( aBoundRect );
2067     ToTop( pEntry );
2068     if( !IsAutoArrange() )
2069     {
2070         sal_Bool bAdjustVirtSize = sal_False;
2071         if( rPos != aBoundRect.TopLeft() )
2072         {
2073             Point aGridOffs(
2074                 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
2075             pImpCursor->Clear();
2076             if( !bKeepGridMap )
2077                 pGridMap->Clear();
2078             aBoundRect.SetPos( rPos );
2079             pEntry->aRect = aBoundRect;
2080             pEntry->aGridRect.SetPos( rPos + aGridOffs );
2081             bAdjustVirtSize = sal_True;
2082         }
2083         if( bAdjustAtGrid )
2084         {
2085             if( bAdjustVirtSize )
2086             {
2087                 // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags,
2088                 // kann er wieder komplett
2089                 // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar
2090                 // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der
2091                 // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen
2092                 // Ausgabegroesse bereits das ausgerichtete Boundrect des
2093                 // Eintrags genommen. Die virtuelle Groesse muss angepasst werden,
2094                 // da AdjustEntryAtGrid von ihr abhaengt.
2095                 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
2096                 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
2097                 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
2098                 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
2099                 AdjustVirtSize( aNewBoundRect );
2100                 bAdjustVirtSize = sal_False;
2101             }
2102             AdjustEntryAtGrid( pEntry );
2103             ToTop( pEntry );
2104         }
2105         if( bAdjustVirtSize )
2106             AdjustVirtSize( pEntry->aRect );
2107 
2108         if( bCheckScrollBars && bUpdateMode )
2109             CheckScrollBars();
2110 
2111         pView->Invalidate( pEntry->aRect );
2112         pGridMap->OccupyGrids( pEntry );
2113     }
2114     else
2115     {
2116         SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
2117         SetEntryPredecessor( pEntry, pPrev );
2118         aAutoArrangeTimer.Start();
2119     }
2120     ShowCursor( sal_True );
2121 }
2122 
2123 void SvxIconChoiceCtrl_Impl::SetNoSelection()
2124 {
2125     // rekursive Aufrufe ueber SelectEntry abblocken
2126     if( !(nFlags & F_CLEARING_SELECTION ))
2127     {
2128         nFlags |= F_CLEARING_SELECTION;
2129         DeselectAllBut( 0, sal_True );
2130         nFlags &= ~F_CLEARING_SELECTION;
2131     }
2132 }
2133 
2134 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit )
2135 {
2136     CheckBoundingRects();
2137     // Z-Order-Liste vom Ende her absuchen
2138     sal_uLong nCount = pZOrderList->Count();
2139     while( nCount )
2140     {
2141         nCount--;
2142         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount));
2143         if( pEntry->aRect.IsInside( rDocPos ) )
2144         {
2145             if( bHit )
2146             {
2147                 Rectangle aRect = CalcBmpRect( pEntry );
2148                 aRect.Top() -= 3;
2149                 aRect.Bottom() += 3;
2150                 aRect.Left() -= 3;
2151                 aRect.Right() += 3;
2152                 if( aRect.IsInside( rDocPos ) )
2153                     return pEntry;
2154                 aRect = CalcTextRect( pEntry );
2155                 if( aRect.IsInside( rDocPos ) )
2156                     return pEntry;
2157             }
2158             else
2159                 return pEntry;
2160         }
2161     }
2162     return 0;
2163 }
2164 
2165 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2166 {
2167     CheckBoundingRects();
2168     SvxIconChoiceCtrlEntry* pTarget = 0;
2169     const sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2170     if( nStartPos != LIST_ENTRY_NOTFOUND )
2171     {
2172         const sal_uLong nCount = pZOrderList->Count();
2173         for( sal_uLong nCur = nStartPos+1; nCur < nCount; nCur++ )
2174         {
2175             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
2176             if( pEntry->aRect.IsInside( rDocPos ) )
2177             {
2178                 pTarget = pEntry;
2179                 break;
2180             }
2181         }
2182     }
2183     return pTarget;
2184 }
2185 
2186 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2187 {
2188     CheckBoundingRects();
2189     SvxIconChoiceCtrlEntry* pTarget = 0;
2190     sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2191     if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 )
2192     {
2193         nStartPos--;
2194         do
2195         {
2196             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos));
2197             if( pEntry->aRect.IsInside( rDocPos ) )
2198             {
2199                 pTarget = pEntry;
2200                 break;
2201             }
2202         } while( nStartPos > 0 );
2203     }
2204     return pTarget;
2205 }
2206 
2207 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
2208 {
2209     return pEntry->aRect.TopLeft();
2210 }
2211 
2212 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound )
2213 {
2214     if ( bBound )
2215     {
2216         const Rectangle& rRect = GetEntryBoundRect( pEntry );
2217         MakeVisible( rRect );
2218     }
2219     else
2220     {
2221         Rectangle aRect = CalcBmpRect( pEntry );
2222         aRect.Union( CalcTextRect( pEntry ) );
2223         aRect.Top() += TBOFFS_BOUND;
2224         aRect.Bottom() += TBOFFS_BOUND;
2225         aRect.Left() += LROFFS_BOUND;
2226         aRect.Right() += LROFFS_BOUND;
2227         MakeVisible( aRect );
2228     }
2229 }
2230 
2231 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2232 {
2233     if( !IsBoundingRectValid( pEntry->aRect ))
2234         FindBoundingRect( pEntry );
2235     return pEntry->aRect;
2236 }
2237 
2238 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2239 {
2240     Rectangle aBound = GetEntryBoundRect( pEntry );
2241     if( pPos )
2242         aBound.SetPos( *pPos );
2243     Point aPos( aBound.TopLeft() );
2244 
2245     switch( nWinBits & (VIEWMODE_MASK) )
2246     {
2247         case WB_ICON:
2248         {
2249             aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2250             return Rectangle( aPos, aImageSize );
2251         }
2252 
2253         case WB_SMALLICON:
2254         case WB_DETAILS:
2255             aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2256             //todo: hor. Abstand zum BoundRect?
2257             return Rectangle( aPos, aImageSize );
2258 
2259         default:
2260             DBG_ERROR("IconView: Viewmode not set");
2261             return aBound;
2262     }
2263 }
2264 
2265 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2266     const Point* pEntryPos, sal_Bool bEdit, const String* pStr )
2267 {
2268     String aEntryText;
2269     if( !pStr )
2270         aEntryText = pView->GetEntryText( pEntry, bEdit );
2271     else
2272         aEntryText = *pStr;
2273 
2274     const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2275     Rectangle aBound( GetEntryBoundRect( pEntry ) );
2276     if( pEntryPos )
2277         aBound.SetPos( *pEntryPos );
2278 
2279     Rectangle aTextRect( aMaxTextRect );
2280     if( !bEdit )
2281         aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2282 
2283     Size aTextSize( aTextRect.GetSize() );
2284 
2285     Point aPos( aBound.TopLeft() );
2286     long nBoundWidth = aBound.GetWidth();
2287     long nBoundHeight = aBound.GetHeight();
2288 
2289     switch( nWinBits & (VIEWMODE_MASK) )
2290     {
2291         case WB_ICON:
2292             aPos.Y() += aImageSize.Height();
2293             aPos.Y() += VER_DIST_BMP_STRING;
2294             // beim Editieren etwas mehr Platz
2295             if( bEdit )
2296             {
2297                 // 20% rauf
2298                 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2299                                  aImageSize.Width();
2300                 if( nMinWidth > nBoundWidth )
2301                     nMinWidth = nBoundWidth;
2302 
2303                 if( aTextSize.Width() < nMinWidth )
2304                     aTextSize.Width() = nMinWidth;
2305 
2306                 // beim Editieren ist Ueberlappung nach unten erlaubt
2307                 Size aOptSize = aMaxTextRect.GetSize();
2308                 if( aOptSize.Height() > aTextSize.Height() )
2309                     aTextSize.Height() = aOptSize.Height();
2310             }
2311             aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2312             break;
2313 
2314         case WB_SMALLICON:
2315         case WB_DETAILS:
2316             aPos.X() += aImageSize.Width();
2317             aPos.X() += HOR_DIST_BMP_STRING;
2318             aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2319             break;
2320     }
2321     return Rectangle( aPos, aTextSize );
2322 }
2323 
2324 
2325 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2326 {
2327     long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2328 //  nStringWidth += 2*LROFFS_TEXT;
2329     long nWidth = 0;
2330 
2331     switch( nWinBits & (VIEWMODE_MASK) )
2332     {
2333         case WB_ICON:
2334             nWidth = Max( nStringWidth, aImageSize.Width() );
2335             break;
2336 
2337         case WB_SMALLICON:
2338         case WB_DETAILS:
2339             nWidth = aImageSize.Width();
2340             nWidth += HOR_DIST_BMP_STRING;
2341             nWidth += nStringWidth;
2342             break;
2343     }
2344     return nWidth;
2345 }
2346 
2347 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2348 {
2349     long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2350     long nHeight = 0;
2351 
2352     switch( nWinBits & (VIEWMODE_MASK) )
2353     {
2354         case WB_ICON:
2355             nHeight = aImageSize.Height();
2356             nHeight += VER_DIST_BMP_STRING;
2357             nHeight += nStringHeight;
2358             break;
2359 
2360         case WB_SMALLICON:
2361         case WB_DETAILS:
2362             nHeight = Max( aImageSize.Height(), nStringHeight );
2363             break;
2364     }
2365     if( nHeight > nMaxBoundHeight )
2366     {
2367         ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2368         ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2369         ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2370     }
2371     return nHeight;
2372 }
2373 
2374 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2375 {
2376     return Size( CalcBoundingWidth( pEntry ),
2377                  CalcBoundingHeight( pEntry ) );
2378 }
2379 
2380 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects()
2381 {
2382     nMaxBoundHeight = 0;
2383     pZOrderList->Clear();
2384     sal_uLong nCount = aEntries.Count();
2385     sal_uLong nCur;
2386     SvxIconChoiceCtrlEntry* pEntry;
2387 
2388     if( !IsAutoArrange() || !pHead )
2389     {
2390         for( nCur = 0; nCur < nCount; nCur++ )
2391         {
2392             pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2393             FindBoundingRect( pEntry );
2394             pZOrderList->Insert( pEntry, LIST_APPEND );
2395         }
2396     }
2397     else
2398     {
2399         nCur = 0;
2400         pEntry = pHead;
2401         while( nCur != nCount )
2402         {
2403             DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2404             FindBoundingRect( pEntry );
2405             pZOrderList->Insert( pEntry, pZOrderList->Count() );
2406             pEntry = pEntry->pflink;
2407             nCur++;
2408         }
2409     }
2410     bBoundRectsDirty = sal_False;
2411     AdjustScrollBars();
2412 }
2413 
2414 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2415 {
2416     nMaxBoundHeight = 0;
2417     pZOrderList->Clear();
2418     sal_uLong nCur;
2419     SvxIconChoiceCtrlEntry* pEntry;
2420     const sal_uLong nCount = aEntries.Count();
2421 
2422     if( !IsAutoArrange() || !pHead )
2423     {
2424         for( nCur = 0; nCur < nCount; nCur++ )
2425         {
2426             pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2427             if( IsBoundingRectValid( pEntry->aRect ))
2428             {
2429                 Size aBoundSize( pEntry->aRect.GetSize() );
2430                 if( aBoundSize.Height() > nMaxBoundHeight )
2431                     nMaxBoundHeight = aBoundSize.Height();
2432             }
2433             else
2434                 FindBoundingRect( pEntry );
2435             pZOrderList->Insert( pEntry, LIST_APPEND );
2436         }
2437     }
2438     else
2439     {
2440         nCur = 0;
2441         pEntry = pHead;
2442         while( nCur != nCount )
2443         {
2444             DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2445             if( IsBoundingRectValid( pEntry->aRect ))
2446             {
2447                 Size aBoundSize( pEntry->aRect.GetSize() );
2448                 if( aBoundSize.Height() > nMaxBoundHeight )
2449                     nMaxBoundHeight = aBoundSize.Height();
2450             }
2451             else
2452                 FindBoundingRect( pEntry );
2453             pZOrderList->Insert( pEntry, LIST_APPEND );
2454             pEntry = pEntry->pflink;
2455             nCur++;
2456         }
2457     }
2458     AdjustScrollBars();
2459 }
2460 
2461 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects()
2462 {
2463     const sal_uLong nCount = aEntries.Count();
2464     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2465     {
2466         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2467         GetEntryBoundRect( pEntry );
2468     }
2469 }
2470 
2471 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2472 {
2473     DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2474     if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2475     {
2476         AdjustVirtSize( pEntry->aRect );
2477         return;
2478     }
2479     Size aSize( CalcBoundingSize( pEntry ) );
2480     Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft());
2481     SetBoundingRect_Impl( pEntry, aPos, aSize );
2482 }
2483 
2484 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2485     const Size& /*rBoundingSize*/ )
2486 {
2487     Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2488     pEntry->aGridRect = aGridRect;
2489     Center( pEntry );
2490     AdjustVirtSize( pEntry->aRect );
2491     pGridMap->OccupyGrids( pEntry );
2492 }
2493 
2494 
2495 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection,
2496     sal_Bool bShowFocusAsync )
2497 {
2498     if( pEntry == pCursor )
2499     {
2500         if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2501                 !pCursor->IsSelected() )
2502             SelectEntry( pCursor, sal_True, sal_True );
2503         return;
2504     }
2505     ShowCursor( sal_False );
2506     SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2507     pCursor = pEntry;
2508     if( pOldCursor )
2509     {
2510         pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2511         if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2512             SelectEntry( pOldCursor, sal_False, sal_True ); // alten Cursor deselektieren
2513     }
2514     if( pCursor )
2515     {
2516         ToTop( pCursor );
2517         pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2518         if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2519             SelectEntry( pCursor, sal_True, sal_True );
2520         if( !bShowFocusAsync )
2521             ShowCursor( sal_True );
2522         else
2523         {
2524             if( !nUserEventShowCursor )
2525                 nUserEventShowCursor =
2526                     Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2527                         EVENTID_SHOW_CURSOR );
2528         }
2529     }
2530 }
2531 
2532 
2533 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow )
2534 {
2535     if( !pCursor || !bShow || !pView->HasFocus() )
2536     {
2537         pView->HideFocus();
2538         return;
2539     }
2540     Rectangle aRect ( CalcFocusRect( pCursor ) );
2541     /*pView->*/ShowFocus( aRect );
2542 }
2543 
2544 
2545 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2546 {
2547     pView->Update();
2548     ImpHideDDIcon();
2549     pDDBufDev = pDDDev;
2550     pDDDev = 0;
2551 }
2552 
2553 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2554 {
2555     if( pDDDev )
2556     {
2557         Size aSize( pDDDev->GetOutputSizePixel() );
2558         // pView restaurieren
2559         pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2560     }
2561 }
2562 
2563 
2564 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2565 {
2566     pView->Update();
2567     if( pRefEntry != pDDRefEntry )
2568     {
2569         DELETEZ(pDDDev);
2570         DELETEZ(pDDBufDev);
2571     }
2572     sal_Bool bSelected = pRefEntry->IsSelected();
2573     pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED );
2574     if( !pDDDev )
2575     {
2576         if( pDDBufDev )
2577         {
2578             // nicht bei jedem Move ein Device anlegen, da dies besonders
2579             // auf Remote-Clients zu langsam ist
2580             pDDDev = pDDBufDev;
2581             pDDBufDev = 0;
2582         }
2583         else
2584         {
2585             pDDDev = new VirtualDevice( *pView );
2586             pDDDev->SetFont( pView->GetFont() );
2587         }
2588     }
2589     else
2590     {
2591         ImpHideDDIcon();
2592     }
2593     const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2594     pDDDev->SetOutputSizePixel( rRect.GetSize() );
2595 
2596     Point aPos( rPosPix );
2597     ToDocPos( aPos );
2598 
2599     Size aSize( pDDDev->GetOutputSizePixel() );
2600     pDDRefEntry = pRefEntry;
2601     aDDLastEntryPos = aPos;
2602     aDDLastRectPos = aPos;
2603 
2604     // Hintergrund sichern
2605     pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2606     // Icon in pView malen
2607     pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2608     PaintEntry( pRefEntry, aPos );
2609     pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2610     if( bSelected )
2611         pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED );
2612 }
2613 
2614 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2615 {
2616 /*  In Notfaellen folgenden flackernden Code aktivieren:
2617 
2618         HideDDIcon();
2619         ShowDDIcon( pRefEntry, rPosPix );
2620         return;
2621 */
2622     if( !pDDDev )
2623     {
2624         ShowDDIcon( pRefEntry, rPosPix );
2625         return;
2626     }
2627 
2628     if( pRefEntry != pDDRefEntry )
2629     {
2630         HideDDIcon();
2631         ShowDDIcon( pRefEntry, rPosPix );
2632         return;
2633     }
2634 
2635     Point aEmptyPoint;
2636 
2637     Point aCurEntryPos( rPosPix );
2638     ToDocPos( aCurEntryPos );
2639 
2640     const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2641     Size aEntrySize( rRect.GetSize() );
2642     Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2643     Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2644 
2645     if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2646     {
2647         HideDDIcon();
2648         ShowDDIcon( pRefEntry, rPosPix );
2649         return;
2650     }
2651 
2652     // Ueberlappung des neuen und alten D&D-Pointers!
2653 
2654     Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2655     if( !pDDTempDev )
2656     {
2657         pDDTempDev = new VirtualDevice( *pView );
2658         pDDTempDev->SetFont( pView->GetFont() );
2659     }
2660 
2661     Size aFullSize( aFullRect.GetSize() );
2662     Point aFullPos( aFullRect.TopLeft() );
2663 
2664     pDDTempDev->SetOutputSizePixel( aFullSize );
2665 
2666     // Hintergrund (mit dem alten D&D-Pointer!) sichern
2667     pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2668     // den alten Buffer in den neuen Buffer pasten
2669     aDDLastRectPos = aDDLastRectPos - aFullPos;
2670 
2671     pDDTempDev->DrawOutDev(
2672         aDDLastRectPos,
2673         pDDDev->GetOutputSizePixel(),
2674         aEmptyPoint,
2675         pDDDev->GetOutputSizePixel(),
2676         *pDDDev );
2677 
2678     // Swap
2679     VirtualDevice* pTemp = pDDDev;
2680     pDDDev = pDDTempDev;
2681     pDDTempDev = pTemp;
2682 
2683     // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2684     pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2685     pDDTempDev->DrawOutDev(
2686         aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2687     Point aRelPos = aCurEntryPos - aFullPos;
2688     pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2689     PaintEntry( pRefEntry, aRelPos, pDDTempDev );
2690     pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2691 
2692     aDDLastRectPos = aFullPos;
2693     aDDLastEntryPos = aCurEntryPos;
2694 
2695     pView->DrawOutDev(
2696         aDDLastRectPos,
2697         pDDDev->GetOutputSizePixel(),
2698         aEmptyPoint,
2699         pDDDev->GetOutputSizePixel(),
2700         *pDDTempDev );
2701 }
2702 
2703 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2704 {
2705     InvalidateBoundingRect( pEntry->aRect );
2706 }
2707 
2708 
2709 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2710 {
2711     Rectangle aDocRect( GetDocumentRect() );
2712     Rectangle aVisRect( GetVisibleRect() );
2713     if( aVisRect.IsInside( aDocRect ))
2714         return sal_False;
2715     Size aDocSize( aDocRect.GetSize() );
2716     Size aVisSize( aVisRect.GetSize() );
2717     sal_Bool bHor = aDocSize.Width() > aVisSize.Width();
2718     sal_Bool bVer = aDocSize.Height() > aVisSize.Height();
2719 
2720     long nScrollDX = 0, nScrollDY = 0;
2721 
2722     switch( rCmd.GetCommand() )
2723     {
2724         case COMMAND_STARTAUTOSCROLL:
2725         {
2726             pView->EndTracking();
2727             sal_uInt16 nScrollFlags = 0;
2728             if( bHor )
2729                 nScrollFlags |= AUTOSCROLL_HORZ;
2730             if( bVer )
2731                 nScrollFlags |= AUTOSCROLL_VERT;
2732             if( nScrollFlags )
2733             {
2734                 pView->StartAutoScroll( nScrollFlags );
2735                 return sal_True;
2736             }
2737         }
2738         break;
2739 
2740         case COMMAND_WHEEL:
2741         {
2742             const CommandWheelData* pData = rCmd.GetWheelData();
2743             if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2744             {
2745                 sal_uLong nScrollLines = pData->GetScrollLines();
2746                 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2747                 {
2748                     nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2749                     if( pData->GetDelta() < 0 )
2750                         nScrollDY *= -1;
2751                 }
2752                 else
2753                 {
2754                     nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2755                     nScrollDY *= GetScrollBarLineSize();
2756                 }
2757             }
2758         }
2759         break;
2760 
2761         case COMMAND_AUTOSCROLL:
2762         {
2763             const CommandScrollData* pData = rCmd.GetAutoScrollData();
2764             if( pData )
2765             {
2766                 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2767                 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2768             }
2769         }
2770         break;
2771     }
2772 
2773     if( nScrollDX || nScrollDY )
2774     {
2775         aVisRect.Top() -= nScrollDY;
2776         aVisRect.Bottom() -= nScrollDY;
2777         aVisRect.Left() -= nScrollDX;
2778         aVisRect.Right() -= nScrollDX;
2779         MakeVisible( aVisRect );
2780         return sal_True;
2781     }
2782     return sal_False;
2783 }
2784 
2785 
2786 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2787 {
2788     // Rollmaus-Event?
2789     if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2790         (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2791         (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2792     {
2793 #if 1
2794         if( HandleScrollCommand( rCEvt ) )
2795             return;
2796 #else
2797         ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0;
2798         ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0;
2799         if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) )
2800             return;
2801 #endif
2802     }
2803 }
2804 
2805 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2806 {
2807     if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry )
2808     {
2809         sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry );
2810         pZOrderList->Remove( nPos );
2811         pZOrderList->Insert( pEntry, LIST_APPEND );
2812     }
2813 }
2814 
2815 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2816 {
2817     if( rRect.Bottom() >= aVirtOutputSize.Height() )
2818         rRect.Bottom() = aVirtOutputSize.Height() - 1;
2819     if( rRect.Right() >= aVirtOutputSize.Width() )
2820         rRect.Right() = aVirtOutputSize.Width() - 1;
2821     if( rRect.Top() < 0 )
2822         rRect.Top() = 0;
2823     if( rRect.Left() < 0 )
2824         rRect.Left() = 0;
2825 }
2826 
2827 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2828 // sichtbar gemacht werden soll.
2829 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2830 
2831 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar,
2832     sal_Bool bCallRectChangedHdl )
2833 {
2834     Rectangle aVirtRect( rRect );
2835     ClipAtVirtOutRect( aVirtRect );
2836     Point aOrigin( pView->GetMapMode().GetOrigin() );
2837     // in Dokumentkoordinate umwandeln
2838     aOrigin *= -1;
2839     Rectangle aOutputArea( GetOutputRect() );
2840     if( aOutputArea.IsInside( aVirtRect ) )
2841         return; // ist schon sichtbar
2842 
2843     long nDy;
2844     if( aVirtRect.Top() < aOutputArea.Top() )
2845     {
2846         // nach oben scrollen (nDy < 0)
2847         nDy = aVirtRect.Top() - aOutputArea.Top();
2848     }
2849     else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2850     {
2851         // nach unten scrollen (nDy > 0)
2852         nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2853     }
2854     else
2855         nDy = 0;
2856 
2857     long nDx;
2858     if( aVirtRect.Left() < aOutputArea.Left() )
2859     {
2860         // nach links scrollen (nDx < 0)
2861         nDx = aVirtRect.Left() - aOutputArea.Left();
2862     }
2863     else if( aVirtRect.Right() > aOutputArea.Right() )
2864     {
2865         // nach rechts scrollen (nDx > 0)
2866         nDx = aVirtRect.Right() - aOutputArea.Right();
2867     }
2868     else
2869         nDx = 0;
2870 
2871     aOrigin.X() += nDx;
2872     aOrigin.Y() += nDy;
2873     aOutputArea.SetPos( aOrigin );
2874     if( GetUpdateMode() )
2875     {
2876         HideDDIcon();
2877         pView->Update();
2878         ShowCursor( sal_False );
2879     }
2880 
2881     // Origin fuer SV invertieren (damit wir in
2882     // Dokumentkoordinaten scrollen/painten koennen)
2883     aOrigin *= -1;
2884     SetOrigin( aOrigin );
2885 
2886     sal_Bool bScrollable = pView->GetBackground().IsScrollable();
2887     if( pView->HasBackground() && !bScrollable )
2888     {
2889         Rectangle aRect( GetOutputRect());
2890         Wallpaper aPaper( pView->GetBackground() );
2891         aPaper.SetRect( aRect );
2892         pView->SetBackground( aPaper );
2893     }
2894 
2895     if( bScrollable && GetUpdateMode() )
2896     {
2897         // in umgekehrte Richtung scrollen!
2898         pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2899             SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2900     }
2901     else
2902         pView->Invalidate(INVALIDATE_NOCHILDREN);
2903 
2904     if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2905     {
2906         if( !bScrBar )
2907         {
2908             aOrigin *= -1;
2909             // Thumbs korrigieren
2910             if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2911                 aHorSBar.SetThumbPos( aOrigin.X() );
2912             if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2913                 aVerSBar.SetThumbPos( aOrigin.Y() );
2914         }
2915     }
2916 
2917     if( GetUpdateMode() )
2918         ShowCursor( sal_True );
2919 
2920     // pruefen, ob ScrollBars noch benoetigt werden
2921     CheckScrollBars();
2922     if( bScrollable && GetUpdateMode() )
2923         pView->Update();
2924 
2925     // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden,
2926     // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der
2927     // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind,
2928     // eine ScrollBar aber eine groessere Line-Size eingestellt hat.
2929     if( bCallRectChangedHdl || GetOutputRect() != rRect )
2930         VisRectChanged();
2931 }
2932 
2933 
2934 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor()
2935 {
2936     SvxIconChoiceCtrlEntry* pNewCursor;
2937     if( pCursor )
2938     {
2939         pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False );
2940         if( !pNewCursor )
2941         {
2942             pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True );
2943             if( !pNewCursor )
2944             {
2945                 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False );
2946                 if( !pNewCursor )
2947                     pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True );
2948             }
2949         }
2950     }
2951     else
2952         pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
2953     DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed");
2954     return pNewCursor;
2955 }
2956 
2957 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2958 {
2959     if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2960         return 1;
2961     return nSelectionCount;
2962 }
2963 
2964 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2965 {
2966     sal_Bool bSel;
2967     if( pEntry->IsSelected() )
2968         bSel = sal_False;
2969     else
2970         bSel = sal_True;
2971     SelectEntry( pEntry, bSel, sal_True, sal_True );
2972 }
2973 
2974 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2975     sal_Bool bPaintSync )
2976 {
2977     ClearSelectedRectList();
2978     //
2979     // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!!
2980     //
2981     sal_uLong nCount = aEntries.Count();
2982     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2983     {
2984         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2985         if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2986             SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync );
2987     }
2988     pAnchor = 0;
2989     nFlags &= (~F_ADD_MODE);
2990 }
2991 
2992 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2993 {
2994     Size aMinSize( aImageSize );
2995     aMinSize.Width() += 2 * LROFFS_BOUND;
2996     aMinSize.Height() += TBOFFS_BOUND;  // PB: einmal Offset reicht (FileDlg)
2997     String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
2998     Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2999     if( nWinBits & WB_ICON )
3000     {
3001         aMinSize.Height() += VER_DIST_BMP_STRING;
3002         aMinSize.Height() += aTextSize.Height();
3003     }
3004     else
3005     {
3006         aMinSize.Width() += HOR_DIST_BMP_STRING;
3007         aMinSize.Width() += aTextSize.Width();
3008     }
3009     return aMinSize;
3010 }
3011 
3012 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
3013 {
3014     Size aSize( rSize );
3015     Size aMinSize( GetMinGrid() );
3016     if( aSize.Width() < aMinSize.Width() )
3017         aSize.Width() = aMinSize.Width();
3018     if( aSize.Height() < aMinSize.Height() )
3019         aSize.Height() = aMinSize.Height();
3020 
3021     nGridDX = aSize.Width();
3022     // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
3023     // dieses Workaround bringts mit einer Spalte zum Fliegen
3024     if( nWinBits & WB_DETAILS )
3025     {
3026         const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
3027         if( pCol )
3028             ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
3029     }
3030     nGridDY = aSize.Height();
3031     SetDefaultTextSize();
3032 }
3033 
3034 // berechnet die maximale Groesse, die das Textrechteck innerhalb des
3035 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und
3036 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt
3037 
3038 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
3039 {
3040     Rectangle aBoundRect;
3041     // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen
3042     if( IsBoundingRectValid( pEntry->aRect ) )
3043         aBoundRect = pEntry->aRect;
3044     else
3045         aBoundRect = pEntry->aGridRect;
3046 
3047     Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
3048         (SvxIconChoiceCtrlEntry*)pEntry ) );
3049     if( nWinBits & WB_ICON )
3050     {
3051         aBoundRect.Top() = aBmpRect.Bottom();
3052         aBoundRect.Top() += VER_DIST_BMP_STRING;
3053         if( aBoundRect.Top() > aBoundRect.Bottom())
3054             aBoundRect.Top() = aBoundRect.Bottom();
3055         aBoundRect.Left() += LROFFS_BOUND;
3056         aBoundRect.Left()++;
3057         aBoundRect.Right() -= LROFFS_BOUND;
3058         aBoundRect.Right()--;
3059         if( aBoundRect.Left() > aBoundRect.Right())
3060             aBoundRect.Left() = aBoundRect.Right();
3061         if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
3062             aBoundRect.Bottom() = LONG_MAX;
3063     }
3064     else
3065     {
3066         aBoundRect.Left() = aBmpRect.Right();
3067         aBoundRect.Left() += HOR_DIST_BMP_STRING;
3068         aBoundRect.Right() -= LROFFS_BOUND;
3069         if( aBoundRect.Left() > aBoundRect.Right() )
3070             aBoundRect.Left() = aBoundRect.Right();
3071         long nHeight = aBoundRect.GetSize().Height();
3072         nHeight = nHeight - aDefaultTextSize.Height();
3073         nHeight /= 2;
3074         aBoundRect.Top() += nHeight;
3075         aBoundRect.Bottom() -= nHeight;
3076     }
3077     return aBoundRect;
3078 }
3079 
3080 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
3081 {
3082     long nDY = nGridDY;
3083     nDY -= aImageSize.Height();
3084     nDY -= VER_DIST_BMP_STRING;
3085     nDY -= 2*TBOFFS_BOUND;
3086     if( nDY <= 0 )
3087         nDY = 2;
3088 
3089     long nDX = nGridDX;
3090     nDX -= 2*LROFFS_BOUND;
3091     nDX -= 2;
3092     if( nDX <= 0 )
3093         nDX = 2;
3094 
3095     String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
3096     long nHeight = pView->GetTextHeight();
3097     if( nDY < nHeight )
3098         nDY = nHeight;
3099     aDefaultTextSize = Size( nDX, nDY );
3100 }
3101 
3102 
3103 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
3104 {
3105     pEntry->aRect = pEntry->aGridRect;
3106     Size aSize( CalcBoundingSize( pEntry ) );
3107     if( nWinBits & WB_ICON )
3108     {
3109         // horizontal zentrieren
3110         long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
3111         pEntry->aRect.Left() += nBorder / 2;
3112         pEntry->aRect.Right() -= nBorder / 2;
3113     }
3114     // vertikal zentrieren
3115     pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
3116 }
3117 
3118 
3119 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3120 // links, hoch: Offsets < 0
3121 // rechts, runter: Offsets > 0
3122 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
3123 {
3124     const MapMode& rMapMode = pView->GetMapMode();
3125     Point aOrigin( rMapMode.GetOrigin() );
3126     // in Dokumentkoordinate umwandeln
3127     aOrigin *= -1;
3128     aOrigin.Y() += nDeltaY;
3129     aOrigin.X() += nDeltaX;
3130     Rectangle aRect( aOrigin, aOutputSize );
3131     MakeVisible( aRect, bScrollBar );
3132 }
3133 
3134 
3135 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
3136     IcnViewFieldType eItem ) const
3137 {
3138     if( eItem == IcnViewFieldTypeText )
3139         return aDefaultTextSize;
3140     return aImageSize;
3141 }
3142 
3143 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
3144 {
3145     Rectangle aBmpRect( CalcBmpRect( pEntry ) );
3146     Rectangle aTextRect( CalcTextRect( pEntry ) );
3147     Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
3148     Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1,
3149                           aBoundRect.Right() - 4, aTextRect.Bottom() + 1 );
3150     // Das Fokusrechteck soll nicht den Text beruehren
3151     if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() )
3152         aFocusRect.Left()--;
3153     if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() )
3154         aFocusRect.Right()++;
3155 
3156     return aFocusRect;
3157 }
3158 
3159 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
3160 static Rectangle GetHotSpot( const Rectangle& rRect )
3161 {
3162     Rectangle aResult( rRect );
3163     aResult.Justify();
3164     Size aSize( rRect.GetSize() );
3165     long nDelta = aSize.Width() / 4;
3166     aResult.Left() += nDelta;
3167     aResult.Right() -= nDelta;
3168     nDelta = aSize.Height() / 4;
3169     aResult.Top() += nDelta;
3170     aResult.Bottom() -= nDelta;
3171     return aResult;
3172 }
3173 
3174 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
3175     sal_Bool bAdd, SvPtrarr* pOtherRects )
3176 {
3177     DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3178     Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3179     aRect.Union( GetEntryBoundRect( pEntry2 ) );
3180     SelectRect( aRect, bAdd, pOtherRects );
3181 }
3182 
3183 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, sal_Bool bAdd,
3184     SvPtrarr* pOtherRects )
3185 {
3186     aCurSelectionRect = rRect;
3187     if( !pZOrderList || !pZOrderList->Count() )
3188         return;
3189 
3190     // Flag setzen, damit im Select kein ToTop gerufen wird
3191     sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False;
3192     nFlags |= F_SELECTING_RECT;
3193 
3194     CheckBoundingRects();
3195     pView->Update();
3196     const sal_uLong nCount = pZOrderList->Count();
3197 
3198     Rectangle aRect( rRect );
3199     aRect.Justify();
3200     sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False;
3201 
3202     sal_Bool bResetClipRegion = sal_False;
3203     if( !pView->IsClipRegion() )
3204     {
3205         bResetClipRegion = sal_True;
3206         pView->SetClipRegion( GetOutputRect() );
3207     }
3208 
3209     for( sal_uLong nPos = 0; nPos < nCount; nPos++ )
3210     {
3211         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
3212 
3213         if( !IsBoundingRectValid( pEntry->aRect ))
3214             FindBoundingRect( pEntry );
3215         Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
3216         sal_Bool bSelected = pEntry->IsSelected();
3217 
3218         sal_Bool bOverlaps;
3219         if( bCalcOverlap )
3220             bOverlaps = IsOver( pOtherRects, aBoundRect );
3221         else
3222             bOverlaps = sal_False;
3223         sal_Bool bOver = aRect.IsOver( aBoundRect );
3224 
3225         if( bOver && !bOverlaps )
3226         {
3227             // Ist im neuen Selektionsrechteck und in keinem alten
3228             // => selektieren
3229             if( !bSelected )
3230                 SelectEntry( pEntry, sal_True, sal_True, sal_True );
3231         }
3232         else if( !bAdd )
3233         {
3234             // ist ausserhalb des Selektionsrechtecks
3235             // => Selektion entfernen
3236             if( bSelected )
3237                 SelectEntry( pEntry, sal_False, sal_True, sal_True );
3238         }
3239         else if( bAdd && bOverlaps )
3240         {
3241             // Der Eintrag befindet sich in einem alten (=>Aufspannen
3242             // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3243 
3244             // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3245             // in einem vorherigen Rechteck, muss restauriert werden, wenn
3246             // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3247             // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3248             // pauschal davon aus, dass die Eintraege in den alten Rechtecken
3249             // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3250             // nur zu deselektieren.
3251             // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3252             // spannen des Rechtecks merken
3253             if( aBoundRect.IsOver( rRect))
3254             {
3255                 // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3256                 if( bSelected )
3257                     SelectEntry( pEntry, sal_False, sal_True, sal_True );
3258             }
3259             else
3260             {
3261                 // Eintrag eines alten Rects selektieren
3262                 if( !bSelected )
3263                     SelectEntry( pEntry, sal_True, sal_True, sal_True );
3264             }
3265         }
3266         else if( !bOver && bSelected )
3267         {
3268             // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3269             SelectEntry( pEntry, sal_False, sal_True, sal_True );
3270         }
3271     }
3272 
3273     if( !bAlreadySelectingRect )
3274         nFlags &= ~F_SELECTING_RECT;
3275 
3276     pView->Update();
3277     if( bResetClipRegion )
3278         pView->SetClipRegion();
3279 }
3280 
3281 void SvxIconChoiceCtrl_Impl::SelectRange(
3282                         SvxIconChoiceCtrlEntry* pStart,
3283                         SvxIconChoiceCtrlEntry* pEnd,
3284                         sal_Bool bAdd )
3285 {
3286     sal_uLong nFront = GetEntryListPos( pStart );
3287     sal_uLong nBack  = GetEntryListPos( pEnd );
3288     sal_uLong nFirst = std::min( nFront, nBack );
3289     sal_uLong nLast  = std::max( nFront, nBack );
3290     sal_uLong i;
3291     SvxIconChoiceCtrlEntry* pEntry;
3292 
3293     if ( ! bAdd )
3294     {
3295         // deselect everything before the first entry if not in
3296         // adding mode
3297         for ( i=0; i<nFirst; i++ )
3298         {
3299             pEntry = GetEntry( i );
3300             if( pEntry->IsSelected() )
3301                 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3302         }
3303     }
3304 
3305     // select everything between nFirst and nLast
3306     for ( i=nFirst; i<=nLast; i++ )
3307     {
3308         pEntry = GetEntry( i );
3309         if( ! pEntry->IsSelected() )
3310             SelectEntry( pEntry, sal_True, sal_True,  sal_True, sal_True );
3311     }
3312 
3313     if ( ! bAdd )
3314     {
3315         // deselect everything behind the last entry if not in
3316         // adding mode
3317         sal_uLong nEnd = GetEntryCount();
3318         for ( ; i<nEnd; i++ )
3319         {
3320             pEntry = GetEntry( i );
3321             if( pEntry->IsSelected() )
3322                 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3323         }
3324     }
3325 }
3326 
3327 sal_Bool SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3328 {
3329     const sal_uInt16 nCount = pRectList->Count();
3330     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3331     {
3332         Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3333         if( rBoundRect.IsOver( *pRect ))
3334             return sal_True;
3335     }
3336     return sal_False;
3337 }
3338 
3339 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
3340     SvxIconChoiceCtrlEntry* pEntry2 )
3341 {
3342     DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3343     Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3344     aRect.Union( GetEntryBoundRect( pEntry2 ) );
3345     AddSelectedRect( aRect );
3346 }
3347 
3348 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
3349 {
3350     Rectangle* pRect = new Rectangle( rRect );
3351     pRect->Justify();
3352     aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3353 }
3354 
3355 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
3356 {
3357     const sal_uInt16 nCount = aSelectedRectList.Count();
3358     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3359     {
3360         Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3361         delete pRect;
3362     }
3363     aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3364 }
3365 
3366 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel,
3367     long& rX, long& rY, sal_Bool isInDragDrop, sal_uInt16 nBorderWidth)
3368 {
3369     // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3370     // Fensters befindet
3371     long nPixelToScrollX = 0;
3372     long nPixelToScrollY = 0;
3373     Size aWndSize = aOutputSize;
3374 
3375     nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3376     nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3377 
3378     if ( rPosPixel.X() < nBorderWidth )
3379     {
3380         if( isInDragDrop )
3381             nPixelToScrollX = -DD_SCROLL_PIXEL;
3382         else
3383             nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3384     }
3385     else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3386     {
3387         if( isInDragDrop )
3388             nPixelToScrollX = DD_SCROLL_PIXEL;
3389         else
3390             nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3391     }
3392     if ( rPosPixel.Y() < nBorderWidth )
3393     {
3394         if( isInDragDrop )
3395             nPixelToScrollY = -DD_SCROLL_PIXEL;
3396         else
3397             nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3398     }
3399     else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3400     {
3401         if( isInDragDrop )
3402             nPixelToScrollY = DD_SCROLL_PIXEL;
3403         else
3404             nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3405     }
3406 
3407     rX = nPixelToScrollX;
3408     rY = nPixelToScrollY;
3409 }
3410 
3411 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG )
3412 {
3413     aAutoArrangeTimer.Stop();
3414     Arrange( IsAutoArrange() );
3415     return 0;
3416 }
3417 
3418 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG )
3419 {
3420     aVisRectChangedTimer.Stop();
3421     pView->VisibleRectChanged();
3422     return 0;
3423 }
3424 
3425 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG )
3426 {
3427     aDocRectChangedTimer.Stop();
3428     pView->DocumentRectChanged();
3429     return 0;
3430 }
3431 
3432 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt )
3433 {
3434     StopEditTimer();
3435     SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() );
3436     if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() )
3437         SelectEntry( pEntry, sal_True, sal_True );
3438     nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
3439 }
3440 
3441 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
3442 {
3443     Rectangle aRect( CalcTextRect( pEntry ));
3444     if( aRect.IsInside( rDocPos ) )
3445         return sal_True;
3446     return sal_False;
3447 }
3448 
3449 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG )
3450 {
3451     SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
3452     if( bEntryEditingEnabled && pEntry &&
3453         pEntry->IsSelected())
3454     {
3455         if( pView->EditingEntry( pEntry ))
3456             EditEntry( pEntry );
3457     }
3458     return 0;
3459 }
3460 
3461 
3462 //
3463 // Funktionen zum Ausrichten der Eintraege am Grid
3464 //
3465 
3466 // pStart == 0: Alle Eintraege werden ausgerichtet
3467 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
3468 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
3469 {
3470     SvPtrarr aLists;
3471     pImpCursor->CreateGridAjustData( aLists, pStart );
3472     const sal_uInt16 nCount = aLists.Count();
3473     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3474         AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
3475     IcnCursor_Impl::DestroyGridAdjustData( aLists );
3476     CheckScrollBars();
3477 }
3478 
3479 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
3480 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart )
3481 {
3482     if( !rRow.Count() )
3483         return;
3484 
3485     sal_Bool bGo;
3486     if( !pStart )
3487         bGo = sal_True;
3488     else
3489         bGo = sal_False;
3490 
3491     long nCurRight = 0;
3492     for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ )
3493     {
3494         SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ];
3495         if( !bGo && pCur == pStart )
3496             bGo = sal_True;
3497 
3498         //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3499         // Massgebend (fuer unser Auge) ist die Bitmap, da sonst
3500         // durch lange Texte der Eintrag stark springen kann
3501         const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3502         Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3503         if( bGo && !pCur->IsPosLocked() )
3504         {
3505             long nWidth = aCenterRect.GetSize().Width();
3506             Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3507             while( aNewPos.X() < nCurRight )
3508                 aNewPos.X() += nGridDX;
3509             if( aNewPos != rBoundRect.TopLeft() )
3510             {
3511                 SetEntryPos( pCur, aNewPos );
3512                 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3513                 nFlags |= F_MOVED_ENTRIES;
3514             }
3515             nCurRight = aNewPos.X() + nWidth;
3516         }
3517         else
3518         {
3519             nCurRight = rBoundRect.Right();
3520         }
3521     }
3522 }
3523 
3524 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
3525 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
3526 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
3527 // die Berechnung des Ziel-Rechtecks verwendet wird.
3528 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3529     const Rectangle& rBoundRect ) const
3530 {
3531     Point aPos( rCenterRect.TopLeft() );
3532     Size aSize( rCenterRect.GetSize() );
3533 
3534     aPos.X() -= LROFFS_WINBORDER;
3535     aPos.Y() -= TBOFFS_WINBORDER;
3536 
3537     // align (ref ist mitte des rects)
3538     short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3539     short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3540     aPos.X() = nGridX * nGridDX;
3541     aPos.Y() = nGridY * nGridDY;
3542     // hor. center
3543     aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3544 
3545     aPos.X() += LROFFS_WINBORDER;
3546     aPos.Y() += TBOFFS_WINBORDER;
3547 
3548     return aPos;
3549 }
3550 
3551 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3552 {
3553     if( !pEntry )
3554     {
3555         if( eTextMode != eMode )
3556         {
3557             if( eTextMode == IcnShowTextDontKnow )
3558                 eTextMode = IcnShowTextShort;
3559             eTextMode = eMode;
3560             Arrange( sal_True );
3561         }
3562     }
3563     else
3564     {
3565         if( pEntry->eTextMode != eMode )
3566         {
3567             pEntry->eTextMode = eMode;
3568             InvalidateEntry( pEntry );
3569             pView->Invalidate( GetEntryBoundRect( pEntry ) );
3570             AdjustVirtSize( pEntry->aRect );
3571         }
3572     }
3573 }
3574 
3575 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
3576 {
3577     if( !pEntry )
3578         return eTextMode;
3579     return pEntry->GetTextMode();
3580 }
3581 
3582 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3583 {
3584     DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3585     SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3586     if( eMode == IcnShowTextDontKnow )
3587         return eTextMode;
3588     return eMode;
3589 }
3590 
3591 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry )
3592 {
3593     if( !pEntry )
3594     {
3595         pView->HideFocus();
3596     }
3597     else
3598     {
3599         Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
3600         /*pView->*/ShowFocus( aRect );
3601     }
3602 }
3603 
3604 ////////////////////////////////////////////////////////////////////////////////////////////////
3605 //
3606 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3607 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see
3608 // a gray focusrect on a gray background !!!
3609 //
3610 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3611 {
3612     Color aBkgColor ( pView->GetBackground().GetColor() );
3613     Color aPenColor;
3614     sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3615     if ( nColor > 128 )
3616         aPenColor.SetColor ( COL_BLACK );
3617     else
3618         aPenColor.SetColor( COL_WHITE );
3619 
3620     aFocus.bOn = sal_True;
3621     aFocus.aPenColor = aPenColor;
3622     aFocus.aRect = rRect;
3623 }
3624 
3625 void SvxIconChoiceCtrl_Impl::HideFocus ()
3626 {
3627     aFocus.bOn = sal_False;
3628 }
3629 
3630 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3631 {
3632     pOut->SetLineColor( aFocus.aPenColor );
3633     pOut->SetFillColor();
3634     Polygon aPolygon ( aFocus.aRect );
3635 
3636     LineInfo aLineInfo ( LINE_DASH );
3637 
3638     aLineInfo.SetDashLen ( 1 );
3639 
3640     aLineInfo.SetDotLen ( 1L );
3641     aLineInfo.SetDistance ( 1L );
3642     aLineInfo.SetDotCount ( 1 );
3643 
3644     pOut->DrawPolyLine ( aPolygon, aLineInfo );
3645 }
3646 
3647 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
3648 {
3649     sal_Bool bRet = sal_False;
3650     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3651     sal_uLong nEntryCount = GetEntryCount();
3652     for ( sal_uLong i = 0; i < nEntryCount; ++i )
3653     {
3654         if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3655         {
3656             bRet = sal_True;
3657             rPos = i;
3658             break;
3659         }
3660     }
3661 
3662     return bRet;
3663 }
3664 
3665 //
3666 ////////////////////////////////////////////////////////////////////////////////////////////////
3667 
3668 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3669 {
3670     if( nId == EVENTID_ADJUST_SCROLLBARS )
3671     {
3672         nUserEventAdjustScrBars = 0;
3673         AdjustScrollBars();
3674     }
3675     else if( nId == EVENTID_SHOW_CURSOR )
3676     {
3677         nUserEventShowCursor = 0;
3678         ShowCursor( sal_True );
3679     }
3680     return 0;
3681 }
3682 
3683 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3684 {
3685     if( nUserEventAdjustScrBars )
3686     {
3687         Application::RemoveUserEvent( nUserEventAdjustScrBars );
3688         nUserEventAdjustScrBars = 0;
3689     }
3690     if( nUserEventShowCursor )
3691     {
3692         Application::RemoveUserEvent( nUserEventShowCursor );
3693         nUserEventShowCursor = 0;
3694     }
3695 }
3696 
3697 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3698 {
3699     if( pEntry == pCursor )
3700         ShowCursor( sal_False );
3701     pView->Invalidate( pEntry->aRect );
3702     Center( pEntry );
3703     pView->Invalidate( pEntry->aRect );
3704     if( pEntry == pCursor )
3705         ShowCursor( sal_True );
3706 }
3707 
3708 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3709 {
3710     DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3711     if( !pEntry )
3712         return;
3713 
3714     StopEntryEditing( sal_True );
3715     DELETEZ(pEdit);
3716     SetNoSelection();
3717 
3718     pCurEditedEntry = pEntry;
3719     String aEntryText( pView->GetEntryText( pEntry, sal_True ) );
3720     Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) );
3721     MakeVisible( aRect );
3722     Point aPos( aRect.TopLeft() );
3723     aPos = pView->GetPixelPos( aPos );
3724     aRect.SetPos( aPos );
3725     pView->HideFocus();
3726     pEdit = new IcnViewEdit_Impl(
3727         pView,
3728         aRect.TopLeft(),
3729         aRect.GetSize(),
3730         aEntryText,
3731         LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3732 }
3733 
3734 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG )
3735 {
3736     DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3737     if( !pEdit )
3738     {
3739         pCurEditedEntry = 0;
3740         return 0;
3741     }
3742     DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3743 
3744     if( !pCurEditedEntry )
3745     {
3746         pEdit->Hide();
3747         if( pEdit->IsGrabFocus() )
3748             pView->GrabFocus();
3749         return 0;
3750     }
3751 
3752     String aText;
3753     if ( !pEdit->EditingCanceled() )
3754         aText = pEdit->GetText();
3755     else
3756         aText = pEdit->GetSavedValue();
3757 
3758     if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3759         InvalidateEntry( pCurEditedEntry );
3760     if( !GetSelectionCount() )
3761         SelectEntry( pCurEditedEntry, sal_True );
3762 
3763     pEdit->Hide();
3764     if( pEdit->IsGrabFocus() )
3765         pView->GrabFocus();
3766     // Das Edit kann nicht hier geloescht werden, weil es noch in einem
3767     // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht.
3768     pCurEditedEntry = 0;
3769     return 0;
3770 }
3771 
3772 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel )
3773 {
3774     if( pEdit )
3775         pEdit->StopEditing( bCancel );
3776 }
3777 
3778 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bLock )
3779 {
3780     if( bLock )
3781         pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED );
3782     else
3783         pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED );
3784 }
3785 
3786 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3787 {
3788     if( !GetSelectionCount() )
3789         return 0;
3790 
3791     if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3792     {
3793         rPos = pView->GetEntryListPos( pCurHighlightFrame );
3794         return pCurHighlightFrame;
3795     }
3796 
3797     sal_uLong nCount = aEntries.Count();
3798     if( !pHead )
3799     {
3800         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
3801         {
3802             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3803             if( pEntry->IsSelected() )
3804             {
3805                 rPos = nCur;
3806                 return pEntry;
3807             }
3808         }
3809     }
3810     else
3811     {
3812         SvxIconChoiceCtrlEntry* pEntry = pHead;
3813         while( nCount-- )
3814         {
3815             if( pEntry->IsSelected() )
3816             {
3817                 rPos = GetEntryListPos( pEntry );
3818                 return pEntry;
3819             }
3820             pEntry = pEntry->pflink;
3821             if( nCount && pEntry == pHead )
3822             {
3823                 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
3824                 return 0;
3825             }
3826         }
3827     }
3828     return 0;
3829 }
3830 
3831 // kein Round Robin!
3832 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( sal_uLong& rStartPos ) const
3833 {
3834     sal_uLong nCount = aEntries.Count();
3835     if( rStartPos > nCount || !GetSelectionCount() )
3836         return 0;
3837     if( !pHead )
3838     {
3839         for( sal_uLong nCur = rStartPos+1; nCur < nCount; nCur++ )
3840         {
3841             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3842             if( pEntry->IsSelected() )
3843             {
3844                 rStartPos = nCur;
3845                 return pEntry;
3846             }
3847         }
3848     }
3849     else
3850     {
3851         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos );
3852         pEntry = pEntry->pflink;
3853         while( pEntry != pHead )
3854         {
3855             if( pEntry->IsSelected() )
3856             {
3857                 rStartPos = GetEntryListPos( pEntry );
3858                 return pEntry;
3859             }
3860             pEntry = pEntry->pflink;
3861         }
3862     }
3863 
3864     rStartPos = 0xffffffff;
3865     return 0;
3866 }
3867 
3868 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint )
3869 {
3870     bPaint = sal_True;
3871 
3872     sal_uLong nCount = aEntries.Count();
3873     for( sal_uLong nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3874     {
3875         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3876         SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint );
3877     }
3878     nFlags &= (~F_ADD_MODE);
3879     pAnchor = 0;
3880 }
3881 
3882 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList )
3883 {
3884     if( !*ppList )
3885         *ppList = new List;
3886     sal_uLong nPos;
3887     SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos );
3888     while( pEntry && GetSelectionCount() != (*ppList)->Count() )
3889     {
3890         (*ppList)->Insert( pEntry, LIST_APPEND );
3891         pEntry = GetNextSelectedEntry( nPos );
3892     }
3893 }
3894 
3895 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3896     const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
3897     MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3898     aCallBackHdl( rNotifyEditEnd ),
3899     bCanceled( sal_False ),
3900     bAlreadyInCallback( sal_False ),
3901     bGrabFocus( sal_False )
3902 {
3903     Font aFont( pParent->GetPointFont() );
3904     aFont.SetTransparent( sal_False );
3905     SetControlFont( aFont );
3906     if( !pParent->HasFontFillColor() )
3907     {
3908         Color aColor( pParent->GetBackground().GetColor() );
3909         SetControlBackground( aColor );
3910     }
3911     else
3912         SetControlBackground( aFont.GetFillColor() );
3913     SetControlForeground( aFont.GetColor() );
3914     SetPosPixel( rPos );
3915     SetSizePixel( CalcAdjustedSize(rSize) );
3916     SetText( rData );
3917     SaveValue();
3918 
3919     aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3920     aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3921 
3922     aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3923     aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3924     GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3925     GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3926     Show();
3927     GrabFocus();
3928 }
3929 
3930 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3931 {
3932     if( !bAlreadyInCallback )
3933     {
3934         GetpApp()->RemoveAccel( &aAccReturn );
3935         GetpApp()->RemoveAccel( &aAccEscape );
3936     }
3937 }
3938 
3939 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3940 {
3941     aTimer.Stop();
3942     if ( !bAlreadyInCallback )
3943     {
3944         bAlreadyInCallback = sal_True;
3945         GetpApp()->RemoveAccel( &aAccReturn );
3946         GetpApp()->RemoveAccel( &aAccEscape );
3947         Hide();
3948         aCallBackHdl.Call( this );
3949     }
3950 }
3951 
3952 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG )
3953 {
3954     CallCallBackHdl_Impl();
3955     return 0;
3956 }
3957 
3958 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG  )
3959 {
3960     bCanceled = sal_False;
3961     bGrabFocus = sal_True;
3962     CallCallBackHdl_Impl();
3963     return 1;
3964 }
3965 
3966 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG  )
3967 {
3968     bCanceled = sal_True;
3969     bGrabFocus = sal_True;
3970     CallCallBackHdl_Impl();
3971     return 1;
3972 }
3973 
3974 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3975 {
3976     KeyCode aCode = rKEvt.GetKeyCode();
3977     sal_uInt16 nCode = aCode.GetCode();
3978 
3979     switch ( nCode )
3980     {
3981         case KEY_ESCAPE:
3982             bCanceled = sal_True;
3983             bGrabFocus = sal_True;
3984             CallCallBackHdl_Impl();
3985             break;
3986 
3987         case KEY_RETURN:
3988             bCanceled = sal_False;
3989             bGrabFocus = sal_True;
3990             CallCallBackHdl_Impl();
3991             break;
3992 
3993         default:
3994             MultiLineEdit::KeyInput( rKEvt );
3995     }
3996 }
3997 
3998 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3999 {
4000     if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4001     {
4002         if ( !bAlreadyInCallback &&
4003             ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
4004         {
4005             bCanceled = sal_False;
4006             aTimer.SetTimeout(10);
4007             aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
4008             aTimer.Start();
4009         }
4010     }
4011     return 0;
4012 }
4013 
4014 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel )
4015 {
4016     if ( !bAlreadyInCallback )
4017     {
4018         bCanceled = bCancel;
4019         CallCallBackHdl_Impl();
4020     }
4021 }
4022 
4023 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
4024 {
4025     if( !(nFlags & F_ENTRYLISTPOS_VALID ))
4026         ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
4027     return pEntry->nPos;
4028 }
4029 
4030 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, sal_uLong nNewPos )
4031 {
4032     sal_uLong nCurPos = GetEntryListPos( pListEntry );
4033     if( nCurPos == nNewPos )
4034         return;
4035     aEntries.List::Remove( nCurPos );
4036     aEntries.List::Insert( (void*)pListEntry, nNewPos );
4037     // Eintragspositionen anpassen
4038     sal_uLong nStart, nEnd;
4039     if( nNewPos < nCurPos )
4040     {
4041         nStart = nNewPos;
4042         nEnd = nCurPos;
4043     }
4044     else
4045     {
4046         nStart = nCurPos;
4047         nEnd = nNewPos;
4048     }
4049     for( ; nStart <= nEnd; nStart++ )
4050     {
4051         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart );
4052         pEntry->nPos = nStart;
4053     }
4054 }
4055 
4056 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nEntryFlags )
4057 {
4058     pEntry->nFlags = nEntryFlags;
4059     if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED )
4060         nFlags |= F_MOVED_ENTRIES;
4061 }
4062 
4063 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, sal_Bool bRight )
4064 {
4065     return pImpCursor->GoLeftRight( pStart, bRight );
4066 }
4067 
4068 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown )
4069 {
4070     return pImpCursor->GoUpDown( pStart, bDown );
4071 }
4072 
4073 void SvxIconChoiceCtrl_Impl::InitSettings()
4074 {
4075     const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
4076 
4077     if( !pView->HasFont() )
4078     {
4079         // Unit aus den Settings ist Point
4080         Font aFont( rStyleSettings.GetFieldFont() );
4081         //const Font& rFont = pView->GetFont();
4082         //if( pView->HasFontTextColor() )
4083             aFont.SetColor( rStyleSettings.GetWindowTextColor() );
4084         //if( pView->HasFontFillColor() )
4085             //aFont.SetFillColor( rFont.GetFillColor() );
4086         pView->SetPointFont( aFont );
4087         SetDefaultTextSize();
4088     }
4089 
4090     //if( !pView->HasFontTextColor() )
4091         pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
4092     //if( !pView->HasFontFillColor() )
4093         pView->SetTextFillColor();
4094 
4095     //if( !pView->HasBackground() )
4096         pView->SetBackground( rStyleSettings.GetFieldColor());
4097 
4098     long nScrBarSize = rStyleSettings.GetScrollBarSize();
4099     if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
4100     {
4101         nHorSBarHeight = nScrBarSize;
4102         Size aSize( aHorSBar.GetSizePixel() );
4103         aSize.Height() = nScrBarSize;
4104         aHorSBar.Hide();
4105         aHorSBar.SetSizePixel( aSize );
4106 
4107         nVerSBarWidth = nScrBarSize;
4108         aSize = aVerSBar.GetSizePixel();
4109         aSize.Width() = nScrBarSize;
4110         aVerSBar.Hide();
4111         aVerSBar.SetSizePixel( aSize );
4112 
4113         Size aOSize( pView->Control::GetOutputSizePixel() );
4114         PositionScrollBars( aOSize.Width(), aOSize.Height() );
4115         AdjustScrollBars();
4116     }
4117 }
4118 
4119 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nInitSize , sal_uInt16 _nReSize ) :
4120     List( _nInitSize, _nReSize ),
4121     _pOwner( pOwner )
4122 {
4123     _pOwner->pHead = 0;
4124 }
4125 
4126 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) :
4127     List( _nBlockSize, _nInitSize, _nReSize ),
4128     _pOwner( pOwner )
4129 {
4130     _pOwner->pHead = 0;
4131 }
4132 
4133 EntryList_Impl::~EntryList_Impl()
4134 {
4135     _pOwner->pHead = 0;
4136 }
4137 
4138 void EntryList_Impl::Clear()
4139 {
4140     _pOwner->pHead = 0;
4141     List::Clear();
4142 }
4143 
4144 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos )
4145 {
4146     List::Insert( pEntry, nPos );
4147     if( _pOwner->pHead )
4148         pEntry->SetBacklink( _pOwner->pHead->pblink );
4149 }
4150 
4151 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( sal_uLong nPos )
4152 {
4153     SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos );
4154     DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found");
4155     Removed_Impl( pEntry );
4156     return pEntry;
4157 }
4158 
4159 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry )
4160 {
4161     List::Remove( (void*)pEntry );
4162     Removed_Impl( pEntry );
4163 }
4164 
4165 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry )
4166 {
4167     if( _pOwner->pHead )
4168     {
4169         if( _pOwner->pHead == pEntry )
4170         {
4171             if( _pOwner->pHead != pEntry->pflink )
4172                 _pOwner->pHead = pEntry->pflink;
4173             else
4174             {
4175                 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
4176                 _pOwner->pHead = 0;
4177             }
4178         }
4179         pEntry->Unlink();
4180     }
4181 }
4182 
4183 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
4184 {
4185     sal_uLong nCur;
4186 
4187     if( eMode == ePositionMode )
4188         return;
4189 
4190     SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
4191     ePositionMode = eMode;
4192     sal_uLong nCount = aEntries.Count();
4193 
4194     if( eOldMode == IcnViewPositionModeAutoArrange )
4195     {
4196         // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme
4197         // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange
4198         // nicht beruecksichtigt werden.
4199 #if 1
4200         if( aEntries.Count() )
4201             aAutoArrangeTimer.Start();
4202 #else
4203         if( pHead )
4204         {
4205             // verschobene Eintraege 'hart' auf ihre Position setzen
4206             nCur = nCount;
4207             SvxIconChoiceCtrlEntry* pEntry = pHead;
4208             while( nCur )
4209             {
4210                 SvxIconChoiceCtrlEntry* pPred;
4211                 if( GetEntryPredecessor( pEntry, &pPred ))
4212                     SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED );
4213                 pEntry = pEntry->pflink;
4214                 nCur--;
4215             }
4216             ClearPredecessors();
4217         }
4218 #endif
4219         return;
4220     }
4221 
4222     if( ePositionMode == IcnViewPositionModeAutoArrange )
4223     {
4224         List aMovedEntries;
4225         for( nCur = 0; nCur < nCount; nCur++ )
4226         {
4227             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
4228             if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
4229             {
4230                 SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl(
4231                         pEntry, GetEntryBoundRect( pEntry ));
4232                 aMovedEntries.Insert( pE, LIST_APPEND );
4233             }
4234         }
4235         nCount = aMovedEntries.Count();
4236         for( nCur = 0; nCur < nCount; nCur++ )
4237         {
4238             SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur);
4239             SetEntryPos( pE->_pEntry, pE->_aPos );
4240         }
4241         for( nCur = 0; nCur < nCount; nCur++ )
4242             delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur );
4243         if( aEntries.Count() )
4244             aAutoArrangeTimer.Start();
4245     }
4246     else if( ePositionMode == IcnViewPositionModeAutoAdjust )
4247     {
4248         AdjustEntryAtGrid( 0 );
4249     }
4250 }
4251 
4252 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4253     SvxIconChoiceCtrlEntry* pPredecessor )
4254 {
4255     if( !IsAutoArrange() )
4256         return;
4257 
4258     if( pEntry == pPredecessor )
4259         return;
4260 
4261     sal_uLong nPos1 = GetEntryListPos( pEntry );
4262     if( !pHead )
4263     {
4264         if( pPredecessor )
4265         {
4266             sal_uLong nPos2 = GetEntryListPos( pPredecessor );
4267             if( nPos1 == (nPos2 + 1) )
4268                 return; // ist schon Vorgaenger
4269         }
4270         else if( !nPos1 )
4271             return;
4272     }
4273 
4274     if( !pHead )
4275         InitPredecessors();
4276 
4277     if( !pPredecessor && pHead == pEntry )
4278         return; // ist schon der Erste
4279 
4280     sal_Bool bSetHead = sal_False;
4281     if( !pPredecessor )
4282     {
4283         bSetHead = sal_True;
4284         pPredecessor = pHead->pblink;
4285     }
4286     if( pEntry == pHead )
4287     {
4288         pHead = pHead->pflink;
4289         bSetHead = sal_False;
4290     }
4291     if( pEntry != pPredecessor )
4292     {
4293         pEntry->Unlink();
4294         pEntry->SetBacklink( pPredecessor );
4295     }
4296     if( bSetHead )
4297         pHead = pEntry;
4298     pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
4299     aAutoArrangeTimer.Start();
4300 }
4301 
4302 sal_Bool SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4303     SvxIconChoiceCtrlEntry** ppPredecessor )
4304 {
4305     *ppPredecessor = 0;
4306     if( !pHead )
4307         return sal_False;
4308     DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set");
4309     DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set");
4310 
4311     if( pEntry == pHead )
4312     {
4313         SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0);
4314         if( pFirst != pEntry )
4315             return sal_True;
4316         return sal_False;
4317     }
4318     *ppPredecessor = pEntry->pblink;
4319     if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) &&
4320         (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry ))
4321         return sal_False;
4322     return sal_True;
4323 }
4324 
4325 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4326     const Point& rPosTopLeft )
4327 {
4328     Point aPos( rPosTopLeft ); //TopLeft
4329     Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
4330     Point aNewPos( aCenterRect.Center() );
4331     sal_uLong nGrid = GetPredecessorGrid( aNewPos );
4332     sal_uLong nCount = aEntries.Count();
4333     if( nGrid == ULONG_MAX )
4334         return 0;
4335     if( nGrid >= nCount )
4336         nGrid = nCount - 1;
4337     if( !pHead )
4338         return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid );
4339 
4340     SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
4341     // todo: Liste von hinten aufrollen wenn nGrid > nCount/2
4342     for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
4343         pCur = pCur->pflink;
4344 
4345     return pCur;
4346 }
4347 
4348 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
4349 {
4350     Point aPos( rPos );
4351     aPos.X() -= LROFFS_WINBORDER;
4352     aPos.Y() -= TBOFFS_WINBORDER;
4353     sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX);
4354     if( nMaxCol )
4355         nMaxCol--;
4356     sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX);
4357     if( nGridX > nMaxCol )
4358         nGridX = nMaxCol;
4359     sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY);
4360     sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX);
4361     sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
4362     long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
4363     if( rPos.X() < nMiddle )
4364     {
4365         if( !nGrid )
4366             nGrid = ULONG_MAX;
4367         else
4368             nGrid--;
4369     }
4370     return nGrid;
4371 }
4372 
4373 void SvxIconChoiceCtrl_Impl::Flush()
4374 {
4375     if( aAutoArrangeTimer.IsActive() )
4376     {
4377         AutoArrangeHdl( 0 );
4378     }
4379 }
4380 
4381 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
4382 {
4383     if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
4384         return sal_False;
4385 
4386     Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
4387     aPos -= pView->GetMapMode().GetOrigin();
4388     SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True );
4389 
4390     if ( !pEntry )
4391         return sal_False;
4392 
4393     String sQuickHelpText = pEntry->GetQuickHelpText();
4394     String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
4395     Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) );
4396     if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
4397         return sal_False;
4398 
4399     Rectangle aOptTextRect( aTextRect );
4400     aOptTextRect.Bottom() = LONG_MAX;
4401     sal_uInt16 nNewFlags = nCurTextDrawFlags;
4402     nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
4403     aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
4404     if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
4405     {
4406         //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
4407         Point aPt( aOptTextRect.TopLeft() );
4408         aPt += pView->GetMapMode().GetOrigin();
4409         aPt = pView->OutputToScreenPixel( aPt );
4410         // Border der Tiphilfe abziehen
4411         aPt.Y() -= 1;
4412         aPt.X() -= 3;
4413         aOptTextRect.SetPos( aPt );
4414         String sHelpText;
4415         if ( sQuickHelpText.Len() > 0 )
4416             sHelpText = sQuickHelpText;
4417         else
4418             sHelpText = aEntryText;
4419         Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
4420     }
4421 
4422     return sal_True;
4423 }
4424 
4425 void SvxIconChoiceCtrl_Impl::ClearColumnList()
4426 {
4427     if( !pColumns )
4428         return;
4429 
4430     const sal_uInt16 nCount = pColumns->Count();
4431     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4432     {
4433         SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*)
4434             pColumns->GetObject( nCur );
4435         delete pInfo;
4436     }
4437     DELETEZ(pColumns);
4438 }
4439 
4440 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
4441 {
4442     if( !pColumns )
4443         pColumns = new SvPtrarr;
4444     while( pColumns->Count() < nIndex + 1 )
4445         pColumns->Insert( (void*)0, pColumns->Count() );
4446 
4447     SvxIconChoiceCtrlColumnInfo* pInfo =
4448         (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex);
4449     if( !pInfo )
4450     {
4451         pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4452         pColumns->Insert( (void*)pInfo, nIndex );
4453     }
4454     else
4455     {
4456         delete pInfo;
4457         pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4458         pColumns->Replace( pInfo, nIndex );
4459     }
4460 
4461     // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
4462     // dieses Workaround bringts mit einer Spalte zum Fliegen
4463     if( !nIndex && (nWinBits & WB_DETAILS) )
4464         nGridDX = pInfo->GetWidth();
4465 
4466     if( GetUpdateMode() )
4467         Arrange( IsAutoArrange() );
4468 }
4469 
4470 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
4471 {
4472     if( !pColumns || nIndex >= pColumns->Count() )
4473         return 0;
4474     return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex );
4475 }
4476 
4477 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( sal_uInt16 nSubItem,
4478     long& rLeft ) const
4479 {
4480     rLeft = 0;
4481     if( !pColumns )
4482         return 0;
4483     const sal_uInt16 nCount = pColumns->Count();
4484     const SvxIconChoiceCtrlColumnInfo* pCol = 0;
4485     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4486     {
4487          pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur );
4488         if( !pCol || pCol->GetSubItem() == nSubItem )
4489             return pCol;
4490         rLeft += pCol->GetWidth();
4491     }
4492     return pCol;
4493 }
4494 
4495 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
4496     OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide )
4497 {
4498     Rectangle aBmpRect( rBmpRect );
4499     long nBorder = 2;
4500     if( aImageSize.Width() < 32 )
4501         nBorder = 1;
4502     aBmpRect.Right() += nBorder;
4503     aBmpRect.Left() -= nBorder;
4504     aBmpRect.Bottom() += nBorder;
4505     aBmpRect.Top() -= nBorder;
4506 
4507     if ( bHide )
4508         pView->Invalidate( aBmpRect );
4509     else
4510     {
4511         DecorationView aDecoView( pOut );
4512         sal_uInt16 nDecoFlags;
4513         if ( bHighlightFramePressed )
4514             nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
4515         else
4516             nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
4517         aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
4518     }
4519 }
4520 
4521 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
4522     sal_Bool bKeepHighlightFlags )
4523 {
4524     if( pEntry == pCurHighlightFrame )
4525         return;
4526 
4527     if( !bKeepHighlightFlags )
4528         bHighlightFramePressed = sal_False;
4529 
4530     HideEntryHighlightFrame();
4531     pCurHighlightFrame = pEntry;
4532     if( pEntry )
4533     {
4534         Rectangle aBmpRect( CalcFocusRect(pEntry) );
4535         DrawHighlightFrame( pView, aBmpRect, sal_False );
4536     }
4537 }
4538 
4539 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
4540 {
4541     if( !pCurHighlightFrame )
4542         return;
4543 
4544     SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
4545     pCurHighlightFrame = 0;
4546     Rectangle aBmpRect( CalcFocusRect(pEntry) );
4547     DrawHighlightFrame( pView, aBmpRect, sal_True );
4548 }
4549 
4550 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
4551 {
4552     // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler
4553     // synchron gerufen werden, weil die Selektion automatisch
4554     // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt
4555     // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen,
4556     // wenn das Objekt aus einer Mausbewegung heraus selektiert wird,
4557     // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U.
4558     // schon verlassen hat.
4559     // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone
4560     // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden.
4561     if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
4562     {
4563         pHdlEntry = 0;
4564         pView->ClickIcon();
4565         //pView->Select();
4566     }
4567     else
4568         aCallSelectHdlTimer.Start();
4569 }
4570 
4571 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG )
4572 {
4573     pHdlEntry = 0;
4574     pView->ClickIcon();
4575     //pView->Select();
4576     return 0;
4577 }
4578 
4579 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
4580 {
4581     Point aResult;
4582     if( !GetSelectionCount() )
4583         return aResult;
4584 
4585     SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
4586     if( !pEntry || !pEntry->IsSelected() )
4587     {
4588         sal_uLong nNext;
4589         pEntry = GetFirstSelectedEntry( nNext );
4590     }
4591     if( pEntry )
4592     {
4593         Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) );
4594         aResult = aRect.Center();
4595         aResult = pView->GetPixelPos( aResult );
4596     }
4597     return aResult;
4598 }
4599 
4600 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper )
4601 {
4602     MapMode aMapMode( pView->GetMapMode() );
4603     aMapMode.SetOrigin( rPos );
4604     pView->SetMapMode( aMapMode );
4605     if( !bDoNotUpdateWallpaper )
4606     {
4607         sal_Bool bScrollable = pView->GetBackground().IsScrollable();
4608         if( pView->HasBackground() && !bScrollable )
4609         {
4610             Rectangle aRect( GetOutputRect());
4611             Wallpaper aPaper( pView->GetBackground() );
4612             aPaper.SetRect( aRect );
4613             pView->SetBackground( aPaper );
4614         }
4615     }
4616 }
4617 
4618 sal_uLong SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, sal_Bool bCheckScrBars,
4619     sal_Bool bSmartScrBar ) const
4620 {
4621     Size aSize( rSize );
4622     if( bCheckScrBars && aHorSBar.IsVisible() )
4623         aSize.Height() -= nHorSBarHeight;
4624     else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) )
4625         aSize.Height() -= nHorSBarHeight;
4626 
4627     if( bCheckScrBars && aVerSBar.IsVisible() )
4628         aSize.Width() -= nVerSBarWidth;
4629     else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) )
4630         aSize.Width() -= nVerSBarWidth;
4631 
4632     if( aSize.Width() < 0 )
4633         aSize.Width() = 0;
4634     if( aSize.Height() < 0 )
4635         aSize.Height() = 0;
4636 
4637     return IcnGridMap_Impl::GetGridCount( aSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
4638 }
4639 
4640 sal_Bool SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt )
4641 {
4642     StopEditTimer();
4643 
4644     sal_Bool        bRet = sal_False;
4645 
4646     DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" );
4647 
4648     sal_Unicode cChar = rKEvt.GetCharCode();
4649     sal_uLong       nPos = (sal_uLong)-1;
4650 
4651     if( cChar && IsMnemonicChar( cChar, nPos ) )
4652     {
4653         // shortcut is clicked
4654         SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
4655         SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
4656         if( pNewCursor != pOldCursor )
4657         {
4658             SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
4659 
4660             if( pNewCursor != NULL )
4661             {
4662                 pHdlEntry = pNewCursor;
4663                 pCurHighlightFrame = pHdlEntry;
4664                 pView->ClickIcon();
4665                 pCurHighlightFrame = NULL;
4666             }
4667         }
4668         bRet = sal_True;
4669     }
4670 
4671     return bRet;
4672 }
4673 
4674 // -----------------------------------------------------------------------
4675 
4676 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
4677 {
4678     pView->CallImplEventListeners( nEvent, pData );
4679 }
4680 
4681 
4682