fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / contnr / imivctl1.cxx
blobb0ea08268d1548debd90c6cb68f121ff4c2889ee
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 XubString& 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 String aTxt = pEntry->GetText();
346 if( _pGenerator->CreateMnemonic( aTxt ) )
347 pEntry->SetText( aTxt );
351 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
353 Point aOrigin( pView->GetMapMode().GetOrigin() );
354 aOrigin *= -1;
355 return Rectangle( aOrigin, aOutputSize );
358 void SvxIconChoiceCtrl_Impl::SetListPositions()
360 if( nFlags & F_ENTRYLISTPOS_VALID )
361 return;
363 size_t nCount = aEntries.size();
364 for( size_t nCur = 0; nCur < nCount; nCur++ )
366 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
367 pEntry->nPos = nCur;
369 nFlags |= F_ENTRYLISTPOS_VALID;
372 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
373 sal_Bool bCallHdl, sal_Bool bAdd, sal_Bool bSyncPaint )
375 if( eSelectionMode == NO_SELECTION )
376 return;
378 if( !bAdd )
380 if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
382 nFlags |= F_CLEARING_SELECTION;
383 DeselectAllBut( pEntry, sal_True );
384 nFlags &= ~F_CLEARING_SELECTION;
387 if( pEntry->IsSelected() != bSelect )
389 pHdlEntry = pEntry;
390 sal_uInt16 nEntryFlags = pEntry->GetFlags();
391 if( bSelect )
393 nEntryFlags |= ICNVIEW_FLAG_SELECTED;
394 pEntry->AssignFlags( nEntryFlags );
395 nSelectionCount++;
396 if( bCallHdl )
397 CallSelectHandler( pEntry );
399 else
401 nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
402 pEntry->AssignFlags( nEntryFlags );
403 nSelectionCount--;
404 if( bCallHdl )
405 CallSelectHandler( 0 );
407 EntrySelected( pEntry, bSelect, bSyncPaint );
411 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
412 sal_Bool bSyncPaint )
414 // When using SingleSelection, make sure that the cursor is always placed
415 // over the (only) selected entry. (But only if a cursor exists.)
416 if( bSelect && pCursor &&
417 eSelectionMode == SINGLE_SELECTION &&
418 pEntry != pCursor )
420 SetCursor( pEntry );
421 //DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
424 // Not when dragging though, else the loop in SelectRect doesn't work
425 // correctly!
426 if( !(nFlags & F_SELECTING_RECT) )
427 ToTop( pEntry );
428 if( bUpdateMode )
430 if( pEntry == pCursor )
431 ShowCursor( sal_False );
432 if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // always synchronous when tracking
433 PaintEntry( pEntry );
434 else if( bSyncPaint ) // synchronous & with a virtual OutDev!
435 PaintEntryVirtOutDev( pEntry );
436 else
438 pView->Invalidate( CalcFocusRect( pEntry ) );
440 if( pEntry == pCursor )
441 ShowCursor( sal_True );
444 // #i101012# emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
445 if ( bSelect )
447 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
451 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
453 StopEditTimer();
454 aVirtOutputSize.Width() = 0;
455 aVirtOutputSize.Height() = 0;
456 const size_t nCount = aEntries.size();
457 for( size_t nCur = 0; nCur < nCount; nCur++ )
459 SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
460 pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
461 if( pCur->IsPosLocked() )
463 // adapt (among others) VirtSize
464 if( !IsBoundingRectValid( pCur->aRect ) )
465 FindBoundingRect( pCur );
466 else
467 AdjustVirtSize( pCur->aRect );
469 else
470 InvalidateBoundingRect( pCur->aRect );
473 if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
475 Size aRealOutputSize( pView->GetOutputSizePixel() );
476 if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
477 aVirtOutputSize.Height() < aRealOutputSize.Height() )
479 sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
480 aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
481 if( nGridCount < nCount )
483 if( nWinBits & WB_ALIGN_TOP )
484 nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
485 else // WB_ALIGN_LEFT
486 nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
491 pImpCursor->Clear();
492 pGridMap->Clear();
493 VisRectChanged();
496 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
498 long nHeightOffs = 0;
499 long nWidthOffs = 0;
501 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
502 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
504 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
505 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
507 if( nWidthOffs || nHeightOffs )
509 Range aRange;
510 aVirtOutputSize.Width() += nWidthOffs;
511 aRange.Max() = aVirtOutputSize.Width();
512 aHorSBar.SetRange( aRange );
514 aVirtOutputSize.Height() += nHeightOffs;
515 aRange.Max() = aVirtOutputSize.Height();
516 aVerSBar.SetRange( aRange );
518 pImpCursor->Clear();
519 pGridMap->OutputSizeChanged();
520 AdjustScrollBars();
521 DocRectChanged();
525 void SvxIconChoiceCtrl_Impl::InitPredecessors()
527 DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
528 size_t nCount = aEntries.size();
529 if( nCount )
531 SvxIconChoiceCtrlEntry* pPrev = aEntries[ 0 ];
532 for( size_t nCur = 1; nCur <= nCount; nCur++ )
534 pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
535 ICNVIEW_FLAG_PRED_SET);
537 SvxIconChoiceCtrlEntry* pNext;
538 if( nCur == nCount )
539 pNext = aEntries[ 0 ];
540 else
541 pNext = aEntries[ nCur ];
542 pPrev->pflink = pNext;
543 pNext->pblink = pPrev;
544 pPrev = pNext;
546 pHead = aEntries[ 0 ];
548 else
549 pHead = 0;
550 nFlags &= ~F_MOVED_ENTRIES;
553 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
555 if( pHead )
557 size_t nCount = aEntries.size();
558 for( size_t nCur = 0; nCur < nCount; nCur++ )
560 SvxIconChoiceCtrlEntry* pCur = aEntries[ nCur ];
561 pCur->pflink = 0;
562 pCur->pblink = 0;
563 pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
565 pHead = 0;
569 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
571 if ( nSetMaxVirtWidth != 0 )
572 nMaxVirtWidth = nSetMaxVirtWidth;
573 else
574 nMaxVirtWidth = aOutputSize.Width();
576 if ( nSetMaxVirtHeight != 0 )
577 nMaxVirtHeight = nSetMaxVirtHeight;
578 else
579 nMaxVirtHeight = aOutputSize.Height();
581 ImpArrange( bKeepPredecessors );
584 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors )
586 static Point aEmptyPoint;
588 sal_Bool bOldUpdate = bUpdateMode;
589 Rectangle aCurOutputArea( GetOutputRect() );
590 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
591 bUpdateMode = sal_False;
592 aAutoArrangeTimer.Stop();
593 nFlags &= ~F_MOVED_ENTRIES;
594 nFlags |= F_ARRANGING;
595 StopEditTimer();
596 ShowCursor( sal_False );
597 ResetVirtSize();
598 if( !bKeepPredecessors )
599 ClearPredecessors();
600 bBoundRectsDirty = sal_False;
601 SetOrigin( Point() );
602 VisRectChanged();
603 RecalcAllBoundingRectsSmart();
604 // TODO: the invalidation in the detail view should be more intelligent
605 //if( !(nWinBits & WB_DETAILS ))
606 pView->Invalidate( INVALIDATE_NOCHILDREN );
607 nFlags &= ~F_ARRANGING;
608 if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
610 MakeVisible( aCurOutputArea );
611 SetUpdateMode( bOldUpdate );
613 ShowCursor( sal_True );
616 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
618 bEndScrollInvalidate = sal_False;
620 #if defined(OV_DRAWGRID)
621 Color aOldColor ( pView->GetLineColor() );
622 Color aColor( COL_BLACK );
623 pView->SetLineColor( aColor );
624 Point aOffs( pView->GetMapMode().GetOrigin());
625 Size aXSize( pView->GetOutputSizePixel() );
628 Point aStart( LROFFS_WINBORDER, 0 );
629 Point aEnd( LROFFS_WINBORDER, aXSize.Height());
630 aStart -= aOffs;
631 aEnd -= aOffs;
632 pView->DrawLine( aStart, aEnd );
635 Point aStart( 0, TBOFFS_WINBORDER );
636 Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
637 aStart -= aOffs;
638 aEnd -= aOffs;
639 pView->DrawLine( aStart, aEnd );
642 for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
644 Point aStart( nDX+LROFFS_WINBORDER, 0 );
645 Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
646 aStart -= aOffs;
647 aEnd -= aOffs;
648 pView->DrawLine( aStart, aEnd );
650 for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
652 Point aStart( 0, nDY+TBOFFS_WINBORDER );
653 Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
654 aStart -= aOffs;
655 aEnd -= aOffs;
656 pView->DrawLine( aStart, aEnd );
658 pView->SetLineColor( aOldColor );
659 #endif
660 nFlags |= F_PAINTED;
662 if( !aEntries.size() )
663 return;
664 if( !pCursor )
666 // set cursor to item with focus-flag
667 sal_Bool bfound = sal_False;
668 for ( sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++)
670 SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
671 if( pEntry->IsFocused() )
673 pCursor = pEntry;
674 bfound=sal_True;
678 if( !bfound )
679 pCursor = aEntries[ 0 ];
682 // Show Focus at Init-Time
683 if ( pView->HasFocus() )
684 GetFocus();
686 size_t nCount = pZOrderList->size();
687 if( !nCount )
688 return;
690 sal_Bool bResetClipRegion = sal_False;
691 if( !pView->IsClipRegion() )
693 Region const aOutputArea( GetOutputRect() );
694 bResetClipRegion = sal_True;
695 pView->SetClipRegion( aOutputArea );
698 SvxIconChoiceCtrlEntryList_impl* pNewZOrderList = new SvxIconChoiceCtrlEntryList_impl();
699 SvxIconChoiceCtrlEntryList_impl* pPaintedEntries = new SvxIconChoiceCtrlEntryList_impl();
701 size_t nPos = 0;
702 while( nCount )
704 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nPos ];
705 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
706 if( rRect.IsOver( rBoundRect ) )
708 PaintEntry( pEntry, rBoundRect.TopLeft(), pView, sal_True );
709 // set entries to Top if they are being repainted
710 pPaintedEntries->push_back( pEntry );
712 else
713 pNewZOrderList->push_back( pEntry );
715 nCount--;
716 nPos++;
718 delete pZOrderList;
719 pZOrderList = pNewZOrderList;
720 nCount = pPaintedEntries->size();
721 if( nCount )
723 for( size_t nCur = 0; nCur < nCount; nCur++ )
724 pZOrderList->push_back( (*pPaintedEntries)[ nCur ] );
726 delete pPaintedEntries;
728 if( bResetClipRegion )
729 pView->SetClipRegion();
732 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask )
734 const size_t nCount = pZOrderList->size();
735 if( !nCount )
736 return;
738 sal_Bool bResetClipRegion = sal_False;
739 Rectangle aOutRect( GetOutputRect() );
740 if( !pView->IsClipRegion() )
742 bResetClipRegion = sal_True;
743 pView->SetClipRegion(Region(aOutRect));
745 for( size_t nCur = 0; nCur < nCount; nCur++ )
747 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
748 if( pEntry->GetFlags() & nEntryFlagsMask )
750 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
751 if( aOutRect.IsOver( rBoundRect ) )
752 PaintEntry( pEntry, rBoundRect.TopLeft() );
755 if( bResetClipRegion )
756 pView->SetClipRegion();
760 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
762 aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
763 Size aSize( pView->GetOutputSizePixel() );
764 aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
767 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
769 sal_Bool bHandled = sal_True;
770 bHighlightFramePressed = sal_False;
771 StopEditTimer();
772 sal_Bool bGotFocus = (sal_Bool)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
773 if( !(nWinBits & WB_NOPOINTERFOCUS) )
774 pView->GrabFocus();
776 Point aDocPos( rMEvt.GetPosPixel() );
777 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
778 return sal_False;
779 ToDocPos( aDocPos );
780 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
781 if( pEntry )
782 MakeEntryVisible( pEntry, sal_False );
784 if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
786 if( pEntry )
787 SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), sal_True);
788 return sal_True;
791 if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // keyboard selection?
793 DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
794 if( rMEvt.IsMod1() )
795 nFlags |= F_ADD_MODE;
797 if( rMEvt.IsShift() )
799 Rectangle aRect( GetEntryBoundRect( pAnchor ));
800 if( pEntry )
801 aRect.Union( GetEntryBoundRect( pEntry ) );
802 else
804 Rectangle aTempRect( aDocPos, Size(1,1));
805 aRect.Union( aTempRect );
807 aCurSelectionRect = aRect;
808 SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
810 else if( rMEvt.IsMod1() )
812 AddSelectedRect( aCurSelectionRect );
813 pAnchor = 0;
814 aCurSelectionRect.SetPos( aDocPos );
817 if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
818 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
819 return sal_True;
821 else
823 if( !pEntry )
825 if( eSelectionMode == MULTIPLE_SELECTION )
827 if( !rMEvt.IsMod1() ) // Ctrl
829 if( !bGotFocus )
831 SetNoSelection();
832 ClearSelectedRectList();
835 else
836 nFlags |= F_ADD_MODE;
837 aCurSelectionRect.SetPos( aDocPos );
838 pView->StartTracking( STARTTRACK_SCROLLREPEAT );
840 else
841 bHandled = sal_False;
842 return bHandled;
845 sal_Bool bSelected = pEntry->IsSelected();
846 sal_Bool bEditingEnabled = IsEntryEditingEnabled();
848 if( rMEvt.GetClicks() == 2 )
850 DeselectAllBut( pEntry );
851 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
852 pHdlEntry = pEntry;
853 pView->ClickIcon();
855 else
857 // Inplace-Editing ?
858 if( rMEvt.IsMod2() ) // Alt?
860 if( bEntryEditingEnabled && pEntry &&
861 pEntry->IsSelected())
863 if( pView->EditingEntry( pEntry ))
864 EditEntry( pEntry );
867 else if( eSelectionMode == SINGLE_SELECTION )
869 DeselectAllBut( pEntry );
870 SetCursor( pEntry );
871 if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
872 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
874 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
877 else if( eSelectionMode == NO_SELECTION )
879 if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
881 pCurHighlightFrame = 0; // force repaint of frame
882 bHighlightFramePressed = sal_True;
883 SetEntryHighlightFrame( pEntry, sal_True );
886 else
888 if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
890 if( !bSelected )
892 DeselectAllBut( pEntry, sal_True /* paint synchronously */ );
893 SetCursor( pEntry );
894 SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
896 else
898 // deselect only in the Up, if the Move happened via D&D!
899 nFlags |= F_DOWN_DESELECT;
900 if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
901 rMEvt.IsLeft())
903 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
907 else if( rMEvt.IsMod1() )
908 nFlags |= F_DOWN_CTRL;
911 return bHandled;
914 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
916 sal_Bool bHandled = sal_False;
917 if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
919 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
920 bHandled = sal_True;
923 Point aDocPos( rMEvt.GetPosPixel() );
924 ToDocPos( aDocPos );
925 SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
926 if( pDocEntry )
928 if( nFlags & F_DOWN_CTRL )
930 // Ctrl & MultiSelection
931 ToggleSelection( pDocEntry );
932 SetCursor( pDocEntry );
933 bHandled = sal_True;
935 else if( nFlags & F_DOWN_DESELECT )
937 DeselectAllBut( pDocEntry );
938 SetCursor( pDocEntry );
939 SelectEntry( pDocEntry, sal_True, sal_True, sal_False, sal_True );
940 bHandled = sal_True;
944 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
945 if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
947 bHandled = sal_True;
948 StartEditTimer();
949 nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
952 if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
954 bHandled = sal_True;
955 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
956 pCurHighlightFrame = 0; // force repaint of frame
957 bHighlightFramePressed = sal_False;
958 SetEntryHighlightFrame( pEntry, sal_True );
960 pHdlEntry = pCurHighlightFrame;
961 pView->ClickIcon();
963 // set focus on Icon
964 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
965 SetCursor_Impl( pOldCursor, pHdlEntry, sal_False, sal_False, sal_True );
967 pHdlEntry = 0;
969 return bHandled;
972 sal_Bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
974 const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
976 if( pView->IsTracking() )
977 return sal_False;
978 else if( nWinBits & WB_HIGHLIGHTFRAME )
980 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
981 SetEntryHighlightFrame( pEntry );
983 else
984 return sal_False;
985 return sal_True;
988 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
989 SvxIconChoiceCtrlEntry* pNewCursor, sal_Bool bMod1, sal_Bool bShift, sal_Bool bPaintSync )
991 if( pNewCursor )
993 SvxIconChoiceCtrlEntry* pFilterEntry = 0;
994 sal_Bool bDeselectAll = sal_False;
995 if( eSelectionMode != SINGLE_SELECTION )
997 if( !bMod1 && !bShift )
998 bDeselectAll = sal_True;
999 else if( bShift && !bMod1 && !pAnchor )
1001 bDeselectAll = sal_True;
1002 pFilterEntry = pOldCursor;
1005 if( bDeselectAll )
1006 DeselectAllBut( pFilterEntry, bPaintSync );
1007 ShowCursor( sal_False );
1008 MakeEntryVisible( pNewCursor );
1009 SetCursor( pNewCursor );
1010 if( bMod1 && !bShift )
1012 if( pAnchor )
1014 AddSelectedRect( pAnchor, pOldCursor );
1015 pAnchor = 0;
1018 else if( bShift )
1020 if( !pAnchor )
1021 pAnchor = pOldCursor;
1022 if ( nWinBits & WB_ALIGN_LEFT )
1023 SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
1024 else
1025 SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
1027 else
1029 SelectEntry( pCursor, sal_True, sal_True, sal_False, bPaintSync );
1030 aCurSelectionRect = GetEntryBoundRect( pCursor );
1035 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1037 StopEditTimer();
1039 sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2();
1040 sal_Unicode cChar = rKEvt.GetCharCode();
1041 sal_uLong nPos = (sal_uLong)-1;
1042 if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1044 // shortcut is clicked
1045 SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1046 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1047 if ( pNewCursor != pOldCursor )
1048 SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
1049 return sal_True;
1052 if ( bMod2 )
1053 // no actions with <ALT>
1054 return sal_False;
1056 sal_Bool bKeyUsed = sal_True;
1057 sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1058 sal_Bool bShift = rKEvt.GetKeyCode().IsShift();
1060 if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1062 bShift = sal_False;
1063 bMod1 = sal_False;
1066 if( bMod1 )
1067 nFlags |= F_ADD_MODE;
1069 SvxIconChoiceCtrlEntry* pNewCursor;
1070 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1072 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1073 switch( nCode )
1075 case KEY_UP:
1076 case KEY_PAGEUP:
1077 if( pCursor )
1079 MakeEntryVisible( pCursor );
1080 if( nCode == KEY_UP )
1081 pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1082 else
1083 pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False);
1084 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1085 if( !pNewCursor )
1087 Rectangle aRect( GetEntryBoundRect( pCursor ) );
1088 if( aRect.Top())
1090 aRect.Bottom() -= aRect.Top();
1091 aRect.Top() = 0;
1092 MakeVisible( aRect );
1096 if ( bChooseWithCursor && pNewCursor != NULL )
1098 pHdlEntry = pNewCursor;//GetCurEntry();
1099 pCurHighlightFrame = pHdlEntry;
1100 pView->ClickIcon();
1101 pCurHighlightFrame = NULL;
1104 break;
1106 case KEY_DOWN:
1107 case KEY_PAGEDOWN:
1108 if( pCursor )
1110 if( nCode == KEY_DOWN )
1111 pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1112 else
1113 pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True );
1114 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1116 if ( bChooseWithCursor && pNewCursor != NULL)
1118 pHdlEntry = pNewCursor;//GetCurEntry();
1119 pCurHighlightFrame = pHdlEntry;
1120 pView->ClickIcon();
1121 pCurHighlightFrame = NULL;
1124 break;
1126 case KEY_RIGHT:
1127 if( pCursor )
1129 pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1130 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1132 break;
1134 case KEY_LEFT:
1135 if( pCursor )
1137 MakeEntryVisible( pCursor );
1138 pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1139 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1140 if( !pNewCursor )
1142 Rectangle aRect( GetEntryBoundRect(pCursor));
1143 if( aRect.Left() )
1145 aRect.Right() -= aRect.Left();
1146 aRect.Left() = 0;
1147 MakeVisible( aRect );
1151 break;
1153 case KEY_F2:
1154 if( !bMod1 && !bShift )
1155 EditTimeoutHdl( 0 );
1156 else
1157 bKeyUsed = sal_False;
1158 break;
1160 case KEY_F8:
1161 if( rKEvt.GetKeyCode().IsShift() )
1163 if( nFlags & F_ADD_MODE )
1164 nFlags &= (~F_ADD_MODE);
1165 else
1166 nFlags |= F_ADD_MODE;
1168 else
1169 bKeyUsed = sal_False;
1170 break;
1172 case KEY_SPACE:
1173 if( pCursor && eSelectionMode != SINGLE_SELECTION )
1175 if( !bMod1 )
1177 //SelectAll( sal_False );
1178 SetNoSelection();
1179 ClearSelectedRectList();
1181 // click Icon with spacebar
1182 SetEntryHighlightFrame( GetCurEntry(), sal_True );
1183 pView->ClickIcon();
1184 pHdlEntry = pCurHighlightFrame;
1185 pCurHighlightFrame=0;
1187 else
1188 ToggleSelection( pCursor );
1190 break;
1192 #ifdef DBG_UTIL
1193 case KEY_F10:
1194 if( rKEvt.GetKeyCode().IsShift() )
1196 if( pCursor )
1197 pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1199 if( rKEvt.GetKeyCode().IsMod1() )
1201 if( pCursor )
1202 pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1204 break;
1205 #endif
1207 case KEY_ADD:
1208 case KEY_DIVIDE :
1209 case KEY_A:
1210 if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1211 SelectAll( sal_True );
1212 else
1213 bKeyUsed = sal_False;
1214 break;
1216 case KEY_SUBTRACT:
1217 case KEY_COMMA :
1218 if( bMod1 )
1219 SetNoSelection();
1220 else
1221 bKeyUsed = sal_False;
1222 break;
1224 case KEY_RETURN:
1225 if( bMod1 )
1227 if( pCursor && bEntryEditingEnabled )
1228 /*pView->*/EditEntry( pCursor );
1230 else
1231 bKeyUsed = sal_False;
1232 break;
1234 case KEY_END:
1235 if( pCursor )
1237 pNewCursor = aEntries[ aEntries.size() - 1 ];
1238 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1240 break;
1242 case KEY_HOME:
1243 if( pCursor )
1245 pNewCursor = aEntries[ 0 ];
1246 SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1248 break;
1250 default:
1251 bKeyUsed = sal_False;
1254 return bKeyUsed;
1257 // recalculate TopLeft of scrollbars (but not their sizes!)
1258 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1260 // horizontal scrollbar
1261 Point aPos( 0, nRealHeight );
1262 aPos.Y() -= nHorSBarHeight;
1264 if( aHorSBar.GetPosPixel() != aPos )
1265 aHorSBar.SetPosPixel( aPos );
1267 // vertical scrollbar
1268 aPos.X() = nRealWidth; aPos.Y() = 0;
1269 aPos.X() -= nVerSBarWidth;
1270 aPos.X()++;
1271 aPos.Y()--;
1273 if( aVerSBar.GetPosPixel() != aPos )
1274 aVerSBar.SetPosPixel( aPos );
1277 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool )
1279 Rectangle aOldOutRect( GetOutputRect() );
1280 long nVirtHeight = aVirtOutputSize.Height();
1281 long nVirtWidth = aVirtOutputSize.Width();
1283 Size aOSize( pView->Control::GetOutputSizePixel() );
1284 long nRealHeight = aOSize.Height();
1285 long nRealWidth = aOSize.Width();
1287 PositionScrollBars( nRealWidth, nRealHeight );
1289 const MapMode& rMapMode = pView->GetMapMode();
1290 Point aOrigin( rMapMode.GetOrigin() );
1292 long nVisibleWidth;
1293 if( nRealWidth > nVirtWidth )
1294 nVisibleWidth = nVirtWidth + aOrigin.X();
1295 else
1296 nVisibleWidth = nRealWidth;
1298 long nVisibleHeight;
1299 if( nRealHeight > nVirtHeight )
1300 nVisibleHeight = nVirtHeight + aOrigin.Y();
1301 else
1302 nVisibleHeight = nRealHeight;
1304 sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1305 sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1306 sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1307 sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1309 sal_uInt16 nResult = 0;
1310 if( nVirtHeight )
1312 // activate vertical scrollbar?
1313 if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1315 nResult = 0x0001;
1316 nRealWidth -= nVerSBarWidth;
1318 if( nRealWidth > nVirtWidth )
1319 nVisibleWidth = nVirtWidth + aOrigin.X();
1320 else
1321 nVisibleWidth = nRealWidth;
1323 nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1325 // activate horizontal scrollbar?
1326 if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1328 nResult |= 0x0002;
1329 nRealHeight -= nHorSBarHeight;
1331 if( nRealHeight > nVirtHeight )
1332 nVisibleHeight = nVirtHeight + aOrigin.Y();
1333 else
1334 nVisibleHeight = nRealHeight;
1336 // do we need a vertical scrollbar after all?
1337 if( !(nResult & 0x0001) && // only if not already there
1338 ( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1340 nResult = 3; // both turned on
1341 nRealWidth -= nVerSBarWidth;
1343 if( nRealWidth > nVirtWidth )
1344 nVisibleWidth = nVirtWidth + aOrigin.X();
1345 else
1346 nVisibleWidth = nRealWidth;
1348 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1353 // size vertical scrollbar
1354 long nThumb = aVerSBar.GetThumbPos();
1355 Size aSize( nVerSBarWidth, nRealHeight );
1356 aSize.Height() += 2;
1357 if( aSize != aVerSBar.GetSizePixel() )
1358 aVerSBar.SetSizePixel( aSize );
1359 aVerSBar.SetVisibleSize( nVisibleHeight );
1360 aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1362 if( nResult & 0x0001 )
1364 aVerSBar.SetThumbPos( nThumb );
1365 aVerSBar.Show();
1367 else
1369 aVerSBar.SetThumbPos( 0 );
1370 aVerSBar.Hide();
1373 // size horizontal scrollbar
1374 nThumb = aHorSBar.GetThumbPos();
1375 aSize.Width() = nRealWidth;
1376 aSize.Height() = nHorSBarHeight;
1377 aSize.Width()++;
1378 if( nResult & 0x0001 ) // vertical scrollbar?
1380 aSize.Width()++;
1381 nRealWidth++;
1383 if( aSize != aHorSBar.GetSizePixel() )
1384 aHorSBar.SetSizePixel( aSize );
1385 aHorSBar.SetVisibleSize( nVisibleWidth );
1386 aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1387 if( nResult & 0x0002 )
1389 aHorSBar.SetThumbPos( nThumb );
1390 aHorSBar.Show();
1392 else
1394 aHorSBar.SetThumbPos( 0 );
1395 aHorSBar.Hide();
1398 aOutputSize.Width() = nRealWidth;
1399 if( nResult & 0x0002 ) // horizontal scrollbar ?
1400 nRealHeight++; // because lower border is clipped
1401 aOutputSize.Height() = nRealHeight;
1403 Rectangle aNewOutRect( GetOutputRect() );
1404 if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1406 Wallpaper aPaper( pView->GetBackground() );
1407 aPaper.SetRect( aNewOutRect );
1408 pView->SetBackground( aPaper );
1411 if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1412 aScrBarBox.Show();
1413 else
1414 aScrBarBox.Hide();
1417 void SvxIconChoiceCtrl_Impl::Resize()
1419 StopEditTimer();
1420 InitScrollBarBox();
1421 aOutputSize = pView->GetOutputSizePixel();
1422 pImpCursor->Clear();
1423 pGridMap->OutputSizeChanged();
1425 const Size& rSize = pView->Control::GetOutputSizePixel();
1426 PositionScrollBars( rSize.Width(), rSize.Height() );
1427 // The scrollbars are shown/hidden asynchronously, so derived classes can
1428 // do an Arrange during Resize, without the scrollbars suddenly turning
1429 // on and off again.
1430 // If an event is already underway, we don't need to send a new one, at least
1431 // as long as there is only one event type.
1432 if ( ! nUserEventAdjustScrBars )
1433 nUserEventAdjustScrBars =
1434 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1435 EVENTID_ADJUST_SCROLLBARS);
1437 if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1439 Rectangle aRect( GetOutputRect());
1440 Wallpaper aPaper( pView->GetBackground() );
1441 aPaper.SetRect( aRect );
1442 pView->SetBackground( aPaper );
1444 VisRectChanged();
1447 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1449 if( !pZOrderList || !aHorSBar.IsVisible() )
1450 return sal_False;
1451 const MapMode& rMapMode = pView->GetMapMode();
1452 Point aOrigin( rMapMode.GetOrigin() );
1453 if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1455 long nWidth = aOutputSize.Width();
1456 const size_t nCount = pZOrderList->size();
1457 long nMostRight = 0;
1458 for( size_t nCur = 0; nCur < nCount; nCur++ )
1460 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1461 long nRight = GetEntryBoundRect(pEntry).Right();
1462 if( nRight > nWidth )
1463 return sal_False;
1464 if( nRight > nMostRight )
1465 nMostRight = nRight;
1467 aHorSBar.Hide();
1468 aOutputSize.Height() += nHorSBarHeight;
1469 aVirtOutputSize.Width() = nMostRight;
1470 aHorSBar.SetThumbPos( 0 );
1471 Range aRange;
1472 aRange.Max() = nMostRight - 1;
1473 aHorSBar.SetRange( aRange );
1474 if( aVerSBar.IsVisible() )
1476 Size aSize( aVerSBar.GetSizePixel());
1477 aSize.Height() += nHorSBarHeight;
1478 aVerSBar.SetSizePixel( aSize );
1480 return sal_True;
1482 return sal_False;
1485 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1487 if( !pZOrderList || !aVerSBar.IsVisible() )
1488 return sal_False;
1489 const MapMode& rMapMode = pView->GetMapMode();
1490 Point aOrigin( rMapMode.GetOrigin() );
1491 if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1493 long nDeepest = 0;
1494 long nHeight = aOutputSize.Height();
1495 const size_t nCount = pZOrderList->size();
1496 for( size_t nCur = 0; nCur < nCount; nCur++ )
1498 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCur ];
1499 long nBottom = GetEntryBoundRect(pEntry).Bottom();
1500 if( nBottom > nHeight )
1501 return sal_False;
1502 if( nBottom > nDeepest )
1503 nDeepest = nBottom;
1505 aVerSBar.Hide();
1506 aOutputSize.Width() += nVerSBarWidth;
1507 aVirtOutputSize.Height() = nDeepest;
1508 aVerSBar.SetThumbPos( 0 );
1509 Range aRange;
1510 aRange.Max() = nDeepest - 1;
1511 aVerSBar.SetRange( aRange );
1512 if( aHorSBar.IsVisible() )
1514 Size aSize( aHorSBar.GetSizePixel());
1515 aSize.Width() += nVerSBarWidth;
1516 aHorSBar.SetSizePixel( aSize );
1518 return sal_True;
1520 return sal_False;
1524 // hides scrollbars if they're unnecessary
1525 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1527 CheckVerScrollBar();
1528 if( CheckHorScrollBar() )
1529 CheckVerScrollBar();
1530 if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1531 aScrBarBox.Show();
1532 else
1533 aScrBarBox.Hide();
1537 void SvxIconChoiceCtrl_Impl::GetFocus()
1539 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1540 if( pCursor )
1542 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1543 ShowCursor( sal_True );
1547 void SvxIconChoiceCtrl_Impl::LoseFocus()
1549 StopEditTimer();
1550 if( pCursor )
1551 pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1552 ShowCursor( sal_False );
1554 // HideFocus ();
1555 // pView->Invalidate ( aFocus.aRect );
1557 RepaintEntries( ICNVIEW_FLAG_SELECTED );
1560 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate )
1562 if( bUpdate != bUpdateMode )
1564 bUpdateMode = bUpdate;
1565 if( bUpdate )
1567 AdjustScrollBars();
1568 pImpCursor->Clear();
1569 pGridMap->Clear();
1570 pView->Invalidate(INVALIDATE_NOCHILDREN);
1575 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted )
1577 Point aPos( GetEntryPos( pEntry ) );
1578 PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1581 // priorities of the emphasis: bDropTarget => bCursored => bSelected
1582 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1583 const Rectangle& rTextRect, const Rectangle& rImageRect,
1584 sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut,
1585 sal_Bool bIsBackgroundPainted )
1587 static Color aTransparent( COL_TRANSPARENT );
1589 if( !pOut )
1590 pOut = pView;
1592 #ifdef OV_CHECK_EMPH_RECTS
1594 Color aXOld( pOut->GetFillColor() );
1595 pOut->SetFillColor( Color( COL_GREEN ));
1596 pOut->DrawRect( rTextRect );
1597 pOut->DrawRect( rImageRect );
1598 pOut->SetFillColor( aXOld );
1600 #endif
1602 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1603 Color aOldFillColor( pOut->GetFillColor() );
1605 sal_Bool bSolidTextRect = sal_False;
1606 sal_Bool bSolidImageRect = sal_False;
1608 if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1610 pOut->SetFillColor( rSettings.GetHighlightColor() );
1611 bSolidTextRect = sal_True;
1612 bSolidImageRect = sal_True;
1614 else
1616 if ( !bSelected || bCursored )
1618 if( !pView->HasFontFillColor() )
1619 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1620 else
1622 const Color& rFillColor = pView->GetFont().GetFillColor();
1623 pOut->SetFillColor( rFillColor );
1624 if( rFillColor != aTransparent )
1625 bSolidTextRect = sal_True;
1630 // draw text rectangle
1631 if( !bSolidTextRect )
1633 if( !bIsBackgroundPainted )
1634 pOut->Erase( rTextRect );
1636 else
1638 Color aOldLineColor;
1639 if( bCursored )
1641 aOldLineColor = pOut->GetLineColor();
1642 pOut->SetLineColor( Color( COL_GRAY ) );
1644 pOut->DrawRect( rTextRect );
1645 if( bCursored )
1646 pOut->SetLineColor( aOldLineColor );
1649 // draw image rectangle
1650 if( !bSolidImageRect )
1652 if( !bIsBackgroundPainted )
1653 pOut->Erase( rImageRect );
1655 // the emphasis of the images has to be drawn by the derived class (in the
1656 // virtual function DrawEntryImage)
1657 // else
1658 // pOut->DrawRect( rImageRect );
1660 pOut->SetFillColor( aOldFillColor );
1664 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1665 IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1666 OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1668 if( eItem == IcnViewFieldTypeText )
1670 String aText;
1671 if( !pStr )
1672 aText = pView->GetEntryText( pEntry, sal_False );
1673 else
1674 aText = *pStr;
1676 if ( _pLayoutData )
1678 pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1679 &_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1681 else
1683 Color aOldFontColor = pOut->GetTextColor();
1684 if ( pView->AutoFontColor() )
1686 Color aBkgColor( pOut->GetBackground().GetColor() );
1687 Color aFontColor;
1688 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1689 if ( nColor > 127 )
1690 aFontColor.SetColor ( COL_BLACK );
1691 else
1692 aFontColor.SetColor( COL_WHITE );
1693 pOut->SetTextColor( aFontColor );
1696 pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1698 if ( pView->AutoFontColor() )
1699 pOut->SetTextColor( aOldFontColor );
1701 if( pEntry->IsFocused() )
1703 Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1704 /*pView->*/ShowFocus( aRect );
1705 DrawFocusRect( pOut );
1709 else
1711 Point aPos( rRect.TopLeft() );
1712 if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1713 aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1714 if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1715 aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1716 pView->DrawEntryImage( pEntry, aPos, *pOut );
1720 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1722 #ifdef OV_NO_VIRT_OUTDEV
1723 PaintEntry( pEntry );
1724 #else
1725 if( !pEntryPaintDev )
1727 pEntryPaintDev = new VirtualDevice( *pView );
1728 pEntryPaintDev->SetFont( pView->GetFont() );
1729 pEntryPaintDev->SetLineColor();
1730 //pEntryPaintDev->SetBackground( pView->GetBackground() );
1732 const Rectangle& rRect = GetEntryBoundRect( pEntry );
1733 Rectangle aOutRect( GetOutputRect() );
1734 if( !rRect.IsOver( aOutRect ) )
1735 return;
1736 Wallpaper aPaper( pView->GetBackground() );
1737 Rectangle aRect( aPaper.GetRect() );
1739 // move rectangle, so the bounding rectangle of the entry lies in
1740 // VirtOut-Dev at 0,0
1741 aRect.Move( -rRect.Left(), -rRect.Top() );
1742 aPaper.SetRect( aRect );
1743 pEntryPaintDev->SetBackground( aPaper );
1744 pEntryPaintDev->SetFont( pView->GetFont() );
1746 Size aSize( rRect.GetSize() );
1747 pEntryPaintDev->SetOutputSizePixel( aSize );
1748 pEntryPaintDev->DrawOutDev(
1749 Point(), aSize, rRect.TopLeft(), aSize, *pView );
1751 PaintEntry( pEntry, Point(), pEntryPaintDev );
1753 pView->DrawOutDev(
1754 rRect.TopLeft(),
1755 aSize,
1756 Point(),
1757 aSize,
1758 *pEntryPaintDev );
1759 #endif
1763 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1764 OutputDevice* pOut, sal_Bool bIsBackgroundPainted )
1766 if( !pOut )
1767 pOut = pView;
1769 sal_Bool bSelected = sal_False;
1771 if( eSelectionMode != NO_SELECTION )
1772 bSelected = pEntry->IsSelected();
1774 sal_Bool bCursored = pEntry->IsCursored();
1775 sal_Bool bDropTarget = pEntry->IsDropTarget();
1776 sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1778 Font aTempFont( pOut->GetFont() );
1780 // AutoFontColor
1782 if ( pView->AutoFontColor() )
1784 aTempFont.SetColor ( aFontColor );
1788 String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
1789 Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText));
1790 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1792 sal_Bool bShowSelection =
1793 ( ( ( bSelected && !bCursored )
1794 || bDropTarget
1796 && !bNoEmphasis
1797 && ( eSelectionMode != NO_SELECTION )
1799 sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1801 if ( bShowSelection )
1803 const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1804 Font aNewFont( aTempFont );
1806 // font fill colors that are attributed "hard" need corresponding "hard"
1807 // attributed highlight colors
1808 if( pView->HasFontFillColor() )
1810 if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1811 aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1812 else
1813 aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
1816 Color aWinCol = rSettings.GetWindowTextColor();
1817 if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
1818 aNewFont.SetColor( rSettings.GetWindowTextColor() );
1819 else
1820 aNewFont.SetColor( rSettings.GetHighlightTextColor() );
1822 pOut->SetFont( aNewFont );
1824 pOut->SetFillColor( pOut->GetBackground().GetColor() );
1825 pOut->DrawRect( CalcFocusRect( pEntry ) );
1826 pOut->SetFillColor( );
1829 sal_Bool bResetClipRegion = sal_False;
1830 if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
1832 Rectangle aOutputArea( GetOutputRect() );
1833 if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
1835 pView->SetClipRegion(Region(aOutputArea));
1836 bResetClipRegion = sal_True;
1840 #ifdef OV_DRAWBOUNDRECT
1842 Color aXOldColor = pOut->GetLineColor();
1843 pOut->SetLineColor( Color( COL_LIGHTRED ) );
1844 Rectangle aXRect( pEntry->aRect );
1845 aXRect.SetPos( rPos );
1846 pOut->DrawRect( aXRect );
1847 pOut->SetLineColor( aXOldColor );
1849 #endif
1851 sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
1852 sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
1853 if ( bLargeIconMode )
1854 nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
1855 sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
1857 if( !bNoEmphasis )
1858 PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
1860 if ( bShowSelection )
1861 pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
1862 bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
1864 PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
1866 PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
1867 nTextPaintFlags, pOut );
1869 // draw highlight frame
1870 if( pEntry == pCurHighlightFrame && !bNoEmphasis )
1871 DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False );
1873 pOut->SetFont( aTempFont );
1874 if( bResetClipRegion )
1875 pView->SetClipRegion();
1878 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1879 sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap )
1881 ShowCursor( sal_False );
1882 Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
1883 pView->Invalidate( aBoundRect );
1884 ToTop( pEntry );
1885 if( !IsAutoArrange() )
1887 sal_Bool bAdjustVirtSize = sal_False;
1888 if( rPos != aBoundRect.TopLeft() )
1890 Point aGridOffs(
1891 pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
1892 pImpCursor->Clear();
1893 if( !bKeepGridMap )
1894 pGridMap->Clear();
1895 aBoundRect.SetPos( rPos );
1896 pEntry->aRect = aBoundRect;
1897 pEntry->aGridRect.SetPos( rPos + aGridOffs );
1898 bAdjustVirtSize = sal_True;
1900 if( bAdjustAtGrid )
1902 if( bAdjustVirtSize )
1904 // By aligning the (in some cases newly positioned) entry, it
1905 // can become completely visible again, so that maybe we don't
1906 // need a scrollbar after all. To avoid suddenly turning the
1907 // scrollbar(s) on and then off again, we use the aligned
1908 // bounding rectangle of the entry to enlarge the virtual
1909 // output size. The virtual size has to be adapted, because
1910 // AdjustEntryAtGrid depends on it.
1911 const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
1912 Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
1913 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
1914 Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
1915 AdjustVirtSize( aNewBoundRect );
1916 bAdjustVirtSize = sal_False;
1918 AdjustEntryAtGrid( pEntry );
1919 ToTop( pEntry );
1921 if( bAdjustVirtSize )
1922 AdjustVirtSize( pEntry->aRect );
1924 if( bCheckScrollBars && bUpdateMode )
1925 CheckScrollBars();
1927 pView->Invalidate( pEntry->aRect );
1928 pGridMap->OccupyGrids( pEntry );
1930 else
1932 SvxIconChoiceCtrlEntry* pPrev = FindEntryPredecessor( pEntry, rPos );
1933 SetEntryPredecessor( pEntry, pPrev );
1934 aAutoArrangeTimer.Start();
1936 ShowCursor( sal_True );
1939 void SvxIconChoiceCtrl_Impl::SetNoSelection()
1941 // block recursive calls via SelectEntry
1942 if( !(nFlags & F_CLEARING_SELECTION ))
1944 nFlags |= F_CLEARING_SELECTION;
1945 DeselectAllBut( 0, sal_True );
1946 nFlags &= ~F_CLEARING_SELECTION;
1950 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit )
1952 CheckBoundingRects();
1953 // search through z-order list from the end
1954 size_t nCount = pZOrderList->size();
1955 while( nCount )
1957 nCount--;
1958 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nCount ];
1959 if( pEntry->aRect.IsInside( rDocPos ) )
1961 if( bHit )
1963 Rectangle aRect = CalcBmpRect( pEntry );
1964 aRect.Top() -= 3;
1965 aRect.Bottom() += 3;
1966 aRect.Left() -= 3;
1967 aRect.Right() += 3;
1968 if( aRect.IsInside( rDocPos ) )
1969 return pEntry;
1970 aRect = CalcTextRect( pEntry );
1971 if( aRect.IsInside( rDocPos ) )
1972 return pEntry;
1974 else
1975 return pEntry;
1978 return 0;
1981 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
1983 return pEntry->aRect.TopLeft();
1986 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound )
1988 if ( bBound )
1990 const Rectangle& rRect = GetEntryBoundRect( pEntry );
1991 MakeVisible( rRect );
1993 else
1995 Rectangle aRect = CalcBmpRect( pEntry );
1996 aRect.Union( CalcTextRect( pEntry ) );
1997 aRect.Top() += TBOFFS_BOUND;
1998 aRect.Bottom() += TBOFFS_BOUND;
1999 aRect.Left() += LROFFS_BOUND;
2000 aRect.Right() += LROFFS_BOUND;
2001 MakeVisible( aRect );
2005 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2007 if( !IsBoundingRectValid( pEntry->aRect ))
2008 FindBoundingRect( pEntry );
2009 return pEntry->aRect;
2012 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2014 Rectangle aBound = GetEntryBoundRect( pEntry );
2015 if( pPos )
2016 aBound.SetPos( *pPos );
2017 Point aPos( aBound.TopLeft() );
2019 switch( nWinBits & (VIEWMODE_MASK) )
2021 case WB_ICON:
2023 aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2024 return Rectangle( aPos, aImageSize );
2027 case WB_SMALLICON:
2028 case WB_DETAILS:
2029 aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2030 //TODO: determine horizontal distance to bounding rectangle
2031 return Rectangle( aPos, aImageSize );
2033 default:
2034 OSL_FAIL("IconView: Viewmode not set");
2035 return aBound;
2039 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2040 const Point* pEntryPos, sal_Bool bEdit, const String* pStr )
2042 String aEntryText;
2043 if( !pStr )
2044 aEntryText = pView->GetEntryText( pEntry, bEdit );
2045 else
2046 aEntryText = *pStr;
2048 const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2049 Rectangle aBound( GetEntryBoundRect( pEntry ) );
2050 if( pEntryPos )
2051 aBound.SetPos( *pEntryPos );
2053 Rectangle aTextRect( aMaxTextRect );
2054 if( !bEdit )
2055 aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2057 Size aTextSize( aTextRect.GetSize() );
2059 Point aPos( aBound.TopLeft() );
2060 long nBoundWidth = aBound.GetWidth();
2061 long nBoundHeight = aBound.GetHeight();
2063 switch( nWinBits & (VIEWMODE_MASK) )
2065 case WB_ICON:
2066 aPos.Y() += aImageSize.Height();
2067 aPos.Y() += VER_DIST_BMP_STRING;
2068 // at little more space when editing
2069 if( bEdit )
2071 // +20%
2072 long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2073 aImageSize.Width();
2074 if( nMinWidth > nBoundWidth )
2075 nMinWidth = nBoundWidth;
2077 if( aTextSize.Width() < nMinWidth )
2078 aTextSize.Width() = nMinWidth;
2080 // when editing, overlap with the area below is allowed
2081 Size aOptSize = aMaxTextRect.GetSize();
2082 if( aOptSize.Height() > aTextSize.Height() )
2083 aTextSize.Height() = aOptSize.Height();
2085 aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2086 break;
2088 case WB_SMALLICON:
2089 case WB_DETAILS:
2090 aPos.X() += aImageSize.Width();
2091 aPos.X() += HOR_DIST_BMP_STRING;
2092 aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2093 break;
2095 return Rectangle( aPos, aTextSize );
2099 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2101 long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2102 // nStringWidth += 2*LROFFS_TEXT;
2103 long nWidth = 0;
2105 switch( nWinBits & (VIEWMODE_MASK) )
2107 case WB_ICON:
2108 nWidth = std::max( nStringWidth, aImageSize.Width() );
2109 break;
2111 case WB_SMALLICON:
2112 case WB_DETAILS:
2113 nWidth = aImageSize.Width();
2114 nWidth += HOR_DIST_BMP_STRING;
2115 nWidth += nStringWidth;
2116 break;
2118 return nWidth;
2121 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2123 long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2124 long nHeight = 0;
2126 switch( nWinBits & (VIEWMODE_MASK) )
2128 case WB_ICON:
2129 nHeight = aImageSize.Height();
2130 nHeight += VER_DIST_BMP_STRING;
2131 nHeight += nStringHeight;
2132 break;
2134 case WB_SMALLICON:
2135 case WB_DETAILS:
2136 nHeight = std::max( aImageSize.Height(), nStringHeight );
2137 break;
2139 if( nHeight > nMaxBoundHeight )
2141 ((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2142 ((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2143 ((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2145 return nHeight;
2148 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2150 return Size( CalcBoundingWidth( pEntry ),
2151 CalcBoundingHeight( pEntry ) );
2154 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2156 nMaxBoundHeight = 0;
2157 pZOrderList->clear();
2158 size_t nCur;
2159 SvxIconChoiceCtrlEntry* pEntry;
2160 const size_t nCount = aEntries.size();
2162 if( !IsAutoArrange() || !pHead )
2164 for( nCur = 0; nCur < nCount; nCur++ )
2166 pEntry = aEntries[ nCur ];
2167 if( IsBoundingRectValid( pEntry->aRect ))
2169 Size aBoundSize( pEntry->aRect.GetSize() );
2170 if( aBoundSize.Height() > nMaxBoundHeight )
2171 nMaxBoundHeight = aBoundSize.Height();
2173 else
2174 FindBoundingRect( pEntry );
2175 pZOrderList->push_back( pEntry );
2178 else
2180 nCur = 0;
2181 pEntry = pHead;
2182 while( nCur != nCount )
2184 DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2185 if( IsBoundingRectValid( pEntry->aRect ))
2187 Size aBoundSize( pEntry->aRect.GetSize() );
2188 if( aBoundSize.Height() > nMaxBoundHeight )
2189 nMaxBoundHeight = aBoundSize.Height();
2191 else
2192 FindBoundingRect( pEntry );
2193 pZOrderList->push_back( pEntry );
2194 pEntry = pEntry->pflink;
2195 nCur++;
2198 AdjustScrollBars();
2201 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2203 DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2204 if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2206 AdjustVirtSize( pEntry->aRect );
2207 return;
2209 Size aSize( CalcBoundingSize( pEntry ) );
2210 Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft());
2211 SetBoundingRect_Impl( pEntry, aPos, aSize );
2214 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2215 const Size& /*rBoundingSize*/ )
2217 Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2218 pEntry->aGridRect = aGridRect;
2219 Center( pEntry );
2220 AdjustVirtSize( pEntry->aRect );
2221 pGridMap->OccupyGrids( pEntry );
2225 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection,
2226 sal_Bool bShowFocusAsync )
2228 if( pEntry == pCursor )
2230 if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2231 !pCursor->IsSelected() )
2232 SelectEntry( pCursor, sal_True, sal_True );
2233 return;
2235 ShowCursor( sal_False );
2236 SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2237 pCursor = pEntry;
2238 if( pOldCursor )
2240 pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2241 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2242 SelectEntry( pOldCursor, sal_False, sal_True ); // deselect old cursor
2244 if( pCursor )
2246 ToTop( pCursor );
2247 pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2248 if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2249 SelectEntry( pCursor, sal_True, sal_True );
2250 if( !bShowFocusAsync )
2251 ShowCursor( sal_True );
2252 else
2254 if( !nUserEventShowCursor )
2255 nUserEventShowCursor =
2256 Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2257 EVENTID_SHOW_CURSOR );
2263 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow )
2265 if( !pCursor || !bShow || !pView->HasFocus() )
2267 pView->HideFocus();
2268 return;
2270 Rectangle aRect ( CalcFocusRect( pCursor ) );
2271 /*pView->*/ShowFocus( aRect );
2275 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2277 pView->Update();
2278 ImpHideDDIcon();
2279 pDDBufDev = pDDDev;
2280 pDDDev = 0;
2283 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2285 if( pDDDev )
2287 Size aSize( pDDDev->GetOutputSizePixel() );
2288 // restore pView
2289 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2293 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2295 Rectangle aDocRect( GetDocumentRect() );
2296 Rectangle aVisRect( GetVisibleRect() );
2297 if( aVisRect.IsInside( aDocRect ))
2298 return sal_False;
2299 Size aDocSize( aDocRect.GetSize() );
2300 Size aVisSize( aVisRect.GetSize() );
2301 sal_Bool bHor = aDocSize.Width() > aVisSize.Width();
2302 sal_Bool bVer = aDocSize.Height() > aVisSize.Height();
2304 long nScrollDX = 0, nScrollDY = 0;
2306 switch( rCmd.GetCommand() )
2308 case COMMAND_STARTAUTOSCROLL:
2310 pView->EndTracking();
2311 sal_uInt16 nScrollFlags = 0;
2312 if( bHor )
2313 nScrollFlags |= AUTOSCROLL_HORZ;
2314 if( bVer )
2315 nScrollFlags |= AUTOSCROLL_VERT;
2316 if( nScrollFlags )
2318 pView->StartAutoScroll( nScrollFlags );
2319 return sal_True;
2322 break;
2324 case COMMAND_WHEEL:
2326 const CommandWheelData* pData = rCmd.GetWheelData();
2327 if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2329 sal_uLong nScrollLines = pData->GetScrollLines();
2330 if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2332 nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2333 if( pData->GetDelta() < 0 )
2334 nScrollDY *= -1;
2336 else
2338 nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2339 nScrollDY *= GetScrollBarLineSize();
2343 break;
2345 case COMMAND_AUTOSCROLL:
2347 const CommandScrollData* pData = rCmd.GetAutoScrollData();
2348 if( pData )
2350 nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2351 nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2354 break;
2357 if( nScrollDX || nScrollDY )
2359 aVisRect.Top() -= nScrollDY;
2360 aVisRect.Bottom() -= nScrollDY;
2361 aVisRect.Left() -= nScrollDX;
2362 aVisRect.Right() -= nScrollDX;
2363 MakeVisible( aVisRect );
2364 return sal_True;
2366 return sal_False;
2370 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2372 // scroll mouse event?
2373 if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2374 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2375 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2377 if( HandleScrollCommand( rCEvt ) )
2378 return;
2382 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2384 if( !pZOrderList->empty()
2385 && pEntry != pZOrderList->back()
2387 for(
2388 SvxIconChoiceCtrlEntryList_impl::iterator it = pZOrderList->begin();
2389 it != pZOrderList->end();
2390 ++it
2392 if ( *it == pEntry )
2394 pZOrderList->erase( it );
2395 pZOrderList->push_back( pEntry );
2396 break;
2402 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2404 if( rRect.Bottom() >= aVirtOutputSize.Height() )
2405 rRect.Bottom() = aVirtOutputSize.Height() - 1;
2406 if( rRect.Right() >= aVirtOutputSize.Width() )
2407 rRect.Right() = aVirtOutputSize.Width() - 1;
2408 if( rRect.Top() < 0 )
2409 rRect.Top() = 0;
2410 if( rRect.Left() < 0 )
2411 rRect.Left() = 0;
2414 // rRect: area of the document (in document coordinates) that we want to make
2415 // visible
2416 // bScrBar == sal_True: rectangle was calculated because of a scrollbar event
2418 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar,
2419 sal_Bool bCallRectChangedHdl )
2421 Rectangle aVirtRect( rRect );
2422 ClipAtVirtOutRect( aVirtRect );
2423 Point aOrigin( pView->GetMapMode().GetOrigin() );
2424 // convert to document coordinate
2425 aOrigin *= -1;
2426 Rectangle aOutputArea( GetOutputRect() );
2427 if( aOutputArea.IsInside( aVirtRect ) )
2428 return; // is already visible
2430 long nDy;
2431 if( aVirtRect.Top() < aOutputArea.Top() )
2433 // scroll up (nDy < 0)
2434 nDy = aVirtRect.Top() - aOutputArea.Top();
2436 else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2438 // scroll down (nDy > 0)
2439 nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2441 else
2442 nDy = 0;
2444 long nDx;
2445 if( aVirtRect.Left() < aOutputArea.Left() )
2447 // scroll to the left (nDx < 0)
2448 nDx = aVirtRect.Left() - aOutputArea.Left();
2450 else if( aVirtRect.Right() > aOutputArea.Right() )
2452 // scroll to the right (nDx > 0)
2453 nDx = aVirtRect.Right() - aOutputArea.Right();
2455 else
2456 nDx = 0;
2458 aOrigin.X() += nDx;
2459 aOrigin.Y() += nDy;
2460 aOutputArea.SetPos( aOrigin );
2461 if( GetUpdateMode() )
2463 HideDDIcon();
2464 pView->Update();
2465 ShowCursor( sal_False );
2468 // invert origin for SV (so we can scroll/paint using document coordinates)
2469 aOrigin *= -1;
2470 SetOrigin( aOrigin );
2472 sal_Bool bScrollable = pView->GetBackground().IsScrollable();
2473 if( pView->HasBackground() && !bScrollable )
2475 Rectangle aRect( GetOutputRect());
2476 Wallpaper aPaper( pView->GetBackground() );
2477 aPaper.SetRect( aRect );
2478 pView->SetBackground( aPaper );
2481 if( bScrollable && GetUpdateMode() )
2483 // scroll in reverse direction!
2484 pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2485 SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2487 else
2488 pView->Invalidate(INVALIDATE_NOCHILDREN);
2490 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2492 if( !bScrBar )
2494 aOrigin *= -1;
2495 // correct thumbs
2496 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2497 aHorSBar.SetThumbPos( aOrigin.X() );
2498 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2499 aVerSBar.SetThumbPos( aOrigin.Y() );
2503 if( GetUpdateMode() )
2504 ShowCursor( sal_True );
2506 // check if we still need scrollbars
2507 CheckScrollBars();
2508 if( bScrollable && GetUpdateMode() )
2509 pView->Update();
2511 // If the requested area can not be made completely visible, the
2512 // Vis-Rect-Changed handler is called in any case. This case may occur e.g.
2513 // if only few pixels of the lower border are invisible, but a scrollbar has
2514 // a larger line size.
2515 if( bCallRectChangedHdl || GetOutputRect() != rRect )
2516 VisRectChanged();
2519 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2521 if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2522 return 1;
2523 return nSelectionCount;
2526 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2528 sal_Bool bSel;
2529 if( pEntry->IsSelected() )
2530 bSel = sal_False;
2531 else
2532 bSel = sal_True;
2533 SelectEntry( pEntry, bSel, sal_True, sal_True );
2536 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2537 sal_Bool bPaintSync )
2539 ClearSelectedRectList();
2541 // TODO: work through z-order list, if necessary!
2543 size_t nCount = aEntries.size();
2544 for( size_t nCur = 0; nCur < nCount; nCur++ )
2546 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
2547 if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2548 SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync );
2550 pAnchor = 0;
2551 nFlags &= (~F_ADD_MODE);
2554 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2556 Size aMinSize( aImageSize );
2557 aMinSize.Width() += 2 * LROFFS_BOUND;
2558 aMinSize.Height() += TBOFFS_BOUND; // single offset is enough (FileDlg)
2559 String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
2560 Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2561 if( nWinBits & WB_ICON )
2563 aMinSize.Height() += VER_DIST_BMP_STRING;
2564 aMinSize.Height() += aTextSize.Height();
2566 else
2568 aMinSize.Width() += HOR_DIST_BMP_STRING;
2569 aMinSize.Width() += aTextSize.Width();
2571 return aMinSize;
2574 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
2576 Size aSize( rSize );
2577 Size aMinSize( GetMinGrid() );
2578 if( aSize.Width() < aMinSize.Width() )
2579 aSize.Width() = aMinSize.Width();
2580 if( aSize.Height() < aMinSize.Height() )
2581 aSize.Height() = aMinSize.Height();
2583 nGridDX = aSize.Width();
2584 // HACK: Detail mode is not yet fully implemented, this workaround makes it
2585 // fly with a single column
2586 if( nWinBits & WB_DETAILS )
2588 const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
2589 if( pCol )
2590 ((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
2592 nGridDY = aSize.Height();
2593 SetDefaultTextSize();
2596 // Calculates the maximum size that the text rectangle may use within its
2597 // bounding rectangle. In WB_ICON mode with IcnShowTextFull, Bottom is set to
2598 // LONG_MAX.
2600 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
2602 Rectangle aBoundRect;
2603 // avoid infinite recursion: don't calculate the bounding rectangle here
2604 if( IsBoundingRectValid( pEntry->aRect ) )
2605 aBoundRect = pEntry->aRect;
2606 else
2607 aBoundRect = pEntry->aGridRect;
2609 Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
2610 (SvxIconChoiceCtrlEntry*)pEntry ) );
2611 if( nWinBits & WB_ICON )
2613 aBoundRect.Top() = aBmpRect.Bottom();
2614 aBoundRect.Top() += VER_DIST_BMP_STRING;
2615 if( aBoundRect.Top() > aBoundRect.Bottom())
2616 aBoundRect.Top() = aBoundRect.Bottom();
2617 aBoundRect.Left() += LROFFS_BOUND;
2618 aBoundRect.Left()++;
2619 aBoundRect.Right() -= LROFFS_BOUND;
2620 aBoundRect.Right()--;
2621 if( aBoundRect.Left() > aBoundRect.Right())
2622 aBoundRect.Left() = aBoundRect.Right();
2623 if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
2624 aBoundRect.Bottom() = LONG_MAX;
2626 else
2628 aBoundRect.Left() = aBmpRect.Right();
2629 aBoundRect.Left() += HOR_DIST_BMP_STRING;
2630 aBoundRect.Right() -= LROFFS_BOUND;
2631 if( aBoundRect.Left() > aBoundRect.Right() )
2632 aBoundRect.Left() = aBoundRect.Right();
2633 long nHeight = aBoundRect.GetSize().Height();
2634 nHeight = nHeight - aDefaultTextSize.Height();
2635 nHeight /= 2;
2636 aBoundRect.Top() += nHeight;
2637 aBoundRect.Bottom() -= nHeight;
2639 return aBoundRect;
2642 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
2644 long nDY = nGridDY;
2645 nDY -= aImageSize.Height();
2646 nDY -= VER_DIST_BMP_STRING;
2647 nDY -= 2*TBOFFS_BOUND;
2648 if( nDY <= 0 )
2649 nDY = 2;
2651 long nDX = nGridDX;
2652 nDX -= 2*LROFFS_BOUND;
2653 nDX -= 2;
2654 if( nDX <= 0 )
2655 nDX = 2;
2657 long nHeight = pView->GetTextHeight();
2658 if( nDY < nHeight )
2659 nDY = nHeight;
2660 aDefaultTextSize = Size( nDX, nDY );
2664 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
2666 pEntry->aRect = pEntry->aGridRect;
2667 Size aSize( CalcBoundingSize( pEntry ) );
2668 if( nWinBits & WB_ICON )
2670 // center horizontally
2671 long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
2672 pEntry->aRect.Left() += nBorder / 2;
2673 pEntry->aRect.Right() -= nBorder / 2;
2675 // center vertically
2676 pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
2680 // The deltas are the offsets by which the view is moved on the document.
2681 // left, up: offsets < 0
2682 // right, down: offsets > 0
2683 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
2685 const MapMode& rMapMode = pView->GetMapMode();
2686 Point aOrigin( rMapMode.GetOrigin() );
2687 // convert to document coordinate
2688 aOrigin *= -1;
2689 aOrigin.Y() += nDeltaY;
2690 aOrigin.X() += nDeltaX;
2691 Rectangle aRect( aOrigin, aOutputSize );
2692 MakeVisible( aRect, bScrollBar );
2696 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
2697 IcnViewFieldType eItem ) const
2699 if( eItem == IcnViewFieldTypeText )
2700 return aDefaultTextSize;
2701 return aImageSize;
2704 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
2706 Rectangle aTextRect( CalcTextRect( pEntry ) );
2707 Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
2708 return Rectangle(
2709 aBoundRect.Left(), aBoundRect.Top() - 1, aBoundRect.Right() - 1,
2710 aTextRect.Bottom() + 1);
2713 // the hot spot is the inner 50 % of the rectangle
2714 static Rectangle GetHotSpot( const Rectangle& rRect )
2716 Rectangle aResult( rRect );
2717 aResult.Justify();
2718 Size aSize( rRect.GetSize() );
2719 long nDelta = aSize.Width() / 4;
2720 aResult.Left() += nDelta;
2721 aResult.Right() -= nDelta;
2722 nDelta = aSize.Height() / 4;
2723 aResult.Top() += nDelta;
2724 aResult.Bottom() -= nDelta;
2725 return aResult;
2728 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
2729 sal_Bool bAdd, std::vector<Rectangle*>* pOtherRects )
2731 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2732 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2733 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2734 SelectRect( aRect, bAdd, pOtherRects );
2737 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, bool bAdd,
2738 std::vector<Rectangle*>* pOtherRects )
2740 aCurSelectionRect = rRect;
2741 if( !pZOrderList || !pZOrderList->size() )
2742 return;
2744 // set flag, so ToTop won't be called in Select
2745 sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False;
2746 nFlags |= F_SELECTING_RECT;
2748 CheckBoundingRects();
2749 pView->Update();
2750 const size_t nCount = pZOrderList->size();
2752 Rectangle aRect( rRect );
2753 aRect.Justify();
2754 bool bCalcOverlap = (bAdd && pOtherRects && !pOtherRects->empty()) ? true : false;
2756 sal_Bool bResetClipRegion = sal_False;
2757 if( !pView->IsClipRegion() )
2759 bResetClipRegion = sal_True;
2760 pView->SetClipRegion(Region(GetOutputRect()));
2763 for( size_t nPos = 0; nPos < nCount; nPos++ )
2765 SvxIconChoiceCtrlEntry* pEntry = (*pZOrderList)[ nPos ];
2767 if( !IsBoundingRectValid( pEntry->aRect ))
2768 FindBoundingRect( pEntry );
2769 Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
2770 sal_Bool bSelected = pEntry->IsSelected();
2772 sal_Bool bOverlaps;
2773 if( bCalcOverlap )
2774 bOverlaps = IsOver( pOtherRects, aBoundRect );
2775 else
2776 bOverlaps = sal_False;
2777 sal_Bool bOver = aRect.IsOver( aBoundRect );
2779 if( bOver && !bOverlaps )
2781 // is inside the new selection rectangle and outside of any old one
2782 // => select
2783 if( !bSelected )
2784 SelectEntry( pEntry, sal_True, sal_True, sal_True );
2786 else if( !bAdd )
2788 // is outside of the selection rectangle
2789 // => deselect
2790 if( bSelected )
2791 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2793 else if( bAdd && bOverlaps )
2795 // The entry is inside an old (=>span multiple rectangles with Ctrl)
2796 // selection rectangle.
2798 // There is still a bug here! The selection status of an entry in a
2799 // previous rectangle has to be restored, if it was touched by the
2800 // current selection rectangle but is not inside it any more.
2801 // For simplicity's sake, let's assume that all entries in the old
2802 // rectangles were correctly selected. It is wrong to just deselect
2803 // the intersection.
2804 // Possible solution: remember a snapshot of the selection before
2805 // spanning the rectangle.
2806 if( aBoundRect.IsOver( rRect))
2808 // deselect intersection between old rectangles and current rectangle
2809 if( bSelected )
2810 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2812 else
2814 // select entry of an old rectangle
2815 if( !bSelected )
2816 SelectEntry( pEntry, sal_True, sal_True, sal_True );
2819 else if( !bOver && bSelected )
2821 // this entry is completely outside the rectangle => deselect it
2822 SelectEntry( pEntry, sal_False, sal_True, sal_True );
2826 if( !bAlreadySelectingRect )
2827 nFlags &= ~F_SELECTING_RECT;
2829 pView->Update();
2830 if( bResetClipRegion )
2831 pView->SetClipRegion();
2834 void SvxIconChoiceCtrl_Impl::SelectRange(
2835 SvxIconChoiceCtrlEntry* pStart,
2836 SvxIconChoiceCtrlEntry* pEnd,
2837 sal_Bool bAdd )
2839 sal_uLong nFront = GetEntryListPos( pStart );
2840 sal_uLong nBack = GetEntryListPos( pEnd );
2841 sal_uLong nFirst = std::min( nFront, nBack );
2842 sal_uLong nLast = std::max( nFront, nBack );
2843 sal_uLong i;
2844 SvxIconChoiceCtrlEntry* pEntry;
2846 if ( ! bAdd )
2848 // deselect everything before the first entry if not in
2849 // adding mode
2850 for ( i=0; i<nFirst; i++ )
2852 pEntry = GetEntry( i );
2853 if( pEntry->IsSelected() )
2854 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
2858 // select everything between nFirst and nLast
2859 for ( i=nFirst; i<=nLast; i++ )
2861 pEntry = GetEntry( i );
2862 if( ! pEntry->IsSelected() )
2863 SelectEntry( pEntry, sal_True, sal_True, sal_True, sal_True );
2866 if ( ! bAdd )
2868 // deselect everything behind the last entry if not in
2869 // adding mode
2870 sal_uLong nEnd = GetEntryCount();
2871 for ( ; i<nEnd; i++ )
2873 pEntry = GetEntry( i );
2874 if( pEntry->IsSelected() )
2875 SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
2880 bool SvxIconChoiceCtrl_Impl::IsOver( std::vector<Rectangle*>* pRectList, const Rectangle& rBoundRect ) const
2882 const sal_uInt16 nCount = pRectList->size();
2883 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2885 Rectangle* pRect = (*pRectList)[ nCur ];
2886 if( rBoundRect.IsOver( *pRect ))
2887 return true;
2889 return false;
2892 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
2893 SvxIconChoiceCtrlEntry* pEntry2 )
2895 DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
2896 Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
2897 aRect.Union( GetEntryBoundRect( pEntry2 ) );
2898 AddSelectedRect( aRect );
2901 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
2903 Rectangle* pRect = new Rectangle( rRect );
2904 pRect->Justify();
2905 aSelectedRectList.push_back( pRect );
2908 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
2910 const sal_uInt16 nCount = aSelectedRectList.size();
2911 for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
2913 Rectangle* pRect = aSelectedRectList[ nCur ];
2914 delete pRect;
2916 aSelectedRectList.clear();
2919 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, AutoArrangeHdl)
2921 aAutoArrangeTimer.Stop();
2922 Arrange( IsAutoArrange() );
2923 return 0;
2926 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, VisRectChangedHdl)
2928 aVisRectChangedTimer.Stop();
2929 pView->VisibleRectChanged();
2930 return 0;
2933 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, DocRectChangedHdl)
2935 aDocRectChangedTimer.Stop();
2936 pView->DocumentRectChanged();
2937 return 0;
2940 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
2942 Rectangle aRect( CalcTextRect( pEntry ));
2943 if( aRect.IsInside( rDocPos ) )
2944 return sal_True;
2945 return sal_False;
2948 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, EditTimeoutHdl)
2950 SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
2951 if( bEntryEditingEnabled && pEntry &&
2952 pEntry->IsSelected())
2954 if( pView->EditingEntry( pEntry ))
2955 EditEntry( pEntry );
2957 return 0;
2962 // Function to align entries to the grid
2965 // pStart == 0: align all entries
2966 // else: align all entries of the row from pStart on (including pStart)
2967 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
2969 IconChoiceMap aLists;
2970 pImpCursor->CreateGridAjustData( aLists, pStart );
2971 for (IconChoiceMap::const_iterator iter = aLists.begin();
2972 iter != aLists.end(); ++iter)
2974 AdjustAtGrid(iter->second, pStart);
2976 IcnCursor_Impl::DestroyGridAdjustData( aLists );
2977 CheckScrollBars();
2980 // align a row, might expand width, doesn't break the line
2981 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvxIconChoiceCtrlEntryPtrVec& rRow, SvxIconChoiceCtrlEntry* pStart )
2983 if( rRow.empty() )
2984 return;
2986 sal_Bool bGo;
2987 if( !pStart )
2988 bGo = sal_True;
2989 else
2990 bGo = sal_False;
2992 long nCurRight = 0;
2993 for( sal_uInt16 nCur = 0; nCur < rRow.size(); nCur++ )
2995 SvxIconChoiceCtrlEntry* pCur = rRow[ nCur ];
2996 if( !bGo && pCur == pStart )
2997 bGo = sal_True;
2999 // SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3000 // Decisive (for our eye) is the bitmap, else, the entry might jump too
3001 // much within long texts.
3002 const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3003 Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3004 if( bGo && !pCur->IsPosLocked() )
3006 long nWidth = aCenterRect.GetSize().Width();
3007 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3008 while( aNewPos.X() < nCurRight )
3009 aNewPos.X() += nGridDX;
3010 if( aNewPos != rBoundRect.TopLeft() )
3012 SetEntryPos( pCur, aNewPos );
3013 pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3014 nFlags |= F_MOVED_ENTRIES;
3016 nCurRight = aNewPos.X() + nWidth;
3018 else
3020 nCurRight = rBoundRect.Right();
3025 // Aligns a rectangle to the grid, but doesn't guarantee that the new position
3026 // is vacant. The position can be used for SetEntryPos. The CenterRect describes
3027 // a part of the bounding rectangle that is used for calculating the target
3028 // rectangle.
3029 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3030 const Rectangle& rBoundRect ) const
3032 Point aPos( rCenterRect.TopLeft() );
3033 Size aSize( rCenterRect.GetSize() );
3035 aPos.X() -= LROFFS_WINBORDER;
3036 aPos.Y() -= TBOFFS_WINBORDER;
3038 // align (the center of the rectangle is the reference)
3039 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3040 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3041 aPos.X() = nGridX * nGridDX;
3042 aPos.Y() = nGridY * nGridDY;
3043 // horizontal center
3044 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3046 aPos.X() += LROFFS_WINBORDER;
3047 aPos.Y() += TBOFFS_WINBORDER;
3049 return aPos;
3052 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3054 if( !pEntry )
3056 if( eTextMode != eMode )
3058 if( eTextMode == IcnShowTextDontKnow )
3059 eTextMode = IcnShowTextShort;
3060 eTextMode = eMode;
3061 Arrange( sal_True );
3064 else
3066 if( pEntry->eTextMode != eMode )
3068 pEntry->eTextMode = eMode;
3069 InvalidateEntry( pEntry );
3070 pView->Invalidate( GetEntryBoundRect( pEntry ) );
3071 AdjustVirtSize( pEntry->aRect );
3076 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3078 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3079 SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3080 if( eMode == IcnShowTextDontKnow )
3081 return eTextMode;
3082 return eMode;
3085 ////////////////////////////////////////////////////////////////////////////////////////////////
3087 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3088 // of the background. But what will we see, if the backgroundcolor is gray ? - We will see
3089 // a gray focusrect on a gray background !!!
3091 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3093 Color aBkgColor ( pView->GetBackground().GetColor() );
3094 Color aPenColor;
3095 sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3096 if ( nColor > 128 )
3097 aPenColor.SetColor ( COL_BLACK );
3098 else
3099 aPenColor.SetColor( COL_WHITE );
3101 aFocus.bOn = sal_True;
3102 aFocus.aPenColor = aPenColor;
3103 aFocus.aRect = rRect;
3106 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3108 pOut->SetLineColor( aFocus.aPenColor );
3109 pOut->SetFillColor();
3110 Polygon aPolygon ( aFocus.aRect );
3112 LineInfo aLineInfo ( LINE_DASH );
3114 aLineInfo.SetDashLen ( 1 );
3116 aLineInfo.SetDotLen ( 1L );
3117 aLineInfo.SetDistance ( 1L );
3118 aLineInfo.SetDotCount ( 1 );
3120 pOut->DrawPolyLine ( aPolygon, aLineInfo );
3123 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
3125 sal_Bool bRet = sal_False;
3126 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3127 size_t nEntryCount = GetEntryCount();
3128 for ( size_t i = 0; i < nEntryCount; ++i )
3130 if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3132 bRet = sal_True;
3133 rPos = i;
3134 break;
3138 return bRet;
3142 ////////////////////////////////////////////////////////////////////////////////////////////////
3144 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3146 if( nId == EVENTID_ADJUST_SCROLLBARS )
3148 nUserEventAdjustScrBars = 0;
3149 AdjustScrollBars();
3151 else if( nId == EVENTID_SHOW_CURSOR )
3153 nUserEventShowCursor = 0;
3154 ShowCursor( sal_True );
3156 return 0;
3159 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3161 if( nUserEventAdjustScrBars )
3163 Application::RemoveUserEvent( nUserEventAdjustScrBars );
3164 nUserEventAdjustScrBars = 0;
3166 if( nUserEventShowCursor )
3168 Application::RemoveUserEvent( nUserEventShowCursor );
3169 nUserEventShowCursor = 0;
3173 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3175 if( pEntry == pCursor )
3176 ShowCursor( sal_False );
3177 pView->Invalidate( pEntry->aRect );
3178 Center( pEntry );
3179 pView->Invalidate( pEntry->aRect );
3180 if( pEntry == pCursor )
3181 ShowCursor( sal_True );
3184 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3186 DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3187 if( !pEntry )
3188 return;
3190 StopEntryEditing( sal_True );
3191 DELETEZ(pEdit);
3192 SetNoSelection();
3194 pCurEditedEntry = pEntry;
3195 String aEntryText( pView->GetEntryText( pEntry, sal_True ) );
3196 Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) );
3197 MakeVisible( aRect );
3198 Point aPos( aRect.TopLeft() );
3199 aPos = pView->GetPixelPos( aPos );
3200 aRect.SetPos( aPos );
3201 pView->HideFocus();
3202 pEdit = new IcnViewEdit_Impl(
3203 pView,
3204 aRect.TopLeft(),
3205 aRect.GetSize(),
3206 aEntryText,
3207 LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3210 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, TextEditEndedHdl)
3212 DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3213 if( !pEdit )
3215 pCurEditedEntry = 0;
3216 return 0;
3218 DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3220 if( !pCurEditedEntry )
3222 pEdit->Hide();
3223 if( pEdit->IsGrabFocus() )
3224 pView->GrabFocus();
3225 return 0;
3228 String aText;
3229 if ( !pEdit->EditingCanceled() )
3230 aText = pEdit->GetText();
3231 else
3232 aText = pEdit->GetSavedValue();
3234 if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3235 InvalidateEntry( pCurEditedEntry );
3236 if( !GetSelectionCount() )
3237 SelectEntry( pCurEditedEntry, sal_True );
3239 pEdit->Hide();
3240 if( pEdit->IsGrabFocus() )
3241 pView->GrabFocus();
3242 // The edit can not be deleted here, because it is not within a handler. It
3243 // will be deleted in the dtor or in the next EditEntry.
3244 pCurEditedEntry = 0;
3245 return 0;
3248 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel )
3250 if( pEdit )
3251 pEdit->StopEditing( bCancel );
3254 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3256 if( !GetSelectionCount() )
3257 return 0;
3259 if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3261 rPos = pView->GetEntryListPos( pCurHighlightFrame );
3262 return pCurHighlightFrame;
3265 size_t nCount = aEntries.size();
3266 if( !pHead )
3268 for( size_t nCur = 0; nCur < nCount; nCur++ )
3270 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3271 if( pEntry->IsSelected() )
3273 rPos = nCur;
3274 return pEntry;
3278 else
3280 SvxIconChoiceCtrlEntry* pEntry = pHead;
3281 while( nCount-- )
3283 if( pEntry->IsSelected() )
3285 rPos = GetEntryListPos( pEntry );
3286 return pEntry;
3288 pEntry = pEntry->pflink;
3289 if( nCount && pEntry == pHead )
3291 OSL_FAIL("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > infinite loop!");
3292 return 0;
3296 return 0;
3299 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint )
3301 bPaint = sal_True;
3303 size_t nCount = aEntries.size();
3304 for( size_t nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3306 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3307 SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint );
3309 nFlags &= (~F_ADD_MODE);
3310 pAnchor = 0;
3313 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3314 const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
3315 MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3316 aCallBackHdl( rNotifyEditEnd ),
3317 bCanceled( sal_False ),
3318 bAlreadyInCallback( sal_False ),
3319 bGrabFocus( sal_False )
3321 Font aFont( pParent->GetPointFont() );
3322 aFont.SetTransparent( sal_False );
3323 SetControlFont( aFont );
3324 if( !pParent->HasFontFillColor() )
3326 Color aColor( pParent->GetBackground().GetColor() );
3327 SetControlBackground( aColor );
3329 else
3330 SetControlBackground( aFont.GetFillColor() );
3331 SetControlForeground( aFont.GetColor() );
3332 SetPosPixel( rPos );
3333 SetSizePixel( CalcAdjustedSize(rSize) );
3334 SetText( rData );
3335 SaveValue();
3337 aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3338 aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3340 aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3341 aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3342 GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3343 GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3344 Show();
3345 GrabFocus();
3348 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3350 if( !bAlreadyInCallback )
3352 GetpApp()->RemoveAccel( &aAccReturn );
3353 GetpApp()->RemoveAccel( &aAccEscape );
3357 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3359 aTimer.Stop();
3360 if ( !bAlreadyInCallback )
3362 bAlreadyInCallback = sal_True;
3363 GetpApp()->RemoveAccel( &aAccReturn );
3364 GetpApp()->RemoveAccel( &aAccEscape );
3365 Hide();
3366 aCallBackHdl.Call( this );
3370 IMPL_LINK_NOARG(IcnViewEdit_Impl, Timeout_Impl)
3372 CallCallBackHdl_Impl();
3373 return 0;
3376 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG )
3378 bCanceled = sal_False;
3379 bGrabFocus = sal_True;
3380 CallCallBackHdl_Impl();
3381 return 1;
3384 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG )
3386 bCanceled = sal_True;
3387 bGrabFocus = sal_True;
3388 CallCallBackHdl_Impl();
3389 return 1;
3392 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3394 KeyCode aCode = rKEvt.GetKeyCode();
3395 sal_uInt16 nCode = aCode.GetCode();
3397 switch ( nCode )
3399 case KEY_ESCAPE:
3400 bCanceled = sal_True;
3401 bGrabFocus = sal_True;
3402 CallCallBackHdl_Impl();
3403 break;
3405 case KEY_RETURN:
3406 bCanceled = sal_False;
3407 bGrabFocus = sal_True;
3408 CallCallBackHdl_Impl();
3409 break;
3411 default:
3412 MultiLineEdit::KeyInput( rKEvt );
3416 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3418 if( rNEvt.GetType() == EVENT_LOSEFOCUS )
3420 if ( !bAlreadyInCallback &&
3421 ((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
3423 bCanceled = sal_False;
3424 aTimer.SetTimeout(10);
3425 aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
3426 aTimer.Start();
3429 return 0;
3432 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel )
3434 if ( !bAlreadyInCallback )
3436 bCanceled = bCancel;
3437 CallCallBackHdl_Impl();
3441 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
3443 if( !(nFlags & F_ENTRYLISTPOS_VALID ))
3444 ((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
3445 return pEntry->nPos;
3448 void SvxIconChoiceCtrl_Impl::InitSettings()
3450 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
3452 if( !pView->HasFont() )
3454 // unit (from settings) is Point
3455 Font aFont( rStyleSettings.GetFieldFont() );
3456 //const Font& rFont = pView->GetFont();
3457 //if( pView->HasFontTextColor() )
3458 aFont.SetColor( rStyleSettings.GetWindowTextColor() );
3459 //if( pView->HasFontFillColor() )
3460 //aFont.SetFillColor( rFont.GetFillColor() );
3461 pView->SetPointFont( aFont );
3462 SetDefaultTextSize();
3465 //if( !pView->HasFontTextColor() )
3466 pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
3467 //if( !pView->HasFontFillColor() )
3468 pView->SetTextFillColor();
3470 //if( !pView->HasBackground() )
3471 pView->SetBackground( rStyleSettings.GetFieldColor());
3473 long nScrBarSize = rStyleSettings.GetScrollBarSize();
3474 if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
3476 nHorSBarHeight = nScrBarSize;
3477 Size aSize( aHorSBar.GetSizePixel() );
3478 aSize.Height() = nScrBarSize;
3479 aHorSBar.Hide();
3480 aHorSBar.SetSizePixel( aSize );
3482 nVerSBarWidth = nScrBarSize;
3483 aSize = aVerSBar.GetSizePixel();
3484 aSize.Width() = nScrBarSize;
3485 aVerSBar.Hide();
3486 aVerSBar.SetSizePixel( aSize );
3488 Size aOSize( pView->Control::GetOutputSizePixel() );
3489 PositionScrollBars( aOSize.Width(), aOSize.Height() );
3490 AdjustScrollBars();
3494 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner ) :
3495 _pOwner( pOwner )
3497 _pOwner->pHead = 0;
3500 EntryList_Impl::~EntryList_Impl()
3502 _pOwner->pHead = 0;
3505 void EntryList_Impl::clear()
3507 _pOwner->pHead = 0;
3508 maIconChoiceCtrlEntryList.clear();
3511 void EntryList_Impl::insert( size_t nPos, SvxIconChoiceCtrlEntry* pEntry )
3513 if ( nPos < maIconChoiceCtrlEntryList.size() ) {
3514 maIconChoiceCtrlEntryList.insert( maIconChoiceCtrlEntryList.begin() + nPos, pEntry );
3515 } else {
3516 maIconChoiceCtrlEntryList.push_back( pEntry );
3518 if( _pOwner->pHead )
3519 pEntry->SetBacklink( _pOwner->pHead->pblink );
3522 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
3524 if( eMode == ePositionMode )
3525 return;
3527 SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
3528 ePositionMode = eMode;
3529 size_t nCount = aEntries.size();
3531 if( eOldMode == IcnViewPositionModeAutoArrange )
3533 // when positioning moved entries "hard", there are problems with
3534 // unwanted overlaps, as these entries aren't taken into account in
3535 // Arrange.
3536 if( aEntries.size() )
3537 aAutoArrangeTimer.Start();
3538 return;
3541 if( ePositionMode == IcnViewPositionModeAutoArrange )
3543 for( size_t nCur = 0; nCur < nCount; nCur++ )
3545 SvxIconChoiceCtrlEntry* pEntry = aEntries[ nCur ];
3546 if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
3547 SetEntryPos(pEntry, GetEntryBoundRect( pEntry ).TopLeft());
3550 if( aEntries.size() )
3551 aAutoArrangeTimer.Start();
3553 else if( ePositionMode == IcnViewPositionModeAutoAdjust )
3555 AdjustEntryAtGrid( 0 );
3559 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3560 SvxIconChoiceCtrlEntry* pPredecessor )
3562 if( !IsAutoArrange() )
3563 return;
3565 if( pEntry == pPredecessor )
3566 return;
3568 sal_uLong nPos1 = GetEntryListPos( pEntry );
3569 if( !pHead )
3571 if( pPredecessor )
3573 sal_uLong nPos2 = GetEntryListPos( pPredecessor );
3574 if( nPos1 == (nPos2 + 1) )
3575 return; // is already the predecessor
3577 else if( !nPos1 )
3578 return;
3581 if( !pHead )
3582 InitPredecessors();
3584 if( !pPredecessor && pHead == pEntry )
3585 return; // is already the first one
3587 sal_Bool bSetHead = sal_False;
3588 if( !pPredecessor )
3590 bSetHead = sal_True;
3591 pPredecessor = pHead->pblink;
3593 if( pEntry == pHead )
3595 pHead = pHead->pflink;
3596 bSetHead = sal_False;
3598 if( pEntry != pPredecessor )
3600 pEntry->Unlink();
3601 pEntry->SetBacklink( pPredecessor );
3603 if( bSetHead )
3604 pHead = pEntry;
3605 pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
3606 aAutoArrangeTimer.Start();
3609 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
3610 const Point& rPosTopLeft )
3612 Point aPos( rPosTopLeft ); //TopLeft
3613 Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
3614 Point aNewPos( aCenterRect.Center() );
3615 sal_uLong nGrid = GetPredecessorGrid( aNewPos );
3616 size_t nCount = aEntries.size();
3617 if( nGrid == ULONG_MAX )
3618 return 0;
3619 if( nGrid >= nCount )
3620 nGrid = nCount - 1;
3621 if( !pHead )
3622 return aEntries[ nGrid ];
3624 SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
3625 // TODO: go through list from the end if nGrid > nCount/2
3626 for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
3627 pCur = pCur->pflink;
3629 return pCur;
3632 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
3634 Point aPos( rPos );
3635 aPos.X() -= LROFFS_WINBORDER;
3636 aPos.Y() -= TBOFFS_WINBORDER;
3637 sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX);
3638 if( nMaxCol )
3639 nMaxCol--;
3640 sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX);
3641 if( nGridX > nMaxCol )
3642 nGridX = nMaxCol;
3643 sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY);
3644 sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX);
3645 sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
3646 long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
3647 if( rPos.X() < nMiddle )
3649 if( !nGrid )
3650 nGrid = ULONG_MAX;
3651 else
3652 nGrid--;
3654 return nGrid;
3657 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
3659 if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
3660 return sal_False;
3662 Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
3663 aPos -= pView->GetMapMode().GetOrigin();
3664 SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True );
3666 if ( !pEntry )
3667 return sal_False;
3669 String sQuickHelpText = pEntry->GetQuickHelpText();
3670 String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
3671 Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) );
3672 if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
3673 return sal_False;
3675 Rectangle aOptTextRect( aTextRect );
3676 aOptTextRect.Bottom() = LONG_MAX;
3677 sal_uInt16 nNewFlags = nCurTextDrawFlags;
3678 nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
3679 aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
3680 if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
3682 //aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
3683 Point aPt( aOptTextRect.TopLeft() );
3684 aPt += pView->GetMapMode().GetOrigin();
3685 aPt = pView->OutputToScreenPixel( aPt );
3686 // subtract border of tooltip help
3687 aPt.Y() -= 1;
3688 aPt.X() -= 3;
3689 aOptTextRect.SetPos( aPt );
3690 String sHelpText;
3691 if ( sQuickHelpText.Len() > 0 )
3692 sHelpText = sQuickHelpText;
3693 else
3694 sHelpText = aEntryText;
3695 Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
3698 return sal_True;
3701 void SvxIconChoiceCtrl_Impl::ClearColumnList()
3703 if( !pColumns )
3704 return;
3706 pColumns->clear();
3707 DELETEZ(pColumns);
3710 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
3712 if( !pColumns )
3713 pColumns = new SvxIconChoiceCtrlColumnInfoMap;
3715 SvxIconChoiceCtrlColumnInfo* pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
3716 pColumns->insert( nIndex, pInfo );
3718 // HACK: Detail mode is not yet fully implemented, this workaround makes it
3719 // fly with a single column
3720 if( !nIndex && (nWinBits & WB_DETAILS) )
3721 nGridDX = pInfo->GetWidth();
3723 if( GetUpdateMode() )
3724 Arrange( IsAutoArrange() );
3727 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
3729 if (!pColumns)
3730 return 0;
3731 SvxIconChoiceCtrlColumnInfoMap::const_iterator it = pColumns->find( nIndex );
3732 if( it == pColumns->end() )
3733 return 0;
3734 return it->second;
3737 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
3738 OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide )
3740 Rectangle aBmpRect( rBmpRect );
3741 long nBorder = 2;
3742 if( aImageSize.Width() < 32 )
3743 nBorder = 1;
3744 aBmpRect.Right() += nBorder;
3745 aBmpRect.Left() -= nBorder;
3746 aBmpRect.Bottom() += nBorder;
3747 aBmpRect.Top() -= nBorder;
3749 if ( bHide )
3750 pView->Invalidate( aBmpRect );
3751 else
3753 DecorationView aDecoView( pOut );
3754 sal_uInt16 nDecoFlags;
3755 if ( bHighlightFramePressed )
3756 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
3757 else
3758 nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
3759 aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
3763 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
3764 sal_Bool bKeepHighlightFlags )
3766 if( pEntry == pCurHighlightFrame )
3767 return;
3769 if( !bKeepHighlightFlags )
3770 bHighlightFramePressed = sal_False;
3772 HideEntryHighlightFrame();
3773 pCurHighlightFrame = pEntry;
3774 if( pEntry )
3776 Rectangle aBmpRect( CalcFocusRect(pEntry) );
3777 DrawHighlightFrame( pView, aBmpRect, sal_False );
3781 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
3783 if( !pCurHighlightFrame )
3784 return;
3786 SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
3787 pCurHighlightFrame = 0;
3788 Rectangle aBmpRect( CalcFocusRect(pEntry) );
3789 DrawHighlightFrame( pView, aBmpRect, sal_True );
3792 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
3794 // When single-click mode is active, the selection handler should be called
3795 // synchronously, as the selection is automatically taken away once the
3796 // mouse cursor doesn't touch the object any more. Else, we might run into
3797 // missing calls to Select if the object is selected from a mouse movement,
3798 // because when starting the timer, the mouse cursor might have already left
3799 // the object.
3800 // In special cases (=>SfxFileDialog!), synchronous calls can be forced via
3801 // WB_NOASYNCSELECTHDL.
3802 if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
3804 pHdlEntry = 0;
3805 pView->ClickIcon();
3806 //pView->Select();
3808 else
3809 aCallSelectHdlTimer.Start();
3812 IMPL_LINK_NOARG(SvxIconChoiceCtrl_Impl, CallSelectHdlHdl)
3814 pHdlEntry = 0;
3815 pView->ClickIcon();
3816 //pView->Select();
3817 return 0;
3820 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper )
3822 MapMode aMapMode( pView->GetMapMode() );
3823 aMapMode.SetOrigin( rPos );
3824 pView->SetMapMode( aMapMode );
3825 if( !bDoNotUpdateWallpaper )
3827 sal_Bool bScrollable = pView->GetBackground().IsScrollable();
3828 if( pView->HasBackground() && !bScrollable )
3830 Rectangle aRect( GetOutputRect());
3831 Wallpaper aPaper( pView->GetBackground() );
3832 aPaper.SetRect( aRect );
3833 pView->SetBackground( aPaper );
3838 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
3840 pView->CallImplEventListeners( nEvent, pData );
3844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */