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