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 <osl/diagnose.h>
23 #include <tools/debug.hxx>
24 #include <vcl/wall.hxx>
25 #include <vcl/help.hxx>
26 #include <vcl/decoview.hxx>
27 #include <vcl/svapp.hxx>
28 #include <tools/poly.hxx>
29 #include <vcl/lineinfo.hxx>
30 #include <vcl/i18nhelp.hxx>
31 #include <vcl/mnemonic.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/commandevent.hxx>
35 #include <vcl/ivctrl.hxx>
36 #include "imivctl.hxx"
40 #include <vcl/idle.hxx>
42 static constexpr auto DRAWTEXT_FLAGS_ICON
=
43 DrawTextFlags::Center
| DrawTextFlags::Top
| DrawTextFlags::EndEllipsis
|
44 DrawTextFlags::Clip
| DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
| DrawTextFlags::Mnemonic
;
46 #define DRAWTEXT_FLAGS_SMALLICON (DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags::Clip)
48 #define EVENTID_SHOW_CURSOR (reinterpret_cast<void*>(1))
49 #define EVENTID_ADJUST_SCROLLBARS (reinterpret_cast<void*>(2))
51 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
52 SvtIconChoiceCtrl
* pCurView
,
55 aVerSBar( VclPtr
<ScrollBar
>::Create(pCurView
, WB_DRAG
| WB_VSCROLL
) ),
56 aHorSBar( VclPtr
<ScrollBar
>::Create(pCurView
, WB_DRAG
| WB_HSCROLL
) ),
57 aScrBarBox( VclPtr
<ScrollBarBox
>::Create(pCurView
) ),
58 aAutoArrangeIdle ( "svtools contnr SvxIconChoiceCtrl_Impl AutoArrange" ),
59 aDocRectChangedIdle ( "svtools contnr SvxIconChoiceCtrl_Impl DocRectChanged" ),
60 aVisRectChangedIdle ( "svtools contnr SvxIconChoiceCtrl_Impl VisRectChanged" ),
61 aCallSelectHdlIdle ( "svtools contnr SvxIconChoiceCtrl_Impl CallSelectHdl" ),
62 aImageSize( 32 * pCurView
->GetDPIScaleFactor(), 32 * pCurView
->GetDPIScaleFactor())
64 bChooseWithCursor
= false;
65 pEntryPaintDev
= nullptr;
66 pCurHighlightFrame
= nullptr;
72 bHighlightFramePressed
= false;
73 eSelectionMode
= SelectionMode::Multiple
;
75 ePositionMode
= SvxIconChoiceCtrlPositionMode::Free
;
76 SetStyle( nWinStyle
);
77 nFlags
= IconChoiceFlags::NONE
;
78 nUserEventAdjustScrBars
= nullptr;
79 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
80 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
84 eTextMode
= SvxIconChoiceCtrlTextMode::Short
;
85 pImpCursor
.reset( new IcnCursor_Impl( this ) );
86 pGridMap
.reset( new IcnGridMap_Impl( this ) );
88 aVerSBar
->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
) );
89 aHorSBar
->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
) );
91 nHorSBarHeight
= aHorSBar
->GetSizePixel().Height();
92 nVerSBarWidth
= aVerSBar
->GetSizePixel().Width();
94 aAutoArrangeIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
95 aAutoArrangeIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,AutoArrangeHdl
));
96 aAutoArrangeIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aAutoArrangeIdle" );
98 aCallSelectHdlIdle
.SetPriority( TaskPriority::LOWEST
);
99 aCallSelectHdlIdle
.SetInvokeHandler( LINK(this,SvxIconChoiceCtrl_Impl
,CallSelectHdlHdl
));
100 aCallSelectHdlIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aCallSelectHdlIdle" );
102 aDocRectChangedIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
103 aDocRectChangedIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,DocRectChangedHdl
));
104 aDocRectChangedIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" );
106 aVisRectChangedIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
107 aVisRectChangedIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,VisRectChangedHdl
));
108 aVisRectChangedIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" );
111 Size
gridSize(100,70);
112 if(pView
->GetDPIScaleFactor() > 1)
114 gridSize
.setHeight( gridSize
.Height() * ( pView
->GetDPIScaleFactor()) );
119 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
125 pDDDev
.disposeAndClear();
126 pDDBufDev
.disposeAndClear();
127 pDDTempDev
.disposeAndClear();
128 pEntryPaintDev
.disposeAndClear();
129 ClearSelectedRectList();
131 aVerSBar
.disposeAndClear();
132 aHorSBar
.disposeAndClear();
133 aScrBarBox
.disposeAndClear();
136 void SvxIconChoiceCtrl_Impl::Clear( bool bInCtor
)
139 pCurHighlightFrame
= nullptr;
142 bBoundRectsDirty
= false;
150 aVirtOutputSize
.setWidth( 0 );
151 aVirtOutputSize
.setHeight( 0 );
152 Size
aSize( pView
->GetOutputSizePixel() );
153 nMaxVirtWidth
= aSize
.Width() - nVerSBarWidth
;
154 if( nMaxVirtWidth
<= 0 )
155 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
156 nMaxVirtHeight
= aSize
.Height() - nHorSBarHeight
;
157 if( nMaxVirtHeight
<= 0 )
158 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
159 maZOrderList
.clear();
160 SetOrigin( Point() );
162 pView
->Invalidate(InvalidateFlags::NoChildren
);
170 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle
)
172 nWinBits
= nWinStyle
;
173 nCurTextDrawFlags
= DRAWTEXT_FLAGS_ICON
;
174 if( nWinBits
& (WB_SMALLICON
| WB_DETAILS
) )
175 nCurTextDrawFlags
= DRAWTEXT_FLAGS_SMALLICON
;
176 if( nWinBits
& WB_NOSELECTION
)
177 eSelectionMode
= SelectionMode::NONE
;
178 if( !(nWinStyle
& (WB_ALIGN_TOP
| WB_ALIGN_LEFT
)))
179 nWinBits
|= WB_ALIGN_LEFT
;
180 if( nWinStyle
& WB_DETAILS
)
183 SetColumn( 0, SvxIconChoiceCtrlColumnInfo() );
187 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
, ScrollBar
*, pScrollBar
, void )
189 // arrow up: delta=-1; arrow down: delta=+1
190 Scroll( 0, pScrollBar
->GetDelta() );
193 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
, ScrollBar
*, pScrollBar
, void )
195 // arrow left: delta=-1; arrow right: delta=+1
196 Scroll( pScrollBar
->GetDelta(), 0 );
199 void SvxIconChoiceCtrl_Impl::FontModified()
201 pDDDev
.disposeAndClear();
202 pDDBufDev
.disposeAndClear();
203 pDDTempDev
.disposeAndClear();
204 pEntryPaintDev
.disposeAndClear();
205 SetDefaultTextSize();
210 void SvxIconChoiceCtrl_Impl::InsertEntry( std::unique_ptr
<SvxIconChoiceCtrlEntry
> pEntry1
, size_t nPos
)
212 auto pEntry
= pEntry1
.get();
214 if ( nPos
< maEntries
.size() ) {
215 maEntries
.insert( maEntries
.begin() + nPos
, std::move(pEntry1
) );
217 maEntries
.push_back( std::move(pEntry1
) );
221 pEntry
->SetBacklink( pHead
->pblink
);
223 if( (nFlags
& IconChoiceFlags::EntryListPosValid
) && nPos
>= maEntries
.size() - 1 )
224 pEntry
->nPos
= maEntries
.size() - 1;
226 nFlags
&= ~IconChoiceFlags::EntryListPosValid
;
228 maZOrderList
.push_back( pEntry
);
231 // If the UpdateMode is true, don't set all bounding rectangles to
232 // 'to be checked', but only the bounding rectangle of the new entry.
233 // Thus, don't call InvalidateBoundingRect!
234 pEntry
->aRect
.SetRight( LONG_MAX
);
237 FindBoundingRect( pEntry
);
238 tools::Rectangle
aOutputArea( GetOutputRect() );
239 pGridMap
->OccupyGrids( pEntry
);
240 if( !aOutputArea
.IsOver( pEntry
->aRect
) )
241 return; // is invisible
242 pView
->Invalidate( pEntry
->aRect
);
245 InvalidateBoundingRect( pEntry
->aRect
);
248 void SvxIconChoiceCtrl_Impl::RemoveEntry(size_t nPos
)
251 maEntries
.erase(maEntries
.begin() + nPos
);
252 RecalcAllBoundingRectsSmart();
255 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator
* _pGenerator
)
257 std::unique_ptr
< MnemonicGenerator
> pAutoDeleteOwnGenerator
;
260 _pGenerator
= new MnemonicGenerator
;
261 pAutoDeleteOwnGenerator
.reset( _pGenerator
);
264 sal_uLong nEntryCount
= GetEntryCount();
267 // insert texts in generator
268 for( i
= 0; i
< nEntryCount
; ++i
)
270 DBG_ASSERT( GetEntry( i
), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
272 _pGenerator
->RegisterMnemonic( GetEntry( i
)->GetText() );
275 // exchange texts with generated mnemonics
276 for( i
= 0; i
< nEntryCount
; ++i
)
278 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( i
);
279 OUString aTxt
= pEntry
->GetText();
281 OUString aNewText
= _pGenerator
->CreateMnemonic( aTxt
);
282 if( aNewText
!= aTxt
)
283 pEntry
->SetText( aNewText
);
287 tools::Rectangle
SvxIconChoiceCtrl_Impl::GetOutputRect() const
289 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
291 return tools::Rectangle( aOrigin
, aOutputSize
);
294 void SvxIconChoiceCtrl_Impl::SetListPositions()
296 if( nFlags
& IconChoiceFlags::EntryListPosValid
)
299 size_t nCount
= maEntries
.size();
300 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
302 maEntries
[ nCur
]->nPos
= nCur
;
304 nFlags
|= IconChoiceFlags::EntryListPosValid
;
307 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry
* pEntry
, bool bSelect
,
310 if( eSelectionMode
== SelectionMode::NONE
)
315 if ( !( nFlags
& IconChoiceFlags::ClearingSelection
) )
317 nFlags
|= IconChoiceFlags::ClearingSelection
;
318 DeselectAllBut( pEntry
);
319 nFlags
&= ~IconChoiceFlags::ClearingSelection
;
322 if( pEntry
->IsSelected() == bSelect
)
326 SvxIconViewFlags nEntryFlags
= pEntry
->GetFlags();
329 nEntryFlags
|= SvxIconViewFlags::SELECTED
;
330 pEntry
->AssignFlags( nEntryFlags
);
336 nEntryFlags
&= ~SvxIconViewFlags::SELECTED
;
337 pEntry
->AssignFlags( nEntryFlags
);
341 EntrySelected( pEntry
, bSelect
);
344 void SvxIconChoiceCtrl_Impl::EntrySelected(SvxIconChoiceCtrlEntry
* pEntry
, bool bSelect
)
346 // When using SingleSelection, make sure that the cursor is always placed
347 // over the (only) selected entry. (But only if a cursor exists.)
348 if (bSelect
&& pCursor
&&
349 eSelectionMode
== SelectionMode::Single
&&
355 // Not when dragging though, else the loop in SelectRect doesn't work
357 if (!(nFlags
& IconChoiceFlags::SelectingRect
))
361 if (pEntry
== pCursor
)
363 pView
->Invalidate(CalcFocusRect(pEntry
));
364 if (pEntry
== pCursor
)
368 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
371 CallEventListeners(VclEventId::ListboxSelect
, pEntry
);
375 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
377 aVirtOutputSize
.setWidth( 0 );
378 aVirtOutputSize
.setHeight( 0 );
379 const size_t nCount
= maEntries
.size();
380 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
382 SvxIconChoiceCtrlEntry
* pCur
= maEntries
[ nCur
].get();
383 pCur
->ClearFlags( SvxIconViewFlags::POS_MOVED
);
384 if( pCur
->IsPosLocked() )
386 // adapt (among others) VirtSize
387 if( !IsBoundingRectValid( pCur
->aRect
) )
388 FindBoundingRect( pCur
);
390 AdjustVirtSize( pCur
->aRect
);
393 InvalidateBoundingRect( pCur
->aRect
);
396 if( !(nWinBits
& (WB_NOVSCROLL
| WB_NOHSCROLL
)) )
398 Size
aRealOutputSize( pView
->GetOutputSizePixel() );
399 if( aVirtOutputSize
.Width() < aRealOutputSize
.Width() ||
400 aVirtOutputSize
.Height() < aRealOutputSize
.Height() )
402 sal_uLong nGridCount
= IcnGridMap_Impl::GetGridCount(
403 aRealOutputSize
, static_cast<sal_uInt16
>(nGridDX
), static_cast<sal_uInt16
>(nGridDY
) );
404 if( nGridCount
< nCount
)
406 if( nWinBits
& WB_ALIGN_TOP
)
407 nMaxVirtWidth
= aRealOutputSize
.Width() - nVerSBarWidth
;
408 else // WB_ALIGN_LEFT
409 nMaxVirtHeight
= aRealOutputSize
.Height() - nHorSBarHeight
;
419 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const tools::Rectangle
& rRect
)
421 long nHeightOffs
= 0;
424 if( aVirtOutputSize
.Width() < (rRect
.Right()+LROFFS_WINBORDER
) )
425 nWidthOffs
= (rRect
.Right()+LROFFS_WINBORDER
) - aVirtOutputSize
.Width();
427 if( aVirtOutputSize
.Height() < (rRect
.Bottom()+TBOFFS_WINBORDER
) )
428 nHeightOffs
= (rRect
.Bottom()+TBOFFS_WINBORDER
) - aVirtOutputSize
.Height();
430 if( !(nWidthOffs
|| nHeightOffs
) )
434 aVirtOutputSize
.AdjustWidth(nWidthOffs
);
435 aRange
.Max() = aVirtOutputSize
.Width();
436 aHorSBar
->SetRange( aRange
);
438 aVirtOutputSize
.AdjustHeight(nHeightOffs
);
439 aRange
.Max() = aVirtOutputSize
.Height();
440 aVerSBar
->SetRange( aRange
);
443 pGridMap
->OutputSizeChanged();
448 void SvxIconChoiceCtrl_Impl::InitPredecessors()
450 DBG_ASSERT(!pHead
,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
451 size_t nCount
= maEntries
.size();
454 SvxIconChoiceCtrlEntry
* pPrev
= maEntries
[ 0 ].get();
455 for( size_t nCur
= 1; nCur
<= nCount
; nCur
++ )
457 pPrev
->ClearFlags( SvxIconViewFlags::POS_LOCKED
| SvxIconViewFlags::POS_MOVED
);
459 SvxIconChoiceCtrlEntry
* pNext
;
461 pNext
= maEntries
[ 0 ].get();
463 pNext
= maEntries
[ nCur
].get();
464 pPrev
->pflink
= pNext
;
465 pNext
->pblink
= pPrev
;
468 pHead
= maEntries
[ 0 ].get();
474 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
478 size_t nCount
= maEntries
.size();
479 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
481 SvxIconChoiceCtrlEntry
* pCur
= maEntries
[ nCur
].get();
482 pCur
->pflink
= nullptr;
483 pCur
->pblink
= nullptr;
489 void SvxIconChoiceCtrl_Impl::Arrange( bool bKeepPredecessors
, long nSetMaxVirtWidth
, long nSetMaxVirtHeight
)
491 if ( nSetMaxVirtWidth
!= 0 )
492 nMaxVirtWidth
= nSetMaxVirtWidth
;
494 nMaxVirtWidth
= aOutputSize
.Width();
496 if ( nSetMaxVirtHeight
!= 0 )
497 nMaxVirtHeight
= nSetMaxVirtHeight
;
499 nMaxVirtHeight
= aOutputSize
.Height();
501 ImpArrange( bKeepPredecessors
);
504 void SvxIconChoiceCtrl_Impl::ImpArrange( bool bKeepPredecessors
)
506 static Point aEmptyPoint
;
508 bool bOldUpdate
= bUpdateMode
;
509 tools::Rectangle
aCurOutputArea( GetOutputRect() );
510 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
512 aAutoArrangeIdle
.Stop();
513 nFlags
|= IconChoiceFlags::Arranging
;
516 if( !bKeepPredecessors
)
518 bBoundRectsDirty
= false;
519 SetOrigin( Point() );
521 RecalcAllBoundingRectsSmart();
522 // TODO: the invalidation in the detail view should be more intelligent
523 //if( !(nWinBits & WB_DETAILS ))
524 pView
->Invalidate( InvalidateFlags::NoChildren
);
525 nFlags
&= ~IconChoiceFlags::Arranging
;
526 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
528 MakeVisible( aCurOutputArea
);
529 SetUpdateMode( bOldUpdate
);
534 void SvxIconChoiceCtrl_Impl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
536 #if defined(OV_DRAWGRID)
537 Color
aOldColor (rRenderContext
.GetLineColor());
539 rRenderContext
.SetLineColor( aColor
);
540 Point
aOffs(rRenderContext
.GetMapMode().GetOrigin());
541 Size
aXSize(GetOutputSizePixel());
543 Point
aStart(LROFFS_WINBORDER
, 0);
544 Point
aEnd(LROFFS_WINBORDER
, aXSize
.Height());
547 rRenderContext
.DrawLine(aStart
, aEnd
);
550 Point
aStart(0, TBOFFS_WINBORDER
);
551 Point
aEnd(aXSize
.Width(), TBOFFS_WINBORDER
);
554 rRenderContext
.DrawLine(aStart
, aEnd
);
557 for (long nDX
= nGridDX
; nDX
<= aXSize
.Width(); nDX
+= nGridDX
)
559 Point
aStart( nDX
+LROFFS_WINBORDER
, 0 );
560 Point
aEnd( nDX
+LROFFS_WINBORDER
, aXSize
.Height());
563 rRenderContext
.DrawLine(aStart
, aEnd
);
565 for (long nDY
= nGridDY
; nDY
<= aXSize
.Height(); nDY
+= nGridDY
)
567 Point
aStart(0, nDY
+ TBOFFS_WINBORDER
);
568 Point
aEnd(aXSize
.Width(), nDY
+ TBOFFS_WINBORDER
);
571 rRenderContext
.DrawLine(aStart
, aEnd
);
573 rRenderContext
.SetLineColor(aOldColor
);
576 if (!maEntries
.size())
580 // set cursor to item with focus-flag
582 for (sal_Int32 i
= 0; i
< pView
->GetEntryCount() && !bfound
; i
++)
584 SvxIconChoiceCtrlEntry
* pEntry
= pView
->GetEntry(i
);
585 if (pEntry
->IsFocused())
593 pCursor
= maEntries
[ 0 ].get();
596 size_t nCount
= maZOrderList
.size();
600 rRenderContext
.Push(PushFlags::CLIPREGION
);
601 rRenderContext
.SetClipRegion(vcl::Region(rRect
));
603 std::vector
< SvxIconChoiceCtrlEntry
* > aNewZOrderList
;
604 std::vector
< SvxIconChoiceCtrlEntry
* > aPaintedEntries
;
609 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[nPos
];
610 const tools::Rectangle
& rBoundRect
= GetEntryBoundRect(pEntry
);
611 if (rRect
.IsOver(rBoundRect
))
613 PaintEntry(pEntry
, rBoundRect
.TopLeft(), rRenderContext
);
614 // set entries to Top if they are being repainted
615 aPaintedEntries
.push_back(pEntry
);
618 aNewZOrderList
.push_back(pEntry
);
623 maZOrderList
= std::move( aNewZOrderList
);
624 maZOrderList
.insert(maZOrderList
.end(), aPaintedEntries
.begin(), aPaintedEntries
.end());
626 rRenderContext
.Pop();
629 void SvxIconChoiceCtrl_Impl::RepaintSelectedEntries()
631 const size_t nCount
= maZOrderList
.size();
635 tools::Rectangle
aOutRect(GetOutputRect());
636 for (size_t nCur
= 0; nCur
< nCount
; nCur
++)
638 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[nCur
];
639 if (pEntry
->GetFlags() & SvxIconViewFlags::SELECTED
)
641 const tools::Rectangle
& rBoundRect
= GetEntryBoundRect(pEntry
);
642 if (aOutRect
.IsOver(rBoundRect
))
643 pView
->Invalidate(rBoundRect
);
648 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
650 aScrBarBox
->SetSizePixel( Size(nVerSBarWidth
-1, nHorSBarHeight
-1) );
651 Size
aSize( pView
->GetOutputSizePixel() );
652 aScrBarBox
->SetPosPixel( Point(aSize
.Width()-nVerSBarWidth
+1, aSize
.Height()-nHorSBarHeight
+1));
655 bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent
& rMEvt
)
657 bool bHandled
= true;
658 bHighlightFramePressed
= false;
659 bool bGotFocus
= (!pView
->HasFocus() && !(nWinBits
& WB_NOPOINTERFOCUS
));
660 if( !(nWinBits
& WB_NOPOINTERFOCUS
) )
663 Point
aDocPos( rMEvt
.GetPosPixel() );
664 if(aDocPos
.X()>=aOutputSize
.Width() || aDocPos
.Y()>=aOutputSize
.Height())
667 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, true );
669 MakeEntryVisible( pEntry
, false );
671 if( rMEvt
.IsShift() && eSelectionMode
!= SelectionMode::Single
)
674 SetCursor_Impl( pCursor
, pEntry
, rMEvt
.IsMod1(), rMEvt
.IsShift() );
678 if( pAnchor
&& (rMEvt
.IsShift() || rMEvt
.IsMod1())) // keyboard selection?
680 DBG_ASSERT(eSelectionMode
!= SelectionMode::Single
,"Invalid selection mode");
682 nFlags
|= IconChoiceFlags::AddMode
;
684 if( rMEvt
.IsShift() )
686 tools::Rectangle
aRect( GetEntryBoundRect( pAnchor
));
688 aRect
.Union( GetEntryBoundRect( pEntry
) );
691 tools::Rectangle
aTempRect( aDocPos
, Size(1,1));
692 aRect
.Union( aTempRect
);
694 aCurSelectionRect
= aRect
;
695 SelectRect( aRect
, bool(nFlags
& IconChoiceFlags::AddMode
), &aSelectedRectList
);
697 else if( rMEvt
.IsMod1() )
699 AddSelectedRect( aCurSelectionRect
);
701 aCurSelectionRect
.SetPos( aDocPos
);
704 if( !pEntry
&& !(nWinBits
& WB_NODRAGSELECTION
))
705 pView
->StartTracking( StartTrackingFlags::ScrollRepeat
);
712 if( eSelectionMode
== SelectionMode::Multiple
)
714 if( !rMEvt
.IsMod1() ) // Ctrl
719 ClearSelectedRectList();
723 nFlags
|= IconChoiceFlags::AddMode
;
724 aCurSelectionRect
.SetPos( aDocPos
);
725 pView
->StartTracking( StartTrackingFlags::ScrollRepeat
);
732 bool bSelected
= pEntry
->IsSelected();
734 if( rMEvt
.GetClicks() == 2 )
736 DeselectAllBut( pEntry
);
737 SelectEntry( pEntry
, true, false );
744 if( rMEvt
.IsMod2() ) // Alt?
747 else if( eSelectionMode
== SelectionMode::Single
)
749 DeselectAllBut( pEntry
);
752 else if( eSelectionMode
== SelectionMode::NONE
)
754 if( rMEvt
.IsLeft() && (nWinBits
& WB_HIGHLIGHTFRAME
) )
756 pCurHighlightFrame
= nullptr; // force repaint of frame
757 bHighlightFramePressed
= true;
758 SetEntryHighlightFrame( pEntry
, true );
763 if( !rMEvt
.GetModifier() && rMEvt
.IsLeft() )
767 DeselectAllBut( pEntry
);
769 SelectEntry( pEntry
, true, false );
773 // deselect only in the Up, if the Move happened via D&D!
774 nFlags
|= IconChoiceFlags::DownDeselect
;
777 else if( rMEvt
.IsMod1() )
778 nFlags
|= IconChoiceFlags::DownCtrl
;
784 bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent
& rMEvt
)
786 bool bHandled
= false;
787 if( rMEvt
.IsRight() && (nFlags
& (IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
) ))
789 nFlags
&= ~IconChoiceFlags(IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
);
793 Point
aDocPos( rMEvt
.GetPosPixel() );
795 SvxIconChoiceCtrlEntry
* pDocEntry
= GetEntry( aDocPos
);
798 if( nFlags
& IconChoiceFlags::DownCtrl
)
800 // Ctrl & MultiSelection
801 ToggleSelection( pDocEntry
);
802 SetCursor( pDocEntry
);
805 else if( nFlags
& IconChoiceFlags::DownDeselect
)
807 DeselectAllBut( pDocEntry
);
808 SetCursor( pDocEntry
);
809 SelectEntry( pDocEntry
, true, false );
814 nFlags
&= ~IconChoiceFlags(IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
);
816 if((nWinBits
& WB_HIGHLIGHTFRAME
) && bHighlightFramePressed
&& pCurHighlightFrame
)
819 SvxIconChoiceCtrlEntry
* pEntry
= pCurHighlightFrame
;
820 pCurHighlightFrame
= nullptr; // force repaint of frame
821 bHighlightFramePressed
= false;
822 SetEntryHighlightFrame( pEntry
, true );
824 pHdlEntry
= pCurHighlightFrame
;
828 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
829 SetCursor_Impl( pOldCursor
, pHdlEntry
, false, false );
836 bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent
& rMEvt
)
838 const Point
aDocPos( pView
->PixelToLogic(rMEvt
.GetPosPixel()) );
840 if( pView
->IsTracking() )
842 else if( nWinBits
& WB_HIGHLIGHTFRAME
)
844 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, true );
845 SetEntryHighlightFrame( pEntry
, false );
852 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry
* pOldCursor
,
853 SvxIconChoiceCtrlEntry
* pNewCursor
, bool bMod1
, bool bShift
)
858 SvxIconChoiceCtrlEntry
* pFilterEntry
= nullptr;
859 bool bDeselectAll
= false;
860 if( eSelectionMode
!= SelectionMode::Single
)
862 if( !bMod1
&& !bShift
)
864 else if( bShift
&& !bMod1
&& !pAnchor
)
867 pFilterEntry
= pOldCursor
;
871 DeselectAllBut( pFilterEntry
);
873 MakeEntryVisible( pNewCursor
);
874 SetCursor( pNewCursor
);
875 if( bMod1
&& !bShift
)
879 AddSelectedRect( pAnchor
, pOldCursor
);
886 pAnchor
= pOldCursor
;
887 if ( nWinBits
& WB_ALIGN_LEFT
)
888 SelectRange( pAnchor
, pNewCursor
, bool(nFlags
& IconChoiceFlags::AddMode
) );
890 SelectRect(pAnchor
,pNewCursor
, bool(nFlags
& IconChoiceFlags::AddMode
), &aSelectedRectList
);
894 SelectEntry( pCursor
, true, false );
895 aCurSelectionRect
= GetEntryBoundRect( pCursor
);
896 CallEventListeners( VclEventId::ListboxSelect
, pCursor
);
900 bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent
& rKEvt
)
902 bool bMod2
= rKEvt
.GetKeyCode().IsMod2();
903 sal_Unicode cChar
= rKEvt
.GetCharCode();
904 sal_uLong nPos
= sal_uLong(-1);
905 if ( bMod2
&& cChar
&& IsMnemonicChar( cChar
, nPos
) )
907 // shortcut is clicked
908 SvxIconChoiceCtrlEntry
* pNewCursor
= GetEntry( nPos
);
909 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
910 if ( pNewCursor
!= pOldCursor
)
911 SetCursor_Impl( pOldCursor
, pNewCursor
, false, false );
916 // no actions with <ALT>
919 bool bKeyUsed
= true;
920 bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
921 bool bShift
= rKEvt
.GetKeyCode().IsShift();
923 if( eSelectionMode
== SelectionMode::Single
|| eSelectionMode
== SelectionMode::NONE
)
930 nFlags
|= IconChoiceFlags::AddMode
;
932 SvxIconChoiceCtrlEntry
* pNewCursor
;
933 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
935 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
942 MakeEntryVisible( pCursor
);
943 if( nCode
== KEY_UP
)
944 pNewCursor
= pImpCursor
->GoUpDown(pCursor
,false);
946 pNewCursor
= pImpCursor
->GoPageUpDown(pCursor
,false);
947 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
950 tools::Rectangle
aRect( GetEntryBoundRect( pCursor
) );
953 aRect
.AdjustBottom( -(aRect
.Top()) );
955 MakeVisible( aRect
);
959 if ( bChooseWithCursor
&& pNewCursor
!= nullptr )
961 pHdlEntry
= pNewCursor
;//GetCurEntry();
962 pCurHighlightFrame
= pHdlEntry
;
964 pCurHighlightFrame
= nullptr;
973 if( nCode
== KEY_DOWN
)
974 pNewCursor
=pImpCursor
->GoUpDown( pCursor
,true );
976 pNewCursor
=pImpCursor
->GoPageUpDown( pCursor
,true );
977 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
979 if ( bChooseWithCursor
&& pNewCursor
!= nullptr)
981 pHdlEntry
= pNewCursor
;//GetCurEntry();
982 pCurHighlightFrame
= pHdlEntry
;
984 pCurHighlightFrame
= nullptr;
992 pNewCursor
=pImpCursor
->GoLeftRight(pCursor
,true );
993 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1000 MakeEntryVisible( pCursor
);
1001 pNewCursor
= pImpCursor
->GoLeftRight(pCursor
,false );
1002 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1005 tools::Rectangle
aRect( GetEntryBoundRect(pCursor
));
1008 aRect
.AdjustRight( -(aRect
.Left()) );
1010 MakeVisible( aRect
);
1017 if( bMod1
|| bShift
)
1022 if( rKEvt
.GetKeyCode().IsShift() )
1024 if( nFlags
& IconChoiceFlags::AddMode
)
1025 nFlags
&= ~IconChoiceFlags::AddMode
;
1027 nFlags
|= IconChoiceFlags::AddMode
;
1034 if( pCursor
&& eSelectionMode
!= SelectionMode::Single
)
1038 //SelectAll( false );
1040 ClearSelectedRectList();
1042 // click Icon with spacebar
1043 SetEntryHighlightFrame( GetCurEntry(), true );
1045 pHdlEntry
= pCurHighlightFrame
;
1046 pCurHighlightFrame
=nullptr;
1049 ToggleSelection( pCursor
);
1055 if( rKEvt
.GetKeyCode().IsShift() )
1058 pView
->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Full
, pCursor
);
1060 if( rKEvt
.GetKeyCode().IsMod1() )
1063 pView
->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Short
, pCursor
);
1071 if( bMod1
&& (eSelectionMode
!= SelectionMode::Single
))
1093 pNewCursor
= maEntries
.back().get();
1094 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1101 pNewCursor
= maEntries
[ 0 ].get();
1102 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1113 // recalculate TopLeft of scrollbars (but not their sizes!)
1114 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth
, long nRealHeight
)
1116 // horizontal scrollbar
1117 Point
aPos( 0, nRealHeight
);
1118 aPos
.AdjustY( -nHorSBarHeight
);
1120 if( aHorSBar
->GetPosPixel() != aPos
)
1121 aHorSBar
->SetPosPixel( aPos
);
1123 // vertical scrollbar
1124 aPos
.setX( nRealWidth
); aPos
.setY( 0 );
1125 aPos
.AdjustX( -nVerSBarWidth
);
1129 if( aVerSBar
->GetPosPixel() != aPos
)
1130 aVerSBar
->SetPosPixel( aPos
);
1133 void SvxIconChoiceCtrl_Impl::AdjustScrollBars()
1135 long nVirtHeight
= aVirtOutputSize
.Height();
1136 long nVirtWidth
= aVirtOutputSize
.Width();
1138 Size
aOSize( pView
->Control::GetOutputSizePixel() );
1139 long nRealHeight
= aOSize
.Height();
1140 long nRealWidth
= aOSize
.Width();
1142 PositionScrollBars( nRealWidth
, nRealHeight
);
1144 const MapMode
& rMapMode
= pView
->GetMapMode();
1145 Point
aOrigin( rMapMode
.GetOrigin() );
1148 if( nRealWidth
> nVirtWidth
)
1149 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1151 nVisibleWidth
= nRealWidth
;
1153 long nVisibleHeight
;
1154 if( nRealHeight
> nVirtHeight
)
1155 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1157 nVisibleHeight
= nRealHeight
;
1159 bool bVerSBar
= ( nWinBits
& WB_VSCROLL
) != 0;
1160 bool bHorSBar
= ( nWinBits
& WB_HSCROLL
) != 0;
1161 bool bNoVerSBar
= ( nWinBits
& WB_NOVSCROLL
) != 0;
1162 bool bNoHorSBar
= ( nWinBits
& WB_NOHSCROLL
) != 0;
1164 sal_uInt16 nResult
= 0;
1167 // activate vertical scrollbar?
1168 if( !bNoVerSBar
&& (bVerSBar
|| ( nVirtHeight
> nVisibleHeight
)) )
1171 nRealWidth
-= nVerSBarWidth
;
1173 if( nRealWidth
> nVirtWidth
)
1174 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1176 nVisibleWidth
= nRealWidth
;
1178 // activate horizontal scrollbar?
1179 if( !bNoHorSBar
&& (bHorSBar
|| (nVirtWidth
> nVisibleWidth
)) )
1182 nRealHeight
-= nHorSBarHeight
;
1184 if( nRealHeight
> nVirtHeight
)
1185 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1187 nVisibleHeight
= nRealHeight
;
1189 // do we need a vertical scrollbar after all?
1190 if( !(nResult
& 0x0001) && // only if not already there
1191 ( !bNoVerSBar
&& ((nVirtHeight
> nVisibleHeight
) || bVerSBar
)) )
1193 nResult
= 3; // both turned on
1194 nRealWidth
-= nVerSBarWidth
;
1196 if( nRealWidth
> nVirtWidth
)
1197 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1199 nVisibleWidth
= nRealWidth
;
1204 // size vertical scrollbar
1205 long nThumb
= aVerSBar
->GetThumbPos();
1206 Size
aSize( nVerSBarWidth
, nRealHeight
);
1207 aSize
.AdjustHeight(2 );
1208 if( aSize
!= aVerSBar
->GetSizePixel() )
1209 aVerSBar
->SetSizePixel( aSize
);
1210 aVerSBar
->SetVisibleSize( nVisibleHeight
);
1211 aVerSBar
->SetPageSize( GetScrollBarPageSize( nVisibleHeight
));
1213 if( nResult
& 0x0001 )
1215 aVerSBar
->SetThumbPos( nThumb
);
1220 aVerSBar
->SetThumbPos( 0 );
1224 // size horizontal scrollbar
1225 nThumb
= aHorSBar
->GetThumbPos();
1226 aSize
.setWidth( nRealWidth
);
1227 aSize
.setHeight( nHorSBarHeight
);
1228 aSize
.AdjustWidth( 1 );
1229 if( nResult
& 0x0001 ) // vertical scrollbar?
1231 aSize
.AdjustWidth( 1 );
1234 if( aSize
!= aHorSBar
->GetSizePixel() )
1235 aHorSBar
->SetSizePixel( aSize
);
1236 aHorSBar
->SetVisibleSize( nVisibleWidth
);
1237 aHorSBar
->SetPageSize( GetScrollBarPageSize(nVisibleWidth
));
1238 if( nResult
& 0x0002 )
1240 aHorSBar
->SetThumbPos( nThumb
);
1245 aHorSBar
->SetThumbPos( 0 );
1249 aOutputSize
.setWidth( nRealWidth
);
1250 if( nResult
& 0x0002 ) // horizontal scrollbar ?
1251 nRealHeight
++; // because lower border is clipped
1252 aOutputSize
.setHeight( nRealHeight
);
1254 if( (nResult
& (0x0001|0x0002)) == (0x0001|0x0002) )
1260 void SvxIconChoiceCtrl_Impl::Resize()
1263 aOutputSize
= pView
->GetOutputSizePixel();
1264 pImpCursor
->Clear();
1265 pGridMap
->OutputSizeChanged();
1267 const Size
& rSize
= pView
->Control::GetOutputSizePixel();
1268 PositionScrollBars( rSize
.Width(), rSize
.Height() );
1269 // The scrollbars are shown/hidden asynchronously, so derived classes can
1270 // do an Arrange during Resize, without the scrollbars suddenly turning
1271 // on and off again.
1272 // If an event is already underway, we don't need to send a new one, at least
1273 // as long as there is only one event type.
1274 if ( ! nUserEventAdjustScrBars
)
1275 nUserEventAdjustScrBars
=
1276 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl
, UserEventHdl
),
1277 EVENTID_ADJUST_SCROLLBARS
);
1282 bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1284 if( maZOrderList
.empty() || !aHorSBar
->IsVisible() )
1286 const MapMode
& rMapMode
= pView
->GetMapMode();
1287 Point
aOrigin( rMapMode
.GetOrigin() );
1288 if(!( nWinBits
& WB_HSCROLL
) && !aOrigin
.X() )
1290 long nWidth
= aOutputSize
.Width();
1291 const size_t nCount
= maZOrderList
.size();
1292 long nMostRight
= 0;
1293 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1295 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCur
];
1296 long nRight
= GetEntryBoundRect(pEntry
).Right();
1297 if( nRight
> nWidth
)
1299 if( nRight
> nMostRight
)
1300 nMostRight
= nRight
;
1303 aOutputSize
.AdjustHeight(nHorSBarHeight
);
1304 aVirtOutputSize
.setWidth( nMostRight
);
1305 aHorSBar
->SetThumbPos( 0 );
1307 aRange
.Max() = nMostRight
- 1;
1308 aHorSBar
->SetRange( aRange
);
1309 if( aVerSBar
->IsVisible() )
1311 Size
aSize( aVerSBar
->GetSizePixel());
1312 aSize
.AdjustHeight(nHorSBarHeight
);
1313 aVerSBar
->SetSizePixel( aSize
);
1320 bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1322 if( maZOrderList
.empty() || !aVerSBar
->IsVisible() )
1324 const MapMode
& rMapMode
= pView
->GetMapMode();
1325 Point
aOrigin( rMapMode
.GetOrigin() );
1326 if(!( nWinBits
& WB_VSCROLL
) && !aOrigin
.Y() )
1329 long nHeight
= aOutputSize
.Height();
1330 const size_t nCount
= maZOrderList
.size();
1331 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1333 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCur
];
1334 long nBottom
= GetEntryBoundRect(pEntry
).Bottom();
1335 if( nBottom
> nHeight
)
1337 if( nBottom
> nDeepest
)
1341 aOutputSize
.AdjustWidth(nVerSBarWidth
);
1342 aVirtOutputSize
.setHeight( nDeepest
);
1343 aVerSBar
->SetThumbPos( 0 );
1345 aRange
.Max() = nDeepest
- 1;
1346 aVerSBar
->SetRange( aRange
);
1347 if( aHorSBar
->IsVisible() )
1349 Size
aSize( aHorSBar
->GetSizePixel());
1350 aSize
.AdjustWidth(nVerSBarWidth
);
1351 aHorSBar
->SetSizePixel( aSize
);
1359 // hides scrollbars if they're unnecessary
1360 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1362 CheckVerScrollBar();
1363 if( CheckHorScrollBar() )
1364 CheckVerScrollBar();
1365 if( aVerSBar
->IsVisible() && aHorSBar
->IsVisible() )
1372 void SvxIconChoiceCtrl_Impl::GetFocus()
1374 RepaintSelectedEntries();
1377 pCursor
->SetFlags( SvxIconViewFlags::FOCUSED
);
1382 void SvxIconChoiceCtrl_Impl::LoseFocus()
1385 pCursor
->ClearFlags( SvxIconViewFlags::FOCUSED
);
1386 ShowCursor( false );
1389 // pView->Invalidate ( aFocus.aRect );
1391 RepaintSelectedEntries();
1394 void SvxIconChoiceCtrl_Impl::SetUpdateMode( bool bUpdate
)
1396 if( bUpdate
!= bUpdateMode
)
1398 bUpdateMode
= bUpdate
;
1402 pImpCursor
->Clear();
1404 pView
->Invalidate(InvalidateFlags::NoChildren
);
1409 // priorities of the emphasis: bSelected
1410 void SvxIconChoiceCtrl_Impl::PaintEmphasis(const tools::Rectangle
& rTextRect
, bool bSelected
,
1411 vcl::RenderContext
& rRenderContext
)
1413 Color
aOldFillColor(rRenderContext
.GetFillColor());
1415 bool bSolidTextRect
= false;
1419 const Color
& rFillColor
= rRenderContext
.GetFont().GetFillColor();
1420 rRenderContext
.SetFillColor(rFillColor
);
1421 if (rFillColor
!= COL_TRANSPARENT
)
1422 bSolidTextRect
= true;
1425 // draw text rectangle
1428 rRenderContext
.DrawRect(rTextRect
);
1431 rRenderContext
.SetFillColor(aOldFillColor
);
1435 void SvxIconChoiceCtrl_Impl::PaintItem(const tools::Rectangle
& rRect
,
1436 IcnViewFieldType eItem
, SvxIconChoiceCtrlEntry
* pEntry
, sal_uInt16 nPaintFlags
,
1437 vcl::RenderContext
& rRenderContext
)
1439 if (eItem
== IcnViewFieldType::Text
)
1441 OUString aText
= SvtIconChoiceCtrl::GetEntryText(pEntry
);
1443 rRenderContext
.DrawText(rRect
, aText
, nCurTextDrawFlags
);
1445 if (pEntry
->IsFocused())
1447 tools::Rectangle
aRect (CalcFocusRect(pEntry
));
1449 DrawFocusRect(rRenderContext
);
1454 Point
aPos(rRect
.TopLeft());
1455 if (nPaintFlags
& PAINTFLAG_HOR_CENTERED
)
1456 aPos
.AdjustX((rRect
.GetWidth() - aImageSize
.Width()) / 2 );
1457 if (nPaintFlags
& PAINTFLAG_VER_CENTERED
)
1458 aPos
.AdjustY((rRect
.GetHeight() - aImageSize
.Height()) / 2 );
1459 SvtIconChoiceCtrl::DrawEntryImage(pEntry
, aPos
, rRenderContext
);
1463 void SvxIconChoiceCtrl_Impl::PaintEntry(SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
, vcl::RenderContext
& rRenderContext
)
1465 bool bSelected
= false;
1467 if (eSelectionMode
!= SelectionMode::NONE
)
1468 bSelected
= pEntry
->IsSelected();
1470 rRenderContext
.Push(PushFlags::FONT
| PushFlags::TEXTCOLOR
);
1472 OUString
aEntryText(SvtIconChoiceCtrl::GetEntryText(pEntry
));
1473 tools::Rectangle
aTextRect(CalcTextRect(pEntry
, &rPos
, &aEntryText
));
1474 tools::Rectangle
aBmpRect(CalcBmpRect(pEntry
, &rPos
));
1476 bool bShowSelection
= (bSelected
&& (eSelectionMode
!= SelectionMode::NONE
));
1478 bool bActiveSelection
= (0 != (nWinBits
& WB_NOHIDESELECTION
)) || pView
->HasFocus();
1482 const StyleSettings
& rSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1483 vcl::Font
aNewFont(rRenderContext
.GetFont());
1485 // font fill colors that are attributed "hard" need corresponding "hard"
1486 // attributed highlight colors
1487 if ((nWinBits
& WB_NOHIDESELECTION
) || pView
->HasFocus())
1488 aNewFont
.SetFillColor(rSettings
.GetHighlightColor());
1490 aNewFont
.SetFillColor(rSettings
.GetDeactiveColor());
1492 Color aWinCol
= rSettings
.GetWindowTextColor();
1493 if (!bActiveSelection
&& rSettings
.GetFaceColor().IsBright() == aWinCol
.IsBright())
1494 aNewFont
.SetColor(rSettings
.GetWindowTextColor());
1496 aNewFont
.SetColor(rSettings
.GetHighlightTextColor());
1498 rRenderContext
.SetFont(aNewFont
);
1500 rRenderContext
.SetFillColor(rRenderContext
.GetBackground().GetColor());
1501 rRenderContext
.DrawRect(CalcFocusRect(pEntry
));
1502 rRenderContext
.SetFillColor();
1505 bool bResetClipRegion
= false;
1506 if (!rRenderContext
.IsClipRegion() && (aVerSBar
->IsVisible() || aHorSBar
->IsVisible()))
1508 tools::Rectangle
aOutputArea(GetOutputRect());
1509 if (aOutputArea
.IsOver(aTextRect
) || aOutputArea
.IsOver(aBmpRect
))
1511 rRenderContext
.SetClipRegion(vcl::Region(aOutputArea
));
1512 bResetClipRegion
= true;
1516 bool bLargeIconMode
= WB_ICON
== ( nWinBits
& VIEWMODE_MASK
);
1517 sal_uInt16 nBmpPaintFlags
= PAINTFLAG_VER_CENTERED
;
1519 nBmpPaintFlags
|= PAINTFLAG_HOR_CENTERED
;
1520 sal_uInt16 nTextPaintFlags
= bLargeIconMode
? PAINTFLAG_HOR_CENTERED
: PAINTFLAG_VER_CENTERED
;
1522 PaintEmphasis(aTextRect
, bSelected
, rRenderContext
);
1524 if ( bShowSelection
)
1525 vcl::RenderTools::DrawSelectionBackground(rRenderContext
, *pView
, CalcFocusRect(pEntry
),
1526 bActiveSelection
? 1 : 2, false, true, false);
1529 PaintItem(aBmpRect
, IcnViewFieldType::Image
, pEntry
, nBmpPaintFlags
, rRenderContext
);
1531 PaintItem(aTextRect
, IcnViewFieldType::Text
, pEntry
, nTextPaintFlags
, rRenderContext
);
1533 // draw highlight frame
1534 if (pEntry
== pCurHighlightFrame
)
1535 DrawHighlightFrame(rRenderContext
, CalcFocusRect(pEntry
));
1537 rRenderContext
.Pop();
1538 if (bResetClipRegion
)
1539 rRenderContext
.SetClipRegion();
1542 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
)
1544 ShowCursor( false );
1545 tools::Rectangle
aBoundRect( GetEntryBoundRect( pEntry
));
1546 pView
->Invalidate( aBoundRect
);
1548 if( !IsAutoArrange() )
1550 bool bAdjustVirtSize
= false;
1551 if( rPos
!= aBoundRect
.TopLeft() )
1554 pEntry
->aGridRect
.TopLeft() - pEntry
->aRect
.TopLeft() );
1555 pImpCursor
->Clear();
1557 aBoundRect
.SetPos( rPos
);
1558 pEntry
->aRect
= aBoundRect
;
1559 pEntry
->aGridRect
.SetPos( rPos
+ aGridOffs
);
1560 bAdjustVirtSize
= true;
1562 if( bAdjustVirtSize
)
1563 AdjustVirtSize( pEntry
->aRect
);
1565 pView
->Invalidate( pEntry
->aRect
);
1566 pGridMap
->OccupyGrids( pEntry
);
1570 SvxIconChoiceCtrlEntry
* pPrev
= FindEntryPredecessor( pEntry
, rPos
);
1571 SetEntryPredecessor( pEntry
, pPrev
);
1572 aAutoArrangeIdle
.Start();
1577 void SvxIconChoiceCtrl_Impl::SetNoSelection()
1579 // block recursive calls via SelectEntry
1580 if( !(nFlags
& IconChoiceFlags::ClearingSelection
))
1582 nFlags
|= IconChoiceFlags::ClearingSelection
;
1583 DeselectAllBut( nullptr );
1584 nFlags
&= ~IconChoiceFlags::ClearingSelection
;
1588 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetEntry( const Point
& rDocPos
, bool bHit
)
1590 CheckBoundingRects();
1591 // search through z-order list from the end
1592 size_t nCount
= maZOrderList
.size();
1596 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCount
];
1597 if( pEntry
->aRect
.IsInside( rDocPos
) )
1601 tools::Rectangle aRect
= CalcBmpRect( pEntry
);
1602 aRect
.AdjustTop( -3 );
1603 aRect
.AdjustBottom(3 );
1604 aRect
.AdjustLeft( -3 );
1605 aRect
.AdjustRight(3 );
1606 if( aRect
.IsInside( rDocPos
) )
1608 aRect
= CalcTextRect( pEntry
);
1609 if( aRect
.IsInside( rDocPos
) )
1619 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry
* pEntry
, bool bBound
)
1623 const tools::Rectangle
& rRect
= GetEntryBoundRect( pEntry
);
1624 MakeVisible( rRect
);
1628 tools::Rectangle aRect
= CalcBmpRect( pEntry
);
1629 aRect
.Union( CalcTextRect( pEntry
) );
1630 aRect
.AdjustTop(TBOFFS_BOUND
);
1631 aRect
.AdjustBottom(TBOFFS_BOUND
);
1632 aRect
.AdjustLeft(LROFFS_BOUND
);
1633 aRect
.AdjustRight(LROFFS_BOUND
);
1634 MakeVisible( aRect
);
1638 const tools::Rectangle
& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry
* pEntry
)
1640 if( !IsBoundingRectValid( pEntry
->aRect
))
1641 FindBoundingRect( pEntry
);
1642 return pEntry
->aRect
;
1645 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry
* pEntry
, const Point
* pPos
)
1647 tools::Rectangle aBound
= GetEntryBoundRect( pEntry
);
1649 aBound
.SetPos( *pPos
);
1650 Point
aPos( aBound
.TopLeft() );
1652 switch( nWinBits
& VIEWMODE_MASK
)
1656 aPos
.AdjustX(( aBound
.GetWidth() - aImageSize
.Width() ) / 2 );
1657 return tools::Rectangle( aPos
, aImageSize
);
1662 aPos
.AdjustY(( aBound
.GetHeight() - aImageSize
.Height() ) / 2 );
1663 //TODO: determine horizontal distance to bounding rectangle
1664 return tools::Rectangle( aPos
, aImageSize
);
1667 OSL_FAIL("IconView: Viewmode not set");
1672 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry
* pEntry
,
1673 const Point
* pEntryPos
, const OUString
* pStr
)
1675 OUString aEntryText
;
1677 aEntryText
= SvtIconChoiceCtrl::GetEntryText( pEntry
);
1681 const tools::Rectangle
aMaxTextRect( CalcMaxTextRect( pEntry
) );
1682 tools::Rectangle
aBound( GetEntryBoundRect( pEntry
) );
1684 aBound
.SetPos( *pEntryPos
);
1686 tools::Rectangle aTextRect
= pView
->GetTextRect( aMaxTextRect
, aEntryText
, nCurTextDrawFlags
);
1688 Size
aTextSize( aTextRect
.GetSize() );
1690 Point
aPos( aBound
.TopLeft() );
1691 long nBoundWidth
= aBound
.GetWidth();
1692 long nBoundHeight
= aBound
.GetHeight();
1694 switch( nWinBits
& VIEWMODE_MASK
)
1697 aPos
.AdjustY(aImageSize
.Height() );
1698 aPos
.AdjustY(VER_DIST_BMP_STRING
);
1699 aPos
.AdjustX((nBoundWidth
- aTextSize
.Width()) / 2 );
1704 aPos
.AdjustX(aImageSize
.Width() );
1705 aPos
.AdjustX(HOR_DIST_BMP_STRING
);
1706 aPos
.AdjustY((nBoundHeight
- aTextSize
.Height()) / 2 );
1709 return tools::Rectangle( aPos
, aTextSize
);
1713 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth() const
1715 long nStringWidth
= GetItemSize( IcnViewFieldType::Text
).Width();
1718 switch( nWinBits
& VIEWMODE_MASK
)
1721 nWidth
= std::max( nStringWidth
, aImageSize
.Width() );
1726 nWidth
= aImageSize
.Width();
1727 nWidth
+= HOR_DIST_BMP_STRING
;
1728 nWidth
+= nStringWidth
;
1734 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight() const
1736 long nStringHeight
= GetItemSize(IcnViewFieldType::Text
).Height();
1739 switch( nWinBits
& VIEWMODE_MASK
)
1742 nHeight
= aImageSize
.Height();
1743 nHeight
+= VER_DIST_BMP_STRING
;
1744 nHeight
+= nStringHeight
;
1749 nHeight
= std::max( aImageSize
.Height(), nStringHeight
);
1752 if( nHeight
> nMaxBoundHeight
)
1754 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->nMaxBoundHeight
= nHeight
;
1755 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->aHorSBar
->SetLineSize( GetScrollBarLineSize() );
1756 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->aVerSBar
->SetLineSize( GetScrollBarLineSize() );
1761 Size
SvxIconChoiceCtrl_Impl::CalcBoundingSize() const
1763 return Size( CalcBoundingWidth(), CalcBoundingHeight() );
1766 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
1768 nMaxBoundHeight
= 0;
1769 maZOrderList
.clear();
1771 SvxIconChoiceCtrlEntry
* pEntry
;
1772 const size_t nCount
= maEntries
.size();
1774 if( !IsAutoArrange() || !pHead
)
1776 for( nCur
= 0; nCur
< nCount
; nCur
++ )
1778 pEntry
= maEntries
[ nCur
].get();
1779 if( IsBoundingRectValid( pEntry
->aRect
))
1781 Size
aBoundSize( pEntry
->aRect
.GetSize() );
1782 if( aBoundSize
.Height() > nMaxBoundHeight
)
1783 nMaxBoundHeight
= aBoundSize
.Height();
1786 FindBoundingRect( pEntry
);
1787 maZOrderList
.push_back( pEntry
);
1794 while( nCur
!= nCount
)
1796 DBG_ASSERT(pEntry
->pflink
&&pEntry
->pblink
,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
1797 if( IsBoundingRectValid( pEntry
->aRect
))
1799 Size
aBoundSize( pEntry
->aRect
.GetSize() );
1800 if( aBoundSize
.Height() > nMaxBoundHeight
)
1801 nMaxBoundHeight
= aBoundSize
.Height();
1804 FindBoundingRect( pEntry
);
1805 maZOrderList
.push_back( pEntry
);
1806 pEntry
= pEntry
->pflink
;
1813 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry
* pEntry
)
1815 DBG_ASSERT(!pEntry
->IsPosLocked(),"Locked entry pos in FindBoundingRect");
1816 if( pEntry
->IsPosLocked() && IsBoundingRectValid( pEntry
->aRect
) )
1818 AdjustVirtSize( pEntry
->aRect
);
1821 Size
aSize( CalcBoundingSize() );
1822 Point
aPos(pGridMap
->GetGridRect(pGridMap
->GetUnoccupiedGrid()).TopLeft());
1823 SetBoundingRect_Impl( pEntry
, aPos
, aSize
);
1826 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
1827 const Size
& /*rBoundingSize*/ )
1829 tools::Rectangle
aGridRect( rPos
, Size(nGridDX
, nGridDY
) );
1830 pEntry
->aGridRect
= aGridRect
;
1832 AdjustVirtSize( pEntry
->aRect
);
1833 pGridMap
->OccupyGrids( pEntry
);
1837 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry
* pEntry
)
1839 if( pEntry
== pCursor
)
1841 if( pCursor
&& eSelectionMode
== SelectionMode::Single
&&
1842 !pCursor
->IsSelected() )
1843 SelectEntry( pCursor
, true );
1846 ShowCursor( false );
1847 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
1851 pOldCursor
->ClearFlags( SvxIconViewFlags::FOCUSED
);
1852 if( eSelectionMode
== SelectionMode::Single
)
1853 SelectEntry( pOldCursor
, false ); // deselect old cursor
1858 pCursor
->SetFlags( SvxIconViewFlags::FOCUSED
);
1859 if( eSelectionMode
== SelectionMode::Single
)
1860 SelectEntry( pCursor
, true );
1866 void SvxIconChoiceCtrl_Impl::ShowCursor( bool bShow
)
1868 if( !pCursor
|| !bShow
|| !pView
->HasFocus() )
1873 tools::Rectangle
aRect ( CalcFocusRect( pCursor
) );
1874 /*pView->*/ShowFocus( aRect
);
1878 void SvxIconChoiceCtrl_Impl::HideDDIcon()
1883 Size
aSize( pDDDev
->GetOutputSizePixel() );
1885 pView
->DrawOutDev( Point(), aSize
, Point(), aSize
, *pDDDev
);
1891 bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent
& rCmd
)
1893 tools::Rectangle
aDocRect( Point(), aVirtOutputSize
);
1894 tools::Rectangle
aVisRect( GetOutputRect() );
1895 if( aVisRect
.IsInside( aDocRect
))
1897 Size
aDocSize( aDocRect
.GetSize() );
1898 Size
aVisSize( aVisRect
.GetSize() );
1899 bool bHor
= aDocSize
.Width() > aVisSize
.Width();
1900 bool bVer
= aDocSize
.Height() > aVisSize
.Height();
1902 long nScrollDX
= 0, nScrollDY
= 0;
1904 switch( rCmd
.GetCommand() )
1906 case CommandEventId::StartAutoScroll
:
1908 pView
->EndTracking();
1909 StartAutoScrollFlags nScrollFlags
= StartAutoScrollFlags::NONE
;
1911 nScrollFlags
|= StartAutoScrollFlags::Horz
;
1913 nScrollFlags
|= StartAutoScrollFlags::Vert
;
1914 if( nScrollFlags
!= StartAutoScrollFlags::NONE
)
1916 pView
->StartAutoScroll( nScrollFlags
);
1922 case CommandEventId::Wheel
:
1924 const CommandWheelData
* pData
= rCmd
.GetWheelData();
1925 if( pData
&& (CommandWheelMode::SCROLL
== pData
->GetMode()) && !pData
->IsHorz() )
1927 sal_uLong nScrollLines
= pData
->GetScrollLines();
1928 if( nScrollLines
== COMMAND_WHEEL_PAGESCROLL
)
1930 nScrollDY
= GetScrollBarPageSize( aVisSize
.Width() );
1931 if( pData
->GetDelta() < 0 )
1936 nScrollDY
= pData
->GetNotchDelta() * static_cast<long>(nScrollLines
);
1937 nScrollDY
*= GetScrollBarLineSize();
1943 case CommandEventId::AutoScroll
:
1945 const CommandScrollData
* pData
= rCmd
.GetAutoScrollData();
1948 nScrollDX
= pData
->GetDeltaX() * GetScrollBarLineSize();
1949 nScrollDY
= pData
->GetDeltaY() * GetScrollBarLineSize();
1957 if( nScrollDX
|| nScrollDY
)
1959 aVisRect
.AdjustTop( -nScrollDY
);
1960 aVisRect
.AdjustBottom( -nScrollDY
);
1961 aVisRect
.AdjustLeft( -nScrollDX
);
1962 aVisRect
.AdjustRight( -nScrollDX
);
1963 MakeVisible( aVisRect
);
1970 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent
& rCEvt
)
1972 // scroll mouse event?
1973 if( (rCEvt
.GetCommand() == CommandEventId::Wheel
) ||
1974 (rCEvt
.GetCommand() == CommandEventId::StartAutoScroll
) ||
1975 (rCEvt
.GetCommand() == CommandEventId::AutoScroll
) )
1977 if( HandleScrollCommand( rCEvt
) )
1982 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry
* pEntry
)
1984 if( maZOrderList
.empty() || pEntry
== maZOrderList
.back())
1987 auto it
= std::find(maZOrderList
.begin(), maZOrderList
.end(), pEntry
);
1988 if (it
!= maZOrderList
.end())
1990 maZOrderList
.erase( it
);
1991 maZOrderList
.push_back( pEntry
);
1995 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( tools::Rectangle
& rRect
) const
1997 if( rRect
.Bottom() >= aVirtOutputSize
.Height() )
1998 rRect
.SetBottom( aVirtOutputSize
.Height() - 1 );
1999 if( rRect
.Right() >= aVirtOutputSize
.Width() )
2000 rRect
.SetRight( aVirtOutputSize
.Width() - 1 );
2001 if( rRect
.Top() < 0 )
2003 if( rRect
.Left() < 0 )
2007 // rRect: area of the document (in document coordinates) that we want to make
2009 // bScrBar == true: rectangle was calculated because of a scrollbar event
2011 void SvxIconChoiceCtrl_Impl::MakeVisible( const tools::Rectangle
& rRect
, bool bScrBar
)
2013 tools::Rectangle
aVirtRect( rRect
);
2014 ClipAtVirtOutRect( aVirtRect
);
2015 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
2016 // convert to document coordinate
2018 tools::Rectangle
aOutputArea( GetOutputRect() );
2019 if( aOutputArea
.IsInside( aVirtRect
) )
2020 return; // is already visible
2023 if( aVirtRect
.Top() < aOutputArea
.Top() )
2025 // scroll up (nDy < 0)
2026 nDy
= aVirtRect
.Top() - aOutputArea
.Top();
2028 else if( aVirtRect
.Bottom() > aOutputArea
.Bottom() )
2030 // scroll down (nDy > 0)
2031 nDy
= aVirtRect
.Bottom() - aOutputArea
.Bottom();
2037 if( aVirtRect
.Left() < aOutputArea
.Left() )
2039 // scroll to the left (nDx < 0)
2040 nDx
= aVirtRect
.Left() - aOutputArea
.Left();
2042 else if( aVirtRect
.Right() > aOutputArea
.Right() )
2044 // scroll to the right (nDx > 0)
2045 nDx
= aVirtRect
.Right() - aOutputArea
.Right();
2050 aOrigin
.AdjustX(nDx
);
2051 aOrigin
.AdjustY(nDy
);
2052 aOutputArea
.SetPos( aOrigin
);
2053 if( GetUpdateMode() )
2057 ShowCursor( false );
2060 // invert origin for SV (so we can scroll/paint using document coordinates)
2062 SetOrigin( aOrigin
);
2064 bool bScrollable
= pView
->GetBackground().IsScrollable();
2066 if( bScrollable
&& GetUpdateMode() )
2068 // scroll in reverse direction!
2069 pView
->Control::Scroll( -nDx
, -nDy
, aOutputArea
,
2070 ScrollFlags::NoChildren
| ScrollFlags::UseClipRegion
| ScrollFlags::Clip
);
2073 pView
->Invalidate(InvalidateFlags::NoChildren
);
2075 if( aHorSBar
->IsVisible() || aVerSBar
->IsVisible() )
2081 if(aHorSBar
->IsVisible() && aHorSBar
->GetThumbPos() != aOrigin
.X())
2082 aHorSBar
->SetThumbPos( aOrigin
.X() );
2083 if(aVerSBar
->IsVisible() && aVerSBar
->GetThumbPos() != aOrigin
.Y())
2084 aVerSBar
->SetThumbPos( aOrigin
.Y() );
2088 if( GetUpdateMode() )
2091 // check if we still need scrollbars
2093 if( bScrollable
&& GetUpdateMode() )
2096 // If the requested area can not be made completely visible, the
2097 // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2098 // if only few pixels of the lower border are invisible, but a scrollbar has
2099 // a larger line size.
2103 sal_Int32
SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2105 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && pCurHighlightFrame
)
2107 return nSelectionCount
;
2110 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry
* pEntry
)
2113 bSel
= !pEntry
->IsSelected();
2114 SelectEntry( pEntry
, bSel
, true );
2117 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry
const * pThisEntryNot
)
2119 ClearSelectedRectList();
2121 // TODO: work through z-order list, if necessary!
2123 size_t nCount
= maEntries
.size();
2124 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2126 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2127 if( pEntry
!= pThisEntryNot
&& pEntry
->IsSelected() )
2128 SelectEntry( pEntry
, false, true );
2131 nFlags
&= ~IconChoiceFlags::AddMode
;
2134 Size
SvxIconChoiceCtrl_Impl::GetMinGrid() const
2136 Size
aMinSize( aImageSize
);
2137 aMinSize
.AdjustWidth(2 * LROFFS_BOUND
);
2138 aMinSize
.AdjustHeight(TBOFFS_BOUND
); // single offset is enough (FileDlg)
2139 OUString
const aStrDummy( "XXX" );
2140 Size
aTextSize( pView
->GetTextWidth( aStrDummy
), pView
->GetTextHeight() );
2141 if( nWinBits
& WB_ICON
)
2143 aMinSize
.AdjustHeight(VER_DIST_BMP_STRING
);
2144 aMinSize
.AdjustHeight(aTextSize
.Height() );
2148 aMinSize
.AdjustWidth(HOR_DIST_BMP_STRING
);
2149 aMinSize
.AdjustWidth(aTextSize
.Width() );
2154 void SvxIconChoiceCtrl_Impl::SetGrid( const Size
& rSize
)
2156 Size
aSize( rSize
);
2157 Size
aMinSize( GetMinGrid() );
2158 if( aSize
.Width() < aMinSize
.Width() )
2159 aSize
.setWidth( aMinSize
.Width() );
2160 if( aSize
.Height() < aMinSize
.Height() )
2161 aSize
.setHeight( aMinSize
.Height() );
2163 nGridDX
= aSize
.Width();
2164 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2165 // fly with a single column
2166 if( nWinBits
& WB_DETAILS
)
2168 const SvxIconChoiceCtrlColumnInfo
* pCol
= GetColumn( 0 );
2170 const_cast<SvxIconChoiceCtrlColumnInfo
*>(pCol
)->SetWidth( nGridDX
);
2172 nGridDY
= aSize
.Height();
2173 SetDefaultTextSize();
2176 // Calculates the maximum size that the text rectangle may use within its
2177 // bounding rectangle. In WB_ICON mode with SvxIconChoiceCtrlTextMode::Full, Bottom is set to
2180 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry
* pEntry
) const
2182 tools::Rectangle aBoundRect
;
2183 // avoid infinite recursion: don't calculate the bounding rectangle here
2184 if( IsBoundingRectValid( pEntry
->aRect
) )
2185 aBoundRect
= pEntry
->aRect
;
2187 aBoundRect
= pEntry
->aGridRect
;
2189 tools::Rectangle
aBmpRect( const_cast<SvxIconChoiceCtrl_Impl
*>(this)->CalcBmpRect(
2190 const_cast<SvxIconChoiceCtrlEntry
*>(pEntry
) ) );
2191 if( nWinBits
& WB_ICON
)
2193 aBoundRect
.SetTop( aBmpRect
.Bottom() );
2194 aBoundRect
.AdjustTop(VER_DIST_BMP_STRING
);
2195 if( aBoundRect
.Top() > aBoundRect
.Bottom())
2196 aBoundRect
.SetTop( aBoundRect
.Bottom() );
2197 aBoundRect
.AdjustLeft(LROFFS_BOUND
);
2198 aBoundRect
.AdjustLeft( 1 );
2199 aBoundRect
.AdjustRight( -(LROFFS_BOUND
) );
2200 aBoundRect
.AdjustRight( -1 );
2201 if( aBoundRect
.Left() > aBoundRect
.Right())
2202 aBoundRect
.SetLeft( aBoundRect
.Right() );
2203 if( pEntry
->GetTextMode() == SvxIconChoiceCtrlTextMode::Full
)
2204 aBoundRect
.SetBottom( LONG_MAX
);
2208 aBoundRect
.SetLeft( aBmpRect
.Right() );
2209 aBoundRect
.AdjustLeft(HOR_DIST_BMP_STRING
);
2210 aBoundRect
.AdjustRight( -(LROFFS_BOUND
) );
2211 if( aBoundRect
.Left() > aBoundRect
.Right() )
2212 aBoundRect
.SetLeft( aBoundRect
.Right() );
2213 long nHeight
= aBoundRect
.GetSize().Height();
2214 nHeight
= nHeight
- aDefaultTextSize
.Height();
2216 aBoundRect
.AdjustTop(nHeight
);
2217 aBoundRect
.AdjustBottom( -nHeight
);
2222 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2225 nDY
-= aImageSize
.Height();
2226 nDY
-= VER_DIST_BMP_STRING
;
2227 nDY
-= 2 * TBOFFS_BOUND
;
2232 nDX
-= 2 * LROFFS_BOUND
;
2237 long nHeight
= pView
->GetTextHeight();
2240 if(pView
->GetDPIScaleFactor() > 1)
2244 aDefaultTextSize
= Size(nDX
, nDY
);
2248 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry
* pEntry
) const
2250 pEntry
->aRect
= pEntry
->aGridRect
;
2251 Size
aSize( CalcBoundingSize() );
2252 if( nWinBits
& WB_ICON
)
2254 // center horizontally
2255 long nBorder
= pEntry
->aGridRect
.GetWidth() - aSize
.Width();
2256 pEntry
->aRect
.AdjustLeft(nBorder
/ 2 );
2257 pEntry
->aRect
.AdjustRight( -(nBorder
/ 2) );
2259 // center vertically
2260 pEntry
->aRect
.SetBottom( pEntry
->aRect
.Top() + aSize
.Height() );
2264 // The deltas are the offsets by which the view is moved on the document.
2265 // left, up: offsets < 0
2266 // right, down: offsets > 0
2267 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX
, long nDeltaY
)
2269 const MapMode
& rMapMode
= pView
->GetMapMode();
2270 Point
aOrigin( rMapMode
.GetOrigin() );
2271 // convert to document coordinate
2273 aOrigin
.AdjustY(nDeltaY
);
2274 aOrigin
.AdjustX(nDeltaX
);
2275 tools::Rectangle
aRect( aOrigin
, aOutputSize
);
2276 MakeVisible( aRect
, true/*bScrollBar*/ );
2280 const Size
& SvxIconChoiceCtrl_Impl::GetItemSize( IcnViewFieldType eItem
) const
2282 if (eItem
== IcnViewFieldType::Text
)
2283 return aDefaultTextSize
;
2284 return aImageSize
; // IcnViewFieldType::Image
2287 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry
* pEntry
)
2289 tools::Rectangle
aTextRect( CalcTextRect( pEntry
) );
2290 tools::Rectangle
aBoundRect( GetEntryBoundRect( pEntry
) );
2291 return tools::Rectangle(
2292 aBoundRect
.Left(), aBoundRect
.Top() - 1, aBoundRect
.Right() - 1,
2293 aTextRect
.Bottom() + 1);
2296 // the hot spot is the inner 50% of the rectangle
2297 static tools::Rectangle
GetHotSpot( const tools::Rectangle
& rRect
)
2299 tools::Rectangle
aResult( rRect
);
2301 Size
aSize( rRect
.GetSize() );
2302 long nDelta
= aSize
.Width() / 4;
2303 aResult
.AdjustLeft(nDelta
);
2304 aResult
.AdjustRight( -nDelta
);
2305 nDelta
= aSize
.Height() / 4;
2306 aResult
.AdjustTop(nDelta
);
2307 aResult
.AdjustBottom( -nDelta
);
2311 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry
* pEntry1
, SvxIconChoiceCtrlEntry
* pEntry2
,
2312 bool bAdd
, std::vector
<tools::Rectangle
>* pOtherRects
)
2314 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2315 tools::Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2316 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2317 SelectRect( aRect
, bAdd
, pOtherRects
);
2320 void SvxIconChoiceCtrl_Impl::SelectRect( const tools::Rectangle
& rRect
, bool bAdd
,
2321 std::vector
<tools::Rectangle
>* pOtherRects
)
2323 aCurSelectionRect
= rRect
;
2324 if( maZOrderList
.empty() )
2327 // set flag, so ToTop won't be called in Select
2328 bool bAlreadySelectingRect(nFlags
& IconChoiceFlags::SelectingRect
);
2329 nFlags
|= IconChoiceFlags::SelectingRect
;
2331 CheckBoundingRects();
2333 const size_t nCount
= maZOrderList
.size();
2335 tools::Rectangle
aRect( rRect
);
2337 bool bCalcOverlap
= (bAdd
&& pOtherRects
&& !pOtherRects
->empty());
2339 bool bResetClipRegion
= false;
2340 if( !pView
->IsClipRegion() )
2342 bResetClipRegion
= true;
2343 pView
->SetClipRegion(vcl::Region(GetOutputRect()));
2346 for( size_t nPos
= 0; nPos
< nCount
; nPos
++ )
2348 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nPos
];
2350 if( !IsBoundingRectValid( pEntry
->aRect
))
2351 FindBoundingRect( pEntry
);
2352 tools::Rectangle
aBoundRect( GetHotSpot( pEntry
->aRect
) );
2353 bool bSelected
= pEntry
->IsSelected();
2357 bOverlaps
= IsOver( pOtherRects
, aBoundRect
);
2360 bool bOver
= aRect
.IsOver( aBoundRect
);
2362 if( bOver
&& !bOverlaps
)
2364 // is inside the new selection rectangle and outside of any old one
2367 SelectEntry( pEntry
, true, true );
2371 // is outside of the selection rectangle
2374 SelectEntry( pEntry
, false, true );
2378 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2379 // selection rectangle.
2381 // There is still a bug here! The selection status of an entry in a
2382 // previous rectangle has to be restored, if it was touched by the
2383 // current selection rectangle but is not inside it any more.
2384 // For simplicity's sake, let's assume that all entries in the old
2385 // rectangles were correctly selected. It is wrong to just deselect
2386 // the intersection.
2387 // Possible solution: remember a snapshot of the selection before
2388 // spanning the rectangle.
2389 if( aBoundRect
.IsOver( rRect
))
2391 // deselect intersection between old rectangles and current rectangle
2393 SelectEntry( pEntry
, false, true );
2397 // select entry of an old rectangle
2399 SelectEntry( pEntry
, true, true );
2402 else if( !bOver
&& bSelected
)
2404 // this entry is completely outside the rectangle => deselect it
2405 SelectEntry( pEntry
, false, true );
2409 if( !bAlreadySelectingRect
)
2410 nFlags
&= ~IconChoiceFlags::SelectingRect
;
2413 if( bResetClipRegion
)
2414 pView
->SetClipRegion();
2417 void SvxIconChoiceCtrl_Impl::SelectRange(
2418 SvxIconChoiceCtrlEntry
const * pStart
,
2419 SvxIconChoiceCtrlEntry
const * pEnd
,
2422 sal_uLong nFront
= GetEntryListPos( pStart
);
2423 sal_uLong nBack
= GetEntryListPos( pEnd
);
2424 sal_uLong nFirst
= std::min( nFront
, nBack
);
2425 sal_uLong nLast
= std::max( nFront
, nBack
);
2427 SvxIconChoiceCtrlEntry
* pEntry
;
2431 // deselect everything before the first entry if not in
2433 for ( i
=0; i
<nFirst
; i
++ )
2435 pEntry
= GetEntry( i
);
2436 if( pEntry
->IsSelected() )
2437 SelectEntry( pEntry
, false, true );
2441 // select everything between nFirst and nLast
2442 for ( i
=nFirst
; i
<=nLast
; i
++ )
2444 pEntry
= GetEntry( i
);
2445 if( ! pEntry
->IsSelected() )
2446 SelectEntry( pEntry
, true, true );
2451 // deselect everything behind the last entry if not in
2453 sal_uLong nEnd
= GetEntryCount();
2454 for ( ; i
<nEnd
; i
++ )
2456 pEntry
= GetEntry( i
);
2457 if( pEntry
->IsSelected() )
2458 SelectEntry( pEntry
, false, true );
2463 bool SvxIconChoiceCtrl_Impl::IsOver( std::vector
<tools::Rectangle
>* pRectList
, const tools::Rectangle
& rBoundRect
)
2465 const sal_uInt16 nCount
= pRectList
->size();
2466 for( sal_uInt16 nCur
= 0; nCur
< nCount
; nCur
++ )
2468 tools::Rectangle
& rRect
= (*pRectList
)[ nCur
];
2469 if( rBoundRect
.IsOver( rRect
))
2475 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry
* pEntry1
,
2476 SvxIconChoiceCtrlEntry
* pEntry2
)
2478 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2479 tools::Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2480 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2481 AddSelectedRect( aRect
);
2484 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const tools::Rectangle
& rRect
)
2486 tools::Rectangle newRect
= rRect
;
2488 aSelectedRectList
.push_back( newRect
);
2491 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2493 aSelectedRectList
.clear();
2496 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, AutoArrangeHdl
, Timer
*, void)
2498 aAutoArrangeIdle
.Stop();
2499 Arrange( IsAutoArrange(), 0, 0 );
2502 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, VisRectChangedHdl
, Timer
*, void)
2504 aVisRectChangedIdle
.Stop();
2507 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, DocRectChangedHdl
, Timer
*, void)
2509 aDocRectChangedIdle
.Stop();
2513 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode
, SvxIconChoiceCtrlEntry
* pEntry
)
2517 if( eTextMode
!= eMode
)
2520 Arrange( true, 0, 0 );
2525 if( pEntry
->eTextMode
!= eMode
)
2527 pEntry
->eTextMode
= eMode
;
2528 InvalidateEntry( pEntry
);
2529 pView
->Invalidate( GetEntryBoundRect( pEntry
) );
2530 AdjustVirtSize( pEntry
->aRect
);
2536 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
2537 // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
2538 // a gray focusrect on a gray background !!!
2540 void SvxIconChoiceCtrl_Impl::ShowFocus ( tools::Rectangle
const & rRect
)
2542 Color
aBkgColor(pView
->GetBackground().GetColor());
2544 sal_uInt16 nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
2546 aPenColor
= COL_BLACK
;
2548 aPenColor
= COL_WHITE
;
2550 aFocus
.aPenColor
= aPenColor
;
2551 aFocus
.aRect
= rRect
;
2554 void SvxIconChoiceCtrl_Impl::DrawFocusRect(vcl::RenderContext
& rRenderContext
)
2556 rRenderContext
.SetLineColor(aFocus
.aPenColor
);
2557 rRenderContext
.SetFillColor();
2558 tools::Polygon
aPolygon (aFocus
.aRect
);
2560 LineInfo
aLineInfo(LineStyle::Dash
);
2562 aLineInfo
.SetDashLen(1);
2563 aLineInfo
.SetDotLen(1);
2564 aLineInfo
.SetDistance(1);
2565 aLineInfo
.SetDotCount(1);
2567 rRenderContext
.DrawPolyLine(aPolygon
, aLineInfo
);
2570 bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar
, sal_uLong
& rPos
) const
2573 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
2574 size_t nEntryCount
= GetEntryCount();
2575 for ( size_t i
= 0; i
< nEntryCount
; ++i
)
2577 if ( rI18nHelper
.MatchMnemonic( GetEntry( i
)->GetText(), cChar
) )
2589 IMPL_LINK(SvxIconChoiceCtrl_Impl
, UserEventHdl
, void*, nId
, void )
2591 if( nId
== EVENTID_ADJUST_SCROLLBARS
)
2593 nUserEventAdjustScrBars
= nullptr;
2596 else if( nId
== EVENTID_SHOW_CURSOR
)
2602 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
2604 if( nUserEventAdjustScrBars
)
2606 Application::RemoveUserEvent( nUserEventAdjustScrBars
);
2607 nUserEventAdjustScrBars
= nullptr;
2611 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry
* pEntry
)
2613 if( pEntry
== pCursor
)
2614 ShowCursor( false );
2615 pView
->Invalidate( pEntry
->aRect
);
2617 pView
->Invalidate( pEntry
->aRect
);
2618 if( pEntry
== pCursor
)
2622 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry() const
2624 if( !GetSelectionCount() )
2627 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && (eSelectionMode
== SelectionMode::NONE
) )
2629 return pCurHighlightFrame
;
2632 size_t nCount
= maEntries
.size();
2635 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2637 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2638 if( pEntry
->IsSelected() )
2646 SvxIconChoiceCtrlEntry
* pEntry
= pHead
;
2649 if( pEntry
->IsSelected() )
2653 pEntry
= pEntry
->pflink
;
2654 if( nCount
&& pEntry
== pHead
)
2656 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
2664 void SvxIconChoiceCtrl_Impl::SelectAll()
2666 size_t nCount
= maEntries
.size();
2667 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2669 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2670 SelectEntry( pEntry
, true/*bSelect*/, true );
2672 nFlags
&= ~IconChoiceFlags::AddMode
;
2679 sal_Int32
SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry
const * pEntry
) const
2681 if( !(nFlags
& IconChoiceFlags::EntryListPosValid
))
2682 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->SetListPositions();
2683 return pEntry
->nPos
;
2686 void SvxIconChoiceCtrl_Impl::InitSettings()
2688 const StyleSettings
& rStyleSettings
= pView
->GetSettings().GetStyleSettings();
2690 // unit (from settings) is Point
2691 vcl::Font
aFont( rStyleSettings
.GetFieldFont() );
2692 aFont
.SetColor( rStyleSettings
.GetWindowTextColor() );
2693 pView
->SetPointFont( aFont
);
2694 SetDefaultTextSize();
2696 pView
->SetTextColor( rStyleSettings
.GetFieldTextColor() );
2697 pView
->SetTextFillColor();
2699 pView
->SetBackground( rStyleSettings
.GetFieldColor());
2701 long nScrBarSize
= rStyleSettings
.GetScrollBarSize();
2702 if( nScrBarSize
== nHorSBarHeight
&& nScrBarSize
== nVerSBarWidth
)
2705 nHorSBarHeight
= nScrBarSize
;
2706 Size
aSize( aHorSBar
->GetSizePixel() );
2707 aSize
.setHeight( nScrBarSize
);
2709 aHorSBar
->SetSizePixel( aSize
);
2711 nVerSBarWidth
= nScrBarSize
;
2712 aSize
= aVerSBar
->GetSizePixel();
2713 aSize
.setWidth( nScrBarSize
);
2715 aVerSBar
->SetSizePixel( aSize
);
2717 Size
aOSize( pView
->Control::GetOutputSizePixel() );
2718 PositionScrollBars( aOSize
.Width(), aOSize
.Height() );
2722 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode
)
2724 if( eMode
== ePositionMode
)
2727 SvxIconChoiceCtrlPositionMode eOldMode
= ePositionMode
;
2728 ePositionMode
= eMode
;
2729 size_t nCount
= maEntries
.size();
2731 if( eOldMode
== SvxIconChoiceCtrlPositionMode::AutoArrange
)
2733 // when positioning moved entries "hard", there are problems with
2734 // unwanted overlaps, as these entries aren't taken into account in
2736 if( maEntries
.size() )
2737 aAutoArrangeIdle
.Start();
2741 if( ePositionMode
== SvxIconChoiceCtrlPositionMode::AutoArrange
)
2743 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2745 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2746 if( pEntry
->GetFlags() & SvxIconViewFlags(SvxIconViewFlags::POS_LOCKED
| SvxIconViewFlags::POS_MOVED
))
2747 SetEntryPos(pEntry
, GetEntryBoundRect( pEntry
).TopLeft());
2750 if( maEntries
.size() )
2751 aAutoArrangeIdle
.Start();
2755 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
2756 SvxIconChoiceCtrlEntry
* pPredecessor
)
2758 if( !IsAutoArrange() )
2761 if( pEntry
== pPredecessor
)
2764 sal_uLong nPos1
= GetEntryListPos( pEntry
);
2769 sal_uLong nPos2
= GetEntryListPos( pPredecessor
);
2770 if( nPos1
== (nPos2
+ 1) )
2771 return; // is already the predecessor
2779 if( !pPredecessor
&& pHead
== pEntry
)
2780 return; // is already the first one
2782 bool bSetHead
= false;
2786 pPredecessor
= pHead
->pblink
;
2788 if( pEntry
== pHead
)
2790 pHead
= pHead
->pflink
;
2793 if( pEntry
!= pPredecessor
)
2796 pEntry
->SetBacklink( pPredecessor
);
2800 aAutoArrangeIdle
.Start();
2803 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
2804 const Point
& rPosTopLeft
)
2806 Point
aPos( rPosTopLeft
); //TopLeft
2807 tools::Rectangle
aCenterRect( CalcBmpRect( pEntry
, &aPos
));
2808 Point
aNewPos( aCenterRect
.Center() );
2809 sal_uLong nGrid
= GetPredecessorGrid( aNewPos
);
2810 size_t nCount
= maEntries
.size();
2811 if( nGrid
== ULONG_MAX
)
2813 if( nGrid
>= nCount
)
2816 return maEntries
[ nGrid
].get();
2818 SvxIconChoiceCtrlEntry
* pCur
= pHead
; // Grid 0
2819 // TODO: go through list from the end if nGrid > nCount/2
2820 for( sal_uLong nCur
= 0; nCur
< nGrid
; nCur
++ )
2821 pCur
= pCur
->pflink
;
2826 sal_uLong
SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point
& rPos
) const
2829 aPos
.AdjustX( -(LROFFS_WINBORDER
) );
2830 aPos
.AdjustY( -(TBOFFS_WINBORDER
) );
2831 long nMaxCol
= aVirtOutputSize
.Width() / nGridDX
;
2834 long nGridX
= aPos
.X() / nGridDX
;
2835 if( nGridX
> nMaxCol
)
2837 long nGridY
= aPos
.Y() / nGridDY
;
2838 long nGridsX
= aOutputSize
.Width() / nGridDX
;
2839 sal_uLong nGrid
= (nGridY
* nGridsX
) + nGridX
;
2840 long nMiddle
= (nGridX
* nGridDX
) + (nGridDX
/ 2);
2841 if( rPos
.X() < nMiddle
)
2851 bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent
& rHEvt
)
2853 if ( !(rHEvt
.GetMode() & HelpEventMode::QUICK
) )
2856 Point
aPos( pView
->ScreenToOutputPixel(rHEvt
.GetMousePosPixel() ) );
2857 aPos
-= pView
->GetMapMode().GetOrigin();
2858 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aPos
, true );
2863 OUString sQuickHelpText
= pEntry
->GetQuickHelpText();
2864 OUString
aEntryText( SvtIconChoiceCtrl::GetEntryText( pEntry
) );
2865 tools::Rectangle
aTextRect( CalcTextRect( pEntry
, nullptr, &aEntryText
) );
2866 if ( ( !aTextRect
.IsInside( aPos
) || aEntryText
.isEmpty() ) && sQuickHelpText
.isEmpty() )
2869 tools::Rectangle
aOptTextRect( aTextRect
);
2870 aOptTextRect
.SetBottom( LONG_MAX
);
2871 DrawTextFlags nNewFlags
= nCurTextDrawFlags
;
2872 nNewFlags
&= ~DrawTextFlags( DrawTextFlags::Clip
| DrawTextFlags::EndEllipsis
);
2873 aOptTextRect
= pView
->GetTextRect( aOptTextRect
, aEntryText
, nNewFlags
);
2874 if ( aOptTextRect
!= aTextRect
|| !sQuickHelpText
.isEmpty() )
2876 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
2877 Point
aPt( aOptTextRect
.TopLeft() );
2878 aPt
+= pView
->GetMapMode().GetOrigin();
2879 aPt
= pView
->OutputToScreenPixel( aPt
);
2880 // subtract border of tooltip help
2883 aOptTextRect
.SetPos( aPt
);
2885 if ( !sQuickHelpText
.isEmpty() )
2886 sHelpText
= sQuickHelpText
;
2888 sHelpText
= aEntryText
;
2889 Help::ShowQuickHelp( static_cast<vcl::Window
*>(pView
), aOptTextRect
, sHelpText
, QuickHelpFlags::Left
| QuickHelpFlags::VCenter
);
2895 void SvxIconChoiceCtrl_Impl::ClearColumnList()
2900 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex
, const SvxIconChoiceCtrlColumnInfo
& rInfo
)
2903 m_pColumns
.reset(new SvxIconChoiceCtrlColumnInfoMap
);
2905 SvxIconChoiceCtrlColumnInfo
* pInfo
= new SvxIconChoiceCtrlColumnInfo( rInfo
);
2906 m_pColumns
->insert(std::make_pair(nIndex
, std::unique_ptr
<SvxIconChoiceCtrlColumnInfo
>(pInfo
)));
2908 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2909 // fly with a single column
2910 if( !nIndex
&& (nWinBits
& WB_DETAILS
) )
2911 nGridDX
= pInfo
->GetWidth();
2913 if( GetUpdateMode() )
2914 Arrange( IsAutoArrange(), 0, 0 );
2917 const SvxIconChoiceCtrlColumnInfo
* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex
) const
2921 auto const it
= m_pColumns
->find( nIndex
);
2922 if (it
== m_pColumns
->end())
2924 return it
->second
.get();
2927 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rBmpRect
)
2929 tools::Rectangle
aBmpRect(rBmpRect
);
2931 if (aImageSize
.Width() < 32)
2933 aBmpRect
.AdjustRight(nBorder
);
2934 aBmpRect
.AdjustLeft( -nBorder
);
2935 aBmpRect
.AdjustBottom(nBorder
);
2936 aBmpRect
.AdjustTop( -nBorder
);
2938 DecorationView
aDecoView(&rRenderContext
);
2939 DrawHighlightFrameStyle nDecoFlags
;
2940 if (bHighlightFramePressed
)
2941 nDecoFlags
= DrawHighlightFrameStyle::In
;
2943 nDecoFlags
= DrawHighlightFrameStyle::Out
;
2944 aDecoView
.DrawHighlightFrame(aBmpRect
, nDecoFlags
);
2947 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry
* pEntry
,
2948 bool bKeepHighlightFlags
)
2950 if( pEntry
== pCurHighlightFrame
)
2953 if( !bKeepHighlightFlags
)
2954 bHighlightFramePressed
= false;
2956 if (pCurHighlightFrame
)
2958 tools::Rectangle
aInvalidationRect(GetEntryBoundRect(pCurHighlightFrame
));
2959 aInvalidationRect
.expand(5);
2960 pCurHighlightFrame
= nullptr;
2961 pView
->Invalidate(aInvalidationRect
);
2964 pCurHighlightFrame
= pEntry
;
2967 tools::Rectangle
aInvalidationRect(GetEntryBoundRect(pEntry
));
2968 aInvalidationRect
.expand(5);
2969 pView
->Invalidate(aInvalidationRect
);
2973 void SvxIconChoiceCtrl_Impl::CallSelectHandler()
2975 // When single-click mode is active, the selection handler should be called
2976 // synchronously, as the selection is automatically taken away once the
2977 // mouse cursor doesn't touch the object any more. Else, we might run into
2978 // missing calls to Select if the object is selected from a mouse movement,
2979 // because when starting the timer, the mouse cursor might have already left
2981 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
2982 // WB_NOASYNCSELECTHDL.
2983 if( nWinBits
& (WB_NOASYNCSELECTHDL
| WB_HIGHLIGHTFRAME
) )
2985 pHdlEntry
= nullptr;
2990 aCallSelectHdlIdle
.Start();
2993 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, CallSelectHdlHdl
, Timer
*, void)
2995 pHdlEntry
= nullptr;
3000 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point
& rPos
)
3002 MapMode
aMapMode( pView
->GetMapMode() );
3003 aMapMode
.SetOrigin( rPos
);
3004 pView
->SetMapMode( aMapMode
);
3007 void SvxIconChoiceCtrl_Impl::CallEventListeners( VclEventId nEvent
, void* pData
)
3009 pView
->CallImplEventListeners( nEvent
, pData
);
3013 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */