xref: /trunk/main/svtools/source/contnr/imivctl1.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
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             //IAccessibility2 Implementation 2009-----
1184             CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
1185             //-----IAccessibility2 Implementation 2009
1186         }
1187     }
1188 }
1189 
1190 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1191 {
1192     StopEditTimer();
1193 
1194     sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2();
1195     sal_Unicode cChar = rKEvt.GetCharCode();
1196     sal_uLong nPos = (sal_uLong)-1;
1197     if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1198     {
1199         // shortcut is clicked
1200         SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1201         SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1202         if ( pNewCursor != pOldCursor )
1203             SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
1204         return sal_True;
1205     }
1206 
1207     if ( bMod2 )
1208         // no actions with <ALT>
1209         return sal_False;
1210 
1211     sal_Bool bKeyUsed = sal_True;
1212     sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1213     sal_Bool bShift = rKEvt.GetKeyCode().IsShift();
1214 
1215     if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1216     {
1217         bShift = sal_False;
1218         bMod1 = sal_False;
1219     }
1220 
1221     if( bMod1 )
1222         nFlags |= F_ADD_MODE;
1223     sal_Bool bDeselectAll = sal_False;
1224     if( eSelectionMode != SINGLE_SELECTION )
1225     {
1226         if( !bMod1 && !bShift )
1227             bDeselectAll = sal_True;
1228         if( bShift && !bMod1 && !pAnchor )
1229             bDeselectAll = sal_True;
1230     }
1231 
1232     SvxIconChoiceCtrlEntry* pNewCursor;
1233     SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1234 
1235     sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1236     switch( nCode )
1237     {
1238         case KEY_UP:
1239         case KEY_PAGEUP:
1240             if( pCursor )
1241             {
1242                 MakeEntryVisible( pCursor );
1243                 if( nCode == KEY_UP )
1244                     pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1245                 else
1246                     pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False);
1247                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1248                 if( !pNewCursor )
1249                 {
1250                     Rectangle aRect( GetEntryBoundRect( pCursor ) );
1251                     if( aRect.Top())
1252                     {
1253                         aRect.Bottom() -= aRect.Top();
1254                         aRect.Top() = 0;
1255                         MakeVisible( aRect );
1256                     }
1257                 }
1258 
1259                 if ( bChooseWithCursor && pNewCursor != NULL )
1260                 {
1261                     pHdlEntry = pNewCursor;//GetCurEntry();
1262                     pCurHighlightFrame = pHdlEntry;
1263                     pView->ClickIcon();
1264                     pCurHighlightFrame = NULL;
1265                 }
1266             }
1267             break;
1268 
1269         case KEY_DOWN:
1270         case KEY_PAGEDOWN:
1271             if( pCursor )
1272             {
1273                 if( nCode == KEY_DOWN )
1274                     pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1275                 else
1276                     pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True );
1277                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1278 
1279                 if ( bChooseWithCursor && pNewCursor != NULL)
1280                 {
1281                     pHdlEntry = pNewCursor;//GetCurEntry();
1282                     pCurHighlightFrame = pHdlEntry;
1283                     pView->ClickIcon();
1284                     pCurHighlightFrame = NULL;
1285                 }
1286             }
1287             break;
1288 
1289         case KEY_RIGHT:
1290             if( pCursor )
1291             {
1292                 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1293                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1294             }
1295             break;
1296 
1297         case KEY_LEFT:
1298             if( pCursor )
1299             {
1300                 MakeEntryVisible( pCursor );
1301                 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1302                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1303                 if( !pNewCursor )
1304                 {
1305                     Rectangle aRect( GetEntryBoundRect(pCursor));
1306                     if( aRect.Left() )
1307                     {
1308                         aRect.Right() -= aRect.Left();
1309                         aRect.Left() = 0;
1310                         MakeVisible( aRect );
1311                     }
1312                 }
1313             }
1314             break;
1315 
1316 // wird vom VCL-Tracking gesteuert
1317 #if 0
1318         case KEY_ESCAPE:
1319             if( pView->IsTracking() )
1320             {
1321                 HideSelectionRect();
1322                 //SelectAll( sal_False );
1323                 SetNoSelection();
1324                 ClearSelectedRectList();
1325                 nFlags &= ~F_TRACKING;
1326             }
1327             else
1328                 bKeyUsed = sal_False;
1329             break;
1330 #endif
1331 
1332 
1333         case KEY_F2:
1334             if( !bMod1 && !bShift )
1335                 EditTimeoutHdl( 0 );
1336             else
1337                 bKeyUsed = sal_False;
1338             break;
1339 
1340         case KEY_F8:
1341             if( rKEvt.GetKeyCode().IsShift() )
1342             {
1343                 if( nFlags & F_ADD_MODE )
1344                     nFlags &= (~F_ADD_MODE);
1345                 else
1346                     nFlags |= F_ADD_MODE;
1347             }
1348             else
1349                 bKeyUsed = sal_False;
1350             break;
1351 
1352         case KEY_SPACE:
1353             if( pCursor && eSelectionMode != SINGLE_SELECTION )
1354             {
1355                 if( !bMod1 )
1356                 {
1357                     //SelectAll( sal_False );
1358                     SetNoSelection();
1359                     ClearSelectedRectList();
1360 
1361                     // click Icon with spacebar
1362                     SetEntryHighlightFrame( GetCurEntry(), sal_True );
1363                     pView->ClickIcon();
1364                     pHdlEntry = pCurHighlightFrame;
1365                     pCurHighlightFrame=0;
1366                 }
1367                 else
1368                     ToggleSelection( pCursor );
1369             }
1370             break;
1371 
1372 #ifdef DBG_UTIL
1373         case KEY_F10:
1374             if( rKEvt.GetKeyCode().IsShift() )
1375             {
1376                 if( pCursor )
1377                     pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1378             }
1379             if( rKEvt.GetKeyCode().IsMod1() )
1380             {
1381                 if( pCursor )
1382                     pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1383             }
1384             break;
1385 #endif
1386 
1387         case KEY_ADD:
1388         case KEY_DIVIDE :
1389         case KEY_A:
1390             if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1391                 SelectAll( sal_True );
1392             else
1393                 bKeyUsed = sal_False;
1394             break;
1395 
1396         case KEY_SUBTRACT:
1397         case KEY_COMMA :
1398             if( bMod1 )
1399                 SetNoSelection();
1400             else
1401                 bKeyUsed = sal_False;
1402             break;
1403 
1404         case KEY_RETURN:
1405             if( bMod1 )
1406             {
1407                 if( pCursor && bEntryEditingEnabled )
1408                     /*pView->*/EditEntry( pCursor );
1409             }
1410             else
1411                 bKeyUsed = sal_False;
1412             break;
1413 
1414         case KEY_END:
1415             if( pCursor )
1416             {
1417                 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 );
1418                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1419             }
1420             break;
1421 
1422         case KEY_HOME:
1423             if( pCursor )
1424             {
1425                 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
1426                 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1427             }
1428             break;
1429 
1430         default:
1431             bKeyUsed = sal_False;
1432 
1433     }
1434     return bKeyUsed;
1435 }
1436 
1437 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
1438 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1439 {
1440     // hor scrollbar
1441     Point aPos( 0, nRealHeight );
1442     aPos.Y() -= nHorSBarHeight;
1443 
1444     if( aHorSBar.GetPosPixel() != aPos )
1445         aHorSBar.SetPosPixel( aPos );
1446 
1447     // ver scrollbar
1448     aPos.X() = nRealWidth; aPos.Y() = 0;
1449     aPos.X() -= nVerSBarWidth;
1450     aPos.X()++;
1451     aPos.Y()--;
1452 
1453     if( aVerSBar.GetPosPixel() != aPos )
1454         aVerSBar.SetPosPixel( aPos );
1455 }
1456 
1457 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool )
1458 {
1459     Rectangle aOldOutRect( GetOutputRect() );
1460     long nVirtHeight = aVirtOutputSize.Height();
1461     long nVirtWidth = aVirtOutputSize.Width();
1462 
1463     Size aOSize( pView->Control::GetOutputSizePixel() );
1464     long nRealHeight = aOSize.Height();
1465     long nRealWidth = aOSize.Width();
1466 
1467     PositionScrollBars( nRealWidth, nRealHeight );
1468 
1469     const MapMode& rMapMode = pView->GetMapMode();
1470     Point aOrigin( rMapMode.GetOrigin() );
1471 
1472     long nVisibleWidth;
1473     if( nRealWidth > nVirtWidth )
1474         nVisibleWidth = nVirtWidth + aOrigin.X();
1475     else
1476         nVisibleWidth = nRealWidth;
1477 
1478     long nVisibleHeight;
1479     if( nRealHeight > nVirtHeight )
1480         nVisibleHeight = nVirtHeight + aOrigin.Y();
1481     else
1482         nVisibleHeight = nRealHeight;
1483 
1484     sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1485     sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1486     sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1487     sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1488 
1489     sal_uInt16 nResult = 0;
1490     if( nVirtHeight )
1491     {
1492         // activate ver scrollbar ?
1493         if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1494         {
1495             nResult = 0x0001;
1496             nRealWidth -= nVerSBarWidth;
1497 
1498             if( nRealWidth > nVirtWidth )
1499                 nVisibleWidth = nVirtWidth + aOrigin.X();
1500             else
1501                 nVisibleWidth = nRealWidth;
1502 
1503             nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1504         }
1505         // activate hor scrollbar ?
1506         if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1507         {
1508             nResult |= 0x0002;
1509             nRealHeight -= nHorSBarHeight;
1510 
1511             if( nRealHeight > nVirtHeight )
1512                 nVisibleHeight = nVirtHeight + aOrigin.Y();
1513             else
1514                 nVisibleHeight = nRealHeight;
1515 
1516             // brauchen wir jetzt doch eine senkrechte Scrollbar ?
1517             if( !(nResult & 0x0001) &&  // nur wenn nicht schon da
1518                 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1519             {
1520                 nResult = 3; // beide sind an
1521                 nRealWidth -= nVerSBarWidth;
1522 
1523                 if( nRealWidth > nVirtWidth )
1524                     nVisibleWidth = nVirtWidth + aOrigin.X();
1525                 else
1526                     nVisibleWidth = nRealWidth;
1527 
1528                 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1529             }
1530         }
1531     }
1532 
1533     // size ver scrollbar
1534     long nThumb = aVerSBar.GetThumbPos();
1535     Size aSize( nVerSBarWidth, nRealHeight );
1536     aSize.Height() += 2;
1537     if( aSize != aVerSBar.GetSizePixel() )
1538         aVerSBar.SetSizePixel( aSize );
1539     aVerSBar.SetVisibleSize( nVisibleHeight );
1540     aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1541 
1542     if( nResult & 0x0001 )
1543     {
1544         aVerSBar.SetThumbPos( nThumb );
1545         aVerSBar.Show();
1546     }
1547     else
1548     {
1549         aVerSBar.SetThumbPos( 0 );
1550         aVerSBar.Hide();
1551     }
1552 
1553     // size hor scrollbar
1554     nThumb = aHorSBar.GetThumbPos();
1555     aSize.Width() = nRealWidth;
1556     aSize.Height() = nHorSBarHeight;
1557     aSize.Width()++;
1558     if( nResult & 0x0001 ) // vertikale Scrollbar ?
1559     {
1560         aSize.Width()++;
1561         nRealWidth++;
1562     }
1563     if( aSize != aHorSBar.GetSizePixel() )
1564         aHorSBar.SetSizePixel( aSize );
1565     aHorSBar.SetVisibleSize( nVisibleWidth );
1566     aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1567     if( nResult & 0x0002 )
1568     {
1569         aHorSBar.SetThumbPos( nThumb );
1570         aHorSBar.Show();
1571     }
1572     else
1573     {
1574         aHorSBar.SetThumbPos( 0 );
1575         aHorSBar.Hide();
1576     }
1577 
1578     aOutputSize.Width() = nRealWidth;
1579     if( nResult & 0x0002 ) // hor scrollbar ?
1580         nRealHeight++; // weil unterer Rand geclippt wird
1581     aOutputSize.Height() = nRealHeight;
1582 
1583     Rectangle aNewOutRect( GetOutputRect() );
1584     if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1585     {
1586         Wallpaper aPaper( pView->GetBackground() );
1587         aPaper.SetRect( aNewOutRect );
1588         pView->SetBackground( aPaper );
1589     }
1590 
1591     if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1592         aScrBarBox.Show();
1593     else
1594         aScrBarBox.Hide();
1595 }
1596 
1597 void SvxIconChoiceCtrl_Impl::Resize()
1598 {
1599     StopEditTimer();
1600     InitScrollBarBox();
1601     aOutputSize = pView->GetOutputSizePixel();
1602     pImpCursor->Clear();
1603     pGridMap->OutputSizeChanged();
1604 
1605     const Size& rSize = pView->Control::GetOutputSizePixel();
1606     PositionScrollBars( rSize.Width(), rSize.Height() );
1607     // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1608     // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1609     // die ScrollBars aufblitzen
1610     // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden,
1611     // zumindest, solange es nur einen EventTypen gibt
1612     if ( ! nUserEventAdjustScrBars )
1613         nUserEventAdjustScrBars =
1614             Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1615                 EVENTID_ADJUST_SCROLLBARS);
1616 
1617     if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1618     {
1619         Rectangle aRect( GetOutputRect());
1620         Wallpaper aPaper( pView->GetBackground() );
1621         aPaper.SetRect( aRect );
1622         pView->SetBackground( aPaper );
1623     }
1624     VisRectChanged();
1625 }
1626 
1627 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1628 {
1629     if( !pZOrderList || !aHorSBar.IsVisible() )
1630         return sal_False;
1631     const MapMode& rMapMode = pView->GetMapMode();
1632     Point aOrigin( rMapMode.GetOrigin() );
1633     if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1634     {
1635         long nWidth = aOutputSize.Width();
1636         const sal_uLong nCount = pZOrderList->Count();
1637         long nMostRight = 0;
1638         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1639         {
1640             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1641             long nRight = GetEntryBoundRect(pEntry).Right();
1642             if( nRight > nWidth )
1643                 return sal_False;
1644             if( nRight > nMostRight )
1645                 nMostRight = nRight;
1646         }
1647         aHorSBar.Hide();
1648         aOutputSize.Height() += nHorSBarHeight;
1649         aVirtOutputSize.Width() = nMostRight;
1650         aHorSBar.SetThumbPos( 0 );
1651         Range aRange;
1652         aRange.Max() = nMostRight - 1;
1653         aHorSBar.SetRange( aRange  );
1654         if( aVerSBar.IsVisible() )
1655         {
1656             Size aSize( aVerSBar.GetSizePixel());
1657             aSize.Height() += nHorSBarHeight;
1658             aVerSBar.SetSizePixel( aSize );
1659         }
1660         return sal_True;
1661     }
1662     return sal_False;
1663 }
1664 
1665 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1666 {
1667     if( !pZOrderList || !aVerSBar.IsVisible() )
1668         return sal_False;
1669     const MapMode& rMapMode = pView->GetMapMode();
1670     Point aOrigin( rMapMode.GetOrigin() );
1671     if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1672     {
1673         long nDeepest = 0;
1674         long nHeight = aOutputSize.Height();
1675         const sal_uLong nCount = pZOrderList->Count();
1676         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1677         {
1678             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1679             long nBottom = GetEntryBoundRect(pEntry).Bottom();
1680             if( nBottom > nHeight )
1681                 return sal_False;
1682             if( nBottom > nDeepest )
1683                 nDeepest = nBottom;
1684         }
1685         aVerSBar.Hide();
1686         aOutputSize.Width() += nVerSBarWidth;
1687         aVirtOutputSize.Height() = nDeepest;
1688         aVerSBar.SetThumbPos( 0 );
1689         Range aRange;
1690         aRange.Max() = nDeepest - 1;
1691         aVerSBar.SetRange( aRange  );
1692         if( aHorSBar.IsVisible() )
1693         {
1694             Size aSize( aHorSBar.GetSizePixel());
1695             aSize.Width() += nVerSBarWidth;
1696             aHorSBar.SetSizePixel( aSize );
1697         }
1698         return sal_True;
1699     }
1700     return sal_False;
1701 }
1702 
1703 
1704 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1705 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1706 {
1707     CheckVerScrollBar();
1708     if( CheckHorScrollBar() )
1709         CheckVerScrollBar();
1710     if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1711         aScrBarBox.Show();
1712     else
1713         aScrBarBox.Hide();
1714 }
1715 
1716 
1717 void SvxIconChoiceCtrl_Impl::GetFocus()
1718 {
1719     RepaintEntries( ICNVIEW_FLAG_SELECTED );
1720     if( pCursor )
1721     {
1722         pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1723         ShowCursor( sal_True );
1724     }
1725 }
1726 
1727 void SvxIconChoiceCtrl_Impl::LoseFocus()
1728 {
1729     StopEditTimer();
1730     if( pCursor )
1731         pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1732     ShowCursor( sal_False );
1733 
1734 //  HideFocus ();
1735 //  pView->Invalidate ( aFocus.aRect );
1736 
1737     RepaintEntries( ICNVIEW_FLAG_SELECTED );
1738 }
1739 
1740 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate )
1741 {
1742     if( bUpdate != bUpdateMode )
1743     {
1744         bUpdateMode = bUpdate;
1745         if( bUpdate )
1746         {
1747             AdjustScrollBars();
1748             pImpCursor->Clear();
1749             pGridMap->Clear();
1750             pView->Invalidate(INVALIDATE_NOCHILDREN);
1751         }
1752     }
1753 }
1754 
1755 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted )
1756 {
1757     Point aPos( GetEntryPos( pEntry ) );
1758     PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1759 }
1760 
1761 // Prios der Emphasis:  bDropTarget => bCursored => bSelected
1762 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1763     const Rectangle& rTextRect, const Rectangle& rImageRect,
1764     sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut,
1765     sal_Bool bIsBackgroundPainted )
1766 {
1767     static Color aTransparent( COL_TRANSPARENT );
1768 
1769     if( !pOut )
1770         pOut = pView;
1771 
1772 #ifdef OV_CHECK_EMPH_RECTS
1773     {
1774         Color aXOld( pOut->GetFillColor() );
1775         pOut->SetFillColor( Color( COL_GREEN ));
1776         pOut->DrawRect( rTextRect );
1777         pOut->DrawRect( rImageRect );
1778         pOut->SetFillColor( aXOld );
1779     }
1780 #endif
1781 
1782     const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1783     Color aOldFillColor( pOut->GetFillColor() );
1784 
1785     sal_Bool bSolidTextRect = sal_False;
1786     sal_Bool bSolidImageRect = sal_False;
1787 
1788     if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1789     {
1790         pOut->SetFillColor( rSettings.GetHighlightColor() );
1791         bSolidTextRect = sal_True;
1792         bSolidImageRect = sal_True;
1793     }
1794     else
1795     {
1796         if ( !bSelected || bCursored )
1797         {
1798             if( !pView->HasFontFillColor() )
1799                 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1800             else
1801             {
1802                 const Color& rFillColor = pView->GetFont().GetFillColor();
1803                 pOut->SetFillColor( rFillColor );
1804                 if( rFillColor != aTransparent )
1805                     bSolidTextRect = sal_True;
1806             }
1807         }
1808     }
1809 
1810     // Textrechteck zeichnen
1811     if( !bSolidTextRect )
1812     {
1813         if( !bIsBackgroundPainted )
1814             pOut->Erase( rTextRect );
1815     }
1816     else
1817     {
1818         Color aOldLineColor;
1819         if( bCursored )
1820         {
1821             aOldLineColor = pOut->GetLineColor();
1822             pOut->SetLineColor( Color( COL_GRAY ) );
1823         }
1824         pOut->DrawRect( rTextRect );
1825         if( bCursored )
1826             pOut->SetLineColor( aOldLineColor );
1827     }
1828 
1829     // Bildrechteck zeichnen
1830     if( !bSolidImageRect )
1831     {
1832         if( !bIsBackgroundPainted )
1833             pOut->Erase( rImageRect );
1834     }
1835 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden
1836 // (in der virtuellen Funktion DrawEntryImage)
1837 //  else
1838 //      pOut->DrawRect( rImageRect );
1839 
1840     pOut->SetFillColor( aOldFillColor );
1841 }
1842 
1843 
1844 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1845     IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1846     OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1847 {
1848     if( eItem == IcnViewFieldTypeText )
1849     {
1850         String aText;
1851         if( !pStr )
1852             aText = pView->GetEntryText( pEntry, sal_False );
1853         else
1854             aText = *pStr;
1855 
1856         if ( _pLayoutData )
1857         {
1858             pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1859                 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1860         }
1861         else
1862         {
1863             Color aOldFontColor = pOut->GetTextColor();
1864             if ( pView->AutoFontColor() )
1865             {
1866                 Color aBkgColor( pOut->GetBackground().GetColor() );
1867                 Color aFontColor;
1868                 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1869                 if ( nColor > 127 )
1870                     aFontColor.SetColor ( COL_BLACK );
1871                 else
1872                     aFontColor.SetColor( COL_WHITE );
1873                 pOut->SetTextColor( aFontColor );
1874             }
1875 
1876             pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1877 
1878             if ( pView->AutoFontColor() )
1879                 pOut->SetTextColor( aOldFontColor );
1880 
1881             if( pEntry->IsFocused() )
1882             {
1883                 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1884                 /*pView->*/ShowFocus( aRect );
1885                 DrawFocusRect( pOut );
1886             }
1887         }
1888     }
1889     else
1890     {
1891         Point aPos( rRect.TopLeft() );
1892         if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1893             aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1894         if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1895             aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1896         pView->DrawEntryImage( pEntry, aPos, *pOut );
1897     }
1898 }
1899 
1900 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1901 {
1902 #ifdef OV_NO_VIRT_OUTDEV
1903     PaintEntry( pEntry );
1904 #else
1905     if( !pEntryPaintDev )
1906     {
1907         pEntryPaintDev = new VirtualDevice( *pView );
1908         pEntryPaintDev->SetFont( pView->GetFont() );
1909         pEntryPaintDev->SetLineColor();
1910         //pEntryPaintDev->SetBackground( pView->GetBackground() );
1911     }
1912     const Rectangle& rRect = GetEntryBoundRect( pEntry );
1913     Rectangle aOutRect( GetOutputRect() );
1914     if( !rRect.IsOver( aOutRect ) )
1915         return;
1916     Wallpaper aPaper( pView->GetBackground() );
1917     Rectangle aRect( aPaper.GetRect() );
1918 
1919     // Rechteck verschieben, so dass das Boundrect des Entries im
1920     // VirtOut-Dev bei 0,0 liegt.
1921     aRect.Move( -rRect.Left(), -rRect.Top() );
1922     aPaper.SetRect( aRect );
1923     pEntryPaintDev->SetBackground( aPaper );
1924     pEntryPaintDev->SetFont( pView->GetFont() );
1925     Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) );
1926 
1927 
1928     Size aSize( rRect.GetSize() );
1929     pEntryPaintDev->SetOutputSizePixel( aSize );
1930     pEntryPaintDev->DrawOutDev(
1931         Point(), aSize, rRect.TopLeft(), aSize, *pView );
1932 
1933     PaintEntry( pEntry, Point(), pEntryPaintDev );
1934 
1935     pView->DrawOutDev(
1936         rRect.TopLeft(),
1937         aSize,
1938         Point(),
1939         aSize,
1940         *pEntryPaintDev );
1941 #endif
1942 }
1943 
1944 
1945 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1946     OutputDevice* pOut, sal_Bool bIsBackgroundPainted )
1947 {
1948     if( !pOut )
1949         pOut = pView;
1950 
1951     sal_Bool bSelected = sal_False;
1952 
1953     if( eSelectionMode != NO_SELECTION )
1954         bSelected = pEntry->IsSelected();
1955 
1956     sal_Bool bCursored = pEntry->IsCursored();
1957     sal_Bool bDropTarget = pEntry->IsDropTarget();
1958     sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1959 
1960     Font aTempFont( pOut->GetFont() );
1961 
1962     // AutoFontColor
1963     /*
1964     if ( pView->AutoFontColor() )
1965     {
1966         aTempFont.SetColor ( aFontColor );
1967     }
1968     */
1969 
1970     String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
1971     Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText));
1972     Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1973 
1974     sal_Bool    bShowSelection =
1975         (   (   ( bSelected && !bCursored )
1976             ||  bDropTarget
1977             )
1978         &&  !bNoEmphasis
1979         &&  ( eSelectionMode != NO_SELECTION )
1980         );
1981     sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1982 
1983     if ( bShowSelection )
1984     {
1985         const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1986         Font aNewFont( aTempFont );
1987 
1988         // bei hart attributierter Font-Fuellcolor muessen wir diese
1989         // hart auf die Highlight-Color setzen
1990         if( pView->HasFontFillColor() )
1991         {
1992             if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1993                 aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1994             else
1995                 aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
1996         }
1997 
1998         Color aWinCol = rSettings.GetWindowTextColor();
1999         if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
2000             aNewFont.SetColor( rSettings.GetWindowTextColor() );
2001         else
2002             aNewFont.SetColor( rSettings.GetHighlightTextColor() );
2003 
2004         pOut->SetFont( aNewFont );
2005 
2006         pOut->SetFillColor( pOut->GetBackground().GetColor() );
2007         pOut->DrawRect( CalcFocusRect( pEntry ) );
2008         pOut->SetFillColor( );
2009     }
2010 
2011     sal_Bool bResetClipRegion = sal_False;
2012     if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
2013     {
2014         Rectangle aOutputArea( GetOutputRect() );
2015         if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
2016         {
2017             pView->SetClipRegion( aOutputArea );
2018             bResetClipRegion = sal_True;
2019         }
2020     }
2021 
2022 #ifdef OV_DRAWBOUNDRECT
2023     {
2024         Color aXOldColor = pOut->GetLineColor();
2025         pOut->SetLineColor( Color( COL_LIGHTRED ) );
2026         Rectangle aXRect( pEntry->aRect );
2027         aXRect.SetPos( rPos );
2028         pOut->DrawRect( aXRect );
2029         pOut->SetLineColor( aXOldColor );
2030     }
2031 #endif
2032 
2033     sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
2034     sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
2035     if ( bLargeIconMode )
2036         nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
2037     sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
2038 
2039     if( !bNoEmphasis )
2040         PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
2041 
2042     if ( bShowSelection )
2043         pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
2044         bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
2045 
2046     PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
2047 
2048     PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
2049         nTextPaintFlags, pOut );
2050 
2051     // Highlight-Frame zeichnen
2052     if( pEntry == pCurHighlightFrame && !bNoEmphasis )
2053         DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False );
2054 
2055     pOut->SetFont( aTempFont );
2056     if( bResetClipRegion )
2057         pView->SetClipRegion();
2058 }
2059 
2060 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2061     sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap )
2062 {
2063     ShowCursor( sal_False );
2064     Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
2065     pView->Invalidate( aBoundRect );
2066     ToTop( pEntry );
2067     if( !IsAutoArrange() )
2068     {
2069         sal_Bool bAdjustVirtSize = sal_False;
2070         if( rPos != aBoundRect.TopLeft() )
2071         {
2072             Point aGridOffs(
2073                 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
2074             pImpCursor->Clear();
2075             if( !bKeepGridMap )
2076                 pGridMap->Clear();
2077             aBoundRect.SetPos( rPos );
2078             pEntry->aRect = aBoundRect;
2079             pEntry->aGridRect.SetPos( rPos + aGridOffs );
2080             bAdjustVirtSize = sal_True;
2081         }
2082         if( bAdjustAtGrid )
2083         {
2084             if( bAdjustVirtSize )
2085             {
2086                 // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags,
2087                 // kann er wieder komplett
2088                 // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar
2089                 // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der
2090                 // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen
2091                 // Ausgabegroesse bereits das ausgerichtete Boundrect des
2092                 // Eintrags genommen. Die virtuelle Groesse muss angepasst werden,
2093                 // da AdjustEntryAtGrid von ihr abhaengt.
2094                 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
2095                 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
2096                 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
2097                 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
2098                 AdjustVirtSize( aNewBoundRect );
2099                 bAdjustVirtSize = sal_False;
2100             }
2101             AdjustEntryAtGrid( pEntry );
2102             ToTop( pEntry );
2103         }
2104         if( bAdjustVirtSize )
2105             AdjustVirtSize( pEntry->aRect );
2106 
2107         if( bCheckScrollBars && bUpdateMode )
2108             CheckScrollBars();
2109 
2110         pView->Invalidate( pEntry->aRect );
2111         pGridMap->OccupyGrids( pEntry );
2112     }
2113     else
2114     {
2115         SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
2116         SetEntryPredecessor( pEntry, pPrev );
2117         aAutoArrangeTimer.Start();
2118     }
2119     ShowCursor( sal_True );
2120 }
2121 
2122 void SvxIconChoiceCtrl_Impl::SetNoSelection()
2123 {
2124     // rekursive Aufrufe ueber SelectEntry abblocken
2125     if( !(nFlags & F_CLEARING_SELECTION ))
2126     {
2127         nFlags |= F_CLEARING_SELECTION;
2128         DeselectAllBut( 0, sal_True );
2129         nFlags &= ~F_CLEARING_SELECTION;
2130     }
2131 }
2132 
2133 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit )
2134 {
2135     CheckBoundingRects();
2136     // Z-Order-Liste vom Ende her absuchen
2137     sal_uLong nCount = pZOrderList->Count();
2138     while( nCount )
2139     {
2140         nCount--;
2141         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount));
2142         if( pEntry->aRect.IsInside( rDocPos ) )
2143         {
2144             if( bHit )
2145             {
2146                 Rectangle aRect = CalcBmpRect( pEntry );
2147                 aRect.Top() -= 3;
2148                 aRect.Bottom() += 3;
2149                 aRect.Left() -= 3;
2150                 aRect.Right() += 3;
2151                 if( aRect.IsInside( rDocPos ) )
2152                     return pEntry;
2153                 aRect = CalcTextRect( pEntry );
2154                 if( aRect.IsInside( rDocPos ) )
2155                     return pEntry;
2156             }
2157             else
2158                 return pEntry;
2159         }
2160     }
2161     return 0;
2162 }
2163 
2164 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2165 {
2166     CheckBoundingRects();
2167     SvxIconChoiceCtrlEntry* pTarget = 0;
2168     const sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2169     if( nStartPos != LIST_ENTRY_NOTFOUND )
2170     {
2171         const sal_uLong nCount = pZOrderList->Count();
2172         for( sal_uLong nCur = nStartPos+1; nCur < nCount; nCur++ )
2173         {
2174             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
2175             if( pEntry->aRect.IsInside( rDocPos ) )
2176             {
2177                 pTarget = pEntry;
2178                 break;
2179             }
2180         }
2181     }
2182     return pTarget;
2183 }
2184 
2185 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2186 {
2187     CheckBoundingRects();
2188     SvxIconChoiceCtrlEntry* pTarget = 0;
2189     sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2190     if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 )
2191     {
2192         nStartPos--;
2193         do
2194         {
2195             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos));
2196             if( pEntry->aRect.IsInside( rDocPos ) )
2197             {
2198                 pTarget = pEntry;
2199                 break;
2200             }
2201         } while( nStartPos > 0 );
2202     }
2203     return pTarget;
2204 }
2205 
2206 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
2207 {
2208     return pEntry->aRect.TopLeft();
2209 }
2210 
2211 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound )
2212 {
2213     if ( bBound )
2214     {
2215         const Rectangle& rRect = GetEntryBoundRect( pEntry );
2216         MakeVisible( rRect );
2217     }
2218     else
2219     {
2220         Rectangle aRect = CalcBmpRect( pEntry );
2221         aRect.Union( CalcTextRect( pEntry ) );
2222         aRect.Top() += TBOFFS_BOUND;
2223         aRect.Bottom() += TBOFFS_BOUND;
2224         aRect.Left() += LROFFS_BOUND;
2225         aRect.Right() += LROFFS_BOUND;
2226         MakeVisible( aRect );
2227     }
2228 }
2229 
2230 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2231 {
2232     if( !IsBoundingRectValid( pEntry->aRect ))
2233         FindBoundingRect( pEntry );
2234     return pEntry->aRect;
2235 }
2236 
2237 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2238 {
2239     Rectangle aBound = GetEntryBoundRect( pEntry );
2240     if( pPos )
2241         aBound.SetPos( *pPos );
2242     Point aPos( aBound.TopLeft() );
2243 
2244     switch( nWinBits & (VIEWMODE_MASK) )
2245     {
2246         case WB_ICON:
2247         {
2248             aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2249             return Rectangle( aPos, aImageSize );
2250         }
2251 
2252         case WB_SMALLICON:
2253         case WB_DETAILS:
2254             aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2255             //todo: hor. Abstand zum BoundRect?
2256             return Rectangle( aPos, aImageSize );
2257 
2258         default:
2259             DBG_ERROR("IconView: Viewmode not set");
2260             return aBound;
2261     }
2262 }
2263 
2264 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2265     const Point* pEntryPos, sal_Bool bEdit, const String* pStr )
2266 {
2267     String aEntryText;
2268     if( !pStr )
2269         aEntryText = pView->GetEntryText( pEntry, bEdit );
2270     else
2271         aEntryText = *pStr;
2272 
2273     const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2274     Rectangle aBound( GetEntryBoundRect( pEntry ) );
2275     if( pEntryPos )
2276         aBound.SetPos( *pEntryPos );
2277 
2278     Rectangle aTextRect( aMaxTextRect );
2279     if( !bEdit )
2280         aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2281 
2282     Size aTextSize( aTextRect.GetSize() );
2283 
2284     Point aPos( aBound.TopLeft() );
2285     long nBoundWidth = aBound.GetWidth();
2286     long nBoundHeight = aBound.GetHeight();
2287 
2288     switch( nWinBits & (VIEWMODE_MASK) )
2289     {
2290         case WB_ICON:
2291             aPos.Y() += aImageSize.Height();
2292             aPos.Y() += VER_DIST_BMP_STRING;
2293             // beim Editieren etwas mehr Platz
2294             if( bEdit )
2295             {
2296                 // 20% rauf
2297                 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2298                                  aImageSize.Width();
2299                 if( nMinWidth > nBoundWidth )
2300                     nMinWidth = nBoundWidth;
2301 
2302                 if( aTextSize.Width() < nMinWidth )
2303                     aTextSize.Width() = nMinWidth;
2304 
2305                 // beim Editieren ist Ueberlappung nach unten erlaubt
2306                 Size aOptSize = aMaxTextRect.GetSize();
2307                 if( aOptSize.Height() > aTextSize.Height() )
2308                     aTextSize.Height() = aOptSize.Height();
2309             }
2310             aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2311             break;
2312 
2313         case WB_SMALLICON:
2314         case WB_DETAILS:
2315             aPos.X() += aImageSize.Width();
2316             aPos.X() += HOR_DIST_BMP_STRING;
2317             aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2318             break;
2319     }
2320     return Rectangle( aPos, aTextSize );
2321 }
2322 
2323 
2324 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2325 {
2326     long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2327 //  nStringWidth += 2*LROFFS_TEXT;
2328     long nWidth = 0;
2329 
2330     switch( nWinBits & (VIEWMODE_MASK) )
2331     {
2332         case WB_ICON:
2333             nWidth = Max( nStringWidth, aImageSize.Width() );
2334             break;
2335 
2336         case WB_SMALLICON:
2337         case WB_DETAILS:
2338             nWidth = aImageSize.Width();
2339             nWidth += HOR_DIST_BMP_STRING;
2340             nWidth += nStringWidth;
2341             break;
2342     }
2343     return nWidth;
2344 }
2345 
2346 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2347 {
2348     long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2349     long nHeight = 0;
2350 
2351     switch( nWinBits & (VIEWMODE_MASK) )
2352     {
2353         case WB_ICON:
2354             nHeight = aImageSize.Height();
2355             nHeight += VER_DIST_BMP_STRING;
2356             nHeight += nStringHeight;
2357             break;
2358 
2359         case WB_SMALLICON:
2360         case WB_DETAILS:
2361             nHeight = Max( aImageSize.Height(), nStringHeight );
2362             break;
2363     }
2364     if( nHeight > nMaxBoundHeight )
2365     {
2366         ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2367         ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2368         ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2369     }
2370     return nHeight;
2371 }
2372 
2373 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2374 {
2375     return Size( CalcBoundingWidth( pEntry ),
2376                  CalcBoundingHeight( pEntry ) );
2377 }
2378 
2379 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects()
2380 {
2381     nMaxBoundHeight = 0;
2382     pZOrderList->Clear();
2383     sal_uLong nCount = aEntries.Count();
2384     sal_uLong nCur;
2385     SvxIconChoiceCtrlEntry* pEntry;
2386 
2387     if( !IsAutoArrange() || !pHead )
2388     {
2389         for( nCur = 0; nCur < nCount; nCur++ )
2390         {
2391             pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2392             FindBoundingRect( pEntry );
2393             pZOrderList->Insert( pEntry, LIST_APPEND );
2394         }
2395     }
2396     else
2397     {
2398         nCur = 0;
2399         pEntry = pHead;
2400         while( nCur != nCount )
2401         {
2402             DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2403             FindBoundingRect( pEntry );
2404             pZOrderList->Insert( pEntry, pZOrderList->Count() );
2405             pEntry = pEntry->pflink;
2406             nCur++;
2407         }
2408     }
2409     bBoundRectsDirty = sal_False;
2410     AdjustScrollBars();
2411 }
2412 
2413 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2414 {
2415     nMaxBoundHeight = 0;
2416     pZOrderList->Clear();
2417     sal_uLong nCur;
2418     SvxIconChoiceCtrlEntry* pEntry;
2419     const sal_uLong nCount = aEntries.Count();
2420 
2421     if( !IsAutoArrange() || !pHead )
2422     {
2423         for( nCur = 0; nCur < nCount; nCur++ )
2424         {
2425             pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2426             if( IsBoundingRectValid( pEntry->aRect ))
2427             {
2428                 Size aBoundSize( pEntry->aRect.GetSize() );
2429                 if( aBoundSize.Height() > nMaxBoundHeight )
2430                     nMaxBoundHeight = aBoundSize.Height();
2431             }
2432             else
2433                 FindBoundingRect( pEntry );
2434             pZOrderList->Insert( pEntry, LIST_APPEND );
2435         }
2436     }
2437     else
2438     {
2439         nCur = 0;
2440         pEntry = pHead;
2441         while( nCur != nCount )
2442         {
2443             DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2444             if( IsBoundingRectValid( pEntry->aRect ))
2445             {
2446                 Size aBoundSize( pEntry->aRect.GetSize() );
2447                 if( aBoundSize.Height() > nMaxBoundHeight )
2448                     nMaxBoundHeight = aBoundSize.Height();
2449             }
2450             else
2451                 FindBoundingRect( pEntry );
2452             pZOrderList->Insert( pEntry, LIST_APPEND );
2453             pEntry = pEntry->pflink;
2454             nCur++;
2455         }
2456     }
2457     AdjustScrollBars();
2458 }
2459 
2460 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects()
2461 {
2462     const sal_uLong nCount = aEntries.Count();
2463     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2464     {
2465         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2466         GetEntryBoundRect( pEntry );
2467     }
2468 }
2469 
2470 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2471 {
2472     DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2473     if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2474     {
2475         AdjustVirtSize( pEntry->aRect );
2476         return;
2477     }
2478     Size aSize( CalcBoundingSize( pEntry ) );
2479     Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft());
2480     SetBoundingRect_Impl( pEntry, aPos, aSize );
2481 }
2482 
2483 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2484     const Size& /*rBoundingSize*/ )
2485 {
2486     Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2487     pEntry->aGridRect = aGridRect;
2488     Center( pEntry );
2489     AdjustVirtSize( pEntry->aRect );
2490     pGridMap->OccupyGrids( pEntry );
2491 }
2492 
2493 
2494 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection,
2495     sal_Bool bShowFocusAsync )
2496 {
2497     if( pEntry == pCursor )
2498     {
2499         if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2500                 !pCursor->IsSelected() )
2501             SelectEntry( pCursor, sal_True, sal_True );
2502         return;
2503     }
2504     ShowCursor( sal_False );
2505     SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2506     pCursor = pEntry;
2507     if( pOldCursor )
2508     {
2509         pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2510         if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2511             SelectEntry( pOldCursor, sal_False, sal_True ); // alten Cursor deselektieren
2512     }
2513     if( pCursor )
2514     {
2515         ToTop( pCursor );
2516         pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2517         if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2518             SelectEntry( pCursor, sal_True, sal_True );
2519         if( !bShowFocusAsync )
2520             ShowCursor( sal_True );
2521         else
2522         {
2523             if( !nUserEventShowCursor )
2524                 nUserEventShowCursor =
2525                     Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2526                         EVENTID_SHOW_CURSOR );
2527         }
2528     }
2529 }
2530 
2531 
2532 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow )
2533 {
2534     if( !pCursor || !bShow || !pView->HasFocus() )
2535     {
2536         pView->HideFocus();
2537         return;
2538     }
2539     Rectangle aRect ( CalcFocusRect( pCursor ) );
2540     /*pView->*/ShowFocus( aRect );
2541 }
2542 
2543 
2544 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2545 {
2546     pView->Update();
2547     ImpHideDDIcon();
2548     pDDBufDev = pDDDev;
2549     pDDDev = 0;
2550 }
2551 
2552 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2553 {
2554     if( pDDDev )
2555     {
2556         Size aSize( pDDDev->GetOutputSizePixel() );
2557         // pView restaurieren
2558         pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2559     }
2560 }
2561 
2562 
2563 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2564 {
2565     pView->Update();
2566     if( pRefEntry != pDDRefEntry )
2567     {
2568         DELETEZ(pDDDev);
2569         DELETEZ(pDDBufDev);
2570     }
2571     sal_Bool bSelected = pRefEntry->IsSelected();
2572     pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED );
2573     if( !pDDDev )
2574     {
2575         if( pDDBufDev )
2576         {
2577             // nicht bei jedem Move ein Device anlegen, da dies besonders
2578             // auf Remote-Clients zu langsam ist
2579             pDDDev = pDDBufDev;
2580             pDDBufDev = 0;
2581         }
2582         else
2583         {
2584             pDDDev = new VirtualDevice( *pView );
2585             pDDDev->SetFont( pView->GetFont() );
2586         }
2587     }
2588     else
2589     {
2590         ImpHideDDIcon();
2591     }
2592     const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2593     pDDDev->SetOutputSizePixel( rRect.GetSize() );
2594 
2595     Point aPos( rPosPix );
2596     ToDocPos( aPos );
2597 
2598     Size aSize( pDDDev->GetOutputSizePixel() );
2599     pDDRefEntry = pRefEntry;
2600     aDDLastEntryPos = aPos;
2601     aDDLastRectPos = aPos;
2602 
2603     // Hintergrund sichern
2604     pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2605     // Icon in pView malen
2606     pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2607     PaintEntry( pRefEntry, aPos );
2608     pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2609     if( bSelected )
2610         pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED );
2611 }
2612 
2613 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2614 {
2615 /*  In Notfaellen folgenden flackernden Code aktivieren:
2616 
2617         HideDDIcon();
2618         ShowDDIcon( pRefEntry, rPosPix );
2619         return;
2620 */
2621     if( !pDDDev )
2622     {
2623         ShowDDIcon( pRefEntry, rPosPix );
2624         return;
2625     }
2626 
2627     if( pRefEntry != pDDRefEntry )
2628     {
2629         HideDDIcon();
2630         ShowDDIcon( pRefEntry, rPosPix );
2631         return;
2632     }
2633 
2634     Point aEmptyPoint;
2635 
2636     Point aCurEntryPos( rPosPix );
2637     ToDocPos( aCurEntryPos );
2638 
2639     const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2640     Size aEntrySize( rRect.GetSize() );
2641     Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2642     Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2643 
2644     if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2645     {
2646         HideDDIcon();
2647         ShowDDIcon( pRefEntry, rPosPix );
2648         return;
2649     }
2650 
2651     // Ueberlappung des neuen und alten D&D-Pointers!
2652 
2653     Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2654     if( !pDDTempDev )
2655     {
2656         pDDTempDev = new VirtualDevice( *pView );
2657         pDDTempDev->SetFont( pView->GetFont() );
2658     }
2659 
2660     Size aFullSize( aFullRect.GetSize() );
2661     Point aFullPos( aFullRect.TopLeft() );
2662 
2663     pDDTempDev->SetOutputSizePixel( aFullSize );
2664 
2665     // Hintergrund (mit dem alten D&D-Pointer!) sichern
2666     pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2667     // den alten Buffer in den neuen Buffer pasten
2668     aDDLastRectPos = aDDLastRectPos - aFullPos;
2669 
2670     pDDTempDev->DrawOutDev(
2671         aDDLastRectPos,
2672         pDDDev->GetOutputSizePixel(),
2673         aEmptyPoint,
2674         pDDDev->GetOutputSizePixel(),
2675         *pDDDev );
2676 
2677     // Swap
2678     VirtualDevice* pTemp = pDDDev;
2679     pDDDev = pDDTempDev;
2680     pDDTempDev = pTemp;
2681 
2682     // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2683     pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2684     pDDTempDev->DrawOutDev(
2685         aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2686     Point aRelPos = aCurEntryPos - aFullPos;
2687     pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2688     PaintEntry( pRefEntry, aRelPos, pDDTempDev );
2689     pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2690 
2691     aDDLastRectPos = aFullPos;
2692     aDDLastEntryPos = aCurEntryPos;
2693 
2694     pView->DrawOutDev(
2695         aDDLastRectPos,
2696         pDDDev->GetOutputSizePixel(),
2697         aEmptyPoint,
2698         pDDDev->GetOutputSizePixel(),
2699         *pDDTempDev );
2700 }
2701 
2702 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2703 {
2704     InvalidateBoundingRect( pEntry->aRect );
2705 }
2706 
2707 
2708 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2709 {
2710     Rectangle aDocRect( GetDocumentRect() );
2711     Rectangle aVisRect( GetVisibleRect() );
2712     if( aVisRect.IsInside( aDocRect ))
2713         return sal_False;
2714     Size aDocSize( aDocRect.GetSize() );
2715     Size aVisSize( aVisRect.GetSize() );
2716     sal_Bool bHor = aDocSize.Width() > aVisSize.Width();
2717     sal_Bool bVer = aDocSize.Height() > aVisSize.Height();
2718 
2719     long nScrollDX = 0, nScrollDY = 0;
2720 
2721     switch( rCmd.GetCommand() )
2722     {
2723         case COMMAND_STARTAUTOSCROLL:
2724         {
2725             pView->EndTracking();
2726             sal_uInt16 nScrollFlags = 0;
2727             if( bHor )
2728                 nScrollFlags |= AUTOSCROLL_HORZ;
2729             if( bVer )
2730                 nScrollFlags |= AUTOSCROLL_VERT;
2731             if( nScrollFlags )
2732             {
2733                 pView->StartAutoScroll( nScrollFlags );
2734                 return sal_True;
2735             }
2736         }
2737         break;
2738 
2739         case COMMAND_WHEEL:
2740         {
2741             const CommandWheelData* pData = rCmd.GetWheelData();
2742             if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2743             {
2744                 sal_uLong nScrollLines = pData->GetScrollLines();
2745                 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2746                 {
2747                     nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2748                     if( pData->GetDelta() < 0 )
2749                         nScrollDY *= -1;
2750                 }
2751                 else
2752                 {
2753                     nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2754                     nScrollDY *= GetScrollBarLineSize();
2755                 }
2756             }
2757         }
2758         break;
2759 
2760         case COMMAND_AUTOSCROLL:
2761         {
2762             const CommandScrollData* pData = rCmd.GetAutoScrollData();
2763             if( pData )
2764             {
2765                 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2766                 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2767             }
2768         }
2769         break;
2770     }
2771 
2772     if( nScrollDX || nScrollDY )
2773     {
2774         aVisRect.Top() -= nScrollDY;
2775         aVisRect.Bottom() -= nScrollDY;
2776         aVisRect.Left() -= nScrollDX;
2777         aVisRect.Right() -= nScrollDX;
2778         MakeVisible( aVisRect );
2779         return sal_True;
2780     }
2781     return sal_False;
2782 }
2783 
2784 
2785 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2786 {
2787     // Rollmaus-Event?
2788     if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2789         (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2790         (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2791     {
2792 #if 1
2793         if( HandleScrollCommand( rCEvt ) )
2794             return;
2795 #else
2796         ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0;
2797         ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0;
2798         if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) )
2799             return;
2800 #endif
2801     }
2802 }
2803 
2804 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2805 {
2806     if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry )
2807     {
2808         sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry );
2809         pZOrderList->Remove( nPos );
2810         pZOrderList->Insert( pEntry, LIST_APPEND );
2811     }
2812 }
2813 
2814 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2815 {
2816     if( rRect.Bottom() >= aVirtOutputSize.Height() )
2817         rRect.Bottom() = aVirtOutputSize.Height() - 1;
2818     if( rRect.Right() >= aVirtOutputSize.Width() )
2819         rRect.Right() = aVirtOutputSize.Width() - 1;
2820     if( rRect.Top() < 0 )
2821         rRect.Top() = 0;
2822     if( rRect.Left() < 0 )
2823         rRect.Left() = 0;
2824 }
2825 
2826 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2827 // sichtbar gemacht werden soll.
2828 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2829 
2830 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar,
2831     sal_Bool bCallRectChangedHdl )
2832 {
2833     Rectangle aVirtRect( rRect );
2834     ClipAtVirtOutRect( aVirtRect );
2835     Point aOrigin( pView->GetMapMode().GetOrigin() );
2836     // in Dokumentkoordinate umwandeln
2837     aOrigin *= -1;
2838     Rectangle aOutputArea( GetOutputRect() );
2839     if( aOutputArea.IsInside( aVirtRect ) )
2840         return; // ist schon sichtbar
2841 
2842     long nDy;
2843     if( aVirtRect.Top() < aOutputArea.Top() )
2844     {
2845         // nach oben scrollen (nDy < 0)
2846         nDy = aVirtRect.Top() - aOutputArea.Top();
2847     }
2848     else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2849     {
2850         // nach unten scrollen (nDy > 0)
2851         nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2852     }
2853     else
2854         nDy = 0;
2855 
2856     long nDx;
2857     if( aVirtRect.Left() < aOutputArea.Left() )
2858     {
2859         // nach links scrollen (nDx < 0)
2860         nDx = aVirtRect.Left() - aOutputArea.Left();
2861     }
2862     else if( aVirtRect.Right() > aOutputArea.Right() )
2863     {
2864         // nach rechts scrollen (nDx > 0)
2865         nDx = aVirtRect.Right() - aOutputArea.Right();
2866     }
2867     else
2868         nDx = 0;
2869 
2870     aOrigin.X() += nDx;
2871     aOrigin.Y() += nDy;
2872     aOutputArea.SetPos( aOrigin );
2873     if( GetUpdateMode() )
2874     {
2875         HideDDIcon();
2876         pView->Update();
2877         ShowCursor( sal_False );
2878     }
2879 
2880     // Origin fuer SV invertieren (damit wir in
2881     // Dokumentkoordinaten scrollen/painten koennen)
2882     aOrigin *= -1;
2883     SetOrigin( aOrigin );
2884 
2885     sal_Bool bScrollable = pView->GetBackground().IsScrollable();
2886     if( pView->HasBackground() && !bScrollable )
2887     {
2888         Rectangle aRect( GetOutputRect());
2889         Wallpaper aPaper( pView->GetBackground() );
2890         aPaper.SetRect( aRect );
2891         pView->SetBackground( aPaper );
2892     }
2893 
2894     if( bScrollable && GetUpdateMode() )
2895     {
2896         // in umgekehrte Richtung scrollen!
2897         pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2898             SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2899     }
2900     else
2901         pView->Invalidate(INVALIDATE_NOCHILDREN);
2902 
2903     if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2904     {
2905         if( !bScrBar )
2906         {
2907             aOrigin *= -1;
2908             // Thumbs korrigieren
2909             if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2910                 aHorSBar.SetThumbPos( aOrigin.X() );
2911             if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2912                 aVerSBar.SetThumbPos( aOrigin.Y() );
2913         }
2914     }
2915 
2916     if( GetUpdateMode() )
2917         ShowCursor( sal_True );
2918 
2919     // pruefen, ob ScrollBars noch benoetigt werden
2920     CheckScrollBars();
2921     if( bScrollable && GetUpdateMode() )
2922         pView->Update();
2923 
2924     // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden,
2925     // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der
2926     // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind,
2927     // eine ScrollBar aber eine groessere Line-Size eingestellt hat.
2928     if( bCallRectChangedHdl || GetOutputRect() != rRect )
2929         VisRectChanged();
2930 }
2931 
2932 
2933 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor()
2934 {
2935     SvxIconChoiceCtrlEntry* pNewCursor;
2936     if( pCursor )
2937     {
2938         pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False );
2939         if( !pNewCursor )
2940         {
2941             pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True );
2942             if( !pNewCursor )
2943             {
2944                 pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False );
2945                 if( !pNewCursor )
2946                     pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True );
2947             }
2948         }
2949     }
2950     else
2951         pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
2952     DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed");
2953     return pNewCursor;
2954 }
2955 
2956 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2957 {
2958     if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2959         return 1;
2960     return nSelectionCount;
2961 }
2962 
2963 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2964 {
2965     sal_Bool bSel;
2966     if( pEntry->IsSelected() )
2967         bSel = sal_False;
2968     else
2969         bSel = sal_True;
2970     SelectEntry( pEntry, bSel, sal_True, sal_True );
2971 }
2972 
2973 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2974     sal_Bool bPaintSync )
2975 {
2976     ClearSelectedRectList();
2977     //
2978     // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!!
2979     //
2980     sal_uLong nCount = aEntries.Count();
2981     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2982     {
2983         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2984         if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2985             SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync );
2986     }
2987     pAnchor = 0;
2988     nFlags &= (~F_ADD_MODE);
2989 }
2990 
2991 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2992 {
2993     Size aMinSize( aImageSize );
2994     aMinSize.Width() += 2 * LROFFS_BOUND;
2995     aMinSize.Height() += TBOFFS_BOUND;  // PB: einmal Offset reicht (FileDlg)
2996     String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
2997     Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2998     if( nWinBits & WB_ICON )
2999     {
3000         aMinSize.Height() += VER_DIST_BMP_STRING;
3001         aMinSize.Height() += aTextSize.Height();
3002     }
3003     else
3004     {
3005         aMinSize.Width() += HOR_DIST_BMP_STRING;
3006         aMinSize.Width() += aTextSize.Width();
3007     }
3008     return aMinSize;
3009 }
3010 
3011 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
3012 {
3013     Size aSize( rSize );
3014     Size aMinSize( GetMinGrid() );
3015     if( aSize.Width() < aMinSize.Width() )
3016         aSize.Width() = aMinSize.Width();
3017     if( aSize.Height() < aMinSize.Height() )
3018         aSize.Height() = aMinSize.Height();
3019 
3020     nGridDX = aSize.Width();
3021     // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
3022     // dieses Workaround bringts mit einer Spalte zum Fliegen
3023     if( nWinBits & WB_DETAILS )
3024     {
3025         const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
3026         if( pCol )
3027             ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
3028     }
3029     nGridDY = aSize.Height();
3030     SetDefaultTextSize();
3031 }
3032 
3033 // berechnet die maximale Groesse, die das Textrechteck innerhalb des
3034 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und
3035 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt
3036 
3037 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
3038 {
3039     Rectangle aBoundRect;
3040     // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen
3041     if( IsBoundingRectValid( pEntry->aRect ) )
3042         aBoundRect = pEntry->aRect;
3043     else
3044         aBoundRect = pEntry->aGridRect;
3045 
3046     Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
3047         (SvxIconChoiceCtrlEntry*)pEntry ) );
3048     if( nWinBits & WB_ICON )
3049     {
3050         aBoundRect.Top() = aBmpRect.Bottom();
3051         aBoundRect.Top() += VER_DIST_BMP_STRING;
3052         if( aBoundRect.Top() > aBoundRect.Bottom())
3053             aBoundRect.Top() = aBoundRect.Bottom();
3054         aBoundRect.Left() += LROFFS_BOUND;
3055         aBoundRect.Left()++;
3056         aBoundRect.Right() -= LROFFS_BOUND;
3057         aBoundRect.Right()--;
3058         if( aBoundRect.Left() > aBoundRect.Right())
3059             aBoundRect.Left() = aBoundRect.Right();
3060         if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
3061             aBoundRect.Bottom() = LONG_MAX;
3062     }
3063     else
3064     {
3065         aBoundRect.Left() = aBmpRect.Right();
3066         aBoundRect.Left() += HOR_DIST_BMP_STRING;
3067         aBoundRect.Right() -= LROFFS_BOUND;
3068         if( aBoundRect.Left() > aBoundRect.Right() )
3069             aBoundRect.Left() = aBoundRect.Right();
3070         long nHeight = aBoundRect.GetSize().Height();
3071         nHeight = nHeight - aDefaultTextSize.Height();
3072         nHeight /= 2;
3073         aBoundRect.Top() += nHeight;
3074         aBoundRect.Bottom() -= nHeight;
3075     }
3076     return aBoundRect;
3077 }
3078 
3079 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
3080 {
3081     long nDY = nGridDY;
3082     nDY -= aImageSize.Height();
3083     nDY -= VER_DIST_BMP_STRING;
3084     nDY -= 2*TBOFFS_BOUND;
3085     if( nDY <= 0 )
3086         nDY = 2;
3087 
3088     long nDX = nGridDX;
3089     nDX -= 2*LROFFS_BOUND;
3090     nDX -= 2;
3091     if( nDX <= 0 )
3092         nDX = 2;
3093 
3094     String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
3095     long nHeight = pView->GetTextHeight();
3096     if( nDY < nHeight )
3097         nDY = nHeight;
3098     aDefaultTextSize = Size( nDX, nDY );
3099 }
3100 
3101 
3102 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
3103 {
3104     pEntry->aRect = pEntry->aGridRect;
3105     Size aSize( CalcBoundingSize( pEntry ) );
3106     if( nWinBits & WB_ICON )
3107     {
3108         // horizontal zentrieren
3109         long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
3110         pEntry->aRect.Left() += nBorder / 2;
3111         pEntry->aRect.Right() -= nBorder / 2;
3112     }
3113     // vertikal zentrieren
3114     pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
3115 }
3116 
3117 
3118 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3119 // links, hoch: Offsets < 0
3120 // rechts, runter: Offsets > 0
3121 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
3122 {
3123     const MapMode& rMapMode = pView->GetMapMode();
3124     Point aOrigin( rMapMode.GetOrigin() );
3125     // in Dokumentkoordinate umwandeln
3126     aOrigin *= -1;
3127     aOrigin.Y() += nDeltaY;
3128     aOrigin.X() += nDeltaX;
3129     Rectangle aRect( aOrigin, aOutputSize );
3130     MakeVisible( aRect, bScrollBar );
3131 }
3132 
3133 
3134 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
3135     IcnViewFieldType eItem ) const
3136 {
3137     if( eItem == IcnViewFieldTypeText )
3138         return aDefaultTextSize;
3139     return aImageSize;
3140 }
3141 
3142 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
3143 {
3144     Rectangle aBmpRect( CalcBmpRect( pEntry ) );
3145     Rectangle aTextRect( CalcTextRect( pEntry ) );
3146     Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
3147     Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1,
3148                           aBoundRect.Right() - 4, aTextRect.Bottom() + 1 );
3149     // Das Fokusrechteck soll nicht den Text beruehren
3150     if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() )
3151         aFocusRect.Left()--;
3152     if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() )
3153         aFocusRect.Right()++;
3154 
3155     return aFocusRect;
3156 }
3157 
3158 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
3159 static Rectangle GetHotSpot( const Rectangle& rRect )
3160 {
3161     Rectangle aResult( rRect );
3162     aResult.Justify();
3163     Size aSize( rRect.GetSize() );
3164     long nDelta = aSize.Width() / 4;
3165     aResult.Left() += nDelta;
3166     aResult.Right() -= nDelta;
3167     nDelta = aSize.Height() / 4;
3168     aResult.Top() += nDelta;
3169     aResult.Bottom() -= nDelta;
3170     return aResult;
3171 }
3172 
3173 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
3174     sal_Bool bAdd, SvPtrarr* pOtherRects )
3175 {
3176     DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3177     Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3178     aRect.Union( GetEntryBoundRect( pEntry2 ) );
3179     SelectRect( aRect, bAdd, pOtherRects );
3180 }
3181 
3182 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, sal_Bool bAdd,
3183     SvPtrarr* pOtherRects )
3184 {
3185     aCurSelectionRect = rRect;
3186     if( !pZOrderList || !pZOrderList->Count() )
3187         return;
3188 
3189     // Flag setzen, damit im Select kein ToTop gerufen wird
3190     sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False;
3191     nFlags |= F_SELECTING_RECT;
3192 
3193     CheckBoundingRects();
3194     pView->Update();
3195     const sal_uLong nCount = pZOrderList->Count();
3196 
3197     Rectangle aRect( rRect );
3198     aRect.Justify();
3199     sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False;
3200 
3201     sal_Bool bResetClipRegion = sal_False;
3202     if( !pView->IsClipRegion() )
3203     {
3204         bResetClipRegion = sal_True;
3205         pView->SetClipRegion( GetOutputRect() );
3206     }
3207 
3208     for( sal_uLong nPos = 0; nPos < nCount; nPos++ )
3209     {
3210         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
3211 
3212         if( !IsBoundingRectValid( pEntry->aRect ))
3213             FindBoundingRect( pEntry );
3214         Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
3215         sal_Bool bSelected = pEntry->IsSelected();
3216 
3217         sal_Bool bOverlaps;
3218         if( bCalcOverlap )
3219             bOverlaps = IsOver( pOtherRects, aBoundRect );
3220         else
3221             bOverlaps = sal_False;
3222         sal_Bool bOver = aRect.IsOver( aBoundRect );
3223 
3224         if( bOver && !bOverlaps )
3225         {
3226             // Ist im neuen Selektionsrechteck und in keinem alten
3227             // => selektieren
3228             if( !bSelected )
3229                 SelectEntry( pEntry, sal_True, sal_True, sal_True );
3230         }
3231         else if( !bAdd )
3232         {
3233             // ist ausserhalb des Selektionsrechtecks
3234             // => Selektion entfernen
3235             if( bSelected )
3236                 SelectEntry( pEntry, sal_False, sal_True, sal_True );
3237         }
3238         else if( bAdd && bOverlaps )
3239         {
3240             // Der Eintrag befindet sich in einem alten (=>Aufspannen
3241             // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3242 
3243             // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3244             // in einem vorherigen Rechteck, muss restauriert werden, wenn
3245             // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3246             // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3247             // pauschal davon aus, dass die Eintraege in den alten Rechtecken
3248             // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3249             // nur zu deselektieren.
3250             // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3251             // spannen des Rechtecks merken
3252             if( aBoundRect.IsOver( rRect))
3253             {
3254                 // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3255                 if( bSelected )
3256                     SelectEntry( pEntry, sal_False, sal_True, sal_True );
3257             }
3258             else
3259             {
3260                 // Eintrag eines alten Rects selektieren
3261                 if( !bSelected )
3262                     SelectEntry( pEntry, sal_True, sal_True, sal_True );
3263             }
3264         }
3265         else if( !bOver && bSelected )
3266         {
3267             // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3268             SelectEntry( pEntry, sal_False, sal_True, sal_True );
3269         }
3270     }
3271 
3272     if( !bAlreadySelectingRect )
3273         nFlags &= ~F_SELECTING_RECT;
3274 
3275     pView->Update();
3276     if( bResetClipRegion )
3277         pView->SetClipRegion();
3278 }
3279 
3280 void SvxIconChoiceCtrl_Impl::SelectRange(
3281                         SvxIconChoiceCtrlEntry* pStart,
3282                         SvxIconChoiceCtrlEntry* pEnd,
3283                         sal_Bool bAdd )
3284 {
3285     sal_uLong nFront = GetEntryListPos( pStart );
3286     sal_uLong nBack  = GetEntryListPos( pEnd );
3287     sal_uLong nFirst = std::min( nFront, nBack );
3288     sal_uLong nLast  = std::max( nFront, nBack );
3289     sal_uLong i;
3290     SvxIconChoiceCtrlEntry* pEntry;
3291 
3292     if ( ! bAdd )
3293     {
3294         // deselect everything before the first entry if not in
3295         // adding mode
3296         for ( i=0; i<nFirst; i++ )
3297         {
3298             pEntry = GetEntry( i );
3299             if( pEntry->IsSelected() )
3300                 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3301         }
3302     }
3303 
3304     // select everything between nFirst and nLast
3305     for ( i=nFirst; i<=nLast; i++ )
3306     {
3307         pEntry = GetEntry( i );
3308         if( ! pEntry->IsSelected() )
3309             SelectEntry( pEntry, sal_True, sal_True,  sal_True, sal_True );
3310     }
3311 
3312     if ( ! bAdd )
3313     {
3314         // deselect everything behind the last entry if not in
3315         // adding mode
3316         sal_uLong nEnd = GetEntryCount();
3317         for ( ; i<nEnd; i++ )
3318         {
3319             pEntry = GetEntry( i );
3320             if( pEntry->IsSelected() )
3321                 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3322         }
3323     }
3324 }
3325 
3326 sal_Bool SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3327 {
3328     const sal_uInt16 nCount = pRectList->Count();
3329     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3330     {
3331         Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3332         if( rBoundRect.IsOver( *pRect ))
3333             return sal_True;
3334     }
3335     return sal_False;
3336 }
3337 
3338 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
3339     SvxIconChoiceCtrlEntry* pEntry2 )
3340 {
3341     DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3342     Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3343     aRect.Union( GetEntryBoundRect( pEntry2 ) );
3344     AddSelectedRect( aRect );
3345 }
3346 
3347 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
3348 {
3349     Rectangle* pRect = new Rectangle( rRect );
3350     pRect->Justify();
3351     aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3352 }
3353 
3354 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
3355 {
3356     const sal_uInt16 nCount = aSelectedRectList.Count();
3357     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3358     {
3359         Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3360         delete pRect;
3361     }
3362     aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3363 }
3364 
3365 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel,
3366     long& rX, long& rY, sal_Bool isInDragDrop, sal_uInt16 nBorderWidth)
3367 {
3368     // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3369     // Fensters befindet
3370     long nPixelToScrollX = 0;
3371     long nPixelToScrollY = 0;
3372     Size aWndSize = aOutputSize;
3373 
3374     nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3375     nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3376 
3377     if ( rPosPixel.X() < nBorderWidth )
3378     {
3379         if( isInDragDrop )
3380             nPixelToScrollX = -DD_SCROLL_PIXEL;
3381         else
3382             nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3383     }
3384     else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3385     {
3386         if( isInDragDrop )
3387             nPixelToScrollX = DD_SCROLL_PIXEL;
3388         else
3389             nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3390     }
3391     if ( rPosPixel.Y() < nBorderWidth )
3392     {
3393         if( isInDragDrop )
3394             nPixelToScrollY = -DD_SCROLL_PIXEL;
3395         else
3396             nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3397     }
3398     else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3399     {
3400         if( isInDragDrop )
3401             nPixelToScrollY = DD_SCROLL_PIXEL;
3402         else
3403             nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3404     }
3405 
3406     rX = nPixelToScrollX;
3407     rY = nPixelToScrollY;
3408 }
3409 
3410 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG )
3411 {
3412     aAutoArrangeTimer.Stop();
3413     Arrange( IsAutoArrange() );
3414     return 0;
3415 }
3416 
3417 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG )
3418 {
3419     aVisRectChangedTimer.Stop();
3420     pView->VisibleRectChanged();
3421     return 0;
3422 }
3423 
3424 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG )
3425 {
3426     aDocRectChangedTimer.Stop();
3427     pView->DocumentRectChanged();
3428     return 0;
3429 }
3430 
3431 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt )
3432 {
3433     StopEditTimer();
3434     SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() );
3435     if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() )
3436         SelectEntry( pEntry, sal_True, sal_True );
3437     nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
3438 }
3439 
3440 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
3441 {
3442     Rectangle aRect( CalcTextRect( pEntry ));
3443     if( aRect.IsInside( rDocPos ) )
3444         return sal_True;
3445     return sal_False;
3446 }
3447 
3448 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG )
3449 {
3450     SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
3451     if( bEntryEditingEnabled && pEntry &&
3452         pEntry->IsSelected())
3453     {
3454         if( pView->EditingEntry( pEntry ))
3455             EditEntry( pEntry );
3456     }
3457     return 0;
3458 }
3459 
3460 
3461 //
3462 // Funktionen zum Ausrichten der Eintraege am Grid
3463 //
3464 
3465 // pStart == 0: Alle Eintraege werden ausgerichtet
3466 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
3467 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
3468 {
3469     SvPtrarr aLists;
3470     pImpCursor->CreateGridAjustData( aLists, pStart );
3471     const sal_uInt16 nCount = aLists.Count();
3472     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3473         AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
3474     IcnCursor_Impl::DestroyGridAdjustData( aLists );
3475     CheckScrollBars();
3476 }
3477 
3478 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
3479 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart )
3480 {
3481     if( !rRow.Count() )
3482         return;
3483 
3484     sal_Bool bGo;
3485     if( !pStart )
3486         bGo = sal_True;
3487     else
3488         bGo = sal_False;
3489 
3490     long nCurRight = 0;
3491     for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ )
3492     {
3493         SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ];
3494         if( !bGo && pCur == pStart )
3495             bGo = sal_True;
3496 
3497         //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3498         // Massgebend (fuer unser Auge) ist die Bitmap, da sonst
3499         // durch lange Texte der Eintrag stark springen kann
3500         const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3501         Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3502         if( bGo && !pCur->IsPosLocked() )
3503         {
3504             long nWidth = aCenterRect.GetSize().Width();
3505             Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3506             while( aNewPos.X() < nCurRight )
3507                 aNewPos.X() += nGridDX;
3508             if( aNewPos != rBoundRect.TopLeft() )
3509             {
3510                 SetEntryPos( pCur, aNewPos );
3511                 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3512                 nFlags |= F_MOVED_ENTRIES;
3513             }
3514             nCurRight = aNewPos.X() + nWidth;
3515         }
3516         else
3517         {
3518             nCurRight = rBoundRect.Right();
3519         }
3520     }
3521 }
3522 
3523 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
3524 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
3525 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
3526 // die Berechnung des Ziel-Rechtecks verwendet wird.
3527 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3528     const Rectangle& rBoundRect ) const
3529 {
3530     Point aPos( rCenterRect.TopLeft() );
3531     Size aSize( rCenterRect.GetSize() );
3532 
3533     aPos.X() -= LROFFS_WINBORDER;
3534     aPos.Y() -= TBOFFS_WINBORDER;
3535 
3536     // align (ref ist mitte des rects)
3537     short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3538     short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3539     aPos.X() = nGridX * nGridDX;
3540     aPos.Y() = nGridY * nGridDY;
3541     // hor. center
3542     aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3543 
3544     aPos.X() += LROFFS_WINBORDER;
3545     aPos.Y() += TBOFFS_WINBORDER;
3546 
3547     return aPos;
3548 }
3549 
3550 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3551 {
3552     if( !pEntry )
3553     {
3554         if( eTextMode != eMode )
3555         {
3556             if( eTextMode == IcnShowTextDontKnow )
3557                 eTextMode = IcnShowTextShort;
3558             eTextMode = eMode;
3559             Arrange( sal_True );
3560         }
3561     }
3562     else
3563     {
3564         if( pEntry->eTextMode != eMode )
3565         {
3566             pEntry->eTextMode = eMode;
3567             InvalidateEntry( pEntry );
3568             pView->Invalidate( GetEntryBoundRect( pEntry ) );
3569             AdjustVirtSize( pEntry->aRect );
3570         }
3571     }
3572 }
3573 
3574 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
3575 {
3576     if( !pEntry )
3577         return eTextMode;
3578     return pEntry->GetTextMode();
3579 }
3580 
3581 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3582 {
3583     DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3584     SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3585     if( eMode == IcnShowTextDontKnow )
3586         return eTextMode;
3587     return eMode;
3588 }
3589 
3590 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry )
3591 {
3592     if( !pEntry )
3593     {
3594         pView->HideFocus();
3595     }
3596     else
3597     {
3598         Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
3599         /*pView->*/ShowFocus( aRect );
3600     }
3601 }
3602 
3603 ////////////////////////////////////////////////////////////////////////////////////////////////
3604 //
3605 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3606 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see
3607 // a gray focusrect on a gray background !!!
3608 //
3609 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3610 {
3611     Color aBkgColor ( pView->GetBackground().GetColor() );
3612     Color aPenColor;
3613     sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3614     if ( nColor > 128 )
3615         aPenColor.SetColor ( COL_BLACK );
3616     else
3617         aPenColor.SetColor( COL_WHITE );
3618 
3619     aFocus.bOn = sal_True;
3620     aFocus.aPenColor = aPenColor;
3621     aFocus.aRect = rRect;
3622 }
3623 
3624 void SvxIconChoiceCtrl_Impl::HideFocus ()
3625 {
3626     aFocus.bOn = sal_False;
3627 }
3628 
3629 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3630 {
3631     pOut->SetLineColor( aFocus.aPenColor );
3632     pOut->SetFillColor();
3633     Polygon aPolygon ( aFocus.aRect );
3634 
3635     LineInfo aLineInfo ( LINE_DASH );
3636 
3637     aLineInfo.SetDashLen ( 1 );
3638 
3639     aLineInfo.SetDotLen ( 1L );
3640     aLineInfo.SetDistance ( 1L );
3641     aLineInfo.SetDotCount ( 1 );
3642 
3643     pOut->DrawPolyLine ( aPolygon, aLineInfo );
3644 }
3645 
3646 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
3647 {
3648     sal_Bool bRet = sal_False;
3649     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3650     sal_uLong nEntryCount = GetEntryCount();
3651     for ( sal_uLong i = 0; i < nEntryCount; ++i )
3652     {
3653         if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3654         {
3655             bRet = sal_True;
3656             rPos = i;
3657             break;
3658         }
3659     }
3660 
3661     return bRet;
3662 }
3663 
3664 //
3665 ////////////////////////////////////////////////////////////////////////////////////////////////
3666 
3667 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3668 {
3669     if( nId == EVENTID_ADJUST_SCROLLBARS )
3670     {
3671         nUserEventAdjustScrBars = 0;
3672         AdjustScrollBars();
3673     }
3674     else if( nId == EVENTID_SHOW_CURSOR )
3675     {
3676         nUserEventShowCursor = 0;
3677         ShowCursor( sal_True );
3678     }
3679     return 0;
3680 }
3681 
3682 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3683 {
3684     if( nUserEventAdjustScrBars )
3685     {
3686         Application::RemoveUserEvent( nUserEventAdjustScrBars );
3687         nUserEventAdjustScrBars = 0;
3688     }
3689     if( nUserEventShowCursor )
3690     {
3691         Application::RemoveUserEvent( nUserEventShowCursor );
3692         nUserEventShowCursor = 0;
3693     }
3694 }
3695 
3696 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3697 {
3698     if( pEntry == pCursor )
3699         ShowCursor( sal_False );
3700     pView->Invalidate( pEntry->aRect );
3701     Center( pEntry );
3702     pView->Invalidate( pEntry->aRect );
3703     if( pEntry == pCursor )
3704         ShowCursor( sal_True );
3705 }
3706 
3707 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3708 {
3709     DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3710     if( !pEntry )
3711         return;
3712 
3713     StopEntryEditing( sal_True );
3714     DELETEZ(pEdit);
3715     SetNoSelection();
3716 
3717     pCurEditedEntry = pEntry;
3718     String aEntryText( pView->GetEntryText( pEntry, sal_True ) );
3719     Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) );
3720     MakeVisible( aRect );
3721     Point aPos( aRect.TopLeft() );
3722     aPos = pView->GetPixelPos( aPos );
3723     aRect.SetPos( aPos );
3724     pView->HideFocus();
3725     pEdit = new IcnViewEdit_Impl(
3726         pView,
3727         aRect.TopLeft(),
3728         aRect.GetSize(),
3729         aEntryText,
3730         LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3731 }
3732 
3733 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG )
3734 {
3735     DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3736     if( !pEdit )
3737     {
3738         pCurEditedEntry = 0;
3739         return 0;
3740     }
3741     DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3742 
3743     if( !pCurEditedEntry )
3744     {
3745         pEdit->Hide();
3746         if( pEdit->IsGrabFocus() )
3747             pView->GrabFocus();
3748         return 0;
3749     }
3750 
3751     String aText;
3752     if ( !pEdit->EditingCanceled() )
3753         aText = pEdit->GetText();
3754     else
3755         aText = pEdit->GetSavedValue();
3756 
3757     if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3758         InvalidateEntry( pCurEditedEntry );
3759     if( !GetSelectionCount() )
3760         SelectEntry( pCurEditedEntry, sal_True );
3761 
3762     pEdit->Hide();
3763     if( pEdit->IsGrabFocus() )
3764         pView->GrabFocus();
3765     // Das Edit kann nicht hier geloescht werden, weil es noch in einem
3766     // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht.
3767     pCurEditedEntry = 0;
3768     return 0;
3769 }
3770 
3771 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel )
3772 {
3773     if( pEdit )
3774         pEdit->StopEditing( bCancel );
3775 }
3776 
3777 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bLock )
3778 {
3779     if( bLock )
3780         pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED );
3781     else
3782         pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED );
3783 }
3784 
3785 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3786 {
3787     if( !GetSelectionCount() )
3788         return 0;
3789 
3790     if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3791     {
3792         rPos = pView->GetEntryListPos( pCurHighlightFrame );
3793         return pCurHighlightFrame;
3794     }
3795 
3796     sal_uLong nCount = aEntries.Count();
3797     if( !pHead )
3798     {
3799         for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
3800         {
3801             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3802             if( pEntry->IsSelected() )
3803             {
3804                 rPos = nCur;
3805                 return pEntry;
3806             }
3807         }
3808     }
3809     else
3810     {
3811         SvxIconChoiceCtrlEntry* pEntry = pHead;
3812         while( nCount-- )
3813         {
3814             if( pEntry->IsSelected() )
3815             {
3816                 rPos = GetEntryListPos( pEntry );
3817                 return pEntry;
3818             }
3819             pEntry = pEntry->pflink;
3820             if( nCount && pEntry == pHead )
3821             {
3822                 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
3823                 return 0;
3824             }
3825         }
3826     }
3827     return 0;
3828 }
3829 
3830 // kein Round Robin!
3831 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( sal_uLong& rStartPos ) const
3832 {
3833     sal_uLong nCount = aEntries.Count();
3834     if( rStartPos > nCount || !GetSelectionCount() )
3835         return 0;
3836     if( !pHead )
3837     {
3838         for( sal_uLong nCur = rStartPos+1; nCur < nCount; nCur++ )
3839         {
3840             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3841             if( pEntry->IsSelected() )
3842             {
3843                 rStartPos = nCur;
3844                 return pEntry;
3845             }
3846         }
3847     }
3848     else
3849     {
3850         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos );
3851         pEntry = pEntry->pflink;
3852         while( pEntry != pHead )
3853         {
3854             if( pEntry->IsSelected() )
3855             {
3856                 rStartPos = GetEntryListPos( pEntry );
3857                 return pEntry;
3858             }
3859             pEntry = pEntry->pflink;
3860         }
3861     }
3862 
3863     rStartPos = 0xffffffff;
3864     return 0;
3865 }
3866 
3867 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint )
3868 {
3869     bPaint = sal_True;
3870 
3871     sal_uLong nCount = aEntries.Count();
3872     for( sal_uLong nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3873     {
3874         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3875         SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint );
3876     }
3877     nFlags &= (~F_ADD_MODE);
3878     pAnchor = 0;
3879 }
3880 
3881 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList )
3882 {
3883     if( !*ppList )
3884         *ppList = new List;
3885     sal_uLong nPos;
3886     SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos );
3887     while( pEntry && GetSelectionCount() != (*ppList)->Count() )
3888     {
3889         (*ppList)->Insert( pEntry, LIST_APPEND );
3890         pEntry = GetNextSelectedEntry( nPos );
3891     }
3892 }
3893 
3894 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3895     const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
3896     MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3897     aCallBackHdl( rNotifyEditEnd ),
3898     bCanceled( sal_False ),
3899     bAlreadyInCallback( sal_False ),
3900     bGrabFocus( sal_False )
3901 {
3902     Font aFont( pParent->GetPointFont() );
3903     aFont.SetTransparent( sal_False );
3904     SetControlFont( aFont );
3905     if( !pParent->HasFontFillColor() )
3906     {
3907         Color aColor( pParent->GetBackground().GetColor() );
3908         SetControlBackground( aColor );
3909     }
3910     else
3911         SetControlBackground( aFont.GetFillColor() );
3912     SetControlForeground( aFont.GetColor() );
3913     SetPosPixel( rPos );
3914     SetSizePixel( CalcAdjustedSize(rSize) );
3915     SetText( rData );
3916     SaveValue();
3917 
3918     aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3919     aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3920 
3921     aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3922     aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3923     GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3924     GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3925     Show();
3926     GrabFocus();
3927 }
3928 
3929 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3930 {
3931     if( !bAlreadyInCallback )
3932     {
3933         GetpApp()->RemoveAccel( &aAccReturn );
3934         GetpApp()->RemoveAccel( &aAccEscape );
3935     }
3936 }
3937 
3938 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3939 {
3940     aTimer.Stop();
3941     if ( !bAlreadyInCallback )
3942     {
3943         bAlreadyInCallback = sal_True;
3944         GetpApp()->RemoveAccel( &aAccReturn );
3945         GetpApp()->RemoveAccel( &aAccEscape );
3946         Hide();
3947         aCallBackHdl.Call( this );
3948     }
3949 }
3950 
3951 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG )
3952 {
3953     CallCallBackHdl_Impl();
3954     return 0;
3955 }
3956 
3957 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG  )
3958 {
3959     bCanceled = sal_False;
3960     bGrabFocus = sal_True;
3961     CallCallBackHdl_Impl();
3962     return 1;
3963 }
3964 
3965 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG  )
3966 {
3967     bCanceled = sal_True;
3968     bGrabFocus = sal_True;
3969     CallCallBackHdl_Impl();
3970     return 1;
3971 }
3972 
3973 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3974 {
3975     KeyCode aCode = rKEvt.GetKeyCode();
3976     sal_uInt16 nCode = aCode.GetCode();
3977 
3978     switch ( nCode )
3979     {
3980         case KEY_ESCAPE:
3981             bCanceled = sal_True;
3982             bGrabFocus = sal_True;
3983             CallCallBackHdl_Impl();
3984             break;
3985 
3986         case KEY_RETURN:
3987             bCanceled = sal_False;
3988             bGrabFocus = sal_True;
3989             CallCallBackHdl_Impl();
3990             break;
3991 
3992         default:
3993             MultiLineEdit::KeyInput( rKEvt );
3994     }
3995 }
3996 
3997 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3998 {
3999     if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4000     {
4001         if ( !bAlreadyInCallback &&
4002             ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
4003         {
4004             bCanceled = sal_False;
4005             aTimer.SetTimeout(10);
4006             aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
4007             aTimer.Start();
4008         }
4009     }
4010     return 0;
4011 }
4012 
4013 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel )
4014 {
4015     if ( !bAlreadyInCallback )
4016     {
4017         bCanceled = bCancel;
4018         CallCallBackHdl_Impl();
4019     }
4020 }
4021 
4022 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
4023 {
4024     if( !(nFlags & F_ENTRYLISTPOS_VALID ))
4025         ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
4026     return pEntry->nPos;
4027 }
4028 
4029 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, sal_uLong nNewPos )
4030 {
4031     sal_uLong nCurPos = GetEntryListPos( pListEntry );
4032     if( nCurPos == nNewPos )
4033         return;
4034     aEntries.List::Remove( nCurPos );
4035     aEntries.List::Insert( (void*)pListEntry, nNewPos );
4036     // Eintragspositionen anpassen
4037     sal_uLong nStart, nEnd;
4038     if( nNewPos < nCurPos )
4039     {
4040         nStart = nNewPos;
4041         nEnd = nCurPos;
4042     }
4043     else
4044     {
4045         nStart = nCurPos;
4046         nEnd = nNewPos;
4047     }
4048     for( ; nStart <= nEnd; nStart++ )
4049     {
4050         SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart );
4051         pEntry->nPos = nStart;
4052     }
4053 }
4054 
4055 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nEntryFlags )
4056 {
4057     pEntry->nFlags = nEntryFlags;
4058     if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED )
4059         nFlags |= F_MOVED_ENTRIES;
4060 }
4061 
4062 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, sal_Bool bRight )
4063 {
4064     return pImpCursor->GoLeftRight( pStart, bRight );
4065 }
4066 
4067 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown )
4068 {
4069     return pImpCursor->GoUpDown( pStart, bDown );
4070 }
4071 
4072 void SvxIconChoiceCtrl_Impl::InitSettings()
4073 {
4074     const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
4075 
4076     if( !pView->HasFont() )
4077     {
4078         // Unit aus den Settings ist Point
4079         Font aFont( rStyleSettings.GetFieldFont() );
4080         //const Font& rFont = pView->GetFont();
4081         //if( pView->HasFontTextColor() )
4082             aFont.SetColor( rStyleSettings.GetWindowTextColor() );
4083         //if( pView->HasFontFillColor() )
4084             //aFont.SetFillColor( rFont.GetFillColor() );
4085         pView->SetPointFont( aFont );
4086         SetDefaultTextSize();
4087     }
4088 
4089     //if( !pView->HasFontTextColor() )
4090         pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
4091     //if( !pView->HasFontFillColor() )
4092         pView->SetTextFillColor();
4093 
4094     //if( !pView->HasBackground() )
4095         pView->SetBackground( rStyleSettings.GetFieldColor());
4096 
4097     long nScrBarSize = rStyleSettings.GetScrollBarSize();
4098     if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
4099     {
4100         nHorSBarHeight = nScrBarSize;
4101         Size aSize( aHorSBar.GetSizePixel() );
4102         aSize.Height() = nScrBarSize;
4103         aHorSBar.Hide();
4104         aHorSBar.SetSizePixel( aSize );
4105 
4106         nVerSBarWidth = nScrBarSize;
4107         aSize = aVerSBar.GetSizePixel();
4108         aSize.Width() = nScrBarSize;
4109         aVerSBar.Hide();
4110         aVerSBar.SetSizePixel( aSize );
4111 
4112         Size aOSize( pView->Control::GetOutputSizePixel() );
4113         PositionScrollBars( aOSize.Width(), aOSize.Height() );
4114         AdjustScrollBars();
4115     }
4116 }
4117 
4118 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nInitSize , sal_uInt16 _nReSize ) :
4119     List( _nInitSize, _nReSize ),
4120     _pOwner( pOwner )
4121 {
4122     _pOwner->pHead = 0;
4123 }
4124 
4125 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) :
4126     List( _nBlockSize, _nInitSize, _nReSize ),
4127     _pOwner( pOwner )
4128 {
4129     _pOwner->pHead = 0;
4130 }
4131 
4132 EntryList_Impl::~EntryList_Impl()
4133 {
4134     _pOwner->pHead = 0;
4135 }
4136 
4137 void EntryList_Impl::Clear()
4138 {
4139     _pOwner->pHead = 0;
4140     List::Clear();
4141 }
4142 
4143 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos )
4144 {
4145     List::Insert( pEntry, nPos );
4146     if( _pOwner->pHead )
4147         pEntry->SetBacklink( _pOwner->pHead->pblink );
4148 }
4149 
4150 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( sal_uLong nPos )
4151 {
4152     SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos );
4153     DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found");
4154     Removed_Impl( pEntry );
4155     return pEntry;
4156 }
4157 
4158 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry )
4159 {
4160     List::Remove( (void*)pEntry );
4161     Removed_Impl( pEntry );
4162 }
4163 
4164 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry )
4165 {
4166     if( _pOwner->pHead )
4167     {
4168         if( _pOwner->pHead == pEntry )
4169         {
4170             if( _pOwner->pHead != pEntry->pflink )
4171                 _pOwner->pHead = pEntry->pflink;
4172             else
4173             {
4174                 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
4175                 _pOwner->pHead = 0;
4176             }
4177         }
4178         pEntry->Unlink();
4179     }
4180 }
4181 
4182 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
4183 {
4184     sal_uLong nCur;
4185 
4186     if( eMode == ePositionMode )
4187         return;
4188 
4189     SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
4190     ePositionMode = eMode;
4191     sal_uLong nCount = aEntries.Count();
4192 
4193     if( eOldMode == IcnViewPositionModeAutoArrange )
4194     {
4195         // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme
4196         // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange
4197         // nicht beruecksichtigt werden.
4198 #if 1
4199         if( aEntries.Count() )
4200             aAutoArrangeTimer.Start();
4201 #else
4202         if( pHead )
4203         {
4204             // verschobene Eintraege 'hart' auf ihre Position setzen
4205             nCur = nCount;
4206             SvxIconChoiceCtrlEntry* pEntry = pHead;
4207             while( nCur )
4208             {
4209                 SvxIconChoiceCtrlEntry* pPred;
4210                 if( GetEntryPredecessor( pEntry, &pPred ))
4211                     SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED );
4212                 pEntry = pEntry->pflink;
4213                 nCur--;
4214             }
4215             ClearPredecessors();
4216         }
4217 #endif
4218         return;
4219     }
4220 
4221     if( ePositionMode == IcnViewPositionModeAutoArrange )
4222     {
4223         List aMovedEntries;
4224         for( nCur = 0; nCur < nCount; nCur++ )
4225         {
4226             SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
4227             if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
4228             {
4229                 SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl(
4230                         pEntry, GetEntryBoundRect( pEntry ));
4231                 aMovedEntries.Insert( pE, LIST_APPEND );
4232             }
4233         }
4234         nCount = aMovedEntries.Count();
4235         for( nCur = 0; nCur < nCount; nCur++ )
4236         {
4237             SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur);
4238             SetEntryPos( pE->_pEntry, pE->_aPos );
4239         }
4240         for( nCur = 0; nCur < nCount; nCur++ )
4241             delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur );
4242         if( aEntries.Count() )
4243             aAutoArrangeTimer.Start();
4244     }
4245     else if( ePositionMode == IcnViewPositionModeAutoAdjust )
4246     {
4247         AdjustEntryAtGrid( 0 );
4248     }
4249 }
4250 
4251 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4252     SvxIconChoiceCtrlEntry* pPredecessor )
4253 {
4254     if( !IsAutoArrange() )
4255         return;
4256 
4257     if( pEntry == pPredecessor )
4258         return;
4259 
4260     sal_uLong nPos1 = GetEntryListPos( pEntry );
4261     if( !pHead )
4262     {
4263         if( pPredecessor )
4264         {
4265             sal_uLong nPos2 = GetEntryListPos( pPredecessor );
4266             if( nPos1 == (nPos2 + 1) )
4267                 return; // ist schon Vorgaenger
4268         }
4269         else if( !nPos1 )
4270             return;
4271     }
4272 
4273     if( !pHead )
4274         InitPredecessors();
4275 
4276     if( !pPredecessor && pHead == pEntry )
4277         return; // ist schon der Erste
4278 
4279     sal_Bool bSetHead = sal_False;
4280     if( !pPredecessor )
4281     {
4282         bSetHead = sal_True;
4283         pPredecessor = pHead->pblink;
4284     }
4285     if( pEntry == pHead )
4286     {
4287         pHead = pHead->pflink;
4288         bSetHead = sal_False;
4289     }
4290     if( pEntry != pPredecessor )
4291     {
4292         pEntry->Unlink();
4293         pEntry->SetBacklink( pPredecessor );
4294     }
4295     if( bSetHead )
4296         pHead = pEntry;
4297     pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
4298     aAutoArrangeTimer.Start();
4299 }
4300 
4301 sal_Bool SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4302     SvxIconChoiceCtrlEntry** ppPredecessor )
4303 {
4304     *ppPredecessor = 0;
4305     if( !pHead )
4306         return sal_False;
4307     DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set");
4308     DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set");
4309 
4310     if( pEntry == pHead )
4311     {
4312         SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0);
4313         if( pFirst != pEntry )
4314             return sal_True;
4315         return sal_False;
4316     }
4317     *ppPredecessor = pEntry->pblink;
4318     if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) &&
4319         (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry ))
4320         return sal_False;
4321     return sal_True;
4322 }
4323 
4324 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4325     const Point& rPosTopLeft )
4326 {
4327     Point aPos( rPosTopLeft ); //TopLeft
4328     Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
4329     Point aNewPos( aCenterRect.Center() );
4330     sal_uLong nGrid = GetPredecessorGrid( aNewPos );
4331     sal_uLong nCount = aEntries.Count();
4332     if( nGrid == ULONG_MAX )
4333         return 0;
4334     if( nGrid >= nCount )
4335         nGrid = nCount - 1;
4336     if( !pHead )
4337         return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid );
4338 
4339     SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
4340     // todo: Liste von hinten aufrollen wenn nGrid > nCount/2
4341     for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
4342         pCur = pCur->pflink;
4343 
4344     return pCur;
4345 }
4346 
4347 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
4348 {
4349     Point aPos( rPos );
4350     aPos.X() -= LROFFS_WINBORDER;
4351     aPos.Y() -= TBOFFS_WINBORDER;
4352     sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX);
4353     if( nMaxCol )
4354         nMaxCol--;
4355     sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX);
4356     if( nGridX > nMaxCol )
4357         nGridX = nMaxCol;
4358     sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY);
4359     sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX);
4360     sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
4361     long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
4362     if( rPos.X() < nMiddle )
4363     {
4364         if( !nGrid )
4365             nGrid = ULONG_MAX;
4366         else
4367             nGrid--;
4368     }
4369     return nGrid;
4370 }
4371 
4372 void SvxIconChoiceCtrl_Impl::Flush()
4373 {
4374     if( aAutoArrangeTimer.IsActive() )
4375     {
4376         AutoArrangeHdl( 0 );
4377     }
4378 }
4379 
4380 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
4381 {
4382     if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
4383         return sal_False;
4384 
4385     Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
4386     aPos -= pView->GetMapMode().GetOrigin();
4387     SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True );
4388 
4389     if ( !pEntry )
4390         return sal_False;
4391 
4392     String sQuickHelpText = pEntry->GetQuickHelpText();
4393     String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
4394     Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) );
4395     if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
4396         return sal_False;
4397 
4398     Rectangle aOptTextRect( aTextRect );
4399     aOptTextRect.Bottom() = LONG_MAX;
4400     sal_uInt16 nNewFlags = nCurTextDrawFlags;
4401     nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
4402     aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
4403     if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
4404     {
4405         //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
4406         Point aPt( aOptTextRect.TopLeft() );
4407         aPt += pView->GetMapMode().GetOrigin();
4408         aPt = pView->OutputToScreenPixel( aPt );
4409         // Border der Tiphilfe abziehen
4410         aPt.Y() -= 1;
4411         aPt.X() -= 3;
4412         aOptTextRect.SetPos( aPt );
4413         String sHelpText;
4414         if ( sQuickHelpText.Len() > 0 )
4415             sHelpText = sQuickHelpText;
4416         else
4417             sHelpText = aEntryText;
4418         Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
4419     }
4420 
4421     return sal_True;
4422 }
4423 
4424 void SvxIconChoiceCtrl_Impl::ClearColumnList()
4425 {
4426     if( !pColumns )
4427         return;
4428 
4429     const sal_uInt16 nCount = pColumns->Count();
4430     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4431     {
4432         SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*)
4433             pColumns->GetObject( nCur );
4434         delete pInfo;
4435     }
4436     DELETEZ(pColumns);
4437 }
4438 
4439 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
4440 {
4441     if( !pColumns )
4442         pColumns = new SvPtrarr;
4443     while( pColumns->Count() < nIndex + 1 )
4444         pColumns->Insert( (void*)0, pColumns->Count() );
4445 
4446     SvxIconChoiceCtrlColumnInfo* pInfo =
4447         (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex);
4448     if( !pInfo )
4449     {
4450         pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4451         pColumns->Insert( (void*)pInfo, nIndex );
4452     }
4453     else
4454     {
4455         delete pInfo;
4456         pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4457         pColumns->Replace( pInfo, nIndex );
4458     }
4459 
4460     // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
4461     // dieses Workaround bringts mit einer Spalte zum Fliegen
4462     if( !nIndex && (nWinBits & WB_DETAILS) )
4463         nGridDX = pInfo->GetWidth();
4464 
4465     if( GetUpdateMode() )
4466         Arrange( IsAutoArrange() );
4467 }
4468 
4469 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
4470 {
4471     if( !pColumns || nIndex >= pColumns->Count() )
4472         return 0;
4473     return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex );
4474 }
4475 
4476 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( sal_uInt16 nSubItem,
4477     long& rLeft ) const
4478 {
4479     rLeft = 0;
4480     if( !pColumns )
4481         return 0;
4482     const sal_uInt16 nCount = pColumns->Count();
4483     const SvxIconChoiceCtrlColumnInfo* pCol = 0;
4484     for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4485     {
4486          pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur );
4487         if( !pCol || pCol->GetSubItem() == nSubItem )
4488             return pCol;
4489         rLeft += pCol->GetWidth();
4490     }
4491     return pCol;
4492 }
4493 
4494 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
4495     OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide )
4496 {
4497     Rectangle aBmpRect( rBmpRect );
4498     long nBorder = 2;
4499     if( aImageSize.Width() < 32 )
4500         nBorder = 1;
4501     aBmpRect.Right() += nBorder;
4502     aBmpRect.Left() -= nBorder;
4503     aBmpRect.Bottom() += nBorder;
4504     aBmpRect.Top() -= nBorder;
4505 
4506     if ( bHide )
4507         pView->Invalidate( aBmpRect );
4508     else
4509     {
4510         DecorationView aDecoView( pOut );
4511         sal_uInt16 nDecoFlags;
4512         if ( bHighlightFramePressed )
4513             nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
4514         else
4515             nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
4516         aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
4517     }
4518 }
4519 
4520 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
4521     sal_Bool bKeepHighlightFlags )
4522 {
4523     if( pEntry == pCurHighlightFrame )
4524         return;
4525 
4526     if( !bKeepHighlightFlags )
4527         bHighlightFramePressed = sal_False;
4528 
4529     HideEntryHighlightFrame();
4530     pCurHighlightFrame = pEntry;
4531     if( pEntry )
4532     {
4533         Rectangle aBmpRect( CalcFocusRect(pEntry) );
4534         DrawHighlightFrame( pView, aBmpRect, sal_False );
4535     }
4536 }
4537 
4538 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
4539 {
4540     if( !pCurHighlightFrame )
4541         return;
4542 
4543     SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
4544     pCurHighlightFrame = 0;
4545     Rectangle aBmpRect( CalcFocusRect(pEntry) );
4546     DrawHighlightFrame( pView, aBmpRect, sal_True );
4547 }
4548 
4549 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
4550 {
4551     // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler
4552     // synchron gerufen werden, weil die Selektion automatisch
4553     // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt
4554     // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen,
4555     // wenn das Objekt aus einer Mausbewegung heraus selektiert wird,
4556     // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U.
4557     // schon verlassen hat.
4558     // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone
4559     // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden.
4560     if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
4561     {
4562         pHdlEntry = 0;
4563         pView->ClickIcon();
4564         //pView->Select();
4565     }
4566     else
4567         aCallSelectHdlTimer.Start();
4568 }
4569 
4570 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG )
4571 {
4572     pHdlEntry = 0;
4573     pView->ClickIcon();
4574     //pView->Select();
4575     return 0;
4576 }
4577 
4578 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
4579 {
4580     Point aResult;
4581     if( !GetSelectionCount() )
4582         return aResult;
4583 
4584     SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
4585     if( !pEntry || !pEntry->IsSelected() )
4586     {
4587         sal_uLong nNext;
4588         pEntry = GetFirstSelectedEntry( nNext );
4589     }
4590     if( pEntry )
4591     {
4592         Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) );
4593         aResult = aRect.Center();
4594         aResult = pView->GetPixelPos( aResult );
4595     }
4596     return aResult;
4597 }
4598 
4599 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper )
4600 {
4601     MapMode aMapMode( pView->GetMapMode() );
4602     aMapMode.SetOrigin( rPos );
4603     pView->SetMapMode( aMapMode );
4604     if( !bDoNotUpdateWallpaper )
4605     {
4606         sal_Bool bScrollable = pView->GetBackground().IsScrollable();
4607         if( pView->HasBackground() && !bScrollable )
4608         {
4609             Rectangle aRect( GetOutputRect());
4610             Wallpaper aPaper( pView->GetBackground() );
4611             aPaper.SetRect( aRect );
4612             pView->SetBackground( aPaper );
4613         }
4614     }
4615 }
4616 
4617 sal_uLong SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, sal_Bool bCheckScrBars,
4618     sal_Bool bSmartScrBar ) const
4619 {
4620     Size aSize( rSize );
4621     if( bCheckScrBars && aHorSBar.IsVisible() )
4622         aSize.Height() -= nHorSBarHeight;
4623     else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) )
4624         aSize.Height() -= nHorSBarHeight;
4625 
4626     if( bCheckScrBars && aVerSBar.IsVisible() )
4627         aSize.Width() -= nVerSBarWidth;
4628     else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) )
4629         aSize.Width() -= nVerSBarWidth;
4630 
4631     if( aSize.Width() < 0 )
4632         aSize.Width() = 0;
4633     if( aSize.Height() < 0 )
4634         aSize.Height() = 0;
4635 
4636     return IcnGridMap_Impl::GetGridCount( aSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
4637 }
4638 
4639 sal_Bool SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt )
4640 {
4641     StopEditTimer();
4642 
4643     sal_Bool        bRet = sal_False;
4644 
4645     DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" );
4646 
4647     sal_Unicode cChar = rKEvt.GetCharCode();
4648     sal_uLong       nPos = (sal_uLong)-1;
4649 
4650     if( cChar && IsMnemonicChar( cChar, nPos ) )
4651     {
4652         // shortcut is clicked
4653         SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
4654         SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
4655         if( pNewCursor != pOldCursor )
4656         {
4657             SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
4658 
4659             if( pNewCursor != NULL )
4660             {
4661                 pHdlEntry = pNewCursor;
4662                 pCurHighlightFrame = pHdlEntry;
4663                 pView->ClickIcon();
4664                 pCurHighlightFrame = NULL;
4665             }
4666         }
4667         bRet = sal_True;
4668     }
4669 
4670     return bRet;
4671 }
4672 
4673 // -----------------------------------------------------------------------
4674 
4675 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
4676 {
4677     pView->CallImplEventListeners( nEvent, pData );
4678 }
4679 
4680 
4681