Update ooo320-m1
[ooovba.git] / svtools / source / contnr / imivctl1.cxx
blobda678db5267ddf771e952a6d6ddfd1be678231e1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: imivctl1.cxx,v $
10 * $Revision: 1.32 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <limits.h>
35 #include <tools/debug.hxx>
36 #include <vcl/wall.hxx>
37 #include <vcl/help.hxx>
38 #include <vcl/decoview.hxx>
39 #include <vcl/svapp.hxx>
40 #include <tools/poly.hxx>
41 #include <vcl/lineinfo.hxx>
42 #include <vcl/i18nhelp.hxx>
43 #include <vcl/mnemonic.hxx>
44 #include <vcl/controllayout.hxx>
46 #include "ivctrl.hxx"
47 #include "imivctl.hxx"
48 #include <svtools/svmedit.hxx>
50 #include <algorithm>
51 #include <memory>
53 #define DD_SCROLL_PIXEL 24
54 #define IMPICNVIEW_ACC_RETURN 1
55 #define IMPICNVIEW_ACC_ESCAPE 2
57 #define DRAWTEXT_FLAGS_ICON \
58 ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
59 TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
61 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
63 #define EVENTID_SHOW_CURSOR ((void*)1)
64 #define EVENTID_ADJUST_SCROLLBARS ((void*)2)
66 struct SvxIconChoiceCtrlEntry_Impl
68 SvxIconChoiceCtrlEntry* _pEntry;
69 Point _aPos;
70 SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect )
71 : _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {}
74 static BOOL bEndScrollInvalidate = TRUE;
76 // ----------------------------------------------------------------------------------------------
78 class IcnViewEdit_Impl : public MultiLineEdit
80 Link aCallBackHdl;
81 Accelerator aAccReturn;
82 Accelerator aAccEscape;
83 Timer aTimer;
84 BOOL bCanceled;
85 BOOL bAlreadyInCallback;
86 BOOL bGrabFocus;
88 void CallCallBackHdl_Impl();
89 DECL_LINK( Timeout_Impl, Timer * );
90 DECL_LINK( ReturnHdl_Impl, Accelerator * );
91 DECL_LINK( EscapeHdl_Impl, Accelerator * );
93 public:
95 IcnViewEdit_Impl(
96 SvtIconChoiceCtrl* pParent,
97 const Point& rPos,
98 const Size& rSize,
99 const XubString& rData,
100 const Link& rNotifyEditEnd );
102 ~IcnViewEdit_Impl();
103 virtual void KeyInput( const KeyEvent& rKEvt );
104 virtual long PreNotify( NotifyEvent& rNEvt );
105 BOOL EditingCanceled() const { return bCanceled; }
106 void StopEditing( BOOL bCancel = FALSE );
107 BOOL IsGrabFocus() const { return bGrabFocus; }
110 // ----------------------------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------------------------
114 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pCurView,
115 WinBits nWinStyle ) :
116 aEntries( this ),
117 aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
118 aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ),
119 aScrBarBox( pCurView ),
120 aImageSize( 32, 32 ),
121 pColumns( 0 )
123 bChooseWithCursor=FALSE;
124 pEntryPaintDev = 0;
125 pCurEditedEntry = 0;
126 pCurHighlightFrame = 0;
127 pEdit = 0;
128 pAnchor = 0;
129 pDraggedSelection = 0;
130 pPrevDropTarget = 0;
131 pHdlEntry = 0;
132 pHead = NULL;
133 pCursor = NULL;
134 bUpdateMode = TRUE;
135 bEntryEditingEnabled = FALSE;
136 bInDragDrop = FALSE;
137 bHighlightFramePressed = FALSE;
138 eSelectionMode = MULTIPLE_SELECTION;
139 pView = pCurView;
140 pZOrderList = new List; //SvPtrarr;
141 ePositionMode = IcnViewPositionModeFree;
142 SetStyle( nWinStyle );
143 nFlags = 0;
144 nUserEventAdjustScrBars = 0;
145 nUserEventShowCursor = 0;
146 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
147 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
148 pDDRefEntry = 0;
149 pDDDev = 0;
150 pDDBufDev = 0;
151 pDDTempDev = 0;
152 eTextMode = IcnShowTextShort;
153 pImpCursor = new IcnCursor_Impl( this );
154 pGridMap = new IcnGridMap_Impl( this );
156 aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
157 aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
158 Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) );
159 aVerSBar.SetEndScrollHdl( aEndScrollHdl );
160 aHorSBar.SetEndScrollHdl( aEndScrollHdl );
162 nHorSBarHeight = aHorSBar.GetSizePixel().Height();
163 nVerSBarWidth = aVerSBar.GetSizePixel().Width();
165 aEditTimer.SetTimeout( 800 );
166 aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
167 aAutoArrangeTimer.SetTimeout( 100 );
168 aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
169 aCallSelectHdlTimer.SetTimeout( 500 );
170 aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
172 aDocRectChangedTimer.SetTimeout( 50 );
173 aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
174 aVisRectChangedTimer.SetTimeout( 50 );
175 aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
177 Clear( TRUE );
179 SetGrid( Size(100, 70) );
182 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
184 pCurEditedEntry = 0;
185 DELETEZ(pEdit);
186 Clear();
187 StopEditTimer();
188 CancelUserEvents();
189 delete pZOrderList;
190 delete pImpCursor;
191 delete pGridMap;
192 delete pDDDev;
193 delete pDDBufDev;
194 delete pDDTempDev;
195 delete pDraggedSelection;
196 delete pEntryPaintDev;
197 ClearSelectedRectList();
198 ClearColumnList();
201 void SvxIconChoiceCtrl_Impl::Clear( BOOL bInCtor )
203 StopEntryEditing( TRUE );
204 nSelectionCount = 0;
205 DELETEZ(pDraggedSelection);
206 bInDragDrop = FALSE;
207 pCurHighlightFrame = 0;
208 StopEditTimer();
209 CancelUserEvents();
210 ShowCursor( FALSE );
211 bBoundRectsDirty = FALSE;
212 nMaxBoundHeight = 0;
214 nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
215 pCursor = 0;
216 if( !bInCtor )
218 pImpCursor->Clear();
219 pGridMap->Clear();
220 aVirtOutputSize.Width() = 0;
221 aVirtOutputSize.Height() = 0;
222 Size aSize( pView->GetOutputSizePixel() );
223 nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
224 if( nMaxVirtWidth <= 0 )
225 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
226 nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
227 if( nMaxVirtHeight <= 0 )
228 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
229 pZOrderList->Clear(); //Remove(0,pZOrderList->Count());
230 SetOrigin( Point() );
231 if( bUpdateMode )
232 pView->Invalidate(INVALIDATE_NOCHILDREN);
234 AdjustScrollBars();
235 ULONG nCount = aEntries.Count();
236 for( ULONG nCur = 0; nCur < nCount; nCur++ )
238 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
239 delete pCur;
241 aEntries.Clear();
242 DocRectChanged();
243 VisRectChanged();
246 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
248 nWinBits = nWinStyle;
249 nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
250 if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
251 nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
252 if( nWinBits & WB_NOSELECTION )
253 eSelectionMode = NO_SELECTION;
254 if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
255 nWinBits |= WB_ALIGN_LEFT;
256 if( (nWinStyle & WB_DETAILS))
258 if( !pColumns )
259 SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
263 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
265 StopEntryEditing( TRUE );
266 // Pfeil hoch: delta=-1; Pfeil runter: delta=+1
267 Scroll( 0, pScrollBar->GetDelta(), TRUE );
268 bEndScrollInvalidate = TRUE;
269 return 0;
272 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
274 StopEntryEditing( TRUE );
275 // Pfeil links: delta=-1; Pfeil rechts: delta=+1
276 Scroll( pScrollBar->GetDelta(), 0, TRUE );
277 bEndScrollInvalidate = TRUE;
278 return 0;
281 IMPL_LINK( SvxIconChoiceCtrl_Impl, EndScrollHdl, void*, EMPTYARG )
283 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() &&
284 bEndScrollInvalidate )
286 pView->Invalidate(INVALIDATE_NOCHILDREN);
288 return 0;
291 void SvxIconChoiceCtrl_Impl::FontModified()
293 StopEditTimer();
294 DELETEZ(pDDDev);
295 DELETEZ(pDDBufDev);
296 DELETEZ(pDDTempDev);
297 DELETEZ(pEntryPaintDev);
298 SetDefaultTextSize();
299 ShowCursor( FALSE );
300 ShowCursor( TRUE );
303 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, ULONG nPos,
304 const Point* pPos )
306 StopEditTimer();
307 aEntries.Insert( pEntry, nPos );
308 if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.Count() - 1 )
309 pEntry->nPos = aEntries.Count() - 1;
310 else
311 nFlags &= ~F_ENTRYLISTPOS_VALID;
313 pZOrderList->Insert( (void*)pEntry, LIST_APPEND ); //pZOrderList->Count() );
314 pImpCursor->Clear();
315 // pGridMap->Clear();
316 if( pPos )
318 Size aSize( CalcBoundingSize( pEntry ) );
319 SetBoundingRect_Impl( pEntry, *pPos, aSize );
320 SetEntryPos( pEntry, *pPos, FALSE, TRUE, TRUE /*keep grid map*/ );
321 pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED;
322 SetEntriesMoved( TRUE );
324 else
326 // wenn der UpdateMode TRUE ist, wollen wir nicht pauschal alle
327 // BoundRects auf 'zu ueberpruefen' setzen, sondern nur das des
328 // neuen Eintrags. Deshalb kein InvalidateBoundingRect aufrufen!
329 pEntry->aRect.Right() = LONG_MAX;
330 if( bUpdateMode )
332 FindBoundingRect( pEntry );
333 Rectangle aOutputArea( GetOutputRect() );
334 pGridMap->OccupyGrids( pEntry );
335 if( !aOutputArea.IsOver( pEntry->aRect ) )
336 return; // ist nicht sichtbar
337 pView->Invalidate( pEntry->aRect );
339 else
340 InvalidateBoundingRect( pEntry->aRect );
344 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
346 ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
347 if ( !_pGenerator )
349 _pGenerator = new MnemonicGenerator;
350 pAutoDeleteOwnGenerator.reset( _pGenerator );
353 ULONG nEntryCount = GetEntryCount();
354 ULONG i;
356 // insert texts in generator
357 for( i = 0; i < nEntryCount; ++i )
359 DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
361 _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
364 // exchange texts with generated mnemonics
365 for( i = 0; i < nEntryCount; ++i )
367 SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
368 String aTxt = pEntry->GetText();
370 if( _pGenerator->CreateMnemonic( aTxt ) )
371 pEntry->SetText( aTxt );
375 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
377 Point aOrigin( pView->GetMapMode().GetOrigin() );
378 aOrigin *= -1;
379 return Rectangle( aOrigin, aOutputSize );
382 void SvxIconChoiceCtrl_Impl::SetListPositions()
384 if( nFlags & F_ENTRYLISTPOS_VALID )
385 return;
387 ULONG nCount = aEntries.Count();
388 for( ULONG nCur = 0; nCur < nCount; nCur++ )
390 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
391 pEntry->nPos = nCur;
393 nFlags |= F_ENTRYLISTPOS_VALID;
396 void SvxIconChoiceCtrl_Impl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry )
398 BOOL bSyncSingleSelection;
399 // bei Single-Selection wird die Selektion beim Umsetzen des Cursors
400 // mitgefuehrt. Das soll aber nur erfolgen, wenn ueberhaupt ein
401 // Eintrag selektiert ist.
402 if( GetSelectionCount() )
403 bSyncSingleSelection = TRUE;
404 else
405 bSyncSingleSelection = FALSE;
407 if( pEntry == pCurHighlightFrame )
408 pCurHighlightFrame = 0;
410 if( bInDragDrop )
412 DELETEZ(pDraggedSelection);
413 bInDragDrop = FALSE;
416 if( pEntry->IsSelected() )
417 CallSelectHandler( 0 );
419 if( aEntries.Count() == 1 && aEntries.GetObject(0) == pEntry )
421 Clear();
422 return;
425 StopEditTimer();
426 if( pEntry == pAnchor )
427 pAnchor = 0;
428 if( pEntry->IsSelected() )
429 nSelectionCount--;
430 BOOL bEntryBoundValid = IsBoundingRectValid( pEntry->aRect );
431 if( bEntryBoundValid )
432 pView->Invalidate( pEntry->aRect );
434 BOOL bSetNewCursor = FALSE;
435 SvxIconChoiceCtrlEntry* pNewCursor = NULL;
437 if( pEntry == pCursor )
439 bSetNewCursor = TRUE;
440 pNewCursor = FindNewCursor();
441 ShowCursor( FALSE );
442 pCursor = 0;
445 BOOL bCurEntryPosValid = (nFlags & F_ENTRYLISTPOS_VALID) ? TRUE : FALSE;
446 if( bCurEntryPosValid && aEntries.GetObject(aEntries.Count()-1) != pEntry )
447 nFlags &= ~F_ENTRYLISTPOS_VALID;
448 ULONG nPos = pZOrderList->GetPos( (void*)pEntry );
449 pZOrderList->Remove( nPos );
450 if( bCurEntryPosValid )
452 DBG_ASSERT(aEntries.GetObject(pEntry->nPos)==pEntry,"RemoveEntry: Wrong nPos in entry");
453 aEntries.Remove( pEntry->nPos );
455 else
456 aEntries.Remove( pEntry );
457 pImpCursor->Clear();
458 pGridMap->Clear();
459 delete pEntry;
460 if( IsAutoArrange() && aEntries.Count() )
461 aAutoArrangeTimer.Start();
462 if( bSetNewCursor )
464 // Fokusrechteck asynchron einblenden, um das Loeschen einer
465 // Multiselektion zu beschleunigen.
466 SetCursor( pNewCursor, bSyncSingleSelection, TRUE );
470 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, BOOL bSelect,
471 BOOL bCallHdl, BOOL bAdd, BOOL bSyncPaint )
473 if( eSelectionMode == NO_SELECTION )
474 return;
476 if( !bAdd )
478 if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
480 nFlags |= F_CLEARING_SELECTION;
481 DeselectAllBut( pEntry, sal_True );
482 nFlags &= ~F_CLEARING_SELECTION;
485 if( pEntry->IsSelected() != bSelect )
487 pHdlEntry = pEntry;
488 USHORT nEntryFlags = pEntry->GetFlags();
489 if( bSelect )
491 nEntryFlags |= ICNVIEW_FLAG_SELECTED;
492 pEntry->AssignFlags( nEntryFlags );
493 nSelectionCount++;
494 if( bCallHdl )
495 CallSelectHandler( pEntry );
497 else
499 nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
500 pEntry->AssignFlags( nEntryFlags );
501 nSelectionCount--;
502 if( bCallHdl )
503 CallSelectHandler( 0 );
505 EntrySelected( pEntry, bSelect, bSyncPaint );
509 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, BOOL bSelect,
510 BOOL bSyncPaint )
512 // bei SingleSelection dafuer sorgen, dass der Cursor immer
513 // auf dem (einzigen) selektierten Eintrag steht. Aber nur,
514 // wenn es bereits einen Cursor gibt
515 if( bSelect && pCursor &&
516 eSelectionMode == SINGLE_SELECTION &&
517 pEntry != pCursor )
519 SetCursor( pEntry );
520 //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
523 // beim Aufziehen nicht, da sonst die Schleife in SelectRect
524 // nicht richtig funktioniert!
525 if( !(nFlags & F_SELECTING_RECT) )
526 ToTop( pEntry );
527 if( bUpdateMode )
529 if( pEntry == pCursor )
530 ShowCursor( FALSE );
531 if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // beim Tracken immer synchron
532 PaintEntry( pEntry );
533 else if( bSyncPaint ) // synchron & mit virtuellem OutDev!
534 PaintEntryVirtOutDev( pEntry );
535 else
537 pView->Invalidate( CalcFocusRect( pEntry ) );
539 if( pEntry == pCursor )
540 ShowCursor( TRUE );
541 } // if( bUpdateMode )
543 // --> OD 2009-05-27 #i101012#
544 // emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
545 if ( bSelect )
547 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
549 // <--
552 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
554 StopEditTimer();
555 aVirtOutputSize.Width() = 0;
556 aVirtOutputSize.Height() = 0;
557 BOOL bLockedEntryFound = FALSE;
558 const ULONG nCount = aEntries.Count();
559 for( ULONG nCur = 0; nCur < nCount; nCur++ )
561 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
562 pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
563 if( pCur->IsPosLocked() )
565 // VirtSize u.a. anpassen
566 if( !IsBoundingRectValid( pCur->aRect ) )
567 FindBoundingRect( pCur );
568 else
569 AdjustVirtSize( pCur->aRect );
570 bLockedEntryFound = TRUE;
572 else
573 InvalidateBoundingRect( pCur->aRect );
576 if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
578 Size aRealOutputSize( pView->GetOutputSizePixel() );
579 if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
580 aVirtOutputSize.Height() < aRealOutputSize.Height() )
582 ULONG nGridCount = IcnGridMap_Impl::GetGridCount(
583 aRealOutputSize, (USHORT)nGridDX, (USHORT)nGridDY );
584 if( nGridCount < nCount )
586 if( nWinBits & WB_ALIGN_TOP )
587 nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
588 else // WB_ALIGN_LEFT
589 nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
594 pImpCursor->Clear();
595 pGridMap->Clear();
596 VisRectChanged();
599 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
601 long nHeightOffs = 0;
602 long nWidthOffs = 0;
604 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
605 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
607 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
608 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
610 if( nWidthOffs || nHeightOffs )
612 Range aRange;
613 aVirtOutputSize.Width() += nWidthOffs;
614 aRange.Max() = aVirtOutputSize.Width();
615 aHorSBar.SetRange( aRange );
617 aVirtOutputSize.Height() += nHeightOffs;
618 aRange.Max() = aVirtOutputSize.Height();
619 aVerSBar.SetRange( aRange );
621 pImpCursor->Clear();
622 pGridMap->OutputSizeChanged();
623 AdjustScrollBars();
624 DocRectChanged();
628 void SvxIconChoiceCtrl_Impl::InitPredecessors()
630 DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
631 ULONG nCount = aEntries.Count();
632 if( nCount )
634 SvxIconChoiceCtrlEntry* pPrev = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
635 for( ULONG nCur = 1; nCur <= nCount; nCur++ )
637 pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
638 ICNVIEW_FLAG_PRED_SET);
640 SvxIconChoiceCtrlEntry* pNext;
641 if( nCur == nCount )
642 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
643 else
644 pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
645 pPrev->pflink = pNext;
646 pNext->pblink = pPrev;
647 pPrev = pNext;
649 pHead = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
651 else
652 pHead = 0;
653 nFlags &= ~F_MOVED_ENTRIES;
656 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
658 if( pHead )
660 ULONG nCount = aEntries.Count();
661 for( ULONG nCur = 0; nCur < nCount; nCur++ )
663 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
664 pCur->pflink = 0;
665 pCur->pblink = 0;
666 pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
668 pHead = 0;
672 void SvxIconChoiceCtrl_Impl::Arrange( BOOL bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
674 if ( nSetMaxVirtWidth != 0 )
675 nMaxVirtWidth = nSetMaxVirtWidth;
676 else
677 nMaxVirtWidth = aOutputSize.Width();
679 if ( nSetMaxVirtHeight != 0 )
680 nMaxVirtHeight = nSetMaxVirtHeight;
681 else
682 nMaxVirtHeight = aOutputSize.Height();
684 ImpArrange( bKeepPredecessors );
687 void SvxIconChoiceCtrl_Impl::ImpArrange( BOOL bKeepPredecessors )
689 static Point aEmptyPoint;
691 BOOL bOldUpdate = bUpdateMode;
692 Rectangle aCurOutputArea( GetOutputRect() );
693 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
694 bUpdateMode = FALSE;
695 aAutoArrangeTimer.Stop();
696 nFlags &= ~F_MOVED_ENTRIES;
697 nFlags |= F_ARRANGING;
698 StopEditTimer();
699 ShowCursor( FALSE );
700 ResetVirtSize();
701 if( !bKeepPredecessors )
702 ClearPredecessors();
703 bBoundRectsDirty = FALSE;
704 SetOrigin( Point() );
705 VisRectChanged();
706 RecalcAllBoundingRectsSmart();
707 // in der Detailsview muss das Invalidieren intelligenter erfolgen
708 //if( !(nWinBits & WB_DETAILS ))
709 pView->Invalidate( INVALIDATE_NOCHILDREN );
710 nFlags &= ~F_ARRANGING;
711 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
713 MakeVisible( aCurOutputArea );
714 SetUpdateMode( bOldUpdate );
716 ShowCursor( TRUE );
719 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
721 bEndScrollInvalidate = FALSE;
723 #if defined(OV_DRAWGRID)
724 Color aOldColor ( pView->GetLineColor() );
725 Color aColor( COL_BLACK );
726 pView->SetLineColor( aColor );
727 Point aOffs( pView->GetMapMode().GetOrigin());
728 Size aXSize( pView->GetOutputSizePixel() );
731 Point aStart( LROFFS_WINBORDER, 0 );
732 Point aEnd( LROFFS_WINBORDER, aXSize.Height());
733 aStart -= aOffs;
734 aEnd -= aOffs;
735 pView->DrawLine( aStart, aEnd );
738 Point aStart( 0, TBOFFS_WINBORDER );
739 Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
740 aStart -= aOffs;
741 aEnd -= aOffs;
742 pView->DrawLine( aStart, aEnd );
745 for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
747 Point aStart( nDX+LROFFS_WINBORDER, 0 );
748 Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
749 aStart -= aOffs;
750 aEnd -= aOffs;
751 pView->DrawLine( aStart, aEnd );
753 for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
755 Point aStart( 0, nDY+TBOFFS_WINBORDER );
756 Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
757 aStart -= aOffs;
758 aEnd -= aOffs;
759 pView->DrawLine( aStart, aEnd );
761 pView->SetLineColor( aOldColor );
762 #endif
763 nFlags |= F_PAINTED;
765 if( !aEntries.Count() )
766 return;
767 if( !pCursor )
769 // set cursor to item with focus-flag
770 BOOL bfound = FALSE;
771 for ( ULONG i = 0; i < pView->GetEntryCount() && !bfound; i++)
773 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
774 if( pEntry->IsFocused() )
776 pCursor = pEntry;
777 bfound=TRUE;
781 if( !bfound )
782 pCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
785 // Show Focus at Init-Time
786 if ( pView->HasFocus() )
787 GetFocus();
789 ULONG nCount = pZOrderList->Count();
790 if( !nCount )
791 return;
793 BOOL bResetClipRegion = FALSE;
794 if( !pView->IsClipRegion() )
796 Rectangle aOutputArea( GetOutputRect() );
797 bResetClipRegion = TRUE;
798 pView->SetClipRegion( aOutputArea );
801 const USHORT nListInitSize = aEntries.Count() > USHRT_MAX ?
802 USHRT_MAX : (USHORT)aEntries.Count();
803 List* pNewZOrderList = new List( nListInitSize );
804 List* pPaintedEntries = new List( nListInitSize );
806 ULONG nPos = 0;
807 while( nCount )
809 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
810 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
811 if( rRect.IsOver( rBoundRect ) )
813 PaintEntry( pEntry, rBoundRect.TopLeft(), pView, TRUE );
814 // Eintraege, die neu gezeichnet werden, auf Top setzen
815 pPaintedEntries->Insert( pEntry, LIST_APPEND );
817 else
818 pNewZOrderList->Insert( pEntry, LIST_APPEND );
820 nCount--;
821 nPos++;
823 delete pZOrderList;
824 pZOrderList = pNewZOrderList;
825 nCount = pPaintedEntries->Count();
826 if( nCount )
828 for( ULONG nCur = 0; nCur < nCount; nCur++ )
829 pZOrderList->Insert( pPaintedEntries->GetObject(nCur), LIST_APPEND);
831 delete pPaintedEntries;
833 if( bResetClipRegion )
834 pView->SetClipRegion();
837 void SvxIconChoiceCtrl_Impl::RepaintEntries( USHORT nEntryFlagsMask )
839 const ULONG nCount = pZOrderList->Count();
840 if( !nCount )
841 return;
843 BOOL bResetClipRegion = FALSE;
844 Rectangle aOutRect( GetOutputRect() );
845 if( !pView->IsClipRegion() )
847 bResetClipRegion = TRUE;
848 pView->SetClipRegion( aOutRect );
850 for( ULONG nCur = 0; nCur < nCount; nCur++ )
852 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
853 if( pEntry->GetFlags() & nEntryFlagsMask )
855 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
856 if( aOutRect.IsOver( rBoundRect ) )
857 PaintEntry( pEntry, rBoundRect.TopLeft() );
860 if( bResetClipRegion )
861 pView->SetClipRegion();
865 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
867 aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
868 Size aSize( pView->GetOutputSizePixel() );
869 aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
872 IcnViewFieldType SvxIconChoiceCtrl_Impl::GetItem( SvxIconChoiceCtrlEntry* pEntry,
873 const Point& rAbsPos )
875 Rectangle aRect( CalcTextRect( pEntry ) );
876 if( aRect.IsInside( rAbsPos ) )
877 return IcnViewFieldTypeText;
879 aRect = CalcBmpRect( pEntry );
880 if( aRect.IsInside( rAbsPos ) )
881 return IcnViewFieldTypeImage;
883 return IcnViewFieldTypeDontknow;
886 BOOL SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
888 BOOL bHandled = TRUE;
889 bHighlightFramePressed = FALSE;
890 StopEditTimer();
891 BOOL bGotFocus = (BOOL)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
892 if( !(nWinBits & WB_NOPOINTERFOCUS) )
893 pView->GrabFocus();
895 Point aDocPos( rMEvt.GetPosPixel() );
896 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
897 return FALSE;
898 ToDocPos( aDocPos );
899 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, TRUE );
900 if( pEntry )
901 MakeEntryVisible( pEntry, FALSE );
903 if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
905 if( pEntry )
906 SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), TRUE);
907 return TRUE;
910 if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // Tastaturselektion?
912 DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
913 if( rMEvt.IsMod1() )
914 nFlags |= F_ADD_MODE;
916 if( rMEvt.IsShift() )
918 Rectangle aRect( GetEntryBoundRect( pAnchor ));
919 if( pEntry )
920 aRect.Union( GetEntryBoundRect( pEntry ) );
921 else
923 Rectangle aTempRect( aDocPos, Size(1,1));
924 aRect.Union( aTempRect );
926 aCurSelectionRect = aRect;
927 SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
929 else if( rMEvt.IsMod1() )
931 AddSelectedRect( aCurSelectionRect );
932 pAnchor = 0;
933 aCurSelectionRect.SetPos( aDocPos );
936 if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
937 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
938 return TRUE;
940 else
942 if( !pEntry )
944 if( eSelectionMode == MULTIPLE_SELECTION )
946 if( !rMEvt.IsMod1() ) // Ctrl
948 if( !bGotFocus )
950 SetNoSelection();
951 ClearSelectedRectList();
954 else
955 nFlags |= F_ADD_MODE;
956 aCurSelectionRect.SetPos( aDocPos );
957 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
959 else
960 bHandled = FALSE;
961 return bHandled;
964 BOOL bSelected = pEntry->IsSelected();
965 BOOL bEditingEnabled = IsEntryEditingEnabled();
967 if( rMEvt.GetClicks() == 2 )
969 DeselectAllBut( pEntry );
970 SelectEntry( pEntry, TRUE, TRUE, FALSE, TRUE );
971 pHdlEntry = pEntry;
972 pView->ClickIcon();
974 else
976 // Inplace-Editing ?
977 if( rMEvt.IsMod2() ) // Alt?
979 if( bEntryEditingEnabled && pEntry &&
980 pEntry->IsSelected())
982 if( pView->EditingEntry( pEntry ))
983 EditEntry( pEntry );
986 else if( eSelectionMode == SINGLE_SELECTION )
988 DeselectAllBut( pEntry );
989 SetCursor( pEntry );
990 if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
991 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
993 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
996 else if( eSelectionMode == NO_SELECTION )
998 if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
1000 pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
1001 bHighlightFramePressed = TRUE;
1002 SetEntryHighlightFrame( pEntry, TRUE );
1005 else
1007 if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
1009 if( !bSelected )
1011 DeselectAllBut( pEntry, TRUE /* Synchron painten */ );
1012 SetCursor( pEntry );
1013 SelectEntry( pEntry, TRUE, TRUE, FALSE, TRUE );
1015 else
1017 // erst im Up deselektieren, falls Move per D&D!
1018 nFlags |= F_DOWN_DESELECT;
1019 if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
1020 rMEvt.IsLeft())
1022 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1026 else if( rMEvt.IsMod1() )
1027 nFlags |= F_DOWN_CTRL;
1030 return bHandled;
1033 BOOL SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
1035 BOOL bHandled = FALSE;
1036 if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
1038 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1039 bHandled = TRUE;
1042 Point aDocPos( rMEvt.GetPosPixel() );
1043 ToDocPos( aDocPos );
1044 SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
1045 if( pDocEntry )
1047 if( nFlags & F_DOWN_CTRL )
1049 // Ctrl & MultiSelection
1050 ToggleSelection( pDocEntry );
1051 SetCursor( pDocEntry );
1052 bHandled = TRUE;
1054 else if( nFlags & F_DOWN_DESELECT )
1056 DeselectAllBut( pDocEntry );
1057 SetCursor( pDocEntry );
1058 SelectEntry( pDocEntry, TRUE, TRUE, FALSE, TRUE );
1059 bHandled = TRUE;
1063 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1064 if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
1066 bHandled = TRUE;
1067 StartEditTimer();
1068 nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
1071 if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
1073 bHandled = TRUE;
1074 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
1075 pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
1076 bHighlightFramePressed = FALSE;
1077 SetEntryHighlightFrame( pEntry, TRUE );
1078 #if 0
1079 CallSelectHandler( pCurHighlightFrame );
1080 #else
1081 pHdlEntry = pCurHighlightFrame;
1082 pView->ClickIcon();
1084 // set focus on Icon
1085 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1086 SetCursor_Impl( pOldCursor, pHdlEntry, FALSE, FALSE, TRUE );
1087 #endif
1088 pHdlEntry = 0;
1090 return bHandled;
1093 BOOL SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
1095 const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
1097 if( pView->IsTracking() )
1098 return FALSE;
1099 else if( nWinBits & WB_HIGHLIGHTFRAME )
1101 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, TRUE );
1102 SetEntryHighlightFrame( pEntry );
1104 else
1105 return FALSE;
1106 return TRUE;
1109 void SvxIconChoiceCtrl_Impl::Tracking( const TrackingEvent& rTEvt )
1111 if ( rTEvt.IsTrackingEnded() )
1113 // Das Rechteck darf nicht "justified" sein, da seine
1114 // TopLeft-Position u.U. zur Berechnung eines Ankers
1115 // benutzt wird.
1116 AddSelectedRect( aCurSelectionRect );
1117 pView->HideTracking();
1118 nFlags &= ~(F_ADD_MODE);
1119 if( rTEvt.IsTrackingCanceled() )
1120 SetNoSelection();
1122 else
1124 Point aPosPixel = rTEvt.GetMouseEvent().GetPosPixel();
1125 Point aDocPos( aPosPixel );
1126 ToDocPos( aDocPos );
1128 long nScrollDX, nScrollDY;
1130 CalcScrollOffsets( aPosPixel, nScrollDX, nScrollDY, FALSE );
1131 if( nScrollDX || nScrollDY )
1133 pView->HideTracking();
1134 pView->Scroll( nScrollDX, nScrollDY );
1136 Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
1137 if( aRect != aCurSelectionRect )
1139 pView->HideTracking();
1140 BOOL bAdd = (nFlags & F_ADD_MODE) ? TRUE : FALSE;
1141 SelectRect( aRect, bAdd, &aSelectedRectList );
1143 pView->ShowTracking( aRect, SHOWTRACK_SMALL | SHOWTRACK_CLIP );
1147 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
1148 SvxIconChoiceCtrlEntry* pNewCursor, BOOL bMod1, BOOL bShift, BOOL bPaintSync )
1150 if( pNewCursor )
1152 SvxIconChoiceCtrlEntry* pFilterEntry = 0;
1153 BOOL bDeselectAll = FALSE;
1154 if( eSelectionMode != SINGLE_SELECTION )
1156 if( !bMod1 && !bShift )
1157 bDeselectAll = TRUE;
1158 else if( bShift && !bMod1 && !pAnchor )
1160 bDeselectAll = TRUE;
1161 pFilterEntry = pOldCursor;
1164 if( bDeselectAll )
1165 DeselectAllBut( pFilterEntry, bPaintSync );
1166 ShowCursor( FALSE );
1167 MakeEntryVisible( pNewCursor );
1168 SetCursor( pNewCursor );
1169 if( bMod1 && !bShift )
1171 if( pAnchor )
1173 AddSelectedRect( pAnchor, pOldCursor );
1174 pAnchor = 0;
1177 else if( bShift )
1179 if( !pAnchor )
1180 pAnchor = pOldCursor;
1181 if ( nWinBits & WB_ALIGN_LEFT )
1182 SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
1183 else
1184 SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
1186 else
1188 SelectEntry( pCursor, TRUE, TRUE, FALSE, bPaintSync );
1189 aCurSelectionRect = GetEntryBoundRect( pCursor );
1194 BOOL SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1196 StopEditTimer();
1198 BOOL bMod2 = rKEvt.GetKeyCode().IsMod2();
1199 sal_Unicode cChar = rKEvt.GetCharCode();
1200 ULONG nPos = (ULONG)-1;
1201 if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1203 // shortcut is clicked
1204 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1205 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1206 if ( pNewCursor != pOldCursor )
1207 SetCursor_Impl( pOldCursor, pNewCursor, FALSE, FALSE, FALSE );
1208 return TRUE;
1211 if ( bMod2 )
1212 // no actions with <ALT>
1213 return FALSE;
1215 BOOL bKeyUsed = TRUE;
1216 BOOL bMod1 = rKEvt.GetKeyCode().IsMod1();
1217 BOOL bShift = rKEvt.GetKeyCode().IsShift();
1219 if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1221 bShift = FALSE;
1222 bMod1 = FALSE;
1225 if( bMod1 )
1226 nFlags |= F_ADD_MODE;
1227 BOOL bDeselectAll = FALSE;
1228 if( eSelectionMode != SINGLE_SELECTION )
1230 if( !bMod1 && !bShift )
1231 bDeselectAll = TRUE;
1232 if( bShift && !bMod1 && !pAnchor )
1233 bDeselectAll = TRUE;
1236 SvxIconChoiceCtrlEntry* pNewCursor;
1237 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1239 USHORT nCode = rKEvt.GetKeyCode().GetCode();
1240 switch( nCode )
1242 case KEY_UP:
1243 case KEY_PAGEUP:
1244 if( pCursor )
1246 MakeEntryVisible( pCursor );
1247 if( nCode == KEY_UP )
1248 pNewCursor = pImpCursor->GoUpDown(pCursor,FALSE);
1249 else
1250 pNewCursor = pImpCursor->GoPageUpDown(pCursor,FALSE);
1251 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1252 if( !pNewCursor )
1254 Rectangle aRect( GetEntryBoundRect( pCursor ) );
1255 if( aRect.Top())
1257 aRect.Bottom() -= aRect.Top();
1258 aRect.Top() = 0;
1259 MakeVisible( aRect );
1263 if ( bChooseWithCursor && pNewCursor != NULL )
1265 pHdlEntry = pNewCursor;//GetCurEntry();
1266 pCurHighlightFrame = pHdlEntry;
1267 pView->ClickIcon();
1268 pCurHighlightFrame = NULL;
1271 break;
1273 case KEY_DOWN:
1274 case KEY_PAGEDOWN:
1275 if( pCursor )
1277 if( nCode == KEY_DOWN )
1278 pNewCursor=pImpCursor->GoUpDown( pCursor,TRUE );
1279 else
1280 pNewCursor=pImpCursor->GoPageUpDown( pCursor,TRUE );
1281 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1283 if ( bChooseWithCursor && pNewCursor != NULL)
1285 pHdlEntry = pNewCursor;//GetCurEntry();
1286 pCurHighlightFrame = pHdlEntry;
1287 pView->ClickIcon();
1288 pCurHighlightFrame = NULL;
1291 break;
1293 case KEY_RIGHT:
1294 if( pCursor )
1296 pNewCursor=pImpCursor->GoLeftRight(pCursor,TRUE );
1297 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1299 break;
1301 case KEY_LEFT:
1302 if( pCursor )
1304 MakeEntryVisible( pCursor );
1305 pNewCursor = pImpCursor->GoLeftRight(pCursor,FALSE );
1306 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1307 if( !pNewCursor )
1309 Rectangle aRect( GetEntryBoundRect(pCursor));
1310 if( aRect.Left() )
1312 aRect.Right() -= aRect.Left();
1313 aRect.Left() = 0;
1314 MakeVisible( aRect );
1318 break;
1320 // wird vom VCL-Tracking gesteuert
1321 #if 0
1322 case KEY_ESCAPE:
1323 if( pView->IsTracking() )
1325 HideSelectionRect();
1326 //SelectAll( FALSE );
1327 SetNoSelection();
1328 ClearSelectedRectList();
1329 nFlags &= ~F_TRACKING;
1331 else
1332 bKeyUsed = FALSE;
1333 break;
1334 #endif
1337 case KEY_F2:
1338 if( !bMod1 && !bShift )
1339 EditTimeoutHdl( 0 );
1340 else
1341 bKeyUsed = FALSE;
1342 break;
1344 case KEY_F8:
1345 if( rKEvt.GetKeyCode().IsShift() )
1347 if( nFlags & F_ADD_MODE )
1348 nFlags &= (~F_ADD_MODE);
1349 else
1350 nFlags |= F_ADD_MODE;
1352 else
1353 bKeyUsed = FALSE;
1354 break;
1356 case KEY_SPACE:
1357 if( pCursor && eSelectionMode != SINGLE_SELECTION )
1359 if( !bMod1 )
1361 //SelectAll( FALSE );
1362 SetNoSelection();
1363 ClearSelectedRectList();
1365 // click Icon with spacebar
1366 SetEntryHighlightFrame( GetCurEntry(), TRUE );
1367 pView->ClickIcon();
1368 pHdlEntry = pCurHighlightFrame;
1369 pCurHighlightFrame=0;
1371 else
1372 ToggleSelection( pCursor );
1374 break;
1376 #ifdef DBG_UTIL
1377 case KEY_F10:
1378 if( rKEvt.GetKeyCode().IsShift() )
1380 if( pCursor )
1381 pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1383 if( rKEvt.GetKeyCode().IsMod1() )
1385 if( pCursor )
1386 pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1388 break;
1389 #endif
1391 case KEY_ADD:
1392 case KEY_DIVIDE :
1393 case KEY_A:
1394 if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1395 SelectAll( TRUE );
1396 else
1397 bKeyUsed = FALSE;
1398 break;
1400 case KEY_SUBTRACT:
1401 case KEY_COMMA :
1402 if( bMod1 )
1403 SetNoSelection();
1404 else
1405 bKeyUsed = FALSE;
1406 break;
1408 case KEY_RETURN:
1409 if( bMod1 )
1411 if( pCursor && bEntryEditingEnabled )
1412 /*pView->*/EditEntry( pCursor );
1414 else
1415 bKeyUsed = FALSE;
1416 break;
1418 case KEY_END:
1419 if( pCursor )
1421 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 );
1422 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1424 break;
1426 case KEY_HOME:
1427 if( pCursor )
1429 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
1430 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, TRUE );
1432 break;
1434 default:
1435 bKeyUsed = FALSE;
1438 return bKeyUsed;
1441 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
1442 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1444 // hor scrollbar
1445 Point aPos( 0, nRealHeight );
1446 aPos.Y() -= nHorSBarHeight;
1448 if( aHorSBar.GetPosPixel() != aPos )
1449 aHorSBar.SetPosPixel( aPos );
1451 // ver scrollbar
1452 aPos.X() = nRealWidth; aPos.Y() = 0;
1453 aPos.X() -= nVerSBarWidth;
1454 aPos.X()++;
1455 aPos.Y()--;
1457 if( aVerSBar.GetPosPixel() != aPos )
1458 aVerSBar.SetPosPixel( aPos );
1461 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( BOOL )
1463 Rectangle aOldOutRect( GetOutputRect() );
1464 long nVirtHeight = aVirtOutputSize.Height();
1465 long nVirtWidth = aVirtOutputSize.Width();
1467 Size aOSize( pView->Control::GetOutputSizePixel() );
1468 long nRealHeight = aOSize.Height();
1469 long nRealWidth = aOSize.Width();
1471 PositionScrollBars( nRealWidth, nRealHeight );
1473 const MapMode& rMapMode = pView->GetMapMode();
1474 Point aOrigin( rMapMode.GetOrigin() );
1476 long nVisibleWidth;
1477 if( nRealWidth > nVirtWidth )
1478 nVisibleWidth = nVirtWidth + aOrigin.X();
1479 else
1480 nVisibleWidth = nRealWidth;
1482 long nVisibleHeight;
1483 if( nRealHeight > nVirtHeight )
1484 nVisibleHeight = nVirtHeight + aOrigin.Y();
1485 else
1486 nVisibleHeight = nRealHeight;
1488 sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1489 sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1490 sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1491 sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1493 USHORT nResult = 0;
1494 if( nVirtHeight )
1496 // activate ver scrollbar ?
1497 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1499 nResult = 0x0001;
1500 nRealWidth -= nVerSBarWidth;
1502 if( nRealWidth > nVirtWidth )
1503 nVisibleWidth = nVirtWidth + aOrigin.X();
1504 else
1505 nVisibleWidth = nRealWidth;
1507 nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1509 // activate hor scrollbar ?
1510 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1512 nResult |= 0x0002;
1513 nRealHeight -= nHorSBarHeight;
1515 if( nRealHeight > nVirtHeight )
1516 nVisibleHeight = nVirtHeight + aOrigin.Y();
1517 else
1518 nVisibleHeight = nRealHeight;
1520 // brauchen wir jetzt doch eine senkrechte Scrollbar ?
1521 if( !(nResult & 0x0001) && // nur wenn nicht schon da
1522 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1524 nResult = 3; // beide sind an
1525 nRealWidth -= nVerSBarWidth;
1527 if( nRealWidth > nVirtWidth )
1528 nVisibleWidth = nVirtWidth + aOrigin.X();
1529 else
1530 nVisibleWidth = nRealWidth;
1532 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1537 // size ver scrollbar
1538 long nThumb = aVerSBar.GetThumbPos();
1539 Size aSize( nVerSBarWidth, nRealHeight );
1540 aSize.Height() += 2;
1541 if( aSize != aVerSBar.GetSizePixel() )
1542 aVerSBar.SetSizePixel( aSize );
1543 aVerSBar.SetVisibleSize( nVisibleHeight );
1544 aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1546 if( nResult & 0x0001 )
1548 aVerSBar.SetThumbPos( nThumb );
1549 aVerSBar.Show();
1551 else
1553 aVerSBar.SetThumbPos( 0 );
1554 aVerSBar.Hide();
1557 // size hor scrollbar
1558 nThumb = aHorSBar.GetThumbPos();
1559 aSize.Width() = nRealWidth;
1560 aSize.Height() = nHorSBarHeight;
1561 aSize.Width()++;
1562 if( nResult & 0x0001 ) // vertikale Scrollbar ?
1564 aSize.Width()++;
1565 nRealWidth++;
1567 if( aSize != aHorSBar.GetSizePixel() )
1568 aHorSBar.SetSizePixel( aSize );
1569 aHorSBar.SetVisibleSize( nVisibleWidth );
1570 aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1571 if( nResult & 0x0002 )
1573 aHorSBar.SetThumbPos( nThumb );
1574 aHorSBar.Show();
1576 else
1578 aHorSBar.SetThumbPos( 0 );
1579 aHorSBar.Hide();
1582 aOutputSize.Width() = nRealWidth;
1583 if( nResult & 0x0002 ) // hor scrollbar ?
1584 nRealHeight++; // weil unterer Rand geclippt wird
1585 aOutputSize.Height() = nRealHeight;
1587 Rectangle aNewOutRect( GetOutputRect() );
1588 if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1590 Wallpaper aPaper( pView->GetBackground() );
1591 aPaper.SetRect( aNewOutRect );
1592 pView->SetBackground( aPaper );
1595 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1596 aScrBarBox.Show();
1597 else
1598 aScrBarBox.Hide();
1601 void SvxIconChoiceCtrl_Impl::Resize()
1603 StopEditTimer();
1604 InitScrollBarBox();
1605 aOutputSize = pView->GetOutputSizePixel();
1606 pImpCursor->Clear();
1607 pGridMap->OutputSizeChanged();
1609 const Size& rSize = pView->Control::GetOutputSizePixel();
1610 PositionScrollBars( rSize.Width(), rSize.Height() );
1611 // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1612 // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1613 // die ScrollBars aufblitzen
1614 // Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden,
1615 // zumindest, solange es nur einen EventTypen gibt
1616 if ( ! nUserEventAdjustScrBars )
1617 nUserEventAdjustScrBars =
1618 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1619 EVENTID_ADJUST_SCROLLBARS);
1621 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1623 Rectangle aRect( GetOutputRect());
1624 Wallpaper aPaper( pView->GetBackground() );
1625 aPaper.SetRect( aRect );
1626 pView->SetBackground( aPaper );
1628 VisRectChanged();
1631 BOOL SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1633 if( !pZOrderList || !aHorSBar.IsVisible() )
1634 return FALSE;
1635 const MapMode& rMapMode = pView->GetMapMode();
1636 Point aOrigin( rMapMode.GetOrigin() );
1637 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1639 long nWidth = aOutputSize.Width();
1640 const ULONG nCount = pZOrderList->Count();
1641 long nMostRight = 0;
1642 for( ULONG nCur = 0; nCur < nCount; nCur++ )
1644 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1645 long nRight = GetEntryBoundRect(pEntry).Right();
1646 if( nRight > nWidth )
1647 return FALSE;
1648 if( nRight > nMostRight )
1649 nMostRight = nRight;
1651 aHorSBar.Hide();
1652 aOutputSize.Height() += nHorSBarHeight;
1653 aVirtOutputSize.Width() = nMostRight;
1654 aHorSBar.SetThumbPos( 0 );
1655 Range aRange;
1656 aRange.Max() = nMostRight - 1;
1657 aHorSBar.SetRange( aRange );
1658 if( aVerSBar.IsVisible() )
1660 Size aSize( aVerSBar.GetSizePixel());
1661 aSize.Height() += nHorSBarHeight;
1662 aVerSBar.SetSizePixel( aSize );
1664 return TRUE;
1666 return FALSE;
1669 BOOL SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1671 if( !pZOrderList || !aVerSBar.IsVisible() )
1672 return FALSE;
1673 const MapMode& rMapMode = pView->GetMapMode();
1674 Point aOrigin( rMapMode.GetOrigin() );
1675 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1677 long nDeepest = 0;
1678 long nHeight = aOutputSize.Height();
1679 const ULONG nCount = pZOrderList->Count();
1680 for( ULONG nCur = 0; nCur < nCount; nCur++ )
1682 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1683 long nBottom = GetEntryBoundRect(pEntry).Bottom();
1684 if( nBottom > nHeight )
1685 return FALSE;
1686 if( nBottom > nDeepest )
1687 nDeepest = nBottom;
1689 aVerSBar.Hide();
1690 aOutputSize.Width() += nVerSBarWidth;
1691 aVirtOutputSize.Height() = nDeepest;
1692 aVerSBar.SetThumbPos( 0 );
1693 Range aRange;
1694 aRange.Max() = nDeepest - 1;
1695 aVerSBar.SetRange( aRange );
1696 if( aHorSBar.IsVisible() )
1698 Size aSize( aHorSBar.GetSizePixel());
1699 aSize.Width() += nVerSBarWidth;
1700 aHorSBar.SetSizePixel( aSize );
1702 return TRUE;
1704 return FALSE;
1708 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1709 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1711 CheckVerScrollBar();
1712 if( CheckHorScrollBar() )
1713 CheckVerScrollBar();
1714 if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1715 aScrBarBox.Show();
1716 else
1717 aScrBarBox.Hide();
1721 void SvxIconChoiceCtrl_Impl::GetFocus()
1723 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1724 if( pCursor )
1726 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1727 ShowCursor( TRUE );
1731 void SvxIconChoiceCtrl_Impl::LoseFocus()
1733 StopEditTimer();
1734 if( pCursor )
1735 pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1736 ShowCursor( FALSE );
1738 // HideFocus ();
1739 // pView->Invalidate ( aFocus.aRect );
1741 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1744 void SvxIconChoiceCtrl_Impl::SetUpdateMode( BOOL bUpdate )
1746 if( bUpdate != bUpdateMode )
1748 bUpdateMode = bUpdate;
1749 if( bUpdate )
1751 AdjustScrollBars();
1752 pImpCursor->Clear();
1753 pGridMap->Clear();
1754 pView->Invalidate(INVALIDATE_NOCHILDREN);
1759 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, BOOL bIsBackgroundPainted )
1761 Point aPos( GetEntryPos( pEntry ) );
1762 PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1765 // Prios der Emphasis: bDropTarget => bCursored => bSelected
1766 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1767 const Rectangle& rTextRect, const Rectangle& rImageRect,
1768 BOOL bSelected, BOOL bDropTarget, BOOL bCursored, OutputDevice* pOut,
1769 BOOL bIsBackgroundPainted )
1771 static Color aTransparent( COL_TRANSPARENT );
1773 if( !pOut )
1774 pOut = pView;
1776 #ifdef OV_CHECK_EMPH_RECTS
1778 Color aXOld( pOut->GetFillColor() );
1779 pOut->SetFillColor( Color( COL_GREEN ));
1780 pOut->DrawRect( rTextRect );
1781 pOut->DrawRect( rImageRect );
1782 pOut->SetFillColor( aXOld );
1784 #endif
1786 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1787 Color aOldFillColor( pOut->GetFillColor() );
1789 BOOL bSolidTextRect = FALSE;
1790 BOOL bSolidImageRect = FALSE;
1792 if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1794 pOut->SetFillColor( rSettings.GetHighlightColor() );
1795 bSolidTextRect = TRUE;
1796 bSolidImageRect = TRUE;
1798 else
1800 if ( !bSelected || bCursored )
1802 if( !pView->HasFontFillColor() )
1803 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1804 else
1806 const Color& rFillColor = pView->GetFont().GetFillColor();
1807 pOut->SetFillColor( rFillColor );
1808 if( rFillColor != aTransparent )
1809 bSolidTextRect = TRUE;
1814 // Textrechteck zeichnen
1815 if( !bSolidTextRect )
1817 if( !bIsBackgroundPainted )
1818 pOut->Erase( rTextRect );
1820 else
1822 Color aOldLineColor;
1823 if( bCursored )
1825 aOldLineColor = pOut->GetLineColor();
1826 pOut->SetLineColor( Color( COL_GRAY ) );
1828 pOut->DrawRect( rTextRect );
1829 if( bCursored )
1830 pOut->SetLineColor( aOldLineColor );
1833 // Bildrechteck zeichnen
1834 if( !bSolidImageRect )
1836 if( !bIsBackgroundPainted )
1837 pOut->Erase( rImageRect );
1839 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden
1840 // (in der virtuellen Funktion DrawEntryImage)
1841 // else
1842 // pOut->DrawRect( rImageRect );
1844 pOut->SetFillColor( aOldFillColor );
1848 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1849 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, USHORT nPaintFlags,
1850 OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1852 if( eItem == IcnViewFieldTypeText )
1854 String aText;
1855 if( !pStr )
1856 aText = pView->GetEntryText( pEntry, FALSE );
1857 else
1858 aText = *pStr;
1860 if ( _pLayoutData )
1862 pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1863 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1865 else
1867 Color aOldFontColor = pOut->GetTextColor();
1868 if ( pView->AutoFontColor() )
1870 Color aBkgColor( pOut->GetBackground().GetColor() );
1871 Color aFontColor;
1872 USHORT nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1873 if ( nColor > 127 )
1874 aFontColor.SetColor ( COL_BLACK );
1875 else
1876 aFontColor.SetColor( COL_WHITE );
1877 pOut->SetTextColor( aFontColor );
1880 pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1882 if ( pView->AutoFontColor() )
1883 pOut->SetTextColor( aOldFontColor );
1885 if( pEntry->IsFocused() )
1887 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1888 /*pView->*/ShowFocus( aRect );
1889 DrawFocusRect( pOut );
1893 else
1895 Point aPos( rRect.TopLeft() );
1896 if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1897 aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1898 if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1899 aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1900 pView->DrawEntryImage( pEntry, aPos, *pOut );
1904 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1906 #ifdef OV_NO_VIRT_OUTDEV
1907 PaintEntry( pEntry );
1908 #else
1909 if( !pEntryPaintDev )
1911 pEntryPaintDev = new VirtualDevice( *pView );
1912 pEntryPaintDev->SetFont( pView->GetFont() );
1913 pEntryPaintDev->SetLineColor();
1914 //pEntryPaintDev->SetBackground( pView->GetBackground() );
1916 const Rectangle& rRect = GetEntryBoundRect( pEntry );
1917 Rectangle aOutRect( GetOutputRect() );
1918 if( !rRect.IsOver( aOutRect ) )
1919 return;
1920 Wallpaper aPaper( pView->GetBackground() );
1921 Rectangle aRect( aPaper.GetRect() );
1923 // Rechteck verschieben, so dass das Boundrect des Entries im
1924 // VirtOut-Dev bei 0,0 liegt.
1925 aRect.Move( -rRect.Left(), -rRect.Top() );
1926 aPaper.SetRect( aRect );
1927 pEntryPaintDev->SetBackground( aPaper );
1928 pEntryPaintDev->SetFont( pView->GetFont() );
1929 Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) );
1932 Size aSize( rRect.GetSize() );
1933 pEntryPaintDev->SetOutputSizePixel( aSize );
1934 pEntryPaintDev->DrawOutDev(
1935 Point(), aSize, rRect.TopLeft(), aSize, *pView );
1937 PaintEntry( pEntry, Point(), pEntryPaintDev );
1939 pView->DrawOutDev(
1940 rRect.TopLeft(),
1941 aSize,
1942 Point(),
1943 aSize,
1944 *pEntryPaintDev );
1945 #endif
1949 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1950 OutputDevice* pOut, BOOL bIsBackgroundPainted )
1952 if( !pOut )
1953 pOut = pView;
1955 BOOL bSelected = FALSE;
1957 if( eSelectionMode != NO_SELECTION )
1958 bSelected = pEntry->IsSelected();
1960 BOOL bCursored = pEntry->IsCursored();
1961 BOOL bDropTarget = pEntry->IsDropTarget();
1962 BOOL bNoEmphasis = pEntry->IsBlockingEmphasis();
1964 Font aTempFont( pOut->GetFont() );
1966 // AutoFontColor
1968 if ( pView->AutoFontColor() )
1970 aTempFont.SetColor ( aFontColor );
1974 String aEntryText( pView->GetEntryText( pEntry, FALSE ) );
1975 Rectangle aTextRect( CalcTextRect(pEntry,&rPos,FALSE,&aEntryText));
1976 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1978 sal_Bool bShowSelection =
1979 ( ( ( bSelected && !bCursored )
1980 || bDropTarget
1982 && !bNoEmphasis
1983 && ( eSelectionMode != NO_SELECTION )
1985 sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1987 if ( bShowSelection )
1989 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1990 Font aNewFont( aTempFont );
1992 // bei hart attributierter Font-Fuellcolor muessen wir diese
1993 // hart auf die Highlight-Color setzen
1994 if( pView->HasFontFillColor() )
1996 if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1997 aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1998 else
1999 aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
2002 Color aWinCol = rSettings.GetWindowTextColor();
2003 if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
2004 aNewFont.SetColor( rSettings.GetWindowTextColor() );
2005 else
2006 aNewFont.SetColor( rSettings.GetHighlightTextColor() );
2008 pOut->SetFont( aNewFont );
2010 pOut->SetFillColor( pOut->GetBackground().GetColor() );
2011 pOut->DrawRect( CalcFocusRect( pEntry ) );
2012 pOut->SetFillColor( );
2015 BOOL bResetClipRegion = FALSE;
2016 if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
2018 Rectangle aOutputArea( GetOutputRect() );
2019 if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
2021 pView->SetClipRegion( aOutputArea );
2022 bResetClipRegion = TRUE;
2026 #ifdef OV_DRAWBOUNDRECT
2028 Color aXOldColor = pOut->GetLineColor();
2029 pOut->SetLineColor( Color( COL_LIGHTRED ) );
2030 Rectangle aXRect( pEntry->aRect );
2031 aXRect.SetPos( rPos );
2032 pOut->DrawRect( aXRect );
2033 pOut->SetLineColor( aXOldColor );
2035 #endif
2037 sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
2038 USHORT nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
2039 if ( bLargeIconMode )
2040 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
2041 USHORT nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
2043 if( !bNoEmphasis )
2044 PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
2046 if ( bShowSelection )
2047 pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
2048 bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
2050 PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
2052 PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
2053 nTextPaintFlags, pOut );
2055 // Highlight-Frame zeichnen
2056 if( pEntry == pCurHighlightFrame && !bNoEmphasis )
2057 DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), FALSE );
2059 pOut->SetFont( aTempFont );
2060 if( bResetClipRegion )
2061 pView->SetClipRegion();
2064 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2065 BOOL bAdjustAtGrid, BOOL bCheckScrollBars, BOOL bKeepGridMap )
2067 ShowCursor( FALSE );
2068 Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
2069 pView->Invalidate( aBoundRect );
2070 ToTop( pEntry );
2071 if( !IsAutoArrange() )
2073 BOOL bAdjustVirtSize = FALSE;
2074 if( rPos != aBoundRect.TopLeft() )
2076 Point aGridOffs(
2077 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
2078 pImpCursor->Clear();
2079 if( !bKeepGridMap )
2080 pGridMap->Clear();
2081 aBoundRect.SetPos( rPos );
2082 pEntry->aRect = aBoundRect;
2083 pEntry->aGridRect.SetPos( rPos + aGridOffs );
2084 bAdjustVirtSize = TRUE;
2086 if( bAdjustAtGrid )
2088 if( bAdjustVirtSize )
2090 // Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags,
2091 // kann er wieder komplett
2092 // in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar
2093 // eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der
2094 // Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen
2095 // Ausgabegroesse bereits das ausgerichtete Boundrect des
2096 // Eintrags genommen. Die virtuelle Groesse muss angepasst werden,
2097 // da AdjustEntryAtGrid von ihr abhaengt.
2098 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
2099 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
2100 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
2101 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
2102 AdjustVirtSize( aNewBoundRect );
2103 bAdjustVirtSize = FALSE;
2105 AdjustEntryAtGrid( pEntry );
2106 ToTop( pEntry );
2108 if( bAdjustVirtSize )
2109 AdjustVirtSize( pEntry->aRect );
2111 if( bCheckScrollBars && bUpdateMode )
2112 CheckScrollBars();
2114 pView->Invalidate( pEntry->aRect );
2115 pGridMap->OccupyGrids( pEntry );
2117 else
2119 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
2120 SetEntryPredecessor( pEntry, pPrev );
2121 aAutoArrangeTimer.Start();
2123 ShowCursor( TRUE );
2126 void SvxIconChoiceCtrl_Impl::SetNoSelection()
2128 // rekursive Aufrufe ueber SelectEntry abblocken
2129 if( !(nFlags & F_CLEARING_SELECTION ))
2131 nFlags |= F_CLEARING_SELECTION;
2132 DeselectAllBut( 0, TRUE );
2133 nFlags &= ~F_CLEARING_SELECTION;
2137 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, BOOL bHit )
2139 CheckBoundingRects();
2140 // Z-Order-Liste vom Ende her absuchen
2141 ULONG nCount = pZOrderList->Count();
2142 while( nCount )
2144 nCount--;
2145 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount));
2146 if( pEntry->aRect.IsInside( rDocPos ) )
2148 if( bHit )
2150 Rectangle aRect = CalcBmpRect( pEntry );
2151 aRect.Top() -= 3;
2152 aRect.Bottom() += 3;
2153 aRect.Left() -= 3;
2154 aRect.Right() += 3;
2155 if( aRect.IsInside( rDocPos ) )
2156 return pEntry;
2157 aRect = CalcTextRect( pEntry );
2158 if( aRect.IsInside( rDocPos ) )
2159 return pEntry;
2161 else
2162 return pEntry;
2165 return 0;
2168 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2170 CheckBoundingRects();
2171 SvxIconChoiceCtrlEntry* pTarget = 0;
2172 const ULONG nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2173 if( nStartPos != LIST_ENTRY_NOTFOUND )
2175 const ULONG nCount = pZOrderList->Count();
2176 for( ULONG nCur = nStartPos+1; nCur < nCount; nCur++ )
2178 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
2179 if( pEntry->aRect.IsInside( rDocPos ) )
2181 pTarget = pEntry;
2182 break;
2186 return pTarget;
2189 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2191 CheckBoundingRects();
2192 SvxIconChoiceCtrlEntry* pTarget = 0;
2193 ULONG nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2194 if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 )
2196 nStartPos--;
2199 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos));
2200 if( pEntry->aRect.IsInside( rDocPos ) )
2202 pTarget = pEntry;
2203 break;
2205 } while( nStartPos > 0 );
2207 return pTarget;
2210 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
2212 return pEntry->aRect.TopLeft();
2215 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, BOOL bBound )
2217 if ( bBound )
2219 const Rectangle& rRect = GetEntryBoundRect( pEntry );
2220 MakeVisible( rRect );
2222 else
2224 Rectangle aRect = CalcBmpRect( pEntry );
2225 aRect.Union( CalcTextRect( pEntry ) );
2226 aRect.Top() += TBOFFS_BOUND;
2227 aRect.Bottom() += TBOFFS_BOUND;
2228 aRect.Left() += LROFFS_BOUND;
2229 aRect.Right() += LROFFS_BOUND;
2230 MakeVisible( aRect );
2234 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2236 if( !IsBoundingRectValid( pEntry->aRect ))
2237 FindBoundingRect( pEntry );
2238 return pEntry->aRect;
2241 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2243 Rectangle aBound = GetEntryBoundRect( pEntry );
2244 if( pPos )
2245 aBound.SetPos( *pPos );
2246 Point aPos( aBound.TopLeft() );
2248 switch( nWinBits & (VIEWMODE_MASK) )
2250 case WB_ICON:
2252 aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2253 return Rectangle( aPos, aImageSize );
2256 case WB_SMALLICON:
2257 case WB_DETAILS:
2258 aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2259 //todo: hor. Abstand zum BoundRect?
2260 return Rectangle( aPos, aImageSize );
2262 default:
2263 DBG_ERROR("IconView: Viewmode not set");
2264 return aBound;
2268 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2269 const Point* pEntryPos, BOOL bEdit, const String* pStr )
2271 String aEntryText;
2272 if( !pStr )
2273 aEntryText = pView->GetEntryText( pEntry, bEdit );
2274 else
2275 aEntryText = *pStr;
2277 const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2278 Rectangle aBound( GetEntryBoundRect( pEntry ) );
2279 if( pEntryPos )
2280 aBound.SetPos( *pEntryPos );
2282 Rectangle aTextRect( aMaxTextRect );
2283 if( !bEdit )
2284 aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2286 Size aTextSize( aTextRect.GetSize() );
2288 Point aPos( aBound.TopLeft() );
2289 long nBoundWidth = aBound.GetWidth();
2290 long nBoundHeight = aBound.GetHeight();
2292 switch( nWinBits & (VIEWMODE_MASK) )
2294 case WB_ICON:
2295 aPos.Y() += aImageSize.Height();
2296 aPos.Y() += VER_DIST_BMP_STRING;
2297 // beim Editieren etwas mehr Platz
2298 if( bEdit )
2300 // 20% rauf
2301 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2302 aImageSize.Width();
2303 if( nMinWidth > nBoundWidth )
2304 nMinWidth = nBoundWidth;
2306 if( aTextSize.Width() < nMinWidth )
2307 aTextSize.Width() = nMinWidth;
2309 // beim Editieren ist Ueberlappung nach unten erlaubt
2310 Size aOptSize = aMaxTextRect.GetSize();
2311 if( aOptSize.Height() > aTextSize.Height() )
2312 aTextSize.Height() = aOptSize.Height();
2314 aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2315 break;
2317 case WB_SMALLICON:
2318 case WB_DETAILS:
2319 aPos.X() += aImageSize.Width();
2320 aPos.X() += HOR_DIST_BMP_STRING;
2321 aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2322 break;
2324 return Rectangle( aPos, aTextSize );
2328 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2330 long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2331 // nStringWidth += 2*LROFFS_TEXT;
2332 long nWidth = 0;
2334 switch( nWinBits & (VIEWMODE_MASK) )
2336 case WB_ICON:
2337 nWidth = Max( nStringWidth, aImageSize.Width() );
2338 break;
2340 case WB_SMALLICON:
2341 case WB_DETAILS:
2342 nWidth = aImageSize.Width();
2343 nWidth += HOR_DIST_BMP_STRING;
2344 nWidth += nStringWidth;
2345 break;
2347 return nWidth;
2350 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2352 long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2353 long nHeight = 0;
2355 switch( nWinBits & (VIEWMODE_MASK) )
2357 case WB_ICON:
2358 nHeight = aImageSize.Height();
2359 nHeight += VER_DIST_BMP_STRING;
2360 nHeight += nStringHeight;
2361 break;
2363 case WB_SMALLICON:
2364 case WB_DETAILS:
2365 nHeight = Max( aImageSize.Height(), nStringHeight );
2366 break;
2368 if( nHeight > nMaxBoundHeight )
2370 ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2371 ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2372 ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2374 return nHeight;
2377 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2379 return Size( CalcBoundingWidth( pEntry ),
2380 CalcBoundingHeight( pEntry ) );
2383 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects()
2385 nMaxBoundHeight = 0;
2386 pZOrderList->Clear();
2387 ULONG nCount = aEntries.Count();
2388 ULONG nCur;
2389 SvxIconChoiceCtrlEntry* pEntry;
2391 if( !IsAutoArrange() || !pHead )
2393 for( nCur = 0; nCur < nCount; nCur++ )
2395 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2396 FindBoundingRect( pEntry );
2397 pZOrderList->Insert( pEntry, LIST_APPEND );
2400 else
2402 nCur = 0;
2403 pEntry = pHead;
2404 while( nCur != nCount )
2406 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2407 FindBoundingRect( pEntry );
2408 pZOrderList->Insert( pEntry, pZOrderList->Count() );
2409 pEntry = pEntry->pflink;
2410 nCur++;
2413 bBoundRectsDirty = FALSE;
2414 AdjustScrollBars();
2417 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2419 nMaxBoundHeight = 0;
2420 pZOrderList->Clear();
2421 ULONG nCur;
2422 SvxIconChoiceCtrlEntry* pEntry;
2423 const ULONG nCount = aEntries.Count();
2425 if( !IsAutoArrange() || !pHead )
2427 for( nCur = 0; nCur < nCount; nCur++ )
2429 pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2430 if( IsBoundingRectValid( pEntry->aRect ))
2432 Size aBoundSize( pEntry->aRect.GetSize() );
2433 if( aBoundSize.Height() > nMaxBoundHeight )
2434 nMaxBoundHeight = aBoundSize.Height();
2436 else
2437 FindBoundingRect( pEntry );
2438 pZOrderList->Insert( pEntry, LIST_APPEND );
2441 else
2443 nCur = 0;
2444 pEntry = pHead;
2445 while( nCur != nCount )
2447 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2448 if( IsBoundingRectValid( pEntry->aRect ))
2450 Size aBoundSize( pEntry->aRect.GetSize() );
2451 if( aBoundSize.Height() > nMaxBoundHeight )
2452 nMaxBoundHeight = aBoundSize.Height();
2454 else
2455 FindBoundingRect( pEntry );
2456 pZOrderList->Insert( pEntry, LIST_APPEND );
2457 pEntry = pEntry->pflink;
2458 nCur++;
2461 AdjustScrollBars();
2464 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects()
2466 const ULONG nCount = aEntries.Count();
2467 for( ULONG nCur = 0; nCur < nCount; nCur++ )
2469 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2470 GetEntryBoundRect( pEntry );
2474 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2476 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2477 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2479 AdjustVirtSize( pEntry->aRect );
2480 return;
2482 Size aSize( CalcBoundingSize( pEntry ) );
2483 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(TRUE)).TopLeft());
2484 SetBoundingRect_Impl( pEntry, aPos, aSize );
2487 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2488 const Size& /*rBoundingSize*/ )
2490 Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2491 pEntry->aGridRect = aGridRect;
2492 Center( pEntry );
2493 AdjustVirtSize( pEntry->aRect );
2494 pGridMap->OccupyGrids( pEntry );
2498 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, BOOL bSyncSingleSelection,
2499 BOOL bShowFocusAsync )
2501 if( pEntry == pCursor )
2503 if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2504 !pCursor->IsSelected() )
2505 SelectEntry( pCursor, TRUE, TRUE );
2506 return;
2508 ShowCursor( FALSE );
2509 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2510 pCursor = pEntry;
2511 if( pOldCursor )
2513 pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2514 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2515 SelectEntry( pOldCursor, FALSE, TRUE ); // alten Cursor deselektieren
2517 if( pCursor )
2519 ToTop( pCursor );
2520 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2521 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2522 SelectEntry( pCursor, TRUE, TRUE );
2523 if( !bShowFocusAsync )
2524 ShowCursor( TRUE );
2525 else
2527 if( !nUserEventShowCursor )
2528 nUserEventShowCursor =
2529 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2530 EVENTID_SHOW_CURSOR );
2536 void SvxIconChoiceCtrl_Impl::ShowCursor( BOOL bShow )
2538 if( !pCursor || !bShow || !pView->HasFocus() )
2540 pView->HideFocus();
2541 return;
2543 Rectangle aRect ( CalcFocusRect( pCursor ) );
2544 /*pView->*/ShowFocus( aRect );
2548 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2550 pView->Update();
2551 ImpHideDDIcon();
2552 pDDBufDev = pDDDev;
2553 pDDDev = 0;
2556 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2558 if( pDDDev )
2560 Size aSize( pDDDev->GetOutputSizePixel() );
2561 // pView restaurieren
2562 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2567 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2569 pView->Update();
2570 if( pRefEntry != pDDRefEntry )
2572 DELETEZ(pDDDev);
2573 DELETEZ(pDDBufDev);
2575 BOOL bSelected = pRefEntry->IsSelected();
2576 pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED );
2577 if( !pDDDev )
2579 if( pDDBufDev )
2581 // nicht bei jedem Move ein Device anlegen, da dies besonders
2582 // auf Remote-Clients zu langsam ist
2583 pDDDev = pDDBufDev;
2584 pDDBufDev = 0;
2586 else
2588 pDDDev = new VirtualDevice( *pView );
2589 pDDDev->SetFont( pView->GetFont() );
2592 else
2594 ImpHideDDIcon();
2596 const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2597 pDDDev->SetOutputSizePixel( rRect.GetSize() );
2599 Point aPos( rPosPix );
2600 ToDocPos( aPos );
2602 Size aSize( pDDDev->GetOutputSizePixel() );
2603 pDDRefEntry = pRefEntry;
2604 aDDLastEntryPos = aPos;
2605 aDDLastRectPos = aPos;
2607 // Hintergrund sichern
2608 pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2609 // Icon in pView malen
2610 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2611 PaintEntry( pRefEntry, aPos );
2612 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2613 if( bSelected )
2614 pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED );
2617 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2619 /* In Notfaellen folgenden flackernden Code aktivieren:
2621 HideDDIcon();
2622 ShowDDIcon( pRefEntry, rPosPix );
2623 return;
2625 if( !pDDDev )
2627 ShowDDIcon( pRefEntry, rPosPix );
2628 return;
2631 if( pRefEntry != pDDRefEntry )
2633 HideDDIcon();
2634 ShowDDIcon( pRefEntry, rPosPix );
2635 return;
2638 Point aEmptyPoint;
2640 Point aCurEntryPos( rPosPix );
2641 ToDocPos( aCurEntryPos );
2643 const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2644 Size aEntrySize( rRect.GetSize() );
2645 Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2646 Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2648 if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2650 HideDDIcon();
2651 ShowDDIcon( pRefEntry, rPosPix );
2652 return;
2655 // Ueberlappung des neuen und alten D&D-Pointers!
2657 Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2658 if( !pDDTempDev )
2660 pDDTempDev = new VirtualDevice( *pView );
2661 pDDTempDev->SetFont( pView->GetFont() );
2664 Size aFullSize( aFullRect.GetSize() );
2665 Point aFullPos( aFullRect.TopLeft() );
2667 pDDTempDev->SetOutputSizePixel( aFullSize );
2669 // Hintergrund (mit dem alten D&D-Pointer!) sichern
2670 pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2671 // den alten Buffer in den neuen Buffer pasten
2672 aDDLastRectPos = aDDLastRectPos - aFullPos;
2674 pDDTempDev->DrawOutDev(
2675 aDDLastRectPos,
2676 pDDDev->GetOutputSizePixel(),
2677 aEmptyPoint,
2678 pDDDev->GetOutputSizePixel(),
2679 *pDDDev );
2681 // Swap
2682 VirtualDevice* pTemp = pDDDev;
2683 pDDDev = pDDTempDev;
2684 pDDTempDev = pTemp;
2686 // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2687 pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2688 pDDTempDev->DrawOutDev(
2689 aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2690 Point aRelPos = aCurEntryPos - aFullPos;
2691 pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2692 PaintEntry( pRefEntry, aRelPos, pDDTempDev );
2693 pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2695 aDDLastRectPos = aFullPos;
2696 aDDLastEntryPos = aCurEntryPos;
2698 pView->DrawOutDev(
2699 aDDLastRectPos,
2700 pDDDev->GetOutputSizePixel(),
2701 aEmptyPoint,
2702 pDDDev->GetOutputSizePixel(),
2703 *pDDTempDev );
2706 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2708 InvalidateBoundingRect( pEntry->aRect );
2712 BOOL SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2714 Rectangle aDocRect( GetDocumentRect() );
2715 Rectangle aVisRect( GetVisibleRect() );
2716 if( aVisRect.IsInside( aDocRect ))
2717 return FALSE;
2718 Size aDocSize( aDocRect.GetSize() );
2719 Size aVisSize( aVisRect.GetSize() );
2720 BOOL bHor = aDocSize.Width() > aVisSize.Width();
2721 BOOL bVer = aDocSize.Height() > aVisSize.Height();
2723 long nScrollDX = 0, nScrollDY = 0;
2725 switch( rCmd.GetCommand() )
2727 case COMMAND_STARTAUTOSCROLL:
2729 pView->EndTracking();
2730 USHORT nScrollFlags = 0;
2731 if( bHor )
2732 nScrollFlags |= AUTOSCROLL_HORZ;
2733 if( bVer )
2734 nScrollFlags |= AUTOSCROLL_VERT;
2735 if( nScrollFlags )
2737 pView->StartAutoScroll( nScrollFlags );
2738 return TRUE;
2741 break;
2743 case COMMAND_WHEEL:
2745 const CommandWheelData* pData = rCmd.GetWheelData();
2746 if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2748 ULONG nScrollLines = pData->GetScrollLines();
2749 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2751 nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2752 if( pData->GetDelta() < 0 )
2753 nScrollDY *= -1;
2755 else
2757 nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2758 nScrollDY *= GetScrollBarLineSize();
2762 break;
2764 case COMMAND_AUTOSCROLL:
2766 const CommandScrollData* pData = rCmd.GetAutoScrollData();
2767 if( pData )
2769 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2770 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2773 break;
2776 if( nScrollDX || nScrollDY )
2778 aVisRect.Top() -= nScrollDY;
2779 aVisRect.Bottom() -= nScrollDY;
2780 aVisRect.Left() -= nScrollDX;
2781 aVisRect.Right() -= nScrollDX;
2782 MakeVisible( aVisRect );
2783 return TRUE;
2785 return FALSE;
2789 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2791 // Rollmaus-Event?
2792 if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2793 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2794 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2796 #if 1
2797 if( HandleScrollCommand( rCEvt ) )
2798 return;
2799 #else
2800 ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0;
2801 ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0;
2802 if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) )
2803 return;
2804 #endif
2808 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2810 if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry )
2812 ULONG nPos = pZOrderList->GetPos( (void*)pEntry );
2813 pZOrderList->Remove( nPos );
2814 pZOrderList->Insert( pEntry, LIST_APPEND );
2818 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2820 if( rRect.Bottom() >= aVirtOutputSize.Height() )
2821 rRect.Bottom() = aVirtOutputSize.Height() - 1;
2822 if( rRect.Right() >= aVirtOutputSize.Width() )
2823 rRect.Right() = aVirtOutputSize.Width() - 1;
2824 if( rRect.Top() < 0 )
2825 rRect.Top() = 0;
2826 if( rRect.Left() < 0 )
2827 rRect.Left() = 0;
2830 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2831 // sichtbar gemacht werden soll.
2832 // bScrBar == TRUE: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2834 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, BOOL bScrBar,
2835 BOOL bCallRectChangedHdl )
2837 Rectangle aVirtRect( rRect );
2838 ClipAtVirtOutRect( aVirtRect );
2839 Point aOrigin( pView->GetMapMode().GetOrigin() );
2840 // in Dokumentkoordinate umwandeln
2841 aOrigin *= -1;
2842 Rectangle aOutputArea( GetOutputRect() );
2843 if( aOutputArea.IsInside( aVirtRect ) )
2844 return; // ist schon sichtbar
2846 long nDy;
2847 if( aVirtRect.Top() < aOutputArea.Top() )
2849 // nach oben scrollen (nDy < 0)
2850 nDy = aVirtRect.Top() - aOutputArea.Top();
2852 else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2854 // nach unten scrollen (nDy > 0)
2855 nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2857 else
2858 nDy = 0;
2860 long nDx;
2861 if( aVirtRect.Left() < aOutputArea.Left() )
2863 // nach links scrollen (nDx < 0)
2864 nDx = aVirtRect.Left() - aOutputArea.Left();
2866 else if( aVirtRect.Right() > aOutputArea.Right() )
2868 // nach rechts scrollen (nDx > 0)
2869 nDx = aVirtRect.Right() - aOutputArea.Right();
2871 else
2872 nDx = 0;
2874 aOrigin.X() += nDx;
2875 aOrigin.Y() += nDy;
2876 aOutputArea.SetPos( aOrigin );
2877 if( GetUpdateMode() )
2879 HideDDIcon();
2880 pView->Update();
2881 ShowCursor( FALSE );
2884 // Origin fuer SV invertieren (damit wir in
2885 // Dokumentkoordinaten scrollen/painten koennen)
2886 aOrigin *= -1;
2887 SetOrigin( aOrigin );
2889 BOOL bScrollable = pView->GetBackground().IsScrollable();
2890 if( pView->HasBackground() && !bScrollable )
2892 Rectangle aRect( GetOutputRect());
2893 Wallpaper aPaper( pView->GetBackground() );
2894 aPaper.SetRect( aRect );
2895 pView->SetBackground( aPaper );
2898 if( bScrollable && GetUpdateMode() )
2900 // in umgekehrte Richtung scrollen!
2901 pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2902 SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2904 else
2905 pView->Invalidate(INVALIDATE_NOCHILDREN);
2907 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2909 if( !bScrBar )
2911 aOrigin *= -1;
2912 // Thumbs korrigieren
2913 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2914 aHorSBar.SetThumbPos( aOrigin.X() );
2915 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2916 aVerSBar.SetThumbPos( aOrigin.Y() );
2920 if( GetUpdateMode() )
2921 ShowCursor( TRUE );
2923 // pruefen, ob ScrollBars noch benoetigt werden
2924 CheckScrollBars();
2925 if( bScrollable && GetUpdateMode() )
2926 pView->Update();
2928 // kann der angeforderte Bereich nicht komplett sichtbar gemacht werden,
2929 // wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der
2930 // Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind,
2931 // eine ScrollBar aber eine groessere Line-Size eingestellt hat.
2932 if( bCallRectChangedHdl || GetOutputRect() != rRect )
2933 VisRectChanged();
2937 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor()
2939 SvxIconChoiceCtrlEntry* pNewCursor;
2940 if( pCursor )
2942 pNewCursor = pImpCursor->GoLeftRight( pCursor, FALSE );
2943 if( !pNewCursor )
2945 pNewCursor = pImpCursor->GoLeftRight( pCursor, TRUE );
2946 if( !pNewCursor )
2948 pNewCursor = pImpCursor->GoUpDown( pCursor, FALSE );
2949 if( !pNewCursor )
2950 pNewCursor = pImpCursor->GoUpDown( pCursor, TRUE );
2954 else
2955 pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
2956 DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed");
2957 return pNewCursor;
2960 ULONG SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2962 if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2963 return 1;
2964 return nSelectionCount;
2967 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2969 BOOL bSel;
2970 if( pEntry->IsSelected() )
2971 bSel = FALSE;
2972 else
2973 bSel = TRUE;
2974 SelectEntry( pEntry, bSel, TRUE, TRUE );
2977 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2978 BOOL bPaintSync )
2980 ClearSelectedRectList();
2982 // !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!!
2984 ULONG nCount = aEntries.Count();
2985 for( ULONG nCur = 0; nCur < nCount; nCur++ )
2987 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2988 if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2989 SelectEntry( pEntry, FALSE, TRUE, TRUE, bPaintSync );
2991 pAnchor = 0;
2992 nFlags &= (~F_ADD_MODE);
2995 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2997 Size aMinSize( aImageSize );
2998 aMinSize.Width() += 2 * LROFFS_BOUND;
2999 aMinSize.Height() += TBOFFS_BOUND; // PB: einmal Offset reicht (FileDlg)
3000 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
3001 Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
3002 if( nWinBits & WB_ICON )
3004 aMinSize.Height() += VER_DIST_BMP_STRING;
3005 aMinSize.Height() += aTextSize.Height();
3007 else
3009 aMinSize.Width() += HOR_DIST_BMP_STRING;
3010 aMinSize.Width() += aTextSize.Width();
3012 return aMinSize;
3015 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
3017 Size aSize( rSize );
3018 Size aMinSize( GetMinGrid() );
3019 if( aSize.Width() < aMinSize.Width() )
3020 aSize.Width() = aMinSize.Width();
3021 if( aSize.Height() < aMinSize.Height() )
3022 aSize.Height() = aMinSize.Height();
3024 nGridDX = aSize.Width();
3025 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
3026 // dieses Workaround bringts mit einer Spalte zum Fliegen
3027 if( nWinBits & WB_DETAILS )
3029 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
3030 if( pCol )
3031 ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
3033 nGridDY = aSize.Height();
3034 SetDefaultTextSize();
3037 // berechnet die maximale Groesse, die das Textrechteck innerhalb des
3038 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und
3039 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt
3041 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
3043 Rectangle aBoundRect;
3044 // keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen
3045 if( IsBoundingRectValid( pEntry->aRect ) )
3046 aBoundRect = pEntry->aRect;
3047 else
3048 aBoundRect = pEntry->aGridRect;
3050 Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
3051 (SvxIconChoiceCtrlEntry*)pEntry ) );
3052 if( nWinBits & WB_ICON )
3054 aBoundRect.Top() = aBmpRect.Bottom();
3055 aBoundRect.Top() += VER_DIST_BMP_STRING;
3056 if( aBoundRect.Top() > aBoundRect.Bottom())
3057 aBoundRect.Top() = aBoundRect.Bottom();
3058 aBoundRect.Left() += LROFFS_BOUND;
3059 aBoundRect.Left()++;
3060 aBoundRect.Right() -= LROFFS_BOUND;
3061 aBoundRect.Right()--;
3062 if( aBoundRect.Left() > aBoundRect.Right())
3063 aBoundRect.Left() = aBoundRect.Right();
3064 if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
3065 aBoundRect.Bottom() = LONG_MAX;
3067 else
3069 aBoundRect.Left() = aBmpRect.Right();
3070 aBoundRect.Left() += HOR_DIST_BMP_STRING;
3071 aBoundRect.Right() -= LROFFS_BOUND;
3072 if( aBoundRect.Left() > aBoundRect.Right() )
3073 aBoundRect.Left() = aBoundRect.Right();
3074 long nHeight = aBoundRect.GetSize().Height();
3075 nHeight = nHeight - aDefaultTextSize.Height();
3076 nHeight /= 2;
3077 aBoundRect.Top() += nHeight;
3078 aBoundRect.Bottom() -= nHeight;
3080 return aBoundRect;
3083 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
3085 long nDY = nGridDY;
3086 nDY -= aImageSize.Height();
3087 nDY -= VER_DIST_BMP_STRING;
3088 nDY -= 2*TBOFFS_BOUND;
3089 if( nDY <= 0 )
3090 nDY = 2;
3092 long nDX = nGridDX;
3093 nDX -= 2*LROFFS_BOUND;
3094 nDX -= 2;
3095 if( nDX <= 0 )
3096 nDX = 2;
3098 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
3099 long nHeight = pView->GetTextHeight();
3100 if( nDY < nHeight )
3101 nDY = nHeight;
3102 aDefaultTextSize = Size( nDX, nDY );
3106 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
3108 pEntry->aRect = pEntry->aGridRect;
3109 Size aSize( CalcBoundingSize( pEntry ) );
3110 if( nWinBits & WB_ICON )
3112 // horizontal zentrieren
3113 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
3114 pEntry->aRect.Left() += nBorder / 2;
3115 pEntry->aRect.Right() -= nBorder / 2;
3117 // vertikal zentrieren
3118 pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
3122 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3123 // links, hoch: Offsets < 0
3124 // rechts, runter: Offsets > 0
3125 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, BOOL bScrollBar )
3127 const MapMode& rMapMode = pView->GetMapMode();
3128 Point aOrigin( rMapMode.GetOrigin() );
3129 // in Dokumentkoordinate umwandeln
3130 aOrigin *= -1;
3131 aOrigin.Y() += nDeltaY;
3132 aOrigin.X() += nDeltaX;
3133 Rectangle aRect( aOrigin, aOutputSize );
3134 MakeVisible( aRect, bScrollBar );
3138 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
3139 IcnViewFieldType eItem ) const
3141 if( eItem == IcnViewFieldTypeText )
3142 return aDefaultTextSize;
3143 return aImageSize;
3146 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
3148 Rectangle aBmpRect( CalcBmpRect( pEntry ) );
3149 Rectangle aTextRect( CalcTextRect( pEntry ) );
3150 Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
3151 Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1,
3152 aBoundRect.Right() - 4, aTextRect.Bottom() + 1 );
3153 // Das Fokusrechteck soll nicht den Text beruehren
3154 if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() )
3155 aFocusRect.Left()--;
3156 if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() )
3157 aFocusRect.Right()++;
3159 return aFocusRect;
3162 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
3163 static Rectangle GetHotSpot( const Rectangle& rRect )
3165 Rectangle aResult( rRect );
3166 aResult.Justify();
3167 Size aSize( rRect.GetSize() );
3168 long nDelta = aSize.Width() / 4;
3169 aResult.Left() += nDelta;
3170 aResult.Right() -= nDelta;
3171 nDelta = aSize.Height() / 4;
3172 aResult.Top() += nDelta;
3173 aResult.Bottom() -= nDelta;
3174 return aResult;
3177 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
3178 BOOL bAdd, SvPtrarr* pOtherRects )
3180 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3181 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3182 aRect.Union( GetEntryBoundRect( pEntry2 ) );
3183 SelectRect( aRect, bAdd, pOtherRects );
3186 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, BOOL bAdd,
3187 SvPtrarr* pOtherRects )
3189 aCurSelectionRect = rRect;
3190 if( !pZOrderList || !pZOrderList->Count() )
3191 return;
3193 // Flag setzen, damit im Select kein ToTop gerufen wird
3194 BOOL bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? TRUE : FALSE;
3195 nFlags |= F_SELECTING_RECT;
3197 CheckBoundingRects();
3198 pView->Update();
3199 const ULONG nCount = pZOrderList->Count();
3201 Rectangle aRect( rRect );
3202 aRect.Justify();
3203 BOOL bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? TRUE : FALSE;
3205 BOOL bResetClipRegion = FALSE;
3206 if( !pView->IsClipRegion() )
3208 bResetClipRegion = TRUE;
3209 pView->SetClipRegion( GetOutputRect() );
3212 for( ULONG nPos = 0; nPos < nCount; nPos++ )
3214 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
3216 if( !IsBoundingRectValid( pEntry->aRect ))
3217 FindBoundingRect( pEntry );
3218 Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
3219 BOOL bSelected = pEntry->IsSelected();
3221 BOOL bOverlaps;
3222 if( bCalcOverlap )
3223 bOverlaps = IsOver( pOtherRects, aBoundRect );
3224 else
3225 bOverlaps = FALSE;
3226 BOOL bOver = aRect.IsOver( aBoundRect );
3228 if( bOver && !bOverlaps )
3230 // Ist im neuen Selektionsrechteck und in keinem alten
3231 // => selektieren
3232 if( !bSelected )
3233 SelectEntry( pEntry, TRUE, TRUE, TRUE );
3235 else if( !bAdd )
3237 // ist ausserhalb des Selektionsrechtecks
3238 // => Selektion entfernen
3239 if( bSelected )
3240 SelectEntry( pEntry, FALSE, TRUE, TRUE );
3242 else if( bAdd && bOverlaps )
3244 // Der Eintrag befindet sich in einem alten (=>Aufspannen
3245 // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3247 // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3248 // in einem vorherigen Rechteck, muss restauriert werden, wenn
3249 // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3250 // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3251 // pauschal davon aus, dass die Eintraege in den alten Rechtecken
3252 // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3253 // nur zu deselektieren.
3254 // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3255 // spannen des Rechtecks merken
3256 if( aBoundRect.IsOver( rRect))
3258 // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3259 if( bSelected )
3260 SelectEntry( pEntry, FALSE, TRUE, TRUE );
3262 else
3264 // Eintrag eines alten Rects selektieren
3265 if( !bSelected )
3266 SelectEntry( pEntry, TRUE, TRUE, TRUE );
3269 else if( !bOver && bSelected )
3271 // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3272 SelectEntry( pEntry, FALSE, TRUE, TRUE );
3276 if( !bAlreadySelectingRect )
3277 nFlags &= ~F_SELECTING_RECT;
3279 pView->Update();
3280 if( bResetClipRegion )
3281 pView->SetClipRegion();
3284 void SvxIconChoiceCtrl_Impl::SelectRange(
3285 SvxIconChoiceCtrlEntry* pStart,
3286 SvxIconChoiceCtrlEntry* pEnd,
3287 BOOL bAdd )
3289 ULONG nFront = GetEntryListPos( pStart );
3290 ULONG nBack = GetEntryListPos( pEnd );
3291 ULONG nFirst = std::min( nFront, nBack );
3292 ULONG nLast = std::max( nFront, nBack );
3293 ULONG i;
3294 SvxIconChoiceCtrlEntry* pEntry;
3296 if ( ! bAdd )
3298 // deselect everything before the first entry if not in
3299 // adding mode
3300 for ( i=0; i<nFirst; i++ )
3302 pEntry = GetEntry( i );
3303 if( pEntry->IsSelected() )
3304 SelectEntry( pEntry, FALSE, TRUE, TRUE, TRUE );
3308 // select everything between nFirst and nLast
3309 for ( i=nFirst; i<=nLast; i++ )
3311 pEntry = GetEntry( i );
3312 if( ! pEntry->IsSelected() )
3313 SelectEntry( pEntry, TRUE, TRUE, TRUE, TRUE );
3316 if ( ! bAdd )
3318 // deselect everything behind the last entry if not in
3319 // adding mode
3320 ULONG nEnd = GetEntryCount();
3321 for ( ; i<nEnd; i++ )
3323 pEntry = GetEntry( i );
3324 if( pEntry->IsSelected() )
3325 SelectEntry( pEntry, FALSE, TRUE, TRUE, TRUE );
3330 BOOL SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3332 const USHORT nCount = pRectList->Count();
3333 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3335 Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3336 if( rBoundRect.IsOver( *pRect ))
3337 return TRUE;
3339 return FALSE;
3342 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
3343 SvxIconChoiceCtrlEntry* pEntry2 )
3345 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3346 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3347 aRect.Union( GetEntryBoundRect( pEntry2 ) );
3348 AddSelectedRect( aRect );
3351 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
3353 Rectangle* pRect = new Rectangle( rRect );
3354 pRect->Justify();
3355 aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3358 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
3360 const USHORT nCount = aSelectedRectList.Count();
3361 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3363 Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3364 delete pRect;
3366 aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3369 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel,
3370 long& rX, long& rY, BOOL isInDragDrop, USHORT nBorderWidth)
3372 // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3373 // Fensters befindet
3374 long nPixelToScrollX = 0;
3375 long nPixelToScrollY = 0;
3376 Size aWndSize = aOutputSize;
3378 nBorderWidth = (USHORT)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3379 nBorderWidth = (USHORT)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3381 if ( rPosPixel.X() < nBorderWidth )
3383 if( isInDragDrop )
3384 nPixelToScrollX = -DD_SCROLL_PIXEL;
3385 else
3386 nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3388 else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3390 if( isInDragDrop )
3391 nPixelToScrollX = DD_SCROLL_PIXEL;
3392 else
3393 nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3395 if ( rPosPixel.Y() < nBorderWidth )
3397 if( isInDragDrop )
3398 nPixelToScrollY = -DD_SCROLL_PIXEL;
3399 else
3400 nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3402 else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3404 if( isInDragDrop )
3405 nPixelToScrollY = DD_SCROLL_PIXEL;
3406 else
3407 nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3410 rX = nPixelToScrollX;
3411 rY = nPixelToScrollY;
3414 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG )
3416 aAutoArrangeTimer.Stop();
3417 Arrange( IsAutoArrange() );
3418 return 0;
3421 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG )
3423 aVisRectChangedTimer.Stop();
3424 pView->VisibleRectChanged();
3425 return 0;
3428 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG )
3430 aDocRectChangedTimer.Stop();
3431 pView->DocumentRectChanged();
3432 return 0;
3435 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt )
3437 StopEditTimer();
3438 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() );
3439 if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() )
3440 SelectEntry( pEntry, TRUE, TRUE );
3441 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
3444 BOOL SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
3446 Rectangle aRect( CalcTextRect( pEntry ));
3447 if( aRect.IsInside( rDocPos ) )
3448 return TRUE;
3449 return FALSE;
3452 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG )
3454 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
3455 if( bEntryEditingEnabled && pEntry &&
3456 pEntry->IsSelected())
3458 if( pView->EditingEntry( pEntry ))
3459 EditEntry( pEntry );
3461 return 0;
3466 // Funktionen zum Ausrichten der Eintraege am Grid
3469 // pStart == 0: Alle Eintraege werden ausgerichtet
3470 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
3471 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
3473 SvPtrarr aLists;
3474 pImpCursor->CreateGridAjustData( aLists, pStart );
3475 const USHORT nCount = aLists.Count();
3476 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3477 AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
3478 IcnCursor_Impl::DestroyGridAdjustData( aLists );
3479 CheckScrollBars();
3482 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
3483 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart )
3485 if( !rRow.Count() )
3486 return;
3488 BOOL bGo;
3489 if( !pStart )
3490 bGo = TRUE;
3491 else
3492 bGo = FALSE;
3494 long nCurRight = 0;
3495 for( USHORT nCur = 0; nCur < rRow.Count(); nCur++ )
3497 SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ];
3498 if( !bGo && pCur == pStart )
3499 bGo = TRUE;
3501 //SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3502 // Massgebend (fuer unser Auge) ist die Bitmap, da sonst
3503 // durch lange Texte der Eintrag stark springen kann
3504 const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3505 Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3506 if( bGo && !pCur->IsPosLocked() )
3508 long nWidth = aCenterRect.GetSize().Width();
3509 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3510 while( aNewPos.X() < nCurRight )
3511 aNewPos.X() += nGridDX;
3512 if( aNewPos != rBoundRect.TopLeft() )
3514 SetEntryPos( pCur, aNewPos );
3515 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3516 nFlags |= F_MOVED_ENTRIES;
3518 nCurRight = aNewPos.X() + nWidth;
3520 else
3522 nCurRight = rBoundRect.Right();
3527 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
3528 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
3529 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
3530 // die Berechnung des Ziel-Rechtecks verwendet wird.
3531 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3532 const Rectangle& rBoundRect ) const
3534 Point aPos( rCenterRect.TopLeft() );
3535 Size aSize( rCenterRect.GetSize() );
3537 aPos.X() -= LROFFS_WINBORDER;
3538 aPos.Y() -= TBOFFS_WINBORDER;
3540 // align (ref ist mitte des rects)
3541 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3542 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3543 aPos.X() = nGridX * nGridDX;
3544 aPos.Y() = nGridY * nGridDY;
3545 // hor. center
3546 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3548 aPos.X() += LROFFS_WINBORDER;
3549 aPos.Y() += TBOFFS_WINBORDER;
3551 return aPos;
3554 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3556 if( !pEntry )
3558 if( eTextMode != eMode )
3560 if( eTextMode == IcnShowTextDontKnow )
3561 eTextMode = IcnShowTextShort;
3562 eTextMode = eMode;
3563 Arrange( TRUE );
3566 else
3568 if( pEntry->eTextMode != eMode )
3570 pEntry->eTextMode = eMode;
3571 InvalidateEntry( pEntry );
3572 pView->Invalidate( GetEntryBoundRect( pEntry ) );
3573 AdjustVirtSize( pEntry->aRect );
3578 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
3580 if( !pEntry )
3581 return eTextMode;
3582 return pEntry->GetTextMode();
3585 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3587 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3588 SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3589 if( eMode == IcnShowTextDontKnow )
3590 return eTextMode;
3591 return eMode;
3594 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry )
3596 if( !pEntry )
3598 pView->HideFocus();
3600 else
3602 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
3603 /*pView->*/ShowFocus( aRect );
3607 ////////////////////////////////////////////////////////////////////////////////////////////////
3609 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3610 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see
3611 // a gray focusrect on a gray background !!!
3613 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3615 Color aBkgColor ( pView->GetBackground().GetColor() );
3616 Color aPenColor;
3617 USHORT nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3618 if ( nColor > 128 )
3619 aPenColor.SetColor ( COL_BLACK );
3620 else
3621 aPenColor.SetColor( COL_WHITE );
3623 aFocus.bOn = TRUE;
3624 aFocus.aPenColor = aPenColor;
3625 aFocus.aRect = rRect;
3628 void SvxIconChoiceCtrl_Impl::HideFocus ()
3630 aFocus.bOn = FALSE;
3633 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3635 pOut->SetLineColor( aFocus.aPenColor );
3636 pOut->SetFillColor();
3637 Polygon aPolygon ( aFocus.aRect );
3639 LineInfo aLineInfo ( LINE_DASH );
3641 aLineInfo.SetDashLen ( 1 );
3643 aLineInfo.SetDotLen ( 1L );
3644 aLineInfo.SetDistance ( 1L );
3645 aLineInfo.SetDotCount ( 1 );
3647 pOut->DrawPolyLine ( aPolygon, aLineInfo );
3650 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, ULONG& rPos ) const
3652 sal_Bool bRet = sal_False;
3653 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3654 ULONG nEntryCount = GetEntryCount();
3655 for ( ULONG i = 0; i < nEntryCount; ++i )
3657 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3659 bRet = sal_True;
3660 rPos = i;
3661 break;
3665 return bRet;
3669 ////////////////////////////////////////////////////////////////////////////////////////////////
3671 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3673 if( nId == EVENTID_ADJUST_SCROLLBARS )
3675 nUserEventAdjustScrBars = 0;
3676 AdjustScrollBars();
3678 else if( nId == EVENTID_SHOW_CURSOR )
3680 nUserEventShowCursor = 0;
3681 ShowCursor( TRUE );
3683 return 0;
3686 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3688 if( nUserEventAdjustScrBars )
3690 Application::RemoveUserEvent( nUserEventAdjustScrBars );
3691 nUserEventAdjustScrBars = 0;
3693 if( nUserEventShowCursor )
3695 Application::RemoveUserEvent( nUserEventShowCursor );
3696 nUserEventShowCursor = 0;
3700 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3702 if( pEntry == pCursor )
3703 ShowCursor( FALSE );
3704 pView->Invalidate( pEntry->aRect );
3705 Center( pEntry );
3706 pView->Invalidate( pEntry->aRect );
3707 if( pEntry == pCursor )
3708 ShowCursor( TRUE );
3711 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3713 DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3714 if( !pEntry )
3715 return;
3717 StopEntryEditing( TRUE );
3718 DELETEZ(pEdit);
3719 SetNoSelection();
3721 pCurEditedEntry = pEntry;
3722 String aEntryText( pView->GetEntryText( pEntry, TRUE ) );
3723 Rectangle aRect( CalcTextRect( pEntry, 0, TRUE, &aEntryText ) );
3724 MakeVisible( aRect );
3725 Point aPos( aRect.TopLeft() );
3726 aPos = pView->GetPixelPos( aPos );
3727 aRect.SetPos( aPos );
3728 pView->HideFocus();
3729 pEdit = new IcnViewEdit_Impl(
3730 pView,
3731 aRect.TopLeft(),
3732 aRect.GetSize(),
3733 aEntryText,
3734 LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3737 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG )
3739 DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3740 if( !pEdit )
3742 pCurEditedEntry = 0;
3743 return 0;
3745 DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3747 if( !pCurEditedEntry )
3749 pEdit->Hide();
3750 if( pEdit->IsGrabFocus() )
3751 pView->GrabFocus();
3752 return 0;
3755 String aText;
3756 if ( !pEdit->EditingCanceled() )
3757 aText = pEdit->GetText();
3758 else
3759 aText = pEdit->GetSavedValue();
3761 if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3762 InvalidateEntry( pCurEditedEntry );
3763 if( !GetSelectionCount() )
3764 SelectEntry( pCurEditedEntry, TRUE );
3766 pEdit->Hide();
3767 if( pEdit->IsGrabFocus() )
3768 pView->GrabFocus();
3769 // Das Edit kann nicht hier geloescht werden, weil es noch in einem
3770 // Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht.
3771 pCurEditedEntry = 0;
3772 return 0;
3775 void SvxIconChoiceCtrl_Impl::StopEntryEditing( BOOL bCancel )
3777 if( pEdit )
3778 pEdit->StopEditing( bCancel );
3781 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, BOOL bLock )
3783 if( bLock )
3784 pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED );
3785 else
3786 pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED );
3789 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( ULONG& rPos ) const
3791 if( !GetSelectionCount() )
3792 return 0;
3794 if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3796 rPos = pView->GetEntryListPos( pCurHighlightFrame );
3797 return pCurHighlightFrame;
3800 ULONG nCount = aEntries.Count();
3801 if( !pHead )
3803 for( ULONG nCur = 0; nCur < nCount; nCur++ )
3805 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3806 if( pEntry->IsSelected() )
3808 rPos = nCur;
3809 return pEntry;
3813 else
3815 SvxIconChoiceCtrlEntry* pEntry = pHead;
3816 while( nCount-- )
3818 if( pEntry->IsSelected() )
3820 rPos = GetEntryListPos( pEntry );
3821 return pEntry;
3823 pEntry = pEntry->pflink;
3824 if( nCount && pEntry == pHead )
3826 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
3827 return 0;
3831 return 0;
3834 // kein Round Robin!
3835 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( ULONG& rStartPos ) const
3837 ULONG nCount = aEntries.Count();
3838 if( rStartPos > nCount || !GetSelectionCount() )
3839 return 0;
3840 if( !pHead )
3842 for( ULONG nCur = rStartPos+1; nCur < nCount; nCur++ )
3844 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3845 if( pEntry->IsSelected() )
3847 rStartPos = nCur;
3848 return pEntry;
3852 else
3854 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos );
3855 pEntry = pEntry->pflink;
3856 while( pEntry != pHead )
3858 if( pEntry->IsSelected() )
3860 rStartPos = GetEntryListPos( pEntry );
3861 return pEntry;
3863 pEntry = pEntry->pflink;
3867 rStartPos = 0xffffffff;
3868 return 0;
3871 void SvxIconChoiceCtrl_Impl::SelectAll( BOOL bSelect, BOOL bPaint )
3873 bPaint = TRUE;
3875 ULONG nCount = aEntries.Count();
3876 for( ULONG nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3878 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3879 SelectEntry( pEntry, bSelect, TRUE, TRUE, bPaint );
3881 nFlags &= (~F_ADD_MODE);
3882 pAnchor = 0;
3885 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList )
3887 if( !*ppList )
3888 *ppList = new List;
3889 ULONG nPos;
3890 SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos );
3891 while( pEntry && GetSelectionCount() != (*ppList)->Count() )
3893 (*ppList)->Insert( pEntry, LIST_APPEND );
3894 pEntry = GetNextSelectedEntry( nPos );
3898 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3899 const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
3900 MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3901 aCallBackHdl( rNotifyEditEnd ),
3902 bCanceled( FALSE ),
3903 bAlreadyInCallback( FALSE ),
3904 bGrabFocus( FALSE )
3906 Font aFont( pParent->GetPointFont() );
3907 aFont.SetTransparent( FALSE );
3908 SetControlFont( aFont );
3909 if( !pParent->HasFontFillColor() )
3911 Color aColor( pParent->GetBackground().GetColor() );
3912 SetControlBackground( aColor );
3914 else
3915 SetControlBackground( aFont.GetFillColor() );
3916 SetControlForeground( aFont.GetColor() );
3917 SetPosPixel( rPos );
3918 SetSizePixel( CalcAdjustedSize(rSize) );
3919 SetText( rData );
3920 SaveValue();
3922 aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3923 aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3925 aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3926 aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3927 GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3928 GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3929 Show();
3930 GrabFocus();
3933 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3935 if( !bAlreadyInCallback )
3937 GetpApp()->RemoveAccel( &aAccReturn );
3938 GetpApp()->RemoveAccel( &aAccEscape );
3942 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3944 aTimer.Stop();
3945 if ( !bAlreadyInCallback )
3947 bAlreadyInCallback = TRUE;
3948 GetpApp()->RemoveAccel( &aAccReturn );
3949 GetpApp()->RemoveAccel( &aAccEscape );
3950 Hide();
3951 aCallBackHdl.Call( this );
3955 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG )
3957 CallCallBackHdl_Impl();
3958 return 0;
3961 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG )
3963 bCanceled = FALSE;
3964 bGrabFocus = TRUE;
3965 CallCallBackHdl_Impl();
3966 return 1;
3969 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG )
3971 bCanceled = TRUE;
3972 bGrabFocus = TRUE;
3973 CallCallBackHdl_Impl();
3974 return 1;
3977 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3979 KeyCode aCode = rKEvt.GetKeyCode();
3980 USHORT nCode = aCode.GetCode();
3982 switch ( nCode )
3984 case KEY_ESCAPE:
3985 bCanceled = TRUE;
3986 bGrabFocus = TRUE;
3987 CallCallBackHdl_Impl();
3988 break;
3990 case KEY_RETURN:
3991 bCanceled = FALSE;
3992 bGrabFocus = TRUE;
3993 CallCallBackHdl_Impl();
3994 break;
3996 default:
3997 MultiLineEdit::KeyInput( rKEvt );
4001 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
4003 if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4005 if ( !bAlreadyInCallback &&
4006 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
4008 bCanceled = FALSE;
4009 aTimer.SetTimeout(10);
4010 aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
4011 aTimer.Start();
4014 return 0;
4017 void IcnViewEdit_Impl::StopEditing( BOOL bCancel )
4019 if ( !bAlreadyInCallback )
4021 bCanceled = bCancel;
4022 CallCallBackHdl_Impl();
4026 ULONG SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
4028 if( !(nFlags & F_ENTRYLISTPOS_VALID ))
4029 ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
4030 return pEntry->nPos;
4033 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, ULONG nNewPos )
4035 ULONG nCurPos = GetEntryListPos( pListEntry );
4036 if( nCurPos == nNewPos )
4037 return;
4038 aEntries.List::Remove( nCurPos );
4039 aEntries.List::Insert( (void*)pListEntry, nNewPos );
4040 // Eintragspositionen anpassen
4041 ULONG nStart, nEnd;
4042 if( nNewPos < nCurPos )
4044 nStart = nNewPos;
4045 nEnd = nCurPos;
4047 else
4049 nStart = nCurPos;
4050 nEnd = nNewPos;
4052 for( ; nStart <= nEnd; nStart++ )
4054 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart );
4055 pEntry->nPos = nStart;
4059 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, USHORT nEntryFlags )
4061 pEntry->nFlags = nEntryFlags;
4062 if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED )
4063 nFlags |= F_MOVED_ENTRIES;
4066 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, BOOL bRight )
4068 return pImpCursor->GoLeftRight( pStart, bRight );
4071 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, BOOL bDown )
4073 return pImpCursor->GoUpDown( pStart, bDown );
4076 void SvxIconChoiceCtrl_Impl::InitSettings()
4078 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
4080 if( !pView->HasFont() )
4082 // Unit aus den Settings ist Point
4083 Font aFont( rStyleSettings.GetFieldFont() );
4084 //const Font& rFont = pView->GetFont();
4085 //if( pView->HasFontTextColor() )
4086 aFont.SetColor( rStyleSettings.GetWindowTextColor() );
4087 //if( pView->HasFontFillColor() )
4088 //aFont.SetFillColor( rFont.GetFillColor() );
4089 pView->SetPointFont( aFont );
4090 SetDefaultTextSize();
4093 //if( !pView->HasFontTextColor() )
4094 pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
4095 //if( !pView->HasFontFillColor() )
4096 pView->SetTextFillColor();
4098 //if( !pView->HasBackground() )
4099 pView->SetBackground( rStyleSettings.GetFieldColor());
4101 long nScrBarSize = rStyleSettings.GetScrollBarSize();
4102 if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
4104 nHorSBarHeight = nScrBarSize;
4105 Size aSize( aHorSBar.GetSizePixel() );
4106 aSize.Height() = nScrBarSize;
4107 aHorSBar.Hide();
4108 aHorSBar.SetSizePixel( aSize );
4110 nVerSBarWidth = nScrBarSize;
4111 aSize = aVerSBar.GetSizePixel();
4112 aSize.Width() = nScrBarSize;
4113 aVerSBar.Hide();
4114 aVerSBar.SetSizePixel( aSize );
4116 Size aOSize( pView->Control::GetOutputSizePixel() );
4117 PositionScrollBars( aOSize.Width(), aOSize.Height() );
4118 AdjustScrollBars();
4122 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, USHORT _nInitSize , USHORT _nReSize ) :
4123 List( _nInitSize, _nReSize ),
4124 _pOwner( pOwner )
4126 _pOwner->pHead = 0;
4129 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, USHORT _nBlockSize, USHORT _nInitSize, USHORT _nReSize ) :
4130 List( _nBlockSize, _nInitSize, _nReSize ),
4131 _pOwner( pOwner )
4133 _pOwner->pHead = 0;
4136 EntryList_Impl::~EntryList_Impl()
4138 _pOwner->pHead = 0;
4141 void EntryList_Impl::Clear()
4143 _pOwner->pHead = 0;
4144 List::Clear();
4147 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, ULONG nPos )
4149 List::Insert( pEntry, nPos );
4150 if( _pOwner->pHead )
4151 pEntry->SetBacklink( _pOwner->pHead->pblink );
4154 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( ULONG nPos )
4156 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos );
4157 DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found");
4158 Removed_Impl( pEntry );
4159 return pEntry;
4162 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry )
4164 List::Remove( (void*)pEntry );
4165 Removed_Impl( pEntry );
4168 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry )
4170 if( _pOwner->pHead )
4172 if( _pOwner->pHead == pEntry )
4174 if( _pOwner->pHead != pEntry->pflink )
4175 _pOwner->pHead = pEntry->pflink;
4176 else
4178 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
4179 _pOwner->pHead = 0;
4182 pEntry->Unlink();
4186 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
4188 ULONG nCur;
4190 if( eMode == ePositionMode )
4191 return;
4193 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
4194 ePositionMode = eMode;
4195 ULONG nCount = aEntries.Count();
4197 if( eOldMode == IcnViewPositionModeAutoArrange )
4199 // positionieren wir verschobene Eintraege 'hart' gibts noch Probleme
4200 // mit ungewollten Ueberlappungen, da diese Eintrage im Arrange
4201 // nicht beruecksichtigt werden.
4202 #if 1
4203 if( aEntries.Count() )
4204 aAutoArrangeTimer.Start();
4205 #else
4206 if( pHead )
4208 // verschobene Eintraege 'hart' auf ihre Position setzen
4209 nCur = nCount;
4210 SvxIconChoiceCtrlEntry* pEntry = pHead;
4211 while( nCur )
4213 SvxIconChoiceCtrlEntry* pPred;
4214 if( GetEntryPredecessor( pEntry, &pPred ))
4215 SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED );
4216 pEntry = pEntry->pflink;
4217 nCur--;
4219 ClearPredecessors();
4221 #endif
4222 return;
4225 if( ePositionMode == IcnViewPositionModeAutoArrange )
4227 List aMovedEntries;
4228 for( nCur = 0; nCur < nCount; nCur++ )
4230 SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
4231 if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
4233 SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl(
4234 pEntry, GetEntryBoundRect( pEntry ));
4235 aMovedEntries.Insert( pE, LIST_APPEND );
4238 nCount = aMovedEntries.Count();
4239 for( nCur = 0; nCur < nCount; nCur++ )
4241 SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur);
4242 SetEntryPos( pE->_pEntry, pE->_aPos );
4244 for( nCur = 0; nCur < nCount; nCur++ )
4245 delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur );
4246 if( aEntries.Count() )
4247 aAutoArrangeTimer.Start();
4249 else if( ePositionMode == IcnViewPositionModeAutoAdjust )
4251 AdjustEntryAtGrid( 0 );
4255 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4256 SvxIconChoiceCtrlEntry* pPredecessor )
4258 if( !IsAutoArrange() )
4259 return;
4261 if( pEntry == pPredecessor )
4262 return;
4264 ULONG nPos1 = GetEntryListPos( pEntry );
4265 if( !pHead )
4267 if( pPredecessor )
4269 ULONG nPos2 = GetEntryListPos( pPredecessor );
4270 if( nPos1 == (nPos2 + 1) )
4271 return; // ist schon Vorgaenger
4273 else if( !nPos1 )
4274 return;
4277 if( !pHead )
4278 InitPredecessors();
4280 if( !pPredecessor && pHead == pEntry )
4281 return; // ist schon der Erste
4283 BOOL bSetHead = FALSE;
4284 if( !pPredecessor )
4286 bSetHead = TRUE;
4287 pPredecessor = pHead->pblink;
4289 if( pEntry == pHead )
4291 pHead = pHead->pflink;
4292 bSetHead = FALSE;
4294 if( pEntry != pPredecessor )
4296 pEntry->Unlink();
4297 pEntry->SetBacklink( pPredecessor );
4299 if( bSetHead )
4300 pHead = pEntry;
4301 pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
4302 aAutoArrangeTimer.Start();
4305 BOOL SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4306 SvxIconChoiceCtrlEntry** ppPredecessor )
4308 *ppPredecessor = 0;
4309 if( !pHead )
4310 return FALSE;
4311 DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set");
4312 DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set");
4314 if( pEntry == pHead )
4316 SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0);
4317 if( pFirst != pEntry )
4318 return TRUE;
4319 return FALSE;
4321 *ppPredecessor = pEntry->pblink;
4322 if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) &&
4323 (GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry ))
4324 return FALSE;
4325 return TRUE;
4328 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4329 const Point& rPosTopLeft )
4331 Point aPos( rPosTopLeft ); //TopLeft
4332 Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
4333 Point aNewPos( aCenterRect.Center() );
4334 ULONG nGrid = GetPredecessorGrid( aNewPos );
4335 ULONG nCount = aEntries.Count();
4336 if( nGrid == ULONG_MAX )
4337 return 0;
4338 if( nGrid >= nCount )
4339 nGrid = nCount - 1;
4340 if( !pHead )
4341 return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid );
4343 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
4344 // todo: Liste von hinten aufrollen wenn nGrid > nCount/2
4345 for( ULONG nCur = 0; nCur < nGrid; nCur++ )
4346 pCur = pCur->pflink;
4348 return pCur;
4351 ULONG SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
4353 Point aPos( rPos );
4354 aPos.X() -= LROFFS_WINBORDER;
4355 aPos.Y() -= TBOFFS_WINBORDER;
4356 USHORT nMaxCol = (USHORT)(aVirtOutputSize.Width() / nGridDX);
4357 if( nMaxCol )
4358 nMaxCol--;
4359 USHORT nGridX = (USHORT)(aPos.X() / nGridDX);
4360 if( nGridX > nMaxCol )
4361 nGridX = nMaxCol;
4362 USHORT nGridY = (USHORT)(aPos.Y() / nGridDY);
4363 USHORT nGridsX = (USHORT)(aOutputSize.Width() / nGridDX);
4364 ULONG nGrid = (nGridY * nGridsX) + nGridX;
4365 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
4366 if( rPos.X() < nMiddle )
4368 if( !nGrid )
4369 nGrid = ULONG_MAX;
4370 else
4371 nGrid--;
4373 return nGrid;
4376 void SvxIconChoiceCtrl_Impl::Flush()
4378 if( aAutoArrangeTimer.IsActive() )
4380 AutoArrangeHdl( 0 );
4384 BOOL SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
4386 if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
4387 return FALSE;
4389 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
4390 aPos -= pView->GetMapMode().GetOrigin();
4391 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, TRUE );
4393 if ( !pEntry )
4394 return FALSE;
4396 String sQuickHelpText = pEntry->GetQuickHelpText();
4397 String aEntryText( pView->GetEntryText( pEntry, FALSE ) );
4398 Rectangle aTextRect( CalcTextRect( pEntry, 0, FALSE, &aEntryText ) );
4399 if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
4400 return FALSE;
4402 Rectangle aOptTextRect( aTextRect );
4403 aOptTextRect.Bottom() = LONG_MAX;
4404 USHORT nNewFlags = nCurTextDrawFlags;
4405 nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
4406 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
4407 if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
4409 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
4410 Point aPt( aOptTextRect.TopLeft() );
4411 aPt += pView->GetMapMode().GetOrigin();
4412 aPt = pView->OutputToScreenPixel( aPt );
4413 // Border der Tiphilfe abziehen
4414 aPt.Y() -= 1;
4415 aPt.X() -= 3;
4416 aOptTextRect.SetPos( aPt );
4417 String sHelpText;
4418 if ( sQuickHelpText.Len() > 0 )
4419 sHelpText = sQuickHelpText;
4420 else
4421 sHelpText = aEntryText;
4422 Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
4425 return TRUE;
4428 void SvxIconChoiceCtrl_Impl::ClearColumnList()
4430 if( !pColumns )
4431 return;
4433 const USHORT nCount = pColumns->Count();
4434 for( USHORT nCur = 0; nCur < nCount; nCur++ )
4436 SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*)
4437 pColumns->GetObject( nCur );
4438 delete pInfo;
4440 DELETEZ(pColumns);
4443 void SvxIconChoiceCtrl_Impl::SetColumn( USHORT nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
4445 if( !pColumns )
4446 pColumns = new SvPtrarr;
4447 while( pColumns->Count() < nIndex + 1 )
4448 pColumns->Insert( (void*)0, pColumns->Count() );
4450 SvxIconChoiceCtrlColumnInfo* pInfo =
4451 (SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex);
4452 if( !pInfo )
4454 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4455 pColumns->Insert( (void*)pInfo, nIndex );
4457 else
4459 delete pInfo;
4460 pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4461 pColumns->Replace( pInfo, nIndex );
4464 // HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
4465 // dieses Workaround bringts mit einer Spalte zum Fliegen
4466 if( !nIndex && (nWinBits & WB_DETAILS) )
4467 nGridDX = pInfo->GetWidth();
4469 if( GetUpdateMode() )
4470 Arrange( IsAutoArrange() );
4473 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( USHORT nIndex ) const
4475 if( !pColumns || nIndex >= pColumns->Count() )
4476 return 0;
4477 return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex );
4480 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( USHORT nSubItem,
4481 long& rLeft ) const
4483 rLeft = 0;
4484 if( !pColumns )
4485 return 0;
4486 const USHORT nCount = pColumns->Count();
4487 const SvxIconChoiceCtrlColumnInfo* pCol = 0;
4488 for( USHORT nCur = 0; nCur < nCount; nCur++ )
4490 pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur );
4491 if( !pCol || pCol->GetSubItem() == nSubItem )
4492 return pCol;
4493 rLeft += pCol->GetWidth();
4495 return pCol;
4498 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
4499 OutputDevice* pOut, const Rectangle& rBmpRect, BOOL bHide )
4501 Rectangle aBmpRect( rBmpRect );
4502 long nBorder = 2;
4503 if( aImageSize.Width() < 32 )
4504 nBorder = 1;
4505 aBmpRect.Right() += nBorder;
4506 aBmpRect.Left() -= nBorder;
4507 aBmpRect.Bottom() += nBorder;
4508 aBmpRect.Top() -= nBorder;
4510 if ( bHide )
4511 pView->Invalidate( aBmpRect );
4512 else
4514 DecorationView aDecoView( pOut );
4515 USHORT nDecoFlags;
4516 if ( bHighlightFramePressed )
4517 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
4518 else
4519 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
4520 aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
4524 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
4525 BOOL bKeepHighlightFlags )
4527 if( pEntry == pCurHighlightFrame )
4528 return;
4530 if( !bKeepHighlightFlags )
4531 bHighlightFramePressed = FALSE;
4533 HideEntryHighlightFrame();
4534 pCurHighlightFrame = pEntry;
4535 if( pEntry )
4537 Rectangle aBmpRect( CalcFocusRect(pEntry) );
4538 DrawHighlightFrame( pView, aBmpRect, FALSE );
4542 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
4544 if( !pCurHighlightFrame )
4545 return;
4547 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
4548 pCurHighlightFrame = 0;
4549 Rectangle aBmpRect( CalcFocusRect(pEntry) );
4550 DrawHighlightFrame( pView, aBmpRect, TRUE );
4553 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
4555 // Bei aktiviertem Single-Click-Modus sollte der Selektionshandler
4556 // synchron gerufen werden, weil die Selektion automatisch
4557 // weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt
4558 // beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen,
4559 // wenn das Objekt aus einer Mausbewegung heraus selektiert wird,
4560 // weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U.
4561 // schon verlassen hat.
4562 // Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone
4563 // Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden.
4564 if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
4566 pHdlEntry = 0;
4567 pView->ClickIcon();
4568 //pView->Select();
4570 else
4571 aCallSelectHdlTimer.Start();
4574 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG )
4576 pHdlEntry = 0;
4577 pView->ClickIcon();
4578 //pView->Select();
4579 return 0;
4582 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
4584 Point aResult;
4585 if( !GetSelectionCount() )
4586 return aResult;
4588 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
4589 if( !pEntry || !pEntry->IsSelected() )
4591 ULONG nNext;
4592 pEntry = GetFirstSelectedEntry( nNext );
4594 if( pEntry )
4596 Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) );
4597 aResult = aRect.Center();
4598 aResult = pView->GetPixelPos( aResult );
4600 return aResult;
4603 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, BOOL bDoNotUpdateWallpaper )
4605 MapMode aMapMode( pView->GetMapMode() );
4606 aMapMode.SetOrigin( rPos );
4607 pView->SetMapMode( aMapMode );
4608 if( !bDoNotUpdateWallpaper )
4610 BOOL bScrollable = pView->GetBackground().IsScrollable();
4611 if( pView->HasBackground() && !bScrollable )
4613 Rectangle aRect( GetOutputRect());
4614 Wallpaper aPaper( pView->GetBackground() );
4615 aPaper.SetRect( aRect );
4616 pView->SetBackground( aPaper );
4621 ULONG SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, BOOL bCheckScrBars,
4622 BOOL bSmartScrBar ) const
4624 Size aSize( rSize );
4625 if( bCheckScrBars && aHorSBar.IsVisible() )
4626 aSize.Height() -= nHorSBarHeight;
4627 else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) )
4628 aSize.Height() -= nHorSBarHeight;
4630 if( bCheckScrBars && aVerSBar.IsVisible() )
4631 aSize.Width() -= nVerSBarWidth;
4632 else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) )
4633 aSize.Width() -= nVerSBarWidth;
4635 if( aSize.Width() < 0 )
4636 aSize.Width() = 0;
4637 if( aSize.Height() < 0 )
4638 aSize.Height() = 0;
4640 return IcnGridMap_Impl::GetGridCount( aSize, (USHORT)nGridDX, (USHORT)nGridDY );
4643 BOOL SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt )
4645 StopEditTimer();
4647 BOOL bRet = FALSE;
4649 DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" );
4651 sal_Unicode cChar = rKEvt.GetCharCode();
4652 ULONG nPos = (ULONG)-1;
4654 if( cChar && IsMnemonicChar( cChar, nPos ) )
4656 // shortcut is clicked
4657 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
4658 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
4659 if( pNewCursor != pOldCursor )
4661 SetCursor_Impl( pOldCursor, pNewCursor, FALSE, FALSE, FALSE );
4663 if( pNewCursor != NULL )
4665 pHdlEntry = pNewCursor;
4666 pCurHighlightFrame = pHdlEntry;
4667 pView->ClickIcon();
4668 pCurHighlightFrame = NULL;
4671 bRet = TRUE;
4674 return bRet;
4677 // -----------------------------------------------------------------------
4679 void SvxIconChoiceCtrl_Impl::CallEventListeners( ULONG nEvent, void* pData )
4681 pView->CallImplEventListeners( nEvent, pData );