Line data Source code
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 <tools/debug.hxx>
23 : #include <vcl/wall.hxx>
24 : #include <vcl/help.hxx>
25 : #include <vcl/decoview.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <tools/poly.hxx>
28 : #include <vcl/lineinfo.hxx>
29 : #include <vcl/i18nhelp.hxx>
30 : #include <vcl/mnemonic.hxx>
31 : #include <vcl/controllayout.hxx>
32 : #include <vcl/settings.hxx>
33 :
34 : #include <svtools/ivctrl.hxx>
35 : #include "imivctl.hxx"
36 : #include <svtools/svmedit.hxx>
37 :
38 : #include <algorithm>
39 : #include <boost/scoped_ptr.hpp>
40 : #include <vcl/idle.hxx>
41 :
42 : #define IMPICNVIEW_ACC_RETURN 1
43 : #define IMPICNVIEW_ACC_ESCAPE 2
44 :
45 : #define DRAWTEXT_FLAGS_ICON \
46 : ( DrawTextFlags::Center | DrawTextFlags::Top | DrawTextFlags::EndEllipsis | \
47 : DrawTextFlags::Clip | DrawTextFlags::MultiLine | DrawTextFlags::WordBreak | DrawTextFlags::Mnemonic )
48 :
49 : #define DRAWTEXT_FLAGS_SMALLICON (DrawTextFlags::Left|DrawTextFlags::EndEllipsis|DrawTextFlags::Clip)
50 :
51 : #define EVENTID_SHOW_CURSOR (reinterpret_cast<void*>(1))
52 : #define EVENTID_ADJUST_SCROLLBARS (reinterpret_cast<void*>(2))
53 :
54 : static bool bEndScrollInvalidate = true;
55 :
56 : class IcnViewEdit_Impl : public MultiLineEdit
57 : {
58 : Link<> aCallBackHdl;
59 : Accelerator aAccReturn;
60 : Accelerator aAccEscape;
61 : Idle aIdle;
62 : bool bCanceled;
63 : bool bAlreadyInCallback;
64 : bool bGrabFocus;
65 :
66 : void CallCallBackHdl_Impl();
67 : DECL_LINK_TYPED(Timeout_Impl, Idle *, void);
68 : DECL_LINK( ReturnHdl_Impl, Accelerator * );
69 : DECL_LINK( EscapeHdl_Impl, Accelerator * );
70 :
71 : public:
72 :
73 : IcnViewEdit_Impl(
74 : SvtIconChoiceCtrl* pParent,
75 : const Point& rPos,
76 : const Size& rSize,
77 : const OUString& rData,
78 : const Link<>& rNotifyEditEnd );
79 :
80 : virtual ~IcnViewEdit_Impl();
81 : virtual void dispose() SAL_OVERRIDE;
82 : virtual void KeyInput( const KeyEvent& rKEvt ) SAL_OVERRIDE;
83 : virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
84 0 : bool EditingCanceled() const { return bCanceled; }
85 : void StopEditing( bool bCancel = false );
86 0 : bool IsGrabFocus() const { return bGrabFocus; }
87 : };
88 :
89 7 : SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
90 : SvtIconChoiceCtrl* pCurView,
91 : WinBits nWinStyle
92 : ) :
93 : aEntries( this ),
94 : aVerSBar( VclPtr<ScrollBar>::Create(pCurView, WB_DRAG | WB_VSCROLL) ),
95 : aHorSBar( VclPtr<ScrollBar>::Create(pCurView, WB_DRAG | WB_HSCROLL) ),
96 : aScrBarBox( VclPtr<ScrollBarBox>::Create(pCurView) ),
97 : aImageSize( 32, 32 ),
98 7 : pColumns( 0 )
99 : {
100 7 : bChooseWithCursor = false;
101 7 : pEntryPaintDev = 0;
102 7 : pCurEditedEntry = 0;
103 7 : pCurHighlightFrame = 0;
104 7 : pEdit = 0;
105 7 : pAnchor = 0;
106 7 : pPrevDropTarget = 0;
107 7 : pHdlEntry = 0;
108 7 : pHead = NULL;
109 7 : pCursor = NULL;
110 7 : bUpdateMode = true;
111 7 : bEntryEditingEnabled = false;
112 7 : bHighlightFramePressed = false;
113 7 : eSelectionMode = MULTIPLE_SELECTION;
114 7 : pView = pCurView;
115 7 : pZOrderList = new SvxIconChoiceCtrlEntryList_impl();
116 7 : ePositionMode = IcnViewPositionModeFree;
117 7 : SetStyle( nWinStyle );
118 7 : nFlags = 0;
119 7 : nUserEventAdjustScrBars = 0;
120 7 : nUserEventShowCursor = 0;
121 7 : nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
122 7 : nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
123 7 : pDDRefEntry = 0;
124 7 : pDDDev = 0;
125 7 : pDDBufDev = 0;
126 7 : pDDTempDev = 0;
127 7 : eTextMode = IcnShowTextShort;
128 7 : pImpCursor = new IcnCursor_Impl( this );
129 7 : pGridMap = new IcnGridMap_Impl( this );
130 :
131 7 : aVerSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
132 7 : aHorSBar->SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
133 :
134 7 : nHorSBarHeight = aHorSBar->GetSizePixel().Height();
135 7 : nVerSBarWidth = aVerSBar->GetSizePixel().Width();
136 :
137 7 : aEditIdle.SetPriority( SchedulerPriority::LOWEST );
138 7 : aEditIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
139 7 : aAutoArrangeIdle.SetPriority( SchedulerPriority::LOW );
140 7 : aAutoArrangeIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
141 7 : aCallSelectHdlIdle.SetPriority( SchedulerPriority::LOWEST );
142 7 : aCallSelectHdlIdle.SetIdleHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
143 :
144 7 : aDocRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
145 7 : aDocRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
146 7 : aVisRectChangedIdle.SetPriority( SchedulerPriority::MEDIUM );
147 7 : aVisRectChangedIdle.SetIdleHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
148 :
149 7 : Clear( true );
150 :
151 7 : SetGrid( Size(100, 70) );
152 7 : }
153 :
154 10 : SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
155 : {
156 5 : pCurEditedEntry = 0;
157 5 : pEdit.disposeAndClear();
158 5 : Clear();
159 5 : StopEditTimer();
160 5 : CancelUserEvents();
161 5 : delete pZOrderList;
162 5 : delete pImpCursor;
163 5 : delete pGridMap;
164 5 : pDDDev.disposeAndClear();
165 5 : pDDBufDev.disposeAndClear();
166 5 : pDDTempDev.disposeAndClear();
167 5 : pEntryPaintDev.disposeAndClear();
168 5 : ClearSelectedRectList();
169 5 : ClearColumnList();
170 5 : aVerSBar.disposeAndClear();
171 5 : aHorSBar.disposeAndClear();
172 5 : aScrBarBox.disposeAndClear();
173 5 : }
174 :
175 12 : void SvxIconChoiceCtrl_Impl::Clear( bool bInCtor )
176 : {
177 12 : StopEntryEditing( true );
178 12 : nSelectionCount = 0;
179 12 : pCurHighlightFrame = 0;
180 12 : StopEditTimer();
181 12 : CancelUserEvents();
182 12 : ShowCursor( false );
183 12 : bBoundRectsDirty = false;
184 12 : nMaxBoundHeight = 0;
185 :
186 12 : nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
187 12 : pCursor = 0;
188 12 : if( !bInCtor )
189 : {
190 5 : pImpCursor->Clear();
191 5 : pGridMap->Clear();
192 5 : aVirtOutputSize.Width() = 0;
193 5 : aVirtOutputSize.Height() = 0;
194 5 : Size aSize( pView->GetOutputSizePixel() );
195 5 : nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
196 5 : if( nMaxVirtWidth <= 0 )
197 0 : nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
198 5 : nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
199 5 : if( nMaxVirtHeight <= 0 )
200 1 : nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
201 5 : pZOrderList->clear();
202 5 : SetOrigin( Point() );
203 5 : if( bUpdateMode )
204 5 : pView->Invalidate(InvalidateFlags::NoChildren);
205 : }
206 12 : AdjustScrollBars();
207 12 : size_t nCount = aEntries.size();
208 32 : for( size_t nCur = 0; nCur < nCount; nCur++ )
209 : {
210 20 : SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
211 20 : delete pCur;
212 : }
213 12 : aEntries.clear();
214 12 : DocRectChanged();
215 12 : VisRectChanged();
216 12 : }
217 :
218 7 : void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
219 : {
220 7 : nWinBits = nWinStyle;
221 7 : nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
222 7 : if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
223 0 : nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
224 7 : if( nWinBits & WB_NOSELECTION )
225 0 : eSelectionMode = NO_SELECTION;
226 7 : if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
227 7 : nWinBits |= WB_ALIGN_LEFT;
228 7 : if( (nWinStyle & WB_DETAILS))
229 : {
230 0 : if( !pColumns )
231 0 : SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
232 : }
233 7 : }
234 :
235 0 : IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
236 : {
237 0 : StopEntryEditing( true );
238 : // arrow up: delta=-1; arrow down: delta=+1
239 0 : Scroll( 0, pScrollBar->GetDelta(), true );
240 0 : bEndScrollInvalidate = true;
241 0 : return 0;
242 : }
243 :
244 0 : IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
245 : {
246 0 : StopEntryEditing( true );
247 : // arrow left: delta=-1; arrow right: delta=+1
248 0 : Scroll( pScrollBar->GetDelta(), 0, true );
249 0 : bEndScrollInvalidate = true;
250 0 : return 0;
251 : }
252 :
253 7 : void SvxIconChoiceCtrl_Impl::FontModified()
254 : {
255 7 : StopEditTimer();
256 7 : pDDDev.disposeAndClear();
257 7 : pDDBufDev.disposeAndClear();
258 7 : pDDTempDev.disposeAndClear();
259 7 : pEntryPaintDev.disposeAndClear();
260 7 : SetDefaultTextSize();
261 7 : ShowCursor( false );
262 7 : ShowCursor( true );
263 7 : }
264 :
265 28 : void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, size_t nPos,
266 : const Point* pPos )
267 : {
268 28 : StopEditTimer();
269 28 : aEntries.insert( nPos, pEntry );
270 28 : if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.size() - 1 )
271 0 : pEntry->nPos = aEntries.size() - 1;
272 : else
273 28 : nFlags &= ~F_ENTRYLISTPOS_VALID;
274 :
275 28 : pZOrderList->push_back( pEntry );
276 28 : pImpCursor->Clear();
277 28 : if( pPos )
278 : {
279 0 : Size aSize( CalcBoundingSize( pEntry ) );
280 0 : SetBoundingRect_Impl( pEntry, *pPos, aSize );
281 0 : SetEntryPos( pEntry, *pPos, false, true, true /*keep grid map*/ );
282 0 : pEntry->nFlags |= SvxIconViewFlags::POS_MOVED;
283 0 : SetEntriesMoved( true );
284 : }
285 : else
286 : {
287 : // If the UpdateMode is true, don't set all bounding rectangles to
288 : // 'to be checked', but only the bounding rectangle of the new entry.
289 : // Thus, don't call InvalidateBoundingRect!
290 28 : pEntry->aRect.Right() = LONG_MAX;
291 28 : if( bUpdateMode )
292 : {
293 28 : FindBoundingRect( pEntry );
294 28 : Rectangle aOutputArea( GetOutputRect() );
295 28 : pGridMap->OccupyGrids( pEntry );
296 28 : if( !aOutputArea.IsOver( pEntry->aRect ) )
297 56 : return; // is invisible
298 0 : pView->Invalidate( pEntry->aRect );
299 : }
300 : else
301 0 : InvalidateBoundingRect( pEntry->aRect );
302 : }
303 : }
304 :
305 7 : void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
306 : {
307 7 : boost::scoped_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
308 7 : if ( !_pGenerator )
309 : {
310 0 : _pGenerator = new MnemonicGenerator;
311 0 : pAutoDeleteOwnGenerator.reset( _pGenerator );
312 : }
313 :
314 7 : sal_uLong nEntryCount = GetEntryCount();
315 : sal_uLong i;
316 :
317 : // insert texts in generator
318 35 : for( i = 0; i < nEntryCount; ++i )
319 : {
320 : DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
321 :
322 28 : _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
323 : }
324 :
325 : // exchange texts with generated mnemonics
326 35 : for( i = 0; i < nEntryCount; ++i )
327 : {
328 28 : SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
329 28 : OUString aTxt = pEntry->GetText();
330 :
331 56 : OUString aNewText = _pGenerator->CreateMnemonic( aTxt );
332 28 : if( aNewText != aTxt )
333 28 : pEntry->SetText( aNewText );
334 35 : }
335 7 : }
336 :
337 104 : Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
338 : {
339 104 : Point aOrigin( pView->GetMapMode().GetOrigin() );
340 104 : aOrigin *= -1;
341 104 : return Rectangle( aOrigin, aOutputSize );
342 : }
343 :
344 0 : void SvxIconChoiceCtrl_Impl::SetListPositions()
345 : {
346 0 : if( nFlags & F_ENTRYLISTPOS_VALID )
347 0 : return;
348 :
349 0 : size_t nCount = aEntries.size();
350 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
351 : {
352 0 : SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
353 0 : pEntry->nPos = nCur;
354 : }
355 0 : nFlags |= F_ENTRYLISTPOS_VALID;
356 : }
357 :
358 6 : void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, bool bSelect,
359 : bool bCallHdl, bool bAdd, bool bSyncPaint )
360 : {
361 6 : if( eSelectionMode == NO_SELECTION )
362 6 : return;
363 :
364 6 : if( !bAdd )
365 : {
366 6 : if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
367 : {
368 6 : nFlags |= F_CLEARING_SELECTION;
369 6 : DeselectAllBut( pEntry, true );
370 6 : nFlags &= ~F_CLEARING_SELECTION;
371 : }
372 : }
373 6 : if( pEntry->IsSelected() != bSelect )
374 : {
375 3 : pHdlEntry = pEntry;
376 3 : SvxIconViewFlags nEntryFlags = pEntry->GetFlags();
377 3 : if( bSelect )
378 : {
379 3 : nEntryFlags |= SvxIconViewFlags::SELECTED;
380 3 : pEntry->AssignFlags( nEntryFlags );
381 3 : nSelectionCount++;
382 3 : if( bCallHdl )
383 3 : CallSelectHandler( pEntry );
384 : }
385 : else
386 : {
387 0 : nEntryFlags &= ~( SvxIconViewFlags::SELECTED);
388 0 : pEntry->AssignFlags( nEntryFlags );
389 0 : nSelectionCount--;
390 0 : if( bCallHdl )
391 0 : CallSelectHandler( 0 );
392 : }
393 3 : EntrySelected( pEntry, bSelect, bSyncPaint );
394 : }
395 : }
396 :
397 3 : void SvxIconChoiceCtrl_Impl::EntrySelected(SvxIconChoiceCtrlEntry* pEntry, bool bSelect, bool /*bSyncPaint*/)
398 : {
399 : // When using SingleSelection, make sure that the cursor is always placed
400 : // over the (only) selected entry. (But only if a cursor exists.)
401 6 : if (bSelect && pCursor &&
402 6 : eSelectionMode == SINGLE_SELECTION &&
403 3 : pEntry != pCursor)
404 : {
405 0 : SetCursor(pEntry);
406 : }
407 :
408 : // Not when dragging though, else the loop in SelectRect doesn't work
409 : // correctly!
410 3 : if (!(nFlags & F_SELECTING_RECT))
411 3 : ToTop(pEntry);
412 3 : if (bUpdateMode)
413 : {
414 3 : if (pEntry == pCursor)
415 3 : ShowCursor(false);
416 3 : pView->Invalidate(CalcFocusRect(pEntry));
417 3 : if (pEntry == pCursor)
418 3 : ShowCursor(true);
419 : }
420 :
421 : // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
422 3 : if (bSelect)
423 : {
424 3 : CallEventListeners(VCLEVENT_LISTBOX_SELECT, pEntry);
425 : }
426 3 : }
427 :
428 58 : void SvxIconChoiceCtrl_Impl::ResetVirtSize()
429 : {
430 58 : StopEditTimer();
431 58 : aVirtOutputSize.Width() = 0;
432 58 : aVirtOutputSize.Height() = 0;
433 58 : const size_t nCount = aEntries.size();
434 290 : for( size_t nCur = 0; nCur < nCount; nCur++ )
435 : {
436 232 : SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
437 232 : pCur->ClearFlags( SvxIconViewFlags::POS_MOVED );
438 232 : if( pCur->IsPosLocked() )
439 : {
440 : // adapt (among others) VirtSize
441 0 : if( !IsBoundingRectValid( pCur->aRect ) )
442 0 : FindBoundingRect( pCur );
443 : else
444 0 : AdjustVirtSize( pCur->aRect );
445 : }
446 : else
447 232 : InvalidateBoundingRect( pCur->aRect );
448 : }
449 :
450 58 : if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
451 : {
452 0 : Size aRealOutputSize( pView->GetOutputSizePixel() );
453 0 : if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
454 0 : aVirtOutputSize.Height() < aRealOutputSize.Height() )
455 : {
456 : sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
457 0 : aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
458 0 : if( nGridCount < nCount )
459 : {
460 0 : if( nWinBits & WB_ALIGN_TOP )
461 0 : nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
462 : else // WB_ALIGN_LEFT
463 0 : nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
464 : }
465 : }
466 : }
467 :
468 58 : pImpCursor->Clear();
469 58 : pGridMap->Clear();
470 58 : VisRectChanged();
471 58 : }
472 :
473 260 : void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
474 : {
475 260 : long nHeightOffs = 0;
476 260 : long nWidthOffs = 0;
477 :
478 260 : if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
479 101 : nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
480 :
481 260 : if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
482 217 : nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
483 :
484 260 : if( nWidthOffs || nHeightOffs )
485 : {
486 253 : Range aRange;
487 253 : aVirtOutputSize.Width() += nWidthOffs;
488 253 : aRange.Max() = aVirtOutputSize.Width();
489 253 : aHorSBar->SetRange( aRange );
490 :
491 253 : aVirtOutputSize.Height() += nHeightOffs;
492 253 : aRange.Max() = aVirtOutputSize.Height();
493 253 : aVerSBar->SetRange( aRange );
494 :
495 253 : pImpCursor->Clear();
496 253 : pGridMap->OutputSizeChanged();
497 253 : AdjustScrollBars();
498 253 : DocRectChanged();
499 : }
500 260 : }
501 :
502 0 : void SvxIconChoiceCtrl_Impl::InitPredecessors()
503 : {
504 : DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
505 0 : size_t nCount = aEntries.size();
506 0 : if( nCount )
507 : {
508 0 : SvxIconChoiceCtrlEntry* pPrev = aEntries[ 0 ];
509 0 : for( size_t nCur = 1; nCur <= nCount; nCur++ )
510 : {
511 0 : pPrev->ClearFlags( SvxIconViewFlags::POS_LOCKED | SvxIconViewFlags::POS_MOVED |
512 0 : SvxIconViewFlags::PRED_SET);
513 :
514 : SvxIconChoiceCtrlEntry* pNext;
515 0 : if( nCur == nCount )
516 0 : pNext = aEntries[ 0 ];
517 : else
518 0 : pNext = aEntries[ nCur ];
519 0 : pPrev->pflink = pNext;
520 0 : pNext->pblink = pPrev;
521 0 : pPrev = pNext;
522 : }
523 0 : pHead = aEntries[ 0 ];
524 : }
525 : else
526 0 : pHead = 0;
527 0 : nFlags &= ~F_MOVED_ENTRIES;
528 0 : }
529 :
530 58 : void SvxIconChoiceCtrl_Impl::ClearPredecessors()
531 : {
532 58 : if( pHead )
533 : {
534 0 : size_t nCount = aEntries.size();
535 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
536 : {
537 0 : SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
538 0 : pCur->pflink = 0;
539 0 : pCur->pblink = 0;
540 0 : pCur->ClearFlags( SvxIconViewFlags::PRED_SET );
541 : }
542 0 : pHead = 0;
543 : }
544 58 : }
545 :
546 58 : void SvxIconChoiceCtrl_Impl::Arrange( bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
547 : {
548 58 : if ( nSetMaxVirtWidth != 0 )
549 0 : nMaxVirtWidth = nSetMaxVirtWidth;
550 : else
551 58 : nMaxVirtWidth = aOutputSize.Width();
552 :
553 58 : if ( nSetMaxVirtHeight != 0 )
554 58 : nMaxVirtHeight = nSetMaxVirtHeight;
555 : else
556 0 : nMaxVirtHeight = aOutputSize.Height();
557 :
558 58 : ImpArrange( bKeepPredecessors );
559 58 : }
560 :
561 58 : void SvxIconChoiceCtrl_Impl::ImpArrange( bool bKeepPredecessors )
562 : {
563 58 : static Point aEmptyPoint;
564 :
565 58 : bool bOldUpdate = bUpdateMode;
566 58 : Rectangle aCurOutputArea( GetOutputRect() );
567 58 : if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
568 0 : bUpdateMode = false;
569 58 : aAutoArrangeIdle.Stop();
570 58 : nFlags &= ~F_MOVED_ENTRIES;
571 58 : nFlags |= F_ARRANGING;
572 58 : StopEditTimer();
573 58 : ShowCursor( false );
574 58 : ResetVirtSize();
575 58 : if( !bKeepPredecessors )
576 58 : ClearPredecessors();
577 58 : bBoundRectsDirty = false;
578 58 : SetOrigin( Point() );
579 58 : VisRectChanged();
580 58 : RecalcAllBoundingRectsSmart();
581 : // TODO: the invalidation in the detail view should be more intelligent
582 : //if( !(nWinBits & WB_DETAILS ))
583 58 : pView->Invalidate( InvalidateFlags::NoChildren );
584 58 : nFlags &= ~F_ARRANGING;
585 58 : if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
586 : {
587 0 : MakeVisible( aCurOutputArea );
588 0 : SetUpdateMode( bOldUpdate );
589 : }
590 58 : ShowCursor( true );
591 58 : }
592 :
593 6 : void SvxIconChoiceCtrl_Impl::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
594 : {
595 6 : bEndScrollInvalidate = false;
596 :
597 : #if defined(OV_DRAWGRID)
598 : Color aOldColor (rRenderContext.GetLineColor());
599 : Color aColor(COL_BLACK);
600 : rRenderContext.SetLineColor( aColor );
601 : Point aOffs(rRenderContext.GetMapMode().GetOrigin());
602 : Size aXSize(rRenderContext.GetOutputSizePixel());
603 : {
604 : Point aStart(LROFFS_WINBORDER, 0);
605 : Point aEnd(LROFFS_WINBORDER, aXSize.Height());
606 : aStart -= aOffs;
607 : aEnd -= aOffs;
608 : rRenderContext.DrawLine(aStart, aEnd);
609 : }
610 : {
611 : Point aStart(0, TBOFFS_WINBORDER);
612 : Point aEnd(aXSize.Width(), TBOFFS_WINBORDER);
613 : aStart -= aOffs;
614 : aEnd -= aOffs;
615 : rRenderContext.DrawLine(aStart, aEnd);
616 : }
617 :
618 : for (long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX)
619 : {
620 : Point aStart( nDX+LROFFS_WINBORDER, 0 );
621 : Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
622 : aStart -= aOffs;
623 : aEnd -= aOffs;
624 : rRenderContext.DrawLine(aStart, aEnd);
625 : }
626 : for (long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY)
627 : {
628 : Point aStart(0, nDY + TBOFFS_WINBORDER);
629 : Point aEnd(aXSize.Width(), nDY + TBOFFS_WINBORDER);
630 : aStart -= aOffs;
631 : aEnd -= aOffs;
632 : rRenderContext.DrawLine(aStart, aEnd);
633 : }
634 : rRenderContext.SetLineColor(aOldColor);
635 : #endif
636 6 : nFlags |= F_PAINTED;
637 :
638 6 : if (!aEntries.size())
639 0 : return;
640 6 : if (!pCursor)
641 : {
642 : // set cursor to item with focus-flag
643 3 : bool bfound = false;
644 15 : for (sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++)
645 : {
646 12 : SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry (i);
647 12 : if (pEntry->IsFocused())
648 : {
649 0 : pCursor = pEntry;
650 0 : bfound = true;
651 : }
652 : }
653 :
654 3 : if (!bfound)
655 3 : pCursor = aEntries[ 0 ];
656 : }
657 :
658 6 : size_t nCount = pZOrderList->size();
659 6 : if (!nCount)
660 0 : return;
661 :
662 6 : rRenderContext.Push(PushFlags::CLIPREGION);
663 6 : rRenderContext.SetClipRegion(vcl::Region(rRect));
664 :
665 6 : SvxIconChoiceCtrlEntryList_impl* pNewZOrderList = new SvxIconChoiceCtrlEntryList_impl();
666 6 : boost::scoped_ptr<SvxIconChoiceCtrlEntryList_impl> pPaintedEntries(new SvxIconChoiceCtrlEntryList_impl());
667 :
668 6 : size_t nPos = 0;
669 36 : while(nCount)
670 : {
671 24 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[nPos];
672 24 : const Rectangle& rBoundRect = GetEntryBoundRect(pEntry);
673 24 : if (rRect.IsOver(rBoundRect))
674 : {
675 24 : PaintEntry(pEntry, rBoundRect.TopLeft(), rRenderContext, true);
676 : // set entries to Top if they are being repainted
677 24 : pPaintedEntries->push_back(pEntry);
678 : }
679 : else
680 0 : pNewZOrderList->push_back(pEntry);
681 :
682 24 : nCount--;
683 24 : nPos++;
684 : }
685 6 : delete pZOrderList;
686 6 : pZOrderList = pNewZOrderList;
687 6 : nCount = pPaintedEntries->size();
688 6 : if (nCount)
689 : {
690 30 : for (size_t nCur = 0; nCur < nCount; nCur++)
691 24 : pZOrderList->push_back((*pPaintedEntries)[nCur]);
692 : }
693 6 : pPaintedEntries.reset();
694 :
695 6 : rRenderContext.Pop();
696 : }
697 :
698 18 : void SvxIconChoiceCtrl_Impl::RepaintEntries(SvxIconViewFlags nEntryFlagsMask)
699 : {
700 18 : const size_t nCount = pZOrderList->size();
701 18 : if (!nCount)
702 18 : return;
703 :
704 18 : Rectangle aOutRect(GetOutputRect());
705 90 : for (size_t nCur = 0; nCur < nCount; nCur++)
706 : {
707 72 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[nCur];
708 72 : if (pEntry->GetFlags() & nEntryFlagsMask)
709 : {
710 0 : const Rectangle& rBoundRect = GetEntryBoundRect(pEntry);
711 0 : if (aOutRect.IsOver(rBoundRect))
712 0 : pView->Invalidate(rBoundRect);
713 : }
714 : }
715 : }
716 :
717 29 : void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
718 : {
719 29 : aScrBarBox->SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
720 29 : Size aSize( pView->GetOutputSizePixel() );
721 29 : aScrBarBox->SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
722 29 : }
723 :
724 0 : bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
725 : {
726 0 : bool bHandled = true;
727 0 : bHighlightFramePressed = false;
728 0 : StopEditTimer();
729 0 : bool bGotFocus = (!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
730 0 : if( !(nWinBits & WB_NOPOINTERFOCUS) )
731 0 : pView->GrabFocus();
732 :
733 0 : Point aDocPos( rMEvt.GetPosPixel() );
734 0 : if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
735 0 : return false;
736 0 : ToDocPos( aDocPos );
737 0 : SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, true );
738 0 : if( pEntry )
739 0 : MakeEntryVisible( pEntry, false );
740 :
741 0 : if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
742 : {
743 0 : if( pEntry )
744 0 : SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), true);
745 0 : return true;
746 : }
747 :
748 0 : if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // keyboard selection?
749 : {
750 : DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
751 0 : if( rMEvt.IsMod1() )
752 0 : nFlags |= F_ADD_MODE;
753 :
754 0 : if( rMEvt.IsShift() )
755 : {
756 0 : Rectangle aRect( GetEntryBoundRect( pAnchor ));
757 0 : if( pEntry )
758 0 : aRect.Union( GetEntryBoundRect( pEntry ) );
759 : else
760 : {
761 0 : Rectangle aTempRect( aDocPos, Size(1,1));
762 0 : aRect.Union( aTempRect );
763 : }
764 0 : aCurSelectionRect = aRect;
765 0 : SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
766 : }
767 0 : else if( rMEvt.IsMod1() )
768 : {
769 0 : AddSelectedRect( aCurSelectionRect );
770 0 : pAnchor = 0;
771 0 : aCurSelectionRect.SetPos( aDocPos );
772 : }
773 :
774 0 : if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
775 0 : pView->StartTracking( StartTrackingFlags::ScrollRepeat );
776 0 : return true;
777 : }
778 : else
779 : {
780 0 : if( !pEntry )
781 : {
782 0 : if( eSelectionMode == MULTIPLE_SELECTION )
783 : {
784 0 : if( !rMEvt.IsMod1() ) // Ctrl
785 : {
786 0 : if( !bGotFocus )
787 : {
788 0 : SetNoSelection();
789 0 : ClearSelectedRectList();
790 : }
791 : }
792 : else
793 0 : nFlags |= F_ADD_MODE;
794 0 : aCurSelectionRect.SetPos( aDocPos );
795 0 : pView->StartTracking( StartTrackingFlags::ScrollRepeat );
796 : }
797 : else
798 0 : bHandled = false;
799 0 : return bHandled;
800 : }
801 : }
802 0 : bool bSelected = pEntry->IsSelected();
803 0 : bool bEditingEnabled = IsEntryEditingEnabled();
804 :
805 0 : if( rMEvt.GetClicks() == 2 )
806 : {
807 0 : DeselectAllBut( pEntry );
808 0 : SelectEntry( pEntry, true, true, false, true );
809 0 : pHdlEntry = pEntry;
810 0 : pView->ClickIcon();
811 : }
812 : else
813 : {
814 : // Inplace-Editing ?
815 0 : if( rMEvt.IsMod2() ) // Alt?
816 : {
817 0 : if( bEntryEditingEnabled && pEntry &&
818 0 : pEntry->IsSelected())
819 : {
820 0 : EditEntry( pEntry );
821 : }
822 : }
823 0 : else if( eSelectionMode == SINGLE_SELECTION )
824 : {
825 0 : DeselectAllBut( pEntry );
826 0 : SetCursor( pEntry );
827 0 : if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
828 0 : rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
829 : {
830 0 : nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
831 : }
832 : }
833 0 : else if( eSelectionMode == NO_SELECTION )
834 : {
835 0 : if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
836 : {
837 0 : pCurHighlightFrame = 0; // force repaint of frame
838 0 : bHighlightFramePressed = true;
839 0 : SetEntryHighlightFrame( pEntry, true );
840 : }
841 : }
842 : else
843 : {
844 0 : if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
845 : {
846 0 : if( !bSelected )
847 : {
848 0 : DeselectAllBut( pEntry, true /* paint synchronously */ );
849 0 : SetCursor( pEntry );
850 0 : SelectEntry( pEntry, true, true, false, true );
851 : }
852 : else
853 : {
854 : // deselect only in the Up, if the Move happened via D&D!
855 0 : nFlags |= F_DOWN_DESELECT;
856 0 : if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
857 0 : rMEvt.IsLeft())
858 : {
859 0 : nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
860 : }
861 : }
862 : }
863 0 : else if( rMEvt.IsMod1() )
864 0 : nFlags |= F_DOWN_CTRL;
865 : }
866 : }
867 0 : return bHandled;
868 : }
869 :
870 0 : bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
871 : {
872 0 : bool bHandled = false;
873 0 : if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
874 : {
875 0 : nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
876 0 : bHandled = true;
877 : }
878 :
879 0 : Point aDocPos( rMEvt.GetPosPixel() );
880 0 : ToDocPos( aDocPos );
881 0 : SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
882 0 : if( pDocEntry )
883 : {
884 0 : if( nFlags & F_DOWN_CTRL )
885 : {
886 : // Ctrl & MultiSelection
887 0 : ToggleSelection( pDocEntry );
888 0 : SetCursor( pDocEntry );
889 0 : bHandled = true;
890 : }
891 0 : else if( nFlags & F_DOWN_DESELECT )
892 : {
893 0 : DeselectAllBut( pDocEntry );
894 0 : SetCursor( pDocEntry );
895 0 : SelectEntry( pDocEntry, true, true, false, true );
896 0 : bHandled = true;
897 : }
898 : }
899 :
900 0 : nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
901 0 : if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
902 : {
903 0 : bHandled = true;
904 0 : StartEditTimer();
905 0 : nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
906 : }
907 :
908 0 : if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
909 : {
910 0 : bHandled = true;
911 0 : SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
912 0 : pCurHighlightFrame = 0; // force repaint of frame
913 0 : bHighlightFramePressed = false;
914 0 : SetEntryHighlightFrame( pEntry, true );
915 :
916 0 : pHdlEntry = pCurHighlightFrame;
917 0 : pView->ClickIcon();
918 :
919 : // set focus on Icon
920 0 : SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
921 0 : SetCursor_Impl( pOldCursor, pHdlEntry, false, false, true );
922 :
923 0 : pHdlEntry = 0;
924 : }
925 0 : return bHandled;
926 : }
927 :
928 0 : bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
929 : {
930 0 : const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
931 :
932 0 : if( pView->IsTracking() )
933 0 : return false;
934 0 : else if( nWinBits & WB_HIGHLIGHTFRAME )
935 : {
936 0 : SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, true );
937 0 : SetEntryHighlightFrame( pEntry );
938 : }
939 : else
940 0 : return false;
941 0 : return true;
942 : }
943 :
944 0 : void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
945 : SvxIconChoiceCtrlEntry* pNewCursor, bool bMod1, bool bShift, bool bPaintSync )
946 : {
947 0 : if( pNewCursor )
948 : {
949 0 : SvxIconChoiceCtrlEntry* pFilterEntry = 0;
950 0 : bool bDeselectAll = false;
951 0 : if( eSelectionMode != SINGLE_SELECTION )
952 : {
953 0 : if( !bMod1 && !bShift )
954 0 : bDeselectAll = true;
955 0 : else if( bShift && !bMod1 && !pAnchor )
956 : {
957 0 : bDeselectAll = true;
958 0 : pFilterEntry = pOldCursor;
959 : }
960 : }
961 0 : if( bDeselectAll )
962 0 : DeselectAllBut( pFilterEntry, bPaintSync );
963 0 : ShowCursor( false );
964 0 : MakeEntryVisible( pNewCursor );
965 0 : SetCursor( pNewCursor );
966 0 : if( bMod1 && !bShift )
967 : {
968 0 : if( pAnchor )
969 : {
970 0 : AddSelectedRect( pAnchor, pOldCursor );
971 0 : pAnchor = 0;
972 : }
973 : }
974 0 : else if( bShift )
975 : {
976 0 : if( !pAnchor )
977 0 : pAnchor = pOldCursor;
978 0 : if ( nWinBits & WB_ALIGN_LEFT )
979 0 : SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
980 : else
981 0 : SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
982 : }
983 : else
984 : {
985 0 : SelectEntry( pCursor, true, true, false, bPaintSync );
986 0 : aCurSelectionRect = GetEntryBoundRect( pCursor );
987 0 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
988 : }
989 : }
990 0 : }
991 :
992 0 : bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
993 : {
994 0 : StopEditTimer();
995 :
996 0 : bool bMod2 = rKEvt.GetKeyCode().IsMod2();
997 0 : sal_Unicode cChar = rKEvt.GetCharCode();
998 0 : sal_uLong nPos = (sal_uLong)-1;
999 0 : if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1000 : {
1001 : // shortcut is clicked
1002 0 : SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1003 0 : SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1004 0 : if ( pNewCursor != pOldCursor )
1005 0 : SetCursor_Impl( pOldCursor, pNewCursor, false, false, false );
1006 0 : return true;
1007 : }
1008 :
1009 0 : if ( bMod2 )
1010 : // no actions with <ALT>
1011 0 : return false;
1012 :
1013 0 : bool bKeyUsed = true;
1014 0 : bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1015 0 : bool bShift = rKEvt.GetKeyCode().IsShift();
1016 :
1017 0 : if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1018 : {
1019 0 : bShift = false;
1020 0 : bMod1 = false;
1021 : }
1022 :
1023 0 : if( bMod1 )
1024 0 : nFlags |= F_ADD_MODE;
1025 :
1026 : SvxIconChoiceCtrlEntry* pNewCursor;
1027 0 : SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1028 :
1029 0 : sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1030 0 : switch( nCode )
1031 : {
1032 : case KEY_UP:
1033 : case KEY_PAGEUP:
1034 0 : if( pCursor )
1035 : {
1036 0 : MakeEntryVisible( pCursor );
1037 0 : if( nCode == KEY_UP )
1038 0 : pNewCursor = pImpCursor->GoUpDown(pCursor,false);
1039 : else
1040 0 : pNewCursor = pImpCursor->GoPageUpDown(pCursor,false);
1041 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1042 0 : if( !pNewCursor )
1043 : {
1044 0 : Rectangle aRect( GetEntryBoundRect( pCursor ) );
1045 0 : if( aRect.Top())
1046 : {
1047 0 : aRect.Bottom() -= aRect.Top();
1048 0 : aRect.Top() = 0;
1049 0 : MakeVisible( aRect );
1050 : }
1051 : }
1052 :
1053 0 : if ( bChooseWithCursor && pNewCursor != NULL )
1054 : {
1055 0 : pHdlEntry = pNewCursor;//GetCurEntry();
1056 0 : pCurHighlightFrame = pHdlEntry;
1057 0 : pView->ClickIcon();
1058 0 : pCurHighlightFrame = NULL;
1059 : }
1060 : }
1061 0 : break;
1062 :
1063 : case KEY_DOWN:
1064 : case KEY_PAGEDOWN:
1065 0 : if( pCursor )
1066 : {
1067 0 : if( nCode == KEY_DOWN )
1068 0 : pNewCursor=pImpCursor->GoUpDown( pCursor,true );
1069 : else
1070 0 : pNewCursor=pImpCursor->GoPageUpDown( pCursor,true );
1071 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1072 :
1073 0 : if ( bChooseWithCursor && pNewCursor != NULL)
1074 : {
1075 0 : pHdlEntry = pNewCursor;//GetCurEntry();
1076 0 : pCurHighlightFrame = pHdlEntry;
1077 0 : pView->ClickIcon();
1078 0 : pCurHighlightFrame = NULL;
1079 : }
1080 : }
1081 0 : break;
1082 :
1083 : case KEY_RIGHT:
1084 0 : if( pCursor )
1085 : {
1086 0 : pNewCursor=pImpCursor->GoLeftRight(pCursor,true );
1087 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1088 : }
1089 0 : break;
1090 :
1091 : case KEY_LEFT:
1092 0 : if( pCursor )
1093 : {
1094 0 : MakeEntryVisible( pCursor );
1095 0 : pNewCursor = pImpCursor->GoLeftRight(pCursor,false );
1096 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1097 0 : if( !pNewCursor )
1098 : {
1099 0 : Rectangle aRect( GetEntryBoundRect(pCursor));
1100 0 : if( aRect.Left() )
1101 : {
1102 0 : aRect.Right() -= aRect.Left();
1103 0 : aRect.Left() = 0;
1104 0 : MakeVisible( aRect );
1105 : }
1106 : }
1107 : }
1108 0 : break;
1109 :
1110 : case KEY_F2:
1111 0 : if( !bMod1 && !bShift )
1112 0 : EditTimeoutHdl( 0 );
1113 : else
1114 0 : bKeyUsed = false;
1115 0 : break;
1116 :
1117 : case KEY_F8:
1118 0 : if( rKEvt.GetKeyCode().IsShift() )
1119 : {
1120 0 : if( nFlags & F_ADD_MODE )
1121 0 : nFlags &= (~F_ADD_MODE);
1122 : else
1123 0 : nFlags |= F_ADD_MODE;
1124 : }
1125 : else
1126 0 : bKeyUsed = false;
1127 0 : break;
1128 :
1129 : case KEY_SPACE:
1130 0 : if( pCursor && eSelectionMode != SINGLE_SELECTION )
1131 : {
1132 0 : if( !bMod1 )
1133 : {
1134 : //SelectAll( false );
1135 0 : SetNoSelection();
1136 0 : ClearSelectedRectList();
1137 :
1138 : // click Icon with spacebar
1139 0 : SetEntryHighlightFrame( GetCurEntry(), true );
1140 0 : pView->ClickIcon();
1141 0 : pHdlEntry = pCurHighlightFrame;
1142 0 : pCurHighlightFrame=0;
1143 : }
1144 : else
1145 0 : ToggleSelection( pCursor );
1146 : }
1147 0 : break;
1148 :
1149 : #ifdef DBG_UTIL
1150 : case KEY_F10:
1151 : if( rKEvt.GetKeyCode().IsShift() )
1152 : {
1153 : if( pCursor )
1154 : pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1155 : }
1156 : if( rKEvt.GetKeyCode().IsMod1() )
1157 : {
1158 : if( pCursor )
1159 : pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1160 : }
1161 : break;
1162 : #endif
1163 :
1164 : case KEY_ADD:
1165 : case KEY_DIVIDE :
1166 : case KEY_A:
1167 0 : if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1168 0 : SelectAll( true );
1169 : else
1170 0 : bKeyUsed = false;
1171 0 : break;
1172 :
1173 : case KEY_SUBTRACT:
1174 : case KEY_COMMA :
1175 0 : if( bMod1 )
1176 0 : SetNoSelection();
1177 : else
1178 0 : bKeyUsed = false;
1179 0 : break;
1180 :
1181 : case KEY_RETURN:
1182 0 : if( bMod1 )
1183 : {
1184 0 : if( pCursor && bEntryEditingEnabled )
1185 0 : /*pView->*/EditEntry( pCursor );
1186 : }
1187 : else
1188 0 : bKeyUsed = false;
1189 0 : break;
1190 :
1191 : case KEY_END:
1192 0 : if( pCursor )
1193 : {
1194 0 : pNewCursor = aEntries[ aEntries.size() - 1 ];
1195 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1196 : }
1197 0 : break;
1198 :
1199 : case KEY_HOME:
1200 0 : if( pCursor )
1201 : {
1202 0 : pNewCursor = aEntries[ 0 ];
1203 0 : SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, true );
1204 : }
1205 0 : break;
1206 :
1207 : default:
1208 0 : bKeyUsed = false;
1209 :
1210 : }
1211 0 : return bKeyUsed;
1212 : }
1213 :
1214 : // recalculate TopLeft of scrollbars (but not their sizes!)
1215 358 : void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1216 : {
1217 : // horizontal scrollbar
1218 358 : Point aPos( 0, nRealHeight );
1219 358 : aPos.Y() -= nHorSBarHeight;
1220 :
1221 358 : if( aHorSBar->GetPosPixel() != aPos )
1222 22 : aHorSBar->SetPosPixel( aPos );
1223 :
1224 : // vertical scrollbar
1225 358 : aPos.X() = nRealWidth; aPos.Y() = 0;
1226 358 : aPos.X() -= nVerSBarWidth;
1227 358 : aPos.X()++;
1228 358 : aPos.Y()--;
1229 :
1230 358 : if( aVerSBar->GetPosPixel() != aPos )
1231 14 : aVerSBar->SetPosPixel( aPos );
1232 358 : }
1233 :
1234 329 : void SvxIconChoiceCtrl_Impl::AdjustScrollBars( bool )
1235 : {
1236 329 : long nVirtHeight = aVirtOutputSize.Height();
1237 329 : long nVirtWidth = aVirtOutputSize.Width();
1238 :
1239 329 : Size aOSize( pView->Control::GetOutputSizePixel() );
1240 329 : long nRealHeight = aOSize.Height();
1241 329 : long nRealWidth = aOSize.Width();
1242 :
1243 329 : PositionScrollBars( nRealWidth, nRealHeight );
1244 :
1245 329 : const MapMode& rMapMode = pView->GetMapMode();
1246 329 : Point aOrigin( rMapMode.GetOrigin() );
1247 :
1248 : long nVisibleWidth;
1249 329 : if( nRealWidth > nVirtWidth )
1250 243 : nVisibleWidth = nVirtWidth + aOrigin.X();
1251 : else
1252 86 : nVisibleWidth = nRealWidth;
1253 :
1254 : long nVisibleHeight;
1255 329 : if( nRealHeight > nVirtHeight )
1256 160 : nVisibleHeight = nVirtHeight + aOrigin.Y();
1257 : else
1258 169 : nVisibleHeight = nRealHeight;
1259 :
1260 329 : bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1261 329 : bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1262 329 : bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1263 329 : bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1264 :
1265 329 : sal_uInt16 nResult = 0;
1266 329 : if( nVirtHeight )
1267 : {
1268 : // activate vertical scrollbar?
1269 317 : if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1270 : {
1271 0 : nResult = 0x0001;
1272 0 : nRealWidth -= nVerSBarWidth;
1273 :
1274 0 : if( nRealWidth > nVirtWidth )
1275 0 : nVisibleWidth = nVirtWidth + aOrigin.X();
1276 : else
1277 0 : nVisibleWidth = nRealWidth;
1278 :
1279 0 : nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1280 : }
1281 : // activate horizontal scrollbar?
1282 317 : if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1283 : {
1284 0 : nResult |= 0x0002;
1285 0 : nRealHeight -= nHorSBarHeight;
1286 :
1287 0 : if( nRealHeight > nVirtHeight )
1288 0 : nVisibleHeight = nVirtHeight + aOrigin.Y();
1289 : else
1290 0 : nVisibleHeight = nRealHeight;
1291 :
1292 : // do we need a vertical scrollbar after all?
1293 0 : if( !(nResult & 0x0001) && // only if not already there
1294 0 : ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1295 : {
1296 0 : nResult = 3; // both turned on
1297 0 : nRealWidth -= nVerSBarWidth;
1298 :
1299 0 : if( nRealWidth > nVirtWidth )
1300 0 : nVisibleWidth = nVirtWidth + aOrigin.X();
1301 : else
1302 0 : nVisibleWidth = nRealWidth;
1303 :
1304 0 : nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1305 : }
1306 : }
1307 : }
1308 :
1309 : // size vertical scrollbar
1310 329 : long nThumb = aVerSBar->GetThumbPos();
1311 329 : Size aSize( nVerSBarWidth, nRealHeight );
1312 329 : aSize.Height() += 2;
1313 329 : if( aSize != aVerSBar->GetSizePixel() )
1314 22 : aVerSBar->SetSizePixel( aSize );
1315 329 : aVerSBar->SetVisibleSize( nVisibleHeight );
1316 329 : aVerSBar->SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1317 :
1318 329 : if( nResult & 0x0001 )
1319 : {
1320 0 : aVerSBar->SetThumbPos( nThumb );
1321 0 : aVerSBar->Show();
1322 : }
1323 : else
1324 : {
1325 329 : aVerSBar->SetThumbPos( 0 );
1326 329 : aVerSBar->Hide();
1327 : }
1328 :
1329 : // size horizontal scrollbar
1330 329 : nThumb = aHorSBar->GetThumbPos();
1331 329 : aSize.Width() = nRealWidth;
1332 329 : aSize.Height() = nHorSBarHeight;
1333 329 : aSize.Width()++;
1334 329 : if( nResult & 0x0001 ) // vertical scrollbar?
1335 : {
1336 0 : aSize.Width()++;
1337 0 : nRealWidth++;
1338 : }
1339 329 : if( aSize != aHorSBar->GetSizePixel() )
1340 14 : aHorSBar->SetSizePixel( aSize );
1341 329 : aHorSBar->SetVisibleSize( nVisibleWidth );
1342 329 : aHorSBar->SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1343 329 : if( nResult & 0x0002 )
1344 : {
1345 0 : aHorSBar->SetThumbPos( nThumb );
1346 0 : aHorSBar->Show();
1347 : }
1348 : else
1349 : {
1350 329 : aHorSBar->SetThumbPos( 0 );
1351 329 : aHorSBar->Hide();
1352 : }
1353 :
1354 329 : aOutputSize.Width() = nRealWidth;
1355 329 : if( nResult & 0x0002 ) // horizontal scrollbar ?
1356 0 : nRealHeight++; // because lower border is clipped
1357 329 : aOutputSize.Height() = nRealHeight;
1358 :
1359 329 : if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1360 0 : aScrBarBox->Show();
1361 : else
1362 329 : aScrBarBox->Hide();
1363 329 : }
1364 :
1365 29 : void SvxIconChoiceCtrl_Impl::Resize()
1366 : {
1367 29 : StopEditTimer();
1368 29 : InitScrollBarBox();
1369 29 : aOutputSize = pView->GetOutputSizePixel();
1370 29 : pImpCursor->Clear();
1371 29 : pGridMap->OutputSizeChanged();
1372 :
1373 29 : const Size& rSize = pView->Control::GetOutputSizePixel();
1374 29 : PositionScrollBars( rSize.Width(), rSize.Height() );
1375 : // The scrollbars are shown/hidden asynchronously, so derived classes can
1376 : // do an Arrange during Resize, without the scrollbars suddenly turning
1377 : // on and off again.
1378 : // If an event is already underway, we don't need to send a new one, at least
1379 : // as long as there is only one event type.
1380 29 : if ( ! nUserEventAdjustScrBars )
1381 : nUserEventAdjustScrBars =
1382 : Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1383 10 : EVENTID_ADJUST_SCROLLBARS);
1384 :
1385 29 : VisRectChanged();
1386 29 : }
1387 :
1388 0 : bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1389 : {
1390 0 : if( !pZOrderList || !aHorSBar->IsVisible() )
1391 0 : return false;
1392 0 : const MapMode& rMapMode = pView->GetMapMode();
1393 0 : Point aOrigin( rMapMode.GetOrigin() );
1394 0 : if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1395 : {
1396 0 : long nWidth = aOutputSize.Width();
1397 0 : const size_t nCount = pZOrderList->size();
1398 0 : long nMostRight = 0;
1399 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
1400 : {
1401 0 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1402 0 : long nRight = GetEntryBoundRect(pEntry).Right();
1403 0 : if( nRight > nWidth )
1404 0 : return false;
1405 0 : if( nRight > nMostRight )
1406 0 : nMostRight = nRight;
1407 : }
1408 0 : aHorSBar->Hide();
1409 0 : aOutputSize.Height() += nHorSBarHeight;
1410 0 : aVirtOutputSize.Width() = nMostRight;
1411 0 : aHorSBar->SetThumbPos( 0 );
1412 0 : Range aRange;
1413 0 : aRange.Max() = nMostRight - 1;
1414 0 : aHorSBar->SetRange( aRange );
1415 0 : if( aVerSBar->IsVisible() )
1416 : {
1417 0 : Size aSize( aVerSBar->GetSizePixel());
1418 0 : aSize.Height() += nHorSBarHeight;
1419 0 : aVerSBar->SetSizePixel( aSize );
1420 : }
1421 0 : return true;
1422 : }
1423 0 : return false;
1424 : }
1425 :
1426 0 : bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1427 : {
1428 0 : if( !pZOrderList || !aVerSBar->IsVisible() )
1429 0 : return false;
1430 0 : const MapMode& rMapMode = pView->GetMapMode();
1431 0 : Point aOrigin( rMapMode.GetOrigin() );
1432 0 : if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1433 : {
1434 0 : long nDeepest = 0;
1435 0 : long nHeight = aOutputSize.Height();
1436 0 : const size_t nCount = pZOrderList->size();
1437 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
1438 : {
1439 0 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1440 0 : long nBottom = GetEntryBoundRect(pEntry).Bottom();
1441 0 : if( nBottom > nHeight )
1442 0 : return false;
1443 0 : if( nBottom > nDeepest )
1444 0 : nDeepest = nBottom;
1445 : }
1446 0 : aVerSBar->Hide();
1447 0 : aOutputSize.Width() += nVerSBarWidth;
1448 0 : aVirtOutputSize.Height() = nDeepest;
1449 0 : aVerSBar->SetThumbPos( 0 );
1450 0 : Range aRange;
1451 0 : aRange.Max() = nDeepest - 1;
1452 0 : aVerSBar->SetRange( aRange );
1453 0 : if( aHorSBar->IsVisible() )
1454 : {
1455 0 : Size aSize( aHorSBar->GetSizePixel());
1456 0 : aSize.Width() += nVerSBarWidth;
1457 0 : aHorSBar->SetSizePixel( aSize );
1458 : }
1459 0 : return true;
1460 : }
1461 0 : return false;
1462 : }
1463 :
1464 :
1465 : // hides scrollbars if they're unnecessary
1466 0 : void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1467 : {
1468 0 : CheckVerScrollBar();
1469 0 : if( CheckHorScrollBar() )
1470 0 : CheckVerScrollBar();
1471 0 : if( aVerSBar->IsVisible() && aHorSBar->IsVisible() )
1472 0 : aScrBarBox->Show();
1473 : else
1474 0 : aScrBarBox->Hide();
1475 0 : }
1476 :
1477 :
1478 12 : void SvxIconChoiceCtrl_Impl::GetFocus()
1479 : {
1480 12 : RepaintEntries( SvxIconViewFlags::SELECTED );
1481 12 : if( pCursor )
1482 : {
1483 0 : pCursor->SetFlags( SvxIconViewFlags::FOCUSED );
1484 0 : ShowCursor( true );
1485 : }
1486 12 : }
1487 :
1488 6 : void SvxIconChoiceCtrl_Impl::LoseFocus()
1489 : {
1490 6 : StopEditTimer();
1491 6 : if( pCursor )
1492 0 : pCursor->ClearFlags( SvxIconViewFlags::FOCUSED );
1493 6 : ShowCursor( false );
1494 :
1495 : // HideFocus ();
1496 : // pView->Invalidate ( aFocus.aRect );
1497 :
1498 6 : RepaintEntries( SvxIconViewFlags::SELECTED );
1499 6 : }
1500 :
1501 0 : void SvxIconChoiceCtrl_Impl::SetUpdateMode( bool bUpdate )
1502 : {
1503 0 : if( bUpdate != bUpdateMode )
1504 : {
1505 0 : bUpdateMode = bUpdate;
1506 0 : if( bUpdate )
1507 : {
1508 0 : AdjustScrollBars();
1509 0 : pImpCursor->Clear();
1510 0 : pGridMap->Clear();
1511 0 : pView->Invalidate(InvalidateFlags::NoChildren);
1512 : }
1513 : }
1514 0 : }
1515 :
1516 : // priorities of the emphasis: bDropTarget => bCursored => bSelected
1517 24 : void SvxIconChoiceCtrl_Impl::PaintEmphasis(const Rectangle& rTextRect, const Rectangle& rImageRect, bool bSelected,
1518 : bool bDropTarget, bool bCursored, vcl::RenderContext& rRenderContext, bool bIsBackgroundPainted)
1519 : {
1520 24 : static Color aTransparent(COL_TRANSPARENT);
1521 :
1522 24 : const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
1523 24 : Color aOldFillColor(rRenderContext.GetFillColor());
1524 :
1525 24 : bool bSolidTextRect = false;
1526 24 : bool bSolidImageRect = false;
1527 :
1528 24 : if(bDropTarget && (eSelectionMode != NO_SELECTION))
1529 : {
1530 0 : rRenderContext.SetFillColor(rSettings.GetHighlightColor());
1531 0 : bSolidTextRect = true;
1532 0 : bSolidImageRect = true;
1533 : }
1534 : else
1535 : {
1536 24 : if (!bSelected || bCursored)
1537 : {
1538 21 : const Color& rFillColor = rRenderContext.GetFont().GetFillColor();
1539 21 : rRenderContext.SetFillColor(rFillColor);
1540 21 : if (rFillColor != aTransparent)
1541 0 : bSolidTextRect = true;
1542 : }
1543 : }
1544 :
1545 : // draw text rectangle
1546 24 : if (!bSolidTextRect)
1547 : {
1548 24 : if (!bIsBackgroundPainted)
1549 0 : rRenderContext.Erase(rTextRect);
1550 : }
1551 : else
1552 : {
1553 0 : Color aOldLineColor;
1554 0 : if (bCursored)
1555 : {
1556 0 : aOldLineColor = rRenderContext.GetLineColor();
1557 0 : rRenderContext.SetLineColor(Color(COL_GRAY));
1558 : }
1559 0 : rRenderContext.DrawRect(rTextRect);
1560 0 : if (bCursored)
1561 0 : rRenderContext.SetLineColor(aOldLineColor);
1562 : }
1563 :
1564 : // draw image rectangle
1565 24 : if (!bSolidImageRect)
1566 : {
1567 24 : if (!bIsBackgroundPainted)
1568 0 : rRenderContext.Erase(rImageRect);
1569 : }
1570 :
1571 24 : rRenderContext.SetFillColor(aOldFillColor);
1572 24 : }
1573 :
1574 :
1575 48 : void SvxIconChoiceCtrl_Impl::PaintItem(const Rectangle& rRect,
1576 : IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1577 : vcl::RenderContext& rRenderContext, const OUString* pStr, vcl::ControlLayoutData* _pLayoutData )
1578 : {
1579 48 : if (eItem == IcnViewFieldTypeText)
1580 : {
1581 24 : OUString aText;
1582 24 : if (!pStr)
1583 24 : aText = SvtIconChoiceCtrl::GetEntryText(pEntry, false);
1584 : else
1585 0 : aText = *pStr;
1586 :
1587 24 : if (_pLayoutData)
1588 : {
1589 0 : rRenderContext.DrawText(rRect, aText, nCurTextDrawFlags, &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText);
1590 : }
1591 : else
1592 : {
1593 24 : Color aOldFontColor = rRenderContext.GetTextColor();
1594 24 : if (pView->AutoFontColor())
1595 : {
1596 0 : Color aBkgColor(rRenderContext.GetBackground().GetColor());
1597 0 : Color aFontColor;
1598 0 : sal_uInt16 nColor = (aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue()) / 3;
1599 0 : if (nColor > 127)
1600 0 : aFontColor.SetColor(COL_BLACK);
1601 : else
1602 0 : aFontColor.SetColor(COL_WHITE);
1603 0 : rRenderContext.SetTextColor(aFontColor);
1604 : }
1605 :
1606 24 : rRenderContext.DrawText(rRect, aText, nCurTextDrawFlags);
1607 :
1608 24 : if (pView->AutoFontColor())
1609 0 : rRenderContext.SetTextColor(aOldFontColor);
1610 :
1611 24 : if (pEntry->IsFocused())
1612 : {
1613 3 : Rectangle aRect (CalcFocusRect(pEntry));
1614 3 : ShowFocus(aRect);
1615 3 : DrawFocusRect(rRenderContext);
1616 : }
1617 24 : }
1618 : }
1619 : else
1620 : {
1621 24 : Point aPos(rRect.TopLeft());
1622 24 : if (nPaintFlags & PAINTFLAG_HOR_CENTERED)
1623 24 : aPos.X() += (rRect.GetWidth() - aImageSize.Width()) / 2;
1624 24 : if (nPaintFlags & PAINTFLAG_VER_CENTERED)
1625 24 : aPos.Y() += (rRect.GetHeight() - aImageSize.Height()) / 2;
1626 24 : SvtIconChoiceCtrl::DrawEntryImage(pEntry, aPos, rRenderContext);
1627 : }
1628 48 : }
1629 :
1630 24 : void SvxIconChoiceCtrl_Impl::PaintEntry(SvxIconChoiceCtrlEntry* pEntry, const Point& rPos, vcl::RenderContext& rRenderContext, bool bIsBackgroundPainted)
1631 : {
1632 24 : bool bSelected = false;
1633 :
1634 24 : if (eSelectionMode != NO_SELECTION)
1635 24 : bSelected = pEntry->IsSelected();
1636 :
1637 24 : bool bCursored = pEntry->IsCursored();
1638 24 : bool bDropTarget = pEntry->IsDropTarget();
1639 24 : bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1640 :
1641 24 : rRenderContext.Push(PushFlags::FONT | PushFlags::TEXTCOLOR);
1642 :
1643 24 : OUString aEntryText(SvtIconChoiceCtrl::GetEntryText(pEntry, false));
1644 24 : Rectangle aTextRect(CalcTextRect(pEntry, &rPos, false, &aEntryText));
1645 24 : Rectangle aBmpRect(CalcBmpRect(pEntry, &rPos));
1646 :
1647 24 : bool bShowSelection = ((bSelected && !bCursored) && !bNoEmphasis && (eSelectionMode != NO_SELECTION));
1648 :
1649 24 : bool bActiveSelection = (0 != (nWinBits & WB_NOHIDESELECTION)) || pView->HasFocus();
1650 :
1651 24 : if (bShowSelection)
1652 : {
1653 3 : const StyleSettings& rSettings = rRenderContext.GetSettings().GetStyleSettings();
1654 3 : vcl::Font aNewFont(rRenderContext.GetFont());
1655 :
1656 : // font fill colors that are attributed "hard" need corresponding "hard"
1657 : // attributed highlight colors
1658 3 : if ((nWinBits & WB_NOHIDESELECTION) || pView->HasFocus())
1659 3 : aNewFont.SetFillColor(rSettings.GetHighlightColor());
1660 : else
1661 0 : aNewFont.SetFillColor(rSettings.GetDeactiveColor());
1662 :
1663 3 : Color aWinCol = rSettings.GetWindowTextColor();
1664 3 : if (!bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright())
1665 0 : aNewFont.SetColor(rSettings.GetWindowTextColor());
1666 : else
1667 3 : aNewFont.SetColor(rSettings.GetHighlightTextColor());
1668 :
1669 3 : rRenderContext.SetFont(aNewFont);
1670 :
1671 3 : rRenderContext.SetFillColor(rRenderContext.GetBackground().GetColor());
1672 3 : rRenderContext.DrawRect(CalcFocusRect(pEntry));
1673 3 : rRenderContext.SetFillColor();
1674 : }
1675 :
1676 24 : bool bResetClipRegion = false;
1677 24 : if (!rRenderContext.IsClipRegion() && (aVerSBar->IsVisible() || aHorSBar->IsVisible()))
1678 : {
1679 0 : Rectangle aOutputArea(GetOutputRect());
1680 0 : if (aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect))
1681 : {
1682 0 : rRenderContext.SetClipRegion(vcl::Region(aOutputArea));
1683 0 : bResetClipRegion = true;
1684 : }
1685 : }
1686 :
1687 24 : bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
1688 24 : sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
1689 24 : if (bLargeIconMode)
1690 24 : nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
1691 24 : sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
1692 :
1693 24 : if( !bNoEmphasis )
1694 24 : PaintEmphasis(aTextRect, aBmpRect, bSelected, bDropTarget, bCursored, rRenderContext, bIsBackgroundPainted);
1695 :
1696 24 : if ( bShowSelection )
1697 3 : vcl::RenderTools::DrawSelectionBackground(rRenderContext, *pView.get(), CalcFocusRect(pEntry),
1698 6 : bActiveSelection ? 1 : 2, false, true, false);
1699 :
1700 :
1701 24 : PaintItem(aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, rRenderContext);
1702 :
1703 24 : PaintItem(aTextRect, IcnViewFieldTypeText, pEntry, nTextPaintFlags, rRenderContext);
1704 :
1705 : // draw highlight frame
1706 24 : if (pEntry == pCurHighlightFrame && !bNoEmphasis)
1707 0 : DrawHighlightFrame(rRenderContext, CalcFocusRect(pEntry), false);
1708 :
1709 24 : rRenderContext.Pop();
1710 24 : if (bResetClipRegion)
1711 0 : rRenderContext.SetClipRegion();
1712 24 : }
1713 :
1714 0 : void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1715 : bool bAdjustAtGrid, bool bCheckScrollBars, bool bKeepGridMap )
1716 : {
1717 0 : ShowCursor( false );
1718 0 : Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
1719 0 : pView->Invalidate( aBoundRect );
1720 0 : ToTop( pEntry );
1721 0 : if( !IsAutoArrange() )
1722 : {
1723 0 : bool bAdjustVirtSize = false;
1724 0 : if( rPos != aBoundRect.TopLeft() )
1725 : {
1726 : Point aGridOffs(
1727 0 : pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
1728 0 : pImpCursor->Clear();
1729 0 : if( !bKeepGridMap )
1730 0 : pGridMap->Clear();
1731 0 : aBoundRect.SetPos( rPos );
1732 0 : pEntry->aRect = aBoundRect;
1733 0 : pEntry->aGridRect.SetPos( rPos + aGridOffs );
1734 0 : bAdjustVirtSize = true;
1735 : }
1736 0 : if( bAdjustAtGrid )
1737 : {
1738 0 : if( bAdjustVirtSize )
1739 : {
1740 : // By aligning the (in some cases newly positioned) entry, it
1741 : // can become completely visible again, so that maybe we don't
1742 : // need a scrollbar after all. To avoid suddenly turning the
1743 : // scrollbar(s) on and then off again, we use the aligned
1744 : // bounding rectangle of the entry to enlarge the virtual
1745 : // output size. The virtual size has to be adapted, because
1746 : // AdjustEntryAtGrid depends on it.
1747 0 : const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
1748 0 : Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
1749 0 : Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
1750 0 : Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
1751 0 : AdjustVirtSize( aNewBoundRect );
1752 0 : bAdjustVirtSize = false;
1753 : }
1754 0 : AdjustEntryAtGrid( pEntry );
1755 0 : ToTop( pEntry );
1756 : }
1757 0 : if( bAdjustVirtSize )
1758 0 : AdjustVirtSize( pEntry->aRect );
1759 :
1760 0 : if( bCheckScrollBars && bUpdateMode )
1761 0 : CheckScrollBars();
1762 :
1763 0 : pView->Invalidate( pEntry->aRect );
1764 0 : pGridMap->OccupyGrids( pEntry );
1765 : }
1766 : else
1767 : {
1768 0 : SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
1769 0 : SetEntryPredecessor( pEntry, pPrev );
1770 0 : aAutoArrangeIdle.Start();
1771 : }
1772 0 : ShowCursor( true );
1773 0 : }
1774 :
1775 0 : void SvxIconChoiceCtrl_Impl::SetNoSelection()
1776 : {
1777 : // block recursive calls via SelectEntry
1778 0 : if( !(nFlags & F_CLEARING_SELECTION ))
1779 : {
1780 0 : nFlags |= F_CLEARING_SELECTION;
1781 0 : DeselectAllBut( 0, true );
1782 0 : nFlags &= ~F_CLEARING_SELECTION;
1783 : }
1784 0 : }
1785 :
1786 0 : SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, bool bHit )
1787 : {
1788 0 : CheckBoundingRects();
1789 : // search through z-order list from the end
1790 0 : size_t nCount = pZOrderList->size();
1791 0 : while( nCount )
1792 : {
1793 0 : nCount--;
1794 0 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCount ];
1795 0 : if( pEntry->aRect.IsInside( rDocPos ) )
1796 : {
1797 0 : if( bHit )
1798 : {
1799 0 : Rectangle aRect = CalcBmpRect( pEntry );
1800 0 : aRect.Top() -= 3;
1801 0 : aRect.Bottom() += 3;
1802 0 : aRect.Left() -= 3;
1803 0 : aRect.Right() += 3;
1804 0 : if( aRect.IsInside( rDocPos ) )
1805 0 : return pEntry;
1806 0 : aRect = CalcTextRect( pEntry );
1807 0 : if( aRect.IsInside( rDocPos ) )
1808 0 : return pEntry;
1809 : }
1810 : else
1811 0 : return pEntry;
1812 : }
1813 : }
1814 0 : return 0;
1815 : }
1816 :
1817 0 : void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, bool bBound )
1818 : {
1819 0 : if ( bBound )
1820 : {
1821 0 : const Rectangle& rRect = GetEntryBoundRect( pEntry );
1822 0 : MakeVisible( rRect );
1823 : }
1824 : else
1825 : {
1826 0 : Rectangle aRect = CalcBmpRect( pEntry );
1827 0 : aRect.Union( CalcTextRect( pEntry ) );
1828 0 : aRect.Top() += TBOFFS_BOUND;
1829 0 : aRect.Bottom() += TBOFFS_BOUND;
1830 0 : aRect.Left() += LROFFS_BOUND;
1831 0 : aRect.Right() += LROFFS_BOUND;
1832 0 : MakeVisible( aRect );
1833 : }
1834 0 : }
1835 :
1836 335 : const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
1837 : {
1838 335 : if( !IsBoundingRectValid( pEntry->aRect ))
1839 0 : FindBoundingRect( pEntry );
1840 335 : return pEntry->aRect;
1841 : }
1842 :
1843 72 : Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
1844 : {
1845 72 : Rectangle aBound = GetEntryBoundRect( pEntry );
1846 72 : if( pPos )
1847 24 : aBound.SetPos( *pPos );
1848 72 : Point aPos( aBound.TopLeft() );
1849 :
1850 72 : switch( nWinBits & (VIEWMODE_MASK) )
1851 : {
1852 : case WB_ICON:
1853 : {
1854 72 : aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
1855 72 : return Rectangle( aPos, aImageSize );
1856 : }
1857 :
1858 : case WB_SMALLICON:
1859 : case WB_DETAILS:
1860 0 : aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
1861 : //TODO: determine horizontal distance to bounding rectangle
1862 0 : return Rectangle( aPos, aImageSize );
1863 :
1864 : default:
1865 : OSL_FAIL("IconView: Viewmode not set");
1866 0 : return aBound;
1867 : }
1868 : }
1869 :
1870 48 : Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
1871 : const Point* pEntryPos, bool bEdit, const OUString* pStr )
1872 : {
1873 48 : OUString aEntryText;
1874 48 : if( !pStr )
1875 24 : aEntryText = SvtIconChoiceCtrl::GetEntryText( pEntry, bEdit );
1876 : else
1877 24 : aEntryText = *pStr;
1878 :
1879 48 : const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
1880 48 : Rectangle aBound( GetEntryBoundRect( pEntry ) );
1881 48 : if( pEntryPos )
1882 24 : aBound.SetPos( *pEntryPos );
1883 :
1884 48 : Rectangle aTextRect( aMaxTextRect );
1885 48 : if( !bEdit )
1886 48 : aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
1887 :
1888 48 : Size aTextSize( aTextRect.GetSize() );
1889 :
1890 48 : Point aPos( aBound.TopLeft() );
1891 48 : long nBoundWidth = aBound.GetWidth();
1892 48 : long nBoundHeight = aBound.GetHeight();
1893 :
1894 48 : switch( nWinBits & (VIEWMODE_MASK) )
1895 : {
1896 : case WB_ICON:
1897 48 : aPos.Y() += aImageSize.Height();
1898 48 : aPos.Y() += VER_DIST_BMP_STRING;
1899 : // at little more space when editing
1900 48 : if( bEdit )
1901 : {
1902 : // +20%
1903 0 : long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
1904 0 : aImageSize.Width();
1905 0 : if( nMinWidth > nBoundWidth )
1906 0 : nMinWidth = nBoundWidth;
1907 :
1908 0 : if( aTextSize.Width() < nMinWidth )
1909 0 : aTextSize.Width() = nMinWidth;
1910 :
1911 : // when editing, overlap with the area below is allowed
1912 0 : Size aOptSize = aMaxTextRect.GetSize();
1913 0 : if( aOptSize.Height() > aTextSize.Height() )
1914 0 : aTextSize.Height() = aOptSize.Height();
1915 : }
1916 48 : aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
1917 48 : break;
1918 :
1919 : case WB_SMALLICON:
1920 : case WB_DETAILS:
1921 0 : aPos.X() += aImageSize.Width();
1922 0 : aPos.X() += HOR_DIST_BMP_STRING;
1923 0 : aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
1924 0 : break;
1925 : }
1926 48 : return Rectangle( aPos, aTextSize );
1927 : }
1928 :
1929 :
1930 520 : long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
1931 : {
1932 520 : long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
1933 : // nStringWidth += 2*LROFFS_TEXT;
1934 520 : long nWidth = 0;
1935 :
1936 520 : switch( nWinBits & (VIEWMODE_MASK) )
1937 : {
1938 : case WB_ICON:
1939 520 : nWidth = std::max( nStringWidth, aImageSize.Width() );
1940 520 : break;
1941 :
1942 : case WB_SMALLICON:
1943 : case WB_DETAILS:
1944 0 : nWidth = aImageSize.Width();
1945 0 : nWidth += HOR_DIST_BMP_STRING;
1946 0 : nWidth += nStringWidth;
1947 0 : break;
1948 : }
1949 520 : return nWidth;
1950 : }
1951 :
1952 520 : long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
1953 : {
1954 520 : long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
1955 520 : long nHeight = 0;
1956 :
1957 520 : switch( nWinBits & (VIEWMODE_MASK) )
1958 : {
1959 : case WB_ICON:
1960 520 : nHeight = aImageSize.Height();
1961 520 : nHeight += VER_DIST_BMP_STRING;
1962 520 : nHeight += nStringHeight;
1963 520 : break;
1964 :
1965 : case WB_SMALLICON:
1966 : case WB_DETAILS:
1967 0 : nHeight = std::max( aImageSize.Height(), nStringHeight );
1968 0 : break;
1969 : }
1970 520 : if( nHeight > nMaxBoundHeight )
1971 : {
1972 65 : const_cast<SvxIconChoiceCtrl_Impl*>(this)->nMaxBoundHeight = nHeight;
1973 65 : const_cast<SvxIconChoiceCtrl_Impl*>(this)->aHorSBar->SetLineSize( GetScrollBarLineSize() );
1974 65 : const_cast<SvxIconChoiceCtrl_Impl*>(this)->aVerSBar->SetLineSize( GetScrollBarLineSize() );
1975 : }
1976 520 : return nHeight;
1977 : }
1978 :
1979 520 : Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
1980 : {
1981 : return Size( CalcBoundingWidth( pEntry ),
1982 520 : CalcBoundingHeight( pEntry ) );
1983 : }
1984 :
1985 58 : void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
1986 : {
1987 58 : nMaxBoundHeight = 0;
1988 58 : pZOrderList->clear();
1989 : size_t nCur;
1990 : SvxIconChoiceCtrlEntry* pEntry;
1991 58 : const size_t nCount = aEntries.size();
1992 :
1993 58 : if( !IsAutoArrange() || !pHead )
1994 : {
1995 290 : for( nCur = 0; nCur < nCount; nCur++ )
1996 : {
1997 232 : pEntry = aEntries[ nCur ];
1998 232 : if( IsBoundingRectValid( pEntry->aRect ))
1999 : {
2000 0 : Size aBoundSize( pEntry->aRect.GetSize() );
2001 0 : if( aBoundSize.Height() > nMaxBoundHeight )
2002 0 : nMaxBoundHeight = aBoundSize.Height();
2003 : }
2004 : else
2005 232 : FindBoundingRect( pEntry );
2006 232 : pZOrderList->push_back( pEntry );
2007 : }
2008 : }
2009 : else
2010 : {
2011 0 : nCur = 0;
2012 0 : pEntry = pHead;
2013 0 : while( nCur != nCount )
2014 : {
2015 : DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2016 0 : if( IsBoundingRectValid( pEntry->aRect ))
2017 : {
2018 0 : Size aBoundSize( pEntry->aRect.GetSize() );
2019 0 : if( aBoundSize.Height() > nMaxBoundHeight )
2020 0 : nMaxBoundHeight = aBoundSize.Height();
2021 : }
2022 : else
2023 0 : FindBoundingRect( pEntry );
2024 0 : pZOrderList->push_back( pEntry );
2025 0 : pEntry = pEntry->pflink;
2026 0 : nCur++;
2027 : }
2028 : }
2029 58 : AdjustScrollBars();
2030 58 : }
2031 :
2032 260 : void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2033 : {
2034 : DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2035 260 : if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2036 : {
2037 0 : AdjustVirtSize( pEntry->aRect );
2038 260 : return;
2039 : }
2040 260 : Size aSize( CalcBoundingSize( pEntry ) );
2041 260 : Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(true)).TopLeft());
2042 260 : SetBoundingRect_Impl( pEntry, aPos, aSize );
2043 : }
2044 :
2045 260 : void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2046 : const Size& /*rBoundingSize*/ )
2047 : {
2048 260 : Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2049 260 : pEntry->aGridRect = aGridRect;
2050 260 : Center( pEntry );
2051 260 : AdjustVirtSize( pEntry->aRect );
2052 260 : pGridMap->OccupyGrids( pEntry );
2053 260 : }
2054 :
2055 :
2056 3 : void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, bool bSyncSingleSelection,
2057 : bool bShowFocusAsync )
2058 : {
2059 3 : if( pEntry == pCursor )
2060 : {
2061 0 : if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2062 0 : !pCursor->IsSelected() )
2063 0 : SelectEntry( pCursor, true, true );
2064 3 : return;
2065 : }
2066 3 : ShowCursor( false );
2067 3 : SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2068 3 : pCursor = pEntry;
2069 3 : if( pOldCursor )
2070 : {
2071 3 : pOldCursor->ClearFlags( SvxIconViewFlags::FOCUSED );
2072 3 : if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2073 3 : SelectEntry( pOldCursor, false, true ); // deselect old cursor
2074 : }
2075 3 : if( pCursor )
2076 : {
2077 3 : ToTop( pCursor );
2078 3 : pCursor->SetFlags( SvxIconViewFlags::FOCUSED );
2079 3 : if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2080 3 : SelectEntry( pCursor, true, true );
2081 3 : if( !bShowFocusAsync )
2082 3 : ShowCursor( true );
2083 : else
2084 : {
2085 0 : if( !nUserEventShowCursor )
2086 : nUserEventShowCursor =
2087 : Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2088 0 : EVENTID_SHOW_CURSOR );
2089 : }
2090 : }
2091 : }
2092 :
2093 :
2094 160 : void SvxIconChoiceCtrl_Impl::ShowCursor( bool bShow )
2095 : {
2096 160 : if( !pCursor || !bShow || !pView->HasFocus() )
2097 : {
2098 148 : pView->HideFocus();
2099 308 : return;
2100 : }
2101 12 : Rectangle aRect ( CalcFocusRect( pCursor ) );
2102 12 : /*pView->*/ShowFocus( aRect );
2103 : }
2104 :
2105 :
2106 0 : void SvxIconChoiceCtrl_Impl::HideDDIcon()
2107 : {
2108 0 : pView->Update();
2109 0 : ImpHideDDIcon();
2110 0 : pDDBufDev = pDDDev;
2111 0 : pDDDev = 0;
2112 0 : }
2113 :
2114 0 : void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2115 : {
2116 0 : if( pDDDev )
2117 : {
2118 0 : Size aSize( pDDDev->GetOutputSizePixel() );
2119 : // restore pView
2120 0 : pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2121 : }
2122 0 : }
2123 :
2124 0 : bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2125 : {
2126 0 : Rectangle aDocRect( GetDocumentRect() );
2127 0 : Rectangle aVisRect( GetVisibleRect() );
2128 0 : if( aVisRect.IsInside( aDocRect ))
2129 0 : return false;
2130 0 : Size aDocSize( aDocRect.GetSize() );
2131 0 : Size aVisSize( aVisRect.GetSize() );
2132 0 : bool bHor = aDocSize.Width() > aVisSize.Width();
2133 0 : bool bVer = aDocSize.Height() > aVisSize.Height();
2134 :
2135 0 : long nScrollDX = 0, nScrollDY = 0;
2136 :
2137 0 : switch( rCmd.GetCommand() )
2138 : {
2139 : case CommandEventId::StartAutoScroll:
2140 : {
2141 0 : pView->EndTracking();
2142 0 : StartAutoScrollFlags nScrollFlags = StartAutoScrollFlags::NONE;
2143 0 : if( bHor )
2144 0 : nScrollFlags |= StartAutoScrollFlags::Horz;
2145 0 : if( bVer )
2146 0 : nScrollFlags |= StartAutoScrollFlags::Vert;
2147 0 : if( nScrollFlags != StartAutoScrollFlags::NONE )
2148 : {
2149 0 : pView->StartAutoScroll( nScrollFlags );
2150 0 : return true;
2151 : }
2152 : }
2153 0 : break;
2154 :
2155 : case CommandEventId::Wheel:
2156 : {
2157 0 : const CommandWheelData* pData = rCmd.GetWheelData();
2158 0 : if( pData && (CommandWheelMode::SCROLL == pData->GetMode()) && !pData->IsHorz() )
2159 : {
2160 0 : sal_uLong nScrollLines = pData->GetScrollLines();
2161 0 : if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2162 : {
2163 0 : nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2164 0 : if( pData->GetDelta() < 0 )
2165 0 : nScrollDY *= -1;
2166 : }
2167 : else
2168 : {
2169 0 : nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2170 0 : nScrollDY *= GetScrollBarLineSize();
2171 : }
2172 : }
2173 : }
2174 0 : break;
2175 :
2176 : case CommandEventId::AutoScroll:
2177 : {
2178 0 : const CommandScrollData* pData = rCmd.GetAutoScrollData();
2179 0 : if( pData )
2180 : {
2181 0 : nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2182 0 : nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2183 : }
2184 : }
2185 0 : break;
2186 :
2187 0 : default: break;
2188 : }
2189 :
2190 0 : if( nScrollDX || nScrollDY )
2191 : {
2192 0 : aVisRect.Top() -= nScrollDY;
2193 0 : aVisRect.Bottom() -= nScrollDY;
2194 0 : aVisRect.Left() -= nScrollDX;
2195 0 : aVisRect.Right() -= nScrollDX;
2196 0 : MakeVisible( aVisRect );
2197 0 : return true;
2198 : }
2199 0 : return false;
2200 : }
2201 :
2202 :
2203 0 : void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2204 : {
2205 : // scroll mouse event?
2206 0 : if( (rCEvt.GetCommand() == CommandEventId::Wheel) ||
2207 0 : (rCEvt.GetCommand() == CommandEventId::StartAutoScroll) ||
2208 0 : (rCEvt.GetCommand() == CommandEventId::AutoScroll) )
2209 : {
2210 0 : if( HandleScrollCommand( rCEvt ) )
2211 0 : return;
2212 : }
2213 : }
2214 :
2215 6 : void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2216 : {
2217 12 : if( !pZOrderList->empty()
2218 6 : && pEntry != pZOrderList->back()
2219 : ) {
2220 54 : for(
2221 6 : SvxIconChoiceCtrlEntryList_impl::iterator it = pZOrderList->begin();
2222 36 : it != pZOrderList->end();
2223 : ++it
2224 : ) {
2225 18 : if ( *it == pEntry )
2226 : {
2227 6 : pZOrderList->erase( it );
2228 6 : pZOrderList->push_back( pEntry );
2229 6 : break;
2230 : }
2231 : }
2232 : }
2233 6 : }
2234 :
2235 0 : void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2236 : {
2237 0 : if( rRect.Bottom() >= aVirtOutputSize.Height() )
2238 0 : rRect.Bottom() = aVirtOutputSize.Height() - 1;
2239 0 : if( rRect.Right() >= aVirtOutputSize.Width() )
2240 0 : rRect.Right() = aVirtOutputSize.Width() - 1;
2241 0 : if( rRect.Top() < 0 )
2242 0 : rRect.Top() = 0;
2243 0 : if( rRect.Left() < 0 )
2244 0 : rRect.Left() = 0;
2245 0 : }
2246 :
2247 : // rRect: area of the document (in document coordinates) that we want to make
2248 : // visible
2249 : // bScrBar == true: rectangle was calculated because of a scrollbar event
2250 :
2251 0 : void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, bool bScrBar,
2252 : bool bCallRectChangedHdl )
2253 : {
2254 0 : Rectangle aVirtRect( rRect );
2255 0 : ClipAtVirtOutRect( aVirtRect );
2256 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
2257 : // convert to document coordinate
2258 0 : aOrigin *= -1;
2259 0 : Rectangle aOutputArea( GetOutputRect() );
2260 0 : if( aOutputArea.IsInside( aVirtRect ) )
2261 0 : return; // is already visible
2262 :
2263 : long nDy;
2264 0 : if( aVirtRect.Top() < aOutputArea.Top() )
2265 : {
2266 : // scroll up (nDy < 0)
2267 0 : nDy = aVirtRect.Top() - aOutputArea.Top();
2268 : }
2269 0 : else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2270 : {
2271 : // scroll down (nDy > 0)
2272 0 : nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2273 : }
2274 : else
2275 0 : nDy = 0;
2276 :
2277 : long nDx;
2278 0 : if( aVirtRect.Left() < aOutputArea.Left() )
2279 : {
2280 : // scroll to the left (nDx < 0)
2281 0 : nDx = aVirtRect.Left() - aOutputArea.Left();
2282 : }
2283 0 : else if( aVirtRect.Right() > aOutputArea.Right() )
2284 : {
2285 : // scroll to the right (nDx > 0)
2286 0 : nDx = aVirtRect.Right() - aOutputArea.Right();
2287 : }
2288 : else
2289 0 : nDx = 0;
2290 :
2291 0 : aOrigin.X() += nDx;
2292 0 : aOrigin.Y() += nDy;
2293 0 : aOutputArea.SetPos( aOrigin );
2294 0 : if( GetUpdateMode() )
2295 : {
2296 0 : HideDDIcon();
2297 0 : pView->Update();
2298 0 : ShowCursor( false );
2299 : }
2300 :
2301 : // invert origin for SV (so we can scroll/paint using document coordinates)
2302 0 : aOrigin *= -1;
2303 0 : SetOrigin( aOrigin );
2304 :
2305 0 : bool bScrollable = pView->GetBackground().IsScrollable();
2306 :
2307 0 : if( bScrollable && GetUpdateMode() )
2308 : {
2309 : // scroll in reverse direction!
2310 0 : pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2311 0 : ScrollFlags::NoChildren | ScrollFlags::UseClipRegion | ScrollFlags::Clip );
2312 : }
2313 : else
2314 0 : pView->Invalidate(InvalidateFlags::NoChildren);
2315 :
2316 0 : if( aHorSBar->IsVisible() || aVerSBar->IsVisible() )
2317 : {
2318 0 : if( !bScrBar )
2319 : {
2320 0 : aOrigin *= -1;
2321 : // correct thumbs
2322 0 : if(aHorSBar->IsVisible() && aHorSBar->GetThumbPos() != aOrigin.X())
2323 0 : aHorSBar->SetThumbPos( aOrigin.X() );
2324 0 : if(aVerSBar->IsVisible() && aVerSBar->GetThumbPos() != aOrigin.Y())
2325 0 : aVerSBar->SetThumbPos( aOrigin.Y() );
2326 : }
2327 : }
2328 :
2329 0 : if( GetUpdateMode() )
2330 0 : ShowCursor( true );
2331 :
2332 : // check if we still need scrollbars
2333 0 : CheckScrollBars();
2334 0 : if( bScrollable && GetUpdateMode() )
2335 0 : pView->Update();
2336 :
2337 : // If the requested area can not be made completely visible, the
2338 : // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2339 : // if only few pixels of the lower border are invisible, but a scrollbar has
2340 : // a larger line size.
2341 0 : if( bCallRectChangedHdl || GetOutputRect() != rRect )
2342 0 : VisRectChanged();
2343 : }
2344 :
2345 186 : sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2346 : {
2347 186 : if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2348 0 : return 1;
2349 186 : return nSelectionCount;
2350 : }
2351 :
2352 0 : void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2353 : {
2354 : bool bSel;
2355 0 : if( pEntry->IsSelected() )
2356 0 : bSel = false;
2357 : else
2358 0 : bSel = true;
2359 0 : SelectEntry( pEntry, bSel, true, true );
2360 0 : }
2361 :
2362 6 : void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2363 : bool bPaintSync )
2364 : {
2365 6 : ClearSelectedRectList();
2366 :
2367 : // TODO: work through z-order list, if necessary!
2368 :
2369 6 : size_t nCount = aEntries.size();
2370 30 : for( size_t nCur = 0; nCur < nCount; nCur++ )
2371 : {
2372 24 : SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
2373 24 : if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2374 0 : SelectEntry( pEntry, false, true, true, bPaintSync );
2375 : }
2376 6 : pAnchor = 0;
2377 6 : nFlags &= (~F_ADD_MODE);
2378 6 : }
2379 :
2380 14 : Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2381 : {
2382 14 : Size aMinSize( aImageSize );
2383 14 : aMinSize.Width() += 2 * LROFFS_BOUND;
2384 14 : aMinSize.Height() += TBOFFS_BOUND; // single offset is enough (FileDlg)
2385 14 : OUString aStrDummy( "XXX" );
2386 14 : Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2387 14 : if( nWinBits & WB_ICON )
2388 : {
2389 14 : aMinSize.Height() += VER_DIST_BMP_STRING;
2390 14 : aMinSize.Height() += aTextSize.Height();
2391 : }
2392 : else
2393 : {
2394 0 : aMinSize.Width() += HOR_DIST_BMP_STRING;
2395 0 : aMinSize.Width() += aTextSize.Width();
2396 : }
2397 14 : return aMinSize;
2398 : }
2399 :
2400 14 : void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
2401 : {
2402 14 : Size aSize( rSize );
2403 14 : Size aMinSize( GetMinGrid() );
2404 14 : if( aSize.Width() < aMinSize.Width() )
2405 0 : aSize.Width() = aMinSize.Width();
2406 14 : if( aSize.Height() < aMinSize.Height() )
2407 0 : aSize.Height() = aMinSize.Height();
2408 :
2409 14 : nGridDX = aSize.Width();
2410 : // HACK: Detail mode is not yet fully implemented, this workaround makes it
2411 : // fly with a single column
2412 14 : if( nWinBits & WB_DETAILS )
2413 : {
2414 0 : const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
2415 0 : if( pCol )
2416 0 : const_cast<SvxIconChoiceCtrlColumnInfo*>(pCol)->SetWidth( nGridDX );
2417 : }
2418 14 : nGridDY = aSize.Height();
2419 14 : SetDefaultTextSize();
2420 14 : }
2421 :
2422 : // Calculates the maximum size that the text rectangle may use within its
2423 : // bounding rectangle. In WB_ICON mode with IcnShowTextFull, Bottom is set to
2424 : // LONG_MAX.
2425 :
2426 48 : Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
2427 : {
2428 48 : Rectangle aBoundRect;
2429 : // avoid infinite recursion: don't calculate the bounding rectangle here
2430 48 : if( IsBoundingRectValid( pEntry->aRect ) )
2431 48 : aBoundRect = pEntry->aRect;
2432 : else
2433 0 : aBoundRect = pEntry->aGridRect;
2434 :
2435 : Rectangle aBmpRect( const_cast<SvxIconChoiceCtrl_Impl*>(this)->CalcBmpRect(
2436 48 : const_cast<SvxIconChoiceCtrlEntry*>(pEntry) ) );
2437 48 : if( nWinBits & WB_ICON )
2438 : {
2439 48 : aBoundRect.Top() = aBmpRect.Bottom();
2440 48 : aBoundRect.Top() += VER_DIST_BMP_STRING;
2441 48 : if( aBoundRect.Top() > aBoundRect.Bottom())
2442 0 : aBoundRect.Top() = aBoundRect.Bottom();
2443 48 : aBoundRect.Left() += LROFFS_BOUND;
2444 48 : aBoundRect.Left()++;
2445 48 : aBoundRect.Right() -= LROFFS_BOUND;
2446 48 : aBoundRect.Right()--;
2447 48 : if( aBoundRect.Left() > aBoundRect.Right())
2448 0 : aBoundRect.Left() = aBoundRect.Right();
2449 48 : if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
2450 0 : aBoundRect.Bottom() = LONG_MAX;
2451 : }
2452 : else
2453 : {
2454 0 : aBoundRect.Left() = aBmpRect.Right();
2455 0 : aBoundRect.Left() += HOR_DIST_BMP_STRING;
2456 0 : aBoundRect.Right() -= LROFFS_BOUND;
2457 0 : if( aBoundRect.Left() > aBoundRect.Right() )
2458 0 : aBoundRect.Left() = aBoundRect.Right();
2459 0 : long nHeight = aBoundRect.GetSize().Height();
2460 0 : nHeight = nHeight - aDefaultTextSize.Height();
2461 0 : nHeight /= 2;
2462 0 : aBoundRect.Top() += nHeight;
2463 0 : aBoundRect.Bottom() -= nHeight;
2464 : }
2465 48 : return aBoundRect;
2466 : }
2467 :
2468 28 : void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2469 : {
2470 28 : long nDY = nGridDY;
2471 28 : nDY -= aImageSize.Height();
2472 28 : nDY -= VER_DIST_BMP_STRING;
2473 28 : nDY -= 2 * TBOFFS_BOUND;
2474 28 : if (nDY <= 0)
2475 0 : nDY = 2;
2476 :
2477 28 : long nDX = nGridDX;
2478 28 : nDX -= 2 * LROFFS_BOUND;
2479 28 : nDX -= 2;
2480 28 : if (nDX <= 0)
2481 0 : nDX = 2;
2482 :
2483 28 : long nHeight = pView->GetTextHeight();
2484 28 : if (nDY < nHeight)
2485 0 : nDY = nHeight;
2486 28 : aDefaultTextSize = Size(nDX, nDY);
2487 28 : }
2488 :
2489 :
2490 260 : void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
2491 : {
2492 260 : pEntry->aRect = pEntry->aGridRect;
2493 260 : Size aSize( CalcBoundingSize( pEntry ) );
2494 260 : if( nWinBits & WB_ICON )
2495 : {
2496 : // center horizontally
2497 260 : long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
2498 260 : pEntry->aRect.Left() += nBorder / 2;
2499 260 : pEntry->aRect.Right() -= nBorder / 2;
2500 : }
2501 : // center vertically
2502 260 : pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
2503 260 : }
2504 :
2505 :
2506 : // The deltas are the offsets by which the view is moved on the document.
2507 : // left, up: offsets < 0
2508 : // right, down: offsets > 0
2509 0 : void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, bool bScrollBar )
2510 : {
2511 0 : const MapMode& rMapMode = pView->GetMapMode();
2512 0 : Point aOrigin( rMapMode.GetOrigin() );
2513 : // convert to document coordinate
2514 0 : aOrigin *= -1;
2515 0 : aOrigin.Y() += nDeltaY;
2516 0 : aOrigin.X() += nDeltaX;
2517 0 : Rectangle aRect( aOrigin, aOutputSize );
2518 0 : MakeVisible( aRect, bScrollBar );
2519 0 : }
2520 :
2521 :
2522 1040 : const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
2523 : IcnViewFieldType eItem ) const
2524 : {
2525 1040 : if (eItem == IcnViewFieldTypeText)
2526 1040 : return aDefaultTextSize;
2527 0 : return aImageSize;
2528 : }
2529 :
2530 24 : Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
2531 : {
2532 24 : Rectangle aTextRect( CalcTextRect( pEntry ) );
2533 24 : Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
2534 : return Rectangle(
2535 72 : aBoundRect.Left(), aBoundRect.Top() - 1, aBoundRect.Right() - 1,
2536 96 : aTextRect.Bottom() + 1);
2537 : }
2538 :
2539 : // the hot spot is the inner 50% of the rectangle
2540 0 : static Rectangle GetHotSpot( const Rectangle& rRect )
2541 : {
2542 0 : Rectangle aResult( rRect );
2543 0 : aResult.Justify();
2544 0 : Size aSize( rRect.GetSize() );
2545 0 : long nDelta = aSize.Width() / 4;
2546 0 : aResult.Left() += nDelta;
2547 0 : aResult.Right() -= nDelta;
2548 0 : nDelta = aSize.Height() / 4;
2549 0 : aResult.Top() += nDelta;
2550 0 : aResult.Bottom() -= nDelta;
2551 0 : return aResult;
2552 : }
2553 :
2554 0 : void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
2555 : bool bAdd, std::vector<Rectangle*>* pOtherRects )
2556 : {
2557 : DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2558 0 : Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2559 0 : aRect.Union( GetEntryBoundRect( pEntry2 ) );
2560 0 : SelectRect( aRect, bAdd, pOtherRects );
2561 0 : }
2562 :
2563 0 : void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, bool bAdd,
2564 : std::vector<Rectangle*>* pOtherRects )
2565 : {
2566 0 : aCurSelectionRect = rRect;
2567 0 : if( !pZOrderList || !pZOrderList->size() )
2568 0 : return;
2569 :
2570 : // set flag, so ToTop won't be called in Select
2571 0 : bool bAlreadySelectingRect = (nFlags & F_SELECTING_RECT) != 0;
2572 0 : nFlags |= F_SELECTING_RECT;
2573 :
2574 0 : CheckBoundingRects();
2575 0 : pView->Update();
2576 0 : const size_t nCount = pZOrderList->size();
2577 :
2578 0 : Rectangle aRect( rRect );
2579 0 : aRect.Justify();
2580 0 : bool bCalcOverlap = (bAdd && pOtherRects && !pOtherRects->empty());
2581 :
2582 0 : bool bResetClipRegion = false;
2583 0 : if( !pView->IsClipRegion() )
2584 : {
2585 0 : bResetClipRegion = true;
2586 0 : pView->SetClipRegion(vcl::Region(GetOutputRect()));
2587 : }
2588 :
2589 0 : for( size_t nPos = 0; nPos < nCount; nPos++ )
2590 : {
2591 0 : SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nPos ];
2592 :
2593 0 : if( !IsBoundingRectValid( pEntry->aRect ))
2594 0 : FindBoundingRect( pEntry );
2595 0 : Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
2596 0 : bool bSelected = pEntry->IsSelected();
2597 :
2598 : bool bOverlaps;
2599 0 : if( bCalcOverlap )
2600 0 : bOverlaps = IsOver( pOtherRects, aBoundRect );
2601 : else
2602 0 : bOverlaps = false;
2603 0 : bool bOver = aRect.IsOver( aBoundRect );
2604 :
2605 0 : if( bOver && !bOverlaps )
2606 : {
2607 : // is inside the new selection rectangle and outside of any old one
2608 : // => select
2609 0 : if( !bSelected )
2610 0 : SelectEntry( pEntry, true, true, true );
2611 : }
2612 0 : else if( !bAdd )
2613 : {
2614 : // is outside of the selection rectangle
2615 : // => deselect
2616 0 : if( bSelected )
2617 0 : SelectEntry( pEntry, false, true, true );
2618 : }
2619 0 : else if( bAdd && bOverlaps )
2620 : {
2621 : // The entry is inside an old (=>span multiple rectangles with Ctrl)
2622 : // selection rectangle.
2623 :
2624 : // There is still a bug here! The selection status of an entry in a
2625 : // previous rectangle has to be restored, if it was touched by the
2626 : // current selection rectangle but is not inside it any more.
2627 : // For simplicity's sake, let's assume that all entries in the old
2628 : // rectangles were correctly selected. It is wrong to just deselect
2629 : // the intersection.
2630 : // Possible solution: remember a snapshot of the selection before
2631 : // spanning the rectangle.
2632 0 : if( aBoundRect.IsOver( rRect))
2633 : {
2634 : // deselect intersection between old rectangles and current rectangle
2635 0 : if( bSelected )
2636 0 : SelectEntry( pEntry, false, true, true );
2637 : }
2638 : else
2639 : {
2640 : // select entry of an old rectangle
2641 0 : if( !bSelected )
2642 0 : SelectEntry( pEntry, true, true, true );
2643 : }
2644 : }
2645 0 : else if( !bOver && bSelected )
2646 : {
2647 : // this entry is completely outside the rectangle => deselect it
2648 0 : SelectEntry( pEntry, false, true, true );
2649 : }
2650 : }
2651 :
2652 0 : if( !bAlreadySelectingRect )
2653 0 : nFlags &= ~F_SELECTING_RECT;
2654 :
2655 0 : pView->Update();
2656 0 : if( bResetClipRegion )
2657 0 : pView->SetClipRegion();
2658 : }
2659 :
2660 0 : void SvxIconChoiceCtrl_Impl::SelectRange(
2661 : SvxIconChoiceCtrlEntry* pStart,
2662 : SvxIconChoiceCtrlEntry* pEnd,
2663 : bool bAdd )
2664 : {
2665 0 : sal_uLong nFront = GetEntryListPos( pStart );
2666 0 : sal_uLong nBack = GetEntryListPos( pEnd );
2667 0 : sal_uLong nFirst = std::min( nFront, nBack );
2668 0 : sal_uLong nLast = std::max( nFront, nBack );
2669 : sal_uLong i;
2670 : SvxIconChoiceCtrlEntry* pEntry;
2671 :
2672 0 : if ( ! bAdd )
2673 : {
2674 : // deselect everything before the first entry if not in
2675 : // adding mode
2676 0 : for ( i=0; i<nFirst; i++ )
2677 : {
2678 0 : pEntry = GetEntry( i );
2679 0 : if( pEntry->IsSelected() )
2680 0 : SelectEntry( pEntry, false, true, true, true );
2681 : }
2682 : }
2683 :
2684 : // select everything between nFirst and nLast
2685 0 : for ( i=nFirst; i<=nLast; i++ )
2686 : {
2687 0 : pEntry = GetEntry( i );
2688 0 : if( ! pEntry->IsSelected() )
2689 0 : SelectEntry( pEntry, true, true, true, true );
2690 : }
2691 :
2692 0 : if ( ! bAdd )
2693 : {
2694 : // deselect everything behind the last entry if not in
2695 : // adding mode
2696 0 : sal_uLong nEnd = GetEntryCount();
2697 0 : for ( ; i<nEnd; i++ )
2698 : {
2699 0 : pEntry = GetEntry( i );
2700 0 : if( pEntry->IsSelected() )
2701 0 : SelectEntry( pEntry, false, true, true, true );
2702 : }
2703 : }
2704 0 : }
2705 :
2706 0 : bool SvxIconChoiceCtrl_Impl::IsOver( std::vector<Rectangle*>* pRectList, const Rectangle& rBoundRect )
2707 : {
2708 0 : const sal_uInt16 nCount = pRectList->size();
2709 0 : for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2710 : {
2711 0 : Rectangle* pRect = (*pRectList)[ nCur ];
2712 0 : if( rBoundRect.IsOver( *pRect ))
2713 0 : return true;
2714 : }
2715 0 : return false;
2716 : }
2717 :
2718 0 : void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
2719 : SvxIconChoiceCtrlEntry* pEntry2 )
2720 : {
2721 : DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2722 0 : Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2723 0 : aRect.Union( GetEntryBoundRect( pEntry2 ) );
2724 0 : AddSelectedRect( aRect );
2725 0 : }
2726 :
2727 0 : void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
2728 : {
2729 0 : Rectangle* pRect = new Rectangle( rRect );
2730 0 : pRect->Justify();
2731 0 : aSelectedRectList.push_back( pRect );
2732 0 : }
2733 :
2734 11 : void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2735 : {
2736 11 : const sal_uInt16 nCount = aSelectedRectList.size();
2737 11 : for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2738 : {
2739 0 : Rectangle* pRect = aSelectedRectList[ nCur ];
2740 0 : delete pRect;
2741 : }
2742 11 : aSelectedRectList.clear();
2743 11 : }
2744 :
2745 0 : IMPL_LINK_NOARG_TYPED(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, Idle *, void)
2746 : {
2747 0 : aAutoArrangeIdle.Stop();
2748 0 : Arrange( IsAutoArrange() );
2749 0 : }
2750 :
2751 6 : IMPL_LINK_NOARG_TYPED(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, Idle *, void)
2752 : {
2753 3 : aVisRectChangedIdle.Stop();
2754 3 : pView->VisibleRectChanged();
2755 3 : }
2756 :
2757 6 : IMPL_LINK_NOARG_TYPED(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, Idle *, void)
2758 : {
2759 3 : aDocRectChangedIdle.Stop();
2760 3 : pView->DocumentRectChanged();
2761 3 : }
2762 :
2763 0 : bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
2764 : {
2765 0 : Rectangle aRect( CalcTextRect( pEntry ));
2766 0 : if( aRect.IsInside( rDocPos ) )
2767 0 : return true;
2768 0 : return false;
2769 : }
2770 :
2771 0 : IMPL_LINK_NOARG_TYPED(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Idle *, void)
2772 : {
2773 0 : SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
2774 0 : if( bEntryEditingEnabled && pEntry &&
2775 0 : pEntry->IsSelected())
2776 : {
2777 0 : EditEntry( pEntry );
2778 : }
2779 0 : }
2780 :
2781 :
2782 :
2783 : // Function to align entries to the grid
2784 :
2785 :
2786 : // pStart == 0: align all entries
2787 : // else: align all entries of the row from pStart on (including pStart)
2788 0 : void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
2789 : {
2790 0 : IconChoiceMap aLists;
2791 0 : pImpCursor->CreateGridAjustData( aLists, pStart );
2792 0 : for (IconChoiceMap::const_iterator iter = aLists.begin();
2793 0 : iter != aLists.end(); ++iter)
2794 : {
2795 0 : AdjustAtGrid(iter->second, pStart);
2796 : }
2797 0 : IcnCursor_Impl::DestroyGridAdjustData( aLists );
2798 0 : CheckScrollBars();
2799 0 : }
2800 :
2801 : // align a row, might expand width, doesn't break the line
2802 0 : void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvxIconChoiceCtrlEntryPtrVec& rRow, SvxIconChoiceCtrlEntry* pStart )
2803 : {
2804 0 : if( rRow.empty() )
2805 0 : return;
2806 :
2807 : bool bGo;
2808 0 : if( !pStart )
2809 0 : bGo = true;
2810 : else
2811 0 : bGo = false;
2812 :
2813 0 : long nCurRight = 0;
2814 0 : for( size_t nCur = 0; nCur < rRow.size(); nCur++ )
2815 : {
2816 0 : SvxIconChoiceCtrlEntry* pCur = rRow[ nCur ];
2817 0 : if( !bGo && pCur == pStart )
2818 0 : bGo = true;
2819 :
2820 : // SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
2821 : // Decisive (for our eye) is the bitmap, else, the entry might jump too
2822 : // much within long texts.
2823 0 : const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
2824 0 : Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
2825 0 : if( bGo && !pCur->IsPosLocked() )
2826 : {
2827 0 : long nWidth = aCenterRect.GetSize().Width();
2828 0 : Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
2829 0 : while( aNewPos.X() < nCurRight )
2830 0 : aNewPos.X() += nGridDX;
2831 0 : if( aNewPos != rBoundRect.TopLeft() )
2832 : {
2833 0 : SetEntryPos( pCur, aNewPos );
2834 0 : pCur->SetFlags( SvxIconViewFlags::POS_MOVED );
2835 0 : nFlags |= F_MOVED_ENTRIES;
2836 : }
2837 0 : nCurRight = aNewPos.X() + nWidth;
2838 : }
2839 : else
2840 : {
2841 0 : nCurRight = rBoundRect.Right();
2842 : }
2843 : }
2844 : }
2845 :
2846 : // Aligns a rectangle to the grid, but doesn't guarantee that the new position
2847 : // is vacant. The position can be used for SetEntryPos. The CenterRect describes
2848 : // a part of the bounding rectangle that is used for calculating the target
2849 : // rectangle.
2850 0 : Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
2851 : const Rectangle& rBoundRect ) const
2852 : {
2853 0 : Point aPos( rCenterRect.TopLeft() );
2854 0 : Size aSize( rCenterRect.GetSize() );
2855 :
2856 0 : aPos.X() -= LROFFS_WINBORDER;
2857 0 : aPos.Y() -= TBOFFS_WINBORDER;
2858 :
2859 : // align (the center of the rectangle is the reference)
2860 0 : short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
2861 0 : short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
2862 0 : aPos.X() = nGridX * nGridDX;
2863 0 : aPos.Y() = nGridY * nGridDY;
2864 : // horizontal center
2865 0 : aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
2866 :
2867 0 : aPos.X() += LROFFS_WINBORDER;
2868 0 : aPos.Y() += TBOFFS_WINBORDER;
2869 :
2870 0 : return aPos;
2871 : }
2872 :
2873 : #ifdef DBG_UTIL
2874 : void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
2875 : {
2876 : if( !pEntry )
2877 : {
2878 : if( eTextMode != eMode )
2879 : {
2880 : if( eTextMode == IcnShowTextDontKnow )
2881 : eTextMode = IcnShowTextShort;
2882 : eTextMode = eMode;
2883 : Arrange( true );
2884 : }
2885 : }
2886 : else
2887 : {
2888 : if( pEntry->eTextMode != eMode )
2889 : {
2890 : pEntry->eTextMode = eMode;
2891 : InvalidateEntry( pEntry );
2892 : pView->Invalidate( GetEntryBoundRect( pEntry ) );
2893 : AdjustVirtSize( pEntry->aRect );
2894 : }
2895 : }
2896 : }
2897 : #endif
2898 :
2899 48 : SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
2900 : {
2901 : DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
2902 48 : SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
2903 48 : if( eMode == IcnShowTextDontKnow )
2904 0 : return eTextMode;
2905 48 : return eMode;
2906 : }
2907 :
2908 :
2909 :
2910 : // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
2911 : // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
2912 : // a gray focusrect on a gray background !!!
2913 :
2914 15 : void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
2915 : {
2916 15 : Color aBkgColor(pView->GetBackground().GetColor());
2917 15 : Color aPenColor;
2918 15 : sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
2919 15 : if (nColor > 128)
2920 15 : aPenColor.SetColor(COL_BLACK);
2921 : else
2922 0 : aPenColor.SetColor(COL_WHITE);
2923 :
2924 15 : aFocus.bOn = true;
2925 15 : aFocus.aPenColor = aPenColor;
2926 15 : aFocus.aRect = rRect;
2927 15 : }
2928 :
2929 3 : void SvxIconChoiceCtrl_Impl::DrawFocusRect(vcl::RenderContext& rRenderContext)
2930 : {
2931 3 : rRenderContext.SetLineColor(aFocus.aPenColor);
2932 3 : rRenderContext.SetFillColor();
2933 3 : Polygon aPolygon (aFocus.aRect);
2934 :
2935 6 : LineInfo aLineInfo(LINE_DASH);
2936 :
2937 3 : aLineInfo.SetDashLen(1);
2938 3 : aLineInfo.SetDotLen(1L);
2939 3 : aLineInfo.SetDistance(1L);
2940 3 : aLineInfo.SetDotCount(1);
2941 :
2942 6 : rRenderContext.DrawPolyLine(aPolygon, aLineInfo);
2943 3 : }
2944 :
2945 0 : bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
2946 : {
2947 0 : bool bRet = false;
2948 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
2949 0 : size_t nEntryCount = GetEntryCount();
2950 0 : for ( size_t i = 0; i < nEntryCount; ++i )
2951 : {
2952 0 : if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
2953 : {
2954 0 : bRet = true;
2955 0 : rPos = i;
2956 0 : break;
2957 : }
2958 : }
2959 :
2960 0 : return bRet;
2961 : }
2962 :
2963 :
2964 :
2965 :
2966 12 : IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
2967 : {
2968 6 : if( nId == EVENTID_ADJUST_SCROLLBARS )
2969 : {
2970 6 : nUserEventAdjustScrBars = 0;
2971 6 : AdjustScrollBars();
2972 : }
2973 0 : else if( nId == EVENTID_SHOW_CURSOR )
2974 : {
2975 0 : nUserEventShowCursor = 0;
2976 0 : ShowCursor( true );
2977 : }
2978 6 : return 0;
2979 : }
2980 :
2981 17 : void SvxIconChoiceCtrl_Impl::CancelUserEvents()
2982 : {
2983 17 : if( nUserEventAdjustScrBars )
2984 : {
2985 2 : Application::RemoveUserEvent( nUserEventAdjustScrBars );
2986 2 : nUserEventAdjustScrBars = 0;
2987 : }
2988 17 : if( nUserEventShowCursor )
2989 : {
2990 0 : Application::RemoveUserEvent( nUserEventShowCursor );
2991 0 : nUserEventShowCursor = 0;
2992 : }
2993 17 : }
2994 :
2995 0 : void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
2996 : {
2997 0 : if( pEntry == pCursor )
2998 0 : ShowCursor( false );
2999 0 : pView->Invalidate( pEntry->aRect );
3000 0 : Center( pEntry );
3001 0 : pView->Invalidate( pEntry->aRect );
3002 0 : if( pEntry == pCursor )
3003 0 : ShowCursor( true );
3004 0 : }
3005 :
3006 0 : void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3007 : {
3008 : DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3009 0 : if( !pEntry )
3010 0 : return;
3011 :
3012 0 : StopEntryEditing( true );
3013 0 : pEdit.disposeAndClear();
3014 0 : SetNoSelection();
3015 :
3016 0 : pCurEditedEntry = pEntry;
3017 0 : OUString aEntryText( SvtIconChoiceCtrl::GetEntryText( pEntry, true ) );
3018 0 : Rectangle aRect( CalcTextRect( pEntry, 0, true, &aEntryText ) );
3019 0 : MakeVisible( aRect );
3020 0 : Point aPos( aRect.TopLeft() );
3021 0 : aPos = pView->GetPixelPos( aPos );
3022 0 : aRect.SetPos( aPos );
3023 0 : pView->HideFocus();
3024 0 : pEdit = VclPtr<IcnViewEdit_Impl>::Create(
3025 :
3026 : pView,
3027 : aRect.TopLeft(),
3028 : aRect.GetSize(),
3029 : aEntryText,
3030 0 : LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3031 : }
3032 :
3033 0 : IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, TextEditEndedHdl)
3034 : {
3035 : DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3036 0 : if( !pEdit )
3037 : {
3038 0 : pCurEditedEntry = 0;
3039 0 : return 0;
3040 : }
3041 : DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3042 :
3043 0 : if( !pCurEditedEntry )
3044 : {
3045 0 : pEdit->Hide();
3046 0 : if( pEdit->IsGrabFocus() )
3047 0 : pView->GrabFocus();
3048 0 : return 0;
3049 : }
3050 :
3051 0 : OUString aText;
3052 0 : if ( !pEdit->EditingCanceled() )
3053 0 : aText = pEdit->GetText();
3054 : else
3055 0 : aText = pEdit->GetSavedValue();
3056 :
3057 0 : InvalidateEntry( pCurEditedEntry );
3058 0 : if( !GetSelectionCount() )
3059 0 : SelectEntry( pCurEditedEntry, true );
3060 :
3061 0 : pEdit->Hide();
3062 0 : if( pEdit->IsGrabFocus() )
3063 0 : pView->GrabFocus();
3064 : // The edit can not be deleted here, because it is not within a handler. It
3065 : // will be deleted in the dtor or in the next EditEntry.
3066 0 : pCurEditedEntry = 0;
3067 0 : return 0;
3068 : }
3069 :
3070 12 : void SvxIconChoiceCtrl_Impl::StopEntryEditing( bool bCancel )
3071 : {
3072 12 : if( pEdit )
3073 0 : pEdit->StopEditing( bCancel );
3074 12 : }
3075 :
3076 186 : SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3077 : {
3078 186 : if( !GetSelectionCount() )
3079 12 : return 0;
3080 :
3081 174 : if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3082 : {
3083 0 : rPos = pView->GetEntryListPos( pCurHighlightFrame );
3084 0 : return pCurHighlightFrame;
3085 : }
3086 :
3087 174 : size_t nCount = aEntries.size();
3088 174 : if( !pHead )
3089 : {
3090 522 : for( size_t nCur = 0; nCur < nCount; nCur++ )
3091 : {
3092 522 : SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3093 522 : if( pEntry->IsSelected() )
3094 : {
3095 174 : rPos = nCur;
3096 174 : return pEntry;
3097 : }
3098 : }
3099 : }
3100 : else
3101 : {
3102 0 : SvxIconChoiceCtrlEntry* pEntry = pHead;
3103 0 : while( nCount-- )
3104 : {
3105 0 : if( pEntry->IsSelected() )
3106 : {
3107 0 : rPos = GetEntryListPos( pEntry );
3108 0 : return pEntry;
3109 : }
3110 0 : pEntry = pEntry->pflink;
3111 0 : if( nCount && pEntry == pHead )
3112 : {
3113 : OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
3114 0 : return 0;
3115 : }
3116 : }
3117 : }
3118 0 : return 0;
3119 : }
3120 :
3121 0 : void SvxIconChoiceCtrl_Impl::SelectAll( bool bSelect, bool bPaint )
3122 : {
3123 0 : bPaint = true;
3124 :
3125 0 : size_t nCount = aEntries.size();
3126 0 : for( size_t nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3127 : {
3128 0 : SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3129 0 : SelectEntry( pEntry, bSelect, true, true, bPaint );
3130 : }
3131 0 : nFlags &= (~F_ADD_MODE);
3132 0 : pAnchor = 0;
3133 0 : }
3134 :
3135 0 : IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3136 : const Size& rSize, const OUString& rData, const Link<>& rNotifyEditEnd ) :
3137 0 : MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3138 : aCallBackHdl( rNotifyEditEnd ),
3139 : bCanceled( false ),
3140 : bAlreadyInCallback( false ),
3141 0 : bGrabFocus( false )
3142 : {
3143 : // FIXME: Outside of Paint Hierarchy
3144 0 : vcl::Font aFont(pParent->GetPointFont(*this));
3145 0 : aFont.SetTransparent( false );
3146 0 : SetControlFont(aFont);
3147 0 : SetControlBackground(aFont.GetFillColor());
3148 0 : SetControlForeground(aFont.GetColor());
3149 0 : SetPosPixel(rPos);
3150 0 : SetSizePixel(CalcAdjustedSize(rSize));
3151 0 : SetText(rData);
3152 0 : SaveValue();
3153 :
3154 0 : aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, vcl::KeyCode(KEY_RETURN) );
3155 0 : aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, vcl::KeyCode(KEY_ESCAPE) );
3156 :
3157 0 : aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3158 0 : aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3159 0 : Application::InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3160 0 : Application::InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3161 0 : Show();
3162 0 : GrabFocus();
3163 0 : }
3164 :
3165 0 : IcnViewEdit_Impl::~IcnViewEdit_Impl()
3166 : {
3167 0 : disposeOnce();
3168 0 : }
3169 :
3170 0 : void IcnViewEdit_Impl::dispose()
3171 : {
3172 0 : if( !bAlreadyInCallback )
3173 : {
3174 0 : Application::RemoveAccel( &aAccReturn );
3175 0 : Application::RemoveAccel( &aAccEscape );
3176 : }
3177 0 : MultiLineEdit::dispose();
3178 0 : }
3179 :
3180 0 : void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3181 : {
3182 0 : aIdle.Stop();
3183 0 : if ( !bAlreadyInCallback )
3184 : {
3185 0 : bAlreadyInCallback = true;
3186 0 : Application::RemoveAccel( &aAccReturn );
3187 0 : Application::RemoveAccel( &aAccEscape );
3188 0 : Hide();
3189 0 : aCallBackHdl.Call( this );
3190 : }
3191 0 : }
3192 :
3193 0 : IMPL_LINK_NOARG_TYPED(IcnViewEdit_Impl, Timeout_Impl, Idle *, void)
3194 : {
3195 0 : CallCallBackHdl_Impl();
3196 0 : }
3197 :
3198 0 : IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, )
3199 : {
3200 0 : bCanceled = false;
3201 0 : bGrabFocus = true;
3202 0 : CallCallBackHdl_Impl();
3203 0 : return 1;
3204 : }
3205 :
3206 0 : IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, )
3207 : {
3208 0 : bCanceled = true;
3209 0 : bGrabFocus = true;
3210 0 : CallCallBackHdl_Impl();
3211 0 : return 1;
3212 : }
3213 :
3214 0 : void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3215 : {
3216 0 : vcl::KeyCode aCode = rKEvt.GetKeyCode();
3217 0 : sal_uInt16 nCode = aCode.GetCode();
3218 :
3219 0 : switch ( nCode )
3220 : {
3221 : case KEY_ESCAPE:
3222 0 : bCanceled = true;
3223 0 : bGrabFocus = true;
3224 0 : CallCallBackHdl_Impl();
3225 0 : break;
3226 :
3227 : case KEY_RETURN:
3228 0 : bCanceled = false;
3229 0 : bGrabFocus = true;
3230 0 : CallCallBackHdl_Impl();
3231 0 : break;
3232 :
3233 : default:
3234 0 : MultiLineEdit::KeyInput( rKEvt );
3235 : }
3236 0 : }
3237 :
3238 0 : bool IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3239 : {
3240 0 : if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
3241 : {
3242 0 : if ( !bAlreadyInCallback &&
3243 0 : ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
3244 : {
3245 0 : bCanceled = false;
3246 0 : aIdle.SetPriority(SchedulerPriority::REPAINT);
3247 0 : aIdle.SetIdleHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
3248 0 : aIdle.Start();
3249 : }
3250 : }
3251 0 : return false;
3252 : }
3253 :
3254 0 : void IcnViewEdit_Impl::StopEditing( bool bCancel )
3255 : {
3256 0 : if ( !bAlreadyInCallback )
3257 : {
3258 0 : bCanceled = bCancel;
3259 0 : CallCallBackHdl_Impl();
3260 : }
3261 0 : }
3262 :
3263 0 : sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
3264 : {
3265 0 : if( !(nFlags & F_ENTRYLISTPOS_VALID ))
3266 0 : const_cast<SvxIconChoiceCtrl_Impl*>(this)->SetListPositions();
3267 0 : return pEntry->nPos;
3268 : }
3269 :
3270 7 : void SvxIconChoiceCtrl_Impl::InitSettings()
3271 : {
3272 7 : const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
3273 :
3274 : // unit (from settings) is Point
3275 7 : vcl::Font aFont( rStyleSettings.GetFieldFont() );
3276 7 : aFont.SetColor( rStyleSettings.GetWindowTextColor() );
3277 7 : pView->SetPointFont( aFont );
3278 7 : SetDefaultTextSize();
3279 :
3280 7 : pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
3281 7 : pView->SetTextFillColor();
3282 :
3283 7 : pView->SetBackground( rStyleSettings.GetFieldColor());
3284 :
3285 7 : long nScrBarSize = rStyleSettings.GetScrollBarSize();
3286 7 : if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
3287 : {
3288 0 : nHorSBarHeight = nScrBarSize;
3289 0 : Size aSize( aHorSBar->GetSizePixel() );
3290 0 : aSize.Height() = nScrBarSize;
3291 0 : aHorSBar->Hide();
3292 0 : aHorSBar->SetSizePixel( aSize );
3293 :
3294 0 : nVerSBarWidth = nScrBarSize;
3295 0 : aSize = aVerSBar->GetSizePixel();
3296 0 : aSize.Width() = nScrBarSize;
3297 0 : aVerSBar->Hide();
3298 0 : aVerSBar->SetSizePixel( aSize );
3299 :
3300 0 : Size aOSize( pView->Control::GetOutputSizePixel() );
3301 0 : PositionScrollBars( aOSize.Width(), aOSize.Height() );
3302 0 : AdjustScrollBars();
3303 7 : }
3304 7 : }
3305 :
3306 7 : EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner ) :
3307 7 : _pOwner( pOwner )
3308 : {
3309 7 : _pOwner->pHead = 0;
3310 7 : }
3311 :
3312 10 : EntryList_Impl::~EntryList_Impl()
3313 : {
3314 5 : _pOwner->pHead = 0;
3315 5 : }
3316 :
3317 12 : void EntryList_Impl::clear()
3318 : {
3319 12 : _pOwner->pHead = 0;
3320 12 : maIconChoiceCtrlEntryList.clear();
3321 12 : }
3322 :
3323 28 : void EntryList_Impl::insert( size_t nPos, SvxIconChoiceCtrlEntry* pEntry )
3324 : {
3325 28 : if ( nPos < maIconChoiceCtrlEntryList.size() ) {
3326 0 : maIconChoiceCtrlEntryList.insert( maIconChoiceCtrlEntryList.begin() + nPos, pEntry );
3327 : } else {
3328 28 : maIconChoiceCtrlEntryList.push_back( pEntry );
3329 : }
3330 28 : if( _pOwner->pHead )
3331 0 : pEntry->SetBacklink( _pOwner->pHead->pblink );
3332 28 : }
3333 :
3334 7 : void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
3335 : {
3336 7 : if( eMode == ePositionMode )
3337 0 : return;
3338 :
3339 7 : SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
3340 7 : ePositionMode = eMode;
3341 7 : size_t nCount = aEntries.size();
3342 :
3343 7 : if( eOldMode == IcnViewPositionModeAutoArrange )
3344 : {
3345 : // when positioning moved entries "hard", there are problems with
3346 : // unwanted overlaps, as these entries aren't taken into account in
3347 : // Arrange.
3348 0 : if( aEntries.size() )
3349 0 : aAutoArrangeIdle.Start();
3350 0 : return;
3351 : }
3352 :
3353 7 : if( ePositionMode == IcnViewPositionModeAutoArrange )
3354 : {
3355 7 : for( size_t nCur = 0; nCur < nCount; nCur++ )
3356 : {
3357 0 : SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3358 0 : if( pEntry->GetFlags() & SvxIconViewFlags(SvxIconViewFlags::POS_LOCKED | SvxIconViewFlags::POS_MOVED))
3359 0 : SetEntryPos(pEntry, GetEntryBoundRect( pEntry ).TopLeft());
3360 : }
3361 :
3362 7 : if( aEntries.size() )
3363 0 : aAutoArrangeIdle.Start();
3364 : }
3365 0 : else if( ePositionMode == IcnViewPositionModeAutoAdjust )
3366 : {
3367 0 : AdjustEntryAtGrid( 0 );
3368 : }
3369 : }
3370 :
3371 0 : void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3372 : SvxIconChoiceCtrlEntry* pPredecessor )
3373 : {
3374 0 : if( !IsAutoArrange() )
3375 0 : return;
3376 :
3377 0 : if( pEntry == pPredecessor )
3378 0 : return;
3379 :
3380 0 : sal_uLong nPos1 = GetEntryListPos( pEntry );
3381 0 : if( !pHead )
3382 : {
3383 0 : if( pPredecessor )
3384 : {
3385 0 : sal_uLong nPos2 = GetEntryListPos( pPredecessor );
3386 0 : if( nPos1 == (nPos2 + 1) )
3387 0 : return; // is already the predecessor
3388 : }
3389 0 : else if( !nPos1 )
3390 0 : return;
3391 : }
3392 :
3393 0 : if( !pHead )
3394 0 : InitPredecessors();
3395 :
3396 0 : if( !pPredecessor && pHead == pEntry )
3397 0 : return; // is already the first one
3398 :
3399 0 : bool bSetHead = false;
3400 0 : if( !pPredecessor )
3401 : {
3402 0 : bSetHead = true;
3403 0 : pPredecessor = pHead->pblink;
3404 : }
3405 0 : if( pEntry == pHead )
3406 : {
3407 0 : pHead = pHead->pflink;
3408 0 : bSetHead = false;
3409 : }
3410 0 : if( pEntry != pPredecessor )
3411 : {
3412 0 : pEntry->Unlink();
3413 0 : pEntry->SetBacklink( pPredecessor );
3414 : }
3415 0 : if( bSetHead )
3416 0 : pHead = pEntry;
3417 0 : pEntry->SetFlags( SvxIconViewFlags::PRED_SET );
3418 0 : aAutoArrangeIdle.Start();
3419 : }
3420 :
3421 0 : SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3422 : const Point& rPosTopLeft )
3423 : {
3424 0 : Point aPos( rPosTopLeft ); //TopLeft
3425 0 : Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
3426 0 : Point aNewPos( aCenterRect.Center() );
3427 0 : sal_uLong nGrid = GetPredecessorGrid( aNewPos );
3428 0 : size_t nCount = aEntries.size();
3429 0 : if( nGrid == ULONG_MAX )
3430 0 : return 0;
3431 0 : if( nGrid >= nCount )
3432 0 : nGrid = nCount - 1;
3433 0 : if( !pHead )
3434 0 : return aEntries[ nGrid ];
3435 :
3436 0 : SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
3437 : // TODO: go through list from the end if nGrid > nCount/2
3438 0 : for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
3439 0 : pCur = pCur->pflink;
3440 :
3441 0 : return pCur;
3442 : }
3443 :
3444 0 : sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
3445 : {
3446 0 : Point aPos( rPos );
3447 0 : aPos.X() -= LROFFS_WINBORDER;
3448 0 : aPos.Y() -= TBOFFS_WINBORDER;
3449 0 : long nMaxCol = aVirtOutputSize.Width() / nGridDX;
3450 0 : if( nMaxCol )
3451 0 : nMaxCol--;
3452 0 : long nGridX = aPos.X() / nGridDX;
3453 0 : if( nGridX > nMaxCol )
3454 0 : nGridX = nMaxCol;
3455 0 : long nGridY = aPos.Y() / nGridDY;
3456 0 : long nGridsX = aOutputSize.Width() / nGridDX;
3457 0 : sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
3458 0 : long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
3459 0 : if( rPos.X() < nMiddle )
3460 : {
3461 0 : if( !nGrid )
3462 0 : nGrid = ULONG_MAX;
3463 : else
3464 0 : nGrid--;
3465 : }
3466 0 : return nGrid;
3467 : }
3468 :
3469 0 : bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
3470 : {
3471 0 : if ( !(rHEvt.GetMode() & HelpEventMode::QUICK ) )
3472 0 : return false;
3473 :
3474 0 : Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
3475 0 : aPos -= pView->GetMapMode().GetOrigin();
3476 0 : SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, true );
3477 :
3478 0 : if ( !pEntry )
3479 0 : return false;
3480 :
3481 0 : OUString sQuickHelpText = pEntry->GetQuickHelpText();
3482 0 : OUString aEntryText( SvtIconChoiceCtrl::GetEntryText( pEntry, false ) );
3483 0 : Rectangle aTextRect( CalcTextRect( pEntry, 0, false, &aEntryText ) );
3484 0 : if ( ( !aTextRect.IsInside( aPos ) || aEntryText.isEmpty() ) && sQuickHelpText.isEmpty() )
3485 0 : return false;
3486 :
3487 0 : Rectangle aOptTextRect( aTextRect );
3488 0 : aOptTextRect.Bottom() = LONG_MAX;
3489 0 : DrawTextFlags nNewFlags = nCurTextDrawFlags;
3490 0 : nNewFlags &= ~DrawTextFlags( DrawTextFlags::Clip | DrawTextFlags::EndEllipsis );
3491 0 : aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
3492 0 : if ( aOptTextRect != aTextRect || !sQuickHelpText.isEmpty() )
3493 : {
3494 : //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
3495 0 : Point aPt( aOptTextRect.TopLeft() );
3496 0 : aPt += pView->GetMapMode().GetOrigin();
3497 0 : aPt = pView->OutputToScreenPixel( aPt );
3498 : // subtract border of tooltip help
3499 0 : aPt.Y() -= 1;
3500 0 : aPt.X() -= 3;
3501 0 : aOptTextRect.SetPos( aPt );
3502 0 : OUString sHelpText;
3503 0 : if ( !sQuickHelpText.isEmpty() )
3504 0 : sHelpText = sQuickHelpText;
3505 : else
3506 0 : sHelpText = aEntryText;
3507 0 : Help::ShowQuickHelp( static_cast<vcl::Window*>(pView), aOptTextRect, sHelpText, QuickHelpFlags::Left | QuickHelpFlags::VCenter );
3508 : }
3509 :
3510 0 : return true;
3511 : }
3512 :
3513 5 : void SvxIconChoiceCtrl_Impl::ClearColumnList()
3514 : {
3515 5 : if( !pColumns )
3516 10 : return;
3517 :
3518 0 : pColumns->clear();
3519 0 : DELETEZ(pColumns);
3520 : }
3521 :
3522 0 : void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
3523 : {
3524 0 : if( !pColumns )
3525 0 : pColumns = new SvxIconChoiceCtrlColumnInfoMap;
3526 :
3527 0 : SvxIconChoiceCtrlColumnInfo* pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
3528 0 : pColumns->insert( nIndex, pInfo );
3529 :
3530 : // HACK: Detail mode is not yet fully implemented, this workaround makes it
3531 : // fly with a single column
3532 0 : if( !nIndex && (nWinBits & WB_DETAILS) )
3533 0 : nGridDX = pInfo->GetWidth();
3534 :
3535 0 : if( GetUpdateMode() )
3536 0 : Arrange( IsAutoArrange() );
3537 0 : }
3538 :
3539 0 : const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
3540 : {
3541 0 : if (!pColumns)
3542 0 : return 0;
3543 0 : SvxIconChoiceCtrlColumnInfoMap::const_iterator it = pColumns->find( nIndex );
3544 0 : if( it == pColumns->end() )
3545 0 : return 0;
3546 0 : return it->second;
3547 : }
3548 :
3549 0 : void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(vcl::RenderContext& rRenderContext, const Rectangle& rBmpRect, bool bHide)
3550 : {
3551 0 : Rectangle aBmpRect(rBmpRect);
3552 0 : long nBorder = 2;
3553 0 : if (aImageSize.Width() < 32)
3554 0 : nBorder = 1;
3555 0 : aBmpRect.Right() += nBorder;
3556 0 : aBmpRect.Left() -= nBorder;
3557 0 : aBmpRect.Bottom() += nBorder;
3558 0 : aBmpRect.Top() -= nBorder;
3559 :
3560 0 : if (bHide)
3561 0 : pView->Invalidate(aBmpRect);
3562 : else
3563 : {
3564 0 : DecorationView aDecoView(&rRenderContext);
3565 : DrawHighlightFrameStyle nDecoFlags;
3566 0 : if (bHighlightFramePressed)
3567 0 : nDecoFlags = DrawHighlightFrameStyle::In;
3568 : else
3569 0 : nDecoFlags = DrawHighlightFrameStyle::Out;
3570 0 : aDecoView.DrawHighlightFrame(aBmpRect, nDecoFlags, true/*bTestBackground*/);
3571 : }
3572 0 : }
3573 :
3574 0 : void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
3575 : bool bKeepHighlightFlags )
3576 : {
3577 0 : if( pEntry == pCurHighlightFrame )
3578 0 : return;
3579 :
3580 0 : if( !bKeepHighlightFlags )
3581 0 : bHighlightFramePressed = false;
3582 :
3583 0 : if (pCurHighlightFrame)
3584 : {
3585 0 : Rectangle aInvalidationRect(GetEntryBoundRect(pCurHighlightFrame));
3586 0 : aInvalidationRect.expand(5);
3587 0 : pCurHighlightFrame = nullptr;
3588 0 : pView->Invalidate(aInvalidationRect);
3589 : }
3590 :
3591 0 : pCurHighlightFrame = pEntry;
3592 0 : if (pEntry)
3593 : {
3594 0 : Rectangle aInvalidationRect(GetEntryBoundRect(pEntry));
3595 0 : aInvalidationRect.expand(5);
3596 0 : pView->Invalidate(aInvalidationRect);
3597 : }
3598 : }
3599 :
3600 3 : void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
3601 : {
3602 : // When single-click mode is active, the selection handler should be called
3603 : // synchronously, as the selection is automatically taken away once the
3604 : // mouse cursor doesn't touch the object any more. Else, we might run into
3605 : // missing calls to Select if the object is selected from a mouse movement,
3606 : // because when starting the timer, the mouse cursor might have already left
3607 : // the object.
3608 : // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
3609 : // WB_NOASYNCSELECTHDL.
3610 3 : if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
3611 : {
3612 3 : pHdlEntry = 0;
3613 3 : pView->ClickIcon();
3614 : //pView->Select();
3615 : }
3616 : else
3617 0 : aCallSelectHdlIdle.Start();
3618 3 : }
3619 :
3620 0 : IMPL_LINK_NOARG_TYPED(SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, Idle *, void)
3621 : {
3622 0 : pHdlEntry = 0;
3623 0 : pView->ClickIcon();
3624 : //pView->Select();
3625 0 : }
3626 :
3627 63 : void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos )
3628 : {
3629 63 : MapMode aMapMode( pView->GetMapMode() );
3630 63 : aMapMode.SetOrigin( rPos );
3631 63 : pView->SetMapMode( aMapMode );
3632 63 : }
3633 :
3634 8 : void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
3635 : {
3636 8 : pView->CallImplEventListeners( nEvent, pData );
3637 806 : }
3638 :
3639 :
3640 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|