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/event.hxx>
28 #include <vcl/svapp.hxx>
29 #include <tools/poly.hxx>
30 #include <vcl/lineinfo.hxx>
31 #include <vcl/i18nhelp.hxx>
32 #include <vcl/mnemonic.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/commandevent.hxx>
36 #include <vcl/toolkit/ivctrl.hxx>
37 #include "imivctl.hxx"
41 #include <vcl/idle.hxx>
43 constexpr auto DRAWTEXT_FLAGS_ICON
=
44 DrawTextFlags::Center
| DrawTextFlags::Top
| DrawTextFlags::EndEllipsis
|
45 DrawTextFlags::Clip
| DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
| DrawTextFlags::Mnemonic
;
47 #define DRAWTEXT_FLAGS_SMALLICON (DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags::Clip)
49 #define EVENTID_SHOW_CURSOR (reinterpret_cast<void*>(1))
50 #define EVENTID_ADJUST_SCROLLBARS (reinterpret_cast<void*>(2))
52 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
53 SvtIconChoiceCtrl
* pCurView
,
56 aVerSBar( VclPtr
<ScrollBar
>::Create(pCurView
, WB_DRAG
| WB_VSCROLL
) ),
57 aHorSBar( VclPtr
<ScrollBar
>::Create(pCurView
, WB_DRAG
| WB_HSCROLL
) ),
58 aScrBarBox( VclPtr
<ScrollBarBox
>::Create(pCurView
) ),
59 aAutoArrangeIdle ( "svtools contnr SvxIconChoiceCtrl_Impl AutoArrange" ),
60 aDocRectChangedIdle ( "svtools contnr SvxIconChoiceCtrl_Impl DocRectChanged" ),
61 aVisRectChangedIdle ( "svtools contnr SvxIconChoiceCtrl_Impl VisRectChanged" ),
62 aCallSelectHdlIdle ( "svtools contnr SvxIconChoiceCtrl_Impl CallSelectHdl" ),
63 aImageSize( 32 * pCurView
->GetDPIScaleFactor(), 32 * pCurView
->GetDPIScaleFactor()),
64 pView(pCurView
), nMaxVirtWidth(DEFAULT_MAX_VIRT_WIDTH
), nMaxVirtHeight(DEFAULT_MAX_VIRT_HEIGHT
),
65 nFlags(IconChoiceFlags::NONE
), nUserEventAdjustScrBars(nullptr),
66 pCurHighlightFrame(nullptr), bHighlightFramePressed(false), pHead(nullptr), pCursor(nullptr),
68 pAnchor(nullptr), eTextMode(SvxIconChoiceCtrlTextMode::Short
),
69 eSelectionMode(SelectionMode::Multiple
), ePositionMode(SvxIconChoiceCtrlPositionMode::Free
),
72 SetStyle( nWinStyle
);
73 pImpCursor
.reset( new IcnCursor_Impl( this ) );
74 pGridMap
.reset( new IcnGridMap_Impl( this ) );
76 aVerSBar
->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
) );
77 aHorSBar
->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
) );
79 nHorSBarHeight
= aHorSBar
->GetSizePixel().Height();
80 nVerSBarWidth
= aVerSBar
->GetSizePixel().Width();
82 aAutoArrangeIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
83 aAutoArrangeIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,AutoArrangeHdl
));
84 aAutoArrangeIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aAutoArrangeIdle" );
86 aCallSelectHdlIdle
.SetPriority( TaskPriority::LOWEST
);
87 aCallSelectHdlIdle
.SetInvokeHandler( LINK(this,SvxIconChoiceCtrl_Impl
,CallSelectHdlHdl
));
88 aCallSelectHdlIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aCallSelectHdlIdle" );
90 aDocRectChangedIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
91 aDocRectChangedIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,DocRectChangedHdl
));
92 aDocRectChangedIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" );
94 aVisRectChangedIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
95 aVisRectChangedIdle
.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl
,VisRectChangedHdl
));
96 aVisRectChangedIdle
.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" );
99 Size
gridSize(100,70);
100 if(pView
->GetDPIScaleFactor() > 1)
102 gridSize
.setHeight( gridSize
.Height() * ( pView
->GetDPIScaleFactor()) );
107 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
113 ClearSelectedRectList();
115 aVerSBar
.disposeAndClear();
116 aHorSBar
.disposeAndClear();
117 aScrBarBox
.disposeAndClear();
120 void SvxIconChoiceCtrl_Impl::Clear( bool bInCtor
)
123 pCurHighlightFrame
= nullptr;
126 bBoundRectsDirty
= false;
134 aVirtOutputSize
.setWidth( 0 );
135 aVirtOutputSize
.setHeight( 0 );
136 Size
aSize( pView
->GetOutputSizePixel() );
137 nMaxVirtWidth
= aSize
.Width() - nVerSBarWidth
;
138 if( nMaxVirtWidth
<= 0 )
139 nMaxVirtWidth
= DEFAULT_MAX_VIRT_WIDTH
;
140 nMaxVirtHeight
= aSize
.Height() - nHorSBarHeight
;
141 if( nMaxVirtHeight
<= 0 )
142 nMaxVirtHeight
= DEFAULT_MAX_VIRT_HEIGHT
;
143 maZOrderList
.clear();
144 SetOrigin( Point() );
146 pView
->Invalidate(InvalidateFlags::NoChildren
);
154 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle
)
156 nWinBits
= nWinStyle
;
157 nCurTextDrawFlags
= DRAWTEXT_FLAGS_ICON
;
158 if( nWinBits
& (WB_SMALLICON
| WB_DETAILS
) )
159 nCurTextDrawFlags
= DRAWTEXT_FLAGS_SMALLICON
;
160 if( nWinBits
& WB_NOSELECTION
)
161 eSelectionMode
= SelectionMode::NONE
;
162 if( !(nWinStyle
& (WB_ALIGN_TOP
| WB_ALIGN_LEFT
)))
163 nWinBits
|= WB_ALIGN_LEFT
;
164 if( nWinStyle
& WB_DETAILS
)
167 SetColumn( 0, SvxIconChoiceCtrlColumnInfo() );
171 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollUpDownHdl
, ScrollBar
*, pScrollBar
, void )
173 // arrow up: delta=-1; arrow down: delta=+1
174 Scroll( 0, pScrollBar
->GetDelta() );
177 IMPL_LINK( SvxIconChoiceCtrl_Impl
, ScrollLeftRightHdl
, ScrollBar
*, pScrollBar
, void )
179 // arrow left: delta=-1; arrow right: delta=+1
180 Scroll( pScrollBar
->GetDelta(), 0 );
183 void SvxIconChoiceCtrl_Impl::FontModified()
185 SetDefaultTextSize();
190 void SvxIconChoiceCtrl_Impl::InsertEntry( std::unique_ptr
<SvxIconChoiceCtrlEntry
> pEntry1
, size_t nPos
)
192 auto pEntry
= pEntry1
.get();
194 if ( nPos
< maEntries
.size() ) {
195 maEntries
.insert( maEntries
.begin() + nPos
, std::move(pEntry1
) );
197 maEntries
.push_back( std::move(pEntry1
) );
201 pEntry
->SetBacklink( pHead
->pblink
);
203 if( (nFlags
& IconChoiceFlags::EntryListPosValid
) && nPos
>= maEntries
.size() - 1 )
204 pEntry
->nPos
= maEntries
.size() - 1;
206 nFlags
&= ~IconChoiceFlags::EntryListPosValid
;
208 maZOrderList
.push_back( pEntry
);
211 // If the UpdateMode is true, don't set all bounding rectangles to
212 // 'to be checked', but only the bounding rectangle of the new entry.
213 // Thus, don't call InvalidateBoundingRect!
214 pEntry
->aRect
.SetRight( LONG_MAX
);
217 FindBoundingRect( pEntry
);
218 tools::Rectangle
aOutputArea( GetOutputRect() );
219 pGridMap
->OccupyGrids( pEntry
);
220 if( !aOutputArea
.IsOver( pEntry
->aRect
) )
221 return; // is invisible
222 pView
->Invalidate( pEntry
->aRect
);
225 InvalidateBoundingRect( pEntry
->aRect
);
228 void SvxIconChoiceCtrl_Impl::RemoveEntry(size_t nPos
)
231 maEntries
.erase(maEntries
.begin() + nPos
);
232 RecalcAllBoundingRectsSmart();
235 tools::Rectangle
SvxIconChoiceCtrl_Impl::GetOutputRect() const
237 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
239 return tools::Rectangle( aOrigin
, aOutputSize
);
242 void SvxIconChoiceCtrl_Impl::SetListPositions()
244 if( nFlags
& IconChoiceFlags::EntryListPosValid
)
247 size_t nCount
= maEntries
.size();
248 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
250 maEntries
[ nCur
]->nPos
= nCur
;
252 nFlags
|= IconChoiceFlags::EntryListPosValid
;
255 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry
* pEntry
, bool bSelect
,
258 if( eSelectionMode
== SelectionMode::NONE
)
263 if ( !( nFlags
& IconChoiceFlags::ClearingSelection
) )
265 nFlags
|= IconChoiceFlags::ClearingSelection
;
266 DeselectAllBut( pEntry
);
267 nFlags
&= ~IconChoiceFlags::ClearingSelection
;
270 if( pEntry
->IsSelected() == bSelect
)
274 SvxIconViewFlags nEntryFlags
= pEntry
->GetFlags();
277 nEntryFlags
|= SvxIconViewFlags::SELECTED
;
278 pEntry
->AssignFlags( nEntryFlags
);
284 nEntryFlags
&= ~SvxIconViewFlags::SELECTED
;
285 pEntry
->AssignFlags( nEntryFlags
);
289 EntrySelected( pEntry
, bSelect
);
292 void SvxIconChoiceCtrl_Impl::EntrySelected(SvxIconChoiceCtrlEntry
* pEntry
, bool bSelect
)
294 // When using SingleSelection, make sure that the cursor is always placed
295 // over the (only) selected entry. (But only if a cursor exists.)
296 if (bSelect
&& pCursor
&&
297 eSelectionMode
== SelectionMode::Single
&&
303 // Not when dragging though, else the loop in SelectRect doesn't work
305 if (!(nFlags
& IconChoiceFlags::SelectingRect
))
309 if (pEntry
== pCursor
)
311 pView
->Invalidate(CalcFocusRect(pEntry
));
312 if (pEntry
== pCursor
)
316 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
319 CallEventListeners(VclEventId::ListboxSelect
, pEntry
);
323 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
325 aVirtOutputSize
.setWidth( 0 );
326 aVirtOutputSize
.setHeight( 0 );
327 const size_t nCount
= maEntries
.size();
328 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
330 SvxIconChoiceCtrlEntry
* pCur
= maEntries
[ nCur
].get();
331 pCur
->ClearFlags( SvxIconViewFlags::POS_MOVED
);
332 if( pCur
->IsPosLocked() )
334 // adapt (among others) VirtSize
335 if( !IsBoundingRectValid( pCur
->aRect
) )
336 FindBoundingRect( pCur
);
338 AdjustVirtSize( pCur
->aRect
);
341 InvalidateBoundingRect( pCur
->aRect
);
344 if( !(nWinBits
& (WB_NOVSCROLL
| WB_NOHSCROLL
)) )
346 Size
aRealOutputSize( pView
->GetOutputSizePixel() );
347 if( aVirtOutputSize
.Width() < aRealOutputSize
.Width() ||
348 aVirtOutputSize
.Height() < aRealOutputSize
.Height() )
350 sal_uLong nGridCount
= IcnGridMap_Impl::GetGridCount(
351 aRealOutputSize
, static_cast<sal_uInt16
>(nGridDX
), static_cast<sal_uInt16
>(nGridDY
) );
352 if( nGridCount
< nCount
)
354 if( nWinBits
& WB_ALIGN_TOP
)
355 nMaxVirtWidth
= aRealOutputSize
.Width() - nVerSBarWidth
;
356 else // WB_ALIGN_LEFT
357 nMaxVirtHeight
= aRealOutputSize
.Height() - nHorSBarHeight
;
367 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const tools::Rectangle
& rRect
)
369 tools::Long nHeightOffs
= 0;
370 tools::Long nWidthOffs
= 0;
372 if( aVirtOutputSize
.Width() < (rRect
.Right()+LROFFS_WINBORDER
) )
373 nWidthOffs
= (rRect
.Right()+LROFFS_WINBORDER
) - aVirtOutputSize
.Width();
375 if( aVirtOutputSize
.Height() < (rRect
.Bottom()+TBOFFS_WINBORDER
) )
376 nHeightOffs
= (rRect
.Bottom()+TBOFFS_WINBORDER
) - aVirtOutputSize
.Height();
378 if( !(nWidthOffs
|| nHeightOffs
) )
382 aVirtOutputSize
.AdjustWidth(nWidthOffs
);
383 aRange
.Max() = aVirtOutputSize
.Width();
384 aHorSBar
->SetRange( aRange
);
386 aVirtOutputSize
.AdjustHeight(nHeightOffs
);
387 aRange
.Max() = aVirtOutputSize
.Height();
388 aVerSBar
->SetRange( aRange
);
391 pGridMap
->OutputSizeChanged();
396 void SvxIconChoiceCtrl_Impl::InitPredecessors()
398 DBG_ASSERT(!pHead
,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
399 size_t nCount
= maEntries
.size();
402 SvxIconChoiceCtrlEntry
* pPrev
= maEntries
[ 0 ].get();
403 for( size_t nCur
= 1; nCur
<= nCount
; nCur
++ )
405 pPrev
->ClearFlags( SvxIconViewFlags::POS_LOCKED
| SvxIconViewFlags::POS_MOVED
);
407 SvxIconChoiceCtrlEntry
* pNext
;
409 pNext
= maEntries
[ 0 ].get();
411 pNext
= maEntries
[ nCur
].get();
412 pPrev
->pflink
= pNext
;
413 pNext
->pblink
= pPrev
;
416 pHead
= maEntries
[ 0 ].get();
422 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
426 size_t nCount
= maEntries
.size();
427 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
429 SvxIconChoiceCtrlEntry
* pCur
= maEntries
[ nCur
].get();
430 pCur
->pflink
= nullptr;
431 pCur
->pblink
= nullptr;
437 void SvxIconChoiceCtrl_Impl::Arrange( bool bKeepPredecessors
, tools::Long nSetMaxVirtWidth
, tools::Long nSetMaxVirtHeight
)
439 if ( nSetMaxVirtWidth
!= 0 )
440 nMaxVirtWidth
= nSetMaxVirtWidth
;
442 nMaxVirtWidth
= aOutputSize
.Width();
444 if ( nSetMaxVirtHeight
!= 0 )
445 nMaxVirtHeight
= nSetMaxVirtHeight
;
447 nMaxVirtHeight
= aOutputSize
.Height();
449 ImpArrange( bKeepPredecessors
);
452 void SvxIconChoiceCtrl_Impl::ImpArrange( bool bKeepPredecessors
)
454 static Point aEmptyPoint
;
456 bool bOldUpdate
= bUpdateMode
;
457 tools::Rectangle
aCurOutputArea( GetOutputRect() );
458 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
460 aAutoArrangeIdle
.Stop();
461 nFlags
|= IconChoiceFlags::Arranging
;
464 if( !bKeepPredecessors
)
466 bBoundRectsDirty
= false;
467 SetOrigin( Point() );
469 RecalcAllBoundingRectsSmart();
470 // TODO: the invalidation in the detail view should be more intelligent
471 //if( !(nWinBits & WB_DETAILS ))
472 pView
->Invalidate( InvalidateFlags::NoChildren
);
473 nFlags
&= ~IconChoiceFlags::Arranging
;
474 if( (nWinBits
& WB_SMART_ARRANGE
) && aCurOutputArea
.TopLeft() != aEmptyPoint
)
476 MakeVisible( aCurOutputArea
);
477 SetUpdateMode( bOldUpdate
);
482 void SvxIconChoiceCtrl_Impl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
484 #if defined(OV_DRAWGRID)
485 Color
aOldColor (rRenderContext
.GetLineColor());
487 rRenderContext
.SetLineColor( aColor
);
488 Point
aOffs(rRenderContext
.GetMapMode().GetOrigin());
489 Size
aXSize(GetOutputSizePixel());
491 Point
aStart(LROFFS_WINBORDER
, 0);
492 Point
aEnd(LROFFS_WINBORDER
, aXSize
.Height());
495 rRenderContext
.DrawLine(aStart
, aEnd
);
498 Point
aStart(0, TBOFFS_WINBORDER
);
499 Point
aEnd(aXSize
.Width(), TBOFFS_WINBORDER
);
502 rRenderContext
.DrawLine(aStart
, aEnd
);
505 for (tools::Long nDX
= nGridDX
; nDX
<= aXSize
.Width(); nDX
+= nGridDX
)
507 Point
aStart( nDX
+LROFFS_WINBORDER
, 0 );
508 Point
aEnd( nDX
+LROFFS_WINBORDER
, aXSize
.Height());
511 rRenderContext
.DrawLine(aStart
, aEnd
);
513 for (tools::Long nDY
= nGridDY
; nDY
<= aXSize
.Height(); nDY
+= nGridDY
)
515 Point
aStart(0, nDY
+ TBOFFS_WINBORDER
);
516 Point
aEnd(aXSize
.Width(), nDY
+ TBOFFS_WINBORDER
);
519 rRenderContext
.DrawLine(aStart
, aEnd
);
521 rRenderContext
.SetLineColor(aOldColor
);
524 if (!maEntries
.size())
528 // set cursor to item with focus-flag
530 for (sal_Int32 i
= 0; i
< pView
->GetEntryCount() && !bfound
; i
++)
532 SvxIconChoiceCtrlEntry
* pEntry
= pView
->GetEntry(i
);
533 if (pEntry
->IsFocused())
541 pCursor
= maEntries
[ 0 ].get();
544 size_t nCount
= maZOrderList
.size();
548 rRenderContext
.Push(PushFlags::CLIPREGION
);
549 rRenderContext
.SetClipRegion(vcl::Region(rRect
));
551 std::vector
< SvxIconChoiceCtrlEntry
* > aNewZOrderList
;
552 std::vector
< SvxIconChoiceCtrlEntry
* > aPaintedEntries
;
557 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[nPos
];
558 const tools::Rectangle
& rBoundRect
= GetEntryBoundRect(pEntry
);
559 if (rRect
.IsOver(rBoundRect
))
561 PaintEntry(pEntry
, rBoundRect
.TopLeft(), rRenderContext
);
562 // set entries to Top if they are being repainted
563 aPaintedEntries
.push_back(pEntry
);
566 aNewZOrderList
.push_back(pEntry
);
571 maZOrderList
= std::move( aNewZOrderList
);
572 maZOrderList
.insert(maZOrderList
.end(), aPaintedEntries
.begin(), aPaintedEntries
.end());
574 rRenderContext
.Pop();
577 void SvxIconChoiceCtrl_Impl::RepaintSelectedEntries()
579 const size_t nCount
= maZOrderList
.size();
583 tools::Rectangle
aOutRect(GetOutputRect());
584 for (size_t nCur
= 0; nCur
< nCount
; nCur
++)
586 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[nCur
];
587 if (pEntry
->GetFlags() & SvxIconViewFlags::SELECTED
)
589 const tools::Rectangle
& rBoundRect
= GetEntryBoundRect(pEntry
);
590 if (aOutRect
.IsOver(rBoundRect
))
591 pView
->Invalidate(rBoundRect
);
596 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
598 aScrBarBox
->SetSizePixel( Size(nVerSBarWidth
-1, nHorSBarHeight
-1) );
599 Size
aSize( pView
->GetOutputSizePixel() );
600 aScrBarBox
->SetPosPixel( Point(aSize
.Width()-nVerSBarWidth
+1, aSize
.Height()-nHorSBarHeight
+1));
603 bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent
& rMEvt
)
605 bool bHandled
= true;
606 bHighlightFramePressed
= false;
607 bool bGotFocus
= (!pView
->HasFocus() && !(nWinBits
& WB_NOPOINTERFOCUS
));
608 if( !(nWinBits
& WB_NOPOINTERFOCUS
) )
611 Point
aDocPos( rMEvt
.GetPosPixel() );
612 if(aDocPos
.X()>=aOutputSize
.Width() || aDocPos
.Y()>=aOutputSize
.Height())
615 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, true );
617 MakeEntryVisible( pEntry
, false );
619 if( rMEvt
.IsShift() && eSelectionMode
!= SelectionMode::Single
)
622 SetCursor_Impl( pCursor
, pEntry
, rMEvt
.IsMod1(), rMEvt
.IsShift() );
626 if( pAnchor
&& (rMEvt
.IsShift() || rMEvt
.IsMod1())) // keyboard selection?
628 DBG_ASSERT(eSelectionMode
!= SelectionMode::Single
,"Invalid selection mode");
630 nFlags
|= IconChoiceFlags::AddMode
;
632 if( rMEvt
.IsShift() )
634 tools::Rectangle
aRect( GetEntryBoundRect( pAnchor
));
636 aRect
.Union( GetEntryBoundRect( pEntry
) );
639 tools::Rectangle
aTempRect( aDocPos
, Size(1,1));
640 aRect
.Union( aTempRect
);
642 aCurSelectionRect
= aRect
;
643 SelectRect( aRect
, bool(nFlags
& IconChoiceFlags::AddMode
), &aSelectedRectList
);
645 else if( rMEvt
.IsMod1() )
647 AddSelectedRect( aCurSelectionRect
);
649 aCurSelectionRect
.SetPos( aDocPos
);
652 if( !pEntry
&& !(nWinBits
& WB_NODRAGSELECTION
))
653 pView
->StartTracking( StartTrackingFlags::ScrollRepeat
);
660 if( eSelectionMode
== SelectionMode::Multiple
)
662 if( !rMEvt
.IsMod1() ) // Ctrl
667 ClearSelectedRectList();
671 nFlags
|= IconChoiceFlags::AddMode
;
672 aCurSelectionRect
.SetPos( aDocPos
);
673 pView
->StartTracking( StartTrackingFlags::ScrollRepeat
);
680 bool bSelected
= pEntry
->IsSelected();
682 if( rMEvt
.GetClicks() == 2 )
684 DeselectAllBut( pEntry
);
685 SelectEntry( pEntry
, true, false );
692 if( rMEvt
.IsMod2() ) // Alt?
695 else if( eSelectionMode
== SelectionMode::Single
)
697 DeselectAllBut( pEntry
);
700 else if( eSelectionMode
== SelectionMode::NONE
)
702 if( rMEvt
.IsLeft() && (nWinBits
& WB_HIGHLIGHTFRAME
) )
704 pCurHighlightFrame
= nullptr; // force repaint of frame
705 bHighlightFramePressed
= true;
706 SetEntryHighlightFrame( pEntry
, true );
711 if( !rMEvt
.GetModifier() && rMEvt
.IsLeft() )
715 DeselectAllBut( pEntry
);
717 SelectEntry( pEntry
, true, false );
721 // deselect only in the Up, if the Move happened via D&D!
722 nFlags
|= IconChoiceFlags::DownDeselect
;
725 else if( rMEvt
.IsMod1() )
726 nFlags
|= IconChoiceFlags::DownCtrl
;
732 bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent
& rMEvt
)
734 bool bHandled
= false;
735 if( rMEvt
.IsRight() && (nFlags
& (IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
) ))
737 nFlags
&= ~IconChoiceFlags(IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
);
741 Point
aDocPos( rMEvt
.GetPosPixel() );
743 SvxIconChoiceCtrlEntry
* pDocEntry
= GetEntry( aDocPos
);
746 if( nFlags
& IconChoiceFlags::DownCtrl
)
748 // Ctrl & MultiSelection
749 ToggleSelection( pDocEntry
);
750 SetCursor( pDocEntry
);
753 else if( nFlags
& IconChoiceFlags::DownDeselect
)
755 DeselectAllBut( pDocEntry
);
756 SetCursor( pDocEntry
);
757 SelectEntry( pDocEntry
, true, false );
762 nFlags
&= ~IconChoiceFlags(IconChoiceFlags::DownCtrl
| IconChoiceFlags::DownDeselect
);
764 if((nWinBits
& WB_HIGHLIGHTFRAME
) && bHighlightFramePressed
&& pCurHighlightFrame
)
767 SvxIconChoiceCtrlEntry
* pEntry
= pCurHighlightFrame
;
768 pCurHighlightFrame
= nullptr; // force repaint of frame
769 bHighlightFramePressed
= false;
770 SetEntryHighlightFrame( pEntry
, true );
772 pHdlEntry
= pCurHighlightFrame
;
776 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
777 SetCursor_Impl( pOldCursor
, pHdlEntry
, false, false );
784 bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent
& rMEvt
)
786 const Point
aDocPos( pView
->PixelToLogic(rMEvt
.GetPosPixel()) );
788 if( pView
->IsTracking() )
790 else if( nWinBits
& WB_HIGHLIGHTFRAME
)
792 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aDocPos
, true );
793 SetEntryHighlightFrame( pEntry
, false );
800 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry
* pOldCursor
,
801 SvxIconChoiceCtrlEntry
* pNewCursor
, bool bMod1
, bool bShift
)
806 SvxIconChoiceCtrlEntry
* pFilterEntry
= nullptr;
807 bool bDeselectAll
= false;
808 if( eSelectionMode
!= SelectionMode::Single
)
810 if( !bMod1
&& !bShift
)
812 else if( bShift
&& !bMod1
&& !pAnchor
)
815 pFilterEntry
= pOldCursor
;
819 DeselectAllBut( pFilterEntry
);
821 MakeEntryVisible( pNewCursor
);
822 SetCursor( pNewCursor
);
823 if( bMod1
&& !bShift
)
827 AddSelectedRect( pAnchor
, pOldCursor
);
834 pAnchor
= pOldCursor
;
835 if ( nWinBits
& WB_ALIGN_LEFT
)
836 SelectRange( pAnchor
, pNewCursor
, bool(nFlags
& IconChoiceFlags::AddMode
) );
838 SelectRect(pAnchor
,pNewCursor
, bool(nFlags
& IconChoiceFlags::AddMode
), &aSelectedRectList
);
842 SelectEntry( pCursor
, true, false );
843 aCurSelectionRect
= GetEntryBoundRect( pCursor
);
844 CallEventListeners( VclEventId::ListboxSelect
, pCursor
);
848 bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent
& rKEvt
)
850 bool bMod2
= rKEvt
.GetKeyCode().IsMod2();
851 sal_Unicode cChar
= rKEvt
.GetCharCode();
852 sal_uLong nPos
= sal_uLong(-1);
853 if ( bMod2
&& cChar
&& IsMnemonicChar( cChar
, nPos
) )
855 // shortcut is clicked
856 SvxIconChoiceCtrlEntry
* pNewCursor
= GetEntry( nPos
);
857 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
858 if ( pNewCursor
!= pOldCursor
)
859 SetCursor_Impl( pOldCursor
, pNewCursor
, false, false );
864 // no actions with <ALT>
867 bool bKeyUsed
= true;
868 bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
869 bool bShift
= rKEvt
.GetKeyCode().IsShift();
871 if( eSelectionMode
== SelectionMode::Single
|| eSelectionMode
== SelectionMode::NONE
)
878 nFlags
|= IconChoiceFlags::AddMode
;
880 SvxIconChoiceCtrlEntry
* pNewCursor
;
881 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
883 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
890 MakeEntryVisible( pCursor
);
891 if( nCode
== KEY_UP
)
892 pNewCursor
= pImpCursor
->GoUpDown(pCursor
,false);
894 pNewCursor
= pImpCursor
->GoPageUpDown(pCursor
,false);
895 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
898 tools::Rectangle
aRect( GetEntryBoundRect( pCursor
) );
901 aRect
.AdjustBottom( -(aRect
.Top()) );
903 MakeVisible( aRect
);
913 if( nCode
== KEY_DOWN
)
914 pNewCursor
=pImpCursor
->GoUpDown( pCursor
,true );
916 pNewCursor
=pImpCursor
->GoPageUpDown( pCursor
,true );
917 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
924 pNewCursor
=pImpCursor
->GoLeftRight(pCursor
,true );
925 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
932 MakeEntryVisible( pCursor
);
933 pNewCursor
= pImpCursor
->GoLeftRight(pCursor
,false );
934 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
937 tools::Rectangle
aRect( GetEntryBoundRect(pCursor
));
940 aRect
.AdjustRight( -(aRect
.Left()) );
942 MakeVisible( aRect
);
949 if( bMod1
|| bShift
)
954 if( rKEvt
.GetKeyCode().IsShift() )
956 if( nFlags
& IconChoiceFlags::AddMode
)
957 nFlags
&= ~IconChoiceFlags::AddMode
;
959 nFlags
|= IconChoiceFlags::AddMode
;
966 if( pCursor
&& eSelectionMode
!= SelectionMode::Single
)
970 //SelectAll( false );
972 ClearSelectedRectList();
974 // click Icon with spacebar
975 SetEntryHighlightFrame( GetCurEntry(), true );
977 pHdlEntry
= pCurHighlightFrame
;
978 pCurHighlightFrame
=nullptr;
981 ToggleSelection( pCursor
);
987 if( rKEvt
.GetKeyCode().IsShift() )
990 pView
->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Full
, pCursor
);
992 if( rKEvt
.GetKeyCode().IsMod1() )
995 pView
->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Short
, pCursor
);
1003 if( bMod1
&& (eSelectionMode
!= SelectionMode::Single
))
1025 pNewCursor
= maEntries
.back().get();
1026 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1033 pNewCursor
= maEntries
[ 0 ].get();
1034 SetCursor_Impl( pOldCursor
, pNewCursor
, bMod1
, bShift
);
1045 // recalculate TopLeft of scrollbars (but not their sizes!)
1046 void SvxIconChoiceCtrl_Impl::PositionScrollBars( tools::Long nRealWidth
, tools::Long nRealHeight
)
1048 // horizontal scrollbar
1049 Point
aPos( 0, nRealHeight
);
1050 aPos
.AdjustY( -nHorSBarHeight
);
1052 if( aHorSBar
->GetPosPixel() != aPos
)
1053 aHorSBar
->SetPosPixel( aPos
);
1055 // vertical scrollbar
1056 aPos
.setX( nRealWidth
); aPos
.setY( 0 );
1057 aPos
.AdjustX( -nVerSBarWidth
);
1061 if( aVerSBar
->GetPosPixel() != aPos
)
1062 aVerSBar
->SetPosPixel( aPos
);
1065 void SvxIconChoiceCtrl_Impl::AdjustScrollBars()
1067 tools::Long nVirtHeight
= aVirtOutputSize
.Height();
1068 tools::Long nVirtWidth
= aVirtOutputSize
.Width();
1070 Size
aOSize( pView
->Control::GetOutputSizePixel() );
1071 tools::Long nRealHeight
= aOSize
.Height();
1072 tools::Long nRealWidth
= aOSize
.Width();
1074 PositionScrollBars( nRealWidth
, nRealHeight
);
1076 const MapMode
& rMapMode
= pView
->GetMapMode();
1077 Point
aOrigin( rMapMode
.GetOrigin() );
1079 tools::Long nVisibleWidth
;
1080 if( nRealWidth
> nVirtWidth
)
1081 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1083 nVisibleWidth
= nRealWidth
;
1085 tools::Long nVisibleHeight
;
1086 if( nRealHeight
> nVirtHeight
)
1087 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1089 nVisibleHeight
= nRealHeight
;
1091 bool bVerSBar
= ( nWinBits
& WB_VSCROLL
) != 0;
1092 bool bHorSBar
= ( nWinBits
& WB_HSCROLL
) != 0;
1093 bool bNoVerSBar
= ( nWinBits
& WB_NOVSCROLL
) != 0;
1094 bool bNoHorSBar
= ( nWinBits
& WB_NOHSCROLL
) != 0;
1096 sal_uInt16 nResult
= 0;
1099 // activate vertical scrollbar?
1100 if( !bNoVerSBar
&& (bVerSBar
|| ( nVirtHeight
> nVisibleHeight
)) )
1103 nRealWidth
-= nVerSBarWidth
;
1105 if( nRealWidth
> nVirtWidth
)
1106 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1108 nVisibleWidth
= nRealWidth
;
1110 // activate horizontal scrollbar?
1111 if( !bNoHorSBar
&& (bHorSBar
|| (nVirtWidth
> nVisibleWidth
)) )
1114 nRealHeight
-= nHorSBarHeight
;
1116 if( nRealHeight
> nVirtHeight
)
1117 nVisibleHeight
= nVirtHeight
+ aOrigin
.Y();
1119 nVisibleHeight
= nRealHeight
;
1121 // do we need a vertical scrollbar after all?
1122 if( !(nResult
& 0x0001) && // only if not already there
1123 ( !bNoVerSBar
&& ((nVirtHeight
> nVisibleHeight
) || bVerSBar
)) )
1125 nResult
= 3; // both turned on
1126 nRealWidth
-= nVerSBarWidth
;
1128 if( nRealWidth
> nVirtWidth
)
1129 nVisibleWidth
= nVirtWidth
+ aOrigin
.X();
1131 nVisibleWidth
= nRealWidth
;
1136 // size vertical scrollbar
1137 tools::Long nThumb
= aVerSBar
->GetThumbPos();
1138 Size
aSize( nVerSBarWidth
, nRealHeight
);
1139 aSize
.AdjustHeight(2 );
1140 if( aSize
!= aVerSBar
->GetSizePixel() )
1141 aVerSBar
->SetSizePixel( aSize
);
1142 aVerSBar
->SetVisibleSize( nVisibleHeight
);
1143 aVerSBar
->SetPageSize( GetScrollBarPageSize( nVisibleHeight
));
1145 if( nResult
& 0x0001 )
1147 aVerSBar
->SetThumbPos( nThumb
);
1152 aVerSBar
->SetThumbPos( 0 );
1156 // size horizontal scrollbar
1157 nThumb
= aHorSBar
->GetThumbPos();
1158 aSize
.setWidth( nRealWidth
);
1159 aSize
.setHeight( nHorSBarHeight
);
1160 aSize
.AdjustWidth( 1 );
1161 if( nResult
& 0x0001 ) // vertical scrollbar?
1163 aSize
.AdjustWidth( 1 );
1166 if( aSize
!= aHorSBar
->GetSizePixel() )
1167 aHorSBar
->SetSizePixel( aSize
);
1168 aHorSBar
->SetVisibleSize( nVisibleWidth
);
1169 aHorSBar
->SetPageSize( GetScrollBarPageSize(nVisibleWidth
));
1170 if( nResult
& 0x0002 )
1172 aHorSBar
->SetThumbPos( nThumb
);
1177 aHorSBar
->SetThumbPos( 0 );
1181 aOutputSize
.setWidth( nRealWidth
);
1182 if( nResult
& 0x0002 ) // horizontal scrollbar ?
1183 nRealHeight
++; // because lower border is clipped
1184 aOutputSize
.setHeight( nRealHeight
);
1186 if( (nResult
& (0x0001|0x0002)) == (0x0001|0x0002) )
1192 void SvxIconChoiceCtrl_Impl::Resize()
1195 aOutputSize
= pView
->GetOutputSizePixel();
1196 pImpCursor
->Clear();
1197 pGridMap
->OutputSizeChanged();
1199 const Size
& rSize
= pView
->Control::GetOutputSizePixel();
1200 PositionScrollBars( rSize
.Width(), rSize
.Height() );
1201 // The scrollbars are shown/hidden asynchronously, so derived classes can
1202 // do an Arrange during Resize, without the scrollbars suddenly turning
1203 // on and off again.
1204 // If an event is already underway, we don't need to send a new one, at least
1205 // as long as there is only one event type.
1206 if ( ! nUserEventAdjustScrBars
)
1207 nUserEventAdjustScrBars
=
1208 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl
, UserEventHdl
),
1209 EVENTID_ADJUST_SCROLLBARS
);
1214 bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1216 if( maZOrderList
.empty() || !aHorSBar
->IsVisible() )
1218 const MapMode
& rMapMode
= pView
->GetMapMode();
1219 Point
aOrigin( rMapMode
.GetOrigin() );
1220 if(!( nWinBits
& WB_HSCROLL
) && !aOrigin
.X() )
1222 tools::Long nWidth
= aOutputSize
.Width();
1223 const size_t nCount
= maZOrderList
.size();
1224 tools::Long nMostRight
= 0;
1225 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1227 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCur
];
1228 tools::Long nRight
= GetEntryBoundRect(pEntry
).Right();
1229 if( nRight
> nWidth
)
1231 if( nRight
> nMostRight
)
1232 nMostRight
= nRight
;
1235 aOutputSize
.AdjustHeight(nHorSBarHeight
);
1236 aVirtOutputSize
.setWidth( nMostRight
);
1237 aHorSBar
->SetThumbPos( 0 );
1239 aRange
.Max() = nMostRight
- 1;
1240 aHorSBar
->SetRange( aRange
);
1241 if( aVerSBar
->IsVisible() )
1243 Size
aSize( aVerSBar
->GetSizePixel());
1244 aSize
.AdjustHeight(nHorSBarHeight
);
1245 aVerSBar
->SetSizePixel( aSize
);
1252 bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1254 if( maZOrderList
.empty() || !aVerSBar
->IsVisible() )
1256 const MapMode
& rMapMode
= pView
->GetMapMode();
1257 Point
aOrigin( rMapMode
.GetOrigin() );
1258 if(!( nWinBits
& WB_VSCROLL
) && !aOrigin
.Y() )
1260 tools::Long nDeepest
= 0;
1261 tools::Long nHeight
= aOutputSize
.Height();
1262 const size_t nCount
= maZOrderList
.size();
1263 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
1265 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCur
];
1266 tools::Long nBottom
= GetEntryBoundRect(pEntry
).Bottom();
1267 if( nBottom
> nHeight
)
1269 if( nBottom
> nDeepest
)
1273 aOutputSize
.AdjustWidth(nVerSBarWidth
);
1274 aVirtOutputSize
.setHeight( nDeepest
);
1275 aVerSBar
->SetThumbPos( 0 );
1277 aRange
.Max() = nDeepest
- 1;
1278 aVerSBar
->SetRange( aRange
);
1279 if( aHorSBar
->IsVisible() )
1281 Size
aSize( aHorSBar
->GetSizePixel());
1282 aSize
.AdjustWidth(nVerSBarWidth
);
1283 aHorSBar
->SetSizePixel( aSize
);
1291 // hides scrollbars if they're unnecessary
1292 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1294 CheckVerScrollBar();
1295 if( CheckHorScrollBar() )
1296 CheckVerScrollBar();
1297 if( aVerSBar
->IsVisible() && aHorSBar
->IsVisible() )
1304 void SvxIconChoiceCtrl_Impl::GetFocus()
1306 RepaintSelectedEntries();
1309 pCursor
->SetFlags( SvxIconViewFlags::FOCUSED
);
1314 void SvxIconChoiceCtrl_Impl::LoseFocus()
1317 pCursor
->ClearFlags( SvxIconViewFlags::FOCUSED
);
1318 ShowCursor( false );
1321 // pView->Invalidate ( aFocus.aRect );
1323 RepaintSelectedEntries();
1326 void SvxIconChoiceCtrl_Impl::SetUpdateMode( bool bUpdate
)
1328 if( bUpdate
!= bUpdateMode
)
1330 bUpdateMode
= bUpdate
;
1334 pImpCursor
->Clear();
1336 pView
->Invalidate(InvalidateFlags::NoChildren
);
1341 // priorities of the emphasis: bSelected
1342 void SvxIconChoiceCtrl_Impl::PaintEmphasis(const tools::Rectangle
& rTextRect
, bool bSelected
,
1343 vcl::RenderContext
& rRenderContext
)
1345 Color
aOldFillColor(rRenderContext
.GetFillColor());
1347 bool bSolidTextRect
= false;
1351 const Color
& rFillColor
= rRenderContext
.GetFont().GetFillColor();
1352 rRenderContext
.SetFillColor(rFillColor
);
1353 if (rFillColor
!= COL_TRANSPARENT
)
1354 bSolidTextRect
= true;
1357 // draw text rectangle
1360 rRenderContext
.DrawRect(rTextRect
);
1363 rRenderContext
.SetFillColor(aOldFillColor
);
1367 void SvxIconChoiceCtrl_Impl::PaintItem(const tools::Rectangle
& rRect
,
1368 IcnViewFieldType eItem
, SvxIconChoiceCtrlEntry
* pEntry
, sal_uInt16 nPaintFlags
,
1369 vcl::RenderContext
& rRenderContext
)
1371 if (eItem
== IcnViewFieldType::Text
)
1373 OUString aText
= SvtIconChoiceCtrl::GetEntryText(pEntry
);
1375 rRenderContext
.DrawText(rRect
, aText
, nCurTextDrawFlags
);
1377 if (pEntry
->IsFocused())
1379 tools::Rectangle
aRect (CalcFocusRect(pEntry
));
1381 DrawFocusRect(rRenderContext
);
1386 Point
aPos(rRect
.TopLeft());
1387 if (nPaintFlags
& PAINTFLAG_HOR_CENTERED
)
1388 aPos
.AdjustX((rRect
.GetWidth() - aImageSize
.Width()) / 2 );
1389 if (nPaintFlags
& PAINTFLAG_VER_CENTERED
)
1390 aPos
.AdjustY((rRect
.GetHeight() - aImageSize
.Height()) / 2 );
1391 SvtIconChoiceCtrl::DrawEntryImage(pEntry
, aPos
, rRenderContext
);
1395 void SvxIconChoiceCtrl_Impl::PaintEntry(SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
, vcl::RenderContext
& rRenderContext
)
1397 bool bSelected
= false;
1399 if (eSelectionMode
!= SelectionMode::NONE
)
1400 bSelected
= pEntry
->IsSelected();
1402 rRenderContext
.Push(PushFlags::FONT
| PushFlags::TEXTCOLOR
);
1404 OUString
aEntryText(SvtIconChoiceCtrl::GetEntryText(pEntry
));
1405 tools::Rectangle
aTextRect(CalcTextRect(pEntry
, &rPos
, &aEntryText
));
1406 tools::Rectangle
aBmpRect(CalcBmpRect(pEntry
, &rPos
));
1408 bool bShowSelection
= (bSelected
&& (eSelectionMode
!= SelectionMode::NONE
));
1410 bool bActiveSelection
= (0 != (nWinBits
& WB_NOHIDESELECTION
)) || pView
->HasFocus();
1414 const StyleSettings
& rSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1415 vcl::Font
aNewFont(rRenderContext
.GetFont());
1417 // font fill colors that are attributed "hard" need corresponding "hard"
1418 // attributed highlight colors
1419 if ((nWinBits
& WB_NOHIDESELECTION
) || pView
->HasFocus())
1420 aNewFont
.SetFillColor(rSettings
.GetHighlightColor());
1422 aNewFont
.SetFillColor(rSettings
.GetDeactiveColor());
1424 Color aWinCol
= rSettings
.GetWindowTextColor();
1425 if (!bActiveSelection
&& rSettings
.GetFaceColor().IsBright() == aWinCol
.IsBright())
1426 aNewFont
.SetColor(rSettings
.GetWindowTextColor());
1428 aNewFont
.SetColor(rSettings
.GetHighlightTextColor());
1430 rRenderContext
.SetFont(aNewFont
);
1432 rRenderContext
.SetFillColor(rRenderContext
.GetBackground().GetColor());
1433 rRenderContext
.DrawRect(CalcFocusRect(pEntry
));
1434 rRenderContext
.SetFillColor();
1437 bool bResetClipRegion
= false;
1438 if (!rRenderContext
.IsClipRegion() && (aVerSBar
->IsVisible() || aHorSBar
->IsVisible()))
1440 tools::Rectangle
aOutputArea(GetOutputRect());
1441 if (aOutputArea
.IsOver(aTextRect
) || aOutputArea
.IsOver(aBmpRect
))
1443 rRenderContext
.SetClipRegion(vcl::Region(aOutputArea
));
1444 bResetClipRegion
= true;
1448 bool bLargeIconMode
= WB_ICON
== ( nWinBits
& VIEWMODE_MASK
);
1449 sal_uInt16 nBmpPaintFlags
= PAINTFLAG_VER_CENTERED
;
1451 nBmpPaintFlags
|= PAINTFLAG_HOR_CENTERED
;
1452 sal_uInt16 nTextPaintFlags
= bLargeIconMode
? PAINTFLAG_HOR_CENTERED
: PAINTFLAG_VER_CENTERED
;
1454 PaintEmphasis(aTextRect
, bSelected
, rRenderContext
);
1456 if ( bShowSelection
)
1457 vcl::RenderTools::DrawSelectionBackground(rRenderContext
, *pView
, CalcFocusRect(pEntry
),
1458 bActiveSelection
? 1 : 2, false, true, false);
1461 PaintItem(aBmpRect
, IcnViewFieldType::Image
, pEntry
, nBmpPaintFlags
, rRenderContext
);
1463 PaintItem(aTextRect
, IcnViewFieldType::Text
, pEntry
, nTextPaintFlags
, rRenderContext
);
1465 // draw highlight frame
1466 if (pEntry
== pCurHighlightFrame
)
1467 DrawHighlightFrame(rRenderContext
, CalcFocusRect(pEntry
));
1469 rRenderContext
.Pop();
1470 if (bResetClipRegion
)
1471 rRenderContext
.SetClipRegion();
1474 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
)
1476 ShowCursor( false );
1477 tools::Rectangle
aBoundRect( GetEntryBoundRect( pEntry
));
1478 pView
->Invalidate( aBoundRect
);
1480 if( !IsAutoArrange() )
1482 bool bAdjustVirtSize
= false;
1483 if( rPos
!= aBoundRect
.TopLeft() )
1486 pEntry
->aGridRect
.TopLeft() - pEntry
->aRect
.TopLeft() );
1487 pImpCursor
->Clear();
1489 aBoundRect
.SetPos( rPos
);
1490 pEntry
->aRect
= aBoundRect
;
1491 pEntry
->aGridRect
.SetPos( rPos
+ aGridOffs
);
1492 bAdjustVirtSize
= true;
1494 if( bAdjustVirtSize
)
1495 AdjustVirtSize( pEntry
->aRect
);
1497 pView
->Invalidate( pEntry
->aRect
);
1498 pGridMap
->OccupyGrids( pEntry
);
1502 SvxIconChoiceCtrlEntry
* pPrev
= FindEntryPredecessor( pEntry
, rPos
);
1503 SetEntryPredecessor( pEntry
, pPrev
);
1504 aAutoArrangeIdle
.Start();
1509 void SvxIconChoiceCtrl_Impl::SetNoSelection()
1511 // block recursive calls via SelectEntry
1512 if( !(nFlags
& IconChoiceFlags::ClearingSelection
))
1514 nFlags
|= IconChoiceFlags::ClearingSelection
;
1515 DeselectAllBut( nullptr );
1516 nFlags
&= ~IconChoiceFlags::ClearingSelection
;
1520 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetEntry( const Point
& rDocPos
, bool bHit
)
1522 CheckBoundingRects();
1523 // search through z-order list from the end
1524 size_t nCount
= maZOrderList
.size();
1528 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nCount
];
1529 if( pEntry
->aRect
.IsInside( rDocPos
) )
1533 tools::Rectangle aRect
= CalcBmpRect( pEntry
);
1534 aRect
.AdjustTop( -3 );
1535 aRect
.AdjustBottom(3 );
1536 aRect
.AdjustLeft( -3 );
1537 aRect
.AdjustRight(3 );
1538 if( aRect
.IsInside( rDocPos
) )
1540 aRect
= CalcTextRect( pEntry
);
1541 if( aRect
.IsInside( rDocPos
) )
1551 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry
* pEntry
, bool bBound
)
1555 const tools::Rectangle
& rRect
= GetEntryBoundRect( pEntry
);
1556 MakeVisible( rRect
);
1560 tools::Rectangle aRect
= CalcBmpRect( pEntry
);
1561 aRect
.Union( CalcTextRect( pEntry
) );
1562 aRect
.AdjustTop(TBOFFS_BOUND
);
1563 aRect
.AdjustBottom(TBOFFS_BOUND
);
1564 aRect
.AdjustLeft(LROFFS_BOUND
);
1565 aRect
.AdjustRight(LROFFS_BOUND
);
1566 MakeVisible( aRect
);
1570 const tools::Rectangle
& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry
* pEntry
)
1572 if( !IsBoundingRectValid( pEntry
->aRect
))
1573 FindBoundingRect( pEntry
);
1574 return pEntry
->aRect
;
1577 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry
* pEntry
, const Point
* pPos
)
1579 tools::Rectangle aBound
= GetEntryBoundRect( pEntry
);
1581 aBound
.SetPos( *pPos
);
1582 Point
aPos( aBound
.TopLeft() );
1584 switch( nWinBits
& VIEWMODE_MASK
)
1588 aPos
.AdjustX(( aBound
.GetWidth() - aImageSize
.Width() ) / 2 );
1589 return tools::Rectangle( aPos
, aImageSize
);
1594 aPos
.AdjustY(( aBound
.GetHeight() - aImageSize
.Height() ) / 2 );
1595 //TODO: determine horizontal distance to bounding rectangle
1596 return tools::Rectangle( aPos
, aImageSize
);
1599 OSL_FAIL("IconView: Viewmode not set");
1604 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry
* pEntry
,
1605 const Point
* pEntryPos
, const OUString
* pStr
)
1607 OUString aEntryText
;
1609 aEntryText
= SvtIconChoiceCtrl::GetEntryText( pEntry
);
1613 const tools::Rectangle
aMaxTextRect( CalcMaxTextRect( pEntry
) );
1614 tools::Rectangle
aBound( GetEntryBoundRect( pEntry
) );
1616 aBound
.SetPos( *pEntryPos
);
1618 tools::Rectangle aTextRect
= pView
->GetTextRect( aMaxTextRect
, aEntryText
, nCurTextDrawFlags
);
1620 Size
aTextSize( aTextRect
.GetSize() );
1622 Point
aPos( aBound
.TopLeft() );
1623 tools::Long nBoundWidth
= aBound
.GetWidth();
1624 tools::Long nBoundHeight
= aBound
.GetHeight();
1626 switch( nWinBits
& VIEWMODE_MASK
)
1629 aPos
.AdjustY(aImageSize
.Height() );
1630 aPos
.AdjustY(VER_DIST_BMP_STRING
);
1631 aPos
.AdjustX((nBoundWidth
- aTextSize
.Width()) / 2 );
1636 aPos
.AdjustX(aImageSize
.Width() );
1637 aPos
.AdjustX(HOR_DIST_BMP_STRING
);
1638 aPos
.AdjustY((nBoundHeight
- aTextSize
.Height()) / 2 );
1641 return tools::Rectangle( aPos
, aTextSize
);
1645 tools::Long
SvxIconChoiceCtrl_Impl::CalcBoundingWidth() const
1647 tools::Long nStringWidth
= GetItemSize( IcnViewFieldType::Text
).Width();
1648 tools::Long nWidth
= 0;
1650 switch( nWinBits
& VIEWMODE_MASK
)
1653 nWidth
= std::max( nStringWidth
, aImageSize
.Width() );
1658 nWidth
= aImageSize
.Width();
1659 nWidth
+= HOR_DIST_BMP_STRING
;
1660 nWidth
+= nStringWidth
;
1666 tools::Long
SvxIconChoiceCtrl_Impl::CalcBoundingHeight() const
1668 tools::Long nStringHeight
= GetItemSize(IcnViewFieldType::Text
).Height();
1669 tools::Long nHeight
= 0;
1671 switch( nWinBits
& VIEWMODE_MASK
)
1674 nHeight
= aImageSize
.Height();
1675 nHeight
+= VER_DIST_BMP_STRING
;
1676 nHeight
+= nStringHeight
;
1681 nHeight
= std::max( aImageSize
.Height(), nStringHeight
);
1684 if( nHeight
> nMaxBoundHeight
)
1686 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->nMaxBoundHeight
= nHeight
;
1687 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->aHorSBar
->SetLineSize( GetScrollBarLineSize() );
1688 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->aVerSBar
->SetLineSize( GetScrollBarLineSize() );
1693 Size
SvxIconChoiceCtrl_Impl::CalcBoundingSize() const
1695 return Size( CalcBoundingWidth(), CalcBoundingHeight() );
1698 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
1700 nMaxBoundHeight
= 0;
1701 maZOrderList
.clear();
1703 SvxIconChoiceCtrlEntry
* pEntry
;
1704 const size_t nCount
= maEntries
.size();
1706 if( !IsAutoArrange() || !pHead
)
1708 for( nCur
= 0; nCur
< nCount
; nCur
++ )
1710 pEntry
= maEntries
[ nCur
].get();
1711 if( IsBoundingRectValid( pEntry
->aRect
))
1713 Size
aBoundSize( pEntry
->aRect
.GetSize() );
1714 if( aBoundSize
.Height() > nMaxBoundHeight
)
1715 nMaxBoundHeight
= aBoundSize
.Height();
1718 FindBoundingRect( pEntry
);
1719 maZOrderList
.push_back( pEntry
);
1726 while( nCur
!= nCount
)
1728 DBG_ASSERT(pEntry
->pflink
&&pEntry
->pblink
,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
1729 if( IsBoundingRectValid( pEntry
->aRect
))
1731 Size
aBoundSize( pEntry
->aRect
.GetSize() );
1732 if( aBoundSize
.Height() > nMaxBoundHeight
)
1733 nMaxBoundHeight
= aBoundSize
.Height();
1736 FindBoundingRect( pEntry
);
1737 maZOrderList
.push_back( pEntry
);
1738 pEntry
= pEntry
->pflink
;
1745 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry
* pEntry
)
1747 DBG_ASSERT(!pEntry
->IsPosLocked(),"Locked entry pos in FindBoundingRect");
1748 if( pEntry
->IsPosLocked() && IsBoundingRectValid( pEntry
->aRect
) )
1750 AdjustVirtSize( pEntry
->aRect
);
1753 Size
aSize( CalcBoundingSize() );
1754 Point
aPos(pGridMap
->GetGridRect(pGridMap
->GetUnoccupiedGrid()).TopLeft());
1755 SetBoundingRect_Impl( pEntry
, aPos
, aSize
);
1758 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry
* pEntry
, const Point
& rPos
,
1759 const Size
& /*rBoundingSize*/ )
1761 tools::Rectangle
aGridRect( rPos
, Size(nGridDX
, nGridDY
) );
1762 pEntry
->aGridRect
= aGridRect
;
1764 AdjustVirtSize( pEntry
->aRect
);
1765 pGridMap
->OccupyGrids( pEntry
);
1769 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry
* pEntry
)
1771 if( pEntry
== pCursor
)
1773 if( pCursor
&& eSelectionMode
== SelectionMode::Single
&&
1774 !pCursor
->IsSelected() )
1775 SelectEntry( pCursor
, true );
1778 ShowCursor( false );
1779 SvxIconChoiceCtrlEntry
* pOldCursor
= pCursor
;
1783 pOldCursor
->ClearFlags( SvxIconViewFlags::FOCUSED
);
1784 if( eSelectionMode
== SelectionMode::Single
)
1785 SelectEntry( pOldCursor
, false ); // deselect old cursor
1790 pCursor
->SetFlags( SvxIconViewFlags::FOCUSED
);
1791 if( eSelectionMode
== SelectionMode::Single
)
1792 SelectEntry( pCursor
, true );
1798 void SvxIconChoiceCtrl_Impl::ShowCursor( bool bShow
)
1800 if( !pCursor
|| !bShow
|| !pView
->HasFocus() )
1805 tools::Rectangle
aRect ( CalcFocusRect( pCursor
) );
1806 /*pView->*/ShowFocus( aRect
);
1810 void SvxIconChoiceCtrl_Impl::HideDDIcon()
1812 pView
->PaintImmediately();
1815 bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent
& rCmd
)
1817 tools::Rectangle
aDocRect( Point(), aVirtOutputSize
);
1818 tools::Rectangle
aVisRect( GetOutputRect() );
1819 if( aVisRect
.IsInside( aDocRect
))
1821 Size
aDocSize( aDocRect
.GetSize() );
1822 Size
aVisSize( aVisRect
.GetSize() );
1823 bool bHor
= aDocSize
.Width() > aVisSize
.Width();
1824 bool bVer
= aDocSize
.Height() > aVisSize
.Height();
1826 tools::Long nScrollDX
= 0, nScrollDY
= 0;
1828 switch( rCmd
.GetCommand() )
1830 case CommandEventId::StartAutoScroll
:
1832 pView
->EndTracking();
1833 StartAutoScrollFlags nScrollFlags
= StartAutoScrollFlags::NONE
;
1835 nScrollFlags
|= StartAutoScrollFlags::Horz
;
1837 nScrollFlags
|= StartAutoScrollFlags::Vert
;
1838 if( nScrollFlags
!= StartAutoScrollFlags::NONE
)
1840 pView
->StartAutoScroll( nScrollFlags
);
1846 case CommandEventId::Wheel
:
1848 const CommandWheelData
* pData
= rCmd
.GetWheelData();
1849 if( pData
&& (CommandWheelMode::SCROLL
== pData
->GetMode()) && !pData
->IsHorz() )
1851 sal_uLong nScrollLines
= pData
->GetScrollLines();
1852 if( nScrollLines
== COMMAND_WHEEL_PAGESCROLL
)
1854 nScrollDY
= GetScrollBarPageSize( aVisSize
.Width() );
1855 if( pData
->GetDelta() < 0 )
1860 nScrollDY
= pData
->GetNotchDelta() * static_cast<tools::Long
>(nScrollLines
);
1861 nScrollDY
*= GetScrollBarLineSize();
1867 case CommandEventId::AutoScroll
:
1869 const CommandScrollData
* pData
= rCmd
.GetAutoScrollData();
1872 nScrollDX
= pData
->GetDeltaX() * GetScrollBarLineSize();
1873 nScrollDY
= pData
->GetDeltaY() * GetScrollBarLineSize();
1881 if( nScrollDX
|| nScrollDY
)
1883 aVisRect
.AdjustTop( -nScrollDY
);
1884 aVisRect
.AdjustBottom( -nScrollDY
);
1885 aVisRect
.AdjustLeft( -nScrollDX
);
1886 aVisRect
.AdjustRight( -nScrollDX
);
1887 MakeVisible( aVisRect
);
1894 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent
& rCEvt
)
1896 // scroll mouse event?
1897 if( (rCEvt
.GetCommand() == CommandEventId::Wheel
) ||
1898 (rCEvt
.GetCommand() == CommandEventId::StartAutoScroll
) ||
1899 (rCEvt
.GetCommand() == CommandEventId::AutoScroll
) )
1901 if( HandleScrollCommand( rCEvt
) )
1906 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry
* pEntry
)
1908 if( maZOrderList
.empty() || pEntry
== maZOrderList
.back())
1911 auto it
= std::find(maZOrderList
.begin(), maZOrderList
.end(), pEntry
);
1912 if (it
!= maZOrderList
.end())
1914 maZOrderList
.erase( it
);
1915 maZOrderList
.push_back( pEntry
);
1919 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( tools::Rectangle
& rRect
) const
1921 if( rRect
.Bottom() >= aVirtOutputSize
.Height() )
1922 rRect
.SetBottom( aVirtOutputSize
.Height() - 1 );
1923 if( rRect
.Right() >= aVirtOutputSize
.Width() )
1924 rRect
.SetRight( aVirtOutputSize
.Width() - 1 );
1925 if( rRect
.Top() < 0 )
1927 if( rRect
.Left() < 0 )
1931 // rRect: area of the document (in document coordinates) that we want to make
1933 // bScrBar == true: rectangle was calculated because of a scrollbar event
1935 void SvxIconChoiceCtrl_Impl::MakeVisible( const tools::Rectangle
& rRect
, bool bScrBar
)
1937 tools::Rectangle
aVirtRect( rRect
);
1938 ClipAtVirtOutRect( aVirtRect
);
1939 Point
aOrigin( pView
->GetMapMode().GetOrigin() );
1940 // convert to document coordinate
1942 tools::Rectangle
aOutputArea( GetOutputRect() );
1943 if( aOutputArea
.IsInside( aVirtRect
) )
1944 return; // is already visible
1947 if( aVirtRect
.Top() < aOutputArea
.Top() )
1949 // scroll up (nDy < 0)
1950 nDy
= aVirtRect
.Top() - aOutputArea
.Top();
1952 else if( aVirtRect
.Bottom() > aOutputArea
.Bottom() )
1954 // scroll down (nDy > 0)
1955 nDy
= aVirtRect
.Bottom() - aOutputArea
.Bottom();
1961 if( aVirtRect
.Left() < aOutputArea
.Left() )
1963 // scroll to the left (nDx < 0)
1964 nDx
= aVirtRect
.Left() - aOutputArea
.Left();
1966 else if( aVirtRect
.Right() > aOutputArea
.Right() )
1968 // scroll to the right (nDx > 0)
1969 nDx
= aVirtRect
.Right() - aOutputArea
.Right();
1974 aOrigin
.AdjustX(nDx
);
1975 aOrigin
.AdjustY(nDy
);
1976 aOutputArea
.SetPos( aOrigin
);
1977 if( GetUpdateMode() )
1980 pView
->PaintImmediately();
1981 ShowCursor( false );
1984 // invert origin for SV (so we can scroll/paint using document coordinates)
1986 SetOrigin( aOrigin
);
1988 bool bScrollable
= pView
->GetBackground().IsScrollable();
1990 if( bScrollable
&& GetUpdateMode() )
1992 // scroll in reverse direction!
1993 pView
->Control::Scroll( -nDx
, -nDy
, aOutputArea
,
1994 ScrollFlags::NoChildren
| ScrollFlags::UseClipRegion
| ScrollFlags::Clip
);
1997 pView
->Invalidate(InvalidateFlags::NoChildren
);
1999 if( aHorSBar
->IsVisible() || aVerSBar
->IsVisible() )
2005 if(aHorSBar
->IsVisible() && aHorSBar
->GetThumbPos() != aOrigin
.X())
2006 aHorSBar
->SetThumbPos( aOrigin
.X() );
2007 if(aVerSBar
->IsVisible() && aVerSBar
->GetThumbPos() != aOrigin
.Y())
2008 aVerSBar
->SetThumbPos( aOrigin
.Y() );
2012 if( GetUpdateMode() )
2015 // check if we still need scrollbars
2017 if( bScrollable
&& GetUpdateMode() )
2018 pView
->PaintImmediately();
2020 // If the requested area can not be made completely visible, the
2021 // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2022 // if only few pixels of the lower border are invisible, but a scrollbar has
2023 // a larger line size.
2027 sal_Int32
SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2029 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && pCurHighlightFrame
)
2031 return nSelectionCount
;
2034 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry
* pEntry
)
2037 bSel
= !pEntry
->IsSelected();
2038 SelectEntry( pEntry
, bSel
, true );
2041 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry
const * pThisEntryNot
)
2043 ClearSelectedRectList();
2045 // TODO: work through z-order list, if necessary!
2047 size_t nCount
= maEntries
.size();
2048 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2050 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2051 if( pEntry
!= pThisEntryNot
&& pEntry
->IsSelected() )
2052 SelectEntry( pEntry
, false, true );
2055 nFlags
&= ~IconChoiceFlags::AddMode
;
2058 Size
SvxIconChoiceCtrl_Impl::GetMinGrid() const
2060 Size
aMinSize( aImageSize
);
2061 aMinSize
.AdjustWidth(2 * LROFFS_BOUND
);
2062 aMinSize
.AdjustHeight(TBOFFS_BOUND
); // single offset is enough (FileDlg)
2063 Size
aTextSize( pView
->GetTextWidth( "XXX" ), pView
->GetTextHeight() );
2064 if( nWinBits
& WB_ICON
)
2066 aMinSize
.AdjustHeight(VER_DIST_BMP_STRING
);
2067 aMinSize
.AdjustHeight(aTextSize
.Height() );
2071 aMinSize
.AdjustWidth(HOR_DIST_BMP_STRING
);
2072 aMinSize
.AdjustWidth(aTextSize
.Width() );
2077 void SvxIconChoiceCtrl_Impl::SetGrid( const Size
& rSize
)
2079 Size
aSize( rSize
);
2080 Size
aMinSize( GetMinGrid() );
2081 if( aSize
.Width() < aMinSize
.Width() )
2082 aSize
.setWidth( aMinSize
.Width() );
2083 if( aSize
.Height() < aMinSize
.Height() )
2084 aSize
.setHeight( aMinSize
.Height() );
2086 nGridDX
= aSize
.Width();
2087 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2088 // fly with a single column
2089 if( nWinBits
& WB_DETAILS
)
2091 const SvxIconChoiceCtrlColumnInfo
* pCol
= GetColumn( 0 );
2093 const_cast<SvxIconChoiceCtrlColumnInfo
*>(pCol
)->SetWidth( nGridDX
);
2095 nGridDY
= aSize
.Height();
2096 SetDefaultTextSize();
2099 // Calculates the maximum size that the text rectangle may use within its
2100 // bounding rectangle. In WB_ICON mode with SvxIconChoiceCtrlTextMode::Full, Bottom is set to
2103 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry
* pEntry
) const
2105 tools::Rectangle aBoundRect
;
2106 // avoid infinite recursion: don't calculate the bounding rectangle here
2107 if( IsBoundingRectValid( pEntry
->aRect
) )
2108 aBoundRect
= pEntry
->aRect
;
2110 aBoundRect
= pEntry
->aGridRect
;
2112 tools::Rectangle
aBmpRect( const_cast<SvxIconChoiceCtrl_Impl
*>(this)->CalcBmpRect(
2113 const_cast<SvxIconChoiceCtrlEntry
*>(pEntry
) ) );
2114 if( nWinBits
& WB_ICON
)
2116 aBoundRect
.SetTop( aBmpRect
.Bottom() );
2117 aBoundRect
.AdjustTop(VER_DIST_BMP_STRING
);
2118 if( aBoundRect
.Top() > aBoundRect
.Bottom())
2119 aBoundRect
.SetTop( aBoundRect
.Bottom() );
2120 aBoundRect
.AdjustLeft(LROFFS_BOUND
);
2121 aBoundRect
.AdjustLeft( 1 );
2122 aBoundRect
.AdjustRight( -(LROFFS_BOUND
) );
2123 aBoundRect
.AdjustRight( -1 );
2124 if( aBoundRect
.Left() > aBoundRect
.Right())
2125 aBoundRect
.SetLeft( aBoundRect
.Right() );
2126 if( pEntry
->GetTextMode() == SvxIconChoiceCtrlTextMode::Full
)
2127 aBoundRect
.SetBottom( LONG_MAX
);
2131 aBoundRect
.SetLeft( aBmpRect
.Right() );
2132 aBoundRect
.AdjustLeft(HOR_DIST_BMP_STRING
);
2133 aBoundRect
.AdjustRight( -(LROFFS_BOUND
) );
2134 if( aBoundRect
.Left() > aBoundRect
.Right() )
2135 aBoundRect
.SetLeft( aBoundRect
.Right() );
2136 tools::Long nHeight
= aBoundRect
.GetSize().Height();
2137 nHeight
= nHeight
- aDefaultTextSize
.Height();
2139 aBoundRect
.AdjustTop(nHeight
);
2140 aBoundRect
.AdjustBottom( -nHeight
);
2145 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2147 tools::Long nDY
= nGridDY
;
2148 nDY
-= aImageSize
.Height();
2149 nDY
-= VER_DIST_BMP_STRING
;
2150 nDY
-= 2 * TBOFFS_BOUND
;
2154 tools::Long nDX
= nGridDX
;
2155 nDX
-= 2 * LROFFS_BOUND
;
2160 tools::Long nHeight
= pView
->GetTextHeight();
2163 if(pView
->GetDPIScaleFactor() > 1)
2167 aDefaultTextSize
= Size(nDX
, nDY
);
2171 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry
* pEntry
) const
2173 pEntry
->aRect
= pEntry
->aGridRect
;
2174 Size
aSize( CalcBoundingSize() );
2175 if( nWinBits
& WB_ICON
)
2177 // center horizontally
2178 tools::Long nBorder
= pEntry
->aGridRect
.GetWidth() - aSize
.Width();
2179 pEntry
->aRect
.AdjustLeft(nBorder
/ 2 );
2180 pEntry
->aRect
.AdjustRight( -(nBorder
/ 2) );
2182 // center vertically
2183 pEntry
->aRect
.SetBottom( pEntry
->aRect
.Top() + aSize
.Height() );
2187 // The deltas are the offsets by which the view is moved on the document.
2188 // left, up: offsets < 0
2189 // right, down: offsets > 0
2190 void SvxIconChoiceCtrl_Impl::Scroll( tools::Long nDeltaX
, tools::Long nDeltaY
)
2192 const MapMode
& rMapMode
= pView
->GetMapMode();
2193 Point
aOrigin( rMapMode
.GetOrigin() );
2194 // convert to document coordinate
2196 aOrigin
.AdjustY(nDeltaY
);
2197 aOrigin
.AdjustX(nDeltaX
);
2198 tools::Rectangle
aRect( aOrigin
, aOutputSize
);
2199 MakeVisible( aRect
, true/*bScrollBar*/ );
2203 const Size
& SvxIconChoiceCtrl_Impl::GetItemSize( IcnViewFieldType eItem
) const
2205 if (eItem
== IcnViewFieldType::Text
)
2206 return aDefaultTextSize
;
2207 return aImageSize
; // IcnViewFieldType::Image
2210 tools::Rectangle
SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry
* pEntry
)
2212 tools::Rectangle
aTextRect( CalcTextRect( pEntry
) );
2213 tools::Rectangle
aBoundRect( GetEntryBoundRect( pEntry
) );
2214 return tools::Rectangle(
2215 aBoundRect
.Left(), aBoundRect
.Top() - 1, aBoundRect
.Right() - 1,
2216 aTextRect
.Bottom() + 1);
2219 // the hot spot is the inner 50% of the rectangle
2220 static tools::Rectangle
GetHotSpot( const tools::Rectangle
& rRect
)
2222 tools::Rectangle
aResult( rRect
);
2224 Size
aSize( rRect
.GetSize() );
2225 tools::Long nDelta
= aSize
.Width() / 4;
2226 aResult
.AdjustLeft(nDelta
);
2227 aResult
.AdjustRight( -nDelta
);
2228 nDelta
= aSize
.Height() / 4;
2229 aResult
.AdjustTop(nDelta
);
2230 aResult
.AdjustBottom( -nDelta
);
2234 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry
* pEntry1
, SvxIconChoiceCtrlEntry
* pEntry2
,
2235 bool bAdd
, std::vector
<tools::Rectangle
>* pOtherRects
)
2237 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2238 tools::Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2239 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2240 SelectRect( aRect
, bAdd
, pOtherRects
);
2243 void SvxIconChoiceCtrl_Impl::SelectRect( const tools::Rectangle
& rRect
, bool bAdd
,
2244 std::vector
<tools::Rectangle
>* pOtherRects
)
2246 aCurSelectionRect
= rRect
;
2247 if( maZOrderList
.empty() )
2250 // set flag, so ToTop won't be called in Select
2251 bool bAlreadySelectingRect(nFlags
& IconChoiceFlags::SelectingRect
);
2252 nFlags
|= IconChoiceFlags::SelectingRect
;
2254 CheckBoundingRects();
2255 pView
->PaintImmediately();
2256 const size_t nCount
= maZOrderList
.size();
2258 tools::Rectangle
aRect( rRect
);
2260 bool bCalcOverlap
= (bAdd
&& pOtherRects
&& !pOtherRects
->empty());
2262 bool bResetClipRegion
= false;
2263 if( !pView
->IsClipRegion() )
2265 bResetClipRegion
= true;
2266 pView
->SetClipRegion(vcl::Region(GetOutputRect()));
2269 for( size_t nPos
= 0; nPos
< nCount
; nPos
++ )
2271 SvxIconChoiceCtrlEntry
* pEntry
= maZOrderList
[ nPos
];
2273 if( !IsBoundingRectValid( pEntry
->aRect
))
2274 FindBoundingRect( pEntry
);
2275 tools::Rectangle
aBoundRect( GetHotSpot( pEntry
->aRect
) );
2276 bool bSelected
= pEntry
->IsSelected();
2280 bOverlaps
= IsOver( pOtherRects
, aBoundRect
);
2283 bool bOver
= aRect
.IsOver( aBoundRect
);
2285 if( bOver
&& !bOverlaps
)
2287 // is inside the new selection rectangle and outside of any old one
2290 SelectEntry( pEntry
, true, true );
2294 // is outside of the selection rectangle
2297 SelectEntry( pEntry
, false, true );
2301 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2302 // selection rectangle.
2304 // There is still a bug here! The selection status of an entry in a
2305 // previous rectangle has to be restored, if it was touched by the
2306 // current selection rectangle but is not inside it any more.
2307 // For simplicity's sake, let's assume that all entries in the old
2308 // rectangles were correctly selected. It is wrong to just deselect
2309 // the intersection.
2310 // Possible solution: remember a snapshot of the selection before
2311 // spanning the rectangle.
2312 if( aBoundRect
.IsOver( rRect
))
2314 // deselect intersection between old rectangles and current rectangle
2316 SelectEntry( pEntry
, false, true );
2320 // select entry of an old rectangle
2322 SelectEntry( pEntry
, true, true );
2325 else if( !bOver
&& bSelected
)
2327 // this entry is completely outside the rectangle => deselect it
2328 SelectEntry( pEntry
, false, true );
2332 if( !bAlreadySelectingRect
)
2333 nFlags
&= ~IconChoiceFlags::SelectingRect
;
2335 pView
->PaintImmediately();
2336 if( bResetClipRegion
)
2337 pView
->SetClipRegion();
2340 void SvxIconChoiceCtrl_Impl::SelectRange(
2341 SvxIconChoiceCtrlEntry
const * pStart
,
2342 SvxIconChoiceCtrlEntry
const * pEnd
,
2345 sal_uLong nFront
= GetEntryListPos( pStart
);
2346 sal_uLong nBack
= GetEntryListPos( pEnd
);
2347 sal_uLong nFirst
= std::min( nFront
, nBack
);
2348 sal_uLong nLast
= std::max( nFront
, nBack
);
2350 SvxIconChoiceCtrlEntry
* pEntry
;
2354 // deselect everything before the first entry if not in
2356 for ( i
=0; i
<nFirst
; i
++ )
2358 pEntry
= GetEntry( i
);
2359 if( pEntry
->IsSelected() )
2360 SelectEntry( pEntry
, false, true );
2364 // select everything between nFirst and nLast
2365 for ( i
=nFirst
; i
<=nLast
; i
++ )
2367 pEntry
= GetEntry( i
);
2368 if( ! pEntry
->IsSelected() )
2369 SelectEntry( pEntry
, true, true );
2374 // deselect everything behind the last entry if not in
2376 sal_uLong nEnd
= GetEntryCount();
2377 for ( ; i
<nEnd
; i
++ )
2379 pEntry
= GetEntry( i
);
2380 if( pEntry
->IsSelected() )
2381 SelectEntry( pEntry
, false, true );
2386 bool SvxIconChoiceCtrl_Impl::IsOver( std::vector
<tools::Rectangle
>* pRectList
, const tools::Rectangle
& rBoundRect
)
2388 const sal_uInt16 nCount
= pRectList
->size();
2389 for( sal_uInt16 nCur
= 0; nCur
< nCount
; nCur
++ )
2391 tools::Rectangle
& rRect
= (*pRectList
)[ nCur
];
2392 if( rBoundRect
.IsOver( rRect
))
2398 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry
* pEntry1
,
2399 SvxIconChoiceCtrlEntry
* pEntry2
)
2401 DBG_ASSERT(pEntry1
&& pEntry2
,"SelectEntry: Invalid Entry-Ptr");
2402 tools::Rectangle
aRect( GetEntryBoundRect( pEntry1
) );
2403 aRect
.Union( GetEntryBoundRect( pEntry2
) );
2404 AddSelectedRect( aRect
);
2407 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const tools::Rectangle
& rRect
)
2409 tools::Rectangle newRect
= rRect
;
2411 aSelectedRectList
.push_back( newRect
);
2414 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2416 aSelectedRectList
.clear();
2419 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, AutoArrangeHdl
, Timer
*, void)
2421 aAutoArrangeIdle
.Stop();
2422 Arrange( IsAutoArrange(), 0, 0 );
2425 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, VisRectChangedHdl
, Timer
*, void)
2427 aVisRectChangedIdle
.Stop();
2430 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, DocRectChangedHdl
, Timer
*, void)
2432 aDocRectChangedIdle
.Stop();
2436 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode
, SvxIconChoiceCtrlEntry
* pEntry
)
2440 if( eTextMode
!= eMode
)
2443 Arrange( true, 0, 0 );
2448 if( pEntry
->eTextMode
!= eMode
)
2450 pEntry
->eTextMode
= eMode
;
2451 InvalidateEntry( pEntry
);
2452 pView
->Invalidate( GetEntryBoundRect( pEntry
) );
2453 AdjustVirtSize( pEntry
->aRect
);
2459 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
2460 // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
2461 // a gray focusrect on a gray background !!!
2463 void SvxIconChoiceCtrl_Impl::ShowFocus ( tools::Rectangle
const & rRect
)
2465 Color
aBkgColor(pView
->GetBackground().GetColor());
2467 sal_uInt16 nColor
= ( aBkgColor
.GetRed() + aBkgColor
.GetGreen() + aBkgColor
.GetBlue() ) / 3;
2469 aPenColor
= COL_BLACK
;
2471 aPenColor
= COL_WHITE
;
2473 aFocus
.aPenColor
= aPenColor
;
2474 aFocus
.aRect
= rRect
;
2477 void SvxIconChoiceCtrl_Impl::DrawFocusRect(vcl::RenderContext
& rRenderContext
)
2479 rRenderContext
.SetLineColor(aFocus
.aPenColor
);
2480 rRenderContext
.SetFillColor();
2481 tools::Polygon
aPolygon (aFocus
.aRect
);
2483 LineInfo
aLineInfo(LineStyle::Dash
);
2485 aLineInfo
.SetDashLen(1);
2486 aLineInfo
.SetDotLen(1);
2487 aLineInfo
.SetDistance(1);
2488 aLineInfo
.SetDotCount(1);
2490 rRenderContext
.DrawPolyLine(aPolygon
, aLineInfo
);
2493 bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar
, sal_uLong
& rPos
) const
2496 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
2497 size_t nEntryCount
= GetEntryCount();
2498 for ( size_t i
= 0; i
< nEntryCount
; ++i
)
2500 if ( rI18nHelper
.MatchMnemonic( GetEntry( i
)->GetText(), cChar
) )
2512 IMPL_LINK(SvxIconChoiceCtrl_Impl
, UserEventHdl
, void*, nId
, void )
2514 if( nId
== EVENTID_ADJUST_SCROLLBARS
)
2516 nUserEventAdjustScrBars
= nullptr;
2519 else if( nId
== EVENTID_SHOW_CURSOR
)
2525 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
2527 if( nUserEventAdjustScrBars
)
2529 Application::RemoveUserEvent( nUserEventAdjustScrBars
);
2530 nUserEventAdjustScrBars
= nullptr;
2534 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry
* pEntry
)
2536 if( pEntry
== pCursor
)
2537 ShowCursor( false );
2538 pView
->Invalidate( pEntry
->aRect
);
2540 pView
->Invalidate( pEntry
->aRect
);
2541 if( pEntry
== pCursor
)
2545 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry() const
2547 if( !GetSelectionCount() )
2550 if( (nWinBits
& WB_HIGHLIGHTFRAME
) && (eSelectionMode
== SelectionMode::NONE
) )
2552 return pCurHighlightFrame
;
2555 size_t nCount
= maEntries
.size();
2558 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2560 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2561 if( pEntry
->IsSelected() )
2569 SvxIconChoiceCtrlEntry
* pEntry
= pHead
;
2572 if( pEntry
->IsSelected() )
2576 pEntry
= pEntry
->pflink
;
2577 if( nCount
&& pEntry
== pHead
)
2579 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
2587 void SvxIconChoiceCtrl_Impl::SelectAll()
2589 size_t nCount
= maEntries
.size();
2590 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2592 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2593 SelectEntry( pEntry
, true/*bSelect*/, true );
2595 nFlags
&= ~IconChoiceFlags::AddMode
;
2602 sal_Int32
SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry
const * pEntry
) const
2604 if( !(nFlags
& IconChoiceFlags::EntryListPosValid
))
2605 const_cast<SvxIconChoiceCtrl_Impl
*>(this)->SetListPositions();
2606 return pEntry
->nPos
;
2609 void SvxIconChoiceCtrl_Impl::InitSettings()
2611 const StyleSettings
& rStyleSettings
= pView
->GetSettings().GetStyleSettings();
2613 // unit (from settings) is Point
2614 vcl::Font
aFont( rStyleSettings
.GetFieldFont() );
2615 aFont
.SetColor( rStyleSettings
.GetWindowTextColor() );
2616 pView
->SetPointFont( aFont
);
2617 SetDefaultTextSize();
2619 pView
->SetTextColor( rStyleSettings
.GetFieldTextColor() );
2620 pView
->SetTextFillColor();
2622 pView
->SetBackground( rStyleSettings
.GetFieldColor());
2624 tools::Long nScrBarSize
= rStyleSettings
.GetScrollBarSize();
2625 if( nScrBarSize
== nHorSBarHeight
&& nScrBarSize
== nVerSBarWidth
)
2628 nHorSBarHeight
= nScrBarSize
;
2629 Size
aSize( aHorSBar
->GetSizePixel() );
2630 aSize
.setHeight( nScrBarSize
);
2632 aHorSBar
->SetSizePixel( aSize
);
2634 nVerSBarWidth
= nScrBarSize
;
2635 aSize
= aVerSBar
->GetSizePixel();
2636 aSize
.setWidth( nScrBarSize
);
2638 aVerSBar
->SetSizePixel( aSize
);
2640 Size
aOSize( pView
->Control::GetOutputSizePixel() );
2641 PositionScrollBars( aOSize
.Width(), aOSize
.Height() );
2645 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode
)
2647 if( eMode
== ePositionMode
)
2650 SvxIconChoiceCtrlPositionMode eOldMode
= ePositionMode
;
2651 ePositionMode
= eMode
;
2652 size_t nCount
= maEntries
.size();
2654 if( eOldMode
== SvxIconChoiceCtrlPositionMode::AutoArrange
)
2656 // when positioning moved entries "hard", there are problems with
2657 // unwanted overlaps, as these entries aren't taken into account in
2659 if( maEntries
.size() )
2660 aAutoArrangeIdle
.Start();
2664 if( ePositionMode
== SvxIconChoiceCtrlPositionMode::AutoArrange
)
2666 for( size_t nCur
= 0; nCur
< nCount
; nCur
++ )
2668 SvxIconChoiceCtrlEntry
* pEntry
= maEntries
[ nCur
].get();
2669 if( pEntry
->GetFlags() & SvxIconViewFlags(SvxIconViewFlags::POS_LOCKED
| SvxIconViewFlags::POS_MOVED
))
2670 SetEntryPos(pEntry
, GetEntryBoundRect( pEntry
).TopLeft());
2673 if( maEntries
.size() )
2674 aAutoArrangeIdle
.Start();
2678 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
2679 SvxIconChoiceCtrlEntry
* pPredecessor
)
2681 if( !IsAutoArrange() )
2684 if( pEntry
== pPredecessor
)
2687 sal_uLong nPos1
= GetEntryListPos( pEntry
);
2692 sal_uLong nPos2
= GetEntryListPos( pPredecessor
);
2693 if( nPos1
== (nPos2
+ 1) )
2694 return; // is already the predecessor
2702 if( !pPredecessor
&& pHead
== pEntry
)
2703 return; // is already the first one
2705 bool bSetHead
= false;
2709 pPredecessor
= pHead
->pblink
;
2711 if( pEntry
== pHead
)
2713 pHead
= pHead
->pflink
;
2716 if( pEntry
!= pPredecessor
)
2719 pEntry
->SetBacklink( pPredecessor
);
2723 aAutoArrangeIdle
.Start();
2726 SvxIconChoiceCtrlEntry
* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry
* pEntry
,
2727 const Point
& rPosTopLeft
)
2729 Point
aPos( rPosTopLeft
); //TopLeft
2730 tools::Rectangle
aCenterRect( CalcBmpRect( pEntry
, &aPos
));
2731 Point
aNewPos( aCenterRect
.Center() );
2732 GridId nGrid
= GetPredecessorGrid( aNewPos
);
2733 size_t nCount
= maEntries
.size();
2734 if( nGrid
== GRID_NOT_FOUND
)
2736 if( nGrid
>= nCount
)
2739 return maEntries
[ nGrid
].get();
2741 SvxIconChoiceCtrlEntry
* pCur
= pHead
; // Grid 0
2742 // TODO: go through list from the end if nGrid > nCount/2
2743 for( GridId nCur
= 0; nCur
< nGrid
; nCur
++ )
2744 pCur
= pCur
->pflink
;
2749 GridId
SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point
& rPos
) const
2752 aPos
.AdjustX( -(LROFFS_WINBORDER
) );
2753 aPos
.AdjustY( -(TBOFFS_WINBORDER
) );
2754 tools::Long nMaxCol
= aVirtOutputSize
.Width() / nGridDX
;
2757 tools::Long nGridX
= aPos
.X() / nGridDX
;
2758 if( nGridX
> nMaxCol
)
2760 tools::Long nGridY
= aPos
.Y() / nGridDY
;
2761 tools::Long nGridsX
= aOutputSize
.Width() / nGridDX
;
2762 GridId nGrid
= (nGridY
* nGridsX
) + nGridX
;
2763 tools::Long nMiddle
= (nGridX
* nGridDX
) + (nGridDX
/ 2);
2764 if( rPos
.X() < nMiddle
)
2767 nGrid
= GRID_NOT_FOUND
;
2774 bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent
& rHEvt
)
2776 if ( !(rHEvt
.GetMode() & HelpEventMode::QUICK
) )
2779 Point
aPos( pView
->ScreenToOutputPixel(rHEvt
.GetMousePosPixel() ) );
2780 aPos
-= pView
->GetMapMode().GetOrigin();
2781 SvxIconChoiceCtrlEntry
* pEntry
= GetEntry( aPos
, true );
2786 OUString sQuickHelpText
= pEntry
->GetQuickHelpText();
2787 OUString
aEntryText( SvtIconChoiceCtrl::GetEntryText( pEntry
) );
2788 tools::Rectangle
aTextRect( CalcTextRect( pEntry
, nullptr, &aEntryText
) );
2789 if ( ( !aTextRect
.IsInside( aPos
) || aEntryText
.isEmpty() ) && sQuickHelpText
.isEmpty() )
2792 tools::Rectangle
aOptTextRect( aTextRect
);
2793 aOptTextRect
.SetBottom( LONG_MAX
);
2794 DrawTextFlags nNewFlags
= nCurTextDrawFlags
;
2795 nNewFlags
&= ~DrawTextFlags( DrawTextFlags::Clip
| DrawTextFlags::EndEllipsis
);
2796 aOptTextRect
= pView
->GetTextRect( aOptTextRect
, aEntryText
, nNewFlags
);
2797 if ( aOptTextRect
!= aTextRect
|| !sQuickHelpText
.isEmpty() )
2799 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
2800 Point
aPt( aOptTextRect
.TopLeft() );
2801 aPt
+= pView
->GetMapMode().GetOrigin();
2802 aPt
= pView
->OutputToScreenPixel( aPt
);
2803 // subtract border of tooltip help
2806 aOptTextRect
.SetPos( aPt
);
2808 if ( !sQuickHelpText
.isEmpty() )
2809 sHelpText
= sQuickHelpText
;
2811 sHelpText
= aEntryText
;
2812 Help::ShowQuickHelp( static_cast<vcl::Window
*>(pView
), aOptTextRect
, sHelpText
, QuickHelpFlags::Left
| QuickHelpFlags::VCenter
);
2818 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex
, const SvxIconChoiceCtrlColumnInfo
& rInfo
)
2821 m_pColumns
.reset(new SvxIconChoiceCtrlColumnInfoMap
);
2823 SvxIconChoiceCtrlColumnInfo
* pInfo
= new SvxIconChoiceCtrlColumnInfo( rInfo
);
2824 m_pColumns
->insert(std::make_pair(nIndex
, std::unique_ptr
<SvxIconChoiceCtrlColumnInfo
>(pInfo
)));
2826 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2827 // fly with a single column
2828 if( !nIndex
&& (nWinBits
& WB_DETAILS
) )
2829 nGridDX
= pInfo
->GetWidth();
2831 if( GetUpdateMode() )
2832 Arrange( IsAutoArrange(), 0, 0 );
2835 const SvxIconChoiceCtrlColumnInfo
* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex
) const
2839 auto const it
= m_pColumns
->find( nIndex
);
2840 if (it
== m_pColumns
->end())
2842 return it
->second
.get();
2845 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rBmpRect
)
2847 tools::Rectangle
aBmpRect(rBmpRect
);
2848 tools::Long nBorder
= 2;
2849 if (aImageSize
.Width() < 32)
2851 aBmpRect
.AdjustRight(nBorder
);
2852 aBmpRect
.AdjustLeft( -nBorder
);
2853 aBmpRect
.AdjustBottom(nBorder
);
2854 aBmpRect
.AdjustTop( -nBorder
);
2856 DecorationView
aDecoView(&rRenderContext
);
2857 DrawHighlightFrameStyle nDecoFlags
;
2858 if (bHighlightFramePressed
)
2859 nDecoFlags
= DrawHighlightFrameStyle::In
;
2861 nDecoFlags
= DrawHighlightFrameStyle::Out
;
2862 aDecoView
.DrawHighlightFrame(aBmpRect
, nDecoFlags
);
2865 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry
* pEntry
,
2866 bool bKeepHighlightFlags
)
2868 if( pEntry
== pCurHighlightFrame
)
2871 if( !bKeepHighlightFlags
)
2872 bHighlightFramePressed
= false;
2874 if (pCurHighlightFrame
)
2876 tools::Rectangle
aInvalidationRect(GetEntryBoundRect(pCurHighlightFrame
));
2877 aInvalidationRect
.expand(5);
2878 pCurHighlightFrame
= nullptr;
2879 pView
->Invalidate(aInvalidationRect
);
2882 pCurHighlightFrame
= pEntry
;
2885 tools::Rectangle
aInvalidationRect(GetEntryBoundRect(pEntry
));
2886 aInvalidationRect
.expand(5);
2887 pView
->Invalidate(aInvalidationRect
);
2891 void SvxIconChoiceCtrl_Impl::CallSelectHandler()
2893 // When single-click mode is active, the selection handler should be called
2894 // synchronously, as the selection is automatically taken away once the
2895 // mouse cursor doesn't touch the object any more. Else, we might run into
2896 // missing calls to Select if the object is selected from a mouse movement,
2897 // because when starting the timer, the mouse cursor might have already left
2899 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
2900 // WB_NOASYNCSELECTHDL.
2901 if( nWinBits
& (WB_NOASYNCSELECTHDL
| WB_HIGHLIGHTFRAME
) )
2903 pHdlEntry
= nullptr;
2908 aCallSelectHdlIdle
.Start();
2911 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl
, CallSelectHdlHdl
, Timer
*, void)
2913 pHdlEntry
= nullptr;
2918 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point
& rPos
)
2920 MapMode
aMapMode( pView
->GetMapMode() );
2921 aMapMode
.SetOrigin( rPos
);
2922 pView
->SetMapMode( aMapMode
);
2925 void SvxIconChoiceCtrl_Impl::CallEventListeners( VclEventId nEvent
, void* pData
)
2927 pView
->CallImplEventListeners( nEvent
, pData
);
2931 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */