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