/src/libreoffice/vcl/source/control/imivctl1.cxx
Line | Count | Source |
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/salnativewidgets.hxx> |
29 | | #include <vcl/svapp.hxx> |
30 | | #include <vcl/vclevent.hxx> |
31 | | #include <tools/poly.hxx> |
32 | | #include <vcl/lineinfo.hxx> |
33 | | #include <vcl/i18nhelp.hxx> |
34 | | #include <vcl/mnemonic.hxx> |
35 | | #include <vcl/settings.hxx> |
36 | | #include <vcl/commandevent.hxx> |
37 | | |
38 | | #include <ivctrl.hxx> |
39 | | |
40 | | #include "imivctl.hxx" |
41 | | |
42 | | #include <algorithm> |
43 | | #include <memory> |
44 | | #include <vcl/idle.hxx> |
45 | | |
46 | | constexpr auto DRAWTEXT_FLAGS_ICON = |
47 | | DrawTextFlags::Center | DrawTextFlags::Top | DrawTextFlags::EndEllipsis | |
48 | | DrawTextFlags::Clip | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak | DrawTextFlags::Mnemonic; |
49 | | |
50 | 0 | #define DRAWTEXT_FLAGS_SMALLICON (DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags::Clip) |
51 | | |
52 | 0 | #define EVENTID_ADJUST_SCROLLBARS (reinterpret_cast<void*>(1)) |
53 | | |
54 | | SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( |
55 | | SvtIconChoiceCtrl* pCurView, |
56 | | WinBits nWinStyle |
57 | | ) : |
58 | 0 | aVerSBar( VclPtr<ScrollBar>::Create(pCurView, WB_DRAG | WB_VSCROLL) ), |
59 | 0 | aHorSBar( VclPtr<ScrollBar>::Create(pCurView, WB_DRAG | WB_HSCROLL) ), |
60 | 0 | aScrBarBox( VclPtr<ScrollBarBox>::Create(pCurView) ), |
61 | 0 | aDocRectChangedIdle( "svtools::SvxIconChoiceCtrl_Impl aDocRectChangedIdle" ), |
62 | 0 | aVisRectChangedIdle( "svtools::SvxIconChoiceCtrl_Impl aVisRectChangedIdle" ), |
63 | 0 | aImageSize( 32 * pCurView->GetDPIScaleFactor(), 32 * pCurView->GetDPIScaleFactor()), |
64 | 0 | pView(pCurView), nMaxVirtHeight(DEFAULT_MAX_VIRT_HEIGHT), |
65 | 0 | nFlags(IconChoiceFlags::NONE), nUserEventAdjustScrBars(nullptr), |
66 | 0 | pCurHighlightFrame(nullptr), |
67 | 0 | pCursor(nullptr) |
68 | 0 | { |
69 | 0 | SetStyle( nWinStyle ); |
70 | 0 | pImpCursor.reset( new IcnCursor_Impl( this ) ); |
71 | 0 | pGridMap.reset( new IcnGridMap_Impl( this ) ); |
72 | |
|
73 | 0 | aVerSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) ); |
74 | 0 | aHorSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) ); |
75 | |
|
76 | 0 | nHorSBarHeight = aHorSBar->GetSizePixel().Height(); |
77 | 0 | nVerSBarWidth = aVerSBar->GetSizePixel().Width(); |
78 | |
|
79 | 0 | aDocRectChangedIdle.SetPriority( TaskPriority::HIGH_IDLE ); |
80 | 0 | aDocRectChangedIdle.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl)); |
81 | |
|
82 | 0 | aVisRectChangedIdle.SetPriority( TaskPriority::HIGH_IDLE ); |
83 | 0 | aVisRectChangedIdle.SetInvokeHandler(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl)); |
84 | |
|
85 | 0 | Clear( true ); |
86 | 0 | Size gridSize; |
87 | 0 | if (nWinStyle & WB_SMALLICON) |
88 | 0 | gridSize = Size(-1, 32); |
89 | 0 | else |
90 | 0 | gridSize = Size(140, 70); |
91 | 0 | if(pView->GetDPIScaleFactor() > 1) |
92 | 0 | { |
93 | 0 | gridSize.setHeight( gridSize.Height() * ( pView->GetDPIScaleFactor()) ); |
94 | 0 | } |
95 | 0 | SetGrid(gridSize); |
96 | 0 | } |
97 | | |
98 | | SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl() |
99 | 0 | { |
100 | 0 | Clear(false); |
101 | 0 | CancelUserEvents(); |
102 | 0 | pImpCursor.reset(); |
103 | 0 | pGridMap.reset(); |
104 | 0 | aVerSBar.disposeAndClear(); |
105 | 0 | aHorSBar.disposeAndClear(); |
106 | 0 | aScrBarBox.disposeAndClear(); |
107 | 0 | } |
108 | | |
109 | | void SvxIconChoiceCtrl_Impl::Clear( bool bInCtor ) |
110 | 0 | { |
111 | 0 | pCurHighlightFrame = nullptr; |
112 | 0 | CancelUserEvents(); |
113 | 0 | ShowCursor( false ); |
114 | 0 | bBoundRectsDirty = false; |
115 | 0 | nMaxBoundHeight = 0; |
116 | |
|
117 | 0 | pCursor = nullptr; |
118 | 0 | if( !bInCtor ) |
119 | 0 | { |
120 | 0 | pImpCursor->Clear(); |
121 | 0 | pGridMap->Clear(); |
122 | 0 | aVirtOutputSize.setWidth( 0 ); |
123 | 0 | aVirtOutputSize.setHeight( 0 ); |
124 | 0 | Size aSize( pView->GetOutputSizePixel() ); |
125 | 0 | nMaxVirtHeight = aSize.Height() - nHorSBarHeight; |
126 | 0 | if( nMaxVirtHeight <= 0 ) |
127 | 0 | nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT; |
128 | 0 | maZOrderList.clear(); |
129 | 0 | SetOrigin( Point() ); |
130 | 0 | pView->Invalidate(InvalidateFlags::NoChildren); |
131 | 0 | } |
132 | 0 | AdjustScrollBars(); |
133 | 0 | maEntries.clear(); |
134 | 0 | DocRectChanged(); |
135 | 0 | VisRectChanged(); |
136 | 0 | } |
137 | | |
138 | | void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle ) |
139 | 0 | { |
140 | 0 | nWinBits = nWinStyle; |
141 | 0 | nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON; |
142 | 0 | if( nWinBits & (WB_SMALLICON | WB_DETAILS) ) |
143 | 0 | nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON; |
144 | 0 | } |
145 | | |
146 | | IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar, void ) |
147 | 0 | { |
148 | | // arrow up: delta=-1; arrow down: delta=+1 |
149 | 0 | Scroll( 0, pScrollBar->GetDelta() ); |
150 | 0 | } |
151 | | |
152 | | IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar, void ) |
153 | 0 | { |
154 | | // arrow left: delta=-1; arrow right: delta=+1 |
155 | 0 | Scroll( pScrollBar->GetDelta(), 0 ); |
156 | 0 | } |
157 | | |
158 | | void SvxIconChoiceCtrl_Impl::FontModified() |
159 | 0 | { |
160 | 0 | SetDefaultTextSize(); |
161 | 0 | ShowCursor( false ); |
162 | 0 | ShowCursor( true ); |
163 | 0 | } |
164 | | |
165 | | void SvxIconChoiceCtrl_Impl::InsertEntry( std::unique_ptr<SvxIconChoiceCtrlEntry> pEntry1, size_t nPos) |
166 | 0 | { |
167 | 0 | auto pEntry = pEntry1.get(); |
168 | |
|
169 | 0 | if ( nPos < maEntries.size() ) { |
170 | 0 | maEntries.insert( maEntries.begin() + nPos, std::move(pEntry1) ); |
171 | 0 | } else { |
172 | 0 | maEntries.push_back( std::move(pEntry1) ); |
173 | 0 | } |
174 | |
|
175 | 0 | maZOrderList.push_back( pEntry ); |
176 | 0 | pImpCursor->Clear(); |
177 | | |
178 | | // don't set all bounding rectangles to |
179 | | // 'to be checked', but only the bounding rectangle of the new entry. |
180 | | // Thus, don't call InvalidateBoundingRect! |
181 | 0 | pEntry->aRect.SetRight( LONG_MAX ); |
182 | 0 | FindBoundingRect(pEntry); |
183 | | // initial calculation w/o icon yet to ensure the background is filled |
184 | 0 | if (nWinBits & WB_SMALLICON) |
185 | 0 | { |
186 | 0 | tools::Rectangle aTextRect = pView->GetTextRect( CalcMaxTextRect( pEntry ), pEntry->GetText(), nCurTextDrawFlags ); |
187 | 0 | pView->AdjustWidth(32 + aTextRect.GetSize().Width() + 2 * HOR_DIST_BMP_STRING ); |
188 | 0 | } |
189 | |
|
190 | 0 | tools::Rectangle aOutputArea(GetOutputRect()); |
191 | 0 | pGridMap->OccupyGrids(pEntry); |
192 | 0 | if (!aOutputArea.Overlaps(pEntry->aRect)) |
193 | 0 | return; // is invisible |
194 | 0 | pView->Invalidate(pEntry->aRect); |
195 | 0 | } |
196 | | |
197 | | void SvxIconChoiceCtrl_Impl::RemoveEntry(size_t nPos) |
198 | 0 | { |
199 | 0 | pImpCursor->Clear(); |
200 | 0 | maEntries.erase(maEntries.begin() + nPos); |
201 | 0 | RecalcAllBoundingRectsSmart(); |
202 | 0 | } |
203 | | |
204 | | tools::Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const |
205 | 0 | { |
206 | 0 | Point aOrigin( pView->GetMapMode().GetOrigin() ); |
207 | 0 | aOrigin *= -1; |
208 | 0 | return tools::Rectangle( aOrigin, aOutputSize ); |
209 | 0 | } |
210 | | |
211 | | void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, bool bSelect, |
212 | | bool bAdd ) |
213 | 0 | { |
214 | |
|
215 | 0 | if( !bAdd ) |
216 | 0 | { |
217 | 0 | if ( !( nFlags & IconChoiceFlags::ClearingSelection ) ) |
218 | 0 | { |
219 | 0 | nFlags |= IconChoiceFlags::ClearingSelection; |
220 | 0 | DeselectAllBut( pEntry ); |
221 | 0 | nFlags &= ~IconChoiceFlags::ClearingSelection; |
222 | 0 | } |
223 | 0 | } |
224 | 0 | if( pEntry->IsSelected() == bSelect ) |
225 | 0 | return; |
226 | | |
227 | 0 | SvxIconViewFlags nEntryFlags = pEntry->GetFlags(); |
228 | 0 | if( bSelect ) |
229 | 0 | { |
230 | 0 | nEntryFlags |= SvxIconViewFlags::SELECTED; |
231 | 0 | pEntry->AssignFlags( nEntryFlags ); |
232 | 0 | pView->ClickIcon(); |
233 | 0 | } |
234 | 0 | else |
235 | 0 | { |
236 | 0 | nEntryFlags &= ~SvxIconViewFlags::SELECTED; |
237 | 0 | pEntry->AssignFlags( nEntryFlags ); |
238 | 0 | pView->ClickIcon(); |
239 | 0 | } |
240 | 0 | EntrySelected( pEntry, bSelect ); |
241 | 0 | } |
242 | | |
243 | | void SvxIconChoiceCtrl_Impl::EntrySelected(SvxIconChoiceCtrlEntry* pEntry, bool bSelect) |
244 | 0 | { |
245 | | // make sure that the cursor is always placed |
246 | | // over the (only) selected entry. (But only if a cursor exists.) |
247 | 0 | if (bSelect && pCursor && pEntry != pCursor) |
248 | 0 | { |
249 | 0 | SetCursor(pEntry); |
250 | 0 | } |
251 | |
|
252 | 0 | ToTop(pEntry); |
253 | |
|
254 | 0 | if (pEntry == pCursor) |
255 | 0 | ShowCursor(false); |
256 | 0 | pView->Invalidate(CalcFocusRect(pEntry)); |
257 | 0 | if (pEntry == pCursor) |
258 | 0 | ShowCursor(true); |
259 | | |
260 | | // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected. |
261 | 0 | if (bSelect) |
262 | 0 | { |
263 | 0 | CallEventListeners(VclEventId::ListboxSelect, pEntry); |
264 | 0 | } |
265 | 0 | } |
266 | | |
267 | | void SvxIconChoiceCtrl_Impl::ResetVirtSize() |
268 | 0 | { |
269 | 0 | aVirtOutputSize.setWidth( 0 ); |
270 | 0 | aVirtOutputSize.setHeight( 0 ); |
271 | 0 | const size_t nCount = maEntries.size(); |
272 | 0 | for( size_t nCur = 0; nCur < nCount; nCur++ ) |
273 | 0 | { |
274 | 0 | SvxIconChoiceCtrlEntry* pCur = maEntries[ nCur ].get(); |
275 | 0 | InvalidateBoundingRect(pCur->aRect); |
276 | 0 | } |
277 | |
|
278 | 0 | if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) ) |
279 | 0 | { |
280 | 0 | Size aRealOutputSize( pView->GetOutputSizePixel() ); |
281 | 0 | if( aVirtOutputSize.Width() < aRealOutputSize.Width() || |
282 | 0 | aVirtOutputSize.Height() < aRealOutputSize.Height() ) |
283 | 0 | { |
284 | 0 | sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount( |
285 | 0 | aRealOutputSize, static_cast<sal_uInt16>(nGridDX), static_cast<sal_uInt16>(nGridDY) ); |
286 | 0 | if( nGridCount < nCount ) |
287 | 0 | nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight; |
288 | 0 | } |
289 | 0 | } |
290 | |
|
291 | 0 | pImpCursor->Clear(); |
292 | 0 | pGridMap->Clear(); |
293 | 0 | VisRectChanged(); |
294 | 0 | } |
295 | | |
296 | | void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const tools::Rectangle& rRect ) |
297 | 0 | { |
298 | 0 | tools::Long nHeightOffs = 0; |
299 | 0 | tools::Long nWidthOffs = 0; |
300 | |
|
301 | 0 | if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) ) |
302 | 0 | nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width(); |
303 | |
|
304 | 0 | if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) ) |
305 | 0 | nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height(); |
306 | |
|
307 | 0 | if( !(nWidthOffs || nHeightOffs) ) |
308 | 0 | return; |
309 | | |
310 | 0 | Range aRange; |
311 | 0 | aVirtOutputSize.AdjustWidth(nWidthOffs ); |
312 | 0 | aRange.Max() = aVirtOutputSize.Width(); |
313 | 0 | aHorSBar->SetRange( aRange ); |
314 | |
|
315 | 0 | aVirtOutputSize.AdjustHeight(nHeightOffs ); |
316 | 0 | aRange.Max() = aVirtOutputSize.Height(); |
317 | 0 | aVerSBar->SetRange( aRange ); |
318 | |
|
319 | 0 | pImpCursor->Clear(); |
320 | 0 | pGridMap->OutputSizeChanged(); |
321 | 0 | AdjustScrollBars(); |
322 | 0 | DocRectChanged(); |
323 | 0 | } |
324 | | |
325 | | void SvxIconChoiceCtrl_Impl::Arrange(tools::Long nSetMaxVirtHeight) |
326 | 0 | { |
327 | 0 | if ( nSetMaxVirtHeight != 0 ) |
328 | 0 | nMaxVirtHeight = nSetMaxVirtHeight; |
329 | 0 | else |
330 | 0 | nMaxVirtHeight = aOutputSize.Height(); |
331 | |
|
332 | 0 | ImpArrange(); |
333 | 0 | } |
334 | | |
335 | | void SvxIconChoiceCtrl_Impl::ImpArrange() |
336 | 0 | { |
337 | 0 | nFlags |= IconChoiceFlags::Arranging; |
338 | 0 | ShowCursor( false ); |
339 | 0 | ResetVirtSize(); |
340 | 0 | bBoundRectsDirty = false; |
341 | 0 | SetOrigin( Point() ); |
342 | 0 | VisRectChanged(); |
343 | 0 | RecalcAllBoundingRectsSmart(); |
344 | 0 | pView->Invalidate( InvalidateFlags::NoChildren ); |
345 | 0 | nFlags &= ~IconChoiceFlags::Arranging; |
346 | 0 | ShowCursor( true ); |
347 | 0 | } |
348 | | |
349 | | void SvxIconChoiceCtrl_Impl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) |
350 | 0 | { |
351 | 0 | if (!maEntries.size()) |
352 | 0 | return; |
353 | 0 | if (!pCursor) |
354 | 0 | { |
355 | | // set cursor to item with focus-flag |
356 | 0 | bool bfound = false; |
357 | 0 | for (sal_Int32 i = 0; i < pView->GetEntryCount() && !bfound; i++) |
358 | 0 | { |
359 | 0 | SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry(i); |
360 | 0 | if (pEntry->IsFocused()) |
361 | 0 | { |
362 | 0 | pCursor = pEntry; |
363 | 0 | bfound = true; |
364 | 0 | } |
365 | 0 | } |
366 | |
|
367 | 0 | if (!bfound) |
368 | 0 | pCursor = maEntries[ 0 ].get(); |
369 | 0 | } |
370 | |
|
371 | 0 | size_t nCount = maZOrderList.size(); |
372 | 0 | if (!nCount) |
373 | 0 | return; |
374 | | |
375 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::CLIPREGION); |
376 | 0 | rRenderContext.SetClipRegion(vcl::Region(rRect)); |
377 | |
|
378 | 0 | std::vector< SvxIconChoiceCtrlEntry* > aNewZOrderList; |
379 | 0 | std::vector< SvxIconChoiceCtrlEntry* > aPaintedEntries; |
380 | |
|
381 | 0 | size_t nPos = 0; |
382 | 0 | while(nCount) |
383 | 0 | { |
384 | 0 | SvxIconChoiceCtrlEntry* pEntry = maZOrderList[nPos]; |
385 | 0 | const tools::Rectangle& rBoundRect = GetEntryBoundRect(pEntry); |
386 | 0 | if (rRect.Overlaps(rBoundRect)) |
387 | 0 | { |
388 | 0 | PaintEntry(pEntry, rBoundRect.TopLeft(), rRenderContext); |
389 | | // set entries to Top if they are being repainted |
390 | 0 | aPaintedEntries.push_back(pEntry); |
391 | 0 | } |
392 | 0 | else |
393 | 0 | aNewZOrderList.push_back(pEntry); |
394 | |
|
395 | 0 | nCount--; |
396 | 0 | nPos++; |
397 | 0 | } |
398 | 0 | maZOrderList = std::move( aNewZOrderList ); |
399 | 0 | maZOrderList.insert(maZOrderList.end(), aPaintedEntries.begin(), aPaintedEntries.end()); |
400 | 0 | } |
401 | | |
402 | | void SvxIconChoiceCtrl_Impl::RepaintSelectedEntries() |
403 | 0 | { |
404 | 0 | tools::Rectangle aOutRect(GetOutputRect()); |
405 | 0 | for (SvxIconChoiceCtrlEntry* pEntry : maZOrderList) |
406 | 0 | { |
407 | 0 | if (pEntry->GetFlags() & SvxIconViewFlags::SELECTED) |
408 | 0 | { |
409 | 0 | const tools::Rectangle& rBoundRect = GetEntryBoundRect(pEntry); |
410 | 0 | if (aOutRect.Overlaps(rBoundRect)) |
411 | 0 | pView->Invalidate(rBoundRect); |
412 | 0 | } |
413 | 0 | } |
414 | 0 | } |
415 | | |
416 | | void SvxIconChoiceCtrl_Impl::InitScrollBarBox() |
417 | 0 | { |
418 | 0 | aScrBarBox->SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) ); |
419 | 0 | Size aSize( pView->GetOutputSizePixel() ); |
420 | 0 | aScrBarBox->SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1)); |
421 | 0 | } |
422 | | |
423 | | bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt) |
424 | 0 | { |
425 | 0 | bool bHandled = true; |
426 | 0 | if( !(nWinBits & WB_NOPOINTERFOCUS) ) |
427 | 0 | pView->GrabFocus(); |
428 | |
|
429 | 0 | Point aDocPos( rMEvt.GetPosPixel() ); |
430 | 0 | if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height()) |
431 | 0 | return false; |
432 | 0 | ToDocPos( aDocPos ); |
433 | 0 | SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos ); |
434 | 0 | if( pEntry ) |
435 | 0 | MakeEntryVisible(pEntry); |
436 | |
|
437 | 0 | if( !pEntry ) |
438 | 0 | return false; |
439 | | |
440 | 0 | if( rMEvt.GetClicks() == 2 ) |
441 | 0 | { |
442 | 0 | DeselectAllBut( pEntry ); |
443 | 0 | SelectEntry( pEntry, true, false ); |
444 | 0 | pView->ClickIcon(); |
445 | 0 | } |
446 | 0 | else |
447 | 0 | { |
448 | | // Inplace-Editing ? |
449 | 0 | if( rMEvt.IsMod2() ) // Alt? |
450 | 0 | { |
451 | 0 | } |
452 | 0 | else |
453 | 0 | { |
454 | 0 | DeselectAllBut( pEntry ); |
455 | 0 | SetCursor( pEntry ); |
456 | 0 | } |
457 | 0 | } |
458 | 0 | return bHandled; |
459 | 0 | } |
460 | | |
461 | | bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt ) |
462 | 0 | { |
463 | 0 | if( pView->IsTracking() ) |
464 | 0 | return false; |
465 | | |
466 | 0 | SvxIconChoiceCtrlEntry* pEntry = nullptr; |
467 | 0 | if (!rMEvt.IsLeaveWindow()) |
468 | 0 | { |
469 | 0 | const Point aDocPos(pView->PixelToLogic(rMEvt.GetPosPixel())); |
470 | 0 | pEntry = GetEntry(aDocPos); |
471 | 0 | } |
472 | 0 | SetEntryHighlightFrame(pEntry); |
473 | 0 | return true; |
474 | 0 | } |
475 | | |
476 | | void SvxIconChoiceCtrl_Impl::SetCursor_Impl(SvxIconChoiceCtrlEntry* pNewCursor) |
477 | 0 | { |
478 | 0 | if( !pNewCursor ) |
479 | 0 | return; |
480 | | |
481 | 0 | ShowCursor( false ); |
482 | 0 | MakeEntryVisible( pNewCursor ); |
483 | 0 | SetCursor( pNewCursor ); |
484 | |
|
485 | 0 | SelectEntry( pCursor, true, false ); |
486 | 0 | CallEventListeners( VclEventId::ListboxSelect, pCursor ); |
487 | 0 | } |
488 | | |
489 | | bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt ) |
490 | 0 | { |
491 | 0 | bool bMod2 = rKEvt.GetKeyCode().IsMod2(); |
492 | 0 | sal_Unicode cChar = rKEvt.GetCharCode(); |
493 | 0 | sal_uLong nPos = sal_uLong(-1); |
494 | 0 | if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) ) |
495 | 0 | { |
496 | | // shortcut is clicked |
497 | 0 | SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos ); |
498 | 0 | SvxIconChoiceCtrlEntry* pOldCursor = pCursor; |
499 | 0 | if ( pNewCursor != pOldCursor ) |
500 | 0 | SetCursor_Impl(pNewCursor); |
501 | 0 | return true; |
502 | 0 | } |
503 | | |
504 | 0 | if ( bMod2 ) |
505 | | // no actions with <ALT> |
506 | 0 | return false; |
507 | | |
508 | 0 | bool bKeyUsed = true; |
509 | |
|
510 | 0 | SvxIconChoiceCtrlEntry* pNewCursor; |
511 | |
|
512 | 0 | sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
513 | 0 | switch( nCode ) |
514 | 0 | { |
515 | 0 | case KEY_UP: |
516 | 0 | case KEY_PAGEUP: |
517 | 0 | if( pCursor ) |
518 | 0 | { |
519 | 0 | MakeEntryVisible( pCursor ); |
520 | 0 | if( nCode == KEY_UP || (rKEvt.GetKeyCode().IsMod1() && nCode == KEY_PAGEUP)) |
521 | 0 | pNewCursor = pImpCursor->GoUpDown(pCursor,false); |
522 | 0 | else |
523 | 0 | pNewCursor = pImpCursor->GoPageUpDown(pCursor,false); |
524 | 0 | SetCursor_Impl(pNewCursor); |
525 | 0 | if( !pNewCursor ) |
526 | 0 | { |
527 | 0 | tools::Rectangle aRect( GetEntryBoundRect( pCursor ) ); |
528 | 0 | if( aRect.Top()) |
529 | 0 | { |
530 | 0 | aRect.AdjustBottom( -(aRect.Top()) ); |
531 | 0 | aRect.SetTop( 0 ); |
532 | 0 | MakeVisible( aRect ); |
533 | 0 | } |
534 | 0 | } |
535 | 0 | } |
536 | 0 | break; |
537 | 0 | case KEY_TAB: |
538 | 0 | if (!rKEvt.GetKeyCode().IsMod1()) |
539 | 0 | bKeyUsed = false; // handle simple tab key without ctrl/cmd |
540 | 0 | else if( pCursor ) |
541 | 0 | { |
542 | 0 | MakeEntryVisible( pCursor ); |
543 | 0 | const bool bDown = !rKEvt.GetKeyCode().IsShift(); |
544 | 0 | pNewCursor = pImpCursor->GoUpDown(pCursor, bDown, true); |
545 | 0 | SetCursor_Impl(pNewCursor); |
546 | 0 | if( !pNewCursor ) |
547 | 0 | { |
548 | 0 | tools::Rectangle aRect( GetEntryBoundRect( pCursor ) ); |
549 | 0 | if( aRect.Top()) |
550 | 0 | { |
551 | 0 | aRect.AdjustBottom( -(aRect.Top()) ); |
552 | 0 | aRect.SetTop( 0 ); |
553 | 0 | MakeVisible( aRect ); |
554 | 0 | } |
555 | 0 | } |
556 | 0 | } |
557 | 0 | break; |
558 | | |
559 | 0 | case KEY_DOWN: |
560 | 0 | case KEY_PAGEDOWN: |
561 | 0 | if( pCursor ) |
562 | 0 | { |
563 | 0 | if( nCode == KEY_DOWN || (rKEvt.GetKeyCode().IsMod1() && nCode == KEY_PAGEDOWN) ) |
564 | 0 | pNewCursor=pImpCursor->GoUpDown( pCursor,true ); |
565 | 0 | else |
566 | 0 | pNewCursor=pImpCursor->GoPageUpDown( pCursor,true ); |
567 | 0 | SetCursor_Impl(pNewCursor); |
568 | 0 | } |
569 | 0 | break; |
570 | | |
571 | 0 | case KEY_RIGHT: |
572 | 0 | if( pCursor ) |
573 | 0 | { |
574 | 0 | pNewCursor=pImpCursor->GoLeftRight(pCursor,true ); |
575 | 0 | SetCursor_Impl(pNewCursor); |
576 | 0 | } |
577 | 0 | break; |
578 | | |
579 | 0 | case KEY_LEFT: |
580 | 0 | if( pCursor ) |
581 | 0 | { |
582 | 0 | MakeEntryVisible( pCursor ); |
583 | 0 | pNewCursor = pImpCursor->GoLeftRight(pCursor,false ); |
584 | 0 | SetCursor_Impl(pNewCursor); |
585 | 0 | if( !pNewCursor ) |
586 | 0 | { |
587 | 0 | tools::Rectangle aRect( GetEntryBoundRect(pCursor)); |
588 | 0 | if( aRect.Left() ) |
589 | 0 | { |
590 | 0 | aRect.AdjustRight( -(aRect.Left()) ); |
591 | 0 | aRect.SetLeft( 0 ); |
592 | 0 | MakeVisible( aRect ); |
593 | 0 | } |
594 | 0 | } |
595 | 0 | } |
596 | 0 | break; |
597 | | |
598 | 0 | case KEY_F2: |
599 | 0 | break; |
600 | | |
601 | 0 | case KEY_F8: |
602 | 0 | if( rKEvt.GetKeyCode().IsShift() ) |
603 | 0 | { |
604 | 0 | if( nFlags & IconChoiceFlags::AddMode ) |
605 | 0 | nFlags &= ~IconChoiceFlags::AddMode; |
606 | 0 | else |
607 | 0 | nFlags |= IconChoiceFlags::AddMode; |
608 | 0 | } |
609 | 0 | else |
610 | 0 | bKeyUsed = false; |
611 | 0 | break; |
612 | | |
613 | 0 | case KEY_SPACE: |
614 | 0 | break; |
615 | 0 | case KEY_ADD: |
616 | 0 | case KEY_DIVIDE : |
617 | 0 | case KEY_A: |
618 | 0 | case KEY_SUBTRACT: |
619 | 0 | case KEY_COMMA : |
620 | 0 | case KEY_RETURN: |
621 | 0 | bKeyUsed = false; |
622 | 0 | break; |
623 | | |
624 | 0 | case KEY_END: |
625 | 0 | if( pCursor ) |
626 | 0 | { |
627 | 0 | pNewCursor = maEntries.back().get(); |
628 | 0 | SetCursor_Impl(pNewCursor); |
629 | 0 | } |
630 | 0 | break; |
631 | | |
632 | 0 | case KEY_HOME: |
633 | 0 | if( pCursor ) |
634 | 0 | { |
635 | 0 | pNewCursor = maEntries[ 0 ].get(); |
636 | 0 | SetCursor_Impl(pNewCursor); |
637 | 0 | } |
638 | 0 | break; |
639 | | |
640 | 0 | default: |
641 | 0 | bKeyUsed = false; |
642 | |
|
643 | 0 | } |
644 | 0 | return bKeyUsed; |
645 | 0 | } |
646 | | |
647 | | // recalculate TopLeft of scrollbars (but not their sizes!) |
648 | | void SvxIconChoiceCtrl_Impl::PositionScrollBars( tools::Long nRealWidth, tools::Long nRealHeight ) |
649 | 0 | { |
650 | | // horizontal scrollbar |
651 | 0 | Point aPos( 0, nRealHeight ); |
652 | 0 | aPos.AdjustY( -nHorSBarHeight ); |
653 | |
|
654 | 0 | if( aHorSBar->GetPosPixel() != aPos ) |
655 | 0 | aHorSBar->SetPosPixel( aPos ); |
656 | | |
657 | | // vertical scrollbar |
658 | 0 | aPos.setX( nRealWidth ); aPos.setY( 0 ); |
659 | 0 | aPos.AdjustX( -nVerSBarWidth ); |
660 | 0 | aPos.AdjustX( 1 ); |
661 | 0 | aPos.AdjustY( -1 ); |
662 | |
|
663 | 0 | if( aVerSBar->GetPosPixel() != aPos ) |
664 | 0 | aVerSBar->SetPosPixel( aPos ); |
665 | 0 | } |
666 | | |
667 | | void SvxIconChoiceCtrl_Impl::AdjustScrollBars() |
668 | 0 | { |
669 | 0 | tools::Long nVirtHeight = aVirtOutputSize.Height(); |
670 | 0 | tools::Long nVirtWidth = aVirtOutputSize.Width(); |
671 | |
|
672 | 0 | Size aOSize( pView->GetOutputSizePixel() ); |
673 | 0 | tools::Long nRealHeight = aOSize.Height(); |
674 | 0 | tools::Long nRealWidth = aOSize.Width(); |
675 | |
|
676 | 0 | PositionScrollBars( nRealWidth, nRealHeight ); |
677 | |
|
678 | 0 | const MapMode& rMapMode = pView->GetMapMode(); |
679 | 0 | Point aOrigin( rMapMode.GetOrigin() ); |
680 | |
|
681 | 0 | tools::Long nVisibleWidth; |
682 | 0 | if( nRealWidth > nVirtWidth ) |
683 | 0 | nVisibleWidth = nVirtWidth + aOrigin.X(); |
684 | 0 | else |
685 | 0 | nVisibleWidth = nRealWidth; |
686 | |
|
687 | 0 | tools::Long nVisibleHeight; |
688 | 0 | if( nRealHeight > nVirtHeight ) |
689 | 0 | nVisibleHeight = nVirtHeight + aOrigin.Y(); |
690 | 0 | else |
691 | 0 | nVisibleHeight = nRealHeight; |
692 | |
|
693 | 0 | bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0; |
694 | 0 | bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0; |
695 | 0 | bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0; |
696 | 0 | bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0; |
697 | |
|
698 | 0 | sal_uInt16 nResult = 0; |
699 | 0 | if( nVirtHeight ) |
700 | 0 | { |
701 | | // activate vertical scrollbar? |
702 | 0 | if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) ) |
703 | 0 | { |
704 | 0 | nResult = 0x0001; |
705 | 0 | nRealWidth -= nVerSBarWidth; |
706 | |
|
707 | 0 | if( nRealWidth > nVirtWidth ) |
708 | 0 | nVisibleWidth = nVirtWidth + aOrigin.X(); |
709 | 0 | else |
710 | 0 | nVisibleWidth = nRealWidth; |
711 | 0 | } |
712 | | // activate horizontal scrollbar? |
713 | 0 | if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) ) |
714 | 0 | { |
715 | 0 | nResult |= 0x0002; |
716 | 0 | nRealHeight -= nHorSBarHeight; |
717 | |
|
718 | 0 | if( nRealHeight > nVirtHeight ) |
719 | 0 | nVisibleHeight = nVirtHeight + aOrigin.Y(); |
720 | 0 | else |
721 | 0 | nVisibleHeight = nRealHeight; |
722 | | |
723 | | // do we need a vertical scrollbar after all? |
724 | 0 | if( !(nResult & 0x0001) && // only if not already there |
725 | 0 | ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) ) |
726 | 0 | { |
727 | 0 | nResult = 3; // both turned on |
728 | 0 | nRealWidth -= nVerSBarWidth; |
729 | |
|
730 | 0 | if( nRealWidth > nVirtWidth ) |
731 | 0 | nVisibleWidth = nVirtWidth + aOrigin.X(); |
732 | 0 | else |
733 | 0 | nVisibleWidth = nRealWidth; |
734 | 0 | } |
735 | 0 | } |
736 | 0 | } |
737 | | |
738 | | // size vertical scrollbar |
739 | 0 | tools::Long nThumb = aVerSBar->GetThumbPos(); |
740 | 0 | Size aSize( nVerSBarWidth, nRealHeight ); |
741 | 0 | aSize.AdjustHeight(2 ); |
742 | 0 | if( aSize != aVerSBar->GetSizePixel() ) |
743 | 0 | aVerSBar->SetSizePixel( aSize ); |
744 | 0 | aVerSBar->SetVisibleSize( nVisibleHeight ); |
745 | 0 | aVerSBar->SetPageSize( GetScrollBarPageSize( nVisibleHeight )); |
746 | |
|
747 | 0 | if( nResult & 0x0001 ) |
748 | 0 | { |
749 | 0 | aVerSBar->SetThumbPos( nThumb ); |
750 | 0 | aVerSBar->Show(); |
751 | 0 | } |
752 | 0 | else |
753 | 0 | { |
754 | 0 | aVerSBar->SetThumbPos( 0 ); |
755 | 0 | aVerSBar->Hide(); |
756 | 0 | } |
757 | | |
758 | | // size horizontal scrollbar |
759 | 0 | nThumb = aHorSBar->GetThumbPos(); |
760 | 0 | aSize.setWidth( nRealWidth ); |
761 | 0 | aSize.setHeight( nHorSBarHeight ); |
762 | 0 | aSize.AdjustWidth( 1 ); |
763 | 0 | if( nResult & 0x0001 ) // vertical scrollbar? |
764 | 0 | { |
765 | 0 | aSize.AdjustWidth( 1 ); |
766 | 0 | nRealWidth++; |
767 | 0 | } |
768 | 0 | if( aSize != aHorSBar->GetSizePixel() ) |
769 | 0 | aHorSBar->SetSizePixel( aSize ); |
770 | 0 | aHorSBar->SetVisibleSize( nVisibleWidth ); |
771 | 0 | aHorSBar->SetPageSize( GetScrollBarPageSize(nVisibleWidth )); |
772 | 0 | if( nResult & 0x0002 ) |
773 | 0 | { |
774 | 0 | aHorSBar->SetThumbPos( nThumb ); |
775 | 0 | aHorSBar->Show(); |
776 | 0 | } |
777 | 0 | else |
778 | 0 | { |
779 | 0 | aHorSBar->SetThumbPos( 0 ); |
780 | 0 | aHorSBar->Hide(); |
781 | 0 | } |
782 | |
|
783 | 0 | aOutputSize.setWidth( nRealWidth ); |
784 | 0 | if( nResult & 0x0002 ) // horizontal scrollbar ? |
785 | 0 | nRealHeight++; // because lower border is clipped |
786 | 0 | aOutputSize.setHeight( nRealHeight ); |
787 | |
|
788 | 0 | if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) ) |
789 | 0 | aScrBarBox->Show(); |
790 | 0 | else |
791 | 0 | aScrBarBox->Hide(); |
792 | 0 | } |
793 | | |
794 | | void SvxIconChoiceCtrl_Impl::Resize() |
795 | 0 | { |
796 | 0 | InitScrollBarBox(); |
797 | 0 | aOutputSize = pView->GetOutputSizePixel(); |
798 | 0 | pImpCursor->Clear(); |
799 | 0 | pGridMap->OutputSizeChanged(); |
800 | |
|
801 | 0 | const Size aSize = pView->GetOutputSizePixel(); |
802 | 0 | PositionScrollBars( aSize.Width(), aSize.Height() ); |
803 | | // The scrollbars are shown/hidden asynchronously, so derived classes can |
804 | | // do an Arrange during Resize, without the scrollbars suddenly turning |
805 | | // on and off again. |
806 | | // If an event is already underway, we don't need to send a new one, at least |
807 | | // as long as there is only one event type. |
808 | 0 | if ( ! nUserEventAdjustScrBars ) |
809 | 0 | nUserEventAdjustScrBars = |
810 | 0 | Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl), |
811 | 0 | EVENTID_ADJUST_SCROLLBARS); |
812 | |
|
813 | 0 | VisRectChanged(); |
814 | 0 | } |
815 | | |
816 | | bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar() |
817 | 0 | { |
818 | 0 | if( maZOrderList.empty() || !aHorSBar->IsVisible() ) |
819 | 0 | return false; |
820 | 0 | const MapMode& rMapMode = pView->GetMapMode(); |
821 | 0 | Point aOrigin( rMapMode.GetOrigin() ); |
822 | 0 | if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() ) |
823 | 0 | { |
824 | 0 | tools::Long nWidth = aOutputSize.Width(); |
825 | 0 | const size_t nCount = maZOrderList.size(); |
826 | 0 | tools::Long nMostRight = 0; |
827 | 0 | for( size_t nCur = 0; nCur < nCount; nCur++ ) |
828 | 0 | { |
829 | 0 | SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCur ]; |
830 | 0 | tools::Long nRight = GetEntryBoundRect(pEntry).Right(); |
831 | 0 | if( nRight > nWidth ) |
832 | 0 | return false; |
833 | 0 | if( nRight > nMostRight ) |
834 | 0 | nMostRight = nRight; |
835 | 0 | } |
836 | 0 | aHorSBar->Hide(); |
837 | 0 | aOutputSize.AdjustHeight(nHorSBarHeight ); |
838 | 0 | aVirtOutputSize.setWidth( nMostRight ); |
839 | 0 | aHorSBar->SetThumbPos( 0 ); |
840 | 0 | Range aRange; |
841 | 0 | aRange.Max() = nMostRight - 1; |
842 | 0 | aHorSBar->SetRange( aRange ); |
843 | 0 | if( aVerSBar->IsVisible() ) |
844 | 0 | { |
845 | 0 | Size aSize( aVerSBar->GetSizePixel()); |
846 | 0 | aSize.AdjustHeight(nHorSBarHeight ); |
847 | 0 | aVerSBar->SetSizePixel( aSize ); |
848 | 0 | } |
849 | 0 | return true; |
850 | 0 | } |
851 | 0 | return false; |
852 | 0 | } |
853 | | |
854 | | bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar() |
855 | 0 | { |
856 | 0 | if( maZOrderList.empty() || !aVerSBar->IsVisible() ) |
857 | 0 | return false; |
858 | 0 | const MapMode& rMapMode = pView->GetMapMode(); |
859 | 0 | Point aOrigin( rMapMode.GetOrigin() ); |
860 | 0 | if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() ) |
861 | 0 | { |
862 | 0 | tools::Long nDeepest = 0; |
863 | 0 | tools::Long nHeight = aOutputSize.Height(); |
864 | 0 | const size_t nCount = maZOrderList.size(); |
865 | 0 | for( size_t nCur = 0; nCur < nCount; nCur++ ) |
866 | 0 | { |
867 | 0 | SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCur ]; |
868 | 0 | tools::Long nBottom = GetEntryBoundRect(pEntry).Bottom(); |
869 | 0 | if( nBottom > nHeight ) |
870 | 0 | return false; |
871 | 0 | if( nBottom > nDeepest ) |
872 | 0 | nDeepest = nBottom; |
873 | 0 | } |
874 | 0 | aVerSBar->Hide(); |
875 | 0 | aOutputSize.AdjustWidth(nVerSBarWidth ); |
876 | 0 | aVirtOutputSize.setHeight( nDeepest ); |
877 | 0 | aVerSBar->SetThumbPos( 0 ); |
878 | 0 | Range aRange; |
879 | 0 | aRange.Max() = nDeepest - 1; |
880 | 0 | aVerSBar->SetRange( aRange ); |
881 | 0 | if( aHorSBar->IsVisible() ) |
882 | 0 | { |
883 | 0 | Size aSize( aHorSBar->GetSizePixel()); |
884 | 0 | aSize.AdjustWidth(nVerSBarWidth ); |
885 | 0 | aHorSBar->SetSizePixel( aSize ); |
886 | 0 | } |
887 | 0 | return true; |
888 | 0 | } |
889 | 0 | return false; |
890 | 0 | } |
891 | | |
892 | | |
893 | | // hides scrollbars if they're unnecessary |
894 | | void SvxIconChoiceCtrl_Impl::CheckScrollBars() |
895 | 0 | { |
896 | 0 | CheckVerScrollBar(); |
897 | 0 | if( CheckHorScrollBar() ) |
898 | 0 | CheckVerScrollBar(); |
899 | 0 | if( aVerSBar->IsVisible() && aHorSBar->IsVisible() ) |
900 | 0 | aScrBarBox->Show(); |
901 | 0 | else |
902 | 0 | aScrBarBox->Hide(); |
903 | 0 | } |
904 | | |
905 | | |
906 | | void SvxIconChoiceCtrl_Impl::GetFocus() |
907 | 0 | { |
908 | 0 | RepaintSelectedEntries(); |
909 | 0 | if( pCursor ) |
910 | 0 | { |
911 | 0 | pCursor->SetFlags( SvxIconViewFlags::FOCUSED ); |
912 | 0 | ShowCursor( true ); |
913 | 0 | } |
914 | 0 | } |
915 | | |
916 | | void SvxIconChoiceCtrl_Impl::LoseFocus() |
917 | 0 | { |
918 | 0 | if( pCursor ) |
919 | 0 | pCursor->ClearFlags( SvxIconViewFlags::FOCUSED ); |
920 | 0 | ShowCursor( false ); |
921 | | |
922 | | // HideFocus (); |
923 | | // pView->Invalidate ( aFocus.aRect ); |
924 | |
|
925 | 0 | RepaintSelectedEntries(); |
926 | 0 | } |
927 | | |
928 | | // priorities of the emphasis: bSelected |
929 | | void SvxIconChoiceCtrl_Impl::PaintEmphasis(const tools::Rectangle& rTextRect, |
930 | | vcl::RenderContext& rRenderContext) |
931 | 0 | { |
932 | 0 | const Color& rFillColor = rRenderContext.GetFont().GetFillColor(); |
933 | 0 | if (rFillColor == COL_TRANSPARENT) |
934 | 0 | return; |
935 | | |
936 | | // draw text rectangle |
937 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FILLCOLOR); |
938 | 0 | rRenderContext.SetFillColor(rFillColor); |
939 | 0 | rRenderContext.DrawRect(rTextRect); |
940 | 0 | } |
941 | | |
942 | | |
943 | | void SvxIconChoiceCtrl_Impl::PaintItem(const tools::Rectangle& rRect, |
944 | | IcnViewFieldType eItem, const SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags, |
945 | | vcl::RenderContext& rRenderContext ) |
946 | 0 | { |
947 | 0 | if (eItem == IcnViewFieldType::Text) |
948 | 0 | { |
949 | 0 | if (nWinBits & WB_DETAILS) |
950 | 0 | { |
951 | | // Vertically center text when the entry is text-only |
952 | 0 | tools::Long nBoundingHeight(CalcBoundingHeight()); |
953 | 0 | tools::Long nStringHeight = GetItemSize(IcnViewFieldType::Text).Height(); |
954 | 0 | tools::Long nNewY = (nBoundingHeight - nStringHeight) / 2; |
955 | 0 | Point aRectTL(rRect.TopLeft().getX(), rRect.TopLeft().getY() + nNewY); |
956 | 0 | tools::Rectangle aTextRect(aRectTL, rRect.GetSize()); |
957 | 0 | rRenderContext.DrawText(aTextRect, pEntry->GetText(), nCurTextDrawFlags); |
958 | 0 | } |
959 | 0 | else |
960 | 0 | { |
961 | 0 | rRenderContext.DrawText(rRect, pEntry->GetText(), nCurTextDrawFlags); |
962 | 0 | } |
963 | 0 | } |
964 | 0 | else |
965 | 0 | { |
966 | 0 | Point aPos(rRect.TopLeft()); |
967 | 0 | if (nPaintFlags & PAINTFLAG_HOR_CENTERED) |
968 | 0 | { |
969 | 0 | aPos.AdjustX((rRect.GetWidth() - aImageSize.Width()) / 2 ); |
970 | 0 | aPos.AdjustY( VER_DIST_BMP_STRING ); |
971 | 0 | } |
972 | 0 | if (nPaintFlags & PAINTFLAG_VER_CENTERED) |
973 | 0 | { |
974 | 0 | aPos.AdjustX( HOR_DIST_BMP_STRING ); |
975 | 0 | Size aSize = pEntry->GetImage().GetSizePixel(); |
976 | 0 | aPos.AdjustY((rRect.GetHeight() - aSize.Height()) / 2 ); |
977 | 0 | } |
978 | 0 | rRenderContext.DrawImage(aPos, pEntry->GetImage()); |
979 | |
|
980 | 0 | } |
981 | 0 | } |
982 | | |
983 | | void SvxIconChoiceCtrl_Impl::PaintEntry(SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, vcl::RenderContext& rRenderContext) |
984 | 0 | { |
985 | 0 | auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); |
986 | |
|
987 | 0 | tools::Rectangle aTextRect(CalcTextRect(pEntry, &rPos)); |
988 | 0 | tools::Rectangle aBmpRect(CalcBmpRect(pEntry, &rPos)); |
989 | |
|
990 | 0 | const bool bMouseHovered = pEntry == pCurHighlightFrame; |
991 | 0 | const bool bSelected = pEntry->IsSelected(); |
992 | |
|
993 | 0 | const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings(); |
994 | 0 | vcl::Font aNewFont(rRenderContext.GetFont()); |
995 | 0 | if (bSelected) |
996 | | #ifdef MACOSX |
997 | | // On macOS, selected tabs are drawn as default push buttons |
998 | | aNewFont.SetColor(rSettings.GetDefaultActionButtonPressedRolloverTextColor()); |
999 | | #else |
1000 | 0 | aNewFont.SetColor(rSettings.GetTabHighlightTextColor()); |
1001 | 0 | #endif |
1002 | 0 | else if (bMouseHovered) |
1003 | 0 | aNewFont.SetColor(rSettings.GetTabRolloverTextColor()); |
1004 | 0 | else |
1005 | 0 | aNewFont.SetColor(rSettings.GetTabTextColor()); |
1006 | 0 | rRenderContext.SetFont(aNewFont); |
1007 | |
|
1008 | 0 | bool bResetClipRegion = false; |
1009 | 0 | if (!rRenderContext.IsClipRegion() && (aVerSBar->IsVisible() || aHorSBar->IsVisible())) |
1010 | 0 | { |
1011 | 0 | tools::Rectangle aOutputArea(GetOutputRect()); |
1012 | 0 | if (aOutputArea.Overlaps(aTextRect) || aOutputArea.Overlaps(aBmpRect)) |
1013 | 0 | { |
1014 | 0 | rRenderContext.SetClipRegion(vcl::Region(aOutputArea)); |
1015 | 0 | bResetClipRegion = true; |
1016 | 0 | } |
1017 | 0 | } |
1018 | |
|
1019 | 0 | bool bLargeIconMode = WB_ICON == ( nWinBits & VIEWMODE_MASK ); |
1020 | 0 | sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED; |
1021 | 0 | if (bLargeIconMode) |
1022 | 0 | nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED; |
1023 | 0 | sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED; |
1024 | |
|
1025 | 0 | tools::Rectangle aFocusRect(CalcFocusRect(pEntry)); |
1026 | |
|
1027 | 0 | bool bNativeOK |
1028 | | #ifdef MACOSX |
1029 | | = rRenderContext.IsNativeControlSupported(ControlType::Pushbutton, ControlPart::Entire); |
1030 | | #else |
1031 | 0 | = rRenderContext.IsNativeControlSupported(ControlType::TabItem, ControlPart::Entire); |
1032 | 0 | #endif |
1033 | 0 | if (bNativeOK) |
1034 | 0 | { |
1035 | 0 | ControlState nState = ControlState::ENABLED; |
1036 | 0 | ControlPart nPart(ControlPart::Entire); |
1037 | |
|
1038 | | #ifdef MACOSX |
1039 | | if (bSelected) |
1040 | | { |
1041 | | // Related: tdf#163008 draw the selected tab using a push button |
1042 | | // On macOS, more closely match the vertical tab style of the |
1043 | | // sidebar in the System Settings application. As of macOS Sequoia, |
1044 | | // the sidebar only shows the default style push button for the |
1045 | | // selected tab. The unselected tabs are only text and images so |
1046 | | // no native control needs to be drawn for unselected tabs. |
1047 | | nState |= ControlState::DEFAULT; |
1048 | | |
1049 | | // Allow the native push button to expand its height to match |
1050 | | // the focus rectangle's height. |
1051 | | PushButtonValue aControlValue; |
1052 | | aControlValue.mbSingleLine = false; |
1053 | | aControlValue.m_bFlatButton = true; |
1054 | | |
1055 | | // Eliminate artifacts when this entry becomes unselected by |
1056 | | // making the push button slightly narrower than the focus |
1057 | | // rectangle so that there is no antialiased pixels drawn |
1058 | | // outside the focus rectangle. |
1059 | | tools::Rectangle aButtonRect(aFocusRect); |
1060 | | if (aButtonRect.GetWidth() > 2) |
1061 | | { |
1062 | | aButtonRect.SetLeft(aButtonRect.Left() + 1); |
1063 | | aButtonRect.SetRight(aButtonRect.Right() - 1); |
1064 | | } |
1065 | | |
1066 | | bNativeOK = rRenderContext.DrawNativeControl(ControlType::Pushbutton, nPart, |
1067 | | aButtonRect, nState, aControlValue, OUString()); |
1068 | | } |
1069 | | #else |
1070 | 0 | if (bSelected) |
1071 | 0 | nState |= ControlState::SELECTED; |
1072 | 0 | if (pEntry->IsFocused()) |
1073 | 0 | nState |= ControlState::FOCUSED; |
1074 | 0 | if (bMouseHovered) |
1075 | 0 | nState |= ControlState::ROLLOVER; |
1076 | |
|
1077 | 0 | TabitemValue tiValue(aFocusRect, TabBarPosition::Left); |
1078 | | #ifdef _WIN32 |
1079 | | // ControlPart::MenuItem prevents drawing line around tabs under win |
1080 | | nPart = ControlPart::MenuItem; |
1081 | | #endif |
1082 | 0 | bNativeOK = rRenderContext.DrawNativeControl(ControlType::TabItem, nPart, |
1083 | 0 | aFocusRect, nState, tiValue, OUString()); |
1084 | 0 | #endif |
1085 | 0 | } |
1086 | |
|
1087 | 0 | if (!bNativeOK) |
1088 | 0 | { |
1089 | 0 | if (bSelected) { |
1090 | 0 | rRenderContext.DrawSelectionBackground(aFocusRect, pView->GetBackgroundColor(), |
1091 | 0 | pView->HasFocus() ? 1 : 2, false); |
1092 | 0 | } else |
1093 | 0 | PaintEmphasis(aTextRect, rRenderContext); |
1094 | |
|
1095 | 0 | if (pEntry->IsFocused()) |
1096 | 0 | DrawFocusRect(rRenderContext, pEntry); |
1097 | | |
1098 | | // highlight mouse-hovered entry |
1099 | 0 | if (bMouseHovered) |
1100 | 0 | DrawHighlightFrame(rRenderContext, aFocusRect); |
1101 | 0 | } |
1102 | |
|
1103 | 0 | PaintItem(aBmpRect, IcnViewFieldType::Image, pEntry, nBmpPaintFlags, rRenderContext); |
1104 | | |
1105 | | // Move text a bit to the right for native controls due to potential tab mark (applies to text-only entries) |
1106 | 0 | if (bNativeOK && (nWinBits & WB_DETAILS)) |
1107 | 0 | aTextRect.SetPos(Point(aTextRect.GetPos().X() + TAB_MARK_WIDTH, aTextRect.GetPos().Y())); |
1108 | |
|
1109 | 0 | PaintItem(aTextRect, IcnViewFieldType::Text, pEntry, nTextPaintFlags, rRenderContext); |
1110 | |
|
1111 | 0 | if (bResetClipRegion) |
1112 | 0 | rRenderContext.SetClipRegion(); |
1113 | 0 | } |
1114 | | |
1115 | | SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos ) |
1116 | 0 | { |
1117 | 0 | CheckBoundingRects(); |
1118 | | // search through z-order list from the end |
1119 | 0 | size_t nCount = maZOrderList.size(); |
1120 | 0 | while( nCount ) |
1121 | 0 | { |
1122 | 0 | nCount--; |
1123 | 0 | SvxIconChoiceCtrlEntry* pEntry = maZOrderList[ nCount ]; |
1124 | 0 | tools::Rectangle aBoundingRect(GetEntryBoundRect(pEntry)); |
1125 | 0 | if( aBoundingRect.Contains( rDocPos ) ) |
1126 | 0 | return pEntry; |
1127 | 0 | } |
1128 | 0 | return nullptr; |
1129 | 0 | } |
1130 | | |
1131 | | void SvxIconChoiceCtrl_Impl::MakeEntryVisible(SvxIconChoiceCtrlEntry* pEntry) |
1132 | 0 | { |
1133 | 0 | const tools::Rectangle& rRect = GetEntryBoundRect( pEntry ); |
1134 | 0 | MakeVisible(rRect); |
1135 | 0 | } |
1136 | | |
1137 | | const tools::Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry ) |
1138 | 0 | { |
1139 | 0 | if( !IsBoundingRectValid( pEntry->aRect )) |
1140 | 0 | FindBoundingRect( pEntry ); |
1141 | 0 | return pEntry->aRect; |
1142 | 0 | } |
1143 | | |
1144 | | tools::Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos ) |
1145 | 0 | { |
1146 | 0 | tools::Rectangle aBound = GetEntryBoundRect( pEntry ); |
1147 | 0 | if( pPos ) |
1148 | 0 | aBound.SetPos( *pPos ); |
1149 | 0 | Point aPos( aBound.TopLeft() ); |
1150 | |
|
1151 | 0 | switch( nWinBits & VIEWMODE_MASK ) |
1152 | 0 | { |
1153 | 0 | case WB_ICON: |
1154 | 0 | { |
1155 | 0 | aPos.AdjustX(( aBound.GetWidth() - aImageSize.Width() ) / 2 ); |
1156 | 0 | return tools::Rectangle( aPos, aImageSize ); |
1157 | 0 | } |
1158 | | |
1159 | 0 | case WB_DETAILS: |
1160 | 0 | return tools::Rectangle(aPos, Size(0,0)); |
1161 | 0 | case WB_SMALLICON: |
1162 | 0 | aPos.AdjustY(( aBound.GetHeight() - aImageSize.Height() ) / 2 ); |
1163 | | //TODO: determine horizontal distance to bounding rectangle |
1164 | 0 | return tools::Rectangle( aPos, aImageSize ); |
1165 | | |
1166 | 0 | default: |
1167 | 0 | assert(false && "IconView: Viewmode not set"); |
1168 | 0 | return aBound; |
1169 | 0 | } |
1170 | 0 | } |
1171 | | |
1172 | | tools::Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry, |
1173 | | const Point* pEntryPos) |
1174 | 0 | { |
1175 | 0 | const tools::Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) ); |
1176 | 0 | tools::Rectangle aBound( GetEntryBoundRect( pEntry ) ); |
1177 | 0 | if( pEntryPos ) |
1178 | 0 | aBound.SetPos( *pEntryPos ); |
1179 | |
|
1180 | 0 | const OUString aEntryText = pEntry->GetText(); |
1181 | 0 | tools::Rectangle aTextRect = pView->GetTextRect( aMaxTextRect, aEntryText, nCurTextDrawFlags ); |
1182 | |
|
1183 | 0 | Size aTextSize( aTextRect.GetSize() ); |
1184 | |
|
1185 | 0 | Point aPos( aBound.TopLeft() ); |
1186 | 0 | tools::Long nBoundWidth = aBound.GetWidth(); |
1187 | 0 | tools::Long nBoundHeight = aBound.GetHeight(); |
1188 | |
|
1189 | 0 | switch( nWinBits & VIEWMODE_MASK ) |
1190 | 0 | { |
1191 | 0 | case WB_ICON: |
1192 | 0 | aPos.AdjustY(aImageSize.Height() ); |
1193 | 0 | aPos.AdjustY(VER_DIST_BMP_STRING ); |
1194 | 0 | aPos.AdjustX((nBoundWidth - aTextSize.Width()) / 2 ); |
1195 | 0 | break; |
1196 | | |
1197 | 0 | case WB_DETAILS: |
1198 | 0 | break; |
1199 | | |
1200 | 0 | case WB_SMALLICON: |
1201 | 0 | aPos.AdjustX(aImageSize.Width() ); |
1202 | 0 | aPos.AdjustX(HOR_DIST_BMP_STRING ); |
1203 | 0 | aPos.AdjustY((nBoundHeight - aTextSize.Height()) / 2 ); |
1204 | | // final calculation of width after initially done on insert |
1205 | 0 | long nNewWidth = aImageSize.Width() + aTextSize.Width() + 2*HOR_DIST_BMP_STRING; |
1206 | 0 | nNewWidth = pView->AdjustWidth(nNewWidth); |
1207 | 0 | pEntry->aRect.setWidth(nNewWidth); |
1208 | 0 | break; |
1209 | 0 | } |
1210 | 0 | return tools::Rectangle( aPos, aTextSize ); |
1211 | 0 | } |
1212 | | |
1213 | | |
1214 | | tools::Long SvxIconChoiceCtrl_Impl::CalcBoundingWidth() const |
1215 | 0 | { |
1216 | 0 | tools::Long nStringWidth = GetItemSize( IcnViewFieldType::Text ).Width(); |
1217 | 0 | tools::Long nWidth = 0; |
1218 | |
|
1219 | 0 | switch( nWinBits & VIEWMODE_MASK ) |
1220 | 0 | { |
1221 | 0 | case WB_ICON: |
1222 | 0 | nWidth = std::max( nStringWidth, aImageSize.Width() ); |
1223 | 0 | break; |
1224 | | |
1225 | 0 | case WB_DETAILS: |
1226 | 0 | nWidth = nStringWidth; |
1227 | 0 | break; |
1228 | | |
1229 | 0 | case WB_SMALLICON: |
1230 | 0 | nWidth = aImageSize.Width(); |
1231 | 0 | nWidth += HOR_DIST_BMP_STRING; |
1232 | 0 | nWidth += nStringWidth; |
1233 | 0 | break; |
1234 | 0 | } |
1235 | 0 | return nWidth; |
1236 | 0 | } |
1237 | | |
1238 | | tools::Long SvxIconChoiceCtrl_Impl::CalcBoundingHeight() const |
1239 | 0 | { |
1240 | 0 | tools::Long nStringHeight = GetItemSize(IcnViewFieldType::Text).Height(); |
1241 | 0 | tools::Long nHeight = 0; |
1242 | |
|
1243 | 0 | switch( nWinBits & VIEWMODE_MASK ) |
1244 | 0 | { |
1245 | 0 | case WB_ICON: |
1246 | 0 | nHeight = aImageSize.Height(); |
1247 | 0 | nHeight += VER_DIST_BMP_STRING; |
1248 | 0 | nHeight += nStringHeight; |
1249 | 0 | break; |
1250 | | |
1251 | 0 | case WB_DETAILS: |
1252 | 0 | nHeight = nStringHeight + 2 * VERT_TEXT_PADDING;; |
1253 | 0 | break; |
1254 | | |
1255 | 0 | case WB_SMALLICON: |
1256 | 0 | nHeight = std::max( aImageSize.Height(), nStringHeight ); |
1257 | 0 | break; |
1258 | 0 | } |
1259 | 0 | if( nHeight > nMaxBoundHeight ) |
1260 | 0 | { |
1261 | 0 | const_cast<SvxIconChoiceCtrl_Impl*>(this)->nMaxBoundHeight = nHeight; |
1262 | 0 | const_cast<SvxIconChoiceCtrl_Impl*>(this)->aHorSBar->SetLineSize( GetScrollBarLineSize() ); |
1263 | 0 | const_cast<SvxIconChoiceCtrl_Impl*>(this)->aVerSBar->SetLineSize( GetScrollBarLineSize() ); |
1264 | 0 | } |
1265 | 0 | return nHeight; |
1266 | 0 | } |
1267 | | |
1268 | | Size SvxIconChoiceCtrl_Impl::CalcBoundingSize() const |
1269 | 0 | { |
1270 | 0 | return Size( CalcBoundingWidth(), CalcBoundingHeight() ); |
1271 | 0 | } |
1272 | | |
1273 | | void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart() |
1274 | 0 | { |
1275 | 0 | nMaxBoundHeight = 0; |
1276 | 0 | maZOrderList.clear(); |
1277 | 0 | size_t nCur; |
1278 | 0 | SvxIconChoiceCtrlEntry* pEntry; |
1279 | 0 | const size_t nCount = maEntries.size(); |
1280 | |
|
1281 | 0 | for( nCur = 0; nCur < nCount; nCur++ ) |
1282 | 0 | { |
1283 | 0 | pEntry = maEntries[ nCur ].get(); |
1284 | 0 | if( IsBoundingRectValid( pEntry->aRect )) |
1285 | 0 | { |
1286 | 0 | Size aBoundSize( pEntry->aRect.GetSize() ); |
1287 | 0 | if( aBoundSize.Height() > nMaxBoundHeight ) |
1288 | 0 | nMaxBoundHeight = aBoundSize.Height(); |
1289 | 0 | } |
1290 | 0 | else |
1291 | 0 | FindBoundingRect( pEntry ); |
1292 | 0 | maZOrderList.push_back( pEntry ); |
1293 | 0 | } |
1294 | 0 | AdjustScrollBars(); |
1295 | 0 | } |
1296 | | |
1297 | | void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry ) |
1298 | 0 | { |
1299 | 0 | CalcBoundingSize(); |
1300 | 0 | Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid()).TopLeft()); |
1301 | |
|
1302 | 0 | tools::Rectangle aGridRect(aPos, Size(nGridDX, nGridDY)); |
1303 | 0 | pEntry->aRect = aGridRect; |
1304 | 0 | AdjustVirtSize( pEntry->aRect ); |
1305 | 0 | pGridMap->OccupyGrids( pEntry ); |
1306 | 0 | } |
1307 | | |
1308 | | |
1309 | | void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry ) |
1310 | 0 | { |
1311 | 0 | if( pEntry == pCursor ) |
1312 | 0 | { |
1313 | 0 | if (pCursor && !pCursor->IsSelected()) |
1314 | 0 | SelectEntry( pCursor, true ); |
1315 | 0 | return; |
1316 | 0 | } |
1317 | 0 | ShowCursor( false ); |
1318 | 0 | SvxIconChoiceCtrlEntry* pOldCursor = pCursor; |
1319 | 0 | pCursor = pEntry; |
1320 | 0 | if( pOldCursor ) |
1321 | 0 | { |
1322 | 0 | pOldCursor->ClearFlags( SvxIconViewFlags::FOCUSED ); |
1323 | 0 | SelectEntry(pOldCursor, false); // deselect old cursor |
1324 | 0 | } |
1325 | 0 | if( pCursor ) |
1326 | 0 | { |
1327 | 0 | ToTop( pCursor ); |
1328 | 0 | pCursor->SetFlags( SvxIconViewFlags::FOCUSED ); |
1329 | 0 | SelectEntry(pCursor, true); |
1330 | 0 | ShowCursor( true ); |
1331 | 0 | } |
1332 | 0 | } |
1333 | | |
1334 | | |
1335 | | void SvxIconChoiceCtrl_Impl::ShowCursor( bool bShow ) |
1336 | 0 | { |
1337 | 0 | if( !pCursor || !bShow || !pView->HasFocus() ) |
1338 | 0 | { |
1339 | 0 | pView->HideFocus(); |
1340 | 0 | return; |
1341 | 0 | } |
1342 | 0 | } |
1343 | | |
1344 | | bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd ) |
1345 | 0 | { |
1346 | 0 | tools::Rectangle aDocRect( Point(), aVirtOutputSize ); |
1347 | 0 | tools::Rectangle aVisRect( GetOutputRect() ); |
1348 | 0 | if( aVisRect.Contains( aDocRect )) |
1349 | 0 | return false; |
1350 | 0 | Size aDocSize( aDocRect.GetSize() ); |
1351 | 0 | Size aVisSize( aVisRect.GetSize() ); |
1352 | 0 | bool bHor = aDocSize.Width() > aVisSize.Width(); |
1353 | 0 | bool bVer = aDocSize.Height() > aVisSize.Height(); |
1354 | |
|
1355 | 0 | tools::Long nScrollDX = 0, nScrollDY = 0; |
1356 | |
|
1357 | 0 | switch( rCmd.GetCommand() ) |
1358 | 0 | { |
1359 | 0 | case CommandEventId::StartAutoScroll: |
1360 | 0 | { |
1361 | 0 | pView->EndTracking(); |
1362 | 0 | StartAutoScrollFlags nScrollFlags = StartAutoScrollFlags::NONE; |
1363 | 0 | if( bHor ) |
1364 | 0 | nScrollFlags |= StartAutoScrollFlags::Horz; |
1365 | 0 | if( bVer ) |
1366 | 0 | nScrollFlags |= StartAutoScrollFlags::Vert; |
1367 | 0 | if( nScrollFlags != StartAutoScrollFlags::NONE ) |
1368 | 0 | { |
1369 | 0 | pView->StartAutoScroll( nScrollFlags ); |
1370 | 0 | return true; |
1371 | 0 | } |
1372 | 0 | } |
1373 | 0 | break; |
1374 | | |
1375 | 0 | case CommandEventId::Wheel: |
1376 | 0 | { |
1377 | 0 | const CommandWheelData* pData = rCmd.GetWheelData(); |
1378 | 0 | if( pData && (CommandWheelMode::SCROLL == pData->GetMode()) && !pData->IsHorz() ) |
1379 | 0 | { |
1380 | 0 | double nScrollLines = pData->GetScrollLines(); |
1381 | 0 | if( nScrollLines == COMMAND_WHEEL_PAGESCROLL ) |
1382 | 0 | { |
1383 | 0 | nScrollDY = GetScrollBarPageSize( aVisSize.Width() ); |
1384 | 0 | if( pData->GetDelta() < 0 ) |
1385 | 0 | nScrollDY *= -1; |
1386 | 0 | } |
1387 | 0 | else |
1388 | 0 | { |
1389 | 0 | nScrollDY = pData->GetNotchDelta() * static_cast<tools::Long>(nScrollLines); |
1390 | 0 | nScrollDY *= GetScrollBarLineSize(); |
1391 | 0 | } |
1392 | 0 | } |
1393 | 0 | } |
1394 | 0 | break; |
1395 | | |
1396 | 0 | case CommandEventId::AutoScroll: |
1397 | 0 | { |
1398 | 0 | const CommandScrollData* pData = rCmd.GetAutoScrollData(); |
1399 | 0 | if( pData ) |
1400 | 0 | { |
1401 | 0 | nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize(); |
1402 | 0 | nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize(); |
1403 | 0 | } |
1404 | 0 | } |
1405 | 0 | break; |
1406 | | |
1407 | 0 | default: break; |
1408 | 0 | } |
1409 | | |
1410 | 0 | if( nScrollDX || nScrollDY ) |
1411 | 0 | { |
1412 | 0 | aVisRect.AdjustTop( -nScrollDY ); |
1413 | 0 | aVisRect.AdjustBottom( -nScrollDY ); |
1414 | 0 | aVisRect.AdjustLeft( -nScrollDX ); |
1415 | 0 | aVisRect.AdjustRight( -nScrollDX ); |
1416 | 0 | MakeVisible( aVisRect ); |
1417 | 0 | return true; |
1418 | 0 | } |
1419 | 0 | return false; |
1420 | 0 | } |
1421 | | |
1422 | | |
1423 | | void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt ) |
1424 | 0 | { |
1425 | | // scroll mouse event? |
1426 | 0 | if( (rCEvt.GetCommand() == CommandEventId::Wheel) || |
1427 | 0 | (rCEvt.GetCommand() == CommandEventId::StartAutoScroll) || |
1428 | 0 | (rCEvt.GetCommand() == CommandEventId::AutoScroll) ) |
1429 | 0 | { |
1430 | 0 | if( HandleScrollCommand( rCEvt ) ) |
1431 | 0 | return; |
1432 | 0 | } |
1433 | 0 | } |
1434 | | |
1435 | | void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry ) |
1436 | 0 | { |
1437 | 0 | if( maZOrderList.empty() || pEntry == maZOrderList.back()) |
1438 | 0 | return; |
1439 | | |
1440 | 0 | auto it = std::find(maZOrderList.begin(), maZOrderList.end(), pEntry); |
1441 | 0 | if (it != maZOrderList.end()) |
1442 | 0 | { |
1443 | 0 | maZOrderList.erase( it ); |
1444 | 0 | maZOrderList.push_back( pEntry ); |
1445 | 0 | } |
1446 | 0 | } |
1447 | | |
1448 | | void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( tools::Rectangle& rRect ) const |
1449 | 0 | { |
1450 | 0 | if( rRect.Bottom() >= aVirtOutputSize.Height() ) |
1451 | 0 | rRect.SetBottom( aVirtOutputSize.Height() - 1 ); |
1452 | 0 | if( rRect.Right() >= aVirtOutputSize.Width() ) |
1453 | 0 | rRect.SetRight( aVirtOutputSize.Width() - 1 ); |
1454 | 0 | if( rRect.Top() < 0 ) |
1455 | 0 | rRect.SetTop( 0 ); |
1456 | 0 | if( rRect.Left() < 0 ) |
1457 | 0 | rRect.SetLeft( 0 ); |
1458 | 0 | } |
1459 | | |
1460 | | // rRect: area of the document (in document coordinates) that we want to make |
1461 | | // visible |
1462 | | // bScrBar == true: rectangle was calculated because of a scrollbar event |
1463 | | |
1464 | | void SvxIconChoiceCtrl_Impl::MakeVisible( const tools::Rectangle& rRect, bool bScrBar ) |
1465 | 0 | { |
1466 | 0 | tools::Rectangle aVirtRect( rRect ); |
1467 | 0 | ClipAtVirtOutRect( aVirtRect ); |
1468 | 0 | Point aOrigin( pView->GetMapMode().GetOrigin() ); |
1469 | | // convert to document coordinate |
1470 | 0 | aOrigin *= -1; |
1471 | 0 | tools::Rectangle aOutputArea( GetOutputRect() ); |
1472 | 0 | if( aOutputArea.Contains( aVirtRect ) ) |
1473 | 0 | return; // is already visible |
1474 | | |
1475 | 0 | tools::Long nDy; |
1476 | 0 | if( aVirtRect.Top() < aOutputArea.Top() ) |
1477 | 0 | { |
1478 | | // scroll up (nDy < 0) |
1479 | 0 | nDy = aVirtRect.Top() - aOutputArea.Top(); |
1480 | 0 | } |
1481 | 0 | else if( aVirtRect.Bottom() > aOutputArea.Bottom() ) |
1482 | 0 | { |
1483 | | // scroll down (nDy > 0) |
1484 | 0 | nDy = aVirtRect.Bottom() - aOutputArea.Bottom(); |
1485 | 0 | } |
1486 | 0 | else |
1487 | 0 | nDy = 0; |
1488 | |
|
1489 | 0 | tools::Long nDx = 0; |
1490 | | |
1491 | | // no horizontal scrolling needed in list mode |
1492 | 0 | if (!(nWinBits & WB_DETAILS)) |
1493 | 0 | { |
1494 | 0 | if( aVirtRect.Left() < aOutputArea.Left() ) |
1495 | 0 | { |
1496 | | // scroll to the left (nDx < 0) |
1497 | 0 | nDx = aVirtRect.Left() - aOutputArea.Left(); |
1498 | 0 | } |
1499 | 0 | else if( aVirtRect.Right() > aOutputArea.Right() ) |
1500 | 0 | { |
1501 | | // scroll to the right (nDx > 0) |
1502 | 0 | nDx = aVirtRect.Right() - aOutputArea.Right(); |
1503 | 0 | } |
1504 | 0 | } |
1505 | |
|
1506 | 0 | aOrigin.AdjustX(nDx ); |
1507 | 0 | aOrigin.AdjustY(nDy ); |
1508 | 0 | aOutputArea.SetPos( aOrigin ); |
1509 | |
|
1510 | 0 | pView->PaintImmediately(); |
1511 | 0 | ShowCursor(false); |
1512 | | |
1513 | | // invert origin for SV (so we can scroll/paint using document coordinates) |
1514 | 0 | aOrigin *= -1; |
1515 | 0 | SetOrigin( aOrigin ); |
1516 | |
|
1517 | 0 | bool bScrollable = pView->GetBackground().IsScrollable(); |
1518 | |
|
1519 | 0 | if (bScrollable) |
1520 | 0 | { |
1521 | | // scroll in reverse direction! |
1522 | 0 | pView->Scroll( -nDx, -nDy, aOutputArea, |
1523 | 0 | ScrollFlags::NoChildren | ScrollFlags::UseClipRegion | ScrollFlags::Clip ); |
1524 | 0 | } |
1525 | 0 | else |
1526 | 0 | pView->Invalidate(InvalidateFlags::NoChildren); |
1527 | |
|
1528 | 0 | if( aHorSBar->IsVisible() || aVerSBar->IsVisible() ) |
1529 | 0 | { |
1530 | 0 | if( !bScrBar ) |
1531 | 0 | { |
1532 | 0 | aOrigin *= -1; |
1533 | | // correct thumbs |
1534 | 0 | if(aHorSBar->IsVisible() && aHorSBar->GetThumbPos() != aOrigin.X()) |
1535 | 0 | aHorSBar->SetThumbPos( aOrigin.X() ); |
1536 | 0 | if(aVerSBar->IsVisible() && aVerSBar->GetThumbPos() != aOrigin.Y()) |
1537 | 0 | aVerSBar->SetThumbPos( aOrigin.Y() ); |
1538 | 0 | } |
1539 | 0 | } |
1540 | |
|
1541 | 0 | ShowCursor(true); |
1542 | | |
1543 | | // check if we still need scrollbars |
1544 | 0 | CheckScrollBars(); |
1545 | 0 | if (bScrollable) |
1546 | 0 | pView->PaintImmediately(); |
1547 | | |
1548 | | // If the requested area can not be made completely visible, the |
1549 | | // Vis-Rect-Changed handler is called in any case. This case may occur e.g. |
1550 | | // if only few pixels of the lower border are invisible, but a scrollbar has |
1551 | | // a larger line size. |
1552 | 0 | VisRectChanged(); |
1553 | 0 | } |
1554 | | |
1555 | | void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry const * pThisEntryNot ) |
1556 | 0 | { |
1557 | | // TODO: work through z-order list, if necessary! |
1558 | |
|
1559 | 0 | size_t nCount = maEntries.size(); |
1560 | 0 | for( size_t nCur = 0; nCur < nCount; nCur++ ) |
1561 | 0 | { |
1562 | 0 | SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get(); |
1563 | 0 | if( pEntry != pThisEntryNot && pEntry->IsSelected() ) |
1564 | 0 | SelectEntry( pEntry, false, true ); |
1565 | 0 | } |
1566 | 0 | nFlags &= ~IconChoiceFlags::AddMode; |
1567 | 0 | } |
1568 | | |
1569 | | Size SvxIconChoiceCtrl_Impl::GetMinGrid() const |
1570 | 0 | { |
1571 | 0 | Size aTextSize( pView->GetTextWidth( u"XXX"_ustr ), pView->GetTextHeight() ); |
1572 | 0 | if (nWinBits & WB_DETAILS) |
1573 | 0 | return Size(aTextSize.Width(), aTextSize.Height()); |
1574 | | |
1575 | 0 | Size aMinSize( aImageSize ); |
1576 | 0 | aMinSize.AdjustWidth(2 * LROFFS_BOUND ); |
1577 | 0 | if( nWinBits & WB_ICON ) |
1578 | 0 | { |
1579 | 0 | aMinSize.AdjustHeight(VER_DIST_BMP_STRING ); |
1580 | 0 | aMinSize.AdjustHeight(aTextSize.Height() ); |
1581 | 0 | } |
1582 | 0 | else |
1583 | 0 | { |
1584 | 0 | aMinSize.AdjustWidth(HOR_DIST_BMP_STRING ); |
1585 | 0 | aMinSize.AdjustWidth(aTextSize.Width() ); |
1586 | 0 | } |
1587 | 0 | return aMinSize; |
1588 | 0 | } |
1589 | | |
1590 | | void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize ) |
1591 | 0 | { |
1592 | 0 | Size aSize( rSize ); |
1593 | 0 | Size aMinSize( GetMinGrid() ); |
1594 | 0 | if( aSize.Width() < aMinSize.Width() ) |
1595 | 0 | aSize.setWidth( aMinSize.Width() ); |
1596 | 0 | if( aSize.Height() < aMinSize.Height() ) |
1597 | 0 | aSize.setHeight( aMinSize.Height() ); |
1598 | |
|
1599 | 0 | nGridDX = aSize.Width(); |
1600 | 0 | nGridDY = aSize.Height(); |
1601 | 0 | SetDefaultTextSize(); |
1602 | 0 | } |
1603 | | |
1604 | | // Calculates the maximum size that the text rectangle may use within its |
1605 | | // bounding rectangle. |
1606 | | |
1607 | | tools::Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const |
1608 | 0 | { |
1609 | 0 | assert(IsBoundingRectValid(pEntry->aRect) && "Bounding rect for entry hasn't been calculated yet."); |
1610 | 0 | tools::Rectangle aBoundRect = pEntry->aRect; |
1611 | |
|
1612 | 0 | tools::Rectangle aBmpRect( const_cast<SvxIconChoiceCtrl_Impl*>(this)->CalcBmpRect( |
1613 | 0 | const_cast<SvxIconChoiceCtrlEntry*>(pEntry) ) ); |
1614 | 0 | if( nWinBits & WB_ICON ) |
1615 | 0 | { |
1616 | 0 | aBoundRect.SetTop( aBmpRect.Bottom() ); |
1617 | 0 | aBoundRect.AdjustTop(VER_DIST_BMP_STRING ); |
1618 | 0 | if( aBoundRect.Top() > aBoundRect.Bottom()) |
1619 | 0 | aBoundRect.SetTop( aBoundRect.Bottom() ); |
1620 | 0 | aBoundRect.AdjustLeft(LROFFS_BOUND ); |
1621 | 0 | aBoundRect.AdjustLeft( 1 ); |
1622 | 0 | aBoundRect.AdjustRight( -(LROFFS_BOUND) ); |
1623 | 0 | aBoundRect.AdjustRight( -1 ); |
1624 | 0 | if( aBoundRect.Left() > aBoundRect.Right()) |
1625 | 0 | aBoundRect.SetLeft( aBoundRect.Right() ); |
1626 | 0 | } |
1627 | 0 | else if (nWinBits & WB_SMALLICON) |
1628 | 0 | { |
1629 | 0 | aBoundRect.SetLeft( aBmpRect.Right() ); |
1630 | 0 | aBoundRect.AdjustLeft(HOR_DIST_BMP_STRING ); |
1631 | 0 | aBoundRect.AdjustRight( -(LROFFS_BOUND) ); |
1632 | 0 | if( aBoundRect.Left() > aBoundRect.Right() ) |
1633 | 0 | aBoundRect.SetLeft( aBoundRect.Right() ); |
1634 | 0 | tools::Long nHeight = aBoundRect.GetSize().Height(); |
1635 | 0 | nHeight = nHeight - aDefaultTextSize.Height(); |
1636 | 0 | nHeight /= 2; |
1637 | 0 | aBoundRect.AdjustTop(nHeight ); |
1638 | 0 | aBoundRect.AdjustBottom( -nHeight ); |
1639 | 0 | aBoundRect.setWidth(INT_MAX); // effective width calculated in CalcTextRect() |
1640 | 0 | } |
1641 | 0 | return aBoundRect; |
1642 | 0 | } |
1643 | | |
1644 | | void SvxIconChoiceCtrl_Impl::SetDefaultTextSize() |
1645 | 0 | { |
1646 | 0 | tools::Long nDY = nGridDY; |
1647 | 0 | nDY -= aImageSize.Height(); |
1648 | 0 | nDY -= VER_DIST_BMP_STRING; |
1649 | 0 | if (nDY <= 0) |
1650 | 0 | nDY = 2; |
1651 | |
|
1652 | 0 | tools::Long nDX = nGridDX; |
1653 | 0 | nDX -= 2 * LROFFS_BOUND; |
1654 | 0 | nDX -= 2; |
1655 | 0 | if (nDX <= 0) |
1656 | 0 | nDX = 2; |
1657 | |
|
1658 | 0 | tools::Long nHeight = pView->GetTextHeight(); |
1659 | 0 | if (nDY < nHeight) |
1660 | 0 | nDY = nHeight; |
1661 | 0 | if(pView->GetDPIScaleFactor() > 1) |
1662 | 0 | { |
1663 | 0 | nDY*=2; |
1664 | 0 | } |
1665 | 0 | aDefaultTextSize = Size(nDX, nDY); |
1666 | 0 | } |
1667 | | |
1668 | | // The deltas are the offsets by which the view is moved on the document. |
1669 | | // left, up: offsets < 0 |
1670 | | // right, down: offsets > 0 |
1671 | | void SvxIconChoiceCtrl_Impl::Scroll( tools::Long nDeltaX, tools::Long nDeltaY ) |
1672 | 0 | { |
1673 | 0 | const MapMode& rMapMode = pView->GetMapMode(); |
1674 | 0 | Point aOrigin( rMapMode.GetOrigin() ); |
1675 | | // convert to document coordinate |
1676 | 0 | aOrigin *= -1; |
1677 | 0 | aOrigin.AdjustY(nDeltaY ); |
1678 | 0 | aOrigin.AdjustX(nDeltaX ); |
1679 | 0 | tools::Rectangle aRect( aOrigin, aOutputSize ); |
1680 | 0 | MakeVisible( aRect, true/*bScrollBar*/ ); |
1681 | 0 | } |
1682 | | |
1683 | | |
1684 | | const Size& SvxIconChoiceCtrl_Impl::GetItemSize( IcnViewFieldType eItem ) const |
1685 | 0 | { |
1686 | 0 | if (eItem == IcnViewFieldType::Text) |
1687 | 0 | return aDefaultTextSize; |
1688 | 0 | return aImageSize; // IcnViewFieldType::Image |
1689 | 0 | } |
1690 | | |
1691 | | tools::Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry ) |
1692 | 0 | { |
1693 | 0 | tools::Rectangle aBoundRect( GetEntryBoundRect( pEntry ) ); |
1694 | | |
1695 | | // Remove left margin |
1696 | 0 | if (nWinBits & WB_DETAILS) |
1697 | 0 | aBoundRect.SetPos(Point(0, aBoundRect.GetPos().Y())); |
1698 | |
|
1699 | 0 | return aBoundRect; |
1700 | 0 | } |
1701 | | |
1702 | | IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, Timer *, void) |
1703 | 0 | { |
1704 | 0 | aVisRectChangedIdle.Stop(); |
1705 | 0 | } |
1706 | | |
1707 | | IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, Timer *, void) |
1708 | 0 | { |
1709 | 0 | aDocRectChangedIdle.Stop(); |
1710 | 0 | } |
1711 | | |
1712 | | void SvxIconChoiceCtrl_Impl::DrawFocusRect(vcl::RenderContext& rRenderContext, SvxIconChoiceCtrlEntry* pEntry) |
1713 | 0 | { |
1714 | 0 | const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings(); |
1715 | 0 | tools::Rectangle aRect(CalcFocusRect(pEntry)); |
1716 | 0 | rRenderContext.SetFillColor(rSettings.GetMenuHighlightColor()); |
1717 | 0 | rRenderContext.SetTextColor(rSettings.GetMenuHighlightTextColor()); |
1718 | 0 | rRenderContext.DrawRect(aRect); |
1719 | 0 | } |
1720 | | |
1721 | | bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const |
1722 | 0 | { |
1723 | 0 | bool bRet = false; |
1724 | 0 | const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); |
1725 | 0 | size_t nEntryCount = GetEntryCount(); |
1726 | 0 | for ( size_t i = 0; i < nEntryCount; ++i ) |
1727 | 0 | { |
1728 | 0 | if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) ) |
1729 | 0 | { |
1730 | 0 | bRet = true; |
1731 | 0 | rPos = i; |
1732 | 0 | break; |
1733 | 0 | } |
1734 | 0 | } |
1735 | |
|
1736 | 0 | return bRet; |
1737 | 0 | } |
1738 | | |
1739 | | |
1740 | | IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId, void ) |
1741 | 0 | { |
1742 | 0 | if( nId == EVENTID_ADJUST_SCROLLBARS ) |
1743 | 0 | { |
1744 | 0 | nUserEventAdjustScrBars = nullptr; |
1745 | 0 | AdjustScrollBars(); |
1746 | 0 | } |
1747 | 0 | } |
1748 | | |
1749 | | void SvxIconChoiceCtrl_Impl::CancelUserEvents() |
1750 | 0 | { |
1751 | 0 | if( nUserEventAdjustScrBars ) |
1752 | 0 | { |
1753 | 0 | Application::RemoveUserEvent( nUserEventAdjustScrBars ); |
1754 | 0 | nUserEventAdjustScrBars = nullptr; |
1755 | 0 | } |
1756 | 0 | } |
1757 | | |
1758 | | SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry() const |
1759 | 0 | { |
1760 | 0 | size_t nCount = maEntries.size(); |
1761 | 0 | for( size_t nCur = 0; nCur < nCount; nCur++ ) |
1762 | 0 | { |
1763 | 0 | SvxIconChoiceCtrlEntry* pEntry = maEntries[ nCur ].get(); |
1764 | 0 | if( pEntry->IsSelected() ) |
1765 | 0 | { |
1766 | 0 | return pEntry; |
1767 | 0 | } |
1768 | 0 | } |
1769 | 0 | return nullptr; |
1770 | 0 | } |
1771 | | |
1772 | | sal_Int32 SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry const * pEntry ) const |
1773 | 0 | { |
1774 | 0 | auto it = std::find_if(maEntries.begin(), maEntries.end(), |
1775 | 0 | [pEntry](auto& rIt) { return rIt.get() == pEntry; }); |
1776 | 0 | if (it != maEntries.end()) |
1777 | 0 | return std::distance(maEntries.begin(), it); |
1778 | | |
1779 | 0 | return -1; |
1780 | 0 | } |
1781 | | |
1782 | | void SvxIconChoiceCtrl_Impl::InitSettings() |
1783 | 0 | { |
1784 | 0 | const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings(); |
1785 | | |
1786 | | // unit (from settings) is Point |
1787 | 0 | vcl::Font aFont( rStyleSettings.GetFieldFont() ); |
1788 | 0 | aFont.SetColor( rStyleSettings.GetWindowTextColor() ); |
1789 | 0 | pView->SetPointFont( aFont ); |
1790 | 0 | SetDefaultTextSize(); |
1791 | |
|
1792 | 0 | pView->SetTextColor( rStyleSettings.GetFieldTextColor() ); |
1793 | 0 | pView->SetTextFillColor(); |
1794 | |
|
1795 | 0 | pView->SetBackground( rStyleSettings.GetFieldColor()); |
1796 | |
|
1797 | 0 | tools::Long nScrBarSize = rStyleSettings.GetScrollBarSize(); |
1798 | 0 | if( nScrBarSize == nHorSBarHeight && nScrBarSize == nVerSBarWidth ) |
1799 | 0 | return; |
1800 | | |
1801 | 0 | nHorSBarHeight = nScrBarSize; |
1802 | 0 | Size aSize( aHorSBar->GetSizePixel() ); |
1803 | 0 | aSize.setHeight( nScrBarSize ); |
1804 | 0 | aHorSBar->Hide(); |
1805 | 0 | aHorSBar->SetSizePixel( aSize ); |
1806 | |
|
1807 | 0 | nVerSBarWidth = nScrBarSize; |
1808 | 0 | aSize = aVerSBar->GetSizePixel(); |
1809 | 0 | aSize.setWidth( nScrBarSize ); |
1810 | 0 | aVerSBar->Hide(); |
1811 | 0 | aVerSBar->SetSizePixel( aSize ); |
1812 | |
|
1813 | 0 | Size aOSize(pView->GetOutputSizePixel()); |
1814 | 0 | PositionScrollBars( aOSize.Width(), aOSize.Height() ); |
1815 | 0 | AdjustScrollBars(); |
1816 | 0 | } |
1817 | | |
1818 | | bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt ) |
1819 | 0 | { |
1820 | 0 | if ( !(rHEvt.GetMode() & HelpEventMode::QUICK ) ) |
1821 | 0 | return false; |
1822 | | |
1823 | 0 | Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) ); |
1824 | 0 | aPos -= pView->GetMapMode().GetOrigin(); |
1825 | 0 | SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos ); |
1826 | |
|
1827 | 0 | if ( !pEntry ) |
1828 | 0 | return false; |
1829 | | |
1830 | 0 | OUString sQuickHelpText = pEntry->GetQuickHelpText(); |
1831 | 0 | tools::Rectangle aTextRect(CalcTextRect(pEntry, nullptr)); |
1832 | 0 | const OUString aEntryText = pEntry->GetText(); |
1833 | 0 | if ( ( !aTextRect.Contains( aPos ) || aEntryText.isEmpty() ) && sQuickHelpText.isEmpty() ) |
1834 | 0 | return false; |
1835 | | |
1836 | 0 | tools::Rectangle aOptTextRect( aTextRect ); |
1837 | 0 | aOptTextRect.SetBottom( LONG_MAX ); |
1838 | 0 | DrawTextFlags nNewFlags = nCurTextDrawFlags; |
1839 | 0 | nNewFlags &= ~DrawTextFlags( DrawTextFlags::Clip | DrawTextFlags::EndEllipsis ); |
1840 | 0 | aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags ); |
1841 | 0 | if ( aOptTextRect != aTextRect || !sQuickHelpText.isEmpty() ) |
1842 | 0 | { |
1843 | | //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4; |
1844 | 0 | Point aPt( aOptTextRect.TopLeft() ); |
1845 | 0 | aPt += pView->GetMapMode().GetOrigin(); |
1846 | 0 | aPt = pView->OutputToScreenPixel( aPt ); |
1847 | | // subtract border of tooltip help |
1848 | 0 | aPt.AdjustY( -1 ); |
1849 | 0 | aPt.AdjustX( -3 ); |
1850 | 0 | aOptTextRect.SetPos( aPt ); |
1851 | 0 | OUString sHelpText; |
1852 | 0 | if ( !sQuickHelpText.isEmpty() ) |
1853 | 0 | sHelpText = sQuickHelpText; |
1854 | 0 | else |
1855 | 0 | sHelpText = aEntryText; |
1856 | 0 | Help::ShowQuickHelp(pView, aOptTextRect, sHelpText, QuickHelpFlags::Left | QuickHelpFlags::VCenter); |
1857 | 0 | } |
1858 | |
|
1859 | 0 | return true; |
1860 | 0 | } |
1861 | | |
1862 | | void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(vcl::RenderContext& rRenderContext, |
1863 | | const tools::Rectangle& rRect) |
1864 | 0 | { |
1865 | 0 | const StyleSettings& rStyles = rRenderContext.GetSettings().GetStyleSettings(); |
1866 | 0 | Color aCol(rStyles.GetHighlightColor()); |
1867 | 0 | aCol.Merge(rStyles.GetFieldColor(), 50); |
1868 | 0 | rRenderContext.SetFillColor(aCol); |
1869 | 0 | rRenderContext.DrawRect(rRect); |
1870 | |
|
1871 | 0 | DecorationView aDecoView(&rRenderContext); |
1872 | 0 | aDecoView.DrawHighlightFrame(rRect); |
1873 | 0 | } |
1874 | | |
1875 | | void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame(SvxIconChoiceCtrlEntry* pEntry) |
1876 | 0 | { |
1877 | 0 | if( pEntry == pCurHighlightFrame ) |
1878 | 0 | return; |
1879 | | |
1880 | 0 | if (pCurHighlightFrame) |
1881 | 0 | { |
1882 | 0 | tools::Rectangle aInvalidationRect(GetEntryBoundRect(pCurHighlightFrame)); |
1883 | 0 | aInvalidationRect.expand(5); |
1884 | 0 | pCurHighlightFrame = nullptr; |
1885 | 0 | pView->Invalidate(aInvalidationRect); |
1886 | 0 | } |
1887 | |
|
1888 | 0 | pCurHighlightFrame = pEntry; |
1889 | 0 | if (pEntry) |
1890 | 0 | { |
1891 | 0 | tools::Rectangle aInvalidationRect(GetEntryBoundRect(pEntry)); |
1892 | 0 | aInvalidationRect.expand(5); |
1893 | 0 | pView->Invalidate(aInvalidationRect); |
1894 | 0 | } |
1895 | 0 | } |
1896 | | |
1897 | | void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos ) |
1898 | 0 | { |
1899 | 0 | MapMode aMapMode( pView->GetMapMode() ); |
1900 | 0 | aMapMode.SetOrigin( rPos ); |
1901 | 0 | pView->SetMapMode( aMapMode ); |
1902 | 0 | } |
1903 | | |
1904 | | void SvxIconChoiceCtrl_Impl::CallEventListeners( VclEventId nEvent, void* pData ) |
1905 | 0 | { |
1906 | 0 | pView->CallImplEventListeners( nEvent, pData ); |
1907 | 0 | } |
1908 | | |
1909 | | |
1910 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |