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 $
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"
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>
47 #include "imivctl.hxx"
48 #include <svtools/svmedit.hxx>
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
;
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
81 Accelerator aAccReturn
;
82 Accelerator aAccEscape
;
85 BOOL bAlreadyInCallback
;
88 void CallCallBackHdl_Impl();
89 DECL_LINK( Timeout_Impl
, Timer
* );
90 DECL_LINK( ReturnHdl_Impl
, Accelerator
* );
91 DECL_LINK( EscapeHdl_Impl
, Accelerator
* );
96 SvtIconChoiceCtrl
* pParent
,
99 const XubString
& rData
,
100 const Link
& rNotifyEditEnd
);
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
) :
117 aVerSBar( pCurView
, WB_DRAG
| WB_VSCROLL
),
118 aHorSBar( pCurView
, WB_DRAG
| WB_HSCROLL
),
119 aScrBarBox( pCurView
),
120 aImageSize( 32, 32 ),
123 bChooseWithCursor
=FALSE
;
126 pCurHighlightFrame
= 0;
129 pDraggedSelection
= 0;
135 bEntryEditingEnabled
= FALSE
;
137 bHighlightFramePressed
= FALSE
;
138 eSelectionMode
= MULTIPLE_SELECTION
;
140 pZOrderList
= new List
; //SvPtrarr;
141 ePositionMode
= IcnViewPositionModeFree
;
142 SetStyle( nWinStyle
);
144 nUserEventAdjustScrBars
= 0;
145 nUserEventShowCursor
= 0;
146 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
147 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
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
));
179 SetGrid( Size(100, 70) );
182 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
195 delete pDraggedSelection
;
196 delete pEntryPaintDev
;
197 ClearSelectedRectList();
201 void SvxIconChoiceCtrl_Impl::Clear( BOOL bInCtor
)
203 StopEntryEditing( TRUE
);
205 DELETEZ(pDraggedSelection
);
207 pCurHighlightFrame
= 0;
211 bBoundRectsDirty
= FALSE
;
214 nFlags
&= ~(F_PAINTED
| F_MOVED_ENTRIES
);
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() );
232 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
235 ULONG nCount
= aEntries
.Count();
236 for( ULONG nCur
= 0; nCur
< nCount
; nCur
++ )
238 SvxIconChoiceCtrlEntry
* pCur
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( nCur
);
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
))
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
;
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
;
281 IMPL_LINK( SvxIconChoiceCtrl_Impl
, EndScrollHdl
, void*, EMPTYARG
)
283 if( pView
->HasBackground() && !pView
->GetBackground().IsScrollable() &&
284 bEndScrollInvalidate
)
286 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
291 void SvxIconChoiceCtrl_Impl::FontModified()
297 DELETEZ(pEntryPaintDev
);
298 SetDefaultTextSize();
303 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry
* pEntry
, ULONG nPos
,
307 aEntries
.Insert( pEntry
, nPos
);
308 if( (nFlags
& F_ENTRYLISTPOS_VALID
) && nPos
>= aEntries
.Count() - 1 )
309 pEntry
->nPos
= aEntries
.Count() - 1;
311 nFlags
&= ~F_ENTRYLISTPOS_VALID
;
313 pZOrderList
->Insert( (void*)pEntry
, LIST_APPEND
); //pZOrderList->Count() );
315 // pGridMap->Clear();
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
);
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
;
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
);
340 InvalidateBoundingRect( pEntry
->aRect
);
344 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator
* _pGenerator
)
346 ::std::auto_ptr
< MnemonicGenerator
> pAutoDeleteOwnGenerator
;
349 _pGenerator
= new MnemonicGenerator
;
350 pAutoDeleteOwnGenerator
.reset( _pGenerator
);
353 ULONG nEntryCount
= GetEntryCount();
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() );
379 return Rectangle( aOrigin
, aOutputSize
);
382 void SvxIconChoiceCtrl_Impl::SetListPositions()
384 if( nFlags
& F_ENTRYLISTPOS_VALID
)
387 ULONG nCount
= aEntries
.Count();
388 for( ULONG nCur
= 0; nCur
< nCount
; nCur
++ )
390 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( 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
;
405 bSyncSingleSelection
= FALSE
;
407 if( pEntry
== pCurHighlightFrame
)
408 pCurHighlightFrame
= 0;
412 DELETEZ(pDraggedSelection
);
416 if( pEntry
->IsSelected() )
417 CallSelectHandler( 0 );
419 if( aEntries
.Count() == 1 && aEntries
.GetObject(0) == pEntry
)
426 if( pEntry
== pAnchor
)
428 if( pEntry
->IsSelected() )
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();
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
);
456 aEntries
.Remove( pEntry
);
460 if( IsAutoArrange() && aEntries
.Count() )
461 aAutoArrangeTimer
.Start();
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
)
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
)
488 USHORT nEntryFlags
= pEntry
->GetFlags();
491 nEntryFlags
|= ICNVIEW_FLAG_SELECTED
;
492 pEntry
->AssignFlags( nEntryFlags
);
495 CallSelectHandler( pEntry
);
499 nEntryFlags
&= ~( ICNVIEW_FLAG_SELECTED
);
500 pEntry
->AssignFlags( nEntryFlags
);
503 CallSelectHandler( 0 );
505 EntrySelected( pEntry
, bSelect
, bSyncPaint
);
509 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry
* pEntry
, BOOL bSelect
,
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
&&
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
) )
529 if( pEntry
== pCursor
)
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
);
537 pView
->Invalidate( CalcFocusRect( pEntry
) );
539 if( pEntry
== pCursor
)
541 } // if( bUpdateMode )
543 // --> OD 2009-05-27 #i101012#
544 // emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
547 CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pEntry
);
552 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
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
);
569 AdjustVirtSize( pCur
->aRect
);
570 bLockedEntryFound
= TRUE
;
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
;
599 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle
& rRect
)
601 long nHeightOffs
= 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
)
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
);
622 pGridMap
->OutputSizeChanged();
628 void SvxIconChoiceCtrl_Impl::InitPredecessors()
630 DBG_ASSERT(!pHead
,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
631 ULONG nCount
= aEntries
.Count();
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
;
642 pNext
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( 0 );
644 pNext
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( nCur
);
645 pPrev
->pflink
= pNext
;
646 pNext
->pblink
= pPrev
;
649 pHead
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( 0 );
653 nFlags
&= ~F_MOVED_ENTRIES
;
656 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
660 ULONG nCount
= aEntries
.Count();
661 for( ULONG nCur
= 0; nCur
< nCount
; nCur
++ )
663 SvxIconChoiceCtrlEntry
* pCur
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( nCur
);
666 pCur
->ClearFlags( ICNVIEW_FLAG_PRED_SET
);
672 void SvxIconChoiceCtrl_Impl::Arrange( BOOL bKeepPredecessors
, long nSetMaxVirtWidth
, long nSetMaxVirtHeight
)
674 if ( nSetMaxVirtWidth
!= 0 )
675 nMaxVirtWidth
= nSetMaxVirtWidth
;
677 nMaxVirtWidth
= aOutputSize
.Width();
679 if ( nSetMaxVirtHeight
!= 0 )
680 nMaxVirtHeight
= nSetMaxVirtHeight
;
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
)
695 aAutoArrangeTimer
.Stop();
696 nFlags
&= ~F_MOVED_ENTRIES
;
697 nFlags
|= F_ARRANGING
;
701 if( !bKeepPredecessors
)
703 bBoundRectsDirty
= FALSE
;
704 SetOrigin( Point() );
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
);
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());
735 pView
->DrawLine( aStart
, aEnd
);
738 Point
aStart( 0, TBOFFS_WINBORDER
);
739 Point
aEnd( aXSize
.Width(), TBOFFS_WINBORDER
);
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());
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
);
759 pView
->DrawLine( aStart
, aEnd
);
761 pView
->SetLineColor( aOldColor
);
765 if( !aEntries
.Count() )
769 // set cursor to item with focus-flag
771 for ( ULONG i
= 0; i
< pView
->GetEntryCount() && !bfound
; i
++)
773 SvxIconChoiceCtrlEntry
* pEntry
= pView
->GetEntry ( i
);
774 if( pEntry
->IsFocused() )
782 pCursor
= (SvxIconChoiceCtrlEntry
*)aEntries
.First();
785 // Show Focus at Init-Time
786 if ( pView
->HasFocus() )
789 ULONG nCount
= pZOrderList
->Count();
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
);
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
);
818 pNewZOrderList
->Insert( pEntry
, LIST_APPEND
);
824 pZOrderList
= pNewZOrderList
;
825 nCount
= pPaintedEntries
->Count();
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();
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
;
891 BOOL bGotFocus
= (BOOL
)(!pView
->HasFocus() && !(nWinBits
& WB_NOPOINTERFOCUS
));
892 if( !(nWinBits
& WB_NOPOINTERFOCUS
) )
895 Point
aDocPos( rMEvt
.GetPosPixel() );
896 if(aDocPos
.X()>=aOutputSize
.Width() || aDocPos
.Y()>=aOutputSize
.Height())
899 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, TRUE
);
901 MakeEntryVisible( pEntry
, FALSE
);
903 if( rMEvt
.IsShift() && eSelectionMode
!= SINGLE_SELECTION
)
906 SetCursor_Impl( pCursor
, pEntry
, rMEvt
.IsMod1(), rMEvt
.IsShift(), TRUE
);
910 if( pAnchor
&& (rMEvt
.IsShift() || rMEvt
.IsMod1())) // Tastaturselektion?
912 DBG_ASSERT(eSelectionMode
!= SINGLE_SELECTION
,"Invalid selection mode");
914 nFlags
|= F_ADD_MODE
;
916 if( rMEvt
.IsShift() )
918 Rectangle
aRect( GetEntryBoundRect( pAnchor
));
920 aRect
.Union( GetEntryBoundRect( pEntry
) );
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
);
933 aCurSelectionRect
.SetPos( aDocPos
);
936 if( !pEntry
&& !(nWinBits
& WB_NODRAGSELECTION
))
937 pView
->StartTracking( STARTTRACK_SCROLLREPEAT
);
944 if( eSelectionMode
== MULTIPLE_SELECTION
)
946 if( !rMEvt
.IsMod1() ) // Ctrl
951 ClearSelectedRectList();
955 nFlags
|= F_ADD_MODE
;
956 aCurSelectionRect
.SetPos( aDocPos
);
957 pView
->StartTracking( STARTTRACK_SCROLLREPEAT
);
964 BOOL bSelected
= pEntry
->IsSelected();
965 BOOL bEditingEnabled
= IsEntryEditingEnabled();
967 if( rMEvt
.GetClicks() == 2 )
969 DeselectAllBut( pEntry
);
970 SelectEntry( pEntry
, TRUE
, TRUE
, FALSE
, TRUE
);
977 if( rMEvt
.IsMod2() ) // Alt?
979 if( bEntryEditingEnabled
&& pEntry
&&
980 pEntry
->IsSelected())
982 if( pView
->EditingEntry( pEntry
))
986 else if( eSelectionMode
== SINGLE_SELECTION
)
988 DeselectAllBut( 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
);
1007 if( !rMEvt
.GetModifier() && rMEvt
.IsLeft() )
1011 DeselectAllBut( pEntry
, TRUE
/* Synchron painten */ );
1012 SetCursor( pEntry
);
1013 SelectEntry( pEntry
, TRUE
, TRUE
, FALSE
, TRUE
);
1017 // erst im Up deselektieren, falls Move per D&D!
1018 nFlags
|= F_DOWN_DESELECT
;
1019 if( bEditingEnabled
&& IsTextHit( pEntry
, aDocPos
) &&
1022 nFlags
|= F_START_EDITTIMER_IN_MOUSEUP
;
1026 else if( rMEvt
.IsMod1() )
1027 nFlags
|= F_DOWN_CTRL
;
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
);
1042 Point
aDocPos( rMEvt
.GetPosPixel() );
1043 ToDocPos( aDocPos
);
1044 SvxIconChoiceCtrlEntry
* pDocEntry
= GetEntry( aDocPos
);
1047 if( nFlags
& F_DOWN_CTRL
)
1049 // Ctrl & MultiSelection
1050 ToggleSelection( pDocEntry
);
1051 SetCursor( pDocEntry
);
1054 else if( nFlags
& F_DOWN_DESELECT
)
1056 DeselectAllBut( pDocEntry
);
1057 SetCursor( pDocEntry
);
1058 SelectEntry( pDocEntry
, TRUE
, TRUE
, FALSE
, TRUE
);
1063 nFlags
&= ~(F_DOWN_CTRL
| F_DOWN_DESELECT
);
1064 if( nFlags
& F_START_EDITTIMER_IN_MOUSEUP
)
1068 nFlags
&= ~F_START_EDITTIMER_IN_MOUSEUP
;
1071 if((nWinBits
& WB_HIGHLIGHTFRAME
) && bHighlightFramePressed
&& pCurHighlightFrame
)
1074 SvxIconChoiceCtrlEntry
* pEntry
= pCurHighlightFrame
;
1075 pCurHighlightFrame
= 0; // Neues painten des Frames erzwingen
1076 bHighlightFramePressed
= FALSE
;
1077 SetEntryHighlightFrame( pEntry
, TRUE
);
1079 CallSelectHandler( pCurHighlightFrame
);
1081 pHdlEntry
= pCurHighlightFrame
;
1084 // set focus on Icon
1085 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
1086 SetCursor_Impl( pOldCursor
, pHdlEntry
, FALSE
, FALSE
, TRUE
);
1093 BOOL
SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent
& rMEvt
)
1095 const Point
aDocPos( pView
->PixelToLogic(rMEvt
.GetPosPixel()) );
1097 if( pView
->IsTracking() )
1099 else if( nWinBits
& WB_HIGHLIGHTFRAME
)
1101 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, TRUE
);
1102 SetEntryHighlightFrame( pEntry
);
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
1116 AddSelectedRect( aCurSelectionRect
);
1117 pView
->HideTracking();
1118 nFlags
&= ~(F_ADD_MODE
);
1119 if( rTEvt
.IsTrackingCanceled() )
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
)
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
;
1165 DeselectAllBut( pFilterEntry
, bPaintSync
);
1166 ShowCursor( FALSE
);
1167 MakeEntryVisible( pNewCursor
);
1168 SetCursor( pNewCursor
);
1169 if( bMod1
&& !bShift
)
1173 AddSelectedRect( pAnchor
, pOldCursor
);
1180 pAnchor
= pOldCursor
;
1181 if ( nWinBits
& WB_ALIGN_LEFT
)
1182 SelectRange( pAnchor
, pNewCursor
, (nFlags
& F_ADD_MODE
)!=0 );
1184 SelectRect(pAnchor
,pNewCursor
,(nFlags
& F_ADD_MODE
)!=0,&aSelectedRectList
);
1188 SelectEntry( pCursor
, TRUE
, TRUE
, FALSE
, bPaintSync
);
1189 aCurSelectionRect
= GetEntryBoundRect( pCursor
);
1194 BOOL
SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent
& rKEvt
)
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
);
1212 // no actions with <ALT>
1215 BOOL bKeyUsed
= TRUE
;
1216 BOOL bMod1
= rKEvt
.GetKeyCode().IsMod1();
1217 BOOL bShift
= rKEvt
.GetKeyCode().IsShift();
1219 if( eSelectionMode
== SINGLE_SELECTION
|| eSelectionMode
== NO_SELECTION
)
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();
1246 MakeEntryVisible( pCursor
);
1247 if( nCode
== KEY_UP
)
1248 pNewCursor
= pImpCursor
->GoUpDown(pCursor
,FALSE
);
1250 pNewCursor
= pImpCursor
->GoPageUpDown(pCursor
,FALSE
);
1251 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, TRUE
);
1254 Rectangle
aRect( GetEntryBoundRect( pCursor
) );
1257 aRect
.Bottom() -= aRect
.Top();
1259 MakeVisible( aRect
);
1263 if ( bChooseWithCursor
&& pNewCursor
!= NULL
)
1265 pHdlEntry
= pNewCursor
;//GetCurEntry();
1266 pCurHighlightFrame
= pHdlEntry
;
1268 pCurHighlightFrame
= NULL
;
1277 if( nCode
== KEY_DOWN
)
1278 pNewCursor
=pImpCursor
->GoUpDown( pCursor
,TRUE
);
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
;
1288 pCurHighlightFrame
= NULL
;
1296 pNewCursor
=pImpCursor
->GoLeftRight(pCursor
,TRUE
);
1297 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, TRUE
);
1304 MakeEntryVisible( pCursor
);
1305 pNewCursor
= pImpCursor
->GoLeftRight(pCursor
,FALSE
);
1306 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, TRUE
);
1309 Rectangle
aRect( GetEntryBoundRect(pCursor
));
1312 aRect
.Right() -= aRect
.Left();
1314 MakeVisible( aRect
);
1320 // wird vom VCL-Tracking gesteuert
1323 if( pView
->IsTracking() )
1325 HideSelectionRect();
1326 //SelectAll( FALSE );
1328 ClearSelectedRectList();
1329 nFlags
&= ~F_TRACKING
;
1338 if( !bMod1
&& !bShift
)
1339 EditTimeoutHdl( 0 );
1345 if( rKEvt
.GetKeyCode().IsShift() )
1347 if( nFlags
& F_ADD_MODE
)
1348 nFlags
&= (~F_ADD_MODE
);
1350 nFlags
|= F_ADD_MODE
;
1357 if( pCursor
&& eSelectionMode
!= SINGLE_SELECTION
)
1361 //SelectAll( FALSE );
1363 ClearSelectedRectList();
1365 // click Icon with spacebar
1366 SetEntryHighlightFrame( GetCurEntry(), TRUE
);
1368 pHdlEntry
= pCurHighlightFrame
;
1369 pCurHighlightFrame
=0;
1372 ToggleSelection( pCursor
);
1378 if( rKEvt
.GetKeyCode().IsShift() )
1381 pView
->SetEntryTextMode( IcnShowTextFull
, pCursor
);
1383 if( rKEvt
.GetKeyCode().IsMod1() )
1386 pView
->SetEntryTextMode( IcnShowTextShort
, pCursor
);
1394 if( bMod1
&& (eSelectionMode
!= SINGLE_SELECTION
))
1411 if( pCursor
&& bEntryEditingEnabled
)
1412 /*pView->*/EditEntry( pCursor
);
1421 pNewCursor
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( aEntries
.Count() - 1 );
1422 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, TRUE
);
1429 pNewCursor
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( 0 );
1430 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, TRUE
);
1441 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
1442 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth
, long nRealHeight
)
1445 Point
aPos( 0, nRealHeight
);
1446 aPos
.Y() -= nHorSBarHeight
;
1448 if( aHorSBar
.GetPosPixel() != aPos
)
1449 aHorSBar
.SetPosPixel( aPos
);
1452 aPos
.X() = nRealWidth
; aPos
.Y() = 0;
1453 aPos
.X() -= nVerSBarWidth
;
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() );
1477 if( nRealWidth
> nVirtWidth
)
1478 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1480 nVisibleWidth
= nRealWidth
;
1482 long nVisibleHeight
;
1483 if( nRealHeight
> nVirtHeight
)
1484 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
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;
1496 // activate ver scrollbar ?
1497 if( !bNoVerSBar
&& (bVerSBar
|| ( nVirtHeight
> nVisibleHeight
)) )
1500 nRealWidth
-= nVerSBarWidth
;
1502 if( nRealWidth
> nVirtWidth
)
1503 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1505 nVisibleWidth
= nRealWidth
;
1507 nFlags
|= F_HOR_SBARSIZE_WITH_VBAR
;
1509 // activate hor scrollbar ?
1510 if( !bNoHorSBar
&& (bHorSBar
|| (nVirtWidth
> nVisibleWidth
)) )
1513 nRealHeight
-= nHorSBarHeight
;
1515 if( nRealHeight
> nVirtHeight
)
1516 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
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();
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
);
1553 aVerSBar
.SetThumbPos( 0 );
1557 // size hor scrollbar
1558 nThumb
= aHorSBar
.GetThumbPos();
1559 aSize
.Width() = nRealWidth
;
1560 aSize
.Height() = nHorSBarHeight
;
1562 if( nResult
& 0x0001 ) // vertikale Scrollbar ?
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
);
1578 aHorSBar
.SetThumbPos( 0 );
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) )
1601 void SvxIconChoiceCtrl_Impl::Resize()
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
);
1631 BOOL
SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1633 if( !pZOrderList
|| !aHorSBar
.IsVisible() )
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
)
1648 if( nRight
> nMostRight
)
1649 nMostRight
= nRight
;
1652 aOutputSize
.Height() += nHorSBarHeight
;
1653 aVirtOutputSize
.Width() = nMostRight
;
1654 aHorSBar
.SetThumbPos( 0 );
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
);
1669 BOOL
SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1671 if( !pZOrderList
|| !aVerSBar
.IsVisible() )
1673 const MapMode
& rMapMode
= pView
->GetMapMode();
1674 Point
aOrigin( rMapMode
.GetOrigin() );
1675 if(!( nWinBits
& WB_VSCROLL
) && !aOrigin
.Y() )
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
)
1686 if( nBottom
> nDeepest
)
1690 aOutputSize
.Width() += nVerSBarWidth
;
1691 aVirtOutputSize
.Height() = nDeepest
;
1692 aVerSBar
.SetThumbPos( 0 );
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
);
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() )
1721 void SvxIconChoiceCtrl_Impl::GetFocus()
1723 RepaintEntries( ICNVIEW_FLAG_SELECTED
);
1726 pCursor
->SetFlags( ICNVIEW_FLAG_FOCUSED
);
1731 void SvxIconChoiceCtrl_Impl::LoseFocus()
1735 pCursor
->ClearFlags( ICNVIEW_FLAG_FOCUSED
);
1736 ShowCursor( FALSE
);
1739 // pView->Invalidate ( aFocus.aRect );
1741 RepaintEntries( ICNVIEW_FLAG_SELECTED
);
1744 void SvxIconChoiceCtrl_Impl::SetUpdateMode( BOOL bUpdate
)
1746 if( bUpdate
!= bUpdateMode
)
1748 bUpdateMode
= bUpdate
;
1752 pImpCursor
->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
);
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
);
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
;
1800 if ( !bSelected
|| bCursored
)
1802 if( !pView
->HasFontFillColor() )
1803 pOut
->SetFillColor( pOut
->GetBackground().GetColor() );
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
);
1822 Color aOldLineColor
;
1825 aOldLineColor
= pOut
->GetLineColor();
1826 pOut
->SetLineColor( Color( COL_GRAY
) );
1828 pOut
->DrawRect( rTextRect
);
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)
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
)
1856 aText
= pView
->GetEntryText( pEntry
, FALSE
);
1862 pOut
->DrawText( rRect
, aText
, nCurTextDrawFlags
,
1863 &_pLayoutData
->m_aUnicodeBoundRects
, &_pLayoutData
->m_aDisplayText
);
1867 Color aOldFontColor
= pOut
->GetTextColor();
1868 if ( pView
->AutoFontColor() )
1870 Color
aBkgColor( pOut
->GetBackground().GetColor() );
1872 USHORT nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
1874 aFontColor
.SetColor ( COL_BLACK
);
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
);
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
);
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
) )
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
);
1949 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
1950 OutputDevice
* pOut
, BOOL bIsBackgroundPainted
)
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() );
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
)
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() );
1999 aNewFont
.SetFillColor( rSettings
.GetDeactiveColor() );
2002 Color aWinCol
= rSettings
.GetWindowTextColor();
2003 if ( !bActiveSelection
&& rSettings
.GetFaceColor().IsBright() == aWinCol
.IsBright() )
2004 aNewFont
.SetColor( rSettings
.GetWindowTextColor() );
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
);
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
;
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
);
2071 if( !IsAutoArrange() )
2073 BOOL bAdjustVirtSize
= FALSE
;
2074 if( rPos
!= aBoundRect
.TopLeft() )
2077 pEntry
->aGridRect
.TopLeft() - pEntry
->aRect
.TopLeft() );
2078 pImpCursor
->Clear();
2081 aBoundRect
.SetPos( rPos
);
2082 pEntry
->aRect
= aBoundRect
;
2083 pEntry
->aGridRect
.SetPos( rPos
+ aGridOffs
);
2084 bAdjustVirtSize
= TRUE
;
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
);
2108 if( bAdjustVirtSize
)
2109 AdjustVirtSize( pEntry
->aRect
);
2111 if( bCheckScrollBars
&& bUpdateMode
)
2114 pView
->Invalidate( pEntry
->aRect
);
2115 pGridMap
->OccupyGrids( pEntry
);
2119 SvxIconChoiceCtrlEntry
* pPrev
= FindEntryPredecessor( pEntry
, rPos
);
2120 SetEntryPredecessor( pEntry
, pPrev
);
2121 aAutoArrangeTimer
.Start();
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();
2145 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)(pZOrderList
->GetObject(nCount
));
2146 if( pEntry
->aRect
.IsInside( rDocPos
) )
2150 Rectangle aRect
= CalcBmpRect( pEntry
);
2152 aRect
.Bottom() += 3;
2155 if( aRect
.IsInside( rDocPos
) )
2157 aRect
= CalcTextRect( pEntry
);
2158 if( aRect
.IsInside( rDocPos
) )
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
) )
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 )
2199 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)(pZOrderList
->GetObject(nStartPos
));
2200 if( pEntry
->aRect
.IsInside( rDocPos
) )
2205 } while( nStartPos
> 0 );
2210 Point
SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry
* pEntry
)
2212 return pEntry
->aRect
.TopLeft();
2215 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry
* pEntry
, BOOL bBound
)
2219 const Rectangle
& rRect
= GetEntryBoundRect( pEntry
);
2220 MakeVisible( rRect
);
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
);
2245 aBound
.SetPos( *pPos
);
2246 Point
aPos( aBound
.TopLeft() );
2248 switch( nWinBits
& (VIEWMODE_MASK
) )
2252 aPos
.X() += ( aBound
.GetWidth() - aImageSize
.Width() ) / 2;
2253 return Rectangle( aPos
, aImageSize
);
2258 aPos
.Y() += ( aBound
.GetHeight() - aImageSize
.Height() ) / 2;
2259 //todo: hor. Abstand zum BoundRect?
2260 return Rectangle( aPos
, aImageSize
);
2263 DBG_ERROR("IconView: Viewmode not set");
2268 Rectangle
SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry
* pEntry
,
2269 const Point
* pEntryPos
, BOOL bEdit
, const String
* pStr
)
2273 aEntryText
= pView
->GetEntryText( pEntry
, bEdit
);
2277 const Rectangle
aMaxTextRect( CalcMaxTextRect( pEntry
) );
2278 Rectangle
aBound( GetEntryBoundRect( pEntry
) );
2280 aBound
.SetPos( *pEntryPos
);
2282 Rectangle
aTextRect( aMaxTextRect
);
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
) )
2295 aPos
.Y() += aImageSize
.Height();
2296 aPos
.Y() += VER_DIST_BMP_STRING
;
2297 // beim Editieren etwas mehr Platz
2301 long nMinWidth
= (( (aImageSize
.Width()*10) / 100 ) * 2 ) +
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;
2319 aPos
.X() += aImageSize
.Width();
2320 aPos
.X() += HOR_DIST_BMP_STRING
;
2321 aPos
.Y() += (nBoundHeight
- aTextSize
.Height()) / 2;
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;
2334 switch( nWinBits
& (VIEWMODE_MASK
) )
2337 nWidth
= Max( nStringWidth
, aImageSize
.Width() );
2342 nWidth
= aImageSize
.Width();
2343 nWidth
+= HOR_DIST_BMP_STRING
;
2344 nWidth
+= nStringWidth
;
2350 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry
* pEntry
) const
2352 long nStringHeight
= GetItemSize( pEntry
, IcnViewFieldTypeText
).Height();
2355 switch( nWinBits
& (VIEWMODE_MASK
) )
2358 nHeight
= aImageSize
.Height();
2359 nHeight
+= VER_DIST_BMP_STRING
;
2360 nHeight
+= nStringHeight
;
2365 nHeight
= Max( aImageSize
.Height(), nStringHeight
);
2368 if( nHeight
> nMaxBoundHeight
)
2370 ((SvxIconChoiceCtrl_Impl
*)this)->nMaxBoundHeight
= nHeight
;
2371 ((SvxIconChoiceCtrl_Impl
*)this)->aHorSBar
.SetLineSize( GetScrollBarLineSize() );
2372 ((SvxIconChoiceCtrl_Impl
*)this)->aVerSBar
.SetLineSize( GetScrollBarLineSize() );
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();
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
);
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
;
2413 bBoundRectsDirty
= FALSE
;
2417 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2419 nMaxBoundHeight
= 0;
2420 pZOrderList
->Clear();
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();
2437 FindBoundingRect( pEntry
);
2438 pZOrderList
->Insert( pEntry
, LIST_APPEND
);
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();
2455 FindBoundingRect( pEntry
);
2456 pZOrderList
->Insert( pEntry
, LIST_APPEND
);
2457 pEntry
= pEntry
->pflink
;
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
);
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
;
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
);
2508 ShowCursor( FALSE
);
2509 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
2513 pOldCursor
->ClearFlags( ICNVIEW_FLAG_FOCUSED
);
2514 if( eSelectionMode
== SINGLE_SELECTION
&& bSyncSingleSelection
)
2515 SelectEntry( pOldCursor
, FALSE
, TRUE
); // alten Cursor deselektieren
2520 pCursor
->SetFlags( ICNVIEW_FLAG_FOCUSED
);
2521 if( eSelectionMode
== SINGLE_SELECTION
&& bSyncSingleSelection
)
2522 SelectEntry( pCursor
, TRUE
, TRUE
);
2523 if( !bShowFocusAsync
)
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() )
2543 Rectangle
aRect ( CalcFocusRect( pCursor
) );
2544 /*pView->*/ShowFocus( aRect
);
2548 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2556 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
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
)
2570 if( pRefEntry
!= pDDRefEntry
)
2575 BOOL bSelected
= pRefEntry
->IsSelected();
2576 pRefEntry
->ClearFlags( ICNVIEW_FLAG_SELECTED
);
2581 // nicht bei jedem Move ein Device anlegen, da dies besonders
2582 // auf Remote-Clients zu langsam ist
2588 pDDDev
= new VirtualDevice( *pView
);
2589 pDDDev
->SetFont( pView
->GetFont() );
2596 const Rectangle
& rRect
= GetEntryBoundRect( pRefEntry
);
2597 pDDDev
->SetOutputSizePixel( rRect
.GetSize() );
2599 Point
aPos( rPosPix
);
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
);
2614 pRefEntry
->SetFlags( ICNVIEW_FLAG_SELECTED
);
2617 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry
* pRefEntry
, const Point
& rPosPix
)
2619 /* In Notfaellen folgenden flackernden Code aktivieren:
2622 ShowDDIcon( pRefEntry, rPosPix );
2627 ShowDDIcon( pRefEntry
, rPosPix
);
2631 if( pRefEntry
!= pDDRefEntry
)
2634 ShowDDIcon( pRefEntry
, rPosPix
);
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
) )
2651 ShowDDIcon( pRefEntry
, rPosPix
);
2655 // Ueberlappung des neuen und alten D&D-Pointers!
2657 Rectangle
aFullRect( aPrevEntryRect
.Union( aCurEntryRect
) );
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(
2676 pDDDev
->GetOutputSizePixel(),
2678 pDDDev
->GetOutputSizePixel(),
2682 VirtualDevice
* pTemp
= pDDDev
;
2683 pDDDev
= pDDTempDev
;
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
;
2700 pDDDev
->GetOutputSizePixel(),
2702 pDDDev
->GetOutputSizePixel(),
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
))
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;
2732 nScrollFlags
|= AUTOSCROLL_HORZ
;
2734 nScrollFlags
|= AUTOSCROLL_VERT
;
2737 pView
->StartAutoScroll( nScrollFlags
);
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 )
2757 nScrollDY
= pData
->GetNotchDelta() * (long)nScrollLines
;
2758 nScrollDY
*= GetScrollBarLineSize();
2764 case COMMAND_AUTOSCROLL
:
2766 const CommandScrollData
* pData
= rCmd
.GetAutoScrollData();
2769 nScrollDX
= pData
->GetDeltaX() * GetScrollBarLineSize();
2770 nScrollDY
= pData
->GetDeltaY() * GetScrollBarLineSize();
2776 if( nScrollDX
|| nScrollDY
)
2778 aVisRect
.Top() -= nScrollDY
;
2779 aVisRect
.Bottom() -= nScrollDY
;
2780 aVisRect
.Left() -= nScrollDX
;
2781 aVisRect
.Right() -= nScrollDX
;
2782 MakeVisible( aVisRect
);
2789 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent
& rCEvt
)
2792 if( (rCEvt
.GetCommand() == COMMAND_WHEEL
) ||
2793 (rCEvt
.GetCommand() == COMMAND_STARTAUTOSCROLL
) ||
2794 (rCEvt
.GetCommand() == COMMAND_AUTOSCROLL
) )
2797 if( HandleScrollCommand( rCEvt
) )
2800 ScrollBar
* pHor
= aHorSBar
.IsVisible() ? &aHorSBar
: 0;
2801 ScrollBar
* pVer
= aVerSBar
.IsVisible() ? &aVerSBar
: 0;
2802 if( pView
->HandleScrollCommand( rCEvt
, pHor
, pVer
) )
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 )
2826 if( 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
2842 Rectangle
aOutputArea( GetOutputRect() );
2843 if( aOutputArea
.IsInside( aVirtRect
) )
2844 return; // ist schon sichtbar
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();
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();
2876 aOutputArea
.SetPos( aOrigin
);
2877 if( GetUpdateMode() )
2881 ShowCursor( FALSE
);
2884 // Origin fuer SV invertieren (damit wir in
2885 // Dokumentkoordinaten scrollen/painten koennen)
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
);
2905 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
2907 if( aHorSBar
.IsVisible() || aVerSBar
.IsVisible() )
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() )
2923 // pruefen, ob ScrollBars noch benoetigt werden
2925 if( bScrollable
&& GetUpdateMode() )
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
)
2937 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::FindNewCursor()
2939 SvxIconChoiceCtrlEntry
* pNewCursor
;
2942 pNewCursor
= pImpCursor
->GoLeftRight( pCursor
, FALSE
);
2945 pNewCursor
= pImpCursor
->GoLeftRight( pCursor
, TRUE
);
2948 pNewCursor
= pImpCursor
->GoUpDown( pCursor
, FALSE
);
2950 pNewCursor
= pImpCursor
->GoUpDown( pCursor
, TRUE
);
2955 pNewCursor
= (SvxIconChoiceCtrlEntry
*)aEntries
.First();
2956 DBG_ASSERT(!pNewCursor
|| (pCursor
&&pCursor
!=pNewCursor
),"FindNewCursor failed");
2960 ULONG
SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2962 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && pCurHighlightFrame
)
2964 return nSelectionCount
;
2967 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry
* pEntry
)
2970 if( pEntry
->IsSelected() )
2974 SelectEntry( pEntry
, bSel
, TRUE
, TRUE
);
2977 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry
* pThisEntryNot
,
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
);
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();
3009 aMinSize
.Width() += HOR_DIST_BMP_STRING
;
3010 aMinSize
.Width() += aTextSize
.Width();
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 );
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
;
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
;
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();
3077 aBoundRect
.Top() += nHeight
;
3078 aBoundRect
.Bottom() -= nHeight
;
3083 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
3086 nDY
-= aImageSize
.Height();
3087 nDY
-= VER_DIST_BMP_STRING
;
3088 nDY
-= 2*TBOFFS_BOUND
;
3093 nDX
-= 2*LROFFS_BOUND
;
3098 String
aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
3099 long nHeight
= pView
->GetTextHeight();
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
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
;
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()++;
3162 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
3163 static Rectangle
GetHotSpot( const Rectangle
& rRect
)
3165 Rectangle
aResult( rRect
);
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
;
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() )
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();
3199 const ULONG nCount
= pZOrderList
->Count();
3201 Rectangle
aRect( rRect
);
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();
3223 bOverlaps
= IsOver( pOtherRects
, aBoundRect
);
3226 BOOL bOver
= aRect
.IsOver( aBoundRect
);
3228 if( bOver
&& !bOverlaps
)
3230 // Ist im neuen Selektionsrechteck und in keinem alten
3233 SelectEntry( pEntry
, TRUE
, TRUE
, TRUE
);
3237 // ist ausserhalb des Selektionsrechtecks
3238 // => Selektion entfernen
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.
3260 SelectEntry( pEntry
, FALSE
, TRUE
, TRUE
);
3264 // Eintrag eines alten Rects selektieren
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
;
3280 if( bResetClipRegion
)
3281 pView
->SetClipRegion();
3284 void SvxIconChoiceCtrl_Impl::SelectRange(
3285 SvxIconChoiceCtrlEntry
* pStart
,
3286 SvxIconChoiceCtrlEntry
* pEnd
,
3289 ULONG nFront
= GetEntryListPos( pStart
);
3290 ULONG nBack
= GetEntryListPos( pEnd
);
3291 ULONG nFirst
= std::min( nFront
, nBack
);
3292 ULONG nLast
= std::max( nFront
, nBack
);
3294 SvxIconChoiceCtrlEntry
* pEntry
;
3298 // deselect everything before the first entry if not in
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
);
3318 // deselect everything behind the last entry if not in
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
))
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
);
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
);
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
)
3384 nPixelToScrollX
= -DD_SCROLL_PIXEL
;
3386 nPixelToScrollX
= rPosPixel
.X()- nBorderWidth
;
3388 else if ( rPosPixel
.X() > aWndSize
.Width() - nBorderWidth
)
3391 nPixelToScrollX
= DD_SCROLL_PIXEL
;
3393 nPixelToScrollX
= rPosPixel
.X() - (aWndSize
.Width() - nBorderWidth
);
3395 if ( rPosPixel
.Y() < nBorderWidth
)
3398 nPixelToScrollY
= -DD_SCROLL_PIXEL
;
3400 nPixelToScrollY
= rPosPixel
.Y() - nBorderWidth
;
3402 else if ( rPosPixel
.Y() > aWndSize
.Height() - nBorderWidth
)
3405 nPixelToScrollY
= DD_SCROLL_PIXEL
;
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() );
3421 IMPL_LINK(SvxIconChoiceCtrl_Impl
, VisRectChangedHdl
, void*, EMPTYARG
)
3423 aVisRectChangedTimer
.Stop();
3424 pView
->VisibleRectChanged();
3428 IMPL_LINK(SvxIconChoiceCtrl_Impl
, DocRectChangedHdl
, void*, EMPTYARG
)
3430 aDocRectChangedTimer
.Stop();
3431 pView
->DocumentRectChanged();
3435 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent
& rCEvt
)
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
) )
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
);
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
)
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
);
3482 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
3483 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr
& rRow
, SvxIconChoiceCtrlEntry
* pStart
)
3495 for( USHORT nCur
= 0; nCur
< rRow
.Count(); nCur
++ )
3497 SvxIconChoiceCtrlEntry
* pCur
= (SvxIconChoiceCtrlEntry
*)rRow
[ nCur
];
3498 if( !bGo
&& pCur
== pStart
)
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
;
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
;
3546 aPos
.X() += (nGridDX
- rBoundRect
.GetSize().Width() ) / 2;
3548 aPos
.X() += LROFFS_WINBORDER
;
3549 aPos
.Y() += TBOFFS_WINBORDER
;
3554 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode
, SvxIconChoiceCtrlEntry
* pEntry
)
3558 if( eTextMode
!= eMode
)
3560 if( eTextMode
== IcnShowTextDontKnow
)
3561 eTextMode
= IcnShowTextShort
;
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
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
)
3594 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry
* pEntry
)
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() );
3617 USHORT nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
3619 aPenColor
.SetColor ( COL_BLACK
);
3621 aPenColor
.SetColor( COL_WHITE
);
3624 aFocus
.aPenColor
= aPenColor
;
3625 aFocus
.aRect
= rRect
;
3628 void SvxIconChoiceCtrl_Impl::HideFocus ()
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
) )
3669 ////////////////////////////////////////////////////////////////////////////////////////////////
3671 IMPL_LINK(SvxIconChoiceCtrl_Impl
, UserEventHdl
, void*, nId
)
3673 if( nId
== EVENTID_ADJUST_SCROLLBARS
)
3675 nUserEventAdjustScrBars
= 0;
3678 else if( nId
== EVENTID_SHOW_CURSOR
)
3680 nUserEventShowCursor
= 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
);
3706 pView
->Invalidate( pEntry
->aRect
);
3707 if( pEntry
== pCursor
)
3711 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry
* pEntry
)
3713 DBG_ASSERT(pEntry
,"EditEntry: Entry not set");
3717 StopEntryEditing( TRUE
);
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
);
3729 pEdit
= new IcnViewEdit_Impl(
3734 LINK( this, SvxIconChoiceCtrl_Impl
, TextEditEndedHdl
) );
3737 IMPL_LINK( SvxIconChoiceCtrl_Impl
, TextEditEndedHdl
, IcnViewEdit_Impl
*, EMPTYARG
)
3739 DBG_ASSERT(pEdit
,"TextEditEnded: pEdit not set");
3742 pCurEditedEntry
= 0;
3745 DBG_ASSERT(pCurEditedEntry
,"TextEditEnded: pCurEditedEntry not set");
3747 if( !pCurEditedEntry
)
3750 if( pEdit
->IsGrabFocus() )
3756 if ( !pEdit
->EditingCanceled() )
3757 aText
= pEdit
->GetText();
3759 aText
= pEdit
->GetSavedValue();
3761 if( pView
->EditedEntry( pCurEditedEntry
, aText
, pEdit
->EditingCanceled() ) )
3762 InvalidateEntry( pCurEditedEntry
);
3763 if( !GetSelectionCount() )
3764 SelectEntry( pCurEditedEntry
, TRUE
);
3767 if( pEdit
->IsGrabFocus() )
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;
3775 void SvxIconChoiceCtrl_Impl::StopEntryEditing( BOOL bCancel
)
3778 pEdit
->StopEditing( bCancel
);
3781 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry
* pEntry
, BOOL bLock
)
3784 pEntry
->SetFlags( ICNVIEW_FLAG_POS_LOCKED
);
3786 pEntry
->ClearFlags( ICNVIEW_FLAG_POS_LOCKED
);
3789 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( ULONG
& rPos
) const
3791 if( !GetSelectionCount() )
3794 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && (eSelectionMode
== NO_SELECTION
) )
3796 rPos
= pView
->GetEntryListPos( pCurHighlightFrame
);
3797 return pCurHighlightFrame
;
3800 ULONG nCount
= aEntries
.Count();
3803 for( ULONG nCur
= 0; nCur
< nCount
; nCur
++ )
3805 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( nCur
);
3806 if( pEntry
->IsSelected() )
3815 SvxIconChoiceCtrlEntry
* pEntry
= pHead
;
3818 if( pEntry
->IsSelected() )
3820 rPos
= GetEntryListPos( pEntry
);
3823 pEntry
= pEntry
->pflink
;
3824 if( nCount
&& pEntry
== pHead
)
3826 DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
3834 // kein Round Robin!
3835 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( ULONG
& rStartPos
) const
3837 ULONG nCount
= aEntries
.Count();
3838 if( rStartPos
> nCount
|| !GetSelectionCount() )
3842 for( ULONG nCur
= rStartPos
+1; nCur
< nCount
; nCur
++ )
3844 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( nCur
);
3845 if( pEntry
->IsSelected() )
3854 SvxIconChoiceCtrlEntry
* pEntry
= (SvxIconChoiceCtrlEntry
*)aEntries
.GetObject( rStartPos
);
3855 pEntry
= pEntry
->pflink
;
3856 while( pEntry
!= pHead
)
3858 if( pEntry
->IsSelected() )
3860 rStartPos
= GetEntryListPos( pEntry
);
3863 pEntry
= pEntry
->pflink
;
3867 rStartPos
= 0xffffffff;
3871 void SvxIconChoiceCtrl_Impl::SelectAll( BOOL bSelect
, BOOL bPaint
)
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
);
3885 void SvxIconChoiceCtrl_Impl::SaveSelection( List
** ppList
)
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
),
3903 bAlreadyInCallback( 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
);
3915 SetControlBackground( aFont
.GetFillColor() );
3916 SetControlForeground( aFont
.GetColor() );
3917 SetPosPixel( rPos
);
3918 SetSizePixel( CalcAdjustedSize(rSize
) );
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 );
3933 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3935 if( !bAlreadyInCallback
)
3937 GetpApp()->RemoveAccel( &aAccReturn
);
3938 GetpApp()->RemoveAccel( &aAccEscape
);
3942 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3945 if ( !bAlreadyInCallback
)
3947 bAlreadyInCallback
= TRUE
;
3948 GetpApp()->RemoveAccel( &aAccReturn
);
3949 GetpApp()->RemoveAccel( &aAccEscape
);
3951 aCallBackHdl
.Call( this );
3955 IMPL_LINK( IcnViewEdit_Impl
, Timeout_Impl
, Timer
*, EMPTYARG
)
3957 CallCallBackHdl_Impl();
3961 IMPL_LINK( IcnViewEdit_Impl
, ReturnHdl_Impl
, Accelerator
*, EMPTYARG
)
3965 CallCallBackHdl_Impl();
3969 IMPL_LINK( IcnViewEdit_Impl
, EscapeHdl_Impl
, Accelerator
*, EMPTYARG
)
3973 CallCallBackHdl_Impl();
3977 void IcnViewEdit_Impl::KeyInput( const KeyEvent
& rKEvt
)
3979 KeyCode aCode
= rKEvt
.GetKeyCode();
3980 USHORT nCode
= aCode
.GetCode();
3987 CallCallBackHdl_Impl();
3993 CallCallBackHdl_Impl();
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())))
4009 aTimer
.SetTimeout(10);
4010 aTimer
.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl
,Timeout_Impl
));
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
)
4038 aEntries
.List::Remove( nCurPos
);
4039 aEntries
.List::Insert( (void*)pListEntry
, nNewPos
);
4040 // Eintragspositionen anpassen
4042 if( nNewPos
< nCurPos
)
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
;
4108 aHorSBar
.SetSizePixel( aSize
);
4110 nVerSBarWidth
= nScrBarSize
;
4111 aSize
= aVerSBar
.GetSizePixel();
4112 aSize
.Width() = nScrBarSize
;
4114 aVerSBar
.SetSizePixel( aSize
);
4116 Size
aOSize( pView
->Control::GetOutputSizePixel() );
4117 PositionScrollBars( aOSize
.Width(), aOSize
.Height() );
4122 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl
* pOwner
, USHORT _nInitSize
, USHORT _nReSize
) :
4123 List( _nInitSize
, _nReSize
),
4129 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl
* pOwner
, USHORT _nBlockSize
, USHORT _nInitSize
, USHORT _nReSize
) :
4130 List( _nBlockSize
, _nInitSize
, _nReSize
),
4136 EntryList_Impl::~EntryList_Impl()
4141 void EntryList_Impl::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
);
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
;
4178 DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
4186 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode
)
4190 if( eMode
== ePositionMode
)
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.
4203 if( aEntries
.Count() )
4204 aAutoArrangeTimer
.Start();
4208 // verschobene Eintraege 'hart' auf ihre Position setzen
4210 SvxIconChoiceCtrlEntry
* pEntry
= pHead
;
4213 SvxIconChoiceCtrlEntry
* pPred
;
4214 if( GetEntryPredecessor( pEntry
, &pPred
))
4215 SetEntryFlags( pEntry
, ICNVIEW_FLAG_POS_MOVED
);
4216 pEntry
= pEntry
->pflink
;
4219 ClearPredecessors();
4225 if( ePositionMode
== IcnViewPositionModeAutoArrange
)
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() )
4261 if( pEntry
== pPredecessor
)
4264 ULONG nPos1
= GetEntryListPos( pEntry
);
4269 ULONG nPos2
= GetEntryListPos( pPredecessor
);
4270 if( nPos1
== (nPos2
+ 1) )
4271 return; // ist schon Vorgaenger
4280 if( !pPredecessor
&& pHead
== pEntry
)
4281 return; // ist schon der Erste
4283 BOOL bSetHead
= FALSE
;
4287 pPredecessor
= pHead
->pblink
;
4289 if( pEntry
== pHead
)
4291 pHead
= pHead
->pflink
;
4294 if( pEntry
!= pPredecessor
)
4297 pEntry
->SetBacklink( pPredecessor
);
4301 pEntry
->SetFlags( ICNVIEW_FLAG_PRED_SET
);
4302 aAutoArrangeTimer
.Start();
4305 BOOL
SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
4306 SvxIconChoiceCtrlEntry
** ppPredecessor
)
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
)
4321 *ppPredecessor
= pEntry
->pblink
;
4322 if( !(pEntry
->nFlags
& ICNVIEW_FLAG_PRED_SET
) &&
4323 (GetEntryListPos( *ppPredecessor
) + 1) == GetEntryListPos( pEntry
))
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
)
4338 if( nGrid
>= nCount
)
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
;
4351 ULONG
SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point
& rPos
) const
4354 aPos
.X() -= LROFFS_WINBORDER
;
4355 aPos
.Y() -= TBOFFS_WINBORDER
;
4356 USHORT nMaxCol
= (USHORT
)(aVirtOutputSize
.Width() / nGridDX
);
4359 USHORT nGridX
= (USHORT
)(aPos
.X() / nGridDX
);
4360 if( 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
)
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
) )
4389 Point
aPos( pView
->ScreenToOutputPixel(rHEvt
.GetMousePosPixel() ) );
4390 aPos
-= pView
->GetMapMode().GetOrigin();
4391 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aPos
, TRUE
);
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() )
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
4416 aOptTextRect
.SetPos( aPt
);
4418 if ( sQuickHelpText
.Len() > 0 )
4419 sHelpText
= sQuickHelpText
;
4421 sHelpText
= aEntryText
;
4422 Help::ShowQuickHelp( (Window
*)pView
, aOptTextRect
, sHelpText
, QUICKHELP_LEFT
| QUICKHELP_VCENTER
);
4428 void SvxIconChoiceCtrl_Impl::ClearColumnList()
4433 const USHORT nCount
= pColumns
->Count();
4434 for( USHORT nCur
= 0; nCur
< nCount
; nCur
++ )
4436 SvxIconChoiceCtrlColumnInfo
* pInfo
= (SvxIconChoiceCtrlColumnInfo
*)
4437 pColumns
->GetObject( nCur
);
4443 void SvxIconChoiceCtrl_Impl::SetColumn( USHORT nIndex
, const SvxIconChoiceCtrlColumnInfo
& rInfo
)
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
);
4454 pInfo
= new SvxIconChoiceCtrlColumnInfo( rInfo
);
4455 pColumns
->Insert( (void*)pInfo
, nIndex
);
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() )
4477 return (const SvxIconChoiceCtrlColumnInfo
*)pColumns
->GetObject( nIndex
);
4480 const SvxIconChoiceCtrlColumnInfo
* SvxIconChoiceCtrl_Impl::GetItemColumn( USHORT nSubItem
,
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
)
4493 rLeft
+= pCol
->GetWidth();
4498 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
4499 OutputDevice
* pOut
, const Rectangle
& rBmpRect
, BOOL bHide
)
4501 Rectangle
aBmpRect( rBmpRect
);
4503 if( aImageSize
.Width() < 32 )
4505 aBmpRect
.Right() += nBorder
;
4506 aBmpRect
.Left() -= nBorder
;
4507 aBmpRect
.Bottom() += nBorder
;
4508 aBmpRect
.Top() -= nBorder
;
4511 pView
->Invalidate( aBmpRect
);
4514 DecorationView
aDecoView( pOut
);
4516 if ( bHighlightFramePressed
)
4517 nDecoFlags
= FRAME_HIGHLIGHT_TESTBACKGROUND
| FRAME_HIGHLIGHT_IN
;
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
)
4530 if( !bKeepHighlightFlags
)
4531 bHighlightFramePressed
= FALSE
;
4533 HideEntryHighlightFrame();
4534 pCurHighlightFrame
= pEntry
;
4537 Rectangle
aBmpRect( CalcFocusRect(pEntry
) );
4538 DrawHighlightFrame( pView
, aBmpRect
, FALSE
);
4542 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
4544 if( !pCurHighlightFrame
)
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
) )
4571 aCallSelectHdlTimer
.Start();
4574 IMPL_LINK( SvxIconChoiceCtrl_Impl
, CallSelectHdlHdl
, void*, EMPTYARG
)
4582 Point
SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
4585 if( !GetSelectionCount() )
4588 SvxIconChoiceCtrlEntry
* pEntry
= GetCurEntry();
4589 if( !pEntry
|| !pEntry
->IsSelected() )
4592 pEntry
= GetFirstSelectedEntry( nNext
);
4596 Rectangle
aRect( ((SvxIconChoiceCtrl_Impl
*)this)->CalcBmpRect( pEntry
) );
4597 aResult
= aRect
.Center();
4598 aResult
= pView
->GetPixelPos( 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 )
4637 if( aSize
.Height() < 0 )
4640 return IcnGridMap_Impl::GetGridCount( aSize
, (USHORT
)nGridDX
, (USHORT
)nGridDY
);
4643 BOOL
SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent
& rKEvt
)
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
;
4668 pCurHighlightFrame
= NULL
;
4677 // -----------------------------------------------------------------------
4679 void SvxIconChoiceCtrl_Impl::CallEventListeners( ULONG nEvent
, void* pData
)
4681 pView
->CallImplEventListeners( nEvent
, pData
);