GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / contnr / imivctl1.cxx
blob74d7fe5e0e02269a9355be01a550dac3288e0600
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
33 #include <svtools/ivctrl.hxx>
34 #include "imivctl.hxx"
35 #include <svtools/svmedit.hxx>
37 #include <algorithm>
38 #include <memory>
40 #define IMPICNVIEW_ACC_RETURN 1
41 #define IMPICNVIEW_ACC_ESCAPE 2
43 #define DRAWTEXT_FLAGS_ICON \
44 ( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
45 TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
47 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
49 #define EVENTID_SHOW_CURSOR ((void*)1)
50 #define EVENTID_ADJUST_SCROLLBARS ((void*)2)
52 struct SvxIconChoiceCtrlEntry_Impl
54 SvxIconChoiceCtrlEntry* _pEntry;
55 Point _aPos;
56 SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect )
57 : _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {}
60 static sal_Bool bEndScrollInvalidate = sal_True;
62 class IcnViewEdit_Impl : public MultiLineEdit
64 Link aCallBackHdl;
65 Accelerator aAccReturn;
66 Accelerator aAccEscape;
67 Timer aTimer;
68 sal_Bool bCanceled;
69 sal_Bool bAlreadyInCallback;
70 sal_Bool bGrabFocus;
72 void CallCallBackHdl_Impl();
73 DECL_LINK(Timeout_Impl, void *);
74 DECL_LINK( ReturnHdl_Impl, Accelerator * );
75 DECL_LINK( EscapeHdl_Impl, Accelerator * );
77 public:
79 IcnViewEdit_Impl(
80 SvtIconChoiceCtrl* pParent,
81 const Point& rPos,
82 const Size& rSize,
83 const OUString& rData,
84 const Link& rNotifyEditEnd );
86 ~IcnViewEdit_Impl();
87 virtual void KeyInput( const KeyEvent& rKEvt );
88 virtual long PreNotify( NotifyEvent& rNEvt );
89 sal_Bool EditingCanceled() const { return bCanceled; }
90 void StopEditing( sal_Bool bCancel = sal_False );
91 sal_Bool IsGrabFocus() const { return bGrabFocus; }
94 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl(
95 SvtIconChoiceCtrl* pCurView,
96 WinBits nWinStyle
97 ) :
98 aEntries( this ),
99 aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
100 aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ),
101 aScrBarBox( pCurView ),
102 aImageSize( 32, 32 ),
103 pColumns( 0 )
105 bChooseWithCursor=sal_False;
106 pEntryPaintDev = 0;
107 pCurEditedEntry = 0;
108 pCurHighlightFrame = 0;
109 pEdit = 0;
110 pAnchor = 0;
111 pPrevDropTarget = 0;
112 pHdlEntry = 0;
113 pHead = NULL;
114 pCursor = NULL;
115 bUpdateMode = sal_True;
116 bEntryEditingEnabled = sal_False;
117 bHighlightFramePressed = sal_False;
118 eSelectionMode = MULTIPLE_SELECTION;
119 pView = pCurView;
120 pZOrderList = new SvxIconChoiceCtrlEntryList_impl();
121 ePositionMode = IcnViewPositionModeFree;
122 SetStyle( nWinStyle );
123 nFlags = 0;
124 nUserEventAdjustScrBars = 0;
125 nUserEventShowCursor = 0;
126 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
127 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
128 pDDRefEntry = 0;
129 pDDDev = 0;
130 pDDBufDev = 0;
131 pDDTempDev = 0;
132 eTextMode = IcnShowTextShort;
133 pImpCursor = new IcnCursor_Impl( this );
134 pGridMap = new IcnGridMap_Impl( this );
136 aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
137 aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
138 Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) );
139 aVerSBar.SetEndScrollHdl( aEndScrollHdl );
140 aHorSBar.SetEndScrollHdl( aEndScrollHdl );
142 nHorSBarHeight = aHorSBar.GetSizePixel().Height();
143 nVerSBarWidth = aVerSBar.GetSizePixel().Width();
145 aEditTimer.SetTimeout( 800 );
146 aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
147 aAutoArrangeTimer.SetTimeout( 100 );
148 aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
149 aCallSelectHdlTimer.SetTimeout( 500 );
150 aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
152 aDocRectChangedTimer.SetTimeout( 50 );
153 aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
154 aVisRectChangedTimer.SetTimeout( 50 );
155 aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
157 Clear( sal_True );
159 SetGrid( Size(100, 70) );
162 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
164 pCurEditedEntry = 0;
165 DELETEZ(pEdit);
166 Clear();
167 StopEditTimer();
168 CancelUserEvents();
169 delete pZOrderList;
170 delete pImpCursor;
171 delete pGridMap;
172 delete pDDDev;
173 delete pDDBufDev;
174 delete pDDTempDev;
175 delete pEntryPaintDev;
176 ClearSelectedRectList();
177 ClearColumnList();
180 void SvxIconChoiceCtrl_Impl::Clear( sal_Bool bInCtor )
182 StopEntryEditing( sal_True );
183 nSelectionCount = 0;
184 pCurHighlightFrame = 0;
185 StopEditTimer();
186 CancelUserEvents();
187 ShowCursor( sal_False );
188 bBoundRectsDirty = sal_False;
189 nMaxBoundHeight = 0;
191 nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
192 pCursor = 0;
193 if( !bInCtor )
195 pImpCursor->Clear();
196 pGridMap->Clear();
197 aVirtOutputSize.Width() = 0;
198 aVirtOutputSize.Height() = 0;
199 Size aSize( pView->GetOutputSizePixel() );
200 nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
201 if( nMaxVirtWidth <= 0 )
202 nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
203 nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
204 if( nMaxVirtHeight <= 0 )
205 nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
206 pZOrderList->clear();
207 SetOrigin( Point() );
208 if( bUpdateMode )
209 pView->Invalidate(INVALIDATE_NOCHILDREN);
211 AdjustScrollBars();
212 size_t nCount = aEntries.size();
213 for( size_t nCur = 0; nCur < nCount; nCur++ )
215 SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
216 delete pCur;
218 aEntries.clear();
219 DocRectChanged();
220 VisRectChanged();
223 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
225 nWinBits = nWinStyle;
226 nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
227 if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
228 nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
229 if( nWinBits & WB_NOSELECTION )
230 eSelectionMode = NO_SELECTION;
231 if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
232 nWinBits |= WB_ALIGN_LEFT;
233 if( (nWinStyle & WB_DETAILS))
235 if( !pColumns )
236 SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
240 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
242 StopEntryEditing( sal_True );
243 // arrow up: delta=-1; arrow down: delta=+1
244 Scroll( 0, pScrollBar->GetDelta(), sal_True );
245 bEndScrollInvalidate = sal_True;
246 return 0;
249 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
251 StopEntryEditing( sal_True );
252 // arrow left: delta=-1; arrow right: delta=+1
253 Scroll( pScrollBar->GetDelta(), 0, sal_True );
254 bEndScrollInvalidate = sal_True;
255 return 0;
258 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, EndScrollHdl)
260 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() &&
261 bEndScrollInvalidate )
263 pView->Invalidate(INVALIDATE_NOCHILDREN);
265 return 0;
268 void SvxIconChoiceCtrl_Impl::FontModified()
270 StopEditTimer();
271 DELETEZ(pDDDev);
272 DELETEZ(pDDBufDev);
273 DELETEZ(pDDTempDev);
274 DELETEZ(pEntryPaintDev);
275 SetDefaultTextSize();
276 ShowCursor( sal_False );
277 ShowCursor( sal_True );
280 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, size_t nPos,
281 const Point* pPos )
283 StopEditTimer();
284 aEntries.insert( nPos, pEntry );
285 if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.size() - 1 )
286 pEntry->nPos = aEntries.size() - 1;
287 else
288 nFlags &= ~F_ENTRYLISTPOS_VALID;
290 pZOrderList->push_back( pEntry );
291 pImpCursor->Clear();
292 if( pPos )
294 Size aSize( CalcBoundingSize( pEntry ) );
295 SetBoundingRect_Impl( pEntry, *pPos, aSize );
296 SetEntryPos( pEntry, *pPos, sal_False, sal_True, sal_True /*keep grid map*/ );
297 pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED;
298 SetEntriesMoved( sal_True );
300 else
302 // If the UpdateMode is sal_True, don't set all bounding rectangles to
303 // 'to be checked', but only the bounding rectangle of the new entry.
304 // Thus, don't call InvalidateBoundingRect!
305 pEntry->aRect.Right() = LONG_MAX;
306 if( bUpdateMode )
308 FindBoundingRect( pEntry );
309 Rectangle aOutputArea( GetOutputRect() );
310 pGridMap->OccupyGrids( pEntry );
311 if( !aOutputArea.IsOver( pEntry->aRect ) )
312 return; // is invisible
313 pView->Invalidate( pEntry->aRect );
315 else
316 InvalidateBoundingRect( pEntry->aRect );
320 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
322 ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
323 if ( !_pGenerator )
325 _pGenerator = new MnemonicGenerator;
326 pAutoDeleteOwnGenerator.reset( _pGenerator );
329 sal_uLong nEntryCount = GetEntryCount();
330 sal_uLong i;
332 // insert texts in generator
333 for( i = 0; i < nEntryCount; ++i )
335 DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
337 _pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
340 // exchange texts with generated mnemonics
341 for( i = 0; i < nEntryCount; ++i )
343 SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
344 OUString aTxt = pEntry->GetText();
346 OUString aNewText = _pGenerator->CreateMnemonic( aTxt );
347 if( aNewText != aTxt )
348 pEntry->SetText( aNewText );
352 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
354 Point aOrigin( pView->GetMapMode().GetOrigin() );
355 aOrigin *= -1;
356 return Rectangle( aOrigin, aOutputSize );
359 void SvxIconChoiceCtrl_Impl::SetListPositions()
361 if( nFlags & F_ENTRYLISTPOS_VALID )
362 return;
364 size_t nCount = aEntries.size();
365 for( size_t nCur = 0; nCur < nCount; nCur++ )
367 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
368 pEntry->nPos = nCur;
370 nFlags |= F_ENTRYLISTPOS_VALID;
373 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
374 sal_Bool bCallHdl, sal_Bool bAdd, sal_Bool bSyncPaint )
376 if( eSelectionMode == NO_SELECTION )
377 return;
379 if( !bAdd )
381 if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
383 nFlags |= F_CLEARING_SELECTION;
384 DeselectAllBut( pEntry, sal_True );
385 nFlags &= ~F_CLEARING_SELECTION;
388 if( pEntry->IsSelected() != bSelect )
390 pHdlEntry = pEntry;
391 sal_uInt16 nEntryFlags = pEntry->GetFlags();
392 if( bSelect )
394 nEntryFlags |= ICNVIEW_FLAG_SELECTED;
395 pEntry->AssignFlags( nEntryFlags );
396 nSelectionCount++;
397 if( bCallHdl )
398 CallSelectHandler( pEntry );
400 else
402 nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
403 pEntry->AssignFlags( nEntryFlags );
404 nSelectionCount--;
405 if( bCallHdl )
406 CallSelectHandler( 0 );
408 EntrySelected( pEntry, bSelect, bSyncPaint );
412 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
413 sal_Bool bSyncPaint )
415 // When using SingleSelection, make sure that the cursor is always placed
416 // over the (only) selected entry. (But only if a cursor exists.)
417 if( bSelect && pCursor &&
418 eSelectionMode == SINGLE_SELECTION &&
419 pEntry != pCursor )
421 SetCursor( pEntry );
422 //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
425 // Not when dragging though, else the loop in SelectRect doesn't work
426 // correctly!
427 if( !(nFlags & F_SELECTING_RECT) )
428 ToTop( pEntry );
429 if( bUpdateMode )
431 if( pEntry == pCursor )
432 ShowCursor( sal_False );
433 if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // always synchronous when tracking
434 PaintEntry( pEntry );
435 else if( bSyncPaint ) // synchronous & with a virtual OutDev!
436 PaintEntryVirtOutDev( pEntry );
437 else
439 pView->Invalidate( CalcFocusRect( pEntry ) );
441 if( pEntry == pCursor )
442 ShowCursor( sal_True );
445 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
446 if ( bSelect )
448 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
452 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
454 StopEditTimer();
455 aVirtOutputSize.Width() = 0;
456 aVirtOutputSize.Height() = 0;
457 const size_t nCount = aEntries.size();
458 for( size_t nCur = 0; nCur < nCount; nCur++ )
460 SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
461 pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
462 if( pCur->IsPosLocked() )
464 // adapt (among others) VirtSize
465 if( !IsBoundingRectValid( pCur->aRect ) )
466 FindBoundingRect( pCur );
467 else
468 AdjustVirtSize( pCur->aRect );
470 else
471 InvalidateBoundingRect( pCur->aRect );
474 if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
476 Size aRealOutputSize( pView->GetOutputSizePixel() );
477 if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
478 aVirtOutputSize.Height() < aRealOutputSize.Height() )
480 sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
481 aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
482 if( nGridCount < nCount )
484 if( nWinBits & WB_ALIGN_TOP )
485 nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
486 else // WB_ALIGN_LEFT
487 nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
492 pImpCursor->Clear();
493 pGridMap->Clear();
494 VisRectChanged();
497 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
499 long nHeightOffs = 0;
500 long nWidthOffs = 0;
502 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
503 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
505 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
506 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
508 if( nWidthOffs || nHeightOffs )
510 Range aRange;
511 aVirtOutputSize.Width() += nWidthOffs;
512 aRange.Max() = aVirtOutputSize.Width();
513 aHorSBar.SetRange( aRange );
515 aVirtOutputSize.Height() += nHeightOffs;
516 aRange.Max() = aVirtOutputSize.Height();
517 aVerSBar.SetRange( aRange );
519 pImpCursor->Clear();
520 pGridMap->OutputSizeChanged();
521 AdjustScrollBars();
522 DocRectChanged();
526 void SvxIconChoiceCtrl_Impl::InitPredecessors()
528 DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
529 size_t nCount = aEntries.size();
530 if( nCount )
532 SvxIconChoiceCtrlEntry* pPrev = aEntries[ 0 ];
533 for( size_t nCur = 1; nCur <= nCount; nCur++ )
535 pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
536 ICNVIEW_FLAG_PRED_SET);
538 SvxIconChoiceCtrlEntry* pNext;
539 if( nCur == nCount )
540 pNext = aEntries[ 0 ];
541 else
542 pNext = aEntries[ nCur ];
543 pPrev->pflink = pNext;
544 pNext->pblink = pPrev;
545 pPrev = pNext;
547 pHead = aEntries[ 0 ];
549 else
550 pHead = 0;
551 nFlags &= ~F_MOVED_ENTRIES;
554 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
556 if( pHead )
558 size_t nCount = aEntries.size();
559 for( size_t nCur = 0; nCur < nCount; nCur++ )
561 SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
562 pCur->pflink = 0;
563 pCur->pblink = 0;
564 pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
566 pHead = 0;
570 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
572 if ( nSetMaxVirtWidth != 0 )
573 nMaxVirtWidth = nSetMaxVirtWidth;
574 else
575 nMaxVirtWidth = aOutputSize.Width();
577 if ( nSetMaxVirtHeight != 0 )
578 nMaxVirtHeight = nSetMaxVirtHeight;
579 else
580 nMaxVirtHeight = aOutputSize.Height();
582 ImpArrange( bKeepPredecessors );
585 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors )
587 static Point aEmptyPoint;
589 sal_Bool bOldUpdate = bUpdateMode;
590 Rectangle aCurOutputArea( GetOutputRect() );
591 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
592 bUpdateMode = sal_False;
593 aAutoArrangeTimer.Stop();
594 nFlags &= ~F_MOVED_ENTRIES;
595 nFlags |= F_ARRANGING;
596 StopEditTimer();
597 ShowCursor( sal_False );
598 ResetVirtSize();
599 if( !bKeepPredecessors )
600 ClearPredecessors();
601 bBoundRectsDirty = sal_False;
602 SetOrigin( Point() );
603 VisRectChanged();
604 RecalcAllBoundingRectsSmart();
605 // TODO: the invalidation in the detail view should be more intelligent
606 //if( !(nWinBits & WB_DETAILS ))
607 pView->Invalidate( INVALIDATE_NOCHILDREN );
608 nFlags &= ~F_ARRANGING;
609 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
611 MakeVisible( aCurOutputArea );
612 SetUpdateMode( bOldUpdate );
614 ShowCursor( sal_True );
617 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
619 bEndScrollInvalidate = sal_False;
621 #if defined(OV_DRAWGRID)
622 Color aOldColor ( pView->GetLineColor() );
623 Color aColor( COL_BLACK );
624 pView->SetLineColor( aColor );
625 Point aOffs( pView->GetMapMode().GetOrigin());
626 Size aXSize( pView->GetOutputSizePixel() );
629 Point aStart( LROFFS_WINBORDER, 0 );
630 Point aEnd( LROFFS_WINBORDER, aXSize.Height());
631 aStart -= aOffs;
632 aEnd -= aOffs;
633 pView->DrawLine( aStart, aEnd );
636 Point aStart( 0, TBOFFS_WINBORDER );
637 Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
638 aStart -= aOffs;
639 aEnd -= aOffs;
640 pView->DrawLine( aStart, aEnd );
643 for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
645 Point aStart( nDX+LROFFS_WINBORDER, 0 );
646 Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
647 aStart -= aOffs;
648 aEnd -= aOffs;
649 pView->DrawLine( aStart, aEnd );
651 for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
653 Point aStart( 0, nDY+TBOFFS_WINBORDER );
654 Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
655 aStart -= aOffs;
656 aEnd -= aOffs;
657 pView->DrawLine( aStart, aEnd );
659 pView->SetLineColor( aOldColor );
660 #endif
661 nFlags |= F_PAINTED;
663 if( !aEntries.size() )
664 return;
665 if( !pCursor )
667 // set cursor to item with focus-flag
668 sal_Bool bfound = sal_False;
669 for ( sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++)
671 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
672 if( pEntry->IsFocused() )
674 pCursor = pEntry;
675 bfound=sal_True;
679 if( !bfound )
680 pCursor = aEntries[ 0 ];
683 // Show Focus at Init-Time
684 if ( pView->HasFocus() )
685 GetFocus();
687 size_t nCount = pZOrderList->size();
688 if( !nCount )
689 return;
691 sal_Bool bResetClipRegion = sal_False;
692 if( !pView->IsClipRegion() )
694 Region const aOutputArea( GetOutputRect() );
695 bResetClipRegion = sal_True;
696 pView->SetClipRegion( aOutputArea );
699 SvxIconChoiceCtrlEntryList_impl* pNewZOrderList = new SvxIconChoiceCtrlEntryList_impl();
700 SvxIconChoiceCtrlEntryList_impl* pPaintedEntries = new SvxIconChoiceCtrlEntryList_impl();
702 size_t nPos = 0;
703 while( nCount )
705 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nPos ];
706 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
707 if( rRect.IsOver( rBoundRect ) )
709 PaintEntry( pEntry, rBoundRect.TopLeft(), pView, sal_True );
710 // set entries to Top if they are being repainted
711 pPaintedEntries->push_back( pEntry );
713 else
714 pNewZOrderList->push_back( pEntry );
716 nCount--;
717 nPos++;
719 delete pZOrderList;
720 pZOrderList = pNewZOrderList;
721 nCount = pPaintedEntries->size();
722 if( nCount )
724 for( size_t nCur = 0; nCur < nCount; nCur++ )
725 pZOrderList->push_back( (*pPaintedEntries)[ nCur ] );
727 delete pPaintedEntries;
729 if( bResetClipRegion )
730 pView->SetClipRegion();
733 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask )
735 const size_t nCount = pZOrderList->size();
736 if( !nCount )
737 return;
739 sal_Bool bResetClipRegion = sal_False;
740 Rectangle aOutRect( GetOutputRect() );
741 if( !pView->IsClipRegion() )
743 bResetClipRegion = sal_True;
744 pView->SetClipRegion(Region(aOutRect));
746 for( size_t nCur = 0; nCur < nCount; nCur++ )
748 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
749 if( pEntry->GetFlags() & nEntryFlagsMask )
751 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
752 if( aOutRect.IsOver( rBoundRect ) )
753 PaintEntry( pEntry, rBoundRect.TopLeft() );
756 if( bResetClipRegion )
757 pView->SetClipRegion();
761 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
763 aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
764 Size aSize( pView->GetOutputSizePixel() );
765 aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
768 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
770 sal_Bool bHandled = sal_True;
771 bHighlightFramePressed = sal_False;
772 StopEditTimer();
773 sal_Bool bGotFocus = (sal_Bool)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
774 if( !(nWinBits & WB_NOPOINTERFOCUS) )
775 pView->GrabFocus();
777 Point aDocPos( rMEvt.GetPosPixel() );
778 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
779 return sal_False;
780 ToDocPos( aDocPos );
781 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
782 if( pEntry )
783 MakeEntryVisible( pEntry, sal_False );
785 if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
787 if( pEntry )
788 SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), sal_True);
789 return sal_True;
792 if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // keyboard selection?
794 DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
795 if( rMEvt.IsMod1() )
796 nFlags |= F_ADD_MODE;
798 if( rMEvt.IsShift() )
800 Rectangle aRect( GetEntryBoundRect( pAnchor ));
801 if( pEntry )
802 aRect.Union( GetEntryBoundRect( pEntry ) );
803 else
805 Rectangle aTempRect( aDocPos, Size(1,1));
806 aRect.Union( aTempRect );
808 aCurSelectionRect = aRect;
809 SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
811 else if( rMEvt.IsMod1() )
813 AddSelectedRect( aCurSelectionRect );
814 pAnchor = 0;
815 aCurSelectionRect.SetPos( aDocPos );
818 if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
819 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
820 return sal_True;
822 else
824 if( !pEntry )
826 if( eSelectionMode == MULTIPLE_SELECTION )
828 if( !rMEvt.IsMod1() ) // Ctrl
830 if( !bGotFocus )
832 SetNoSelection();
833 ClearSelectedRectList();
836 else
837 nFlags |= F_ADD_MODE;
838 aCurSelectionRect.SetPos( aDocPos );
839 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
841 else
842 bHandled = sal_False;
843 return bHandled;
846 sal_Bool bSelected = pEntry->IsSelected();
847 sal_Bool bEditingEnabled = IsEntryEditingEnabled();
849 if( rMEvt.GetClicks() == 2 )
851 DeselectAllBut( pEntry );
852 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
853 pHdlEntry = pEntry;
854 pView->ClickIcon();
856 else
858 // Inplace-Editing ?
859 if( rMEvt.IsMod2() ) // Alt?
861 if( bEntryEditingEnabled && pEntry &&
862 pEntry->IsSelected())
864 if( pView->EditingEntry( pEntry ))
865 EditEntry( pEntry );
868 else if( eSelectionMode == SINGLE_SELECTION )
870 DeselectAllBut( pEntry );
871 SetCursor( pEntry );
872 if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
873 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
875 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
878 else if( eSelectionMode == NO_SELECTION )
880 if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
882 pCurHighlightFrame = 0; // force repaint of frame
883 bHighlightFramePressed = sal_True;
884 SetEntryHighlightFrame( pEntry, sal_True );
887 else
889 if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
891 if( !bSelected )
893 DeselectAllBut( pEntry, sal_True /* paint synchronously */ );
894 SetCursor( pEntry );
895 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
897 else
899 // deselect only in the Up, if the Move happened via D&D!
900 nFlags |= F_DOWN_DESELECT;
901 if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
902 rMEvt.IsLeft())
904 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
908 else if( rMEvt.IsMod1() )
909 nFlags |= F_DOWN_CTRL;
912 return bHandled;
915 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
917 sal_Bool bHandled = sal_False;
918 if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
920 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
921 bHandled = sal_True;
924 Point aDocPos( rMEvt.GetPosPixel() );
925 ToDocPos( aDocPos );
926 SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
927 if( pDocEntry )
929 if( nFlags & F_DOWN_CTRL )
931 // Ctrl & MultiSelection
932 ToggleSelection( pDocEntry );
933 SetCursor( pDocEntry );
934 bHandled = sal_True;
936 else if( nFlags & F_DOWN_DESELECT )
938 DeselectAllBut( pDocEntry );
939 SetCursor( pDocEntry );
940 SelectEntry( pDocEntry, sal_True, sal_True, sal_False, sal_True );
941 bHandled = sal_True;
945 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
946 if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
948 bHandled = sal_True;
949 StartEditTimer();
950 nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
953 if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
955 bHandled = sal_True;
956 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
957 pCurHighlightFrame = 0; // force repaint of frame
958 bHighlightFramePressed = sal_False;
959 SetEntryHighlightFrame( pEntry, sal_True );
961 pHdlEntry = pCurHighlightFrame;
962 pView->ClickIcon();
964 // set focus on Icon
965 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
966 SetCursor_Impl( pOldCursor, pHdlEntry, sal_False, sal_False, sal_True );
968 pHdlEntry = 0;
970 return bHandled;
973 sal_Bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
975 const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
977 if( pView->IsTracking() )
978 return sal_False;
979 else if( nWinBits & WB_HIGHLIGHTFRAME )
981 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
982 SetEntryHighlightFrame( pEntry );
984 else
985 return sal_False;
986 return sal_True;
989 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
990 SvxIconChoiceCtrlEntry* pNewCursor, sal_Bool bMod1, sal_Bool bShift, sal_Bool bPaintSync )
992 if( pNewCursor )
994 SvxIconChoiceCtrlEntry* pFilterEntry = 0;
995 sal_Bool bDeselectAll = sal_False;
996 if( eSelectionMode != SINGLE_SELECTION )
998 if( !bMod1 && !bShift )
999 bDeselectAll = sal_True;
1000 else if( bShift && !bMod1 && !pAnchor )
1002 bDeselectAll = sal_True;
1003 pFilterEntry = pOldCursor;
1006 if( bDeselectAll )
1007 DeselectAllBut( pFilterEntry, bPaintSync );
1008 ShowCursor( sal_False );
1009 MakeEntryVisible( pNewCursor );
1010 SetCursor( pNewCursor );
1011 if( bMod1 && !bShift )
1013 if( pAnchor )
1015 AddSelectedRect( pAnchor, pOldCursor );
1016 pAnchor = 0;
1019 else if( bShift )
1021 if( !pAnchor )
1022 pAnchor = pOldCursor;
1023 if ( nWinBits & WB_ALIGN_LEFT )
1024 SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
1025 else
1026 SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
1028 else
1030 SelectEntry( pCursor, sal_True, sal_True, sal_False, bPaintSync );
1031 aCurSelectionRect = GetEntryBoundRect( pCursor );
1036 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1038 StopEditTimer();
1040 sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2();
1041 sal_Unicode cChar = rKEvt.GetCharCode();
1042 sal_uLong nPos = (sal_uLong)-1;
1043 if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1045 // shortcut is clicked
1046 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1047 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1048 if ( pNewCursor != pOldCursor )
1049 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
1050 return sal_True;
1053 if ( bMod2 )
1054 // no actions with <ALT>
1055 return sal_False;
1057 sal_Bool bKeyUsed = sal_True;
1058 sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1059 sal_Bool bShift = rKEvt.GetKeyCode().IsShift();
1061 if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1063 bShift = sal_False;
1064 bMod1 = sal_False;
1067 if( bMod1 )
1068 nFlags |= F_ADD_MODE;
1070 SvxIconChoiceCtrlEntry* pNewCursor;
1071 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1073 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1074 switch( nCode )
1076 case KEY_UP:
1077 case KEY_PAGEUP:
1078 if( pCursor )
1080 MakeEntryVisible( pCursor );
1081 if( nCode == KEY_UP )
1082 pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1083 else
1084 pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False);
1085 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1086 if( !pNewCursor )
1088 Rectangle aRect( GetEntryBoundRect( pCursor ) );
1089 if( aRect.Top())
1091 aRect.Bottom() -= aRect.Top();
1092 aRect.Top() = 0;
1093 MakeVisible( aRect );
1097 if ( bChooseWithCursor && pNewCursor != NULL )
1099 pHdlEntry = pNewCursor;//GetCurEntry();
1100 pCurHighlightFrame = pHdlEntry;
1101 pView->ClickIcon();
1102 pCurHighlightFrame = NULL;
1105 break;
1107 case KEY_DOWN:
1108 case KEY_PAGEDOWN:
1109 if( pCursor )
1111 if( nCode == KEY_DOWN )
1112 pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1113 else
1114 pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True );
1115 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1117 if ( bChooseWithCursor && pNewCursor != NULL)
1119 pHdlEntry = pNewCursor;//GetCurEntry();
1120 pCurHighlightFrame = pHdlEntry;
1121 pView->ClickIcon();
1122 pCurHighlightFrame = NULL;
1125 break;
1127 case KEY_RIGHT:
1128 if( pCursor )
1130 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1131 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1133 break;
1135 case KEY_LEFT:
1136 if( pCursor )
1138 MakeEntryVisible( pCursor );
1139 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1140 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1141 if( !pNewCursor )
1143 Rectangle aRect( GetEntryBoundRect(pCursor));
1144 if( aRect.Left() )
1146 aRect.Right() -= aRect.Left();
1147 aRect.Left() = 0;
1148 MakeVisible( aRect );
1152 break;
1154 case KEY_F2:
1155 if( !bMod1 && !bShift )
1156 EditTimeoutHdl( 0 );
1157 else
1158 bKeyUsed = sal_False;
1159 break;
1161 case KEY_F8:
1162 if( rKEvt.GetKeyCode().IsShift() )
1164 if( nFlags & F_ADD_MODE )
1165 nFlags &= (~F_ADD_MODE);
1166 else
1167 nFlags |= F_ADD_MODE;
1169 else
1170 bKeyUsed = sal_False;
1171 break;
1173 case KEY_SPACE:
1174 if( pCursor && eSelectionMode != SINGLE_SELECTION )
1176 if( !bMod1 )
1178 //SelectAll( sal_False );
1179 SetNoSelection();
1180 ClearSelectedRectList();
1182 // click Icon with spacebar
1183 SetEntryHighlightFrame( GetCurEntry(), sal_True );
1184 pView->ClickIcon();
1185 pHdlEntry = pCurHighlightFrame;
1186 pCurHighlightFrame=0;
1188 else
1189 ToggleSelection( pCursor );
1191 break;
1193 #ifdef DBG_UTIL
1194 case KEY_F10:
1195 if( rKEvt.GetKeyCode().IsShift() )
1197 if( pCursor )
1198 pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1200 if( rKEvt.GetKeyCode().IsMod1() )
1202 if( pCursor )
1203 pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1205 break;
1206 #endif
1208 case KEY_ADD:
1209 case KEY_DIVIDE :
1210 case KEY_A:
1211 if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1212 SelectAll( sal_True );
1213 else
1214 bKeyUsed = sal_False;
1215 break;
1217 case KEY_SUBTRACT:
1218 case KEY_COMMA :
1219 if( bMod1 )
1220 SetNoSelection();
1221 else
1222 bKeyUsed = sal_False;
1223 break;
1225 case KEY_RETURN:
1226 if( bMod1 )
1228 if( pCursor && bEntryEditingEnabled )
1229 /*pView->*/EditEntry( pCursor );
1231 else
1232 bKeyUsed = sal_False;
1233 break;
1235 case KEY_END:
1236 if( pCursor )
1238 pNewCursor = aEntries[ aEntries.size() - 1 ];
1239 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1241 break;
1243 case KEY_HOME:
1244 if( pCursor )
1246 pNewCursor = aEntries[ 0 ];
1247 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1249 break;
1251 default:
1252 bKeyUsed = sal_False;
1255 return bKeyUsed;
1258 // recalculate TopLeft of scrollbars (but not their sizes!)
1259 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1261 // horizontal scrollbar
1262 Point aPos( 0, nRealHeight );
1263 aPos.Y() -= nHorSBarHeight;
1265 if( aHorSBar.GetPosPixel() != aPos )
1266 aHorSBar.SetPosPixel( aPos );
1268 // vertical scrollbar
1269 aPos.X() = nRealWidth; aPos.Y() = 0;
1270 aPos.X() -= nVerSBarWidth;
1271 aPos.X()++;
1272 aPos.Y()--;
1274 if( aVerSBar.GetPosPixel() != aPos )
1275 aVerSBar.SetPosPixel( aPos );
1278 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool )
1280 Rectangle aOldOutRect( GetOutputRect() );
1281 long nVirtHeight = aVirtOutputSize.Height();
1282 long nVirtWidth = aVirtOutputSize.Width();
1284 Size aOSize( pView->Control::GetOutputSizePixel() );
1285 long nRealHeight = aOSize.Height();
1286 long nRealWidth = aOSize.Width();
1288 PositionScrollBars( nRealWidth, nRealHeight );
1290 const MapMode& rMapMode = pView->GetMapMode();
1291 Point aOrigin( rMapMode.GetOrigin() );
1293 long nVisibleWidth;
1294 if( nRealWidth > nVirtWidth )
1295 nVisibleWidth = nVirtWidth + aOrigin.X();
1296 else
1297 nVisibleWidth = nRealWidth;
1299 long nVisibleHeight;
1300 if( nRealHeight > nVirtHeight )
1301 nVisibleHeight = nVirtHeight + aOrigin.Y();
1302 else
1303 nVisibleHeight = nRealHeight;
1305 sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1306 sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1307 sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1308 sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1310 sal_uInt16 nResult = 0;
1311 if( nVirtHeight )
1313 // activate vertical scrollbar?
1314 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1316 nResult = 0x0001;
1317 nRealWidth -= nVerSBarWidth;
1319 if( nRealWidth > nVirtWidth )
1320 nVisibleWidth = nVirtWidth + aOrigin.X();
1321 else
1322 nVisibleWidth = nRealWidth;
1324 nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1326 // activate horizontal scrollbar?
1327 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1329 nResult |= 0x0002;
1330 nRealHeight -= nHorSBarHeight;
1332 if( nRealHeight > nVirtHeight )
1333 nVisibleHeight = nVirtHeight + aOrigin.Y();
1334 else
1335 nVisibleHeight = nRealHeight;
1337 // do we need a vertical scrollbar after all?
1338 if( !(nResult & 0x0001) && // only if not already there
1339 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1341 nResult = 3; // both turned on
1342 nRealWidth -= nVerSBarWidth;
1344 if( nRealWidth > nVirtWidth )
1345 nVisibleWidth = nVirtWidth + aOrigin.X();
1346 else
1347 nVisibleWidth = nRealWidth;
1349 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1354 // size vertical scrollbar
1355 long nThumb = aVerSBar.GetThumbPos();
1356 Size aSize( nVerSBarWidth, nRealHeight );
1357 aSize.Height() += 2;
1358 if( aSize != aVerSBar.GetSizePixel() )
1359 aVerSBar.SetSizePixel( aSize );
1360 aVerSBar.SetVisibleSize( nVisibleHeight );
1361 aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1363 if( nResult & 0x0001 )
1365 aVerSBar.SetThumbPos( nThumb );
1366 aVerSBar.Show();
1368 else
1370 aVerSBar.SetThumbPos( 0 );
1371 aVerSBar.Hide();
1374 // size horizontal scrollbar
1375 nThumb = aHorSBar.GetThumbPos();
1376 aSize.Width() = nRealWidth;
1377 aSize.Height() = nHorSBarHeight;
1378 aSize.Width()++;
1379 if( nResult & 0x0001 ) // vertical scrollbar?
1381 aSize.Width()++;
1382 nRealWidth++;
1384 if( aSize != aHorSBar.GetSizePixel() )
1385 aHorSBar.SetSizePixel( aSize );
1386 aHorSBar.SetVisibleSize( nVisibleWidth );
1387 aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1388 if( nResult & 0x0002 )
1390 aHorSBar.SetThumbPos( nThumb );
1391 aHorSBar.Show();
1393 else
1395 aHorSBar.SetThumbPos( 0 );
1396 aHorSBar.Hide();
1399 aOutputSize.Width() = nRealWidth;
1400 if( nResult & 0x0002 ) // horizontal scrollbar ?
1401 nRealHeight++; // because lower border is clipped
1402 aOutputSize.Height() = nRealHeight;
1404 Rectangle aNewOutRect( GetOutputRect() );
1405 if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1407 Wallpaper aPaper( pView->GetBackground() );
1408 aPaper.SetRect( aNewOutRect );
1409 pView->SetBackground( aPaper );
1412 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1413 aScrBarBox.Show();
1414 else
1415 aScrBarBox.Hide();
1418 void SvxIconChoiceCtrl_Impl::Resize()
1420 StopEditTimer();
1421 InitScrollBarBox();
1422 aOutputSize = pView->GetOutputSizePixel();
1423 pImpCursor->Clear();
1424 pGridMap->OutputSizeChanged();
1426 const Size& rSize = pView->Control::GetOutputSizePixel();
1427 PositionScrollBars( rSize.Width(), rSize.Height() );
1428 // The scrollbars are shown/hidden asynchronously, so derived classes can
1429 // do an Arrange during Resize, without the scrollbars suddenly turning
1430 // on and off again.
1431 // If an event is already underway, we don't need to send a new one, at least
1432 // as long as there is only one event type.
1433 if ( ! nUserEventAdjustScrBars )
1434 nUserEventAdjustScrBars =
1435 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1436 EVENTID_ADJUST_SCROLLBARS);
1438 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1440 Rectangle aRect( GetOutputRect());
1441 Wallpaper aPaper( pView->GetBackground() );
1442 aPaper.SetRect( aRect );
1443 pView->SetBackground( aPaper );
1445 VisRectChanged();
1448 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1450 if( !pZOrderList || !aHorSBar.IsVisible() )
1451 return sal_False;
1452 const MapMode& rMapMode = pView->GetMapMode();
1453 Point aOrigin( rMapMode.GetOrigin() );
1454 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1456 long nWidth = aOutputSize.Width();
1457 const size_t nCount = pZOrderList->size();
1458 long nMostRight = 0;
1459 for( size_t nCur = 0; nCur < nCount; nCur++ )
1461 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1462 long nRight = GetEntryBoundRect(pEntry).Right();
1463 if( nRight > nWidth )
1464 return sal_False;
1465 if( nRight > nMostRight )
1466 nMostRight = nRight;
1468 aHorSBar.Hide();
1469 aOutputSize.Height() += nHorSBarHeight;
1470 aVirtOutputSize.Width() = nMostRight;
1471 aHorSBar.SetThumbPos( 0 );
1472 Range aRange;
1473 aRange.Max() = nMostRight - 1;
1474 aHorSBar.SetRange( aRange );
1475 if( aVerSBar.IsVisible() )
1477 Size aSize( aVerSBar.GetSizePixel());
1478 aSize.Height() += nHorSBarHeight;
1479 aVerSBar.SetSizePixel( aSize );
1481 return sal_True;
1483 return sal_False;
1486 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1488 if( !pZOrderList || !aVerSBar.IsVisible() )
1489 return sal_False;
1490 const MapMode& rMapMode = pView->GetMapMode();
1491 Point aOrigin( rMapMode.GetOrigin() );
1492 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1494 long nDeepest = 0;
1495 long nHeight = aOutputSize.Height();
1496 const size_t nCount = pZOrderList->size();
1497 for( size_t nCur = 0; nCur < nCount; nCur++ )
1499 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1500 long nBottom = GetEntryBoundRect(pEntry).Bottom();
1501 if( nBottom > nHeight )
1502 return sal_False;
1503 if( nBottom > nDeepest )
1504 nDeepest = nBottom;
1506 aVerSBar.Hide();
1507 aOutputSize.Width() += nVerSBarWidth;
1508 aVirtOutputSize.Height() = nDeepest;
1509 aVerSBar.SetThumbPos( 0 );
1510 Range aRange;
1511 aRange.Max() = nDeepest - 1;
1512 aVerSBar.SetRange( aRange );
1513 if( aHorSBar.IsVisible() )
1515 Size aSize( aHorSBar.GetSizePixel());
1516 aSize.Width() += nVerSBarWidth;
1517 aHorSBar.SetSizePixel( aSize );
1519 return sal_True;
1521 return sal_False;
1525 // hides scrollbars if they're unnecessary
1526 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1528 CheckVerScrollBar();
1529 if( CheckHorScrollBar() )
1530 CheckVerScrollBar();
1531 if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1532 aScrBarBox.Show();
1533 else
1534 aScrBarBox.Hide();
1538 void SvxIconChoiceCtrl_Impl::GetFocus()
1540 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1541 if( pCursor )
1543 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1544 ShowCursor( sal_True );
1548 void SvxIconChoiceCtrl_Impl::LoseFocus()
1550 StopEditTimer();
1551 if( pCursor )
1552 pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1553 ShowCursor( sal_False );
1555 // HideFocus ();
1556 // pView->Invalidate ( aFocus.aRect );
1558 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1561 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate )
1563 if( bUpdate != bUpdateMode )
1565 bUpdateMode = bUpdate;
1566 if( bUpdate )
1568 AdjustScrollBars();
1569 pImpCursor->Clear();
1570 pGridMap->Clear();
1571 pView->Invalidate(INVALIDATE_NOCHILDREN);
1576 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted )
1578 Point aPos( GetEntryPos( pEntry ) );
1579 PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1582 // priorities of the emphasis: bDropTarget => bCursored => bSelected
1583 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1584 const Rectangle& rTextRect, const Rectangle& rImageRect,
1585 sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut,
1586 sal_Bool bIsBackgroundPainted )
1588 static Color aTransparent( COL_TRANSPARENT );
1590 if( !pOut )
1591 pOut = pView;
1593 #ifdef OV_CHECK_EMPH_RECTS
1595 Color aXOld( pOut->GetFillColor() );
1596 pOut->SetFillColor( Color( COL_GREEN ));
1597 pOut->DrawRect( rTextRect );
1598 pOut->DrawRect( rImageRect );
1599 pOut->SetFillColor( aXOld );
1601 #endif
1603 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1604 Color aOldFillColor( pOut->GetFillColor() );
1606 sal_Bool bSolidTextRect = sal_False;
1607 sal_Bool bSolidImageRect = sal_False;
1609 if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1611 pOut->SetFillColor( rSettings.GetHighlightColor() );
1612 bSolidTextRect = sal_True;
1613 bSolidImageRect = sal_True;
1615 else
1617 if ( !bSelected || bCursored )
1619 if( !pView->HasFontFillColor() )
1620 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1621 else
1623 const Color& rFillColor = pView->GetFont().GetFillColor();
1624 pOut->SetFillColor( rFillColor );
1625 if( rFillColor != aTransparent )
1626 bSolidTextRect = sal_True;
1631 // draw text rectangle
1632 if( !bSolidTextRect )
1634 if( !bIsBackgroundPainted )
1635 pOut->Erase( rTextRect );
1637 else
1639 Color aOldLineColor;
1640 if( bCursored )
1642 aOldLineColor = pOut->GetLineColor();
1643 pOut->SetLineColor( Color( COL_GRAY ) );
1645 pOut->DrawRect( rTextRect );
1646 if( bCursored )
1647 pOut->SetLineColor( aOldLineColor );
1650 // draw image rectangle
1651 if( !bSolidImageRect )
1653 if( !bIsBackgroundPainted )
1654 pOut->Erase( rImageRect );
1656 // the emphasis of the images has to be drawn by the derived class (in the
1657 // virtual function DrawEntryImage)
1658 // else
1659 // pOut->DrawRect( rImageRect );
1661 pOut->SetFillColor( aOldFillColor );
1665 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1666 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1667 OutputDevice* pOut, const OUString* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1669 if( eItem == IcnViewFieldTypeText )
1671 OUString aText;
1672 if( !pStr )
1673 aText = pView->GetEntryText( pEntry, sal_False );
1674 else
1675 aText = *pStr;
1677 if ( _pLayoutData )
1679 pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1680 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1682 else
1684 Color aOldFontColor = pOut->GetTextColor();
1685 if ( pView->AutoFontColor() )
1687 Color aBkgColor( pOut->GetBackground().GetColor() );
1688 Color aFontColor;
1689 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1690 if ( nColor > 127 )
1691 aFontColor.SetColor ( COL_BLACK );
1692 else
1693 aFontColor.SetColor( COL_WHITE );
1694 pOut->SetTextColor( aFontColor );
1697 pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1699 if ( pView->AutoFontColor() )
1700 pOut->SetTextColor( aOldFontColor );
1702 if( pEntry->IsFocused() )
1704 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1705 /*pView->*/ShowFocus( aRect );
1706 DrawFocusRect( pOut );
1710 else
1712 Point aPos( rRect.TopLeft() );
1713 if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1714 aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1715 if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1716 aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1717 pView->DrawEntryImage( pEntry, aPos, *pOut );
1721 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1723 #ifdef OV_NO_VIRT_OUTDEV
1724 PaintEntry( pEntry );
1725 #else
1726 if( !pEntryPaintDev )
1728 pEntryPaintDev = new VirtualDevice( *pView );
1729 pEntryPaintDev->SetFont( pView->GetFont() );
1730 pEntryPaintDev->SetLineColor();
1731 //pEntryPaintDev->SetBackground( pView->GetBackground() );
1733 const Rectangle& rRect = GetEntryBoundRect( pEntry );
1734 Rectangle aOutRect( GetOutputRect() );
1735 if( !rRect.IsOver( aOutRect ) )
1736 return;
1737 Wallpaper aPaper( pView->GetBackground() );
1738 Rectangle aRect( aPaper.GetRect() );
1740 // move rectangle, so the bounding rectangle of the entry lies in
1741 // VirtOut-Dev at 0,0
1742 aRect.Move( -rRect.Left(), -rRect.Top() );
1743 aPaper.SetRect( aRect );
1744 pEntryPaintDev->SetBackground( aPaper );
1745 pEntryPaintDev->SetFont( pView->GetFont() );
1747 Size aSize( rRect.GetSize() );
1748 pEntryPaintDev->SetOutputSizePixel( aSize );
1749 pEntryPaintDev->DrawOutDev(
1750 Point(), aSize, rRect.TopLeft(), aSize, *pView );
1752 PaintEntry( pEntry, Point(), pEntryPaintDev );
1754 pView->DrawOutDev(
1755 rRect.TopLeft(),
1756 aSize,
1757 Point(),
1758 aSize,
1759 *pEntryPaintDev );
1760 #endif
1764 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1765 OutputDevice* pOut, sal_Bool bIsBackgroundPainted )
1767 if( !pOut )
1768 pOut = pView;
1770 sal_Bool bSelected = sal_False;
1772 if( eSelectionMode != NO_SELECTION )
1773 bSelected = pEntry->IsSelected();
1775 sal_Bool bCursored = pEntry->IsCursored();
1776 sal_Bool bDropTarget = pEntry->IsDropTarget();
1777 sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1779 Font aTempFont( pOut->GetFont() );
1781 // AutoFontColor
1783 if ( pView->AutoFontColor() )
1785 aTempFont.SetColor ( aFontColor );
1789 OUString aEntryText( pView->GetEntryText( pEntry, sal_False ) );
1790 Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText));
1791 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1793 sal_Bool bShowSelection =
1794 ( ( ( bSelected && !bCursored )
1795 || bDropTarget
1797 && !bNoEmphasis
1798 && ( eSelectionMode != NO_SELECTION )
1800 sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1802 if ( bShowSelection )
1804 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1805 Font aNewFont( aTempFont );
1807 // font fill colors that are attributed "hard" need corresponding "hard"
1808 // attributed highlight colors
1809 if( pView->HasFontFillColor() )
1811 if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1812 aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1813 else
1814 aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
1817 Color aWinCol = rSettings.GetWindowTextColor();
1818 if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
1819 aNewFont.SetColor( rSettings.GetWindowTextColor() );
1820 else
1821 aNewFont.SetColor( rSettings.GetHighlightTextColor() );
1823 pOut->SetFont( aNewFont );
1825 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1826 pOut->DrawRect( CalcFocusRect( pEntry ) );
1827 pOut->SetFillColor( );
1830 sal_Bool bResetClipRegion = sal_False;
1831 if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
1833 Rectangle aOutputArea( GetOutputRect() );
1834 if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
1836 pView->SetClipRegion(Region(aOutputArea));
1837 bResetClipRegion = sal_True;
1841 #ifdef OV_DRAWBOUNDRECT
1843 Color aXOldColor = pOut->GetLineColor();
1844 pOut->SetLineColor( Color( COL_LIGHTRED ) );
1845 Rectangle aXRect( pEntry->aRect );
1846 aXRect.SetPos( rPos );
1847 pOut->DrawRect( aXRect );
1848 pOut->SetLineColor( aXOldColor );
1850 #endif
1852 sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
1853 sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
1854 if ( bLargeIconMode )
1855 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
1856 sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
1858 if( !bNoEmphasis )
1859 PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
1861 if ( bShowSelection )
1862 pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
1863 bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
1865 PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
1867 PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
1868 nTextPaintFlags, pOut );
1870 // draw highlight frame
1871 if( pEntry == pCurHighlightFrame && !bNoEmphasis )
1872 DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False );
1874 pOut->SetFont( aTempFont );
1875 if( bResetClipRegion )
1876 pView->SetClipRegion();
1879 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1880 sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap )
1882 ShowCursor( sal_False );
1883 Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
1884 pView->Invalidate( aBoundRect );
1885 ToTop( pEntry );
1886 if( !IsAutoArrange() )
1888 sal_Bool bAdjustVirtSize = sal_False;
1889 if( rPos != aBoundRect.TopLeft() )
1891 Point aGridOffs(
1892 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
1893 pImpCursor->Clear();
1894 if( !bKeepGridMap )
1895 pGridMap->Clear();
1896 aBoundRect.SetPos( rPos );
1897 pEntry->aRect = aBoundRect;
1898 pEntry->aGridRect.SetPos( rPos + aGridOffs );
1899 bAdjustVirtSize = sal_True;
1901 if( bAdjustAtGrid )
1903 if( bAdjustVirtSize )
1905 // By aligning the (in some cases newly positioned) entry, it
1906 // can become completely visible again, so that maybe we don't
1907 // need a scrollbar after all. To avoid suddenly turning the
1908 // scrollbar(s) on and then off again, we use the aligned
1909 // bounding rectangle of the entry to enlarge the virtual
1910 // output size. The virtual size has to be adapted, because
1911 // AdjustEntryAtGrid depends on it.
1912 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
1913 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
1914 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
1915 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
1916 AdjustVirtSize( aNewBoundRect );
1917 bAdjustVirtSize = sal_False;
1919 AdjustEntryAtGrid( pEntry );
1920 ToTop( pEntry );
1922 if( bAdjustVirtSize )
1923 AdjustVirtSize( pEntry->aRect );
1925 if( bCheckScrollBars && bUpdateMode )
1926 CheckScrollBars();
1928 pView->Invalidate( pEntry->aRect );
1929 pGridMap->OccupyGrids( pEntry );
1931 else
1933 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
1934 SetEntryPredecessor( pEntry, pPrev );
1935 aAutoArrangeTimer.Start();
1937 ShowCursor( sal_True );
1940 void SvxIconChoiceCtrl_Impl::SetNoSelection()
1942 // block recursive calls via SelectEntry
1943 if( !(nFlags & F_CLEARING_SELECTION ))
1945 nFlags |= F_CLEARING_SELECTION;
1946 DeselectAllBut( 0, sal_True );
1947 nFlags &= ~F_CLEARING_SELECTION;
1951 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit )
1953 CheckBoundingRects();
1954 // search through z-order list from the end
1955 size_t nCount = pZOrderList->size();
1956 while( nCount )
1958 nCount--;
1959 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCount ];
1960 if( pEntry->aRect.IsInside( rDocPos ) )
1962 if( bHit )
1964 Rectangle aRect = CalcBmpRect( pEntry );
1965 aRect.Top() -= 3;
1966 aRect.Bottom() += 3;
1967 aRect.Left() -= 3;
1968 aRect.Right() += 3;
1969 if( aRect.IsInside( rDocPos ) )
1970 return pEntry;
1971 aRect = CalcTextRect( pEntry );
1972 if( aRect.IsInside( rDocPos ) )
1973 return pEntry;
1975 else
1976 return pEntry;
1979 return 0;
1982 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
1984 return pEntry->aRect.TopLeft();
1987 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound )
1989 if ( bBound )
1991 const Rectangle& rRect = GetEntryBoundRect( pEntry );
1992 MakeVisible( rRect );
1994 else
1996 Rectangle aRect = CalcBmpRect( pEntry );
1997 aRect.Union( CalcTextRect( pEntry ) );
1998 aRect.Top() += TBOFFS_BOUND;
1999 aRect.Bottom() += TBOFFS_BOUND;
2000 aRect.Left() += LROFFS_BOUND;
2001 aRect.Right() += LROFFS_BOUND;
2002 MakeVisible( aRect );
2006 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2008 if( !IsBoundingRectValid( pEntry->aRect ))
2009 FindBoundingRect( pEntry );
2010 return pEntry->aRect;
2013 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2015 Rectangle aBound = GetEntryBoundRect( pEntry );
2016 if( pPos )
2017 aBound.SetPos( *pPos );
2018 Point aPos( aBound.TopLeft() );
2020 switch( nWinBits & (VIEWMODE_MASK) )
2022 case WB_ICON:
2024 aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2025 return Rectangle( aPos, aImageSize );
2028 case WB_SMALLICON:
2029 case WB_DETAILS:
2030 aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2031 //TODO: determine horizontal distance to bounding rectangle
2032 return Rectangle( aPos, aImageSize );
2034 default:
2035 OSL_FAIL("IconView: Viewmode not set");
2036 return aBound;
2040 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2041 const Point* pEntryPos, sal_Bool bEdit, const OUString* pStr )
2043 OUString aEntryText;
2044 if( !pStr )
2045 aEntryText = pView->GetEntryText( pEntry, bEdit );
2046 else
2047 aEntryText = *pStr;
2049 const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2050 Rectangle aBound( GetEntryBoundRect( pEntry ) );
2051 if( pEntryPos )
2052 aBound.SetPos( *pEntryPos );
2054 Rectangle aTextRect( aMaxTextRect );
2055 if( !bEdit )
2056 aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2058 Size aTextSize( aTextRect.GetSize() );
2060 Point aPos( aBound.TopLeft() );
2061 long nBoundWidth = aBound.GetWidth();
2062 long nBoundHeight = aBound.GetHeight();
2064 switch( nWinBits & (VIEWMODE_MASK) )
2066 case WB_ICON:
2067 aPos.Y() += aImageSize.Height();
2068 aPos.Y() += VER_DIST_BMP_STRING;
2069 // at little more space when editing
2070 if( bEdit )
2072 // +20%
2073 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2074 aImageSize.Width();
2075 if( nMinWidth > nBoundWidth )
2076 nMinWidth = nBoundWidth;
2078 if( aTextSize.Width() < nMinWidth )
2079 aTextSize.Width() = nMinWidth;
2081 // when editing, overlap with the area below is allowed
2082 Size aOptSize = aMaxTextRect.GetSize();
2083 if( aOptSize.Height() > aTextSize.Height() )
2084 aTextSize.Height() = aOptSize.Height();
2086 aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2087 break;
2089 case WB_SMALLICON:
2090 case WB_DETAILS:
2091 aPos.X() += aImageSize.Width();
2092 aPos.X() += HOR_DIST_BMP_STRING;
2093 aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2094 break;
2096 return Rectangle( aPos, aTextSize );
2100 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2102 long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2103 // nStringWidth += 2*LROFFS_TEXT;
2104 long nWidth = 0;
2106 switch( nWinBits & (VIEWMODE_MASK) )
2108 case WB_ICON:
2109 nWidth = std::max( nStringWidth, aImageSize.Width() );
2110 break;
2112 case WB_SMALLICON:
2113 case WB_DETAILS:
2114 nWidth = aImageSize.Width();
2115 nWidth += HOR_DIST_BMP_STRING;
2116 nWidth += nStringWidth;
2117 break;
2119 return nWidth;
2122 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2124 long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2125 long nHeight = 0;
2127 switch( nWinBits & (VIEWMODE_MASK) )
2129 case WB_ICON:
2130 nHeight = aImageSize.Height();
2131 nHeight += VER_DIST_BMP_STRING;
2132 nHeight += nStringHeight;
2133 break;
2135 case WB_SMALLICON:
2136 case WB_DETAILS:
2137 nHeight = std::max( aImageSize.Height(), nStringHeight );
2138 break;
2140 if( nHeight > nMaxBoundHeight )
2142 ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2143 ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2144 ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2146 return nHeight;
2149 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2151 return Size( CalcBoundingWidth( pEntry ),
2152 CalcBoundingHeight( pEntry ) );
2155 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2157 nMaxBoundHeight = 0;
2158 pZOrderList->clear();
2159 size_t nCur;
2160 SvxIconChoiceCtrlEntry* pEntry;
2161 const size_t nCount = aEntries.size();
2163 if( !IsAutoArrange() || !pHead )
2165 for( nCur = 0; nCur < nCount; nCur++ )
2167 pEntry = aEntries[ nCur ];
2168 if( IsBoundingRectValid( pEntry->aRect ))
2170 Size aBoundSize( pEntry->aRect.GetSize() );
2171 if( aBoundSize.Height() > nMaxBoundHeight )
2172 nMaxBoundHeight = aBoundSize.Height();
2174 else
2175 FindBoundingRect( pEntry );
2176 pZOrderList->push_back( pEntry );
2179 else
2181 nCur = 0;
2182 pEntry = pHead;
2183 while( nCur != nCount )
2185 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2186 if( IsBoundingRectValid( pEntry->aRect ))
2188 Size aBoundSize( pEntry->aRect.GetSize() );
2189 if( aBoundSize.Height() > nMaxBoundHeight )
2190 nMaxBoundHeight = aBoundSize.Height();
2192 else
2193 FindBoundingRect( pEntry );
2194 pZOrderList->push_back( pEntry );
2195 pEntry = pEntry->pflink;
2196 nCur++;
2199 AdjustScrollBars();
2202 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2204 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2205 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2207 AdjustVirtSize( pEntry->aRect );
2208 return;
2210 Size aSize( CalcBoundingSize( pEntry ) );
2211 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft());
2212 SetBoundingRect_Impl( pEntry, aPos, aSize );
2215 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2216 const Size& /*rBoundingSize*/ )
2218 Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2219 pEntry->aGridRect = aGridRect;
2220 Center( pEntry );
2221 AdjustVirtSize( pEntry->aRect );
2222 pGridMap->OccupyGrids( pEntry );
2226 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection,
2227 sal_Bool bShowFocusAsync )
2229 if( pEntry == pCursor )
2231 if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2232 !pCursor->IsSelected() )
2233 SelectEntry( pCursor, sal_True, sal_True );
2234 return;
2236 ShowCursor( sal_False );
2237 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2238 pCursor = pEntry;
2239 if( pOldCursor )
2241 pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2242 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2243 SelectEntry( pOldCursor, sal_False, sal_True ); // deselect old cursor
2245 if( pCursor )
2247 ToTop( pCursor );
2248 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2249 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2250 SelectEntry( pCursor, sal_True, sal_True );
2251 if( !bShowFocusAsync )
2252 ShowCursor( sal_True );
2253 else
2255 if( !nUserEventShowCursor )
2256 nUserEventShowCursor =
2257 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2258 EVENTID_SHOW_CURSOR );
2264 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow )
2266 if( !pCursor || !bShow || !pView->HasFocus() )
2268 pView->HideFocus();
2269 return;
2271 Rectangle aRect ( CalcFocusRect( pCursor ) );
2272 /*pView->*/ShowFocus( aRect );
2276 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2278 pView->Update();
2279 ImpHideDDIcon();
2280 pDDBufDev = pDDDev;
2281 pDDDev = 0;
2284 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2286 if( pDDDev )
2288 Size aSize( pDDDev->GetOutputSizePixel() );
2289 // restore pView
2290 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2294 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2296 Rectangle aDocRect( GetDocumentRect() );
2297 Rectangle aVisRect( GetVisibleRect() );
2298 if( aVisRect.IsInside( aDocRect ))
2299 return sal_False;
2300 Size aDocSize( aDocRect.GetSize() );
2301 Size aVisSize( aVisRect.GetSize() );
2302 sal_Bool bHor = aDocSize.Width() > aVisSize.Width();
2303 sal_Bool bVer = aDocSize.Height() > aVisSize.Height();
2305 long nScrollDX = 0, nScrollDY = 0;
2307 switch( rCmd.GetCommand() )
2309 case COMMAND_STARTAUTOSCROLL:
2311 pView->EndTracking();
2312 sal_uInt16 nScrollFlags = 0;
2313 if( bHor )
2314 nScrollFlags |= AUTOSCROLL_HORZ;
2315 if( bVer )
2316 nScrollFlags |= AUTOSCROLL_VERT;
2317 if( nScrollFlags )
2319 pView->StartAutoScroll( nScrollFlags );
2320 return sal_True;
2323 break;
2325 case COMMAND_WHEEL:
2327 const CommandWheelData* pData = rCmd.GetWheelData();
2328 if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2330 sal_uLong nScrollLines = pData->GetScrollLines();
2331 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2333 nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2334 if( pData->GetDelta() < 0 )
2335 nScrollDY *= -1;
2337 else
2339 nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2340 nScrollDY *= GetScrollBarLineSize();
2344 break;
2346 case COMMAND_AUTOSCROLL:
2348 const CommandScrollData* pData = rCmd.GetAutoScrollData();
2349 if( pData )
2351 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2352 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2355 break;
2358 if( nScrollDX || nScrollDY )
2360 aVisRect.Top() -= nScrollDY;
2361 aVisRect.Bottom() -= nScrollDY;
2362 aVisRect.Left() -= nScrollDX;
2363 aVisRect.Right() -= nScrollDX;
2364 MakeVisible( aVisRect );
2365 return sal_True;
2367 return sal_False;
2371 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2373 // scroll mouse event?
2374 if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2375 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2376 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2378 if( HandleScrollCommand( rCEvt ) )
2379 return;
2383 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2385 if( !pZOrderList->empty()
2386 && pEntry != pZOrderList->back()
2388 for(
2389 SvxIconChoiceCtrlEntryList_impl::iterator it = pZOrderList->begin();
2390 it != pZOrderList->end();
2391 ++it
2393 if ( *it == pEntry )
2395 pZOrderList->erase( it );
2396 pZOrderList->push_back( pEntry );
2397 break;
2403 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2405 if( rRect.Bottom() >= aVirtOutputSize.Height() )
2406 rRect.Bottom() = aVirtOutputSize.Height() - 1;
2407 if( rRect.Right() >= aVirtOutputSize.Width() )
2408 rRect.Right() = aVirtOutputSize.Width() - 1;
2409 if( rRect.Top() < 0 )
2410 rRect.Top() = 0;
2411 if( rRect.Left() < 0 )
2412 rRect.Left() = 0;
2415 // rRect: area of the document (in document coordinates) that we want to make
2416 // visible
2417 // bScrBar == sal_True: rectangle was calculated because of a scrollbar event
2419 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar,
2420 sal_Bool bCallRectChangedHdl )
2422 Rectangle aVirtRect( rRect );
2423 ClipAtVirtOutRect( aVirtRect );
2424 Point aOrigin( pView->GetMapMode().GetOrigin() );
2425 // convert to document coordinate
2426 aOrigin *= -1;
2427 Rectangle aOutputArea( GetOutputRect() );
2428 if( aOutputArea.IsInside( aVirtRect ) )
2429 return; // is already visible
2431 long nDy;
2432 if( aVirtRect.Top() < aOutputArea.Top() )
2434 // scroll up (nDy < 0)
2435 nDy = aVirtRect.Top() - aOutputArea.Top();
2437 else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2439 // scroll down (nDy > 0)
2440 nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2442 else
2443 nDy = 0;
2445 long nDx;
2446 if( aVirtRect.Left() < aOutputArea.Left() )
2448 // scroll to the left (nDx < 0)
2449 nDx = aVirtRect.Left() - aOutputArea.Left();
2451 else if( aVirtRect.Right() > aOutputArea.Right() )
2453 // scroll to the right (nDx > 0)
2454 nDx = aVirtRect.Right() - aOutputArea.Right();
2456 else
2457 nDx = 0;
2459 aOrigin.X() += nDx;
2460 aOrigin.Y() += nDy;
2461 aOutputArea.SetPos( aOrigin );
2462 if( GetUpdateMode() )
2464 HideDDIcon();
2465 pView->Update();
2466 ShowCursor( sal_False );
2469 // invert origin for SV (so we can scroll/paint using document coordinates)
2470 aOrigin *= -1;
2471 SetOrigin( aOrigin );
2473 sal_Bool bScrollable = pView->GetBackground().IsScrollable();
2474 if( pView->HasBackground() && !bScrollable )
2476 Rectangle aRect( GetOutputRect());
2477 Wallpaper aPaper( pView->GetBackground() );
2478 aPaper.SetRect( aRect );
2479 pView->SetBackground( aPaper );
2482 if( bScrollable && GetUpdateMode() )
2484 // scroll in reverse direction!
2485 pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2486 SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2488 else
2489 pView->Invalidate(INVALIDATE_NOCHILDREN);
2491 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2493 if( !bScrBar )
2495 aOrigin *= -1;
2496 // correct thumbs
2497 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2498 aHorSBar.SetThumbPos( aOrigin.X() );
2499 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2500 aVerSBar.SetThumbPos( aOrigin.Y() );
2504 if( GetUpdateMode() )
2505 ShowCursor( sal_True );
2507 // check if we still need scrollbars
2508 CheckScrollBars();
2509 if( bScrollable && GetUpdateMode() )
2510 pView->Update();
2512 // If the requested area can not be made completely visible, the
2513 // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2514 // if only few pixels of the lower border are invisible, but a scrollbar has
2515 // a larger line size.
2516 if( bCallRectChangedHdl || GetOutputRect() != rRect )
2517 VisRectChanged();
2520 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2522 if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2523 return 1;
2524 return nSelectionCount;
2527 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2529 sal_Bool bSel;
2530 if( pEntry->IsSelected() )
2531 bSel = sal_False;
2532 else
2533 bSel = sal_True;
2534 SelectEntry( pEntry, bSel, sal_True, sal_True );
2537 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2538 sal_Bool bPaintSync )
2540 ClearSelectedRectList();
2542 // TODO: work through z-order list, if necessary!
2544 size_t nCount = aEntries.size();
2545 for( size_t nCur = 0; nCur < nCount; nCur++ )
2547 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
2548 if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2549 SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync );
2551 pAnchor = 0;
2552 nFlags &= (~F_ADD_MODE);
2555 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2557 Size aMinSize( aImageSize );
2558 aMinSize.Width() += 2 * LROFFS_BOUND;
2559 aMinSize.Height() += TBOFFS_BOUND; // single offset is enough (FileDlg)
2560 OUString aStrDummy( "XXX" );
2561 Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2562 if( nWinBits & WB_ICON )
2564 aMinSize.Height() += VER_DIST_BMP_STRING;
2565 aMinSize.Height() += aTextSize.Height();
2567 else
2569 aMinSize.Width() += HOR_DIST_BMP_STRING;
2570 aMinSize.Width() += aTextSize.Width();
2572 return aMinSize;
2575 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
2577 Size aSize( rSize );
2578 Size aMinSize( GetMinGrid() );
2579 if( aSize.Width() < aMinSize.Width() )
2580 aSize.Width() = aMinSize.Width();
2581 if( aSize.Height() < aMinSize.Height() )
2582 aSize.Height() = aMinSize.Height();
2584 nGridDX = aSize.Width();
2585 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2586 // fly with a single column
2587 if( nWinBits & WB_DETAILS )
2589 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
2590 if( pCol )
2591 ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
2593 nGridDY = aSize.Height();
2594 SetDefaultTextSize();
2597 // Calculates the maximum size that the text rectangle may use within its
2598 // bounding rectangle. In WB_ICON mode with IcnShowTextFull, Bottom is set to
2599 // LONG_MAX.
2601 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
2603 Rectangle aBoundRect;
2604 // avoid infinite recursion: don't calculate the bounding rectangle here
2605 if( IsBoundingRectValid( pEntry->aRect ) )
2606 aBoundRect = pEntry->aRect;
2607 else
2608 aBoundRect = pEntry->aGridRect;
2610 Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
2611 (SvxIconChoiceCtrlEntry*)pEntry ) );
2612 if( nWinBits & WB_ICON )
2614 aBoundRect.Top() = aBmpRect.Bottom();
2615 aBoundRect.Top() += VER_DIST_BMP_STRING;
2616 if( aBoundRect.Top() > aBoundRect.Bottom())
2617 aBoundRect.Top() = aBoundRect.Bottom();
2618 aBoundRect.Left() += LROFFS_BOUND;
2619 aBoundRect.Left()++;
2620 aBoundRect.Right() -= LROFFS_BOUND;
2621 aBoundRect.Right()--;
2622 if( aBoundRect.Left() > aBoundRect.Right())
2623 aBoundRect.Left() = aBoundRect.Right();
2624 if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
2625 aBoundRect.Bottom() = LONG_MAX;
2627 else
2629 aBoundRect.Left() = aBmpRect.Right();
2630 aBoundRect.Left() += HOR_DIST_BMP_STRING;
2631 aBoundRect.Right() -= LROFFS_BOUND;
2632 if( aBoundRect.Left() > aBoundRect.Right() )
2633 aBoundRect.Left() = aBoundRect.Right();
2634 long nHeight = aBoundRect.GetSize().Height();
2635 nHeight = nHeight - aDefaultTextSize.Height();
2636 nHeight /= 2;
2637 aBoundRect.Top() += nHeight;
2638 aBoundRect.Bottom() -= nHeight;
2640 return aBoundRect;
2643 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2645 long nDY = nGridDY;
2646 nDY -= aImageSize.Height();
2647 nDY -= VER_DIST_BMP_STRING;
2648 nDY -= 2*TBOFFS_BOUND;
2649 if( nDY <= 0 )
2650 nDY = 2;
2652 long nDX = nGridDX;
2653 nDX -= 2*LROFFS_BOUND;
2654 nDX -= 2;
2655 if( nDX <= 0 )
2656 nDX = 2;
2658 long nHeight = pView->GetTextHeight();
2659 if( nDY < nHeight )
2660 nDY = nHeight;
2661 aDefaultTextSize = Size( nDX, nDY );
2665 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
2667 pEntry->aRect = pEntry->aGridRect;
2668 Size aSize( CalcBoundingSize( pEntry ) );
2669 if( nWinBits & WB_ICON )
2671 // center horizontally
2672 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
2673 pEntry->aRect.Left() += nBorder / 2;
2674 pEntry->aRect.Right() -= nBorder / 2;
2676 // center vertically
2677 pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
2681 // The deltas are the offsets by which the view is moved on the document.
2682 // left, up: offsets < 0
2683 // right, down: offsets > 0
2684 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
2686 const MapMode& rMapMode = pView->GetMapMode();
2687 Point aOrigin( rMapMode.GetOrigin() );
2688 // convert to document coordinate
2689 aOrigin *= -1;
2690 aOrigin.Y() += nDeltaY;
2691 aOrigin.X() += nDeltaX;
2692 Rectangle aRect( aOrigin, aOutputSize );
2693 MakeVisible( aRect, bScrollBar );
2697 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
2698 IcnViewFieldType eItem ) const
2700 if( eItem == IcnViewFieldTypeText )
2701 return aDefaultTextSize;
2702 return aImageSize;
2705 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
2707 Rectangle aTextRect( CalcTextRect( pEntry ) );
2708 Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
2709 return Rectangle(
2710 aBoundRect.Left(), aBoundRect.Top() - 1, aBoundRect.Right() - 1,
2711 aTextRect.Bottom() + 1);
2714 // the hot spot is the inner 50 % of the rectangle
2715 static Rectangle GetHotSpot( const Rectangle& rRect )
2717 Rectangle aResult( rRect );
2718 aResult.Justify();
2719 Size aSize( rRect.GetSize() );
2720 long nDelta = aSize.Width() / 4;
2721 aResult.Left() += nDelta;
2722 aResult.Right() -= nDelta;
2723 nDelta = aSize.Height() / 4;
2724 aResult.Top() += nDelta;
2725 aResult.Bottom() -= nDelta;
2726 return aResult;
2729 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
2730 sal_Bool bAdd, std::vector<Rectangle*>* pOtherRects )
2732 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2733 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2734 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2735 SelectRect( aRect, bAdd, pOtherRects );
2738 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, bool bAdd,
2739 std::vector<Rectangle*>* pOtherRects )
2741 aCurSelectionRect = rRect;
2742 if( !pZOrderList || !pZOrderList->size() )
2743 return;
2745 // set flag, so ToTop won't be called in Select
2746 sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False;
2747 nFlags |= F_SELECTING_RECT;
2749 CheckBoundingRects();
2750 pView->Update();
2751 const size_t nCount = pZOrderList->size();
2753 Rectangle aRect( rRect );
2754 aRect.Justify();
2755 bool bCalcOverlap = (bAdd && pOtherRects && !pOtherRects->empty()) ? true : false;
2757 sal_Bool bResetClipRegion = sal_False;
2758 if( !pView->IsClipRegion() )
2760 bResetClipRegion = sal_True;
2761 pView->SetClipRegion(Region(GetOutputRect()));
2764 for( size_t nPos = 0; nPos < nCount; nPos++ )
2766 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nPos ];
2768 if( !IsBoundingRectValid( pEntry->aRect ))
2769 FindBoundingRect( pEntry );
2770 Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
2771 sal_Bool bSelected = pEntry->IsSelected();
2773 sal_Bool bOverlaps;
2774 if( bCalcOverlap )
2775 bOverlaps = IsOver( pOtherRects, aBoundRect );
2776 else
2777 bOverlaps = sal_False;
2778 sal_Bool bOver = aRect.IsOver( aBoundRect );
2780 if( bOver && !bOverlaps )
2782 // is inside the new selection rectangle and outside of any old one
2783 // => select
2784 if( !bSelected )
2785 SelectEntry( pEntry, sal_True, sal_True, sal_True );
2787 else if( !bAdd )
2789 // is outside of the selection rectangle
2790 // => deselect
2791 if( bSelected )
2792 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2794 else if( bAdd && bOverlaps )
2796 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2797 // selection rectangle.
2799 // There is still a bug here! The selection status of an entry in a
2800 // previous rectangle has to be restored, if it was touched by the
2801 // current selection rectangle but is not inside it any more.
2802 // For simplicity's sake, let's assume that all entries in the old
2803 // rectangles were correctly selected. It is wrong to just deselect
2804 // the intersection.
2805 // Possible solution: remember a snapshot of the selection before
2806 // spanning the rectangle.
2807 if( aBoundRect.IsOver( rRect))
2809 // deselect intersection between old rectangles and current rectangle
2810 if( bSelected )
2811 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2813 else
2815 // select entry of an old rectangle
2816 if( !bSelected )
2817 SelectEntry( pEntry, sal_True, sal_True, sal_True );
2820 else if( !bOver && bSelected )
2822 // this entry is completely outside the rectangle => deselect it
2823 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2827 if( !bAlreadySelectingRect )
2828 nFlags &= ~F_SELECTING_RECT;
2830 pView->Update();
2831 if( bResetClipRegion )
2832 pView->SetClipRegion();
2835 void SvxIconChoiceCtrl_Impl::SelectRange(
2836 SvxIconChoiceCtrlEntry* pStart,
2837 SvxIconChoiceCtrlEntry* pEnd,
2838 sal_Bool bAdd )
2840 sal_uLong nFront = GetEntryListPos( pStart );
2841 sal_uLong nBack = GetEntryListPos( pEnd );
2842 sal_uLong nFirst = std::min( nFront, nBack );
2843 sal_uLong nLast = std::max( nFront, nBack );
2844 sal_uLong i;
2845 SvxIconChoiceCtrlEntry* pEntry;
2847 if ( ! bAdd )
2849 // deselect everything before the first entry if not in
2850 // adding mode
2851 for ( i=0; i<nFirst; i++ )
2853 pEntry = GetEntry( i );
2854 if( pEntry->IsSelected() )
2855 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
2859 // select everything between nFirst and nLast
2860 for ( i=nFirst; i<=nLast; i++ )
2862 pEntry = GetEntry( i );
2863 if( ! pEntry->IsSelected() )
2864 SelectEntry( pEntry, sal_True, sal_True, sal_True, sal_True );
2867 if ( ! bAdd )
2869 // deselect everything behind the last entry if not in
2870 // adding mode
2871 sal_uLong nEnd = GetEntryCount();
2872 for ( ; i<nEnd; i++ )
2874 pEntry = GetEntry( i );
2875 if( pEntry->IsSelected() )
2876 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
2881 bool SvxIconChoiceCtrl_Impl::IsOver( std::vector<Rectangle*>* pRectList, const Rectangle& rBoundRect ) const
2883 const sal_uInt16 nCount = pRectList->size();
2884 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2886 Rectangle* pRect = (*pRectList)[ nCur ];
2887 if( rBoundRect.IsOver( *pRect ))
2888 return true;
2890 return false;
2893 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
2894 SvxIconChoiceCtrlEntry* pEntry2 )
2896 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2897 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2898 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2899 AddSelectedRect( aRect );
2902 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
2904 Rectangle* pRect = new Rectangle( rRect );
2905 pRect->Justify();
2906 aSelectedRectList.push_back( pRect );
2909 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2911 const sal_uInt16 nCount = aSelectedRectList.size();
2912 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2914 Rectangle* pRect = aSelectedRectList[ nCur ];
2915 delete pRect;
2917 aSelectedRectList.clear();
2920 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, AutoArrangeHdl)
2922 aAutoArrangeTimer.Stop();
2923 Arrange( IsAutoArrange() );
2924 return 0;
2927 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, VisRectChangedHdl)
2929 aVisRectChangedTimer.Stop();
2930 pView->VisibleRectChanged();
2931 return 0;
2934 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, DocRectChangedHdl)
2936 aDocRectChangedTimer.Stop();
2937 pView->DocumentRectChanged();
2938 return 0;
2941 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
2943 Rectangle aRect( CalcTextRect( pEntry ));
2944 if( aRect.IsInside( rDocPos ) )
2945 return sal_True;
2946 return sal_False;
2949 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, EditTimeoutHdl)
2951 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
2952 if( bEntryEditingEnabled && pEntry &&
2953 pEntry->IsSelected())
2955 if( pView->EditingEntry( pEntry ))
2956 EditEntry( pEntry );
2958 return 0;
2963 // Function to align entries to the grid
2966 // pStart == 0: align all entries
2967 // else: align all entries of the row from pStart on (including pStart)
2968 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
2970 IconChoiceMap aLists;
2971 pImpCursor->CreateGridAjustData( aLists, pStart );
2972 for (IconChoiceMap::const_iterator iter = aLists.begin();
2973 iter != aLists.end(); ++iter)
2975 AdjustAtGrid(iter->second, pStart);
2977 IcnCursor_Impl::DestroyGridAdjustData( aLists );
2978 CheckScrollBars();
2981 // align a row, might expand width, doesn't break the line
2982 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvxIconChoiceCtrlEntryPtrVec& rRow, SvxIconChoiceCtrlEntry* pStart )
2984 if( rRow.empty() )
2985 return;
2987 sal_Bool bGo;
2988 if( !pStart )
2989 bGo = sal_True;
2990 else
2991 bGo = sal_False;
2993 long nCurRight = 0;
2994 for( sal_uInt16 nCur = 0; nCur < rRow.size(); nCur++ )
2996 SvxIconChoiceCtrlEntry* pCur = rRow[ nCur ];
2997 if( !bGo && pCur == pStart )
2998 bGo = sal_True;
3000 // SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3001 // Decisive (for our eye) is the bitmap, else, the entry might jump too
3002 // much within long texts.
3003 const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3004 Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3005 if( bGo && !pCur->IsPosLocked() )
3007 long nWidth = aCenterRect.GetSize().Width();
3008 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3009 while( aNewPos.X() < nCurRight )
3010 aNewPos.X() += nGridDX;
3011 if( aNewPos != rBoundRect.TopLeft() )
3013 SetEntryPos( pCur, aNewPos );
3014 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3015 nFlags |= F_MOVED_ENTRIES;
3017 nCurRight = aNewPos.X() + nWidth;
3019 else
3021 nCurRight = rBoundRect.Right();
3026 // Aligns a rectangle to the grid, but doesn't guarantee that the new position
3027 // is vacant. The position can be used for SetEntryPos. The CenterRect describes
3028 // a part of the bounding rectangle that is used for calculating the target
3029 // rectangle.
3030 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3031 const Rectangle& rBoundRect ) const
3033 Point aPos( rCenterRect.TopLeft() );
3034 Size aSize( rCenterRect.GetSize() );
3036 aPos.X() -= LROFFS_WINBORDER;
3037 aPos.Y() -= TBOFFS_WINBORDER;
3039 // align (the center of the rectangle is the reference)
3040 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3041 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3042 aPos.X() = nGridX * nGridDX;
3043 aPos.Y() = nGridY * nGridDY;
3044 // horizontal center
3045 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3047 aPos.X() += LROFFS_WINBORDER;
3048 aPos.Y() += TBOFFS_WINBORDER;
3050 return aPos;
3053 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3055 if( !pEntry )
3057 if( eTextMode != eMode )
3059 if( eTextMode == IcnShowTextDontKnow )
3060 eTextMode = IcnShowTextShort;
3061 eTextMode = eMode;
3062 Arrange( sal_True );
3065 else
3067 if( pEntry->eTextMode != eMode )
3069 pEntry->eTextMode = eMode;
3070 InvalidateEntry( pEntry );
3071 pView->Invalidate( GetEntryBoundRect( pEntry ) );
3072 AdjustVirtSize( pEntry->aRect );
3077 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3079 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3080 SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3081 if( eMode == IcnShowTextDontKnow )
3082 return eTextMode;
3083 return eMode;
3086 ////////////////////////////////////////////////////////////////////////////////////////////////
3088 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3089 // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
3090 // a gray focusrect on a gray background !!!
3092 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3094 Color aBkgColor ( pView->GetBackground().GetColor() );
3095 Color aPenColor;
3096 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3097 if ( nColor > 128 )
3098 aPenColor.SetColor ( COL_BLACK );
3099 else
3100 aPenColor.SetColor( COL_WHITE );
3102 aFocus.bOn = sal_True;
3103 aFocus.aPenColor = aPenColor;
3104 aFocus.aRect = rRect;
3107 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3109 pOut->SetLineColor( aFocus.aPenColor );
3110 pOut->SetFillColor();
3111 Polygon aPolygon ( aFocus.aRect );
3113 LineInfo aLineInfo ( LINE_DASH );
3115 aLineInfo.SetDashLen ( 1 );
3117 aLineInfo.SetDotLen ( 1L );
3118 aLineInfo.SetDistance ( 1L );
3119 aLineInfo.SetDotCount ( 1 );
3121 pOut->DrawPolyLine ( aPolygon, aLineInfo );
3124 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
3126 sal_Bool bRet = sal_False;
3127 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3128 size_t nEntryCount = GetEntryCount();
3129 for ( size_t i = 0; i < nEntryCount; ++i )
3131 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3133 bRet = sal_True;
3134 rPos = i;
3135 break;
3139 return bRet;
3143 ////////////////////////////////////////////////////////////////////////////////////////////////
3145 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3147 if( nId == EVENTID_ADJUST_SCROLLBARS )
3149 nUserEventAdjustScrBars = 0;
3150 AdjustScrollBars();
3152 else if( nId == EVENTID_SHOW_CURSOR )
3154 nUserEventShowCursor = 0;
3155 ShowCursor( sal_True );
3157 return 0;
3160 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3162 if( nUserEventAdjustScrBars )
3164 Application::RemoveUserEvent( nUserEventAdjustScrBars );
3165 nUserEventAdjustScrBars = 0;
3167 if( nUserEventShowCursor )
3169 Application::RemoveUserEvent( nUserEventShowCursor );
3170 nUserEventShowCursor = 0;
3174 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3176 if( pEntry == pCursor )
3177 ShowCursor( sal_False );
3178 pView->Invalidate( pEntry->aRect );
3179 Center( pEntry );
3180 pView->Invalidate( pEntry->aRect );
3181 if( pEntry == pCursor )
3182 ShowCursor( sal_True );
3185 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3187 DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3188 if( !pEntry )
3189 return;
3191 StopEntryEditing( sal_True );
3192 DELETEZ(pEdit);
3193 SetNoSelection();
3195 pCurEditedEntry = pEntry;
3196 OUString aEntryText( pView->GetEntryText( pEntry, sal_True ) );
3197 Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) );
3198 MakeVisible( aRect );
3199 Point aPos( aRect.TopLeft() );
3200 aPos = pView->GetPixelPos( aPos );
3201 aRect.SetPos( aPos );
3202 pView->HideFocus();
3203 pEdit = new IcnViewEdit_Impl(
3204 pView,
3205 aRect.TopLeft(),
3206 aRect.GetSize(),
3207 aEntryText,
3208 LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3211 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, TextEditEndedHdl)
3213 DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3214 if( !pEdit )
3216 pCurEditedEntry = 0;
3217 return 0;
3219 DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3221 if( !pCurEditedEntry )
3223 pEdit->Hide();
3224 if( pEdit->IsGrabFocus() )
3225 pView->GrabFocus();
3226 return 0;
3229 OUString aText;
3230 if ( !pEdit->EditingCanceled() )
3231 aText = pEdit->GetText();
3232 else
3233 aText = pEdit->GetSavedValue();
3235 if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3236 InvalidateEntry( pCurEditedEntry );
3237 if( !GetSelectionCount() )
3238 SelectEntry( pCurEditedEntry, sal_True );
3240 pEdit->Hide();
3241 if( pEdit->IsGrabFocus() )
3242 pView->GrabFocus();
3243 // The edit can not be deleted here, because it is not within a handler. It
3244 // will be deleted in the dtor or in the next EditEntry.
3245 pCurEditedEntry = 0;
3246 return 0;
3249 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel )
3251 if( pEdit )
3252 pEdit->StopEditing( bCancel );
3255 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3257 if( !GetSelectionCount() )
3258 return 0;
3260 if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3262 rPos = pView->GetEntryListPos( pCurHighlightFrame );
3263 return pCurHighlightFrame;
3266 size_t nCount = aEntries.size();
3267 if( !pHead )
3269 for( size_t nCur = 0; nCur < nCount; nCur++ )
3271 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3272 if( pEntry->IsSelected() )
3274 rPos = nCur;
3275 return pEntry;
3279 else
3281 SvxIconChoiceCtrlEntry* pEntry = pHead;
3282 while( nCount-- )
3284 if( pEntry->IsSelected() )
3286 rPos = GetEntryListPos( pEntry );
3287 return pEntry;
3289 pEntry = pEntry->pflink;
3290 if( nCount && pEntry == pHead )
3292 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
3293 return 0;
3297 return 0;
3300 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint )
3302 bPaint = sal_True;
3304 size_t nCount = aEntries.size();
3305 for( size_t nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3307 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3308 SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint );
3310 nFlags &= (~F_ADD_MODE);
3311 pAnchor = 0;
3314 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3315 const Size& rSize, const OUString& rData, const Link& rNotifyEditEnd ) :
3316 MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3317 aCallBackHdl( rNotifyEditEnd ),
3318 bCanceled( sal_False ),
3319 bAlreadyInCallback( sal_False ),
3320 bGrabFocus( sal_False )
3322 Font aFont( pParent->GetPointFont() );
3323 aFont.SetTransparent( sal_False );
3324 SetControlFont( aFont );
3325 if( !pParent->HasFontFillColor() )
3327 Color aColor( pParent->GetBackground().GetColor() );
3328 SetControlBackground( aColor );
3330 else
3331 SetControlBackground( aFont.GetFillColor() );
3332 SetControlForeground( aFont.GetColor() );
3333 SetPosPixel( rPos );
3334 SetSizePixel( CalcAdjustedSize(rSize) );
3335 SetText( rData );
3336 SaveValue();
3338 aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3339 aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3341 aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3342 aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3343 GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3344 GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3345 Show();
3346 GrabFocus();
3349 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3351 if( !bAlreadyInCallback )
3353 GetpApp()->RemoveAccel( &aAccReturn );
3354 GetpApp()->RemoveAccel( &aAccEscape );
3358 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3360 aTimer.Stop();
3361 if ( !bAlreadyInCallback )
3363 bAlreadyInCallback = sal_True;
3364 GetpApp()->RemoveAccel( &aAccReturn );
3365 GetpApp()->RemoveAccel( &aAccEscape );
3366 Hide();
3367 aCallBackHdl.Call( this );
3371 IMPL_LINK_NOARG(IcnViewEdit_Impl, Timeout_Impl)
3373 CallCallBackHdl_Impl();
3374 return 0;
3377 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG )
3379 bCanceled = sal_False;
3380 bGrabFocus = sal_True;
3381 CallCallBackHdl_Impl();
3382 return 1;
3385 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG )
3387 bCanceled = sal_True;
3388 bGrabFocus = sal_True;
3389 CallCallBackHdl_Impl();
3390 return 1;
3393 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3395 KeyCode aCode = rKEvt.GetKeyCode();
3396 sal_uInt16 nCode = aCode.GetCode();
3398 switch ( nCode )
3400 case KEY_ESCAPE:
3401 bCanceled = sal_True;
3402 bGrabFocus = sal_True;
3403 CallCallBackHdl_Impl();
3404 break;
3406 case KEY_RETURN:
3407 bCanceled = sal_False;
3408 bGrabFocus = sal_True;
3409 CallCallBackHdl_Impl();
3410 break;
3412 default:
3413 MultiLineEdit::KeyInput( rKEvt );
3417 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3419 if( rNEvt.GetType() == EVENT_LOSEFOCUS )
3421 if ( !bAlreadyInCallback &&
3422 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
3424 bCanceled = sal_False;
3425 aTimer.SetTimeout(10);
3426 aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
3427 aTimer.Start();
3430 return 0;
3433 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel )
3435 if ( !bAlreadyInCallback )
3437 bCanceled = bCancel;
3438 CallCallBackHdl_Impl();
3442 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
3444 if( !(nFlags & F_ENTRYLISTPOS_VALID ))
3445 ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
3446 return pEntry->nPos;
3449 void SvxIconChoiceCtrl_Impl::InitSettings()
3451 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
3453 if( !pView->HasFont() )
3455 // unit (from settings) is Point
3456 Font aFont( rStyleSettings.GetFieldFont() );
3457 //const Font& rFont = pView->GetFont();
3458 //if( pView->HasFontTextColor() )
3459 aFont.SetColor( rStyleSettings.GetWindowTextColor() );
3460 //if( pView->HasFontFillColor() )
3461 //aFont.SetFillColor( rFont.GetFillColor() );
3462 pView->SetPointFont( aFont );
3463 SetDefaultTextSize();
3466 //if( !pView->HasFontTextColor() )
3467 pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
3468 //if( !pView->HasFontFillColor() )
3469 pView->SetTextFillColor();
3471 //if( !pView->HasBackground() )
3472 pView->SetBackground( rStyleSettings.GetFieldColor());
3474 long nScrBarSize = rStyleSettings.GetScrollBarSize();
3475 if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
3477 nHorSBarHeight = nScrBarSize;
3478 Size aSize( aHorSBar.GetSizePixel() );
3479 aSize.Height() = nScrBarSize;
3480 aHorSBar.Hide();
3481 aHorSBar.SetSizePixel( aSize );
3483 nVerSBarWidth = nScrBarSize;
3484 aSize = aVerSBar.GetSizePixel();
3485 aSize.Width() = nScrBarSize;
3486 aVerSBar.Hide();
3487 aVerSBar.SetSizePixel( aSize );
3489 Size aOSize( pView->Control::GetOutputSizePixel() );
3490 PositionScrollBars( aOSize.Width(), aOSize.Height() );
3491 AdjustScrollBars();
3495 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner ) :
3496 _pOwner( pOwner )
3498 _pOwner->pHead = 0;
3501 EntryList_Impl::~EntryList_Impl()
3503 _pOwner->pHead = 0;
3506 void EntryList_Impl::clear()
3508 _pOwner->pHead = 0;
3509 maIconChoiceCtrlEntryList.clear();
3512 void EntryList_Impl::insert( size_t nPos, SvxIconChoiceCtrlEntry* pEntry )
3514 if ( nPos < maIconChoiceCtrlEntryList.size() ) {
3515 maIconChoiceCtrlEntryList.insert( maIconChoiceCtrlEntryList.begin() + nPos, pEntry );
3516 } else {
3517 maIconChoiceCtrlEntryList.push_back( pEntry );
3519 if( _pOwner->pHead )
3520 pEntry->SetBacklink( _pOwner->pHead->pblink );
3523 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
3525 if( eMode == ePositionMode )
3526 return;
3528 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
3529 ePositionMode = eMode;
3530 size_t nCount = aEntries.size();
3532 if( eOldMode == IcnViewPositionModeAutoArrange )
3534 // when positioning moved entries "hard", there are problems with
3535 // unwanted overlaps, as these entries aren't taken into account in
3536 // Arrange.
3537 if( aEntries.size() )
3538 aAutoArrangeTimer.Start();
3539 return;
3542 if( ePositionMode == IcnViewPositionModeAutoArrange )
3544 for( size_t nCur = 0; nCur < nCount; nCur++ )
3546 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3547 if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
3548 SetEntryPos(pEntry, GetEntryBoundRect( pEntry ).TopLeft());
3551 if( aEntries.size() )
3552 aAutoArrangeTimer.Start();
3554 else if( ePositionMode == IcnViewPositionModeAutoAdjust )
3556 AdjustEntryAtGrid( 0 );
3560 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3561 SvxIconChoiceCtrlEntry* pPredecessor )
3563 if( !IsAutoArrange() )
3564 return;
3566 if( pEntry == pPredecessor )
3567 return;
3569 sal_uLong nPos1 = GetEntryListPos( pEntry );
3570 if( !pHead )
3572 if( pPredecessor )
3574 sal_uLong nPos2 = GetEntryListPos( pPredecessor );
3575 if( nPos1 == (nPos2 + 1) )
3576 return; // is already the predecessor
3578 else if( !nPos1 )
3579 return;
3582 if( !pHead )
3583 InitPredecessors();
3585 if( !pPredecessor && pHead == pEntry )
3586 return; // is already the first one
3588 sal_Bool bSetHead = sal_False;
3589 if( !pPredecessor )
3591 bSetHead = sal_True;
3592 pPredecessor = pHead->pblink;
3594 if( pEntry == pHead )
3596 pHead = pHead->pflink;
3597 bSetHead = sal_False;
3599 if( pEntry != pPredecessor )
3601 pEntry->Unlink();
3602 pEntry->SetBacklink( pPredecessor );
3604 if( bSetHead )
3605 pHead = pEntry;
3606 pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
3607 aAutoArrangeTimer.Start();
3610 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3611 const Point& rPosTopLeft )
3613 Point aPos( rPosTopLeft ); //TopLeft
3614 Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
3615 Point aNewPos( aCenterRect.Center() );
3616 sal_uLong nGrid = GetPredecessorGrid( aNewPos );
3617 size_t nCount = aEntries.size();
3618 if( nGrid == ULONG_MAX )
3619 return 0;
3620 if( nGrid >= nCount )
3621 nGrid = nCount - 1;
3622 if( !pHead )
3623 return aEntries[ nGrid ];
3625 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
3626 // TODO: go through list from the end if nGrid > nCount/2
3627 for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
3628 pCur = pCur->pflink;
3630 return pCur;
3633 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
3635 Point aPos( rPos );
3636 aPos.X() -= LROFFS_WINBORDER;
3637 aPos.Y() -= TBOFFS_WINBORDER;
3638 sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX);
3639 if( nMaxCol )
3640 nMaxCol--;
3641 sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX);
3642 if( nGridX > nMaxCol )
3643 nGridX = nMaxCol;
3644 sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY);
3645 sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX);
3646 sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
3647 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
3648 if( rPos.X() < nMiddle )
3650 if( !nGrid )
3651 nGrid = ULONG_MAX;
3652 else
3653 nGrid--;
3655 return nGrid;
3658 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
3660 if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
3661 return sal_False;
3663 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
3664 aPos -= pView->GetMapMode().GetOrigin();
3665 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True );
3667 if ( !pEntry )
3668 return sal_False;
3670 OUString sQuickHelpText = pEntry->GetQuickHelpText();
3671 OUString aEntryText( pView->GetEntryText( pEntry, sal_False ) );
3672 Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) );
3673 if ( ( !aTextRect.IsInside( aPos ) || aEntryText.isEmpty() ) && sQuickHelpText.isEmpty() )
3674 return sal_False;
3676 Rectangle aOptTextRect( aTextRect );
3677 aOptTextRect.Bottom() = LONG_MAX;
3678 sal_uInt16 nNewFlags = nCurTextDrawFlags;
3679 nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
3680 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
3681 if ( aOptTextRect != aTextRect || !sQuickHelpText.isEmpty() )
3683 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
3684 Point aPt( aOptTextRect.TopLeft() );
3685 aPt += pView->GetMapMode().GetOrigin();
3686 aPt = pView->OutputToScreenPixel( aPt );
3687 // subtract border of tooltip help
3688 aPt.Y() -= 1;
3689 aPt.X() -= 3;
3690 aOptTextRect.SetPos( aPt );
3691 OUString sHelpText;
3692 if ( !sQuickHelpText.isEmpty() )
3693 sHelpText = sQuickHelpText;
3694 else
3695 sHelpText = aEntryText;
3696 Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
3699 return sal_True;
3702 void SvxIconChoiceCtrl_Impl::ClearColumnList()
3704 if( !pColumns )
3705 return;
3707 pColumns->clear();
3708 DELETEZ(pColumns);
3711 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
3713 if( !pColumns )
3714 pColumns = new SvxIconChoiceCtrlColumnInfoMap;
3716 SvxIconChoiceCtrlColumnInfo* pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
3717 pColumns->insert( nIndex, pInfo );
3719 // HACK: Detail mode is not yet fully implemented, this workaround makes it
3720 // fly with a single column
3721 if( !nIndex && (nWinBits & WB_DETAILS) )
3722 nGridDX = pInfo->GetWidth();
3724 if( GetUpdateMode() )
3725 Arrange( IsAutoArrange() );
3728 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
3730 if (!pColumns)
3731 return 0;
3732 SvxIconChoiceCtrlColumnInfoMap::const_iterator it = pColumns->find( nIndex );
3733 if( it == pColumns->end() )
3734 return 0;
3735 return it->second;
3738 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
3739 OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide )
3741 Rectangle aBmpRect( rBmpRect );
3742 long nBorder = 2;
3743 if( aImageSize.Width() < 32 )
3744 nBorder = 1;
3745 aBmpRect.Right() += nBorder;
3746 aBmpRect.Left() -= nBorder;
3747 aBmpRect.Bottom() += nBorder;
3748 aBmpRect.Top() -= nBorder;
3750 if ( bHide )
3751 pView->Invalidate( aBmpRect );
3752 else
3754 DecorationView aDecoView( pOut );
3755 sal_uInt16 nDecoFlags;
3756 if ( bHighlightFramePressed )
3757 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
3758 else
3759 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
3760 aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
3764 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
3765 sal_Bool bKeepHighlightFlags )
3767 if( pEntry == pCurHighlightFrame )
3768 return;
3770 if( !bKeepHighlightFlags )
3771 bHighlightFramePressed = sal_False;
3773 HideEntryHighlightFrame();
3774 pCurHighlightFrame = pEntry;
3775 if( pEntry )
3777 Rectangle aBmpRect( CalcFocusRect(pEntry) );
3778 DrawHighlightFrame( pView, aBmpRect, sal_False );
3782 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
3784 if( !pCurHighlightFrame )
3785 return;
3787 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
3788 pCurHighlightFrame = 0;
3789 Rectangle aBmpRect( CalcFocusRect(pEntry) );
3790 DrawHighlightFrame( pView, aBmpRect, sal_True );
3793 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
3795 // When single-click mode is active, the selection handler should be called
3796 // synchronously, as the selection is automatically taken away once the
3797 // mouse cursor doesn't touch the object any more. Else, we might run into
3798 // missing calls to Select if the object is selected from a mouse movement,
3799 // because when starting the timer, the mouse cursor might have already left
3800 // the object.
3801 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
3802 // WB_NOASYNCSELECTHDL.
3803 if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
3805 pHdlEntry = 0;
3806 pView->ClickIcon();
3807 //pView->Select();
3809 else
3810 aCallSelectHdlTimer.Start();
3813 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, CallSelectHdlHdl)
3815 pHdlEntry = 0;
3816 pView->ClickIcon();
3817 //pView->Select();
3818 return 0;
3821 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper )
3823 MapMode aMapMode( pView->GetMapMode() );
3824 aMapMode.SetOrigin( rPos );
3825 pView->SetMapMode( aMapMode );
3826 if( !bDoNotUpdateWallpaper )
3828 sal_Bool bScrollable = pView->GetBackground().IsScrollable();
3829 if( pView->HasBackground() && !bScrollable )
3831 Rectangle aRect( GetOutputRect());
3832 Wallpaper aPaper( pView->GetBackground() );
3833 aPaper.SetRect( aRect );
3834 pView->SetBackground( aPaper );
3839 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
3841 pView->CallImplEventListeners( nEvent, pData );
3845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */