Bug Summary

File:home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx
Warning:line 2709, column 24
Access to field 'pblink' results in a dereference of a null pointer (loaded from field 'pHead')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name imivctl1.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx

/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include <limits.h>
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>
35
36#include <vcl/toolkit/ivctrl.hxx>
37#include "imivctl.hxx"
38
39#include <algorithm>
40#include <memory>
41#include <vcl/idle.hxx>
42
43constexpr auto DRAWTEXT_FLAGS_ICON =
44 DrawTextFlags::Center | DrawTextFlags::Top | DrawTextFlags::EndEllipsis |
45 DrawTextFlags::Clip | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak | DrawTextFlags::Mnemonic;
46
47#define DRAWTEXT_FLAGS_SMALLICON(DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags
::Clip)
(DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags::Clip)
48
49#define EVENTID_SHOW_CURSOR(reinterpret_cast<void*>(1)) (reinterpret_cast<void*>(1))
50#define EVENTID_ADJUST_SCROLLBARS(reinterpret_cast<void*>(2)) (reinterpret_cast<void*>(2))
51
52SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
53 SvtIconChoiceCtrl* pCurView,
54 WinBits nWinStyle
55) :
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_WIDTH200), nMaxVirtHeight(DEFAULT_MAX_VIRT_HEIGHT200),
65 nFlags(IconChoiceFlags::NONE), nUserEventAdjustScrBars(nullptr),
66 pCurHighlightFrame(nullptr), bHighlightFramePressed(false), pHead(nullptr), pCursor(nullptr),
67 pHdlEntry(nullptr),
68 pAnchor(nullptr), eTextMode(SvxIconChoiceCtrlTextMode::Short),
69 eSelectionMode(SelectionMode::Multiple), ePositionMode(SvxIconChoiceCtrlPositionMode::Free),
70 bUpdateMode(true)
71{
72 SetStyle( nWinStyle );
73 pImpCursor.reset( new IcnCursor_Impl( this ) );
74 pGridMap.reset( new IcnGridMap_Impl( this ) );
75
76 aVerSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl )::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubScrollUpDownHdl
)
);
77 aHorSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl )::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubScrollLeftRightHdl
)
);
78
79 nHorSBarHeight = aHorSBar->GetSizePixel().Height();
80 nVerSBarWidth = aVerSBar->GetSizePixel().Width();
81
82 aAutoArrangeIdle.SetPriority( TaskPriority::HIGH_IDLE );
83 aAutoArrangeIdle.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl)::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubAutoArrangeHdl
)
);
84 aAutoArrangeIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aAutoArrangeIdle" );
85
86 aCallSelectHdlIdle.SetPriority( TaskPriority::LOWEST );
87 aCallSelectHdlIdle.SetInvokeHandler( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl)::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubCallSelectHdlHdl
)
);
88 aCallSelectHdlIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aCallSelectHdlIdle" );
89
90 aDocRectChangedIdle.SetPriority( TaskPriority::HIGH_IDLE );
91 aDocRectChangedIdle.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl)::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubDocRectChangedHdl
)
);
92 aDocRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" );
93
94 aVisRectChangedIdle.SetPriority( TaskPriority::HIGH_IDLE );
95 aVisRectChangedIdle.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl)::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubVisRectChangedHdl
)
);
96 aVisRectChangedIdle.SetDebugName( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" );
97
98 Clear( true );
99 Size gridSize(100,70);
100 if(pView->GetDPIScaleFactor() > 1)
101 {
102 gridSize.setHeight( gridSize.Height() * ( pView->GetDPIScaleFactor()) );
103 }
104 SetGrid(gridSize);
105}
106
107SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
108{
109 Clear(false);
110 CancelUserEvents();
111 pImpCursor.reset();
112 pGridMap.reset();
113 ClearSelectedRectList();
114 m_pColumns.reset();
115 aVerSBar.disposeAndClear();
116 aHorSBar.disposeAndClear();
117 aScrBarBox.disposeAndClear();
118}
119
120void SvxIconChoiceCtrl_Impl::Clear( bool bInCtor )
121{
122 nSelectionCount = 0;
123 pCurHighlightFrame = nullptr;
124 CancelUserEvents();
125 ShowCursor( false );
126 bBoundRectsDirty = false;
127 nMaxBoundHeight = 0;
128
129 pCursor = nullptr;
130 if( !bInCtor )
131 {
132 pImpCursor->Clear();
133 pGridMap->Clear();
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_WIDTH200;
140 nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
141 if( nMaxVirtHeight <= 0 )
142 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT200;
143 maZOrderList.clear();
144 SetOrigin( Point() );
145 if( bUpdateMode )
146 pView->Invalidate(InvalidateFlags::NoChildren);
147 }
148 AdjustScrollBars();
149 maEntries.clear();
150 DocRectChanged();
151 VisRectChanged();
152}
153
154void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
155{
156 nWinBits = nWinStyle;
157 nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
158 if( nWinBits & (WB_SMALLICONWB_SMALLSTYLE | WB_DETAILSWB_VCENTER) )
159 nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON(DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags
::Clip)
;
160 if( nWinBits & WB_NOSELECTIONWB_REPEAT )
161 eSelectionMode = SelectionMode::NONE;
162 if( !(nWinStyle & (WB_ALIGN_TOPWB_TOP | WB_ALIGN_LEFTWB_LEFT)))
163 nWinBits |= WB_ALIGN_LEFTWB_LEFT;
164 if( nWinStyle & WB_DETAILSWB_VCENTER )
165 {
166 if (!m_pColumns)
167 SetColumn( 0, SvxIconChoiceCtrlColumnInfo() );
168 }
169}
170
171IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar, void )void SvxIconChoiceCtrl_Impl::LinkStubScrollUpDownHdl(void * instance
, ScrollBar* data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->ScrollUpDownHdl(data); } void SvxIconChoiceCtrl_Impl
::ScrollUpDownHdl(ScrollBar* pScrollBar)
172{
173 // arrow up: delta=-1; arrow down: delta=+1
174 Scroll( 0, pScrollBar->GetDelta() );
175}
176
177IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar, void )void SvxIconChoiceCtrl_Impl::LinkStubScrollLeftRightHdl(void *
instance, ScrollBar* data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->ScrollLeftRightHdl(data); } void SvxIconChoiceCtrl_Impl
::ScrollLeftRightHdl(ScrollBar* pScrollBar)
178{
179 // arrow left: delta=-1; arrow right: delta=+1
180 Scroll( pScrollBar->GetDelta(), 0 );
181}
182
183void SvxIconChoiceCtrl_Impl::FontModified()
184{
185 SetDefaultTextSize();
186 ShowCursor( false );
187 ShowCursor( true );
188}
189
190void SvxIconChoiceCtrl_Impl::InsertEntry( std::unique_ptr<SvxIconChoiceCtrlEntry> pEntry1, size_t nPos)
191{
192 auto pEntry = pEntry1.get();
193
194 if ( nPos < maEntries.size() ) {
195 maEntries.insert( maEntries.begin() + nPos, std::move(pEntry1) );
196 } else {
197 maEntries.push_back( std::move(pEntry1) );
198 }
199
200 if( pHead )
201 pEntry->SetBacklink( pHead->pblink );
202
203 if( (nFlags & IconChoiceFlags::EntryListPosValid) && nPos >= maEntries.size() - 1 )
204 pEntry->nPos = maEntries.size() - 1;
205 else
206 nFlags &= ~IconChoiceFlags::EntryListPosValid;
207
208 maZOrderList.push_back( pEntry );
209 pImpCursor->Clear();
210
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_MAX9223372036854775807L );
215 if( bUpdateMode )
216 {
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 );
223 }
224 else
225 InvalidateBoundingRect( pEntry->aRect );
226}
227
228void SvxIconChoiceCtrl_Impl::RemoveEntry(size_t nPos)
229{
230 pImpCursor->Clear();
231 maEntries.erase(maEntries.begin() + nPos);
232 RecalcAllBoundingRectsSmart();
233}
234
235tools::Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
236{
237 Point aOrigin( pView->GetMapMode().GetOrigin() );
238 aOrigin *= -1;
239 return tools::Rectangle( aOrigin, aOutputSize );
240}
241
242void SvxIconChoiceCtrl_Impl::SetListPositions()
243{
244 if( nFlags & IconChoiceFlags::EntryListPosValid )
245 return;
246
247 size_t nCount = maEntries.size();
248 for( size_t nCur = 0; nCur < nCount; nCur++ )
249 {
250 maEntries[ nCur ]->nPos = nCur;
251 }
252 nFlags |= IconChoiceFlags::EntryListPosValid;
253}
254
255void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, bool bSelect,
256 bool bAdd )
257{
258 if( eSelectionMode == SelectionMode::NONE )
259 return;
260
261 if( !bAdd )
262 {
263 if ( !( nFlags & IconChoiceFlags::ClearingSelection ) )
264 {
265 nFlags |= IconChoiceFlags::ClearingSelection;
266 DeselectAllBut( pEntry );
267 nFlags &= ~IconChoiceFlags::ClearingSelection;
268 }
269 }
270 if( pEntry->IsSelected() == bSelect )
271 return;
272
273 pHdlEntry = pEntry;
274 SvxIconViewFlags nEntryFlags = pEntry->GetFlags();
275 if( bSelect )
276 {
277 nEntryFlags |= SvxIconViewFlags::SELECTED;
278 pEntry->AssignFlags( nEntryFlags );
279 nSelectionCount++;
280 CallSelectHandler();
281 }
282 else
283 {
284 nEntryFlags &= ~SvxIconViewFlags::SELECTED;
285 pEntry->AssignFlags( nEntryFlags );
286 nSelectionCount--;
287 CallSelectHandler();
288 }
289 EntrySelected( pEntry, bSelect );
290}
291
292void SvxIconChoiceCtrl_Impl::EntrySelected(SvxIconChoiceCtrlEntry* pEntry, bool bSelect)
293{
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 &&
298 pEntry != pCursor)
299 {
300 SetCursor(pEntry);
301 }
302
303 // Not when dragging though, else the loop in SelectRect doesn't work
304 // correctly!
305 if (!(nFlags & IconChoiceFlags::SelectingRect))
306 ToTop(pEntry);
307 if (bUpdateMode)
308 {
309 if (pEntry == pCursor)
310 ShowCursor(false);
311 pView->Invalidate(CalcFocusRect(pEntry));
312 if (pEntry == pCursor)
313 ShowCursor(true);
314 }
315
316 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
317 if (bSelect)
318 {
319 CallEventListeners(VclEventId::ListboxSelect, pEntry);
320 }
321}
322
323void SvxIconChoiceCtrl_Impl::ResetVirtSize()
324{
325 aVirtOutputSize.setWidth( 0 );
326 aVirtOutputSize.setHeight( 0 );
327 const size_t nCount = maEntries.size();
328 for( size_t nCur = 0; nCur < nCount; nCur++ )
329 {
330 SvxIconChoiceCtrlEntry* pCur = maEntries[ nCur ].get();
331 pCur->ClearFlags( SvxIconViewFlags::POS_MOVED );
332 if( pCur->IsPosLocked() )
333 {
334 // adapt (among others) VirtSize
335 if( !IsBoundingRectValid( pCur->aRect ) )
336 FindBoundingRect( pCur );
337 else
338 AdjustVirtSize( pCur->aRect );
339 }
340 else
341 InvalidateBoundingRect( pCur->aRect );
342 }
343
344 if( !(nWinBits & (WB_NOVSCROLLWB_DRAG | WB_NOHSCROLLWB_SPIN)) )
345 {
346 Size aRealOutputSize( pView->GetOutputSizePixel() );
347 if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
348 aVirtOutputSize.Height() < aRealOutputSize.Height() )
349 {
350 sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
351 aRealOutputSize, static_cast<sal_uInt16>(nGridDX), static_cast<sal_uInt16>(nGridDY) );
352 if( nGridCount < nCount )
353 {
354 if( nWinBits & WB_ALIGN_TOPWB_TOP )
355 nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
356 else // WB_ALIGN_LEFT
357 nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
358 }
359 }
360 }
361
362 pImpCursor->Clear();
363 pGridMap->Clear();
364 VisRectChanged();
365}
366
367void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const tools::Rectangle& rRect )
368{
369 long nHeightOffs = 0;
370 long nWidthOffs = 0;
371
372 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER4) )
373 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER4) - aVirtOutputSize.Width();
374
375 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER4) )
376 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER4) - aVirtOutputSize.Height();
377
378 if( !(nWidthOffs || nHeightOffs) )
379 return;
380
381 Range aRange;
382 aVirtOutputSize.AdjustWidth(nWidthOffs );
383 aRange.Max() = aVirtOutputSize.Width();
384 aHorSBar->SetRange( aRange );
385
386 aVirtOutputSize.AdjustHeight(nHeightOffs );
387 aRange.Max() = aVirtOutputSize.Height();
388 aVerSBar->SetRange( aRange );
389
390 pImpCursor->Clear();
391 pGridMap->OutputSizeChanged();
392 AdjustScrollBars();
393 DocRectChanged();
394}
395
396void SvxIconChoiceCtrl_Impl::InitPredecessors()
397{
398 DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized")do { if (true && (!(!pHead))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "398" ": "), "%s", "SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized"
); } } while (false)
;
59
Taking false branch
60
Loop condition is false. Exiting loop
399 size_t nCount = maEntries.size();
400 if( nCount )
61
Assuming 'nCount' is 0
62
Taking false branch
401 {
402 SvxIconChoiceCtrlEntry* pPrev = maEntries[ 0 ].get();
403 for( size_t nCur = 1; nCur <= nCount; nCur++ )
404 {
405 pPrev->ClearFlags( SvxIconViewFlags::POS_LOCKED | SvxIconViewFlags::POS_MOVED );
406
407 SvxIconChoiceCtrlEntry* pNext;
408 if( nCur == nCount )
409 pNext = maEntries[ 0 ].get();
410 else
411 pNext = maEntries[ nCur ].get();
412 pPrev->pflink = pNext;
413 pNext->pblink = pPrev;
414 pPrev = pNext;
415 }
416 pHead = maEntries[ 0 ].get();
417 }
418 else
419 pHead = nullptr;
63
Null pointer value stored to field 'pHead'
420}
421
422void SvxIconChoiceCtrl_Impl::ClearPredecessors()
423{
424 if( pHead )
425 {
426 size_t nCount = maEntries.size();
427 for( size_t nCur = 0; nCur < nCount; nCur++ )
428 {
429 SvxIconChoiceCtrlEntry* pCur = maEntries[ nCur ].get();
430 pCur->pflink = nullptr;
431 pCur->pblink = nullptr;
432 }
433 pHead = nullptr;
434 }
435}
436
437void SvxIconChoiceCtrl_Impl::Arrange( bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
438{
439 if ( nSetMaxVirtWidth != 0 )
440 nMaxVirtWidth = nSetMaxVirtWidth;
441 else
442 nMaxVirtWidth = aOutputSize.Width();
443
444 if ( nSetMaxVirtHeight != 0 )
445 nMaxVirtHeight = nSetMaxVirtHeight;
446 else
447 nMaxVirtHeight = aOutputSize.Height();
448
449 ImpArrange( bKeepPredecessors );
450}
451
452void SvxIconChoiceCtrl_Impl::ImpArrange( bool bKeepPredecessors )
453{
454 static Point aEmptyPoint;
455
456 bool bOldUpdate = bUpdateMode;
457 tools::Rectangle aCurOutputArea( GetOutputRect() );
458 if( (nWinBits & WB_SMART_ARRANGE0x01000000) && aCurOutputArea.TopLeft() != aEmptyPoint )
459 bUpdateMode = false;
460 aAutoArrangeIdle.Stop();
461 nFlags |= IconChoiceFlags::Arranging;
462 ShowCursor( false );
463 ResetVirtSize();
464 if( !bKeepPredecessors )
465 ClearPredecessors();
466 bBoundRectsDirty = false;
467 SetOrigin( Point() );
468 VisRectChanged();
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_ARRANGE0x01000000) && aCurOutputArea.TopLeft() != aEmptyPoint )
475 {
476 MakeVisible( aCurOutputArea );
477 SetUpdateMode( bOldUpdate );
478 }
479 ShowCursor( true );
480}
481
482void SvxIconChoiceCtrl_Impl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
483{
484#if defined(OV_DRAWGRID)
485 Color aOldColor (rRenderContext.GetLineColor());
486 Color aCOL_BLACK);
487 rRenderContext.SetLineColor( aColor );
488 Point aOffs(rRenderContext.GetMapMode().GetOrigin());
489 Size aXSize(GetOutputSizePixel());
490 {
491 Point aStart(LROFFS_WINBORDER4, 0);
492 Point aEnd(LROFFS_WINBORDER4, aXSize.Height());
493 aStart -= aOffs;
494 aEnd -= aOffs;
495 rRenderContext.DrawLine(aStart, aEnd);
496 }
497 {
498 Point aStart(0, TBOFFS_WINBORDER4);
499 Point aEnd(aXSize.Width(), TBOFFS_WINBORDER4);
500 aStart -= aOffs;
501 aEnd -= aOffs;
502 rRenderContext.DrawLine(aStart, aEnd);
503 }
504
505 for (long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX)
506 {
507 Point aStart( nDX+LROFFS_WINBORDER4, 0 );
508 Point aEnd( nDX+LROFFS_WINBORDER4, aXSize.Height());
509 aStart -= aOffs;
510 aEnd -= aOffs;
511 rRenderContext.DrawLine(aStart, aEnd);
512 }
513 for (long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY)
514 {
515 Point aStart(0, nDY + TBOFFS_WINBORDER4);
516 Point aEnd(aXSize.Width(), nDY + TBOFFS_WINBORDER4);
517 aStart -= aOffs;
518 aEnd -= aOffs;
519 rRenderContext.DrawLine(aStart, aEnd);
520 }
521 rRenderContext.SetLineColor(aOldColor);
522#endif
523
524 if (!maEntries.size())
525 return;
526 if (!pCursor)
527 {
528 // set cursor to item with focus-flag
529 bool bfound = false;
530 for (sal_Int32 i = 0; i < pView->GetEntryCount() && !bfound; i++)
531 {
532 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry(i);
533 if (pEntry->IsFocused())
534 {
535 pCursor = pEntry;
536 bfound = true;
537 }
538 }
539
540 if (!bfound)
541 pCursor = maEntries[ 0 ].get();
542 }
543
544 size_t nCount = maZOrderList.size();
545 if (!nCount)
546 return;
547
548 rRenderContext.Push(PushFlags::CLIPREGION);
549 rRenderContext.SetClipRegion(vcl::Region(rRect));
550
551 std::vector< SvxIconChoiceCtrlEntry* > aNewZOrderList;
552 std::vector< SvxIconChoiceCtrlEntry* > aPaintedEntries;
553
554 size_t nPos = 0;
555 while(nCount)
556 {
557 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[nPos];
558 const tools::Rectangle& rBoundRect = GetEntryBoundRect(pEntry);
559 if (rRect.IsOver(rBoundRect))
560 {
561 PaintEntry(pEntry, rBoundRect.TopLeft(), rRenderContext);
562 // set entries to Top if they are being repainted
563 aPaintedEntries.push_back(pEntry);
564 }
565 else
566 aNewZOrderList.push_back(pEntry);
567
568 nCount--;
569 nPos++;
570 }
571 maZOrderList = std::move( aNewZOrderList );
572 maZOrderList.insert(maZOrderList.end(), aPaintedEntries.begin(), aPaintedEntries.end());
573
574 rRenderContext.Pop();
575}
576
577void SvxIconChoiceCtrl_Impl::RepaintSelectedEntries()
578{
579 const size_t nCount = maZOrderList.size();
580 if (!nCount)
581 return;
582
583 tools::Rectangle aOutRect(GetOutputRect());
584 for (size_t nCur = 0; nCur < nCount; nCur++)
585 {
586 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[nCur];
587 if (pEntry->GetFlags() & SvxIconViewFlags::SELECTED)
588 {
589 const tools::Rectangle& rBoundRect = GetEntryBoundRect(pEntry);
590 if (aOutRect.IsOver(rBoundRect))
591 pView->Invalidate(rBoundRect);
592 }
593 }
594}
595
596void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
597{
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));
601}
602
603bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
604{
605 bool bHandled = true;
606 bHighlightFramePressed = false;
607 bool bGotFocus = (!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
608 if( !(nWinBits & WB_NOPOINTERFOCUS) )
609 pView->GrabFocus();
610
611 Point aDocPos( rMEvt.GetPosPixel() );
612 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
613 return false;
614 ToDocPos( aDocPos );
615 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, true );
616 if( pEntry )
617 MakeEntryVisible( pEntry, false );
618
619 if( rMEvt.IsShift() && eSelectionMode != SelectionMode::Single )
620 {
621 if( pEntry )
622 SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift() );
623 return true;
624 }
625
626 if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // keyboard selection?
627 {
628 DBG_ASSERT(eSelectionMode != SelectionMode::Single,"Invalid selection mode")do { if (true && (!(eSelectionMode != SelectionMode::
Single))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN),
("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "628" ": "), "%s", "Invalid selection mode"); } } while (
false)
;
629 if( rMEvt.IsMod1() )
630 nFlags |= IconChoiceFlags::AddMode;
631
632 if( rMEvt.IsShift() )
633 {
634 tools::Rectangle aRect( GetEntryBoundRect( pAnchor ));
635 if( pEntry )
636 aRect.Union( GetEntryBoundRect( pEntry ) );
637 else
638 {
639 tools::Rectangle aTempRect( aDocPos, Size(1,1));
640 aRect.Union( aTempRect );
641 }
642 aCurSelectionRect = aRect;
643 SelectRect( aRect, bool(nFlags & IconChoiceFlags::AddMode), &aSelectedRectList );
644 }
645 else if( rMEvt.IsMod1() )
646 {
647 AddSelectedRect( aCurSelectionRect );
648 pAnchor = nullptr;
649 aCurSelectionRect.SetPos( aDocPos );
650 }
651
652 if( !pEntry && !(nWinBits & WB_NODRAGSELECTIONWB_PATHELLIPSIS))
653 pView->StartTracking( StartTrackingFlags::ScrollRepeat );
654 return true;
655 }
656 else
657 {
658 if( !pEntry )
659 {
660 if( eSelectionMode == SelectionMode::Multiple )
661 {
662 if( !rMEvt.IsMod1() ) // Ctrl
663 {
664 if( !bGotFocus )
665 {
666 SetNoSelection();
667 ClearSelectedRectList();
668 }
669 }
670 else
671 nFlags |= IconChoiceFlags::AddMode;
672 aCurSelectionRect.SetPos( aDocPos );
673 pView->StartTracking( StartTrackingFlags::ScrollRepeat );
674 }
675 else
676 bHandled = false;
677 return bHandled;
678 }
679 }
680 bool bSelected = pEntry->IsSelected();
681
682 if( rMEvt.GetClicks() == 2 )
683 {
684 DeselectAllBut( pEntry );
685 SelectEntry( pEntry, true, false );
686 pHdlEntry = pEntry;
687 pView->ClickIcon();
688 }
689 else
690 {
691 // Inplace-Editing ?
692 if( rMEvt.IsMod2() ) // Alt?
693 {
694 }
695 else if( eSelectionMode == SelectionMode::Single )
696 {
697 DeselectAllBut( pEntry );
698 SetCursor( pEntry );
699 }
700 else if( eSelectionMode == SelectionMode::NONE )
701 {
702 if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAMEWB_IGNORETAB) )
703 {
704 pCurHighlightFrame = nullptr; // force repaint of frame
705 bHighlightFramePressed = true;
706 SetEntryHighlightFrame( pEntry, true );
707 }
708 }
709 else
710 {
711 if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
712 {
713 if( !bSelected )
714 {
715 DeselectAllBut( pEntry );
716 SetCursor( pEntry );
717 SelectEntry( pEntry, true, false );
718 }
719 else
720 {
721 // deselect only in the Up, if the Move happened via D&D!
722 nFlags |= IconChoiceFlags::DownDeselect;
723 }
724 }
725 else if( rMEvt.IsMod1() )
726 nFlags |= IconChoiceFlags::DownCtrl;
727 }
728 }
729 return bHandled;
730}
731
732bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
733{
734 bool bHandled = false;
735 if( rMEvt.IsRight() && (nFlags & (IconChoiceFlags::DownCtrl | IconChoiceFlags::DownDeselect) ))
736 {
737 nFlags &= ~IconChoiceFlags(IconChoiceFlags::DownCtrl | IconChoiceFlags::DownDeselect);
738 bHandled = true;
739 }
740
741 Point aDocPos( rMEvt.GetPosPixel() );
742 ToDocPos( aDocPos );
743 SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
744 if( pDocEntry )
745 {
746 if( nFlags & IconChoiceFlags::DownCtrl )
747 {
748 // Ctrl & MultiSelection
749 ToggleSelection( pDocEntry );
750 SetCursor( pDocEntry );
751 bHandled = true;
752 }
753 else if( nFlags & IconChoiceFlags::DownDeselect )
754 {
755 DeselectAllBut( pDocEntry );
756 SetCursor( pDocEntry );
757 SelectEntry( pDocEntry, true, false );
758 bHandled = true;
759 }
760 }
761
762 nFlags &= ~IconChoiceFlags(IconChoiceFlags::DownCtrl | IconChoiceFlags::DownDeselect);
763
764 if((nWinBits & WB_HIGHLIGHTFRAMEWB_IGNORETAB) && bHighlightFramePressed && pCurHighlightFrame)
765 {
766 bHandled = true;
767 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
768 pCurHighlightFrame = nullptr; // force repaint of frame
769 bHighlightFramePressed = false;
770 SetEntryHighlightFrame( pEntry, true );
771
772 pHdlEntry = pCurHighlightFrame;
773 pView->ClickIcon();
774
775 // set focus on Icon
776 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
777 SetCursor_Impl( pOldCursor, pHdlEntry, false, false );
778
779 pHdlEntry = nullptr;
780 }
781 return bHandled;
782}
783
784bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
785{
786 const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
787
788 if( pView->IsTracking() )
789 return false;
790 else if( nWinBits & WB_HIGHLIGHTFRAMEWB_IGNORETAB )
791 {
792 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, true );
793 SetEntryHighlightFrame( pEntry, false );
794 }
795 else
796 return false;
797 return true;
798}
799
800void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
801 SvxIconChoiceCtrlEntry* pNewCursor, bool bMod1, bool bShift )
802{
803 if( !pNewCursor )
804 return;
805
806 SvxIconChoiceCtrlEntry* pFilterEntry = nullptr;
807 bool bDeselectAll = false;
808 if( eSelectionMode != SelectionMode::Single )
809 {
810 if( !bMod1 && !bShift )
811 bDeselectAll = true;
812 else if( bShift && !bMod1 && !pAnchor )
813 {
814 bDeselectAll = true;
815 pFilterEntry = pOldCursor;
816 }
817 }
818 if( bDeselectAll )
819 DeselectAllBut( pFilterEntry );
820 ShowCursor( false );
821 MakeEntryVisible( pNewCursor );
822 SetCursor( pNewCursor );
823 if( bMod1 && !bShift )
824 {
825 if( pAnchor )
826 {
827 AddSelectedRect( pAnchor, pOldCursor );
828 pAnchor = nullptr;
829 }
830 }
831 else if( bShift )
832 {
833 if( !pAnchor )
834 pAnchor = pOldCursor;
835 if ( nWinBits & WB_ALIGN_LEFTWB_LEFT )
836 SelectRange( pAnchor, pNewCursor, bool(nFlags & IconChoiceFlags::AddMode) );
837 else
838 SelectRect(pAnchor,pNewCursor, bool(nFlags & IconChoiceFlags::AddMode), &aSelectedRectList);
839 }
840 else
841 {
842 SelectEntry( pCursor, true, false );
843 aCurSelectionRect = GetEntryBoundRect( pCursor );
844 CallEventListeners( VclEventId::ListboxSelect, pCursor );
845 }
846}
847
848bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
849{
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 ) )
854 {
855 // shortcut is clicked
856 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
857 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
858 if ( pNewCursor != pOldCursor )
859 SetCursor_Impl( pOldCursor, pNewCursor, false, false );
860 return true;
861 }
862
863 if ( bMod2 )
864 // no actions with <ALT>
865 return false;
866
867 bool bKeyUsed = true;
868 bool bMod1 = rKEvt.GetKeyCode().IsMod1();
869 bool bShift = rKEvt.GetKeyCode().IsShift();
870
871 if( eSelectionMode == SelectionMode::Single || eSelectionMode == SelectionMode::NONE)
872 {
873 bShift = false;
874 bMod1 = false;
875 }
876
877 if( bMod1 )
878 nFlags |= IconChoiceFlags::AddMode;
879
880 SvxIconChoiceCtrlEntry* pNewCursor;
881 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
882
883 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
884 switch( nCode )
885 {
886 case KEY_UP:
887 case KEY_PAGEUP:
888 if( pCursor )
889 {
890 MakeEntryVisible( pCursor );
891 if( nCode == KEY_UP )
892 pNewCursor = pImpCursor->GoUpDown(pCursor,false);
893 else
894 pNewCursor = pImpCursor->GoPageUpDown(pCursor,false);
895 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
896 if( !pNewCursor )
897 {
898 tools::Rectangle aRect( GetEntryBoundRect( pCursor ) );
899 if( aRect.Top())
900 {
901 aRect.AdjustBottom( -(aRect.Top()) );
902 aRect.SetTop( 0 );
903 MakeVisible( aRect );
904 }
905 }
906 }
907 break;
908
909 case KEY_DOWN:
910 case KEY_PAGEDOWN:
911 if( pCursor )
912 {
913 if( nCode == KEY_DOWN )
914 pNewCursor=pImpCursor->GoUpDown( pCursor,true );
915 else
916 pNewCursor=pImpCursor->GoPageUpDown( pCursor,true );
917 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
918 }
919 break;
920
921 case KEY_RIGHT:
922 if( pCursor )
923 {
924 pNewCursor=pImpCursor->GoLeftRight(pCursor,true );
925 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
926 }
927 break;
928
929 case KEY_LEFT:
930 if( pCursor )
931 {
932 MakeEntryVisible( pCursor );
933 pNewCursor = pImpCursor->GoLeftRight(pCursor,false );
934 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
935 if( !pNewCursor )
936 {
937 tools::Rectangle aRect( GetEntryBoundRect(pCursor));
938 if( aRect.Left() )
939 {
940 aRect.AdjustRight( -(aRect.Left()) );
941 aRect.SetLeft( 0 );
942 MakeVisible( aRect );
943 }
944 }
945 }
946 break;
947
948 case KEY_F2:
949 if( bMod1 || bShift )
950 bKeyUsed = false;
951 break;
952
953 case KEY_F8:
954 if( rKEvt.GetKeyCode().IsShift() )
955 {
956 if( nFlags & IconChoiceFlags::AddMode )
957 nFlags &= ~IconChoiceFlags::AddMode;
958 else
959 nFlags |= IconChoiceFlags::AddMode;
960 }
961 else
962 bKeyUsed = false;
963 break;
964
965 case KEY_SPACE:
966 if( pCursor && eSelectionMode != SelectionMode::Single )
967 {
968 if( !bMod1 )
969 {
970 //SelectAll( false );
971 SetNoSelection();
972 ClearSelectedRectList();
973
974 // click Icon with spacebar
975 SetEntryHighlightFrame( GetCurEntry(), true );
976 pView->ClickIcon();
977 pHdlEntry = pCurHighlightFrame;
978 pCurHighlightFrame=nullptr;
979 }
980 else
981 ToggleSelection( pCursor );
982 }
983 break;
984
985#ifdef DBG_UTIL
986 case KEY_F10:
987 if( rKEvt.GetKeyCode().IsShift() )
988 {
989 if( pCursor )
990 pView->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Full, pCursor );
991 }
992 if( rKEvt.GetKeyCode().IsMod1() )
993 {
994 if( pCursor )
995 pView->SetEntryTextMode( SvxIconChoiceCtrlTextMode::Short, pCursor );
996 }
997 break;
998#endif
999
1000 case KEY_ADD:
1001 case KEY_DIVIDE :
1002 case KEY_A:
1003 if( bMod1 && (eSelectionMode != SelectionMode::Single))
1004 SelectAll();
1005 else
1006 bKeyUsed = false;
1007 break;
1008
1009 case KEY_SUBTRACT:
1010 case KEY_COMMA :
1011 if( bMod1 )
1012 SetNoSelection();
1013 else
1014 bKeyUsed = false;
1015 break;
1016
1017 case KEY_RETURN:
1018 if( !bMod1 )
1019 bKeyUsed = false;
1020 break;
1021
1022 case KEY_END:
1023 if( pCursor )
1024 {
1025 pNewCursor = maEntries.back().get();
1026 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
1027 }
1028 break;
1029
1030 case KEY_HOME:
1031 if( pCursor )
1032 {
1033 pNewCursor = maEntries[ 0 ].get();
1034 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift );
1035 }
1036 break;
1037
1038 default:
1039 bKeyUsed = false;
1040
1041 }
1042 return bKeyUsed;
1043}
1044
1045// recalculate TopLeft of scrollbars (but not their sizes!)
1046void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1047{
1048 // horizontal scrollbar
1049 Point aPos( 0, nRealHeight );
1050 aPos.AdjustY( -nHorSBarHeight );
1051
1052 if( aHorSBar->GetPosPixel() != aPos )
1053 aHorSBar->SetPosPixel( aPos );
1054
1055 // vertical scrollbar
1056 aPos.setX( nRealWidth ); aPos.setY( 0 );
1057 aPos.AdjustX( -nVerSBarWidth );
1058 aPos.AdjustX( 1 );
1059 aPos.AdjustY( -1 );
1060
1061 if( aVerSBar->GetPosPixel() != aPos )
1062 aVerSBar->SetPosPixel( aPos );
1063}
1064
1065void SvxIconChoiceCtrl_Impl::AdjustScrollBars()
1066{
1067 long nVirtHeight = aVirtOutputSize.Height();
1068 long nVirtWidth = aVirtOutputSize.Width();
1069
1070 Size aOSize( pView->Control::GetOutputSizePixel() );
1071 long nRealHeight = aOSize.Height();
1072 long nRealWidth = aOSize.Width();
1073
1074 PositionScrollBars( nRealWidth, nRealHeight );
1075
1076 const MapMode& rMapMode = pView->GetMapMode();
1077 Point aOrigin( rMapMode.GetOrigin() );
1078
1079 long nVisibleWidth;
1080 if( nRealWidth > nVirtWidth )
1081 nVisibleWidth = nVirtWidth + aOrigin.X();
1082 else
1083 nVisibleWidth = nRealWidth;
1084
1085 long nVisibleHeight;
1086 if( nRealHeight > nVirtHeight )
1087 nVisibleHeight = nVirtHeight + aOrigin.Y();
1088 else
1089 nVisibleHeight = nRealHeight;
1090
1091 bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1092 bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1093 bool bNoVerSBar = ( nWinBits & WB_NOVSCROLLWB_DRAG ) != 0;
1094 bool bNoHorSBar = ( nWinBits & WB_NOHSCROLLWB_SPIN ) != 0;
1095
1096 sal_uInt16 nResult = 0;
1097 if( nVirtHeight )
1098 {
1099 // activate vertical scrollbar?
1100 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1101 {
1102 nResult = 0x0001;
1103 nRealWidth -= nVerSBarWidth;
1104
1105 if( nRealWidth > nVirtWidth )
1106 nVisibleWidth = nVirtWidth + aOrigin.X();
1107 else
1108 nVisibleWidth = nRealWidth;
1109 }
1110 // activate horizontal scrollbar?
1111 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1112 {
1113 nResult |= 0x0002;
1114 nRealHeight -= nHorSBarHeight;
1115
1116 if( nRealHeight > nVirtHeight )
1117 nVisibleHeight = nVirtHeight + aOrigin.Y();
1118 else
1119 nVisibleHeight = nRealHeight;
1120
1121 // do we need a vertical scrollbar after all?
1122 if( !(nResult & 0x0001) && // only if not already there
1123 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1124 {
1125 nResult = 3; // both turned on
1126 nRealWidth -= nVerSBarWidth;
1127
1128 if( nRealWidth > nVirtWidth )
1129 nVisibleWidth = nVirtWidth + aOrigin.X();
1130 else
1131 nVisibleWidth = nRealWidth;
1132 }
1133 }
1134 }
1135
1136 // size vertical scrollbar
1137 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 ));
1144
1145 if( nResult & 0x0001 )
1146 {
1147 aVerSBar->SetThumbPos( nThumb );
1148 aVerSBar->Show();
1149 }
1150 else
1151 {
1152 aVerSBar->SetThumbPos( 0 );
1153 aVerSBar->Hide();
1154 }
1155
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?
1162 {
1163 aSize.AdjustWidth( 1 );
1164 nRealWidth++;
1165 }
1166 if( aSize != aHorSBar->GetSizePixel() )
1167 aHorSBar->SetSizePixel( aSize );
1168 aHorSBar->SetVisibleSize( nVisibleWidth );
1169 aHorSBar->SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1170 if( nResult & 0x0002 )
1171 {
1172 aHorSBar->SetThumbPos( nThumb );
1173 aHorSBar->Show();
1174 }
1175 else
1176 {
1177 aHorSBar->SetThumbPos( 0 );
1178 aHorSBar->Hide();
1179 }
1180
1181 aOutputSize.setWidth( nRealWidth );
1182 if( nResult & 0x0002 ) // horizontal scrollbar ?
1183 nRealHeight++; // because lower border is clipped
1184 aOutputSize.setHeight( nRealHeight );
1185
1186 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1187 aScrBarBox->Show();
1188 else
1189 aScrBarBox->Hide();
1190}
1191
1192void SvxIconChoiceCtrl_Impl::Resize()
1193{
1194 InitScrollBarBox();
1195 aOutputSize = pView->GetOutputSizePixel();
1196 pImpCursor->Clear();
1197 pGridMap->OutputSizeChanged();
1198
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)::tools::detail::makeLink( ::tools::detail::castTo<SvxIconChoiceCtrl_Impl
*>(this), &SvxIconChoiceCtrl_Impl::LinkStubUserEventHdl
)
,
1209 EVENTID_ADJUST_SCROLLBARS(reinterpret_cast<void*>(2)));
1210
1211 VisRectChanged();
1212}
1213
1214bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1215{
1216 if( maZOrderList.empty() || !aHorSBar->IsVisible() )
1217 return false;
1218 const MapMode& rMapMode = pView->GetMapMode();
1219 Point aOrigin( rMapMode.GetOrigin() );
1220 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1221 {
1222 long nWidth = aOutputSize.Width();
1223 const size_t nCount = maZOrderList.size();
1224 long nMostRight = 0;
1225 for( size_t nCur = 0; nCur < nCount; nCur++ )
1226 {
1227 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCur ];
1228 long nRight = GetEntryBoundRect(pEntry).Right();
1229 if( nRight > nWidth )
1230 return false;
1231 if( nRight > nMostRight )
1232 nMostRight = nRight;
1233 }
1234 aHorSBar->Hide();
1235 aOutputSize.AdjustHeight(nHorSBarHeight );
1236 aVirtOutputSize.setWidth( nMostRight );
1237 aHorSBar->SetThumbPos( 0 );
1238 Range aRange;
1239 aRange.Max() = nMostRight - 1;
1240 aHorSBar->SetRange( aRange );
1241 if( aVerSBar->IsVisible() )
1242 {
1243 Size aSize( aVerSBar->GetSizePixel());
1244 aSize.AdjustHeight(nHorSBarHeight );
1245 aVerSBar->SetSizePixel( aSize );
1246 }
1247 return true;
1248 }
1249 return false;
1250}
1251
1252bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1253{
1254 if( maZOrderList.empty() || !aVerSBar->IsVisible() )
1255 return false;
1256 const MapMode& rMapMode = pView->GetMapMode();
1257 Point aOrigin( rMapMode.GetOrigin() );
1258 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1259 {
1260 long nDeepest = 0;
1261 long nHeight = aOutputSize.Height();
1262 const size_t nCount = maZOrderList.size();
1263 for( size_t nCur = 0; nCur < nCount; nCur++ )
1264 {
1265 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCur ];
1266 long nBottom = GetEntryBoundRect(pEntry).Bottom();
1267 if( nBottom > nHeight )
1268 return false;
1269 if( nBottom > nDeepest )
1270 nDeepest = nBottom;
1271 }
1272 aVerSBar->Hide();
1273 aOutputSize.AdjustWidth(nVerSBarWidth );
1274 aVirtOutputSize.setHeight( nDeepest );
1275 aVerSBar->SetThumbPos( 0 );
1276 Range aRange;
1277 aRange.Max() = nDeepest - 1;
1278 aVerSBar->SetRange( aRange );
1279 if( aHorSBar->IsVisible() )
1280 {
1281 Size aSize( aHorSBar->GetSizePixel());
1282 aSize.AdjustWidth(nVerSBarWidth );
1283 aHorSBar->SetSizePixel( aSize );
1284 }
1285 return true;
1286 }
1287 return false;
1288}
1289
1290
1291// hides scrollbars if they're unnecessary
1292void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1293{
1294 CheckVerScrollBar();
1295 if( CheckHorScrollBar() )
1296 CheckVerScrollBar();
1297 if( aVerSBar->IsVisible() && aHorSBar->IsVisible() )
1298 aScrBarBox->Show();
1299 else
1300 aScrBarBox->Hide();
1301}
1302
1303
1304void SvxIconChoiceCtrl_Impl::GetFocus()
1305{
1306 RepaintSelectedEntries();
1307 if( pCursor )
1308 {
1309 pCursor->SetFlags( SvxIconViewFlags::FOCUSED );
1310 ShowCursor( true );
1311 }
1312}
1313
1314void SvxIconChoiceCtrl_Impl::LoseFocus()
1315{
1316 if( pCursor )
1317 pCursor->ClearFlags( SvxIconViewFlags::FOCUSED );
1318 ShowCursor( false );
1319
1320// HideFocus ();
1321// pView->Invalidate ( aFocus.aRect );
1322
1323 RepaintSelectedEntries();
1324}
1325
1326void SvxIconChoiceCtrl_Impl::SetUpdateMode( bool bUpdate )
1327{
1328 if( bUpdate != bUpdateMode )
1329 {
1330 bUpdateMode = bUpdate;
1331 if( bUpdate )
1332 {
1333 AdjustScrollBars();
1334 pImpCursor->Clear();
1335 pGridMap->Clear();
1336 pView->Invalidate(InvalidateFlags::NoChildren);
1337 }
1338 }
1339}
1340
1341// priorities of the emphasis: bSelected
1342void SvxIconChoiceCtrl_Impl::PaintEmphasis(const tools::Rectangle& rTextRect, bool bSelected,
1343 vcl::RenderContext& rRenderContext)
1344{
1345 Color aOldFillColor(rRenderContext.GetFillColor());
1346
1347 bool bSolidTextRect = false;
1348
1349 if (!bSelected)
1350 {
1351 const Color& rFillColor = rRenderContext.GetFont().GetFillColor();
1352 rRenderContext.SetFillColor(rFillColor);
1353 if (rFillColor != COL_TRANSPARENT)
1354 bSolidTextRect = true;
1355 }
1356
1357 // draw text rectangle
1358 if (bSolidTextRect)
1359 {
1360 rRenderContext.DrawRect(rTextRect);
1361 }
1362
1363 rRenderContext.SetFillColor(aOldFillColor);
1364}
1365
1366
1367void SvxIconChoiceCtrl_Impl::PaintItem(const tools::Rectangle& rRect,
1368 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1369 vcl::RenderContext& rRenderContext )
1370{
1371 if (eItem == IcnViewFieldType::Text)
1372 {
1373 OUString aText = SvtIconChoiceCtrl::GetEntryText(pEntry);
1374
1375 rRenderContext.DrawText(rRect, aText, nCurTextDrawFlags);
1376
1377 if (pEntry->IsFocused())
1378 {
1379 tools::Rectangle aRect (CalcFocusRect(pEntry));
1380 ShowFocus(aRect);
1381 DrawFocusRect(rRenderContext);
1382 }
1383 }
1384 else
1385 {
1386 Point aPos(rRect.TopLeft());
1387 if (nPaintFlags & PAINTFLAG_HOR_CENTERED0x0001)
1388 aPos.AdjustX((rRect.GetWidth() - aImageSize.Width()) / 2 );
1389 if (nPaintFlags & PAINTFLAG_VER_CENTERED0x0002)
1390 aPos.AdjustY((rRect.GetHeight() - aImageSize.Height()) / 2 );
1391 SvtIconChoiceCtrl::DrawEntryImage(pEntry, aPos, rRenderContext);
1392 }
1393}
1394
1395void SvxIconChoiceCtrl_Impl::PaintEntry(SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, vcl::RenderContext& rRenderContext)
1396{
1397 bool bSelected = false;
1398
1399 if (eSelectionMode != SelectionMode::NONE)
1400 bSelected = pEntry->IsSelected();
1401
1402 rRenderContext.Push(PushFlags::FONT | PushFlags::TEXTCOLOR);
1403
1404 OUString aEntryText(SvtIconChoiceCtrl::GetEntryText(pEntry));
1405 tools::Rectangle aTextRect(CalcTextRect(pEntry, &rPos, &aEntryText));
1406 tools::Rectangle aBmpRect(CalcBmpRect(pEntry, &rPos));
1407
1408 bool bShowSelection = (bSelected && (eSelectionMode != SelectionMode::NONE));
1409
1410 bool bActiveSelection = (0 != (nWinBits & WB_NOHIDESELECTION)) || pView->HasFocus();
1411
1412 if (bShowSelection)
1413 {
1414 const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
1415 vcl::Font aNewFont(rRenderContext.GetFont());
1416
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());
1421 else
1422 aNewFont.SetFillColor(rSettings.GetDeactiveColor());
1423
1424 Color aWinCol = rSettings.GetWindowTextColor();
1425 if (!bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright())
1426 aNewFont.SetColor(rSettings.GetWindowTextColor());
1427 else
1428 aNewFont.SetColor(rSettings.GetHighlightTextColor());
1429
1430 rRenderContext.SetFont(aNewFont);
1431
1432 rRenderContext.SetFillColor(rRenderContext.GetBackground().GetColor());
1433 rRenderContext.DrawRect(CalcFocusRect(pEntry));
1434 rRenderContext.SetFillColor();
1435 }
1436
1437 bool bResetClipRegion = false;
1438 if (!rRenderContext.IsClipRegion() && (aVerSBar->IsVisible() || aHorSBar->IsVisible()))
1439 {
1440 tools::Rectangle aOutputArea(GetOutputRect());
1441 if (aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect))
1442 {
1443 rRenderContext.SetClipRegion(vcl::Region(aOutputArea));
1444 bResetClipRegion = true;
1445 }
1446 }
1447
1448 bool bLargeIconMode = WB_ICONWB_RECTSTYLE == ( nWinBits & VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) );
1449 sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED0x0002;
1450 if (bLargeIconMode)
1451 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED0x0001;
1452 sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED0x0001 : PAINTFLAG_VER_CENTERED0x0002;
1453
1454 PaintEmphasis(aTextRect, bSelected, rRenderContext);
1455
1456 if ( bShowSelection )
1457 vcl::RenderTools::DrawSelectionBackground(rRenderContext, *pView, CalcFocusRect(pEntry),
1458 bActiveSelection ? 1 : 2, false, true, false);
1459
1460
1461 PaintItem(aBmpRect, IcnViewFieldType::Image, pEntry, nBmpPaintFlags, rRenderContext);
1462
1463 PaintItem(aTextRect, IcnViewFieldType::Text, pEntry, nTextPaintFlags, rRenderContext);
1464
1465 // draw highlight frame
1466 if (pEntry == pCurHighlightFrame)
1467 DrawHighlightFrame(rRenderContext, CalcFocusRect(pEntry));
1468
1469 rRenderContext.Pop();
1470 if (bResetClipRegion)
1471 rRenderContext.SetClipRegion();
1472}
1473
1474void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos )
1475{
1476 ShowCursor( false );
1477 tools::Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
18
Calling 'SvxIconChoiceCtrl_Impl::GetEntryBoundRect'
21
Returning from 'SvxIconChoiceCtrl_Impl::GetEntryBoundRect'
1478 pView->Invalidate( aBoundRect );
1479 ToTop( pEntry );
22
Calling 'SvxIconChoiceCtrl_Impl::ToTop'
25
Returning from 'SvxIconChoiceCtrl_Impl::ToTop'
1480 if( !IsAutoArrange() )
26
Calling 'SvxIconChoiceCtrl_Impl::IsAutoArrange'
29
Returning from 'SvxIconChoiceCtrl_Impl::IsAutoArrange'
30
Taking false branch
1481 {
1482 bool bAdjustVirtSize = false;
1483 if( rPos != aBoundRect.TopLeft() )
1484 {
1485 Point aGridOffs(
1486 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
1487 pImpCursor->Clear();
1488 pGridMap->Clear();
1489 aBoundRect.SetPos( rPos );
1490 pEntry->aRect = aBoundRect;
1491 pEntry->aGridRect.SetPos( rPos + aGridOffs );
1492 bAdjustVirtSize = true;
1493 }
1494 if( bAdjustVirtSize )
1495 AdjustVirtSize( pEntry->aRect );
1496
1497 pView->Invalidate( pEntry->aRect );
1498 pGridMap->OccupyGrids( pEntry );
1499 }
1500 else
1501 {
1502 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
31
Calling 'SvxIconChoiceCtrl_Impl::FindEntryPredecessor'
39
Returning from 'SvxIconChoiceCtrl_Impl::FindEntryPredecessor'
1503 SetEntryPredecessor( pEntry, pPrev );
40
Calling 'SvxIconChoiceCtrl_Impl::SetEntryPredecessor'
1504 aAutoArrangeIdle.Start();
1505 }
1506 ShowCursor( true );
1507}
1508
1509void SvxIconChoiceCtrl_Impl::SetNoSelection()
1510{
1511 // block recursive calls via SelectEntry
1512 if( !(nFlags & IconChoiceFlags::ClearingSelection ))
1513 {
1514 nFlags |= IconChoiceFlags::ClearingSelection;
1515 DeselectAllBut( nullptr );
1516 nFlags &= ~IconChoiceFlags::ClearingSelection;
1517 }
1518}
1519
1520SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, bool bHit )
1521{
1522 CheckBoundingRects();
1523 // search through z-order list from the end
1524 size_t nCount = maZOrderList.size();
1525 while( nCount )
1526 {
1527 nCount--;
1528 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCount ];
1529 if( pEntry->aRect.IsInside( rDocPos ) )
1530 {
1531 if( bHit )
1532 {
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 ) )
1539 return pEntry;
1540 aRect = CalcTextRect( pEntry );
1541 if( aRect.IsInside( rDocPos ) )
1542 return pEntry;
1543 }
1544 else
1545 return pEntry;
1546 }
1547 }
1548 return nullptr;
1549}
1550
1551void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, bool bBound )
1552{
1553 if ( bBound )
1554 {
1555 const tools::Rectangle& rRect = GetEntryBoundRect( pEntry );
1556 MakeVisible( rRect );
1557 }
1558 else
1559 {
1560 tools::Rectangle aRect = CalcBmpRect( pEntry );
1561 aRect.Union( CalcTextRect( pEntry ) );
1562 aRect.AdjustTop(TBOFFS_BOUND2 );
1563 aRect.AdjustBottom(TBOFFS_BOUND2 );
1564 aRect.AdjustLeft(LROFFS_BOUND2 );
1565 aRect.AdjustRight(LROFFS_BOUND2 );
1566 MakeVisible( aRect );
1567 }
1568}
1569
1570const tools::Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
1571{
1572 if( !IsBoundingRectValid( pEntry->aRect ))
14
Taking false branch
19
Taking false branch
1573 FindBoundingRect( pEntry );
1574 return pEntry->aRect;
15
Returning without writing to 'pEntry->nPos', which participates in a condition later
20
Returning without writing to 'pEntry->nPos', which participates in a condition later
1575}
1576
1577tools::Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
1578{
1579 tools::Rectangle aBound = GetEntryBoundRect( pEntry );
1580 if( pPos )
1581 aBound.SetPos( *pPos );
1582 Point aPos( aBound.TopLeft() );
1583
1584 switch( nWinBits & VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) )
1585 {
1586 case WB_ICONWB_RECTSTYLE:
1587 {
1588 aPos.AdjustX(( aBound.GetWidth() - aImageSize.Width() ) / 2 );
1589 return tools::Rectangle( aPos, aImageSize );
1590 }
1591
1592 case WB_SMALLICONWB_SMALLSTYLE:
1593 case WB_DETAILSWB_VCENTER:
1594 aPos.AdjustY(( aBound.GetHeight() - aImageSize.Height() ) / 2 );
1595 //TODO: determine horizontal distance to bounding rectangle
1596 return tools::Rectangle( aPos, aImageSize );
1597
1598 default:
1599 OSL_FAIL("IconView: Viewmode not set")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "1599" ": "), "%s", "IconView: Viewmode not set"); } } while
(false)
;
1600 return aBound;
1601 }
1602}
1603
1604tools::Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
1605 const Point* pEntryPos, const OUString* pStr )
1606{
1607 OUString aEntryText;
1608 if( !pStr )
1609 aEntryText = SvtIconChoiceCtrl::GetEntryText( pEntry );
1610 else
1611 aEntryText = *pStr;
1612
1613 const tools::Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
1614 tools::Rectangle aBound( GetEntryBoundRect( pEntry ) );
1615 if( pEntryPos )
1616 aBound.SetPos( *pEntryPos );
1617
1618 tools::Rectangle aTextRect = pView->GetTextRect( aMaxTextRect, aEntryText, nCurTextDrawFlags );
1619
1620 Size aTextSize( aTextRect.GetSize() );
1621
1622 Point aPos( aBound.TopLeft() );
1623 long nBoundWidth = aBound.GetWidth();
1624 long nBoundHeight = aBound.GetHeight();
1625
1626 switch( nWinBits & VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) )
1627 {
1628 case WB_ICONWB_RECTSTYLE:
1629 aPos.AdjustY(aImageSize.Height() );
1630 aPos.AdjustY(VER_DIST_BMP_STRING3 );
1631 aPos.AdjustX((nBoundWidth - aTextSize.Width()) / 2 );
1632 break;
1633
1634 case WB_SMALLICONWB_SMALLSTYLE:
1635 case WB_DETAILSWB_VCENTER:
1636 aPos.AdjustX(aImageSize.Width() );
1637 aPos.AdjustX(HOR_DIST_BMP_STRING3 );
1638 aPos.AdjustY((nBoundHeight - aTextSize.Height()) / 2 );
1639 break;
1640 }
1641 return tools::Rectangle( aPos, aTextSize );
1642}
1643
1644
1645long SvxIconChoiceCtrl_Impl::CalcBoundingWidth() const
1646{
1647 long nStringWidth = GetItemSize( IcnViewFieldType::Text ).Width();
1648 long nWidth = 0;
1649
1650 switch( nWinBits & VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) )
1651 {
1652 case WB_ICONWB_RECTSTYLE:
1653 nWidth = std::max( nStringWidth, aImageSize.Width() );
1654 break;
1655
1656 case WB_SMALLICONWB_SMALLSTYLE:
1657 case WB_DETAILSWB_VCENTER:
1658 nWidth = aImageSize.Width();
1659 nWidth += HOR_DIST_BMP_STRING3;
1660 nWidth += nStringWidth;
1661 break;
1662 }
1663 return nWidth;
1664}
1665
1666long SvxIconChoiceCtrl_Impl::CalcBoundingHeight() const
1667{
1668 long nStringHeight = GetItemSize(IcnViewFieldType::Text).Height();
1669 long nHeight = 0;
1670
1671 switch( nWinBits & VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) )
1672 {
1673 case WB_ICONWB_RECTSTYLE:
1674 nHeight = aImageSize.Height();
1675 nHeight += VER_DIST_BMP_STRING3;
1676 nHeight += nStringHeight;
1677 break;
1678
1679 case WB_SMALLICONWB_SMALLSTYLE:
1680 case WB_DETAILSWB_VCENTER:
1681 nHeight = std::max( aImageSize.Height(), nStringHeight );
1682 break;
1683 }
1684 if( nHeight > nMaxBoundHeight )
1685 {
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() );
1689 }
1690 return nHeight;
1691}
1692
1693Size SvxIconChoiceCtrl_Impl::CalcBoundingSize() const
1694{
1695 return Size( CalcBoundingWidth(), CalcBoundingHeight() );
1696}
1697
1698void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
1699{
1700 nMaxBoundHeight = 0;
1701 maZOrderList.clear();
1702 size_t nCur;
1703 SvxIconChoiceCtrlEntry* pEntry;
1704 const size_t nCount = maEntries.size();
1705
1706 if( !IsAutoArrange() || !pHead )
1707 {
1708 for( nCur = 0; nCur < nCount; nCur++ )
1709 {
1710 pEntry = maEntries[ nCur ].get();
1711 if( IsBoundingRectValid( pEntry->aRect ))
1712 {
1713 Size aBoundSize( pEntry->aRect.GetSize() );
1714 if( aBoundSize.Height() > nMaxBoundHeight )
1715 nMaxBoundHeight = aBoundSize.Height();
1716 }
1717 else
1718 FindBoundingRect( pEntry );
1719 maZOrderList.push_back( pEntry );
1720 }
1721 }
1722 else
1723 {
1724 nCur = 0;
1725 pEntry = pHead;
1726 while( nCur != nCount )
1727 {
1728 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)")do { if (true && (!(pEntry->pflink&&pEntry
->pblink))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "1728" ": "), "%s", "SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)"
); } } while (false)
;
1729 if( IsBoundingRectValid( pEntry->aRect ))
1730 {
1731 Size aBoundSize( pEntry->aRect.GetSize() );
1732 if( aBoundSize.Height() > nMaxBoundHeight )
1733 nMaxBoundHeight = aBoundSize.Height();
1734 }
1735 else
1736 FindBoundingRect( pEntry );
1737 maZOrderList.push_back( pEntry );
1738 pEntry = pEntry->pflink;
1739 nCur++;
1740 }
1741 }
1742 AdjustScrollBars();
1743}
1744
1745void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
1746{
1747 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect")do { if (true && (!(!pEntry->IsPosLocked()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "1747" ": "), "%s", "Locked entry pos in FindBoundingRect"
); } } while (false)
;
1748 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
1749 {
1750 AdjustVirtSize( pEntry->aRect );
1751 return;
1752 }
1753 Size aSize( CalcBoundingSize() );
1754 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid()).TopLeft());
1755 SetBoundingRect_Impl( pEntry, aPos, aSize );
1756}
1757
1758void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1759 const Size& /*rBoundingSize*/ )
1760{
1761 tools::Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
1762 pEntry->aGridRect = aGridRect;
1763 Center( pEntry );
1764 AdjustVirtSize( pEntry->aRect );
1765 pGridMap->OccupyGrids( pEntry );
1766}
1767
1768
1769void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry )
1770{
1771 if( pEntry == pCursor )
1772 {
1773 if( pCursor && eSelectionMode == SelectionMode::Single &&
1774 !pCursor->IsSelected() )
1775 SelectEntry( pCursor, true );
1776 return;
1777 }
1778 ShowCursor( false );
1779 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1780 pCursor = pEntry;
1781 if( pOldCursor )
1782 {
1783 pOldCursor->ClearFlags( SvxIconViewFlags::FOCUSED );
1784 if( eSelectionMode == SelectionMode::Single )
1785 SelectEntry( pOldCursor, false ); // deselect old cursor
1786 }
1787 if( pCursor )
1788 {
1789 ToTop( pCursor );
1790 pCursor->SetFlags( SvxIconViewFlags::FOCUSED );
1791 if( eSelectionMode == SelectionMode::Single )
1792 SelectEntry( pCursor, true );
1793 ShowCursor( true );
1794 }
1795}
1796
1797
1798void SvxIconChoiceCtrl_Impl::ShowCursor( bool bShow )
1799{
1800 if( !pCursor || !bShow || !pView->HasFocus() )
1801 {
1802 pView->HideFocus();
1803 return;
1804 }
1805 tools::Rectangle aRect ( CalcFocusRect( pCursor ) );
1806 /*pView->*/ShowFocus( aRect );
1807}
1808
1809
1810void SvxIconChoiceCtrl_Impl::HideDDIcon()
1811{
1812 pView->PaintImmediately();
1813}
1814
1815bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
1816{
1817 tools::Rectangle aDocRect( Point(), aVirtOutputSize );
1818 tools::Rectangle aVisRect( GetOutputRect() );
1819 if( aVisRect.IsInside( aDocRect ))
1820 return false;
1821 Size aDocSize( aDocRect.GetSize() );
1822 Size aVisSize( aVisRect.GetSize() );
1823 bool bHor = aDocSize.Width() > aVisSize.Width();
1824 bool bVer = aDocSize.Height() > aVisSize.Height();
1825
1826 long nScrollDX = 0, nScrollDY = 0;
1827
1828 switch( rCmd.GetCommand() )
1829 {
1830 case CommandEventId::StartAutoScroll:
1831 {
1832 pView->EndTracking();
1833 StartAutoScrollFlags nScrollFlags = StartAutoScrollFlags::NONE;
1834 if( bHor )
1835 nScrollFlags |= StartAutoScrollFlags::Horz;
1836 if( bVer )
1837 nScrollFlags |= StartAutoScrollFlags::Vert;
1838 if( nScrollFlags != StartAutoScrollFlags::NONE )
1839 {
1840 pView->StartAutoScroll( nScrollFlags );
1841 return true;
1842 }
1843 }
1844 break;
1845
1846 case CommandEventId::Wheel:
1847 {
1848 const CommandWheelData* pData = rCmd.GetWheelData();
1849 if( pData && (CommandWheelMode::SCROLL == pData->GetMode()) && !pData->IsHorz() )
1850 {
1851 sal_uLong nScrollLines = pData->GetScrollLines();
1852 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL(sal_uLong(0xFFFFFFFF)) )
1853 {
1854 nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
1855 if( pData->GetDelta() < 0 )
1856 nScrollDY *= -1;
1857 }
1858 else
1859 {
1860 nScrollDY = pData->GetNotchDelta() * static_cast<long>(nScrollLines);
1861 nScrollDY *= GetScrollBarLineSize();
1862 }
1863 }
1864 }
1865 break;
1866
1867 case CommandEventId::AutoScroll:
1868 {
1869 const CommandScrollData* pData = rCmd.GetAutoScrollData();
1870 if( pData )
1871 {
1872 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
1873 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
1874 }
1875 }
1876 break;
1877
1878 default: break;
1879 }
1880
1881 if( nScrollDX || nScrollDY )
1882 {
1883 aVisRect.AdjustTop( -nScrollDY );
1884 aVisRect.AdjustBottom( -nScrollDY );
1885 aVisRect.AdjustLeft( -nScrollDX );
1886 aVisRect.AdjustRight( -nScrollDX );
1887 MakeVisible( aVisRect );
1888 return true;
1889 }
1890 return false;
1891}
1892
1893
1894void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
1895{
1896 // scroll mouse event?
1897 if( (rCEvt.GetCommand() == CommandEventId::Wheel) ||
1898 (rCEvt.GetCommand() == CommandEventId::StartAutoScroll) ||
1899 (rCEvt.GetCommand() == CommandEventId::AutoScroll) )
1900 {
1901 if( HandleScrollCommand( rCEvt ) )
1902 return;
1903 }
1904}
1905
1906void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
1907{
1908 if( maZOrderList.empty() || pEntry == maZOrderList.back())
23
Assuming the condition is true
1909 return;
24
Returning without writing to 'pEntry->nPos', which participates in a condition later
1910
1911 auto it = std::find(maZOrderList.begin(), maZOrderList.end(), pEntry);
1912 if (it != maZOrderList.end())
1913 {
1914 maZOrderList.erase( it );
1915 maZOrderList.push_back( pEntry );
1916 }
1917}
1918
1919void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( tools::Rectangle& rRect ) const
1920{
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 )
1926 rRect.SetTop( 0 );
1927 if( rRect.Left() < 0 )
1928 rRect.SetLeft( 0 );
1929}
1930
1931// rRect: area of the document (in document coordinates) that we want to make
1932// visible
1933// bScrBar == true: rectangle was calculated because of a scrollbar event
1934
1935void SvxIconChoiceCtrl_Impl::MakeVisible( const tools::Rectangle& rRect, bool bScrBar )
1936{
1937 tools::Rectangle aVirtRect( rRect );
1938 ClipAtVirtOutRect( aVirtRect );
1939 Point aOrigin( pView->GetMapMode().GetOrigin() );
1940 // convert to document coordinate
1941 aOrigin *= -1;
1942 tools::Rectangle aOutputArea( GetOutputRect() );
1943 if( aOutputArea.IsInside( aVirtRect ) )
1944 return; // is already visible
1945
1946 long nDy;
1947 if( aVirtRect.Top() < aOutputArea.Top() )
1948 {
1949 // scroll up (nDy < 0)
1950 nDy = aVirtRect.Top() - aOutputArea.Top();
1951 }
1952 else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
1953 {
1954 // scroll down (nDy > 0)
1955 nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
1956 }
1957 else
1958 nDy = 0;
1959
1960 long nDx;
1961 if( aVirtRect.Left() < aOutputArea.Left() )
1962 {
1963 // scroll to the left (nDx < 0)
1964 nDx = aVirtRect.Left() - aOutputArea.Left();
1965 }
1966 else if( aVirtRect.Right() > aOutputArea.Right() )
1967 {
1968 // scroll to the right (nDx > 0)
1969 nDx = aVirtRect.Right() - aOutputArea.Right();
1970 }
1971 else
1972 nDx = 0;
1973
1974 aOrigin.AdjustX(nDx );
1975 aOrigin.AdjustY(nDy );
1976 aOutputArea.SetPos( aOrigin );
1977 if( GetUpdateMode() )
1978 {
1979 HideDDIcon();
1980 pView->PaintImmediately();
1981 ShowCursor( false );
1982 }
1983
1984 // invert origin for SV (so we can scroll/paint using document coordinates)
1985 aOrigin *= -1;
1986 SetOrigin( aOrigin );
1987
1988 bool bScrollable = pView->GetBackground().IsScrollable();
1989
1990 if( bScrollable && GetUpdateMode() )
1991 {
1992 // scroll in reverse direction!
1993 pView->Control::Scroll( -nDx, -nDy, aOutputArea,
1994 ScrollFlags::NoChildren | ScrollFlags::UseClipRegion | ScrollFlags::Clip );
1995 }
1996 else
1997 pView->Invalidate(InvalidateFlags::NoChildren);
1998
1999 if( aHorSBar->IsVisible() || aVerSBar->IsVisible() )
2000 {
2001 if( !bScrBar )
2002 {
2003 aOrigin *= -1;
2004 // correct thumbs
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() );
2009 }
2010 }
2011
2012 if( GetUpdateMode() )
2013 ShowCursor( true );
2014
2015 // check if we still need scrollbars
2016 CheckScrollBars();
2017 if( bScrollable && GetUpdateMode() )
2018 pView->PaintImmediately();
2019
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.
2024 VisRectChanged();
2025}
2026
2027sal_Int32 SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2028{
2029 if( (nWinBits & WB_HIGHLIGHTFRAMEWB_IGNORETAB) && pCurHighlightFrame )
2030 return 1;
2031 return nSelectionCount;
2032}
2033
2034void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2035{
2036 bool bSel;
2037 bSel = !pEntry->IsSelected();
2038 SelectEntry( pEntry, bSel, true );
2039}
2040
2041void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry const * pThisEntryNot )
2042{
2043 ClearSelectedRectList();
2044
2045 // TODO: work through z-order list, if necessary!
2046
2047 size_t nCount = maEntries.size();
2048 for( size_t nCur = 0; nCur < nCount; nCur++ )
2049 {
2050 SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get();
2051 if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2052 SelectEntry( pEntry, false, true );
2053 }
2054 pAnchor = nullptr;
2055 nFlags &= ~IconChoiceFlags::AddMode;
2056}
2057
2058Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2059{
2060 Size aMinSize( aImageSize );
2061 aMinSize.AdjustWidth(2 * LROFFS_BOUND2 );
2062 aMinSize.AdjustHeight(TBOFFS_BOUND2 ); // single offset is enough (FileDlg)
2063 Size aTextSize( pView->GetTextWidth( "XXX" ), pView->GetTextHeight() );
2064 if( nWinBits & WB_ICONWB_RECTSTYLE )
2065 {
2066 aMinSize.AdjustHeight(VER_DIST_BMP_STRING3 );
2067 aMinSize.AdjustHeight(aTextSize.Height() );
2068 }
2069 else
2070 {
2071 aMinSize.AdjustWidth(HOR_DIST_BMP_STRING3 );
2072 aMinSize.AdjustWidth(aTextSize.Width() );
2073 }
2074 return aMinSize;
2075}
2076
2077void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
2078{
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() );
2085
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_DETAILSWB_VCENTER )
2090 {
2091 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
2092 if( pCol )
2093 const_cast<SvxIconChoiceCtrlColumnInfo*>(pCol)->SetWidth( nGridDX );
2094 }
2095 nGridDY = aSize.Height();
2096 SetDefaultTextSize();
2097}
2098
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
2101// LONG_MAX.
2102
2103tools::Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
2104{
2105 tools::Rectangle aBoundRect;
2106 // avoid infinite recursion: don't calculate the bounding rectangle here
2107 if( IsBoundingRectValid( pEntry->aRect ) )
2108 aBoundRect = pEntry->aRect;
2109 else
2110 aBoundRect = pEntry->aGridRect;
2111
2112 tools::Rectangle aBmpRect( const_cast<SvxIconChoiceCtrl_Impl*>(this)->CalcBmpRect(
2113 const_cast<SvxIconChoiceCtrlEntry*>(pEntry) ) );
2114 if( nWinBits & WB_ICONWB_RECTSTYLE )
2115 {
2116 aBoundRect.SetTop( aBmpRect.Bottom() );
2117 aBoundRect.AdjustTop(VER_DIST_BMP_STRING3 );
2118 if( aBoundRect.Top() > aBoundRect.Bottom())
2119 aBoundRect.SetTop( aBoundRect.Bottom() );
2120 aBoundRect.AdjustLeft(LROFFS_BOUND2 );
2121 aBoundRect.AdjustLeft( 1 );
2122 aBoundRect.AdjustRight( -(LROFFS_BOUND2) );
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_MAX9223372036854775807L );
2128 }
2129 else
2130 {
2131 aBoundRect.SetLeft( aBmpRect.Right() );
2132 aBoundRect.AdjustLeft(HOR_DIST_BMP_STRING3 );
2133 aBoundRect.AdjustRight( -(LROFFS_BOUND2) );
2134 if( aBoundRect.Left() > aBoundRect.Right() )
2135 aBoundRect.SetLeft( aBoundRect.Right() );
2136 long nHeight = aBoundRect.GetSize().Height();
2137 nHeight = nHeight - aDefaultTextSize.Height();
2138 nHeight /= 2;
2139 aBoundRect.AdjustTop(nHeight );
2140 aBoundRect.AdjustBottom( -nHeight );
2141 }
2142 return aBoundRect;
2143}
2144
2145void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2146{
2147 long nDY = nGridDY;
2148 nDY -= aImageSize.Height();
2149 nDY -= VER_DIST_BMP_STRING3;
2150 nDY -= 2 * TBOFFS_BOUND2;
2151 if (nDY <= 0)
2152 nDY = 2;
2153
2154 long nDX = nGridDX;
2155 nDX -= 2 * LROFFS_BOUND2;
2156 nDX -= 2;
2157 if (nDX <= 0)
2158 nDX = 2;
2159
2160 long nHeight = pView->GetTextHeight();
2161 if (nDY < nHeight)
2162 nDY = nHeight;
2163 if(pView->GetDPIScaleFactor() > 1)
2164 {
2165 nDY*=2;
2166 }
2167 aDefaultTextSize = Size(nDX, nDY);
2168}
2169
2170
2171void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
2172{
2173 pEntry->aRect = pEntry->aGridRect;
2174 Size aSize( CalcBoundingSize() );
2175 if( nWinBits & WB_ICONWB_RECTSTYLE )
2176 {
2177 // center horizontally
2178 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
2179 pEntry->aRect.AdjustLeft(nBorder / 2 );
2180 pEntry->aRect.AdjustRight( -(nBorder / 2) );
2181 }
2182 // center vertically
2183 pEntry->aRect.SetBottom( pEntry->aRect.Top() + aSize.Height() );
2184}
2185
2186
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
2190void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY )
2191{
2192 const MapMode& rMapMode = pView->GetMapMode();
2193 Point aOrigin( rMapMode.GetOrigin() );
2194 // convert to document coordinate
2195 aOrigin *= -1;
2196 aOrigin.AdjustY(nDeltaY );
2197 aOrigin.AdjustX(nDeltaX );
2198 tools::Rectangle aRect( aOrigin, aOutputSize );
2199 MakeVisible( aRect, true/*bScrollBar*/ );
2200}
2201
2202
2203const Size& SvxIconChoiceCtrl_Impl::GetItemSize( IcnViewFieldType eItem ) const
2204{
2205 if (eItem == IcnViewFieldType::Text)
2206 return aDefaultTextSize;
2207 return aImageSize; // IcnViewFieldType::Image
2208}
2209
2210tools::Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
2211{
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);
2217}
2218
2219// the hot spot is the inner 50% of the rectangle
2220static tools::Rectangle GetHotSpot( const tools::Rectangle& rRect )
2221{
2222 tools::Rectangle aResult( rRect );
2223 aResult.Justify();
2224 Size aSize( rRect.GetSize() );
2225 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 );
2231 return aResult;
2232}
2233
2234void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
2235 bool bAdd, std::vector<tools::Rectangle>* pOtherRects )
2236{
2237 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr")do { if (true && (!(pEntry1 && pEntry2))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "2237" ": "), "%s", "SelectEntry: Invalid Entry-Ptr"); }
} while (false)
;
2238 tools::Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2239 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2240 SelectRect( aRect, bAdd, pOtherRects );
2241}
2242
2243void SvxIconChoiceCtrl_Impl::SelectRect( const tools::Rectangle& rRect, bool bAdd,
2244 std::vector<tools::Rectangle>* pOtherRects )
2245{
2246 aCurSelectionRect = rRect;
2247 if( maZOrderList.empty() )
2248 return;
2249
2250 // set flag, so ToTop won't be called in Select
2251 bool bAlreadySelectingRect(nFlags & IconChoiceFlags::SelectingRect);
2252 nFlags |= IconChoiceFlags::SelectingRect;
2253
2254 CheckBoundingRects();
2255 pView->PaintImmediately();
2256 const size_t nCount = maZOrderList.size();
2257
2258 tools::Rectangle aRect( rRect );
2259 aRect.Justify();
2260 bool bCalcOverlap = (bAdd && pOtherRects && !pOtherRects->empty());
2261
2262 bool bResetClipRegion = false;
2263 if( !pView->IsClipRegion() )
2264 {
2265 bResetClipRegion = true;
2266 pView->SetClipRegion(vcl::Region(GetOutputRect()));
2267 }
2268
2269 for( size_t nPos = 0; nPos < nCount; nPos++ )
2270 {
2271 SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nPos ];
2272
2273 if( !IsBoundingRectValid( pEntry->aRect ))
2274 FindBoundingRect( pEntry );
2275 tools::Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
2276 bool bSelected = pEntry->IsSelected();
2277
2278 bool bOverlaps;
2279 if( bCalcOverlap )
2280 bOverlaps = IsOver( pOtherRects, aBoundRect );
2281 else
2282 bOverlaps = false;
2283 bool bOver = aRect.IsOver( aBoundRect );
2284
2285 if( bOver && !bOverlaps )
2286 {
2287 // is inside the new selection rectangle and outside of any old one
2288 // => select
2289 if( !bSelected )
2290 SelectEntry( pEntry, true, true );
2291 }
2292 else if( !bAdd )
2293 {
2294 // is outside of the selection rectangle
2295 // => deselect
2296 if( bSelected )
2297 SelectEntry( pEntry, false, true );
2298 }
2299 else if (bOverlaps)
2300 {
2301 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2302 // selection rectangle.
2303
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))
2313 {
2314 // deselect intersection between old rectangles and current rectangle
2315 if( bSelected )
2316 SelectEntry( pEntry, false, true );
2317 }
2318 else
2319 {
2320 // select entry of an old rectangle
2321 if( !bSelected )
2322 SelectEntry( pEntry, true, true );
2323 }
2324 }
2325 else if( !bOver && bSelected )
2326 {
2327 // this entry is completely outside the rectangle => deselect it
2328 SelectEntry( pEntry, false, true );
2329 }
2330 }
2331
2332 if( !bAlreadySelectingRect )
2333 nFlags &= ~IconChoiceFlags::SelectingRect;
2334
2335 pView->PaintImmediately();
2336 if( bResetClipRegion )
2337 pView->SetClipRegion();
2338}
2339
2340void SvxIconChoiceCtrl_Impl::SelectRange(
2341 SvxIconChoiceCtrlEntry const * pStart,
2342 SvxIconChoiceCtrlEntry const * pEnd,
2343 bool bAdd )
2344{
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 );
2349 sal_uLong i;
2350 SvxIconChoiceCtrlEntry* pEntry;
2351
2352 if ( ! bAdd )
2353 {
2354 // deselect everything before the first entry if not in
2355 // adding mode
2356 for ( i=0; i<nFirst; i++ )
2357 {
2358 pEntry = GetEntry( i );
2359 if( pEntry->IsSelected() )
2360 SelectEntry( pEntry, false, true );
2361 }
2362 }
2363
2364 // select everything between nFirst and nLast
2365 for ( i=nFirst; i<=nLast; i++ )
2366 {
2367 pEntry = GetEntry( i );
2368 if( ! pEntry->IsSelected() )
2369 SelectEntry( pEntry, true, true );
2370 }
2371
2372 if ( ! bAdd )
2373 {
2374 // deselect everything behind the last entry if not in
2375 // adding mode
2376 sal_uLong nEnd = GetEntryCount();
2377 for ( ; i<nEnd; i++ )
2378 {
2379 pEntry = GetEntry( i );
2380 if( pEntry->IsSelected() )
2381 SelectEntry( pEntry, false, true );
2382 }
2383 }
2384}
2385
2386bool SvxIconChoiceCtrl_Impl::IsOver( std::vector<tools::Rectangle>* pRectList, const tools::Rectangle& rBoundRect )
2387{
2388 const sal_uInt16 nCount = pRectList->size();
2389 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2390 {
2391 tools::Rectangle& rRect = (*pRectList)[ nCur ];
2392 if( rBoundRect.IsOver( rRect ))
2393 return true;
2394 }
2395 return false;
2396}
2397
2398void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
2399 SvxIconChoiceCtrlEntry* pEntry2 )
2400{
2401 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr")do { if (true && (!(pEntry1 && pEntry2))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "2401" ": "), "%s", "SelectEntry: Invalid Entry-Ptr"); }
} while (false)
;
2402 tools::Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2403 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2404 AddSelectedRect( aRect );
2405}
2406
2407void SvxIconChoiceCtrl_Impl::AddSelectedRect( const tools::Rectangle& rRect )
2408{
2409 tools::Rectangle newRect = rRect;
2410 newRect.Justify();
2411 aSelectedRectList.push_back( newRect );
2412}
2413
2414void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2415{
2416 aSelectedRectList.clear();
2417}
2418
2419IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, Timer *, void)void SvxIconChoiceCtrl_Impl::LinkStubAutoArrangeHdl(void * instance
, Timer * data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->AutoArrangeHdl(data); } void SvxIconChoiceCtrl_Impl
::AutoArrangeHdl(__attribute__ ((unused)) Timer *)
2420{
2421 aAutoArrangeIdle.Stop();
2422 Arrange( IsAutoArrange(), 0, 0 );
2423}
2424
2425IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, Timer *, void)void SvxIconChoiceCtrl_Impl::LinkStubVisRectChangedHdl(void *
instance, Timer * data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->VisRectChangedHdl(data); } void SvxIconChoiceCtrl_Impl
::VisRectChangedHdl(__attribute__ ((unused)) Timer *)
2426{
2427 aVisRectChangedIdle.Stop();
2428}
2429
2430IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, Timer *, void)void SvxIconChoiceCtrl_Impl::LinkStubDocRectChangedHdl(void *
instance, Timer * data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->DocRectChangedHdl(data); } void SvxIconChoiceCtrl_Impl
::DocRectChangedHdl(__attribute__ ((unused)) Timer *)
2431{
2432 aDocRectChangedIdle.Stop();
2433}
2434
2435#ifdef DBG_UTIL
2436void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
2437{
2438 if( !pEntry )
2439 {
2440 if( eTextMode != eMode )
2441 {
2442 eTextMode = eMode;
2443 Arrange( true, 0, 0 );
2444 }
2445 }
2446 else
2447 {
2448 if( pEntry->eTextMode != eMode )
2449 {
2450 pEntry->eTextMode = eMode;
2451 InvalidateEntry( pEntry );
2452 pView->Invalidate( GetEntryBoundRect( pEntry ) );
2453 AdjustVirtSize( pEntry->aRect );
2454 }
2455 }
2456}
2457#endif
2458
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 !!!
2462
2463void SvxIconChoiceCtrl_Impl::ShowFocus ( tools::Rectangle const & rRect )
2464{
2465 Color aBkgColor(pView->GetBackground().GetColor());
2466 Color aPenColor;
2467 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
2468 if (nColor > 128)
2469 aPenColor = COL_BLACK;
2470 else
2471 aPenColor = COL_WHITE;
2472
2473 aFocus.aPenColor = aPenColor;
2474 aFocus.aRect = rRect;
2475}
2476
2477void SvxIconChoiceCtrl_Impl::DrawFocusRect(vcl::RenderContext& rRenderContext)
2478{
2479 rRenderContext.SetLineColor(aFocus.aPenColor);
2480 rRenderContext.SetFillColor();
2481 tools::Polygon aPolygon (aFocus.aRect);
2482
2483 LineInfo aLineInfo(LineStyle::Dash);
2484
2485 aLineInfo.SetDashLen(1);
2486 aLineInfo.SetDotLen(1);
2487 aLineInfo.SetDistance(1);
2488 aLineInfo.SetDotCount(1);
2489
2490 rRenderContext.DrawPolyLine(aPolygon, aLineInfo);
2491}
2492
2493bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
2494{
2495 bool bRet = false;
2496 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
2497 size_t nEntryCount = GetEntryCount();
2498 for ( size_t i = 0; i < nEntryCount; ++i )
2499 {
2500 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
2501 {
2502 bRet = true;
2503 rPos = i;
2504 break;
2505 }
2506 }
2507
2508 return bRet;
2509}
2510
2511
2512IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId, void )void SvxIconChoiceCtrl_Impl::LinkStubUserEventHdl(void * instance
, void* data) { return static_cast<SvxIconChoiceCtrl_Impl *
>(instance)->UserEventHdl(data); } void SvxIconChoiceCtrl_Impl
::UserEventHdl(void* nId)
2513{
2514 if( nId == EVENTID_ADJUST_SCROLLBARS(reinterpret_cast<void*>(2)) )
2515 {
2516 nUserEventAdjustScrBars = nullptr;
2517 AdjustScrollBars();
2518 }
2519 else if( nId == EVENTID_SHOW_CURSOR(reinterpret_cast<void*>(1)) )
2520 {
2521 ShowCursor( true );
2522 }
2523}
2524
2525void SvxIconChoiceCtrl_Impl::CancelUserEvents()
2526{
2527 if( nUserEventAdjustScrBars )
2528 {
2529 Application::RemoveUserEvent( nUserEventAdjustScrBars );
2530 nUserEventAdjustScrBars = nullptr;
2531 }
2532}
2533
2534void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
2535{
2536 if( pEntry == pCursor )
2537 ShowCursor( false );
2538 pView->Invalidate( pEntry->aRect );
2539 Center( pEntry );
2540 pView->Invalidate( pEntry->aRect );
2541 if( pEntry == pCursor )
2542 ShowCursor( true );
2543}
2544
2545SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry() const
2546{
2547 if( !GetSelectionCount() )
2548 return nullptr;
2549
2550 if( (nWinBits & WB_HIGHLIGHTFRAMEWB_IGNORETAB) && (eSelectionMode == SelectionMode::NONE) )
2551 {
2552 return pCurHighlightFrame;
2553 }
2554
2555 size_t nCount = maEntries.size();
2556 if( !pHead )
2557 {
2558 for( size_t nCur = 0; nCur < nCount; nCur++ )
2559 {
2560 SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get();
2561 if( pEntry->IsSelected() )
2562 {
2563 return pEntry;
2564 }
2565 }
2566 }
2567 else
2568 {
2569 SvxIconChoiceCtrlEntry* pEntry = pHead;
2570 while( nCount-- )
2571 {
2572 if( pEntry->IsSelected() )
2573 {
2574 return pEntry;
2575 }
2576 pEntry = pEntry->pflink;
2577 if( nCount && pEntry == pHead )
2578 {
2579 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl1.cxx"
":" "2579" ": "), "%s", "SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!"
); } } while (false)
;
2580 return nullptr;
2581 }
2582 }
2583 }
2584 return nullptr;
2585}
2586
2587void SvxIconChoiceCtrl_Impl::SelectAll()
2588{
2589 size_t nCount = maEntries.size();
2590 for( size_t nCur = 0; nCur < nCount; nCur++ )
2591 {
2592 SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get();
2593 SelectEntry( pEntry, true/*bSelect*/, true );
2594 }
2595 nFlags &= ~IconChoiceFlags::AddMode;
2596 pAnchor = nullptr;
2597}
2598
2599
2600
2601
2602sal_Int32 SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry const * pEntry ) const
2603{
2604 if( !(nFlags & IconChoiceFlags::EntryListPosValid ))
49
Taking false branch
2605 const_cast<SvxIconChoiceCtrl_Impl*>(this)->SetListPositions();
2606 return pEntry->nPos;
50
Returning value, which participates in a condition later
2607}
2608
2609void SvxIconChoiceCtrl_Impl::InitSettings()
2610{
2611 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
2612
2613 // unit (from settings) is Point
2614 vcl::Font aFont( rStyleSettings.GetFieldFont() );
2615 aFont.SetColor( rStyleSettings.GetWindowTextColor() );
2616 pView->SetPointFont( aFont );
2617 SetDefaultTextSize();
2618
2619 pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
2620 pView->SetTextFillColor();
2621
2622 pView->SetBackground( rStyleSettings.GetFieldColor());
2623
2624 long nScrBarSize = rStyleSettings.GetScrollBarSize();
2625 if( nScrBarSize == nHorSBarHeight && nScrBarSize == nVerSBarWidth )
2626 return;
2627
2628 nHorSBarHeight = nScrBarSize;
2629 Size aSize( aHorSBar->GetSizePixel() );
2630 aSize.setHeight( nScrBarSize );
2631 aHorSBar->Hide();
2632 aHorSBar->SetSizePixel( aSize );
2633
2634 nVerSBarWidth = nScrBarSize;
2635 aSize = aVerSBar->GetSizePixel();
2636 aSize.setWidth( nScrBarSize );
2637 aVerSBar->Hide();
2638 aVerSBar->SetSizePixel( aSize );
2639
2640 Size aOSize( pView->Control::GetOutputSizePixel() );
2641 PositionScrollBars( aOSize.Width(), aOSize.Height() );
2642 AdjustScrollBars();
2643}
2644
2645void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
2646{
2647 if( eMode == ePositionMode )
1
Assuming 'eMode' is not equal to field 'ePositionMode'
2
Taking false branch
2648 return;
2649
2650 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
2651 ePositionMode = eMode;
2652 size_t nCount = maEntries.size();
2653
2654 if( eOldMode == SvxIconChoiceCtrlPositionMode::AutoArrange )
3
Assuming 'eOldMode' is not equal to AutoArrange
4
Taking false branch
2655 {
2656 // when positioning moved entries "hard", there are problems with
2657 // unwanted overlaps, as these entries aren't taken into account in
2658 // Arrange.
2659 if( maEntries.size() )
2660 aAutoArrangeIdle.Start();
2661 return;
2662 }
2663
2664 if( ePositionMode == SvxIconChoiceCtrlPositionMode::AutoArrange )
5
Assuming field 'ePositionMode' is equal to AutoArrange
6
Taking true branch
2665 {
2666 for( size_t nCur = 0; nCur < nCount; nCur++ )
7
Assuming 'nCur' is < 'nCount'
8
Loop condition is true. Entering loop body
10
Assuming 'nCur' is < 'nCount'
11
Loop condition is true. Entering loop body
2667 {
2668 SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get();
2669 if( pEntry->GetFlags() & SvxIconViewFlags(SvxIconViewFlags::POS_LOCKED | SvxIconViewFlags::POS_MOVED))
9
Taking true branch
12
Taking true branch
2670 SetEntryPos(pEntry, GetEntryBoundRect( pEntry ).TopLeft());
13
Calling 'SvxIconChoiceCtrl_Impl::GetEntryBoundRect'
16
Returning from 'SvxIconChoiceCtrl_Impl::GetEntryBoundRect'
17
Calling 'SvxIconChoiceCtrl_Impl::SetEntryPos'
2671 }
2672
2673 if( maEntries.size() )
2674 aAutoArrangeIdle.Start();
2675 }
2676}
2677
2678void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
2679 SvxIconChoiceCtrlEntry* pPredecessor )
2680{
2681 if( !IsAutoArrange() )
41
Calling 'SvxIconChoiceCtrl_Impl::IsAutoArrange'
44
Returning from 'SvxIconChoiceCtrl_Impl::IsAutoArrange'
45
Taking false branch
2682 return;
2683
2684 if( pEntry == pPredecessor )
46
Assuming 'pEntry' is not equal to 'pPredecessor'
47
Taking false branch
2685 return;
2686
2687 sal_uLong nPos1 = GetEntryListPos( pEntry );
48
Calling 'SvxIconChoiceCtrl_Impl::GetEntryListPos'
51
Returning from 'SvxIconChoiceCtrl_Impl::GetEntryListPos'
2688 if( !pHead )
52
Assuming field 'pHead' is null
53
Taking true branch
2689 {
2690 if( pPredecessor )
54
Assuming 'pPredecessor' is null
55
Taking false branch
2691 {
2692 sal_uLong nPos2 = GetEntryListPos( pPredecessor );
2693 if( nPos1 == (nPos2 + 1) )
2694 return; // is already the predecessor
2695 }
2696 else if( !nPos1 )
56
Assuming 'nPos1' is not equal to 0
57
Taking false branch
2697 return;
2698
2699 InitPredecessors();
58
Calling 'SvxIconChoiceCtrl_Impl::InitPredecessors'
64
Returning from 'SvxIconChoiceCtrl_Impl::InitPredecessors'
2700 }
2701
2702 if( !pPredecessor
64.1
'pPredecessor' is null
64.1
'pPredecessor' is null
&& pHead == pEntry
64.2
'pEntry' is not equal to field 'pHead'
64.2
'pEntry' is not equal to field 'pHead'
)
65
Taking false branch
2703 return; // is already the first one
2704
2705 bool bSetHead = false;
2706 if( !pPredecessor
65.1
'pPredecessor' is null
65.1
'pPredecessor' is null
)
66
Taking true branch
2707 {
2708 bSetHead = true;
2709 pPredecessor = pHead->pblink;
67
Access to field 'pblink' results in a dereference of a null pointer (loaded from field 'pHead')
2710 }
2711 if( pEntry == pHead )
2712 {
2713 pHead = pHead->pflink;
2714 bSetHead = false;
2715 }
2716 if( pEntry != pPredecessor )
2717 {
2718 pEntry->Unlink();
2719 pEntry->SetBacklink( pPredecessor );
2720 }
2721 if( bSetHead )
2722 pHead = pEntry;
2723 aAutoArrangeIdle.Start();
2724}
2725
2726SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
2727 const Point& rPosTopLeft )
2728{
2729 Point aPos( rPosTopLeft ); //TopLeft
2730 tools::Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
2731 Point aNewPos( aCenterRect.Center() );
2732 sal_uLong nGrid = GetPredecessorGrid( aNewPos );
2733 size_t nCount = maEntries.size();
2734 if( nGrid == ULONG_MAX(9223372036854775807L *2UL+1UL) )
32
Assuming the condition is false
33
Taking false branch
2735 return nullptr;
2736 if( nGrid >= nCount )
34
Assuming 'nGrid' is < 'nCount'
35
Taking false branch
2737 nGrid = nCount - 1;
2738 if( !pHead )
36
Assuming field 'pHead' is null
37
Taking true branch
2739 return maEntries[ nGrid ].get();
38
Returning pointer, which participates in a condition later
2740
2741 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
2742 // TODO: go through list from the end if nGrid > nCount/2
2743 for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
2744 pCur = pCur->pflink;
2745
2746 return pCur;
2747}
2748
2749sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
2750{
2751 Point aPos( rPos );
2752 aPos.AdjustX( -(LROFFS_WINBORDER4) );
2753 aPos.AdjustY( -(TBOFFS_WINBORDER4) );
2754 long nMaxCol = aVirtOutputSize.Width() / nGridDX;
2755 if( nMaxCol )
2756 nMaxCol--;
2757 long nGridX = aPos.X() / nGridDX;
2758 if( nGridX > nMaxCol )
2759 nGridX = nMaxCol;
2760 long nGridY = aPos.Y() / nGridDY;
2761 long nGridsX = aOutputSize.Width() / nGridDX;
2762 sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
2763 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
2764 if( rPos.X() < nMiddle )
2765 {
2766 if( !nGrid )
2767 nGrid = ULONG_MAX(9223372036854775807L *2UL+1UL);
2768 else
2769 nGrid--;
2770 }
2771 return nGrid;
2772}
2773
2774bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
2775{
2776 if ( !(rHEvt.GetMode() & HelpEventMode::QUICK ) )
2777 return false;
2778
2779 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
2780 aPos -= pView->GetMapMode().GetOrigin();
2781 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, true );
2782
2783 if ( !pEntry )
2784 return false;
2785
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() )
2790 return false;
2791
2792 tools::Rectangle aOptTextRect( aTextRect );
2793 aOptTextRect.SetBottom( LONG_MAX9223372036854775807L );
2794 DrawTextFlags nNewFlags = nCurTextDrawFlags;
2795 nNewFlags &= ~DrawTextFlags( DrawTextFlags::Clip | DrawTextFlags::EndEllipsis );
2796 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
2797 if ( aOptTextRect != aTextRect || !sQuickHelpText.isEmpty() )
2798 {
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
2804 aPt.AdjustY( -1 );
2805 aPt.AdjustX( -3 );
2806 aOptTextRect.SetPos( aPt );
2807 OUString sHelpText;
2808 if ( !sQuickHelpText.isEmpty() )
2809 sHelpText = sQuickHelpText;
2810 else
2811 sHelpText = aEntryText;
2812 Help::ShowQuickHelp( static_cast<vcl::Window*>(pView), aOptTextRect, sHelpText, QuickHelpFlags::Left | QuickHelpFlags::VCenter );
2813 }
2814
2815 return true;
2816}
2817
2818void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
2819{
2820 if (!m_pColumns)
2821 m_pColumns.reset(new SvxIconChoiceCtrlColumnInfoMap);
2822
2823 SvxIconChoiceCtrlColumnInfo* pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
2824 m_pColumns->insert(std::make_pair(nIndex, std::unique_ptr<SvxIconChoiceCtrlColumnInfo>(pInfo)));
2825
2826 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2827 // fly with a single column
2828 if( !nIndex && (nWinBits & WB_DETAILSWB_VCENTER) )
2829 nGridDX = pInfo->GetWidth();
2830
2831 if( GetUpdateMode() )
2832 Arrange( IsAutoArrange(), 0, 0 );
2833}
2834
2835const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
2836{
2837 if (!m_pColumns)
2838 return nullptr;
2839 auto const it = m_pColumns->find( nIndex );
2840 if (it == m_pColumns->end())
2841 return nullptr;
2842 return it->second.get();
2843}
2844
2845void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(vcl::RenderContext& rRenderContext, const tools::Rectangle& rBmpRect)
2846{
2847 tools::Rectangle aBmpRect(rBmpRect);
2848 long nBorder = 2;
2849 if (aImageSize.Width() < 32)
2850 nBorder = 1;
2851 aBmpRect.AdjustRight(nBorder );
2852 aBmpRect.AdjustLeft( -nBorder );
2853 aBmpRect.AdjustBottom(nBorder );
2854 aBmpRect.AdjustTop( -nBorder );
2855
2856 DecorationView aDecoView(&rRenderContext);
2857 DrawHighlightFrameStyle nDecoFlags;
2858 if (bHighlightFramePressed)
2859 nDecoFlags = DrawHighlightFrameStyle::In;
2860 else
2861 nDecoFlags = DrawHighlightFrameStyle::Out;
2862 aDecoView.DrawHighlightFrame(aBmpRect, nDecoFlags);
2863}
2864
2865void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
2866 bool bKeepHighlightFlags )
2867{
2868 if( pEntry == pCurHighlightFrame )
2869 return;
2870
2871 if( !bKeepHighlightFlags )
2872 bHighlightFramePressed = false;
2873
2874 if (pCurHighlightFrame)
2875 {
2876 tools::Rectangle aInvalidationRect(GetEntryBoundRect(pCurHighlightFrame));
2877 aInvalidationRect.expand(5);
2878 pCurHighlightFrame = nullptr;
2879 pView->Invalidate(aInvalidationRect);
2880 }
2881
2882 pCurHighlightFrame = pEntry;
2883 if (pEntry)
2884 {
2885 tools::Rectangle aInvalidationRect(GetEntryBoundRect(pEntry));
2886 aInvalidationRect.expand(5);
2887 pView->Invalidate(aInvalidationRect);
2888 }
2889}
2890
2891void SvxIconChoiceCtrl_Impl::CallSelectHandler()
2892{
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
2898 // the object.
2899 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
2900 // WB_NOASYNCSELECTHDL.
2901 if( nWinBits & (WB_NOASYNCSELECTHDLWB_NOLABEL | WB_HIGHLIGHTFRAMEWB_IGNORETAB) )
2902 {
2903 pHdlEntry = nullptr;
2904 pView->ClickIcon();
2905 //pView->Select();
2906 }
2907 else
2908 aCallSelectHdlIdle.Start();
2909}
2910
2911IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, Timer *, void)void SvxIconChoiceCtrl_Impl::LinkStubCallSelectHdlHdl(void * instance
, Timer * data) { return static_cast<SvxIconChoiceCtrl_Impl
*>(instance)->CallSelectHdlHdl(data); } void SvxIconChoiceCtrl_Impl
::CallSelectHdlHdl(__attribute__ ((unused)) Timer *)
2912{
2913 pHdlEntry = nullptr;
2914 pView->ClickIcon();
2915 //pView->Select();
2916}
2917
2918void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos )
2919{
2920 MapMode aMapMode( pView->GetMapMode() );
2921 aMapMode.SetOrigin( rPos );
2922 pView->SetMapMode( aMapMode );
2923}
2924
2925void SvxIconChoiceCtrl_Impl::CallEventListeners( VclEventId nEvent, void* pData )
2926{
2927 pView->CallImplEventListeners( nEvent, pData );
2928}
2929
2930
2931/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/vcl/source/control/imivctl.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_SVTOOLS_SOURCE_CONTNR_IMIVCTL_HXX
21#define INCLUDED_SVTOOLS_SOURCE_CONTNR_IMIVCTL_HXX
22
23#include <sal/config.h>
24
25#include <o3tl/safeint.hxx>
26#include <vcl/toolkit/ivctrl.hxx>
27#include <vcl/virdev.hxx>
28#include <vcl/scrbar.hxx>
29#include <vcl/timer.hxx>
30#include <vcl/idle.hxx>
31#include <vcl/vclptr.hxx>
32#include <tools/debug.hxx>
33#include <vcl/svtaccessiblefactory.hxx>
34
35#include <limits.h>
36
37
38#include <memory>
39#include <map>
40
41class IcnCursor_Impl;
42class SvtIconChoiceCtrl;
43class SvxIconChoiceCtrlEntry;
44class IcnViewEdit_Impl;
45class IcnGridMap_Impl;
46
47
48// some defines
49
50#define PAINTFLAG_HOR_CENTERED0x0001 0x0001
51#define PAINTFLAG_VER_CENTERED0x0002 0x0002
52
53enum class IconChoiceFlags {
54 NONE = 0x0000,
55 AddMode = 0x0001,
56 SelectingRect = 0x0002,
57 DownCtrl = 0x0004,
58 DownDeselect = 0x0008,
59 EntryListPosValid = 0x0010,
60 ClearingSelection = 0x0020,
61 Arranging = 0x0040
62};
63namespace o3tl {
64 template<> struct typed_flags<IconChoiceFlags> : is_typed_flags<IconChoiceFlags, 0x007f> {};
65}
66
67// unit = pixels
68// distances from window borders
69#define LROFFS_WINBORDER4 4
70#define TBOFFS_WINBORDER4 4
71// for the bounding rectangle
72#define LROFFS_BOUND2 2
73#define TBOFFS_BOUND2 2
74// distance icon to text
75#define HOR_DIST_BMP_STRING3 3
76#define VER_DIST_BMP_STRING3 3
77// width offset of highlight rectangle for Text
78#define LROFFS_TEXT2 2
79
80#define DEFAULT_MAX_VIRT_WIDTH200 200
81#define DEFAULT_MAX_VIRT_HEIGHT200 200
82
83#define VIEWMODE_MASK(WB_RECTSTYLE | WB_SMALLSTYLE | WB_VCENTER) (WB_ICONWB_RECTSTYLE | WB_SMALLICONWB_SMALLSTYLE | WB_DETAILSWB_VCENTER)
84
85
86enum class IcnViewFieldType
87{
88 Image,
89 Text
90};
91
92
93// Data about the focus of entries
94
95struct LocalFocus
96{
97 tools::Rectangle aRect;
98 Color aPenColor;
99};
100
101
102// Implementation-class of IconChoiceCtrl
103
104
105typedef std::map<sal_uInt16, std::unique_ptr<SvxIconChoiceCtrlColumnInfo>> SvxIconChoiceCtrlColumnInfoMap;
106typedef std::vector<SvxIconChoiceCtrlEntry*> SvxIconChoiceCtrlEntryPtrVec;
107
108class SvxIconChoiceCtrl_Impl
109{
110 friend class IcnCursor_Impl;
111 friend class IcnGridMap_Impl;
112
113 std::vector< std::unique_ptr<SvxIconChoiceCtrlEntry> > maEntries;
114 VclPtr<ScrollBar> aVerSBar;
115 VclPtr<ScrollBar> aHorSBar;
116 VclPtr<ScrollBarBox> aScrBarBox;
117 tools::Rectangle aCurSelectionRect;
118 std::vector<tools::Rectangle> aSelectedRectList;
119 Idle aAutoArrangeIdle;
120 Idle aDocRectChangedIdle;
121 Idle aVisRectChangedIdle;
122 Idle aCallSelectHdlIdle;
123 Size aVirtOutputSize;
124 Size aImageSize;
125 Size aDefaultTextSize;
126 Size aOutputSize; // Pixel
127 VclPtr<SvtIconChoiceCtrl> pView;
128 std::unique_ptr<IcnCursor_Impl> pImpCursor;
129 std::unique_ptr<IcnGridMap_Impl> pGridMap;
130 long nMaxVirtWidth; // max. width aVirtOutputSize for ALIGN_TOP
131 long nMaxVirtHeight; // max. height aVirtOutputSize for ALIGN_LEFT
132 std::vector< SvxIconChoiceCtrlEntry* > maZOrderList;
133 std::unique_ptr<SvxIconChoiceCtrlColumnInfoMap> m_pColumns;
134 WinBits nWinBits;
135 long nMaxBoundHeight; // height of highest BoundRects
136 IconChoiceFlags nFlags;
137 DrawTextFlags nCurTextDrawFlags;
138 ImplSVEvent * nUserEventAdjustScrBars;
139 SvxIconChoiceCtrlEntry* pCurHighlightFrame;
140 bool bHighlightFramePressed;
141 SvxIconChoiceCtrlEntry* pHead = nullptr; // top left entry
142 SvxIconChoiceCtrlEntry* pCursor;
143 SvxIconChoiceCtrlEntry* pHdlEntry;
144 SvxIconChoiceCtrlEntry* pAnchor; // for selection
145 LocalFocus aFocus; // Data for focusrect
146 ::vcl::AccessibleFactoryAccess aAccFactory;
147
148 SvxIconChoiceCtrlTextMode eTextMode;
149 SelectionMode eSelectionMode;
150 sal_Int32 nSelectionCount;
151 SvxIconChoiceCtrlPositionMode ePositionMode;
152 bool bBoundRectsDirty;
153 bool bUpdateMode;
154
155 void ShowCursor( bool bShow );
156
157 void ImpArrange( bool bKeepPredecessors );
158 void AdjustVirtSize( const tools::Rectangle& );
159 void ResetVirtSize();
160 void CheckScrollBars();
161
162 DECL_LINK( ScrollUpDownHdl, ScrollBar*, void )static void LinkStubScrollUpDownHdl(void *, ScrollBar*); void
ScrollUpDownHdl(ScrollBar*)
;
163 DECL_LINK( ScrollLeftRightHdl, ScrollBar*, void )static void LinkStubScrollLeftRightHdl(void *, ScrollBar*); void
ScrollLeftRightHdl(ScrollBar*)
;
164 DECL_LINK( UserEventHdl, void*, void )static void LinkStubUserEventHdl(void *, void*); void UserEventHdl
(void*)
;
165 DECL_LINK( AutoArrangeHdl, Timer*, void )static void LinkStubAutoArrangeHdl(void *, Timer*); void AutoArrangeHdl
(Timer*)
;
166 DECL_LINK( DocRectChangedHdl, Timer*, void )static void LinkStubDocRectChangedHdl(void *, Timer*); void DocRectChangedHdl
(Timer*)
;
167 DECL_LINK( VisRectChangedHdl, Timer*, void )static void LinkStubVisRectChangedHdl(void *, Timer*); void VisRectChangedHdl
(Timer*)
;
168 DECL_LINK( CallSelectHdlHdl, Timer*, void )static void LinkStubCallSelectHdlHdl(void *, Timer*); void CallSelectHdlHdl
(Timer*)
;
169
170 void AdjustScrollBars();
171 void PositionScrollBars( long nRealWidth, long nRealHeight );
172 static long GetScrollBarPageSize( long nVisibleRange )
173 {
174 return ((nVisibleRange*75)/100);
175 }
176 long GetScrollBarLineSize() const
177 {
178 return nMaxBoundHeight / 2;
179 }
180 bool HandleScrollCommand( const CommandEvent& rCmd );
181 void ToDocPos( Point& rPosPixel )
182 {
183 rPosPixel -= pView->GetMapMode().GetOrigin();
184 }
185 void InitScrollBarBox();
186 void ToggleSelection( SvxIconChoiceCtrlEntry* );
187 void DeselectAllBut( SvxIconChoiceCtrlEntry const * );
188 void Center( SvxIconChoiceCtrlEntry* pEntry ) const;
189 void CallSelectHandler();
190 void SelectRect(
191 SvxIconChoiceCtrlEntry* pEntry1,
192 SvxIconChoiceCtrlEntry* pEntry2,
193 bool bAdd,
194 std::vector<tools::Rectangle>* pOtherRects
195 );
196
197 void SelectRange(
198 SvxIconChoiceCtrlEntry const * pStart,
199 SvxIconChoiceCtrlEntry const * pEnd,
200 bool bAdd
201 );
202
203 void AddSelectedRect( const tools::Rectangle& );
204 void AddSelectedRect(
205 SvxIconChoiceCtrlEntry* pEntry1,
206 SvxIconChoiceCtrlEntry* pEntry2
207 );
208
209 void ClearSelectedRectList();
210 tools::Rectangle CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const;
211
212 void ClipAtVirtOutRect( tools::Rectangle& rRect ) const;
213 sal_uLong GetPredecessorGrid( const Point& rDocPos) const;
214
215 void InitPredecessors();
216 void ClearPredecessors();
217
218 bool CheckVerScrollBar();
219 bool CheckHorScrollBar();
220 void CancelUserEvents();
221 void EntrySelected(
222 SvxIconChoiceCtrlEntry* pEntry,
223 bool bSelect
224 );
225 void RepaintSelectedEntries();
226 void SetListPositions();
227 void SetDefaultTextSize();
228 bool IsAutoArrange() const
229 {
230 return (ePositionMode == SvxIconChoiceCtrlPositionMode::AutoArrange);
27
Assuming field 'ePositionMode' is equal to AutoArrange
28
Returning the value 1, which participates in a condition later
42
Assuming field 'ePositionMode' is equal to AutoArrange
43
Returning the value 1, which participates in a condition later
231 }
232 void DocRectChanged() { aDocRectChangedIdle.Start(); }
233 void VisRectChanged() { aVisRectChangedIdle.Start(); }
234 void SetOrigin( const Point& );
235
236 void ShowFocus ( tools::Rectangle const & rRect );
237 void DrawFocusRect(vcl::RenderContext& rRenderContext);
238
239 bool IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const;
240
241 // Copy assignment is forbidden and not implemented.
242 SvxIconChoiceCtrl_Impl (const SvxIconChoiceCtrl_Impl &) = delete;
243 SvxIconChoiceCtrl_Impl & operator= (const SvxIconChoiceCtrl_Impl &) = delete;
244
245public:
246
247 long nGridDX;
248 long nGridDY;
249 long nHorSBarHeight;
250 long nVerSBarWidth;
251
252 SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pView, WinBits nWinStyle );
253 ~SvxIconChoiceCtrl_Impl();
254
255 void Clear( bool bInCtor );
256 void SetStyle( WinBits nWinStyle );
257 WinBits GetStyle() const { return nWinBits; }
258 void InsertEntry( std::unique_ptr<SvxIconChoiceCtrlEntry>, size_t nPos );
259 void RemoveEntry( size_t nPos );
260 void FontModified();
261 void SelectAll();
262 void SelectEntry(
263 SvxIconChoiceCtrlEntry*,
264 bool bSelect,
265 bool bAddToSelection = false
266 );
267 void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect);
268 bool MouseButtonDown( const MouseEvent& );
269 bool MouseButtonUp( const MouseEvent& );
270 bool MouseMove( const MouseEvent&);
271 bool RequestHelp( const HelpEvent& rHEvt );
272 void SetCursor_Impl(
273 SvxIconChoiceCtrlEntry* pOldCursor,
274 SvxIconChoiceCtrlEntry* pNewCursor,
275 bool bMod1,
276 bool bShift
277 );
278 bool KeyInput( const KeyEvent& );
279 void Resize();
280 void GetFocus();
281 void LoseFocus();
282 void SetUpdateMode( bool bUpdate );
283 bool GetUpdateMode() const { return bUpdateMode; }
284 void PaintEntry(SvxIconChoiceCtrlEntry*, const Point&, vcl::RenderContext& rRenderContext);
285
286 void SetEntryPos(
287 SvxIconChoiceCtrlEntry* pEntry,
288 const Point& rPos
289 );
290
291 void InvalidateEntry( SvxIconChoiceCtrlEntry* );
292
293 void SetNoSelection();
294
295 SvxIconChoiceCtrlEntry* GetCurEntry() const { return pCursor; }
296 void SetCursor( SvxIconChoiceCtrlEntry* );
297
298 SvxIconChoiceCtrlEntry* GetEntry( const Point& rDocPos, bool bHit = false );
299
300 void MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, bool bBound = true );
301
302 void Arrange(
303 bool bKeepPredecessors,
304 long nSetMaxVirtWidth,
305 long nSetMaxVirtHeight
306 );
307
308 tools::Rectangle CalcFocusRect( SvxIconChoiceCtrlEntry* );
309 tools::Rectangle CalcBmpRect( SvxIconChoiceCtrlEntry*, const Point* pPos = nullptr );
310 tools::Rectangle CalcTextRect(
311 SvxIconChoiceCtrlEntry*,
312 const Point* pPos = nullptr,
313 const OUString* pStr = nullptr
314 );
315
316 long CalcBoundingWidth() const;
317 long CalcBoundingHeight() const;
318 Size CalcBoundingSize() const;
319 void FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry );
320 void SetBoundingRect_Impl(
321 SvxIconChoiceCtrlEntry* pEntry,
322 const Point& rPos,
323 const Size& rBoundingSize
324 );
325 // recalculates all invalid BoundRects
326 void RecalcAllBoundingRectsSmart();
327 const tools::Rectangle& GetEntryBoundRect( SvxIconChoiceCtrlEntry* );
328 void InvalidateBoundingRect( tools::Rectangle& rRect )
329 {
330 rRect.SetRight(LONG_MAX9223372036854775807L);
331 bBoundRectsDirty = true;
332 }
333 static bool IsBoundingRectValid( const tools::Rectangle& rRect ) { return ( rRect.Right() != LONG_MAX9223372036854775807L ); }
334
335 static void PaintEmphasis(const tools::Rectangle& rRect1, bool bSelected,
336 vcl::RenderContext& rRenderContext );
337
338 void PaintItem(const tools::Rectangle& rRect, IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry,
339 sal_uInt16 nPaintFlags, vcl::RenderContext& rRenderContext);
340
341 // recalculates all BoundingRects if bMustRecalcBoundingRects == true
342 void CheckBoundingRects() { if (bBoundRectsDirty) RecalcAllBoundingRectsSmart(); }
343 void Command( const CommandEvent& rCEvt );
344 void ToTop( SvxIconChoiceCtrlEntry* );
345
346 sal_Int32 GetSelectionCount() const;
347 void SetGrid( const Size& );
348 Size GetMinGrid() const;
349 void Scroll( long nDeltaX, long nDeltaY );
350 const Size& GetItemSize( IcnViewFieldType ) const;
351
352 void HideDDIcon();
353
354 static bool IsOver(
355 std::vector<tools::Rectangle>* pSelectedRectList,
356 const tools::Rectangle& rEntryBoundRect
357 );
358
359 void SelectRect(
360 const tools::Rectangle&,
361 bool bAdd,
362 std::vector<tools::Rectangle>* pOtherRects
363 );
364
365 void MakeVisible(
366 const tools::Rectangle& rDocPos,
367 bool bInScrollBarEvent=false
368 );
369
370#ifdef DBG_UTIL
371 void SetEntryTextMode(
372 SvxIconChoiceCtrlTextMode,
373 SvxIconChoiceCtrlEntry* pEntry
374 );
375#endif
376 size_t GetEntryCount() const { return maEntries.size(); }
377 SvxIconChoiceCtrlEntry* GetEntry( size_t nPos )
378 {
379 return maEntries[ nPos ].get();
380 }
381 SvxIconChoiceCtrlEntry* GetEntry( size_t nPos ) const
382 {
383 return maEntries[ nPos ].get();
384 }
385 SvxIconChoiceCtrlEntry* GetFirstSelectedEntry() const;
386 sal_Int32 GetEntryListPos( SvxIconChoiceCtrlEntry const * ) const;
387 void InitSettings();
388 tools::Rectangle GetOutputRect() const;
389
390 void SetEntryPredecessor(SvxIconChoiceCtrlEntry* pEntry,SvxIconChoiceCtrlEntry* pPredecessor);
391 // only delivers valid results when in AutoArrange mode!
392 SvxIconChoiceCtrlEntry* FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry, const Point& );
393
394 void SetPositionMode( SvxIconChoiceCtrlPositionMode );
395
396 void SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& );
397 const SvxIconChoiceCtrlColumnInfo* GetColumn( sal_uInt16 nIndex ) const;
398
399 void SetEntryHighlightFrame(
400 SvxIconChoiceCtrlEntry* pEntry,
401 bool bKeepHighlightFlags
402 );
403 void DrawHighlightFrame(vcl::RenderContext& rRenderContext, const tools::Rectangle& rBmpRect);
404
405 void CallEventListeners( VclEventId nEvent, void* pData );
406
407 ::vcl::IAccessibleFactory& GetAccessibleFactory()
408 {
409 return aAccFactory.getFactory();
410 }
411};
412
413typedef std::map<sal_uInt16, SvxIconChoiceCtrlEntryPtrVec> IconChoiceMap;
414
415class IcnCursor_Impl
416{
417 SvxIconChoiceCtrl_Impl* pView;
418 std::unique_ptr<IconChoiceMap> xColumns;
419 std::unique_ptr<IconChoiceMap> xRows;
420 long nCols;
421 long nRows;
422 short nDeltaWidth;
423 short nDeltaHeight;
424 SvxIconChoiceCtrlEntry* pCurEntry;
425 void SetDeltas();
426 void ImplCreate();
427 void Create() { if( !xColumns ) ImplCreate(); }
428
429 sal_uInt16 GetSortListPos(
430 SvxIconChoiceCtrlEntryPtrVec& rList,
431 long nValue,
432 bool bVertical);
433 SvxIconChoiceCtrlEntry* SearchCol(
434 sal_uInt16 nCol,
435 sal_uInt16 nTop,
436 sal_uInt16 nBottom,
437 bool bDown,
438 bool bSimple
439 );
440
441 SvxIconChoiceCtrlEntry* SearchRow(
442 sal_uInt16 nRow,
443 sal_uInt16 nLeft,
444 sal_uInt16 nRight,
445 bool bRight,
446 bool bSimple
447 );
448
449public:
450 explicit IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner );
451 ~IcnCursor_Impl();
452 void Clear();
453
454 // for Cursortravelling etc.
455 SvxIconChoiceCtrlEntry* GoLeftRight( SvxIconChoiceCtrlEntry*, bool bRight );
456 SvxIconChoiceCtrlEntry* GoUpDown( SvxIconChoiceCtrlEntry*, bool bDown );
457 SvxIconChoiceCtrlEntry* GoPageUpDown( SvxIconChoiceCtrlEntry*, bool bDown );
458};
459
460
461typedef sal_uLong GridId;
462
463#define GRID_NOT_FOUND((GridId)(9223372036854775807L *2UL+1UL)) ((GridId)ULONG_MAX(9223372036854775807L *2UL+1UL))
464
465class IcnGridMap_Impl
466{
467 tools::Rectangle _aLastOccupiedGrid;
468 SvxIconChoiceCtrl_Impl* _pView;
469 std::unique_ptr<bool[]> _pGridMap;
470 sal_uInt16 _nGridCols, _nGridRows;
471
472 void Expand();
473 void Create_Impl();
474 void Create() { if(!_pGridMap) Create_Impl(); }
475
476 void GetMinMapSize( sal_uInt16& rDX, sal_uInt16& rDY ) const;
477
478public:
479 explicit IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView);
480 ~IcnGridMap_Impl();
481
482 void Clear();
483
484 GridId GetGrid( const Point& rDocPos );
485 GridId GetGrid( sal_uInt16 nGridX, sal_uInt16 nGridY );
486 GridId GetUnoccupiedGrid();
487
488 void OccupyGrids( const SvxIconChoiceCtrlEntry* );
489 void OccupyGrid( GridId nId )
490 {
491 DBG_ASSERT(!_pGridMap || nId<o3tl::make_unsigned(_nGridCols*_nGridRows),"OccupyGrid: Bad GridId")do { if (true && (!(!_pGridMap || nId<o3tl::make_unsigned
(_nGridCols*_nGridRows)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/vcl/source/control/imivctl.hxx"
":" "491" ": "), "%s", "OccupyGrid: Bad GridId"); } } while (
false)
;
492 if(_pGridMap && nId < o3tl::make_unsigned(_nGridCols *_nGridRows) )
493 _pGridMap[ nId ] = true;
494 }
495
496 tools::Rectangle GetGridRect( GridId );
497 void GetGridCoord( GridId, sal_uInt16& rGridX, sal_uInt16& rGridY );
498 static sal_uLong GetGridCount(
499 const Size& rSizePixel,
500 sal_uInt16 nGridWidth,
501 sal_uInt16 nGridHeight
502 );
503
504 void OutputSizeChanged();
505};
506
507#endif
508
509/* vim:set shiftwidth=4 softtabstop=4 expandtab: */