1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <tools/debug.hxx>
23 #include <vcl/wall.hxx>
24 #include <vcl/help.hxx>
25 #include <vcl/decoview.hxx>
26 #include <vcl/svapp.hxx>
27 #include <tools/poly.hxx>
28 #include <vcl/lineinfo.hxx>
29 #include <vcl/i18nhelp.hxx>
30 #include <vcl/mnemonic.hxx>
31 #include <vcl/controllayout.hxx>
33 #include <svtools/ivctrl.hxx>
34 #include "imivctl.hxx"
35 #include <svtools/svmedit.hxx>
40 #define IMPICNVIEW_ACC_RETURN 1
41 #define IMPICNVIEW_ACC_ESCAPE 2
43 #define DRAWTEXT_FLAGS_ICON \
44 ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
45 TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
47 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
49 #define EVENTID_SHOW_CURSOR ((void*)1)
50 #define EVENTID_ADJUST_SCROLLBARS ((void*)2)
52 struct SvxIconChoiceCtrlEntry_Impl
54 SvxIconChoiceCtrlEntry
* _pEntry
;
56 SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry
* pEntry
, const Rectangle
& rBoundRect
)
57 : _pEntry( pEntry
), _aPos( rBoundRect
.TopLeft()) {}
60 static sal_Bool bEndScrollInvalidate
= sal_True
;
62 class IcnViewEdit_Impl
: public MultiLineEdit
65 Accelerator aAccReturn
;
66 Accelerator aAccEscape
;
69 sal_Bool bAlreadyInCallback
;
72 void CallCallBackHdl_Impl();
73 DECL_LINK(Timeout_Impl
, void *);
74 DECL_LINK( ReturnHdl_Impl
, Accelerator
* );
75 DECL_LINK( EscapeHdl_Impl
, Accelerator
* );
80 SvtIconChoiceCtrl
* pParent
,
83 const XubString
& rData
,
84 const Link
& rNotifyEditEnd
);
87 virtual void KeyInput( const KeyEvent
& rKEvt
);
88 virtual long PreNotify( NotifyEvent
& rNEvt
);
89 sal_Bool
EditingCanceled() const { return bCanceled
; }
90 void StopEditing( sal_Bool bCancel
= sal_False
);
91 sal_Bool
IsGrabFocus() const { return bGrabFocus
; }
94 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
95 SvtIconChoiceCtrl
* pCurView
,
99 aVerSBar( pCurView
, WB_DRAG
| WB_VSCROLL
),
100 aHorSBar( pCurView
, WB_DRAG
| WB_HSCROLL
),
101 aScrBarBox( pCurView
),
102 aImageSize( 32, 32 ),
105 bChooseWithCursor
=sal_False
;
108 pCurHighlightFrame
= 0;
115 bUpdateMode
= sal_True
;
116 bEntryEditingEnabled
= sal_False
;
117 bHighlightFramePressed
= sal_False
;
118 eSelectionMode
= MULTIPLE_SELECTION
;
120 pZOrderList
= new SvxIconChoiceCtrlEntryList_impl();
121 ePositionMode
= IcnViewPositionModeFree
;
122 SetStyle( nWinStyle
);
124 nUserEventAdjustScrBars
= 0;
125 nUserEventShowCursor
= 0;
126 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
127 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
132 eTextMode
= IcnShowTextShort
;
133 pImpCursor
= new IcnCursor_Impl( this );
134 pGridMap
= new IcnGridMap_Impl( this );
136 aVerSBar
.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
) );
137 aHorSBar
.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
) );
138 Link
aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, EndScrollHdl
) );
139 aVerSBar
.SetEndScrollHdl( aEndScrollHdl
);
140 aHorSBar
.SetEndScrollHdl( aEndScrollHdl
);
142 nHorSBarHeight
= aHorSBar
.GetSizePixel().Height();
143 nVerSBarWidth
= aVerSBar
.GetSizePixel().Width();
145 aEditTimer
.SetTimeout( 800 );
146 aEditTimer
.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl
,EditTimeoutHdl
));
147 aAutoArrangeTimer
.SetTimeout( 100 );
148 aAutoArrangeTimer
.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl
,AutoArrangeHdl
));
149 aCallSelectHdlTimer
.SetTimeout( 500 );
150 aCallSelectHdlTimer
.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl
,CallSelectHdlHdl
));
152 aDocRectChangedTimer
.SetTimeout( 50 );
153 aDocRectChangedTimer
.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl
,DocRectChangedHdl
));
154 aVisRectChangedTimer
.SetTimeout( 50 );
155 aVisRectChangedTimer
.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl
,VisRectChangedHdl
));
159 SetGrid( Size(100, 70) );
162 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
175 delete pEntryPaintDev
;
176 ClearSelectedRectList();
180 void SvxIconChoiceCtrl_Impl::Clear( sal_Bool bInCtor
)
182 StopEntryEditing( sal_True
);
184 pCurHighlightFrame
= 0;
187 ShowCursor( sal_False
);
188 bBoundRectsDirty
= sal_False
;
191 nFlags
&= ~(F_PAINTED
| F_MOVED_ENTRIES
);
197 aVirtOutputSize
.Width() = 0;
198 aVirtOutputSize
.Height() = 0;
199 Size
aSize( pView
->GetOutputSizePixel() );
200 nMaxVirtWidth
= aSize
.Width() - nVerSBarWidth
;
201 if( nMaxVirtWidth
<= 0 )
202 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
203 nMaxVirtHeight
= aSize
.Height() - nHorSBarHeight
;
204 if( nMaxVirtHeight
<= 0 )
205 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
206 pZOrderList
->clear();
207 SetOrigin( Point() );
209 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
212 size_t nCount
= aEntries
.size();
213 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
215 SvxIconChoiceCtrlEntry
* pCur
= aEntries
[ nCur
];
223 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle
)
225 nWinBits
= nWinStyle
;
226 nCurTextDrawFlags
= DRAWTEXT_FLAGS_ICON
;
227 if( nWinBits
& (WB_SMALLICON
| WB_DETAILS
) )
228 nCurTextDrawFlags
= DRAWTEXT_FLAGS_SMALLICON
;
229 if( nWinBits
& WB_NOSELECTION
)
230 eSelectionMode
= NO_SELECTION
;
231 if( !(nWinStyle
& (WB_ALIGN_TOP
| WB_ALIGN_LEFT
)))
232 nWinBits
|= WB_ALIGN_LEFT
;
233 if( (nWinStyle
& WB_DETAILS
))
236 SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft
));
240 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
, ScrollBar
*, pScrollBar
)
242 StopEntryEditing( sal_True
);
243 // arrow up: delta=-1; arrow down: delta=+1
244 Scroll( 0, pScrollBar
->GetDelta(), sal_True
);
245 bEndScrollInvalidate
= sal_True
;
249 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
, ScrollBar
*, pScrollBar
)
251 StopEntryEditing( sal_True
);
252 // arrow left: delta=-1; arrow right: delta=+1
253 Scroll( pScrollBar
->GetDelta(), 0, sal_True
);
254 bEndScrollInvalidate
= sal_True
;
258 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, EndScrollHdl
)
260 if( pView
->HasBackground() && !pView
->GetBackground().IsScrollable() &&
261 bEndScrollInvalidate
)
263 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
268 void SvxIconChoiceCtrl_Impl::FontModified()
274 DELETEZ(pEntryPaintDev
);
275 SetDefaultTextSize();
276 ShowCursor( sal_False
);
277 ShowCursor( sal_True
);
280 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry
* pEntry
, size_t nPos
,
284 aEntries
.insert( nPos
, pEntry
);
285 if( (nFlags
& F_ENTRYLISTPOS_VALID
) && nPos
>= aEntries
.size() - 1 )
286 pEntry
->nPos
= aEntries
.size() - 1;
288 nFlags
&= ~F_ENTRYLISTPOS_VALID
;
290 pZOrderList
->push_back( pEntry
);
294 Size
aSize( CalcBoundingSize( pEntry
) );
295 SetBoundingRect_Impl( pEntry
, *pPos
, aSize
);
296 SetEntryPos( pEntry
, *pPos
, sal_False
, sal_True
, sal_True
/*keep grid map*/ );
297 pEntry
->nFlags
|= ICNVIEW_FLAG_POS_MOVED
;
298 SetEntriesMoved( sal_True
);
302 // If the UpdateMode is sal_True, don't set all bounding rectangles to
303 // 'to be checked', but only the bounding rectangle of the new entry.
304 // Thus, don't call InvalidateBoundingRect!
305 pEntry
->aRect
.Right() = LONG_MAX
;
308 FindBoundingRect( pEntry
);
309 Rectangle
aOutputArea( GetOutputRect() );
310 pGridMap
->OccupyGrids( pEntry
);
311 if( !aOutputArea
.IsOver( pEntry
->aRect
) )
312 return; // is invisible
313 pView
->Invalidate( pEntry
->aRect
);
316 InvalidateBoundingRect( pEntry
->aRect
);
320 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator
* _pGenerator
)
322 ::std::auto_ptr
< MnemonicGenerator
> pAutoDeleteOwnGenerator
;
325 _pGenerator
= new MnemonicGenerator
;
326 pAutoDeleteOwnGenerator
.reset( _pGenerator
);
329 sal_uLong nEntryCount
= GetEntryCount();
332 // insert texts in generator
333 for( i
= 0; i
< nEntryCount
; ++i
)
335 DBG_ASSERT( GetEntry( i
), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
337 _pGenerator
->RegisterMnemonic( GetEntry( i
)->GetText() );
340 // exchange texts with generated mnemonics
341 for( i
= 0; i
< nEntryCount
; ++i
)
343 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( i
);
344 String aTxt
= pEntry
->GetText();
346 if( _pGenerator
->CreateMnemonic( aTxt
) )
347 pEntry
->SetText( aTxt
);
351 Rectangle
SvxIconChoiceCtrl_Impl::GetOutputRect() const
353 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
355 return Rectangle( aOrigin
, aOutputSize
);
358 void SvxIconChoiceCtrl_Impl::SetListPositions()
360 if( nFlags
& F_ENTRYLISTPOS_VALID
)
363 size_t nCount
= aEntries
.size();
364 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
366 SvxIconChoiceCtrlEntry
* pEntry
= aEntries
[ nCur
];
369 nFlags
|= F_ENTRYLISTPOS_VALID
;
372 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry
* pEntry
, sal_Bool bSelect
,
373 sal_Bool bCallHdl
, sal_Bool bAdd
, sal_Bool bSyncPaint
)
375 if( eSelectionMode
== NO_SELECTION
)
380 if ( 0 == ( nFlags
& F_CLEARING_SELECTION
) )
382 nFlags
|= F_CLEARING_SELECTION
;
383 DeselectAllBut( pEntry
, sal_True
);
384 nFlags
&= ~F_CLEARING_SELECTION
;
387 if( pEntry
->IsSelected() != bSelect
)
390 sal_uInt16 nEntryFlags
= pEntry
->GetFlags();
393 nEntryFlags
|= ICNVIEW_FLAG_SELECTED
;
394 pEntry
->AssignFlags( nEntryFlags
);
397 CallSelectHandler( pEntry
);
401 nEntryFlags
&= ~( ICNVIEW_FLAG_SELECTED
);
402 pEntry
->AssignFlags( nEntryFlags
);
405 CallSelectHandler( 0 );
407 EntrySelected( pEntry
, bSelect
, bSyncPaint
);
411 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry
* pEntry
, sal_Bool bSelect
,
412 sal_Bool bSyncPaint
)
414 // When using SingleSelection, make sure that the cursor is always placed
415 // over the (only) selected entry. (But only if a cursor exists.)
416 if( bSelect
&& pCursor
&&
417 eSelectionMode
== SINGLE_SELECTION
&&
421 //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
424 // Not when dragging though, else the loop in SelectRect doesn't work
426 if( !(nFlags
& F_SELECTING_RECT
) )
430 if( pEntry
== pCursor
)
431 ShowCursor( sal_False
);
432 if( pView
->IsTracking() && (bSelect
|| !pView
->HasBackground()) ) // always synchronous when tracking
433 PaintEntry( pEntry
);
434 else if( bSyncPaint
) // synchronous & with a virtual OutDev!
435 PaintEntryVirtOutDev( pEntry
);
438 pView
->Invalidate( CalcFocusRect( pEntry
) );
440 if( pEntry
== pCursor
)
441 ShowCursor( sal_True
);
444 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
447 CallEventListeners( VCLEVENT_LISTBOX_SELECT
, pEntry
);
451 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
454 aVirtOutputSize
.Width() = 0;
455 aVirtOutputSize
.Height() = 0;
456 const size_t nCount
= aEntries
.size();
457 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
459 SvxIconChoiceCtrlEntry
* pCur
= aEntries
[ nCur
];
460 pCur
->ClearFlags( ICNVIEW_FLAG_POS_MOVED
);
461 if( pCur
->IsPosLocked() )
463 // adapt (among others) VirtSize
464 if( !IsBoundingRectValid( pCur
->aRect
) )
465 FindBoundingRect( pCur
);
467 AdjustVirtSize( pCur
->aRect
);
470 InvalidateBoundingRect( pCur
->aRect
);
473 if( !(nWinBits
& (WB_NOVSCROLL
| WB_NOHSCROLL
)) )
475 Size
aRealOutputSize( pView
->GetOutputSizePixel() );
476 if( aVirtOutputSize
.Width() < aRealOutputSize
.Width() ||
477 aVirtOutputSize
.Height() < aRealOutputSize
.Height() )
479 sal_uLong nGridCount
= IcnGridMap_Impl::GetGridCount(
480 aRealOutputSize
, (sal_uInt16
)nGridDX
, (sal_uInt16
)nGridDY
);
481 if( nGridCount
< nCount
)
483 if( nWinBits
& WB_ALIGN_TOP
)
484 nMaxVirtWidth
= aRealOutputSize
.Width() - nVerSBarWidth
;
485 else // WB_ALIGN_LEFT
486 nMaxVirtHeight
= aRealOutputSize
.Height() - nHorSBarHeight
;
496 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle
& rRect
)
498 long nHeightOffs
= 0;
501 if( aVirtOutputSize
.Width() < (rRect
.Right()+LROFFS_WINBORDER
) )
502 nWidthOffs
= (rRect
.Right()+LROFFS_WINBORDER
) - aVirtOutputSize
.Width();
504 if( aVirtOutputSize
.Height() < (rRect
.Bottom()+TBOFFS_WINBORDER
) )
505 nHeightOffs
= (rRect
.Bottom()+TBOFFS_WINBORDER
) - aVirtOutputSize
.Height();
507 if( nWidthOffs
|| nHeightOffs
)
510 aVirtOutputSize
.Width() += nWidthOffs
;
511 aRange
.Max() = aVirtOutputSize
.Width();
512 aHorSBar
.SetRange( aRange
);
514 aVirtOutputSize
.Height() += nHeightOffs
;
515 aRange
.Max() = aVirtOutputSize
.Height();
516 aVerSBar
.SetRange( aRange
);
519 pGridMap
->OutputSizeChanged();
525 void SvxIconChoiceCtrl_Impl::InitPredecessors()
527 DBG_ASSERT(!pHead
,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
528 size_t nCount
= aEntries
.size();
531 SvxIconChoiceCtrlEntry
* pPrev
= aEntries
[ 0 ];
532 for( size_t nCur
= 1; nCur
<= nCount
; nCur
++ )
534 pPrev
->ClearFlags( ICNVIEW_FLAG_POS_LOCKED
| ICNVIEW_FLAG_POS_MOVED
|
535 ICNVIEW_FLAG_PRED_SET
);
537 SvxIconChoiceCtrlEntry
* pNext
;
539 pNext
= aEntries
[ 0 ];
541 pNext
= aEntries
[ nCur
];
542 pPrev
->pflink
= pNext
;
543 pNext
->pblink
= pPrev
;
546 pHead
= aEntries
[ 0 ];
550 nFlags
&= ~F_MOVED_ENTRIES
;
553 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
557 size_t nCount
= aEntries
.size();
558 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
560 SvxIconChoiceCtrlEntry
* pCur
= aEntries
[ nCur
];
563 pCur
->ClearFlags( ICNVIEW_FLAG_PRED_SET
);
569 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors
, long nSetMaxVirtWidth
, long nSetMaxVirtHeight
)
571 if ( nSetMaxVirtWidth
!= 0 )
572 nMaxVirtWidth
= nSetMaxVirtWidth
;
574 nMaxVirtWidth
= aOutputSize
.Width();
576 if ( nSetMaxVirtHeight
!= 0 )
577 nMaxVirtHeight
= nSetMaxVirtHeight
;
579 nMaxVirtHeight
= aOutputSize
.Height();
581 ImpArrange( bKeepPredecessors
);
584 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors
)
586 static Point aEmptyPoint
;
588 sal_Bool bOldUpdate
= bUpdateMode
;
589 Rectangle
aCurOutputArea( GetOutputRect() );
590 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
591 bUpdateMode
= sal_False
;
592 aAutoArrangeTimer
.Stop();
593 nFlags
&= ~F_MOVED_ENTRIES
;
594 nFlags
|= F_ARRANGING
;
596 ShowCursor( sal_False
);
598 if( !bKeepPredecessors
)
600 bBoundRectsDirty
= sal_False
;
601 SetOrigin( Point() );
603 RecalcAllBoundingRectsSmart();
604 // TODO: the invalidation in the detail view should be more intelligent
605 //if( !(nWinBits & WB_DETAILS ))
606 pView
->Invalidate( INVALIDATE_NOCHILDREN
);
607 nFlags
&= ~F_ARRANGING
;
608 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
610 MakeVisible( aCurOutputArea
);
611 SetUpdateMode( bOldUpdate
);
613 ShowCursor( sal_True
);
616 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle
& rRect
)
618 bEndScrollInvalidate
= sal_False
;
620 #if defined(OV_DRAWGRID)
621 Color
aOldColor ( pView
->GetLineColor() );
622 Color
aColor( COL_BLACK
);
623 pView
->SetLineColor( aColor
);
624 Point
aOffs( pView
->GetMapMode().GetOrigin());
625 Size
aXSize( pView
->GetOutputSizePixel() );
628 Point
aStart( LROFFS_WINBORDER
, 0 );
629 Point
aEnd( LROFFS_WINBORDER
, aXSize
.Height());
632 pView
->DrawLine( aStart
, aEnd
);
635 Point
aStart( 0, TBOFFS_WINBORDER
);
636 Point
aEnd( aXSize
.Width(), TBOFFS_WINBORDER
);
639 pView
->DrawLine( aStart
, aEnd
);
642 for( long nDX
= nGridDX
; nDX
<= aXSize
.Width(); nDX
+= nGridDX
)
644 Point
aStart( nDX
+LROFFS_WINBORDER
, 0 );
645 Point
aEnd( nDX
+LROFFS_WINBORDER
, aXSize
.Height());
648 pView
->DrawLine( aStart
, aEnd
);
650 for( long nDY
= nGridDY
; nDY
<= aXSize
.Height(); nDY
+= nGridDY
)
652 Point
aStart( 0, nDY
+TBOFFS_WINBORDER
);
653 Point
aEnd( aXSize
.Width(), nDY
+TBOFFS_WINBORDER
);
656 pView
->DrawLine( aStart
, aEnd
);
658 pView
->SetLineColor( aOldColor
);
662 if( !aEntries
.size() )
666 // set cursor to item with focus-flag
667 sal_Bool bfound
= sal_False
;
668 for ( sal_uLong i
= 0; i
< pView
->GetEntryCount() && !bfound
; i
++)
670 SvxIconChoiceCtrlEntry
* pEntry
= pView
->GetEntry ( i
);
671 if( pEntry
->IsFocused() )
679 pCursor
= aEntries
[ 0 ];
682 // Show Focus at Init-Time
683 if ( pView
->HasFocus() )
686 size_t nCount
= pZOrderList
->size();
690 sal_Bool bResetClipRegion
= sal_False
;
691 if( !pView
->IsClipRegion() )
693 Region
const aOutputArea( GetOutputRect() );
694 bResetClipRegion
= sal_True
;
695 pView
->SetClipRegion( aOutputArea
);
698 SvxIconChoiceCtrlEntryList_impl
* pNewZOrderList
= new SvxIconChoiceCtrlEntryList_impl();
699 SvxIconChoiceCtrlEntryList_impl
* pPaintedEntries
= new SvxIconChoiceCtrlEntryList_impl();
704 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nPos
];
705 const Rectangle
& rBoundRect
= GetEntryBoundRect( pEntry
);
706 if( rRect
.IsOver( rBoundRect
) )
708 PaintEntry( pEntry
, rBoundRect
.TopLeft(), pView
, sal_True
);
709 // set entries to Top if they are being repainted
710 pPaintedEntries
->push_back( pEntry
);
713 pNewZOrderList
->push_back( pEntry
);
719 pZOrderList
= pNewZOrderList
;
720 nCount
= pPaintedEntries
->size();
723 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
724 pZOrderList
->push_back( (*pPaintedEntries
)[ nCur
] );
726 delete pPaintedEntries
;
728 if( bResetClipRegion
)
729 pView
->SetClipRegion();
732 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask
)
734 const size_t nCount
= pZOrderList
->size();
738 sal_Bool bResetClipRegion
= sal_False
;
739 Rectangle
aOutRect( GetOutputRect() );
740 if( !pView
->IsClipRegion() )
742 bResetClipRegion
= sal_True
;
743 pView
->SetClipRegion(Region(aOutRect
));
745 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
747 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nCur
];
748 if( pEntry
->GetFlags() & nEntryFlagsMask
)
750 const Rectangle
& rBoundRect
= GetEntryBoundRect( pEntry
);
751 if( aOutRect
.IsOver( rBoundRect
) )
752 PaintEntry( pEntry
, rBoundRect
.TopLeft() );
755 if( bResetClipRegion
)
756 pView
->SetClipRegion();
760 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
762 aScrBarBox
.SetSizePixel( Size(nVerSBarWidth
-1, nHorSBarHeight
-1) );
763 Size
aSize( pView
->GetOutputSizePixel() );
764 aScrBarBox
.SetPosPixel( Point(aSize
.Width()-nVerSBarWidth
+1, aSize
.Height()-nHorSBarHeight
+1));
767 sal_Bool
SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent
& rMEvt
)
769 sal_Bool bHandled
= sal_True
;
770 bHighlightFramePressed
= sal_False
;
772 sal_Bool bGotFocus
= (sal_Bool
)(!pView
->HasFocus() && !(nWinBits
& WB_NOPOINTERFOCUS
));
773 if( !(nWinBits
& WB_NOPOINTERFOCUS
) )
776 Point
aDocPos( rMEvt
.GetPosPixel() );
777 if(aDocPos
.X()>=aOutputSize
.Width() || aDocPos
.Y()>=aOutputSize
.Height())
780 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, sal_True
);
782 MakeEntryVisible( pEntry
, sal_False
);
784 if( rMEvt
.IsShift() && eSelectionMode
!= SINGLE_SELECTION
)
787 SetCursor_Impl( pCursor
, pEntry
, rMEvt
.IsMod1(), rMEvt
.IsShift(), sal_True
);
791 if( pAnchor
&& (rMEvt
.IsShift() || rMEvt
.IsMod1())) // keyboard selection?
793 DBG_ASSERT(eSelectionMode
!= SINGLE_SELECTION
,"Invalid selection mode");
795 nFlags
|= F_ADD_MODE
;
797 if( rMEvt
.IsShift() )
799 Rectangle
aRect( GetEntryBoundRect( pAnchor
));
801 aRect
.Union( GetEntryBoundRect( pEntry
) );
804 Rectangle
aTempRect( aDocPos
, Size(1,1));
805 aRect
.Union( aTempRect
);
807 aCurSelectionRect
= aRect
;
808 SelectRect( aRect
, (nFlags
& F_ADD_MODE
)!=0, &aSelectedRectList
);
810 else if( rMEvt
.IsMod1() )
812 AddSelectedRect( aCurSelectionRect
);
814 aCurSelectionRect
.SetPos( aDocPos
);
817 if( !pEntry
&& !(nWinBits
& WB_NODRAGSELECTION
))
818 pView
->StartTracking( STARTTRACK_SCROLLREPEAT
);
825 if( eSelectionMode
== MULTIPLE_SELECTION
)
827 if( !rMEvt
.IsMod1() ) // Ctrl
832 ClearSelectedRectList();
836 nFlags
|= F_ADD_MODE
;
837 aCurSelectionRect
.SetPos( aDocPos
);
838 pView
->StartTracking( STARTTRACK_SCROLLREPEAT
);
841 bHandled
= sal_False
;
845 sal_Bool bSelected
= pEntry
->IsSelected();
846 sal_Bool bEditingEnabled
= IsEntryEditingEnabled();
848 if( rMEvt
.GetClicks() == 2 )
850 DeselectAllBut( pEntry
);
851 SelectEntry( pEntry
, sal_True
, sal_True
, sal_False
, sal_True
);
858 if( rMEvt
.IsMod2() ) // Alt?
860 if( bEntryEditingEnabled
&& pEntry
&&
861 pEntry
->IsSelected())
863 if( pView
->EditingEntry( pEntry
))
867 else if( eSelectionMode
== SINGLE_SELECTION
)
869 DeselectAllBut( pEntry
);
871 if( bEditingEnabled
&& bSelected
&& !rMEvt
.GetModifier() &&
872 rMEvt
.IsLeft() && IsTextHit( pEntry
, aDocPos
) )
874 nFlags
|= F_START_EDITTIMER_IN_MOUSEUP
;
877 else if( eSelectionMode
== NO_SELECTION
)
879 if( rMEvt
.IsLeft() && (nWinBits
& WB_HIGHLIGHTFRAME
) )
881 pCurHighlightFrame
= 0; // force repaint of frame
882 bHighlightFramePressed
= sal_True
;
883 SetEntryHighlightFrame( pEntry
, sal_True
);
888 if( !rMEvt
.GetModifier() && rMEvt
.IsLeft() )
892 DeselectAllBut( pEntry
, sal_True
/* paint synchronously */ );
894 SelectEntry( pEntry
, sal_True
, sal_True
, sal_False
, sal_True
);
898 // deselect only in the Up, if the Move happened via D&D!
899 nFlags
|= F_DOWN_DESELECT
;
900 if( bEditingEnabled
&& IsTextHit( pEntry
, aDocPos
) &&
903 nFlags
|= F_START_EDITTIMER_IN_MOUSEUP
;
907 else if( rMEvt
.IsMod1() )
908 nFlags
|= F_DOWN_CTRL
;
914 sal_Bool
SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent
& rMEvt
)
916 sal_Bool bHandled
= sal_False
;
917 if( rMEvt
.IsRight() && (nFlags
& (F_DOWN_CTRL
| F_DOWN_DESELECT
) ))
919 nFlags
&= ~(F_DOWN_CTRL
| F_DOWN_DESELECT
);
923 Point
aDocPos( rMEvt
.GetPosPixel() );
925 SvxIconChoiceCtrlEntry
* pDocEntry
= GetEntry( aDocPos
);
928 if( nFlags
& F_DOWN_CTRL
)
930 // Ctrl & MultiSelection
931 ToggleSelection( pDocEntry
);
932 SetCursor( pDocEntry
);
935 else if( nFlags
& F_DOWN_DESELECT
)
937 DeselectAllBut( pDocEntry
);
938 SetCursor( pDocEntry
);
939 SelectEntry( pDocEntry
, sal_True
, sal_True
, sal_False
, sal_True
);
944 nFlags
&= ~(F_DOWN_CTRL
| F_DOWN_DESELECT
);
945 if( nFlags
& F_START_EDITTIMER_IN_MOUSEUP
)
949 nFlags
&= ~F_START_EDITTIMER_IN_MOUSEUP
;
952 if((nWinBits
& WB_HIGHLIGHTFRAME
) && bHighlightFramePressed
&& pCurHighlightFrame
)
955 SvxIconChoiceCtrlEntry
* pEntry
= pCurHighlightFrame
;
956 pCurHighlightFrame
= 0; // force repaint of frame
957 bHighlightFramePressed
= sal_False
;
958 SetEntryHighlightFrame( pEntry
, sal_True
);
960 pHdlEntry
= pCurHighlightFrame
;
964 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
965 SetCursor_Impl( pOldCursor
, pHdlEntry
, sal_False
, sal_False
, sal_True
);
972 sal_Bool
SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent
& rMEvt
)
974 const Point
aDocPos( pView
->PixelToLogic(rMEvt
.GetPosPixel()) );
976 if( pView
->IsTracking() )
978 else if( nWinBits
& WB_HIGHLIGHTFRAME
)
980 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, sal_True
);
981 SetEntryHighlightFrame( pEntry
);
988 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry
* pOldCursor
,
989 SvxIconChoiceCtrlEntry
* pNewCursor
, sal_Bool bMod1
, sal_Bool bShift
, sal_Bool bPaintSync
)
993 SvxIconChoiceCtrlEntry
* pFilterEntry
= 0;
994 sal_Bool bDeselectAll
= sal_False
;
995 if( eSelectionMode
!= SINGLE_SELECTION
)
997 if( !bMod1
&& !bShift
)
998 bDeselectAll
= sal_True
;
999 else if( bShift
&& !bMod1
&& !pAnchor
)
1001 bDeselectAll
= sal_True
;
1002 pFilterEntry
= pOldCursor
;
1006 DeselectAllBut( pFilterEntry
, bPaintSync
);
1007 ShowCursor( sal_False
);
1008 MakeEntryVisible( pNewCursor
);
1009 SetCursor( pNewCursor
);
1010 if( bMod1
&& !bShift
)
1014 AddSelectedRect( pAnchor
, pOldCursor
);
1021 pAnchor
= pOldCursor
;
1022 if ( nWinBits
& WB_ALIGN_LEFT
)
1023 SelectRange( pAnchor
, pNewCursor
, (nFlags
& F_ADD_MODE
)!=0 );
1025 SelectRect(pAnchor
,pNewCursor
,(nFlags
& F_ADD_MODE
)!=0,&aSelectedRectList
);
1029 SelectEntry( pCursor
, sal_True
, sal_True
, sal_False
, bPaintSync
);
1030 aCurSelectionRect
= GetEntryBoundRect( pCursor
);
1035 sal_Bool
SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent
& rKEvt
)
1039 sal_Bool bMod2
= rKEvt
.GetKeyCode().IsMod2();
1040 sal_Unicode cChar
= rKEvt
.GetCharCode();
1041 sal_uLong nPos
= (sal_uLong
)-1;
1042 if ( bMod2
&& cChar
&& IsMnemonicChar( cChar
, nPos
) )
1044 // shortcut is clicked
1045 SvxIconChoiceCtrlEntry
* pNewCursor
= GetEntry( nPos
);
1046 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
1047 if ( pNewCursor
!= pOldCursor
)
1048 SetCursor_Impl( pOldCursor
, pNewCursor
, sal_False
, sal_False
, sal_False
);
1053 // no actions with <ALT>
1056 sal_Bool bKeyUsed
= sal_True
;
1057 sal_Bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
1058 sal_Bool bShift
= rKEvt
.GetKeyCode().IsShift();
1060 if( eSelectionMode
== SINGLE_SELECTION
|| eSelectionMode
== NO_SELECTION
)
1067 nFlags
|= F_ADD_MODE
;
1069 SvxIconChoiceCtrlEntry
* pNewCursor
;
1070 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
1072 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1079 MakeEntryVisible( pCursor
);
1080 if( nCode
== KEY_UP
)
1081 pNewCursor
= pImpCursor
->GoUpDown(pCursor
,sal_False
);
1083 pNewCursor
= pImpCursor
->GoPageUpDown(pCursor
,sal_False
);
1084 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1087 Rectangle
aRect( GetEntryBoundRect( pCursor
) );
1090 aRect
.Bottom() -= aRect
.Top();
1092 MakeVisible( aRect
);
1096 if ( bChooseWithCursor
&& pNewCursor
!= NULL
)
1098 pHdlEntry
= pNewCursor
;//GetCurEntry();
1099 pCurHighlightFrame
= pHdlEntry
;
1101 pCurHighlightFrame
= NULL
;
1110 if( nCode
== KEY_DOWN
)
1111 pNewCursor
=pImpCursor
->GoUpDown( pCursor
,sal_True
);
1113 pNewCursor
=pImpCursor
->GoPageUpDown( pCursor
,sal_True
);
1114 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1116 if ( bChooseWithCursor
&& pNewCursor
!= NULL
)
1118 pHdlEntry
= pNewCursor
;//GetCurEntry();
1119 pCurHighlightFrame
= pHdlEntry
;
1121 pCurHighlightFrame
= NULL
;
1129 pNewCursor
=pImpCursor
->GoLeftRight(pCursor
,sal_True
);
1130 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1137 MakeEntryVisible( pCursor
);
1138 pNewCursor
= pImpCursor
->GoLeftRight(pCursor
,sal_False
);
1139 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1142 Rectangle
aRect( GetEntryBoundRect(pCursor
));
1145 aRect
.Right() -= aRect
.Left();
1147 MakeVisible( aRect
);
1154 if( !bMod1
&& !bShift
)
1155 EditTimeoutHdl( 0 );
1157 bKeyUsed
= sal_False
;
1161 if( rKEvt
.GetKeyCode().IsShift() )
1163 if( nFlags
& F_ADD_MODE
)
1164 nFlags
&= (~F_ADD_MODE
);
1166 nFlags
|= F_ADD_MODE
;
1169 bKeyUsed
= sal_False
;
1173 if( pCursor
&& eSelectionMode
!= SINGLE_SELECTION
)
1177 //SelectAll( sal_False );
1179 ClearSelectedRectList();
1181 // click Icon with spacebar
1182 SetEntryHighlightFrame( GetCurEntry(), sal_True
);
1184 pHdlEntry
= pCurHighlightFrame
;
1185 pCurHighlightFrame
=0;
1188 ToggleSelection( pCursor
);
1194 if( rKEvt
.GetKeyCode().IsShift() )
1197 pView
->SetEntryTextMode( IcnShowTextFull
, pCursor
);
1199 if( rKEvt
.GetKeyCode().IsMod1() )
1202 pView
->SetEntryTextMode( IcnShowTextShort
, pCursor
);
1210 if( bMod1
&& (eSelectionMode
!= SINGLE_SELECTION
))
1211 SelectAll( sal_True
);
1213 bKeyUsed
= sal_False
;
1221 bKeyUsed
= sal_False
;
1227 if( pCursor
&& bEntryEditingEnabled
)
1228 /*pView->*/EditEntry( pCursor
);
1231 bKeyUsed
= sal_False
;
1237 pNewCursor
= aEntries
[ aEntries
.size() - 1 ];
1238 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1245 pNewCursor
= aEntries
[ 0 ];
1246 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
, sal_True
);
1251 bKeyUsed
= sal_False
;
1257 // recalculate TopLeft of scrollbars (but not their sizes!)
1258 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth
, long nRealHeight
)
1260 // horizontal scrollbar
1261 Point
aPos( 0, nRealHeight
);
1262 aPos
.Y() -= nHorSBarHeight
;
1264 if( aHorSBar
.GetPosPixel() != aPos
)
1265 aHorSBar
.SetPosPixel( aPos
);
1267 // vertical scrollbar
1268 aPos
.X() = nRealWidth
; aPos
.Y() = 0;
1269 aPos
.X() -= nVerSBarWidth
;
1273 if( aVerSBar
.GetPosPixel() != aPos
)
1274 aVerSBar
.SetPosPixel( aPos
);
1277 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool
)
1279 Rectangle
aOldOutRect( GetOutputRect() );
1280 long nVirtHeight
= aVirtOutputSize
.Height();
1281 long nVirtWidth
= aVirtOutputSize
.Width();
1283 Size
aOSize( pView
->Control::GetOutputSizePixel() );
1284 long nRealHeight
= aOSize
.Height();
1285 long nRealWidth
= aOSize
.Width();
1287 PositionScrollBars( nRealWidth
, nRealHeight
);
1289 const MapMode
& rMapMode
= pView
->GetMapMode();
1290 Point
aOrigin( rMapMode
.GetOrigin() );
1293 if( nRealWidth
> nVirtWidth
)
1294 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1296 nVisibleWidth
= nRealWidth
;
1298 long nVisibleHeight
;
1299 if( nRealHeight
> nVirtHeight
)
1300 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1302 nVisibleHeight
= nRealHeight
;
1304 sal_Bool bVerSBar
= ( nWinBits
& WB_VSCROLL
) != 0;
1305 sal_Bool bHorSBar
= ( nWinBits
& WB_HSCROLL
) != 0;
1306 sal_Bool bNoVerSBar
= ( nWinBits
& WB_NOVSCROLL
) != 0;
1307 sal_Bool bNoHorSBar
= ( nWinBits
& WB_NOHSCROLL
) != 0;
1309 sal_uInt16 nResult
= 0;
1312 // activate vertical scrollbar?
1313 if( !bNoVerSBar
&& (bVerSBar
|| ( nVirtHeight
> nVisibleHeight
)) )
1316 nRealWidth
-= nVerSBarWidth
;
1318 if( nRealWidth
> nVirtWidth
)
1319 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1321 nVisibleWidth
= nRealWidth
;
1323 nFlags
|= F_HOR_SBARSIZE_WITH_VBAR
;
1325 // activate horizontal scrollbar?
1326 if( !bNoHorSBar
&& (bHorSBar
|| (nVirtWidth
> nVisibleWidth
)) )
1329 nRealHeight
-= nHorSBarHeight
;
1331 if( nRealHeight
> nVirtHeight
)
1332 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1334 nVisibleHeight
= nRealHeight
;
1336 // do we need a vertical scrollbar after all?
1337 if( !(nResult
& 0x0001) && // only if not already there
1338 ( !bNoVerSBar
&& ((nVirtHeight
> nVisibleHeight
) || bVerSBar
)) )
1340 nResult
= 3; // both turned on
1341 nRealWidth
-= nVerSBarWidth
;
1343 if( nRealWidth
> nVirtWidth
)
1344 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1346 nVisibleWidth
= nRealWidth
;
1348 nFlags
|= F_VER_SBARSIZE_WITH_HBAR
;
1353 // size vertical scrollbar
1354 long nThumb
= aVerSBar
.GetThumbPos();
1355 Size
aSize( nVerSBarWidth
, nRealHeight
);
1356 aSize
.Height() += 2;
1357 if( aSize
!= aVerSBar
.GetSizePixel() )
1358 aVerSBar
.SetSizePixel( aSize
);
1359 aVerSBar
.SetVisibleSize( nVisibleHeight
);
1360 aVerSBar
.SetPageSize( GetScrollBarPageSize( nVisibleHeight
));
1362 if( nResult
& 0x0001 )
1364 aVerSBar
.SetThumbPos( nThumb
);
1369 aVerSBar
.SetThumbPos( 0 );
1373 // size horizontal scrollbar
1374 nThumb
= aHorSBar
.GetThumbPos();
1375 aSize
.Width() = nRealWidth
;
1376 aSize
.Height() = nHorSBarHeight
;
1378 if( nResult
& 0x0001 ) // vertical scrollbar?
1383 if( aSize
!= aHorSBar
.GetSizePixel() )
1384 aHorSBar
.SetSizePixel( aSize
);
1385 aHorSBar
.SetVisibleSize( nVisibleWidth
);
1386 aHorSBar
.SetPageSize( GetScrollBarPageSize(nVisibleWidth
));
1387 if( nResult
& 0x0002 )
1389 aHorSBar
.SetThumbPos( nThumb
);
1394 aHorSBar
.SetThumbPos( 0 );
1398 aOutputSize
.Width() = nRealWidth
;
1399 if( nResult
& 0x0002 ) // horizontal scrollbar ?
1400 nRealHeight
++; // because lower border is clipped
1401 aOutputSize
.Height() = nRealHeight
;
1403 Rectangle
aNewOutRect( GetOutputRect() );
1404 if( aNewOutRect
!= aOldOutRect
&& pView
->HasBackground() )
1406 Wallpaper
aPaper( pView
->GetBackground() );
1407 aPaper
.SetRect( aNewOutRect
);
1408 pView
->SetBackground( aPaper
);
1411 if( (nResult
& (0x0001|0x0002)) == (0x0001|0x0002) )
1417 void SvxIconChoiceCtrl_Impl::Resize()
1421 aOutputSize
= pView
->GetOutputSizePixel();
1422 pImpCursor
->Clear();
1423 pGridMap
->OutputSizeChanged();
1425 const Size
& rSize
= pView
->Control::GetOutputSizePixel();
1426 PositionScrollBars( rSize
.Width(), rSize
.Height() );
1427 // The scrollbars are shown/hidden asynchronously, so derived classes can
1428 // do an Arrange during Resize, without the scrollbars suddenly turning
1429 // on and off again.
1430 // If an event is already underway, we don't need to send a new one, at least
1431 // as long as there is only one event type.
1432 if ( ! nUserEventAdjustScrBars
)
1433 nUserEventAdjustScrBars
=
1434 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl
, UserEventHdl
),
1435 EVENTID_ADJUST_SCROLLBARS
);
1437 if( pView
->HasBackground() && !pView
->GetBackground().IsScrollable() )
1439 Rectangle
aRect( GetOutputRect());
1440 Wallpaper
aPaper( pView
->GetBackground() );
1441 aPaper
.SetRect( aRect
);
1442 pView
->SetBackground( aPaper
);
1447 sal_Bool
SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1449 if( !pZOrderList
|| !aHorSBar
.IsVisible() )
1451 const MapMode
& rMapMode
= pView
->GetMapMode();
1452 Point
aOrigin( rMapMode
.GetOrigin() );
1453 if(!( nWinBits
& WB_HSCROLL
) && !aOrigin
.X() )
1455 long nWidth
= aOutputSize
.Width();
1456 const size_t nCount
= pZOrderList
->size();
1457 long nMostRight
= 0;
1458 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1460 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nCur
];
1461 long nRight
= GetEntryBoundRect(pEntry
).Right();
1462 if( nRight
> nWidth
)
1464 if( nRight
> nMostRight
)
1465 nMostRight
= nRight
;
1468 aOutputSize
.Height() += nHorSBarHeight
;
1469 aVirtOutputSize
.Width() = nMostRight
;
1470 aHorSBar
.SetThumbPos( 0 );
1472 aRange
.Max() = nMostRight
- 1;
1473 aHorSBar
.SetRange( aRange
);
1474 if( aVerSBar
.IsVisible() )
1476 Size
aSize( aVerSBar
.GetSizePixel());
1477 aSize
.Height() += nHorSBarHeight
;
1478 aVerSBar
.SetSizePixel( aSize
);
1485 sal_Bool
SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1487 if( !pZOrderList
|| !aVerSBar
.IsVisible() )
1489 const MapMode
& rMapMode
= pView
->GetMapMode();
1490 Point
aOrigin( rMapMode
.GetOrigin() );
1491 if(!( nWinBits
& WB_VSCROLL
) && !aOrigin
.Y() )
1494 long nHeight
= aOutputSize
.Height();
1495 const size_t nCount
= pZOrderList
->size();
1496 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1498 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nCur
];
1499 long nBottom
= GetEntryBoundRect(pEntry
).Bottom();
1500 if( nBottom
> nHeight
)
1502 if( nBottom
> nDeepest
)
1506 aOutputSize
.Width() += nVerSBarWidth
;
1507 aVirtOutputSize
.Height() = nDeepest
;
1508 aVerSBar
.SetThumbPos( 0 );
1510 aRange
.Max() = nDeepest
- 1;
1511 aVerSBar
.SetRange( aRange
);
1512 if( aHorSBar
.IsVisible() )
1514 Size
aSize( aHorSBar
.GetSizePixel());
1515 aSize
.Width() += nVerSBarWidth
;
1516 aHorSBar
.SetSizePixel( aSize
);
1524 // hides scrollbars if they're unnecessary
1525 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1527 CheckVerScrollBar();
1528 if( CheckHorScrollBar() )
1529 CheckVerScrollBar();
1530 if( aVerSBar
.IsVisible() && aHorSBar
.IsVisible() )
1537 void SvxIconChoiceCtrl_Impl::GetFocus()
1539 RepaintEntries( ICNVIEW_FLAG_SELECTED
);
1542 pCursor
->SetFlags( ICNVIEW_FLAG_FOCUSED
);
1543 ShowCursor( sal_True
);
1547 void SvxIconChoiceCtrl_Impl::LoseFocus()
1551 pCursor
->ClearFlags( ICNVIEW_FLAG_FOCUSED
);
1552 ShowCursor( sal_False
);
1555 // pView->Invalidate ( aFocus.aRect );
1557 RepaintEntries( ICNVIEW_FLAG_SELECTED
);
1560 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate
)
1562 if( bUpdate
!= bUpdateMode
)
1564 bUpdateMode
= bUpdate
;
1568 pImpCursor
->Clear();
1570 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
1575 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry
* pEntry
, sal_Bool bIsBackgroundPainted
)
1577 Point
aPos( GetEntryPos( pEntry
) );
1578 PaintEntry( pEntry
, aPos
, 0, bIsBackgroundPainted
);
1581 // priorities of the emphasis: bDropTarget => bCursored => bSelected
1582 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1583 const Rectangle
& rTextRect
, const Rectangle
& rImageRect
,
1584 sal_Bool bSelected
, sal_Bool bDropTarget
, sal_Bool bCursored
, OutputDevice
* pOut
,
1585 sal_Bool bIsBackgroundPainted
)
1587 static Color
aTransparent( COL_TRANSPARENT
);
1592 #ifdef OV_CHECK_EMPH_RECTS
1594 Color
aXOld( pOut
->GetFillColor() );
1595 pOut
->SetFillColor( Color( COL_GREEN
));
1596 pOut
->DrawRect( rTextRect
);
1597 pOut
->DrawRect( rImageRect
);
1598 pOut
->SetFillColor( aXOld
);
1602 const StyleSettings
& rSettings
= pOut
->GetSettings().GetStyleSettings();
1603 Color
aOldFillColor( pOut
->GetFillColor() );
1605 sal_Bool bSolidTextRect
= sal_False
;
1606 sal_Bool bSolidImageRect
= sal_False
;
1608 if( bDropTarget
&& ( eSelectionMode
!= NO_SELECTION
) )
1610 pOut
->SetFillColor( rSettings
.GetHighlightColor() );
1611 bSolidTextRect
= sal_True
;
1612 bSolidImageRect
= sal_True
;
1616 if ( !bSelected
|| bCursored
)
1618 if( !pView
->HasFontFillColor() )
1619 pOut
->SetFillColor( pOut
->GetBackground().GetColor() );
1622 const Color
& rFillColor
= pView
->GetFont().GetFillColor();
1623 pOut
->SetFillColor( rFillColor
);
1624 if( rFillColor
!= aTransparent
)
1625 bSolidTextRect
= sal_True
;
1630 // draw text rectangle
1631 if( !bSolidTextRect
)
1633 if( !bIsBackgroundPainted
)
1634 pOut
->Erase( rTextRect
);
1638 Color aOldLineColor
;
1641 aOldLineColor
= pOut
->GetLineColor();
1642 pOut
->SetLineColor( Color( COL_GRAY
) );
1644 pOut
->DrawRect( rTextRect
);
1646 pOut
->SetLineColor( aOldLineColor
);
1649 // draw image rectangle
1650 if( !bSolidImageRect
)
1652 if( !bIsBackgroundPainted
)
1653 pOut
->Erase( rImageRect
);
1655 // the emphasis of the images has to be drawn by the derived class (in the
1656 // virtual function DrawEntryImage)
1658 // pOut->DrawRect( rImageRect );
1660 pOut
->SetFillColor( aOldFillColor
);
1664 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle
& rRect
,
1665 IcnViewFieldType eItem
, SvxIconChoiceCtrlEntry
* pEntry
, sal_uInt16 nPaintFlags
,
1666 OutputDevice
* pOut
, const String
* pStr
, ::vcl::ControlLayoutData
* _pLayoutData
)
1668 if( eItem
== IcnViewFieldTypeText
)
1672 aText
= pView
->GetEntryText( pEntry
, sal_False
);
1678 pOut
->DrawText( rRect
, aText
, nCurTextDrawFlags
,
1679 &_pLayoutData
->m_aUnicodeBoundRects
, &_pLayoutData
->m_aDisplayText
);
1683 Color aOldFontColor
= pOut
->GetTextColor();
1684 if ( pView
->AutoFontColor() )
1686 Color
aBkgColor( pOut
->GetBackground().GetColor() );
1688 sal_uInt16 nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
1690 aFontColor
.SetColor ( COL_BLACK
);
1692 aFontColor
.SetColor( COL_WHITE
);
1693 pOut
->SetTextColor( aFontColor
);
1696 pOut
->DrawText( rRect
, aText
, nCurTextDrawFlags
);
1698 if ( pView
->AutoFontColor() )
1699 pOut
->SetTextColor( aOldFontColor
);
1701 if( pEntry
->IsFocused() )
1703 Rectangle
aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry
*)pEntry
) );
1704 /*pView->*/ShowFocus( aRect
);
1705 DrawFocusRect( pOut
);
1711 Point
aPos( rRect
.TopLeft() );
1712 if( nPaintFlags
& PAINTFLAG_HOR_CENTERED
)
1713 aPos
.X() += (rRect
.GetWidth() - aImageSize
.Width() ) / 2;
1714 if( nPaintFlags
& PAINTFLAG_VER_CENTERED
)
1715 aPos
.Y() += (rRect
.GetHeight() - aImageSize
.Height() ) / 2;
1716 pView
->DrawEntryImage( pEntry
, aPos
, *pOut
);
1720 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry
* pEntry
)
1722 #ifdef OV_NO_VIRT_OUTDEV
1723 PaintEntry( pEntry
);
1725 if( !pEntryPaintDev
)
1727 pEntryPaintDev
= new VirtualDevice( *pView
);
1728 pEntryPaintDev
->SetFont( pView
->GetFont() );
1729 pEntryPaintDev
->SetLineColor();
1730 //pEntryPaintDev->SetBackground( pView->GetBackground() );
1732 const Rectangle
& rRect
= GetEntryBoundRect( pEntry
);
1733 Rectangle
aOutRect( GetOutputRect() );
1734 if( !rRect
.IsOver( aOutRect
) )
1736 Wallpaper
aPaper( pView
->GetBackground() );
1737 Rectangle
aRect( aPaper
.GetRect() );
1739 // move rectangle, so the bounding rectangle of the entry lies in
1740 // VirtOut-Dev at 0,0
1741 aRect
.Move( -rRect
.Left(), -rRect
.Top() );
1742 aPaper
.SetRect( aRect
);
1743 pEntryPaintDev
->SetBackground( aPaper
);
1744 pEntryPaintDev
->SetFont( pView
->GetFont() );
1746 Size
aSize( rRect
.GetSize() );
1747 pEntryPaintDev
->SetOutputSizePixel( aSize
);
1748 pEntryPaintDev
->DrawOutDev(
1749 Point(), aSize
, rRect
.TopLeft(), aSize
, *pView
);
1751 PaintEntry( pEntry
, Point(), pEntryPaintDev
);
1763 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
1764 OutputDevice
* pOut
, sal_Bool bIsBackgroundPainted
)
1769 sal_Bool bSelected
= sal_False
;
1771 if( eSelectionMode
!= NO_SELECTION
)
1772 bSelected
= pEntry
->IsSelected();
1774 sal_Bool bCursored
= pEntry
->IsCursored();
1775 sal_Bool bDropTarget
= pEntry
->IsDropTarget();
1776 sal_Bool bNoEmphasis
= pEntry
->IsBlockingEmphasis();
1778 Font
aTempFont( pOut
->GetFont() );
1782 if ( pView->AutoFontColor() )
1784 aTempFont.SetColor ( aFontColor );
1788 String
aEntryText( pView
->GetEntryText( pEntry
, sal_False
) );
1789 Rectangle
aTextRect( CalcTextRect(pEntry
,&rPos
,sal_False
,&aEntryText
));
1790 Rectangle
aBmpRect( CalcBmpRect(pEntry
, &rPos
) );
1792 sal_Bool bShowSelection
=
1793 ( ( ( bSelected
&& !bCursored
)
1797 && ( eSelectionMode
!= NO_SELECTION
)
1799 sal_Bool bActiveSelection
= ( 0 != ( nWinBits
& WB_NOHIDESELECTION
) ) || pView
->HasFocus();
1801 if ( bShowSelection
)
1803 const StyleSettings
& rSettings
= pOut
->GetSettings().GetStyleSettings();
1804 Font
aNewFont( aTempFont
);
1806 // font fill colors that are attributed "hard" need corresponding "hard"
1807 // attributed highlight colors
1808 if( pView
->HasFontFillColor() )
1810 if( (nWinBits
& WB_NOHIDESELECTION
) || pView
->HasFocus() )
1811 aNewFont
.SetFillColor( rSettings
.GetHighlightColor() );
1813 aNewFont
.SetFillColor( rSettings
.GetDeactiveColor() );
1816 Color aWinCol
= rSettings
.GetWindowTextColor();
1817 if ( !bActiveSelection
&& rSettings
.GetFaceColor().IsBright() == aWinCol
.IsBright() )
1818 aNewFont
.SetColor( rSettings
.GetWindowTextColor() );
1820 aNewFont
.SetColor( rSettings
.GetHighlightTextColor() );
1822 pOut
->SetFont( aNewFont
);
1824 pOut
->SetFillColor( pOut
->GetBackground().GetColor() );
1825 pOut
->DrawRect( CalcFocusRect( pEntry
) );
1826 pOut
->SetFillColor( );
1829 sal_Bool bResetClipRegion
= sal_False
;
1830 if( !pView
->IsClipRegion() && (aVerSBar
.IsVisible() || aHorSBar
.IsVisible()) )
1832 Rectangle
aOutputArea( GetOutputRect() );
1833 if( aOutputArea
.IsOver(aTextRect
) || aOutputArea
.IsOver(aBmpRect
) )
1835 pView
->SetClipRegion(Region(aOutputArea
));
1836 bResetClipRegion
= sal_True
;
1840 #ifdef OV_DRAWBOUNDRECT
1842 Color aXOldColor
= pOut
->GetLineColor();
1843 pOut
->SetLineColor( Color( COL_LIGHTRED
) );
1844 Rectangle
aXRect( pEntry
->aRect
);
1845 aXRect
.SetPos( rPos
);
1846 pOut
->DrawRect( aXRect
);
1847 pOut
->SetLineColor( aXOldColor
);
1851 sal_Bool bLargeIconMode
= WB_ICON
== ( nWinBits
& (VIEWMODE_MASK
) );
1852 sal_uInt16 nBmpPaintFlags
= PAINTFLAG_VER_CENTERED
;
1853 if ( bLargeIconMode
)
1854 nBmpPaintFlags
|= PAINTFLAG_HOR_CENTERED
;
1855 sal_uInt16 nTextPaintFlags
= bLargeIconMode
? PAINTFLAG_HOR_CENTERED
: PAINTFLAG_VER_CENTERED
;
1858 PaintEmphasis(aTextRect
,aBmpRect
,bSelected
,bDropTarget
,bCursored
,pOut
,bIsBackgroundPainted
);
1860 if ( bShowSelection
)
1861 pView
->DrawSelectionBackground( CalcFocusRect( pEntry
),
1862 bActiveSelection
? 1 : 2 /* highlight */, sal_False
/* check */, sal_True
/* border */, sal_False
/* ext border only */ );
1864 PaintItem( aBmpRect
, IcnViewFieldTypeImage
, pEntry
, nBmpPaintFlags
, pOut
);
1866 PaintItem( aTextRect
, IcnViewFieldTypeText
, pEntry
,
1867 nTextPaintFlags
, pOut
);
1869 // draw highlight frame
1870 if( pEntry
== pCurHighlightFrame
&& !bNoEmphasis
)
1871 DrawHighlightFrame( pOut
, CalcFocusRect( pEntry
), sal_False
);
1873 pOut
->SetFont( aTempFont
);
1874 if( bResetClipRegion
)
1875 pView
->SetClipRegion();
1878 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
1879 sal_Bool bAdjustAtGrid
, sal_Bool bCheckScrollBars
, sal_Bool bKeepGridMap
)
1881 ShowCursor( sal_False
);
1882 Rectangle
aBoundRect( GetEntryBoundRect( pEntry
));
1883 pView
->Invalidate( aBoundRect
);
1885 if( !IsAutoArrange() )
1887 sal_Bool bAdjustVirtSize
= sal_False
;
1888 if( rPos
!= aBoundRect
.TopLeft() )
1891 pEntry
->aGridRect
.TopLeft() - pEntry
->aRect
.TopLeft() );
1892 pImpCursor
->Clear();
1895 aBoundRect
.SetPos( rPos
);
1896 pEntry
->aRect
= aBoundRect
;
1897 pEntry
->aGridRect
.SetPos( rPos
+ aGridOffs
);
1898 bAdjustVirtSize
= sal_True
;
1902 if( bAdjustVirtSize
)
1904 // By aligning the (in some cases newly positioned) entry, it
1905 // can become completely visible again, so that maybe we don't
1906 // need a scrollbar after all. To avoid suddenly turning the
1907 // scrollbar(s) on and then off again, we use the aligned
1908 // bounding rectangle of the entry to enlarge the virtual
1909 // output size. The virtual size has to be adapted, because
1910 // AdjustEntryAtGrid depends on it.
1911 const Rectangle
& rBoundRect
= GetEntryBoundRect( pEntry
);
1912 Rectangle
aCenterRect( CalcBmpRect( pEntry
, 0 ));
1913 Point
aNewPos( AdjustAtGrid( aCenterRect
, rBoundRect
) );
1914 Rectangle
aNewBoundRect( aNewPos
, pEntry
->aRect
.GetSize());
1915 AdjustVirtSize( aNewBoundRect
);
1916 bAdjustVirtSize
= sal_False
;
1918 AdjustEntryAtGrid( pEntry
);
1921 if( bAdjustVirtSize
)
1922 AdjustVirtSize( pEntry
->aRect
);
1924 if( bCheckScrollBars
&& bUpdateMode
)
1927 pView
->Invalidate( pEntry
->aRect
);
1928 pGridMap
->OccupyGrids( pEntry
);
1932 SvxIconChoiceCtrlEntry
* pPrev
= FindEntryPredecessor( pEntry
, rPos
);
1933 SetEntryPredecessor( pEntry
, pPrev
);
1934 aAutoArrangeTimer
.Start();
1936 ShowCursor( sal_True
);
1939 void SvxIconChoiceCtrl_Impl::SetNoSelection()
1941 // block recursive calls via SelectEntry
1942 if( !(nFlags
& F_CLEARING_SELECTION
))
1944 nFlags
|= F_CLEARING_SELECTION
;
1945 DeselectAllBut( 0, sal_True
);
1946 nFlags
&= ~F_CLEARING_SELECTION
;
1950 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetEntry( const Point
& rDocPos
, sal_Bool bHit
)
1952 CheckBoundingRects();
1953 // search through z-order list from the end
1954 size_t nCount
= pZOrderList
->size();
1958 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nCount
];
1959 if( pEntry
->aRect
.IsInside( rDocPos
) )
1963 Rectangle aRect
= CalcBmpRect( pEntry
);
1965 aRect
.Bottom() += 3;
1968 if( aRect
.IsInside( rDocPos
) )
1970 aRect
= CalcTextRect( pEntry
);
1971 if( aRect
.IsInside( rDocPos
) )
1981 Point
SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry
* pEntry
)
1983 return pEntry
->aRect
.TopLeft();
1986 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry
* pEntry
, sal_Bool bBound
)
1990 const Rectangle
& rRect
= GetEntryBoundRect( pEntry
);
1991 MakeVisible( rRect
);
1995 Rectangle aRect
= CalcBmpRect( pEntry
);
1996 aRect
.Union( CalcTextRect( pEntry
) );
1997 aRect
.Top() += TBOFFS_BOUND
;
1998 aRect
.Bottom() += TBOFFS_BOUND
;
1999 aRect
.Left() += LROFFS_BOUND
;
2000 aRect
.Right() += LROFFS_BOUND
;
2001 MakeVisible( aRect
);
2005 const Rectangle
& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry
* pEntry
)
2007 if( !IsBoundingRectValid( pEntry
->aRect
))
2008 FindBoundingRect( pEntry
);
2009 return pEntry
->aRect
;
2012 Rectangle
SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry
* pEntry
, const Point
* pPos
)
2014 Rectangle aBound
= GetEntryBoundRect( pEntry
);
2016 aBound
.SetPos( *pPos
);
2017 Point
aPos( aBound
.TopLeft() );
2019 switch( nWinBits
& (VIEWMODE_MASK
) )
2023 aPos
.X() += ( aBound
.GetWidth() - aImageSize
.Width() ) / 2;
2024 return Rectangle( aPos
, aImageSize
);
2029 aPos
.Y() += ( aBound
.GetHeight() - aImageSize
.Height() ) / 2;
2030 //TODO: determine horizontal distance to bounding rectangle
2031 return Rectangle( aPos
, aImageSize
);
2034 OSL_FAIL("IconView: Viewmode not set");
2039 Rectangle
SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry
* pEntry
,
2040 const Point
* pEntryPos
, sal_Bool bEdit
, const String
* pStr
)
2044 aEntryText
= pView
->GetEntryText( pEntry
, bEdit
);
2048 const Rectangle
aMaxTextRect( CalcMaxTextRect( pEntry
) );
2049 Rectangle
aBound( GetEntryBoundRect( pEntry
) );
2051 aBound
.SetPos( *pEntryPos
);
2053 Rectangle
aTextRect( aMaxTextRect
);
2055 aTextRect
= pView
->GetTextRect( aTextRect
, aEntryText
, nCurTextDrawFlags
);
2057 Size
aTextSize( aTextRect
.GetSize() );
2059 Point
aPos( aBound
.TopLeft() );
2060 long nBoundWidth
= aBound
.GetWidth();
2061 long nBoundHeight
= aBound
.GetHeight();
2063 switch( nWinBits
& (VIEWMODE_MASK
) )
2066 aPos
.Y() += aImageSize
.Height();
2067 aPos
.Y() += VER_DIST_BMP_STRING
;
2068 // at little more space when editing
2072 long nMinWidth
= (( (aImageSize
.Width()*10) / 100 ) * 2 ) +
2074 if( nMinWidth
> nBoundWidth
)
2075 nMinWidth
= nBoundWidth
;
2077 if( aTextSize
.Width() < nMinWidth
)
2078 aTextSize
.Width() = nMinWidth
;
2080 // when editing, overlap with the area below is allowed
2081 Size aOptSize
= aMaxTextRect
.GetSize();
2082 if( aOptSize
.Height() > aTextSize
.Height() )
2083 aTextSize
.Height() = aOptSize
.Height();
2085 aPos
.X() += (nBoundWidth
- aTextSize
.Width()) / 2;
2090 aPos
.X() += aImageSize
.Width();
2091 aPos
.X() += HOR_DIST_BMP_STRING
;
2092 aPos
.Y() += (nBoundHeight
- aTextSize
.Height()) / 2;
2095 return Rectangle( aPos
, aTextSize
);
2099 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry
* pEntry
) const
2101 long nStringWidth
= GetItemSize( pEntry
, IcnViewFieldTypeText
).Width();
2102 // nStringWidth += 2*LROFFS_TEXT;
2105 switch( nWinBits
& (VIEWMODE_MASK
) )
2108 nWidth
= std::max( nStringWidth
, aImageSize
.Width() );
2113 nWidth
= aImageSize
.Width();
2114 nWidth
+= HOR_DIST_BMP_STRING
;
2115 nWidth
+= nStringWidth
;
2121 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry
* pEntry
) const
2123 long nStringHeight
= GetItemSize( pEntry
, IcnViewFieldTypeText
).Height();
2126 switch( nWinBits
& (VIEWMODE_MASK
) )
2129 nHeight
= aImageSize
.Height();
2130 nHeight
+= VER_DIST_BMP_STRING
;
2131 nHeight
+= nStringHeight
;
2136 nHeight
= std::max( aImageSize
.Height(), nStringHeight
);
2139 if( nHeight
> nMaxBoundHeight
)
2141 ((SvxIconChoiceCtrl_Impl
*)this)->nMaxBoundHeight
= nHeight
;
2142 ((SvxIconChoiceCtrl_Impl
*)this)->aHorSBar
.SetLineSize( GetScrollBarLineSize() );
2143 ((SvxIconChoiceCtrl_Impl
*)this)->aVerSBar
.SetLineSize( GetScrollBarLineSize() );
2148 Size
SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry
* pEntry
) const
2150 return Size( CalcBoundingWidth( pEntry
),
2151 CalcBoundingHeight( pEntry
) );
2154 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2156 nMaxBoundHeight
= 0;
2157 pZOrderList
->clear();
2159 SvxIconChoiceCtrlEntry
* pEntry
;
2160 const size_t nCount
= aEntries
.size();
2162 if( !IsAutoArrange() || !pHead
)
2164 for( nCur
= 0; nCur
< nCount
; nCur
++ )
2166 pEntry
= aEntries
[ nCur
];
2167 if( IsBoundingRectValid( pEntry
->aRect
))
2169 Size
aBoundSize( pEntry
->aRect
.GetSize() );
2170 if( aBoundSize
.Height() > nMaxBoundHeight
)
2171 nMaxBoundHeight
= aBoundSize
.Height();
2174 FindBoundingRect( pEntry
);
2175 pZOrderList
->push_back( pEntry
);
2182 while( nCur
!= nCount
)
2184 DBG_ASSERT(pEntry
->pflink
&&pEntry
->pblink
,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2185 if( IsBoundingRectValid( pEntry
->aRect
))
2187 Size
aBoundSize( pEntry
->aRect
.GetSize() );
2188 if( aBoundSize
.Height() > nMaxBoundHeight
)
2189 nMaxBoundHeight
= aBoundSize
.Height();
2192 FindBoundingRect( pEntry
);
2193 pZOrderList
->push_back( pEntry
);
2194 pEntry
= pEntry
->pflink
;
2201 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry
* pEntry
)
2203 DBG_ASSERT(!pEntry
->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2204 if( pEntry
->IsPosLocked() && IsBoundingRectValid( pEntry
->aRect
) )
2206 AdjustVirtSize( pEntry
->aRect
);
2209 Size
aSize( CalcBoundingSize( pEntry
) );
2210 Point
aPos(pGridMap
->GetGridRect(pGridMap
->GetUnoccupiedGrid(sal_True
)).TopLeft());
2211 SetBoundingRect_Impl( pEntry
, aPos
, aSize
);
2214 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
2215 const Size
& /*rBoundingSize*/ )
2217 Rectangle
aGridRect( rPos
, Size(nGridDX
, nGridDY
) );
2218 pEntry
->aGridRect
= aGridRect
;
2220 AdjustVirtSize( pEntry
->aRect
);
2221 pGridMap
->OccupyGrids( pEntry
);
2225 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry
* pEntry
, sal_Bool bSyncSingleSelection
,
2226 sal_Bool bShowFocusAsync
)
2228 if( pEntry
== pCursor
)
2230 if( pCursor
&& eSelectionMode
== SINGLE_SELECTION
&& bSyncSingleSelection
&&
2231 !pCursor
->IsSelected() )
2232 SelectEntry( pCursor
, sal_True
, sal_True
);
2235 ShowCursor( sal_False
);
2236 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
2240 pOldCursor
->ClearFlags( ICNVIEW_FLAG_FOCUSED
);
2241 if( eSelectionMode
== SINGLE_SELECTION
&& bSyncSingleSelection
)
2242 SelectEntry( pOldCursor
, sal_False
, sal_True
); // deselect old cursor
2247 pCursor
->SetFlags( ICNVIEW_FLAG_FOCUSED
);
2248 if( eSelectionMode
== SINGLE_SELECTION
&& bSyncSingleSelection
)
2249 SelectEntry( pCursor
, sal_True
, sal_True
);
2250 if( !bShowFocusAsync
)
2251 ShowCursor( sal_True
);
2254 if( !nUserEventShowCursor
)
2255 nUserEventShowCursor
=
2256 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl
, UserEventHdl
),
2257 EVENTID_SHOW_CURSOR
);
2263 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow
)
2265 if( !pCursor
|| !bShow
|| !pView
->HasFocus() )
2270 Rectangle
aRect ( CalcFocusRect( pCursor
) );
2271 /*pView->*/ShowFocus( aRect
);
2275 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2283 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2287 Size
aSize( pDDDev
->GetOutputSizePixel() );
2289 pView
->DrawOutDev( aDDLastRectPos
, aSize
, Point(), aSize
, *pDDDev
);
2293 sal_Bool
SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent
& rCmd
)
2295 Rectangle
aDocRect( GetDocumentRect() );
2296 Rectangle
aVisRect( GetVisibleRect() );
2297 if( aVisRect
.IsInside( aDocRect
))
2299 Size
aDocSize( aDocRect
.GetSize() );
2300 Size
aVisSize( aVisRect
.GetSize() );
2301 sal_Bool bHor
= aDocSize
.Width() > aVisSize
.Width();
2302 sal_Bool bVer
= aDocSize
.Height() > aVisSize
.Height();
2304 long nScrollDX
= 0, nScrollDY
= 0;
2306 switch( rCmd
.GetCommand() )
2308 case COMMAND_STARTAUTOSCROLL
:
2310 pView
->EndTracking();
2311 sal_uInt16 nScrollFlags
= 0;
2313 nScrollFlags
|= AUTOSCROLL_HORZ
;
2315 nScrollFlags
|= AUTOSCROLL_VERT
;
2318 pView
->StartAutoScroll( nScrollFlags
);
2326 const CommandWheelData
* pData
= rCmd
.GetWheelData();
2327 if( pData
&& (COMMAND_WHEEL_SCROLL
== pData
->GetMode()) && !pData
->IsHorz() )
2329 sal_uLong nScrollLines
= pData
->GetScrollLines();
2330 if( nScrollLines
== COMMAND_WHEEL_PAGESCROLL
)
2332 nScrollDY
= GetScrollBarPageSize( aVisSize
.Width() );
2333 if( pData
->GetDelta() < 0 )
2338 nScrollDY
= pData
->GetNotchDelta() * (long)nScrollLines
;
2339 nScrollDY
*= GetScrollBarLineSize();
2345 case COMMAND_AUTOSCROLL
:
2347 const CommandScrollData
* pData
= rCmd
.GetAutoScrollData();
2350 nScrollDX
= pData
->GetDeltaX() * GetScrollBarLineSize();
2351 nScrollDY
= pData
->GetDeltaY() * GetScrollBarLineSize();
2357 if( nScrollDX
|| nScrollDY
)
2359 aVisRect
.Top() -= nScrollDY
;
2360 aVisRect
.Bottom() -= nScrollDY
;
2361 aVisRect
.Left() -= nScrollDX
;
2362 aVisRect
.Right() -= nScrollDX
;
2363 MakeVisible( aVisRect
);
2370 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent
& rCEvt
)
2372 // scroll mouse event?
2373 if( (rCEvt
.GetCommand() == COMMAND_WHEEL
) ||
2374 (rCEvt
.GetCommand() == COMMAND_STARTAUTOSCROLL
) ||
2375 (rCEvt
.GetCommand() == COMMAND_AUTOSCROLL
) )
2377 if( HandleScrollCommand( rCEvt
) )
2382 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry
* pEntry
)
2384 if( !pZOrderList
->empty()
2385 && pEntry
!= pZOrderList
->back()
2388 SvxIconChoiceCtrlEntryList_impl::iterator it
= pZOrderList
->begin();
2389 it
!= pZOrderList
->end();
2392 if ( *it
== pEntry
)
2394 pZOrderList
->erase( it
);
2395 pZOrderList
->push_back( pEntry
);
2402 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle
& rRect
) const
2404 if( rRect
.Bottom() >= aVirtOutputSize
.Height() )
2405 rRect
.Bottom() = aVirtOutputSize
.Height() - 1;
2406 if( rRect
.Right() >= aVirtOutputSize
.Width() )
2407 rRect
.Right() = aVirtOutputSize
.Width() - 1;
2408 if( rRect
.Top() < 0 )
2410 if( rRect
.Left() < 0 )
2414 // rRect: area of the document (in document coordinates) that we want to make
2416 // bScrBar == sal_True: rectangle was calculated because of a scrollbar event
2418 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle
& rRect
, sal_Bool bScrBar
,
2419 sal_Bool bCallRectChangedHdl
)
2421 Rectangle
aVirtRect( rRect
);
2422 ClipAtVirtOutRect( aVirtRect
);
2423 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
2424 // convert to document coordinate
2426 Rectangle
aOutputArea( GetOutputRect() );
2427 if( aOutputArea
.IsInside( aVirtRect
) )
2428 return; // is already visible
2431 if( aVirtRect
.Top() < aOutputArea
.Top() )
2433 // scroll up (nDy < 0)
2434 nDy
= aVirtRect
.Top() - aOutputArea
.Top();
2436 else if( aVirtRect
.Bottom() > aOutputArea
.Bottom() )
2438 // scroll down (nDy > 0)
2439 nDy
= aVirtRect
.Bottom() - aOutputArea
.Bottom();
2445 if( aVirtRect
.Left() < aOutputArea
.Left() )
2447 // scroll to the left (nDx < 0)
2448 nDx
= aVirtRect
.Left() - aOutputArea
.Left();
2450 else if( aVirtRect
.Right() > aOutputArea
.Right() )
2452 // scroll to the right (nDx > 0)
2453 nDx
= aVirtRect
.Right() - aOutputArea
.Right();
2460 aOutputArea
.SetPos( aOrigin
);
2461 if( GetUpdateMode() )
2465 ShowCursor( sal_False
);
2468 // invert origin for SV (so we can scroll/paint using document coordinates)
2470 SetOrigin( aOrigin
);
2472 sal_Bool bScrollable
= pView
->GetBackground().IsScrollable();
2473 if( pView
->HasBackground() && !bScrollable
)
2475 Rectangle
aRect( GetOutputRect());
2476 Wallpaper
aPaper( pView
->GetBackground() );
2477 aPaper
.SetRect( aRect
);
2478 pView
->SetBackground( aPaper
);
2481 if( bScrollable
&& GetUpdateMode() )
2483 // scroll in reverse direction!
2484 pView
->Control::Scroll( -nDx
, -nDy
, aOutputArea
,
2485 SCROLL_NOCHILDREN
| SCROLL_USECLIPREGION
| SCROLL_CLIP
);
2488 pView
->Invalidate(INVALIDATE_NOCHILDREN
);
2490 if( aHorSBar
.IsVisible() || aVerSBar
.IsVisible() )
2496 if(aHorSBar
.IsVisible() && aHorSBar
.GetThumbPos() != aOrigin
.X())
2497 aHorSBar
.SetThumbPos( aOrigin
.X() );
2498 if(aVerSBar
.IsVisible() && aVerSBar
.GetThumbPos() != aOrigin
.Y())
2499 aVerSBar
.SetThumbPos( aOrigin
.Y() );
2503 if( GetUpdateMode() )
2504 ShowCursor( sal_True
);
2506 // check if we still need scrollbars
2508 if( bScrollable
&& GetUpdateMode() )
2511 // If the requested area can not be made completely visible, the
2512 // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2513 // if only few pixels of the lower border are invisible, but a scrollbar has
2514 // a larger line size.
2515 if( bCallRectChangedHdl
|| GetOutputRect() != rRect
)
2519 sal_uLong
SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2521 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && pCurHighlightFrame
)
2523 return nSelectionCount
;
2526 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry
* pEntry
)
2529 if( pEntry
->IsSelected() )
2533 SelectEntry( pEntry
, bSel
, sal_True
, sal_True
);
2536 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry
* pThisEntryNot
,
2537 sal_Bool bPaintSync
)
2539 ClearSelectedRectList();
2541 // TODO: work through z-order list, if necessary!
2543 size_t nCount
= aEntries
.size();
2544 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2546 SvxIconChoiceCtrlEntry
* pEntry
= aEntries
[ nCur
];
2547 if( pEntry
!= pThisEntryNot
&& pEntry
->IsSelected() )
2548 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
, bPaintSync
);
2551 nFlags
&= (~F_ADD_MODE
);
2554 Size
SvxIconChoiceCtrl_Impl::GetMinGrid() const
2556 Size
aMinSize( aImageSize
);
2557 aMinSize
.Width() += 2 * LROFFS_BOUND
;
2558 aMinSize
.Height() += TBOFFS_BOUND
; // single offset is enough (FileDlg)
2559 String
aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
2560 Size
aTextSize( pView
->GetTextWidth( aStrDummy
), pView
->GetTextHeight() );
2561 if( nWinBits
& WB_ICON
)
2563 aMinSize
.Height() += VER_DIST_BMP_STRING
;
2564 aMinSize
.Height() += aTextSize
.Height();
2568 aMinSize
.Width() += HOR_DIST_BMP_STRING
;
2569 aMinSize
.Width() += aTextSize
.Width();
2574 void SvxIconChoiceCtrl_Impl::SetGrid( const Size
& rSize
)
2576 Size
aSize( rSize
);
2577 Size
aMinSize( GetMinGrid() );
2578 if( aSize
.Width() < aMinSize
.Width() )
2579 aSize
.Width() = aMinSize
.Width();
2580 if( aSize
.Height() < aMinSize
.Height() )
2581 aSize
.Height() = aMinSize
.Height();
2583 nGridDX
= aSize
.Width();
2584 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2585 // fly with a single column
2586 if( nWinBits
& WB_DETAILS
)
2588 const SvxIconChoiceCtrlColumnInfo
* pCol
= GetColumn( 0 );
2590 ((SvxIconChoiceCtrlColumnInfo
*)pCol
)->SetWidth( nGridDX
);
2592 nGridDY
= aSize
.Height();
2593 SetDefaultTextSize();
2596 // Calculates the maximum size that the text rectangle may use within its
2597 // bounding rectangle. In WB_ICON mode with IcnShowTextFull, Bottom is set to
2600 Rectangle
SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry
* pEntry
) const
2602 Rectangle aBoundRect
;
2603 // avoid infinite recursion: don't calculate the bounding rectangle here
2604 if( IsBoundingRectValid( pEntry
->aRect
) )
2605 aBoundRect
= pEntry
->aRect
;
2607 aBoundRect
= pEntry
->aGridRect
;
2609 Rectangle
aBmpRect( ((SvxIconChoiceCtrl_Impl
*)this)->CalcBmpRect(
2610 (SvxIconChoiceCtrlEntry
*)pEntry
) );
2611 if( nWinBits
& WB_ICON
)
2613 aBoundRect
.Top() = aBmpRect
.Bottom();
2614 aBoundRect
.Top() += VER_DIST_BMP_STRING
;
2615 if( aBoundRect
.Top() > aBoundRect
.Bottom())
2616 aBoundRect
.Top() = aBoundRect
.Bottom();
2617 aBoundRect
.Left() += LROFFS_BOUND
;
2618 aBoundRect
.Left()++;
2619 aBoundRect
.Right() -= LROFFS_BOUND
;
2620 aBoundRect
.Right()--;
2621 if( aBoundRect
.Left() > aBoundRect
.Right())
2622 aBoundRect
.Left() = aBoundRect
.Right();
2623 if( GetEntryTextModeSmart( pEntry
) == IcnShowTextFull
)
2624 aBoundRect
.Bottom() = LONG_MAX
;
2628 aBoundRect
.Left() = aBmpRect
.Right();
2629 aBoundRect
.Left() += HOR_DIST_BMP_STRING
;
2630 aBoundRect
.Right() -= LROFFS_BOUND
;
2631 if( aBoundRect
.Left() > aBoundRect
.Right() )
2632 aBoundRect
.Left() = aBoundRect
.Right();
2633 long nHeight
= aBoundRect
.GetSize().Height();
2634 nHeight
= nHeight
- aDefaultTextSize
.Height();
2636 aBoundRect
.Top() += nHeight
;
2637 aBoundRect
.Bottom() -= nHeight
;
2642 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2645 nDY
-= aImageSize
.Height();
2646 nDY
-= VER_DIST_BMP_STRING
;
2647 nDY
-= 2*TBOFFS_BOUND
;
2652 nDX
-= 2*LROFFS_BOUND
;
2657 long nHeight
= pView
->GetTextHeight();
2660 aDefaultTextSize
= Size( nDX
, nDY
);
2664 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry
* pEntry
) const
2666 pEntry
->aRect
= pEntry
->aGridRect
;
2667 Size
aSize( CalcBoundingSize( pEntry
) );
2668 if( nWinBits
& WB_ICON
)
2670 // center horizontally
2671 long nBorder
= pEntry
->aGridRect
.GetWidth() - aSize
.Width();
2672 pEntry
->aRect
.Left() += nBorder
/ 2;
2673 pEntry
->aRect
.Right() -= nBorder
/ 2;
2675 // center vertically
2676 pEntry
->aRect
.Bottom() = pEntry
->aRect
.Top() + aSize
.Height();
2680 // The deltas are the offsets by which the view is moved on the document.
2681 // left, up: offsets < 0
2682 // right, down: offsets > 0
2683 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX
, long nDeltaY
, sal_Bool bScrollBar
)
2685 const MapMode
& rMapMode
= pView
->GetMapMode();
2686 Point
aOrigin( rMapMode
.GetOrigin() );
2687 // convert to document coordinate
2689 aOrigin
.Y() += nDeltaY
;
2690 aOrigin
.X() += nDeltaX
;
2691 Rectangle
aRect( aOrigin
, aOutputSize
);
2692 MakeVisible( aRect
, bScrollBar
);
2696 const Size
& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry
*,
2697 IcnViewFieldType eItem
) const
2699 if( eItem
== IcnViewFieldTypeText
)
2700 return aDefaultTextSize
;
2704 Rectangle
SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry
* pEntry
)
2706 Rectangle
aTextRect( CalcTextRect( pEntry
) );
2707 Rectangle
aBoundRect( GetEntryBoundRect( pEntry
) );
2709 aBoundRect
.Left(), aBoundRect
.Top() - 1, aBoundRect
.Right() - 1,
2710 aTextRect
.Bottom() + 1);
2713 // the hot spot is the inner 50 % of the rectangle
2714 static Rectangle
GetHotSpot( const Rectangle
& rRect
)
2716 Rectangle
aResult( rRect
);
2718 Size
aSize( rRect
.GetSize() );
2719 long nDelta
= aSize
.Width() / 4;
2720 aResult
.Left() += nDelta
;
2721 aResult
.Right() -= nDelta
;
2722 nDelta
= aSize
.Height() / 4;
2723 aResult
.Top() += nDelta
;
2724 aResult
.Bottom() -= nDelta
;
2728 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry
* pEntry1
, SvxIconChoiceCtrlEntry
* pEntry2
,
2729 sal_Bool bAdd
, std::vector
<Rectangle
*>* pOtherRects
)
2731 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2732 Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2733 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2734 SelectRect( aRect
, bAdd
, pOtherRects
);
2737 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle
& rRect
, bool bAdd
,
2738 std::vector
<Rectangle
*>* pOtherRects
)
2740 aCurSelectionRect
= rRect
;
2741 if( !pZOrderList
|| !pZOrderList
->size() )
2744 // set flag, so ToTop won't be called in Select
2745 sal_Bool bAlreadySelectingRect
= nFlags
& F_SELECTING_RECT
? sal_True
: sal_False
;
2746 nFlags
|= F_SELECTING_RECT
;
2748 CheckBoundingRects();
2750 const size_t nCount
= pZOrderList
->size();
2752 Rectangle
aRect( rRect
);
2754 bool bCalcOverlap
= (bAdd
&& pOtherRects
&& !pOtherRects
->empty()) ? true : false;
2756 sal_Bool bResetClipRegion
= sal_False
;
2757 if( !pView
->IsClipRegion() )
2759 bResetClipRegion
= sal_True
;
2760 pView
->SetClipRegion(Region(GetOutputRect()));
2763 for( size_t nPos
= 0; nPos
< nCount
; nPos
++ )
2765 SvxIconChoiceCtrlEntry
* pEntry
= (*pZOrderList
)[ nPos
];
2767 if( !IsBoundingRectValid( pEntry
->aRect
))
2768 FindBoundingRect( pEntry
);
2769 Rectangle
aBoundRect( GetHotSpot( pEntry
->aRect
) );
2770 sal_Bool bSelected
= pEntry
->IsSelected();
2774 bOverlaps
= IsOver( pOtherRects
, aBoundRect
);
2776 bOverlaps
= sal_False
;
2777 sal_Bool bOver
= aRect
.IsOver( aBoundRect
);
2779 if( bOver
&& !bOverlaps
)
2781 // is inside the new selection rectangle and outside of any old one
2784 SelectEntry( pEntry
, sal_True
, sal_True
, sal_True
);
2788 // is outside of the selection rectangle
2791 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
);
2793 else if( bAdd
&& bOverlaps
)
2795 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2796 // selection rectangle.
2798 // There is still a bug here! The selection status of an entry in a
2799 // previous rectangle has to be restored, if it was touched by the
2800 // current selection rectangle but is not inside it any more.
2801 // For simplicity's sake, let's assume that all entries in the old
2802 // rectangles were correctly selected. It is wrong to just deselect
2803 // the intersection.
2804 // Possible solution: remember a snapshot of the selection before
2805 // spanning the rectangle.
2806 if( aBoundRect
.IsOver( rRect
))
2808 // deselect intersection between old rectangles and current rectangle
2810 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
);
2814 // select entry of an old rectangle
2816 SelectEntry( pEntry
, sal_True
, sal_True
, sal_True
);
2819 else if( !bOver
&& bSelected
)
2821 // this entry is completely outside the rectangle => deselect it
2822 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
);
2826 if( !bAlreadySelectingRect
)
2827 nFlags
&= ~F_SELECTING_RECT
;
2830 if( bResetClipRegion
)
2831 pView
->SetClipRegion();
2834 void SvxIconChoiceCtrl_Impl::SelectRange(
2835 SvxIconChoiceCtrlEntry
* pStart
,
2836 SvxIconChoiceCtrlEntry
* pEnd
,
2839 sal_uLong nFront
= GetEntryListPos( pStart
);
2840 sal_uLong nBack
= GetEntryListPos( pEnd
);
2841 sal_uLong nFirst
= std::min( nFront
, nBack
);
2842 sal_uLong nLast
= std::max( nFront
, nBack
);
2844 SvxIconChoiceCtrlEntry
* pEntry
;
2848 // deselect everything before the first entry if not in
2850 for ( i
=0; i
<nFirst
; i
++ )
2852 pEntry
= GetEntry( i
);
2853 if( pEntry
->IsSelected() )
2854 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
, sal_True
);
2858 // select everything between nFirst and nLast
2859 for ( i
=nFirst
; i
<=nLast
; i
++ )
2861 pEntry
= GetEntry( i
);
2862 if( ! pEntry
->IsSelected() )
2863 SelectEntry( pEntry
, sal_True
, sal_True
, sal_True
, sal_True
);
2868 // deselect everything behind the last entry if not in
2870 sal_uLong nEnd
= GetEntryCount();
2871 for ( ; i
<nEnd
; i
++ )
2873 pEntry
= GetEntry( i
);
2874 if( pEntry
->IsSelected() )
2875 SelectEntry( pEntry
, sal_False
, sal_True
, sal_True
, sal_True
);
2880 bool SvxIconChoiceCtrl_Impl::IsOver( std::vector
<Rectangle
*>* pRectList
, const Rectangle
& rBoundRect
) const
2882 const sal_uInt16 nCount
= pRectList
->size();
2883 for( sal_uInt16 nCur
= 0; nCur
< nCount
; nCur
++ )
2885 Rectangle
* pRect
= (*pRectList
)[ nCur
];
2886 if( rBoundRect
.IsOver( *pRect
))
2892 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry
* pEntry1
,
2893 SvxIconChoiceCtrlEntry
* pEntry2
)
2895 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2896 Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2897 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2898 AddSelectedRect( aRect
);
2901 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle
& rRect
)
2903 Rectangle
* pRect
= new Rectangle( rRect
);
2905 aSelectedRectList
.push_back( pRect
);
2908 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2910 const sal_uInt16 nCount
= aSelectedRectList
.size();
2911 for( sal_uInt16 nCur
= 0; nCur
< nCount
; nCur
++ )
2913 Rectangle
* pRect
= aSelectedRectList
[ nCur
];
2916 aSelectedRectList
.clear();
2919 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, AutoArrangeHdl
)
2921 aAutoArrangeTimer
.Stop();
2922 Arrange( IsAutoArrange() );
2926 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, VisRectChangedHdl
)
2928 aVisRectChangedTimer
.Stop();
2929 pView
->VisibleRectChanged();
2933 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, DocRectChangedHdl
)
2935 aDocRectChangedTimer
.Stop();
2936 pView
->DocumentRectChanged();
2940 sal_Bool
SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rDocPos
)
2942 Rectangle
aRect( CalcTextRect( pEntry
));
2943 if( aRect
.IsInside( rDocPos
) )
2948 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, EditTimeoutHdl
)
2950 SvxIconChoiceCtrlEntry
* pEntry
= GetCurEntry();
2951 if( bEntryEditingEnabled
&& pEntry
&&
2952 pEntry
->IsSelected())
2954 if( pView
->EditingEntry( pEntry
))
2955 EditEntry( pEntry
);
2962 // Function to align entries to the grid
2965 // pStart == 0: align all entries
2966 // else: align all entries of the row from pStart on (including pStart)
2967 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry
* pStart
)
2969 IconChoiceMap aLists
;
2970 pImpCursor
->CreateGridAjustData( aLists
, pStart
);
2971 for (IconChoiceMap::const_iterator iter
= aLists
.begin();
2972 iter
!= aLists
.end(); ++iter
)
2974 AdjustAtGrid(iter
->second
, pStart
);
2976 IcnCursor_Impl::DestroyGridAdjustData( aLists
);
2980 // align a row, might expand width, doesn't break the line
2981 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvxIconChoiceCtrlEntryPtrVec
& rRow
, SvxIconChoiceCtrlEntry
* pStart
)
2993 for( sal_uInt16 nCur
= 0; nCur
< rRow
.size(); nCur
++ )
2995 SvxIconChoiceCtrlEntry
* pCur
= rRow
[ nCur
];
2996 if( !bGo
&& pCur
== pStart
)
2999 // SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3000 // Decisive (for our eye) is the bitmap, else, the entry might jump too
3001 // much within long texts.
3002 const Rectangle
& rBoundRect
= GetEntryBoundRect( pCur
);
3003 Rectangle
aCenterRect( CalcBmpRect( pCur
, 0 ));
3004 if( bGo
&& !pCur
->IsPosLocked() )
3006 long nWidth
= aCenterRect
.GetSize().Width();
3007 Point
aNewPos( AdjustAtGrid( aCenterRect
, rBoundRect
) );
3008 while( aNewPos
.X() < nCurRight
)
3009 aNewPos
.X() += nGridDX
;
3010 if( aNewPos
!= rBoundRect
.TopLeft() )
3012 SetEntryPos( pCur
, aNewPos
);
3013 pCur
->SetFlags( ICNVIEW_FLAG_POS_MOVED
);
3014 nFlags
|= F_MOVED_ENTRIES
;
3016 nCurRight
= aNewPos
.X() + nWidth
;
3020 nCurRight
= rBoundRect
.Right();
3025 // Aligns a rectangle to the grid, but doesn't guarantee that the new position
3026 // is vacant. The position can be used for SetEntryPos. The CenterRect describes
3027 // a part of the bounding rectangle that is used for calculating the target
3029 Point
SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle
& rCenterRect
,
3030 const Rectangle
& rBoundRect
) const
3032 Point
aPos( rCenterRect
.TopLeft() );
3033 Size
aSize( rCenterRect
.GetSize() );
3035 aPos
.X() -= LROFFS_WINBORDER
;
3036 aPos
.Y() -= TBOFFS_WINBORDER
;
3038 // align (the center of the rectangle is the reference)
3039 short nGridX
= (short)((aPos
.X()+(aSize
.Width()/2)) / nGridDX
);
3040 short nGridY
= (short)((aPos
.Y()+(aSize
.Height()/2)) / nGridDY
);
3041 aPos
.X() = nGridX
* nGridDX
;
3042 aPos
.Y() = nGridY
* nGridDY
;
3043 // horizontal center
3044 aPos
.X() += (nGridDX
- rBoundRect
.GetSize().Width() ) / 2;
3046 aPos
.X() += LROFFS_WINBORDER
;
3047 aPos
.Y() += TBOFFS_WINBORDER
;
3052 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode
, SvxIconChoiceCtrlEntry
* pEntry
)
3056 if( eTextMode
!= eMode
)
3058 if( eTextMode
== IcnShowTextDontKnow
)
3059 eTextMode
= IcnShowTextShort
;
3061 Arrange( sal_True
);
3066 if( pEntry
->eTextMode
!= eMode
)
3068 pEntry
->eTextMode
= eMode
;
3069 InvalidateEntry( pEntry
);
3070 pView
->Invalidate( GetEntryBoundRect( pEntry
) );
3071 AdjustVirtSize( pEntry
->aRect
);
3076 SvxIconChoiceCtrlTextMode
SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry
* pEntry
) const
3078 DBG_ASSERT(pEntry
,"GetEntryTextModeSmart: Entry not set");
3079 SvxIconChoiceCtrlTextMode eMode
= pEntry
->GetTextMode();
3080 if( eMode
== IcnShowTextDontKnow
)
3085 ////////////////////////////////////////////////////////////////////////////////////////////////
3087 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3088 // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
3089 // a gray focusrect on a gray background !!!
3091 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle
& rRect
)
3093 Color
aBkgColor ( pView
->GetBackground().GetColor() );
3095 sal_uInt16 nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
3097 aPenColor
.SetColor ( COL_BLACK
);
3099 aPenColor
.SetColor( COL_WHITE
);
3101 aFocus
.bOn
= sal_True
;
3102 aFocus
.aPenColor
= aPenColor
;
3103 aFocus
.aRect
= rRect
;
3106 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice
* pOut
)
3108 pOut
->SetLineColor( aFocus
.aPenColor
);
3109 pOut
->SetFillColor();
3110 Polygon
aPolygon ( aFocus
.aRect
);
3112 LineInfo
aLineInfo ( LINE_DASH
);
3114 aLineInfo
.SetDashLen ( 1 );
3116 aLineInfo
.SetDotLen ( 1L );
3117 aLineInfo
.SetDistance ( 1L );
3118 aLineInfo
.SetDotCount ( 1 );
3120 pOut
->DrawPolyLine ( aPolygon
, aLineInfo
);
3123 sal_Bool
SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar
, sal_uLong
& rPos
) const
3125 sal_Bool bRet
= sal_False
;
3126 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
3127 size_t nEntryCount
= GetEntryCount();
3128 for ( size_t i
= 0; i
< nEntryCount
; ++i
)
3130 if ( rI18nHelper
.MatchMnemonic( GetEntry( i
)->GetText(), cChar
) )
3142 ////////////////////////////////////////////////////////////////////////////////////////////////
3144 IMPL_LINK(SvxIconChoiceCtrl_Impl
, UserEventHdl
, void*, nId
)
3146 if( nId
== EVENTID_ADJUST_SCROLLBARS
)
3148 nUserEventAdjustScrBars
= 0;
3151 else if( nId
== EVENTID_SHOW_CURSOR
)
3153 nUserEventShowCursor
= 0;
3154 ShowCursor( sal_True
);
3159 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3161 if( nUserEventAdjustScrBars
)
3163 Application::RemoveUserEvent( nUserEventAdjustScrBars
);
3164 nUserEventAdjustScrBars
= 0;
3166 if( nUserEventShowCursor
)
3168 Application::RemoveUserEvent( nUserEventShowCursor
);
3169 nUserEventShowCursor
= 0;
3173 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry
* pEntry
)
3175 if( pEntry
== pCursor
)
3176 ShowCursor( sal_False
);
3177 pView
->Invalidate( pEntry
->aRect
);
3179 pView
->Invalidate( pEntry
->aRect
);
3180 if( pEntry
== pCursor
)
3181 ShowCursor( sal_True
);
3184 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry
* pEntry
)
3186 DBG_ASSERT(pEntry
,"EditEntry: Entry not set");
3190 StopEntryEditing( sal_True
);
3194 pCurEditedEntry
= pEntry
;
3195 String
aEntryText( pView
->GetEntryText( pEntry
, sal_True
) );
3196 Rectangle
aRect( CalcTextRect( pEntry
, 0, sal_True
, &aEntryText
) );
3197 MakeVisible( aRect
);
3198 Point
aPos( aRect
.TopLeft() );
3199 aPos
= pView
->GetPixelPos( aPos
);
3200 aRect
.SetPos( aPos
);
3202 pEdit
= new IcnViewEdit_Impl(
3207 LINK( this, SvxIconChoiceCtrl_Impl
, TextEditEndedHdl
) );
3210 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, TextEditEndedHdl
)
3212 DBG_ASSERT(pEdit
,"TextEditEnded: pEdit not set");
3215 pCurEditedEntry
= 0;
3218 DBG_ASSERT(pCurEditedEntry
,"TextEditEnded: pCurEditedEntry not set");
3220 if( !pCurEditedEntry
)
3223 if( pEdit
->IsGrabFocus() )
3229 if ( !pEdit
->EditingCanceled() )
3230 aText
= pEdit
->GetText();
3232 aText
= pEdit
->GetSavedValue();
3234 if( pView
->EditedEntry( pCurEditedEntry
, aText
, pEdit
->EditingCanceled() ) )
3235 InvalidateEntry( pCurEditedEntry
);
3236 if( !GetSelectionCount() )
3237 SelectEntry( pCurEditedEntry
, sal_True
);
3240 if( pEdit
->IsGrabFocus() )
3242 // The edit can not be deleted here, because it is not within a handler. It
3243 // will be deleted in the dtor or in the next EditEntry.
3244 pCurEditedEntry
= 0;
3248 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel
)
3251 pEdit
->StopEditing( bCancel
);
3254 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong
& rPos
) const
3256 if( !GetSelectionCount() )
3259 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && (eSelectionMode
== NO_SELECTION
) )
3261 rPos
= pView
->GetEntryListPos( pCurHighlightFrame
);
3262 return pCurHighlightFrame
;
3265 size_t nCount
= aEntries
.size();
3268 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
3270 SvxIconChoiceCtrlEntry
* pEntry
= aEntries
[ nCur
];
3271 if( pEntry
->IsSelected() )
3280 SvxIconChoiceCtrlEntry
* pEntry
= pHead
;
3283 if( pEntry
->IsSelected() )
3285 rPos
= GetEntryListPos( pEntry
);
3288 pEntry
= pEntry
->pflink
;
3289 if( nCount
&& pEntry
== pHead
)
3291 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
3299 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect
, sal_Bool bPaint
)
3303 size_t nCount
= aEntries
.size();
3304 for( size_t nCur
= 0; nCur
< nCount
&& (bSelect
|| GetSelectionCount() ); nCur
++ )
3306 SvxIconChoiceCtrlEntry
* pEntry
= aEntries
[ nCur
];
3307 SelectEntry( pEntry
, bSelect
, sal_True
, sal_True
, bPaint
);
3309 nFlags
&= (~F_ADD_MODE
);
3313 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl
* pParent
, const Point
& rPos
,
3314 const Size
& rSize
, const XubString
& rData
, const Link
& rNotifyEditEnd
) :
3315 MultiLineEdit( pParent
, (pParent
->GetStyle() & WB_ICON
) ? WB_CENTER
: WB_LEFT
),
3316 aCallBackHdl( rNotifyEditEnd
),
3317 bCanceled( sal_False
),
3318 bAlreadyInCallback( sal_False
),
3319 bGrabFocus( sal_False
)
3321 Font
aFont( pParent
->GetPointFont() );
3322 aFont
.SetTransparent( sal_False
);
3323 SetControlFont( aFont
);
3324 if( !pParent
->HasFontFillColor() )
3326 Color
aColor( pParent
->GetBackground().GetColor() );
3327 SetControlBackground( aColor
);
3330 SetControlBackground( aFont
.GetFillColor() );
3331 SetControlForeground( aFont
.GetColor() );
3332 SetPosPixel( rPos
);
3333 SetSizePixel( CalcAdjustedSize(rSize
) );
3337 aAccReturn
.InsertItem( IMPICNVIEW_ACC_RETURN
, KeyCode(KEY_RETURN
) );
3338 aAccEscape
.InsertItem( IMPICNVIEW_ACC_ESCAPE
, KeyCode(KEY_ESCAPE
) );
3340 aAccReturn
.SetActivateHdl( LINK( this, IcnViewEdit_Impl
, ReturnHdl_Impl
) );
3341 aAccEscape
.SetActivateHdl( LINK( this, IcnViewEdit_Impl
, EscapeHdl_Impl
) );
3342 GetpApp()->InsertAccel( &aAccReturn
);//, ACCEL_ALWAYS );
3343 GetpApp()->InsertAccel( &aAccEscape
);//, ACCEL_ALWAYS );
3348 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3350 if( !bAlreadyInCallback
)
3352 GetpApp()->RemoveAccel( &aAccReturn
);
3353 GetpApp()->RemoveAccel( &aAccEscape
);
3357 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3360 if ( !bAlreadyInCallback
)
3362 bAlreadyInCallback
= sal_True
;
3363 GetpApp()->RemoveAccel( &aAccReturn
);
3364 GetpApp()->RemoveAccel( &aAccEscape
);
3366 aCallBackHdl
.Call( this );
3370 IMPL_LINK_NOARG(IcnViewEdit_Impl
, Timeout_Impl
)
3372 CallCallBackHdl_Impl();
3376 IMPL_LINK( IcnViewEdit_Impl
, ReturnHdl_Impl
, Accelerator
*, EMPTYARG
)
3378 bCanceled
= sal_False
;
3379 bGrabFocus
= sal_True
;
3380 CallCallBackHdl_Impl();
3384 IMPL_LINK( IcnViewEdit_Impl
, EscapeHdl_Impl
, Accelerator
*, EMPTYARG
)
3386 bCanceled
= sal_True
;
3387 bGrabFocus
= sal_True
;
3388 CallCallBackHdl_Impl();
3392 void IcnViewEdit_Impl::KeyInput( const KeyEvent
& rKEvt
)
3394 KeyCode aCode
= rKEvt
.GetKeyCode();
3395 sal_uInt16 nCode
= aCode
.GetCode();
3400 bCanceled
= sal_True
;
3401 bGrabFocus
= sal_True
;
3402 CallCallBackHdl_Impl();
3406 bCanceled
= sal_False
;
3407 bGrabFocus
= sal_True
;
3408 CallCallBackHdl_Impl();
3412 MultiLineEdit::KeyInput( rKEvt
);
3416 long IcnViewEdit_Impl::PreNotify( NotifyEvent
& rNEvt
)
3418 if( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
3420 if ( !bAlreadyInCallback
&&
3421 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
3423 bCanceled
= sal_False
;
3424 aTimer
.SetTimeout(10);
3425 aTimer
.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl
,Timeout_Impl
));
3432 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel
)
3434 if ( !bAlreadyInCallback
)
3436 bCanceled
= bCancel
;
3437 CallCallBackHdl_Impl();
3441 sal_uLong
SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry
* pEntry
) const
3443 if( !(nFlags
& F_ENTRYLISTPOS_VALID
))
3444 ((SvxIconChoiceCtrl_Impl
*)this)->SetListPositions();
3445 return pEntry
->nPos
;
3448 void SvxIconChoiceCtrl_Impl::InitSettings()
3450 const StyleSettings
& rStyleSettings
= pView
->GetSettings().GetStyleSettings();
3452 if( !pView
->HasFont() )
3454 // unit (from settings) is Point
3455 Font
aFont( rStyleSettings
.GetFieldFont() );
3456 //const Font& rFont = pView->GetFont();
3457 //if( pView->HasFontTextColor() )
3458 aFont
.SetColor( rStyleSettings
.GetWindowTextColor() );
3459 //if( pView->HasFontFillColor() )
3460 //aFont.SetFillColor( rFont.GetFillColor() );
3461 pView
->SetPointFont( aFont
);
3462 SetDefaultTextSize();
3465 //if( !pView->HasFontTextColor() )
3466 pView
->SetTextColor( rStyleSettings
.GetFieldTextColor() );
3467 //if( !pView->HasFontFillColor() )
3468 pView
->SetTextFillColor();
3470 //if( !pView->HasBackground() )
3471 pView
->SetBackground( rStyleSettings
.GetFieldColor());
3473 long nScrBarSize
= rStyleSettings
.GetScrollBarSize();
3474 if( nScrBarSize
!= nHorSBarHeight
|| nScrBarSize
!= nVerSBarWidth
)
3476 nHorSBarHeight
= nScrBarSize
;
3477 Size
aSize( aHorSBar
.GetSizePixel() );
3478 aSize
.Height() = nScrBarSize
;
3480 aHorSBar
.SetSizePixel( aSize
);
3482 nVerSBarWidth
= nScrBarSize
;
3483 aSize
= aVerSBar
.GetSizePixel();
3484 aSize
.Width() = nScrBarSize
;
3486 aVerSBar
.SetSizePixel( aSize
);
3488 Size
aOSize( pView
->Control::GetOutputSizePixel() );
3489 PositionScrollBars( aOSize
.Width(), aOSize
.Height() );
3494 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl
* pOwner
) :
3500 EntryList_Impl::~EntryList_Impl()
3505 void EntryList_Impl::clear()
3508 maIconChoiceCtrlEntryList
.clear();
3511 void EntryList_Impl::insert( size_t nPos
, SvxIconChoiceCtrlEntry
* pEntry
)
3513 if ( nPos
< maIconChoiceCtrlEntryList
.size() ) {
3514 maIconChoiceCtrlEntryList
.insert( maIconChoiceCtrlEntryList
.begin() + nPos
, pEntry
);
3516 maIconChoiceCtrlEntryList
.push_back( pEntry
);
3518 if( _pOwner
->pHead
)
3519 pEntry
->SetBacklink( _pOwner
->pHead
->pblink
);
3522 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode
)
3524 if( eMode
== ePositionMode
)
3527 SvxIconChoiceCtrlPositionMode eOldMode
= ePositionMode
;
3528 ePositionMode
= eMode
;
3529 size_t nCount
= aEntries
.size();
3531 if( eOldMode
== IcnViewPositionModeAutoArrange
)
3533 // when positioning moved entries "hard", there are problems with
3534 // unwanted overlaps, as these entries aren't taken into account in
3536 if( aEntries
.size() )
3537 aAutoArrangeTimer
.Start();
3541 if( ePositionMode
== IcnViewPositionModeAutoArrange
)
3543 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
3545 SvxIconChoiceCtrlEntry
* pEntry
= aEntries
[ nCur
];
3546 if( pEntry
->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED
| ICNVIEW_FLAG_POS_MOVED
))
3547 SetEntryPos(pEntry
, GetEntryBoundRect( pEntry
).TopLeft());
3550 if( aEntries
.size() )
3551 aAutoArrangeTimer
.Start();
3553 else if( ePositionMode
== IcnViewPositionModeAutoAdjust
)
3555 AdjustEntryAtGrid( 0 );
3559 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
3560 SvxIconChoiceCtrlEntry
* pPredecessor
)
3562 if( !IsAutoArrange() )
3565 if( pEntry
== pPredecessor
)
3568 sal_uLong nPos1
= GetEntryListPos( pEntry
);
3573 sal_uLong nPos2
= GetEntryListPos( pPredecessor
);
3574 if( nPos1
== (nPos2
+ 1) )
3575 return; // is already the predecessor
3584 if( !pPredecessor
&& pHead
== pEntry
)
3585 return; // is already the first one
3587 sal_Bool bSetHead
= sal_False
;
3590 bSetHead
= sal_True
;
3591 pPredecessor
= pHead
->pblink
;
3593 if( pEntry
== pHead
)
3595 pHead
= pHead
->pflink
;
3596 bSetHead
= sal_False
;
3598 if( pEntry
!= pPredecessor
)
3601 pEntry
->SetBacklink( pPredecessor
);
3605 pEntry
->SetFlags( ICNVIEW_FLAG_PRED_SET
);
3606 aAutoArrangeTimer
.Start();
3609 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
3610 const Point
& rPosTopLeft
)
3612 Point
aPos( rPosTopLeft
); //TopLeft
3613 Rectangle
aCenterRect( CalcBmpRect( pEntry
, &aPos
));
3614 Point
aNewPos( aCenterRect
.Center() );
3615 sal_uLong nGrid
= GetPredecessorGrid( aNewPos
);
3616 size_t nCount
= aEntries
.size();
3617 if( nGrid
== ULONG_MAX
)
3619 if( nGrid
>= nCount
)
3622 return aEntries
[ nGrid
];
3624 SvxIconChoiceCtrlEntry
* pCur
= pHead
; // Grid 0
3625 // TODO: go through list from the end if nGrid > nCount/2
3626 for( sal_uLong nCur
= 0; nCur
< nGrid
; nCur
++ )
3627 pCur
= pCur
->pflink
;
3632 sal_uLong
SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point
& rPos
) const
3635 aPos
.X() -= LROFFS_WINBORDER
;
3636 aPos
.Y() -= TBOFFS_WINBORDER
;
3637 sal_uInt16 nMaxCol
= (sal_uInt16
)(aVirtOutputSize
.Width() / nGridDX
);
3640 sal_uInt16 nGridX
= (sal_uInt16
)(aPos
.X() / nGridDX
);
3641 if( nGridX
> nMaxCol
)
3643 sal_uInt16 nGridY
= (sal_uInt16
)(aPos
.Y() / nGridDY
);
3644 sal_uInt16 nGridsX
= (sal_uInt16
)(aOutputSize
.Width() / nGridDX
);
3645 sal_uLong nGrid
= (nGridY
* nGridsX
) + nGridX
;
3646 long nMiddle
= (nGridX
* nGridDX
) + (nGridDX
/ 2);
3647 if( rPos
.X() < nMiddle
)
3657 sal_Bool
SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent
& rHEvt
)
3659 if ( !(rHEvt
.GetMode() & HELPMODE_QUICK
) )
3662 Point
aPos( pView
->ScreenToOutputPixel(rHEvt
.GetMousePosPixel() ) );
3663 aPos
-= pView
->GetMapMode().GetOrigin();
3664 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aPos
, sal_True
);
3669 String sQuickHelpText
= pEntry
->GetQuickHelpText();
3670 String
aEntryText( pView
->GetEntryText( pEntry
, sal_False
) );
3671 Rectangle
aTextRect( CalcTextRect( pEntry
, 0, sal_False
, &aEntryText
) );
3672 if ( ( !aTextRect
.IsInside( aPos
) || !aEntryText
.Len() ) && !sQuickHelpText
.Len() )
3675 Rectangle
aOptTextRect( aTextRect
);
3676 aOptTextRect
.Bottom() = LONG_MAX
;
3677 sal_uInt16 nNewFlags
= nCurTextDrawFlags
;
3678 nNewFlags
&= ~( TEXT_DRAW_CLIP
| TEXT_DRAW_ENDELLIPSIS
);
3679 aOptTextRect
= pView
->GetTextRect( aOptTextRect
, aEntryText
, nNewFlags
);
3680 if ( aOptTextRect
!= aTextRect
|| sQuickHelpText
.Len() > 0 )
3682 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
3683 Point
aPt( aOptTextRect
.TopLeft() );
3684 aPt
+= pView
->GetMapMode().GetOrigin();
3685 aPt
= pView
->OutputToScreenPixel( aPt
);
3686 // subtract border of tooltip help
3689 aOptTextRect
.SetPos( aPt
);
3691 if ( sQuickHelpText
.Len() > 0 )
3692 sHelpText
= sQuickHelpText
;
3694 sHelpText
= aEntryText
;
3695 Help::ShowQuickHelp( (Window
*)pView
, aOptTextRect
, sHelpText
, QUICKHELP_LEFT
| QUICKHELP_VCENTER
);
3701 void SvxIconChoiceCtrl_Impl::ClearColumnList()
3710 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex
, const SvxIconChoiceCtrlColumnInfo
& rInfo
)
3713 pColumns
= new SvxIconChoiceCtrlColumnInfoMap
;
3715 SvxIconChoiceCtrlColumnInfo
* pInfo
= new SvxIconChoiceCtrlColumnInfo( rInfo
);
3716 pColumns
->insert( nIndex
, pInfo
);
3718 // HACK: Detail mode is not yet fully implemented, this workaround makes it
3719 // fly with a single column
3720 if( !nIndex
&& (nWinBits
& WB_DETAILS
) )
3721 nGridDX
= pInfo
->GetWidth();
3723 if( GetUpdateMode() )
3724 Arrange( IsAutoArrange() );
3727 const SvxIconChoiceCtrlColumnInfo
* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex
) const
3731 SvxIconChoiceCtrlColumnInfoMap::const_iterator it
= pColumns
->find( nIndex
);
3732 if( it
== pColumns
->end() )
3737 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
3738 OutputDevice
* pOut
, const Rectangle
& rBmpRect
, sal_Bool bHide
)
3740 Rectangle
aBmpRect( rBmpRect
);
3742 if( aImageSize
.Width() < 32 )
3744 aBmpRect
.Right() += nBorder
;
3745 aBmpRect
.Left() -= nBorder
;
3746 aBmpRect
.Bottom() += nBorder
;
3747 aBmpRect
.Top() -= nBorder
;
3750 pView
->Invalidate( aBmpRect
);
3753 DecorationView
aDecoView( pOut
);
3754 sal_uInt16 nDecoFlags
;
3755 if ( bHighlightFramePressed
)
3756 nDecoFlags
= FRAME_HIGHLIGHT_TESTBACKGROUND
| FRAME_HIGHLIGHT_IN
;
3758 nDecoFlags
= FRAME_HIGHLIGHT_TESTBACKGROUND
| FRAME_HIGHLIGHT_OUT
;
3759 aDecoView
.DrawHighlightFrame( aBmpRect
, nDecoFlags
);
3763 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry
* pEntry
,
3764 sal_Bool bKeepHighlightFlags
)
3766 if( pEntry
== pCurHighlightFrame
)
3769 if( !bKeepHighlightFlags
)
3770 bHighlightFramePressed
= sal_False
;
3772 HideEntryHighlightFrame();
3773 pCurHighlightFrame
= pEntry
;
3776 Rectangle
aBmpRect( CalcFocusRect(pEntry
) );
3777 DrawHighlightFrame( pView
, aBmpRect
, sal_False
);
3781 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
3783 if( !pCurHighlightFrame
)
3786 SvxIconChoiceCtrlEntry
* pEntry
= pCurHighlightFrame
;
3787 pCurHighlightFrame
= 0;
3788 Rectangle
aBmpRect( CalcFocusRect(pEntry
) );
3789 DrawHighlightFrame( pView
, aBmpRect
, sal_True
);
3792 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry
* )
3794 // When single-click mode is active, the selection handler should be called
3795 // synchronously, as the selection is automatically taken away once the
3796 // mouse cursor doesn't touch the object any more. Else, we might run into
3797 // missing calls to Select if the object is selected from a mouse movement,
3798 // because when starting the timer, the mouse cursor might have already left
3800 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
3801 // WB_NOASYNCSELECTHDL.
3802 if( nWinBits
& (WB_NOASYNCSELECTHDL
| WB_HIGHLIGHTFRAME
) )
3809 aCallSelectHdlTimer
.Start();
3812 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, CallSelectHdlHdl
)
3820 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point
& rPos
, sal_Bool bDoNotUpdateWallpaper
)
3822 MapMode
aMapMode( pView
->GetMapMode() );
3823 aMapMode
.SetOrigin( rPos
);
3824 pView
->SetMapMode( aMapMode
);
3825 if( !bDoNotUpdateWallpaper
)
3827 sal_Bool bScrollable
= pView
->GetBackground().IsScrollable();
3828 if( pView
->HasBackground() && !bScrollable
)
3830 Rectangle
aRect( GetOutputRect());
3831 Wallpaper
aPaper( pView
->GetBackground() );
3832 aPaper
.SetRect( aRect
);
3833 pView
->SetBackground( aPaper
);
3838 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent
, void* pData
)
3840 pView
->CallImplEventListeners( nEvent
, pData
);
3844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */