xref: /aoo41x/main/svtools/source/contnr/imivctl1.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <limits.h>
32 #include <tools/debug.hxx>
33 #include <vcl/wall.hxx>
34 #include <vcl/help.hxx>
35 #include <vcl/decoview.hxx>
36 #include <vcl/svapp.hxx>
37 #include <tools/poly.hxx>
38 #include <vcl/lineinfo.hxx>
39 #include <vcl/i18nhelp.hxx>
40 #include <vcl/mnemonic.hxx>
41 #include <vcl/controllayout.hxx>
42 
43 #include <svtools/ivctrl.hxx>
44 #include "imivctl.hxx"
45 #include <svtools/svmedit.hxx>
46 
47 #include <algorithm>
48 #include <memory>
49 
50 #define DD_SCROLL_PIXEL 24
51 #define IMPICNVIEW_ACC_RETURN 1
52 #define IMPICNVIEW_ACC_ESCAPE 2
53 
54 #define DRAWTEXT_FLAGS_ICON \
55 	( TEXT_DRAW_CENTER | TEXT_DRAW_TOP | TEXT_DRAW_ENDELLIPSIS | \
56 	  TEXT_DRAW_CLIP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MNEMONIC )
57 
58 #define DRAWTEXT_FLAGS_SMALLICON (TEXT_DRAW_LEFT|TEXT_DRAW_ENDELLIPSIS|TEXT_DRAW_CLIP)
59 
60 #define EVENTID_SHOW_CURSOR				((void*)1)
61 #define EVENTID_ADJUST_SCROLLBARS		((void*)2)
62 
63 struct SvxIconChoiceCtrlEntry_Impl
64 {
65 	SvxIconChoiceCtrlEntry*	_pEntry;
66 	Point			_aPos;
67 					SvxIconChoiceCtrlEntry_Impl( SvxIconChoiceCtrlEntry* pEntry, const Rectangle& rBoundRect )
68 					: _pEntry( pEntry), _aPos( rBoundRect.TopLeft()) {}
69 };
70 
71 static sal_Bool bEndScrollInvalidate = sal_True;
72 
73 // ----------------------------------------------------------------------------------------------
74 
75 class IcnViewEdit_Impl : public MultiLineEdit
76 {
77 	Link 			aCallBackHdl;
78 	Accelerator 	aAccReturn;
79 	Accelerator 	aAccEscape;
80 	Timer 			aTimer;
81 	sal_Bool 			bCanceled;
82 	sal_Bool 			bAlreadyInCallback;
83 	sal_Bool			bGrabFocus;
84 
85 	void 			CallCallBackHdl_Impl();
86 					DECL_LINK( Timeout_Impl, Timer * );
87 					DECL_LINK( ReturnHdl_Impl, Accelerator * );
88 					DECL_LINK( EscapeHdl_Impl, Accelerator * );
89 
90 public:
91 
92 					IcnViewEdit_Impl(
93 						SvtIconChoiceCtrl* pParent,
94 						const Point& rPos,
95 						const Size& rSize,
96 						const XubString& rData,
97 						const Link& rNotifyEditEnd );
98 
99 					~IcnViewEdit_Impl();
100 	virtual void 	KeyInput( const KeyEvent& rKEvt );
101 	virtual long 	PreNotify( NotifyEvent& rNEvt );
102 	sal_Bool			EditingCanceled() const { return bCanceled; }
103 	void			StopEditing( sal_Bool bCancel = sal_False );
104 	sal_Bool			IsGrabFocus() const { return bGrabFocus; }
105 };
106 
107 // ----------------------------------------------------------------------------------------------
108 
109 // ----------------------------------------------------------------------------------------------
110 
111 SvxIconChoiceCtrl_Impl::SvxIconChoiceCtrl_Impl( SvtIconChoiceCtrl* pCurView,
112 	WinBits nWinStyle ) :
113 	aEntries( this ),
114 	aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
115 	aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ),
116 	aScrBarBox( pCurView ),
117 	aImageSize( 32, 32 ),
118 	pColumns( 0 )
119 {
120 	bChooseWithCursor=sal_False;
121 	pEntryPaintDev = 0;
122 	pCurEditedEntry = 0;
123 	pCurHighlightFrame = 0;
124 	pEdit = 0;
125 	pAnchor = 0;
126 	pDraggedSelection = 0;
127 	pPrevDropTarget = 0;
128 	pHdlEntry = 0;
129 	pHead = NULL;
130 	pCursor = NULL;
131 	bUpdateMode = sal_True;
132     bEntryEditingEnabled = sal_False;
133 	bInDragDrop = sal_False;
134 	bHighlightFramePressed = sal_False;
135 	eSelectionMode = MULTIPLE_SELECTION;
136 	pView = pCurView;
137 	pZOrderList = new List; //SvPtrarr;
138 	ePositionMode = IcnViewPositionModeFree;
139 	SetStyle( nWinStyle );
140 	nFlags = 0;
141 	nUserEventAdjustScrBars = 0;
142 	nUserEventShowCursor = 0;
143 	nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
144 	nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
145 	pDDRefEntry = 0;
146 	pDDDev = 0;
147 	pDDBufDev = 0;
148 	pDDTempDev = 0;
149 	eTextMode = IcnShowTextShort;
150 	pImpCursor = new IcnCursor_Impl( this );
151 	pGridMap = new IcnGridMap_Impl( this );
152 
153 	aVerSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollUpDownHdl ) );
154 	aHorSBar.SetScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl ) );
155 	Link aEndScrollHdl( LINK( this, SvxIconChoiceCtrl_Impl, EndScrollHdl ) );
156 	aVerSBar.SetEndScrollHdl( aEndScrollHdl );
157 	aHorSBar.SetEndScrollHdl( aEndScrollHdl );
158 
159 	nHorSBarHeight = aHorSBar.GetSizePixel().Height();
160 	nVerSBarWidth = aVerSBar.GetSizePixel().Width();
161 
162 	aEditTimer.SetTimeout( 800 );
163 	aEditTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,EditTimeoutHdl));
164 	aAutoArrangeTimer.SetTimeout( 100 );
165 	aAutoArrangeTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,AutoArrangeHdl));
166 	aCallSelectHdlTimer.SetTimeout( 500 );
167 	aCallSelectHdlTimer.SetTimeoutHdl( LINK(this,SvxIconChoiceCtrl_Impl,CallSelectHdlHdl));
168 
169 	aDocRectChangedTimer.SetTimeout( 50 );
170 	aDocRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,DocRectChangedHdl));
171 	aVisRectChangedTimer.SetTimeout( 50 );
172 	aVisRectChangedTimer.SetTimeoutHdl(LINK(this,SvxIconChoiceCtrl_Impl,VisRectChangedHdl));
173 
174 	Clear( sal_True );
175 
176     SetGrid( Size(100, 70) );
177 }
178 
179 SvxIconChoiceCtrl_Impl::~SvxIconChoiceCtrl_Impl()
180 {
181 	pCurEditedEntry = 0;
182 	DELETEZ(pEdit);
183 	Clear();
184 	StopEditTimer();
185 	CancelUserEvents();
186 	delete pZOrderList;
187 	delete pImpCursor;
188 	delete pGridMap;
189 	delete pDDDev;
190 	delete pDDBufDev;
191 	delete pDDTempDev;
192 	delete pDraggedSelection;
193 	delete pEntryPaintDev;
194 	ClearSelectedRectList();
195 	ClearColumnList();
196 }
197 
198 void SvxIconChoiceCtrl_Impl::Clear( sal_Bool bInCtor )
199 {
200 	StopEntryEditing( sal_True );
201 	nSelectionCount = 0;
202 	DELETEZ(pDraggedSelection);
203 	bInDragDrop = sal_False;
204 	pCurHighlightFrame = 0;
205 	StopEditTimer();
206 	CancelUserEvents();
207 	ShowCursor( sal_False );
208 	bBoundRectsDirty = sal_False;
209 	nMaxBoundHeight = 0;
210 
211 	nFlags &= ~(F_PAINTED | F_MOVED_ENTRIES);
212 	pCursor = 0;
213 	if( !bInCtor )
214 	{
215 		pImpCursor->Clear();
216 		pGridMap->Clear();
217 		aVirtOutputSize.Width() = 0;
218 		aVirtOutputSize.Height() = 0;
219 		Size aSize( pView->GetOutputSizePixel() );
220 		nMaxVirtWidth = aSize.Width() - nVerSBarWidth;
221 		if( nMaxVirtWidth <= 0 )
222 			nMaxVirtWidth = DEFAULT_MAX_VIRT_WIDTH;
223 		nMaxVirtHeight = aSize.Height() - nHorSBarHeight;
224 		if( nMaxVirtHeight <= 0 )
225 			nMaxVirtHeight = DEFAULT_MAX_VIRT_HEIGHT;
226 		pZOrderList->Clear(); //Remove(0,pZOrderList->Count());
227 		SetOrigin( Point() );
228 		if( bUpdateMode )
229 			pView->Invalidate(INVALIDATE_NOCHILDREN);
230 	}
231 	AdjustScrollBars();
232 	sal_uLong nCount = aEntries.Count();
233 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
234 	{
235 		SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
236 		delete pCur;
237 	}
238 	aEntries.Clear();
239 	DocRectChanged();
240 	VisRectChanged();
241 }
242 
243 void SvxIconChoiceCtrl_Impl::SetStyle( WinBits nWinStyle )
244 {
245 	nWinBits = nWinStyle;
246 	nCurTextDrawFlags = DRAWTEXT_FLAGS_ICON;
247 	if( nWinBits & (WB_SMALLICON | WB_DETAILS) )
248 		nCurTextDrawFlags = DRAWTEXT_FLAGS_SMALLICON;
249 	if( nWinBits & WB_NOSELECTION )
250 		eSelectionMode = NO_SELECTION;
251 	if( !(nWinStyle & (WB_ALIGN_TOP | WB_ALIGN_LEFT)))
252 		nWinBits |= WB_ALIGN_LEFT;
253 	if( (nWinStyle & WB_DETAILS))
254 	{
255 		if( !pColumns  )
256 			SetColumn( 0, SvxIconChoiceCtrlColumnInfo( 0, 100, IcnViewAlignLeft ));
257 	}
258 }
259 
260 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollUpDownHdl, ScrollBar*, pScrollBar )
261 {
262 	StopEntryEditing( sal_True );
263 	// Pfeil hoch: delta=-1; Pfeil runter: delta=+1
264 	Scroll( 0, pScrollBar->GetDelta(), sal_True );
265 	bEndScrollInvalidate = sal_True;
266 	return 0;
267 }
268 
269 IMPL_LINK( SvxIconChoiceCtrl_Impl, ScrollLeftRightHdl, ScrollBar*, pScrollBar )
270 {
271 	StopEntryEditing( sal_True );
272 	// Pfeil links: delta=-1; Pfeil rechts: delta=+1
273 	Scroll( pScrollBar->GetDelta(), 0, sal_True );
274 	bEndScrollInvalidate = sal_True;
275 	return 0;
276 }
277 
278 IMPL_LINK( SvxIconChoiceCtrl_Impl, EndScrollHdl, void*, EMPTYARG )
279 {
280 	if( pView->HasBackground() && !pView->GetBackground().IsScrollable() &&
281 		bEndScrollInvalidate )
282 	{
283 		pView->Invalidate(INVALIDATE_NOCHILDREN);
284 	}
285 	return 0;
286 }
287 
288 void SvxIconChoiceCtrl_Impl::FontModified()
289 {
290 	StopEditTimer();
291 	DELETEZ(pDDDev);
292 	DELETEZ(pDDBufDev);
293 	DELETEZ(pDDTempDev);
294 	DELETEZ(pEntryPaintDev);
295 	SetDefaultTextSize();
296 	ShowCursor( sal_False );
297 	ShowCursor( sal_True );
298 }
299 
300 void SvxIconChoiceCtrl_Impl::InsertEntry( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos,
301 	const Point* pPos )
302 {
303 	StopEditTimer();
304 	aEntries.Insert( pEntry, nPos );
305 	if( (nFlags & F_ENTRYLISTPOS_VALID) && nPos >= aEntries.Count() - 1 )
306 		pEntry->nPos = aEntries.Count() - 1;
307 	else
308 		nFlags &= ~F_ENTRYLISTPOS_VALID;
309 
310 	pZOrderList->Insert( (void*)pEntry, LIST_APPEND ); //pZOrderList->Count() );
311 	pImpCursor->Clear();
312 //	pGridMap->Clear();
313 	if( pPos )
314 	{
315 		Size aSize( CalcBoundingSize( pEntry ) );
316 		SetBoundingRect_Impl( pEntry, *pPos, aSize );
317 		SetEntryPos( pEntry, *pPos, sal_False, sal_True, sal_True /*keep grid map*/ );
318 		pEntry->nFlags |= ICNVIEW_FLAG_POS_MOVED;
319 		SetEntriesMoved( sal_True );
320 	}
321 	else
322 	{
323 		// wenn der UpdateMode sal_True ist, wollen wir nicht pauschal alle
324 		// BoundRects auf 'zu ueberpruefen' setzen, sondern nur das des
325 		// neuen Eintrags. Deshalb kein InvalidateBoundingRect aufrufen!
326 		pEntry->aRect.Right() = LONG_MAX;
327 		if( bUpdateMode )
328 		{
329 			FindBoundingRect( pEntry );
330 			Rectangle aOutputArea( GetOutputRect() );
331 			pGridMap->OccupyGrids( pEntry );
332 			if( !aOutputArea.IsOver( pEntry->aRect ) )
333 				return;	// ist nicht sichtbar
334 			pView->Invalidate( pEntry->aRect );
335 		}
336 		else
337 			InvalidateBoundingRect( pEntry->aRect );
338 	}
339 }
340 
341 void SvxIconChoiceCtrl_Impl::CreateAutoMnemonics( MnemonicGenerator* _pGenerator )
342 {
343     ::std::auto_ptr< MnemonicGenerator > pAutoDeleteOwnGenerator;
344     if ( !_pGenerator )
345     {
346         _pGenerator = new MnemonicGenerator;
347         pAutoDeleteOwnGenerator.reset( _pGenerator );
348     }
349 
350     sal_uLong   nEntryCount = GetEntryCount();
351 	sal_uLong   i;
352 
353 	// insert texts in generator
354 	for( i = 0; i < nEntryCount; ++i )
355 	{
356 		DBG_ASSERT( GetEntry( i ), "-SvxIconChoiceCtrl_Impl::CreateAutoMnemonics(): more expected than provided!" );
357 
358 		_pGenerator->RegisterMnemonic( GetEntry( i )->GetText() );
359 	}
360 
361 	// exchange texts with generated mnemonics
362 	for( i = 0; i < nEntryCount; ++i )
363 	{
364 		SvxIconChoiceCtrlEntry*	pEntry = GetEntry( i );
365 		String					aTxt = pEntry->GetText();
366 
367 		if( _pGenerator->CreateMnemonic( aTxt ) )
368 			pEntry->SetText( aTxt );
369 	}
370 }
371 
372 Rectangle SvxIconChoiceCtrl_Impl::GetOutputRect() const
373 {
374 	Point aOrigin( pView->GetMapMode().GetOrigin() );
375 	aOrigin *= -1;
376 	return Rectangle( aOrigin, aOutputSize );
377 }
378 
379 void SvxIconChoiceCtrl_Impl::SetListPositions()
380 {
381 	if( nFlags & F_ENTRYLISTPOS_VALID )
382 		return;
383 
384 	sal_uLong nCount = aEntries.Count();
385 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
386 	{
387 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
388 		pEntry->nPos = nCur;
389 	}
390 	nFlags |= F_ENTRYLISTPOS_VALID;
391 }
392 
393 void SvxIconChoiceCtrl_Impl::RemoveEntry( SvxIconChoiceCtrlEntry* pEntry )
394 {
395 	sal_Bool bSyncSingleSelection;
396 	// bei Single-Selection wird die Selektion beim Umsetzen des Cursors
397 	// mitgefuehrt. Das soll aber nur erfolgen, wenn ueberhaupt ein
398 	// Eintrag selektiert ist.
399 	if( GetSelectionCount() )
400 		bSyncSingleSelection = sal_True;
401 	else
402 		bSyncSingleSelection = sal_False;
403 
404 	if( pEntry == pCurHighlightFrame )
405 		pCurHighlightFrame = 0;
406 
407 	if( bInDragDrop )
408 	{
409 		DELETEZ(pDraggedSelection);
410 		bInDragDrop = sal_False;
411 	}
412 
413 	if( pEntry->IsSelected() )
414 		CallSelectHandler( 0 );
415 
416 	if( aEntries.Count() == 1 && aEntries.GetObject(0) == pEntry )
417 	{
418 		Clear();
419 		return;
420 	}
421 
422 	StopEditTimer();
423 	if( pEntry == pAnchor )
424 		pAnchor = 0;
425 	if( pEntry->IsSelected() )
426 		nSelectionCount--;
427 	sal_Bool bEntryBoundValid = IsBoundingRectValid( pEntry->aRect );
428 	if( bEntryBoundValid )
429 		pView->Invalidate( pEntry->aRect );
430 
431 	sal_Bool bSetNewCursor = sal_False;
432 	SvxIconChoiceCtrlEntry* pNewCursor = NULL;
433 
434 	if( pEntry == pCursor )
435 	{
436 		bSetNewCursor = sal_True;
437 		pNewCursor = FindNewCursor();
438 		ShowCursor( sal_False );
439 		pCursor = 0;
440 	}
441 
442 	sal_Bool bCurEntryPosValid = (nFlags & F_ENTRYLISTPOS_VALID) ? sal_True : sal_False;
443 	if( bCurEntryPosValid && aEntries.GetObject(aEntries.Count()-1) != pEntry )
444 		nFlags &= ~F_ENTRYLISTPOS_VALID;
445 	sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry );
446 	pZOrderList->Remove( nPos );
447 	if( bCurEntryPosValid )
448 	{
449 		DBG_ASSERT(aEntries.GetObject(pEntry->nPos)==pEntry,"RemoveEntry: Wrong nPos in entry");
450 		aEntries.Remove( pEntry->nPos );
451 	}
452 	else
453 		aEntries.Remove( pEntry );
454 	pImpCursor->Clear();
455 	pGridMap->Clear();
456 	delete pEntry;
457 	if( IsAutoArrange() && aEntries.Count() )
458 		aAutoArrangeTimer.Start();
459 	if( bSetNewCursor )
460 	{
461 		// Fokusrechteck asynchron einblenden, um das Loeschen einer
462 		// Multiselektion zu beschleunigen.
463 		SetCursor( pNewCursor, bSyncSingleSelection, sal_True );
464 	}
465 }
466 
467 void SvxIconChoiceCtrl_Impl::SelectEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
468 	sal_Bool bCallHdl, sal_Bool bAdd, sal_Bool bSyncPaint )
469 {
470 	if( eSelectionMode == NO_SELECTION )
471 		return;
472 
473 	if( !bAdd )
474 	{
475 		if ( 0 == ( nFlags & F_CLEARING_SELECTION ) )
476 		{
477 			nFlags |= F_CLEARING_SELECTION;
478 			DeselectAllBut( pEntry, sal_True );
479 			nFlags &= ~F_CLEARING_SELECTION;
480 		}
481 	}
482 	if( pEntry->IsSelected() != bSelect )
483 	{
484 		pHdlEntry = pEntry;
485 		sal_uInt16 nEntryFlags = pEntry->GetFlags();
486 		if( bSelect )
487 		{
488 			nEntryFlags |= ICNVIEW_FLAG_SELECTED;
489 			pEntry->AssignFlags( nEntryFlags );
490 			nSelectionCount++;
491 			if( bCallHdl )
492 				CallSelectHandler( pEntry );
493 		}
494 		else
495 		{
496 			nEntryFlags &= ~( ICNVIEW_FLAG_SELECTED);
497 			pEntry->AssignFlags( nEntryFlags );
498 			nSelectionCount--;
499 			if( bCallHdl )
500 				CallSelectHandler( 0 );
501 		}
502 		EntrySelected( pEntry, bSelect, bSyncPaint );
503 	}
504 }
505 
506 void SvxIconChoiceCtrl_Impl::EntrySelected( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSelect,
507 	sal_Bool bSyncPaint )
508 {
509 	// bei SingleSelection dafuer sorgen, dass der Cursor immer
510 	// auf dem (einzigen) selektierten Eintrag steht. Aber nur,
511 	// wenn es bereits einen Cursor gibt
512 	if( bSelect && pCursor &&
513 		eSelectionMode == SINGLE_SELECTION &&
514 		pEntry != pCursor )
515 	{
516 		SetCursor( pEntry );
517 		//DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?")
518 	}
519 
520 	// beim Aufziehen nicht, da sonst die Schleife in SelectRect
521 	// nicht richtig funktioniert!
522 	if( !(nFlags & F_SELECTING_RECT) )
523 		ToTop( pEntry );
524 	if( bUpdateMode )
525 	{
526 		if( pEntry == pCursor )
527 			ShowCursor( sal_False );
528 		if( pView->IsTracking() && (bSelect || !pView->HasBackground()) ) // beim Tracken immer synchron
529 			PaintEntry( pEntry );
530 		else if( bSyncPaint ) // synchron & mit virtuellem OutDev!
531 			PaintEntryVirtOutDev( pEntry );
532 		else
533 		{
534 			pView->Invalidate( CalcFocusRect( pEntry ) );
535 		}
536 		if( pEntry == pCursor )
537 			ShowCursor( sal_True );
538 	} // if( bUpdateMode )
539 
540     // --> OD 2009-05-27 #i101012#
541     // emit vcl event LISTBOX_SELECT only in case that the given entry is selected.
542     if ( bSelect )
543     {
544         CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
545     }
546     // <--
547 }
548 
549 void SvxIconChoiceCtrl_Impl::ResetVirtSize()
550 {
551 	StopEditTimer();
552 	aVirtOutputSize.Width() = 0;
553 	aVirtOutputSize.Height() = 0;
554 	sal_Bool bLockedEntryFound = sal_False;
555 	const sal_uLong nCount = aEntries.Count();
556 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
557 	{
558 		SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
559 		pCur->ClearFlags( ICNVIEW_FLAG_POS_MOVED );
560 		if( pCur->IsPosLocked() )
561 		{
562 			// VirtSize u.a. anpassen
563 			if( !IsBoundingRectValid( pCur->aRect ) )
564 				FindBoundingRect( pCur );
565 			else
566 				AdjustVirtSize( pCur->aRect );
567 			bLockedEntryFound = sal_True;
568 		}
569 		else
570 			InvalidateBoundingRect( pCur->aRect );
571 	}
572 
573 	if( !(nWinBits & (WB_NOVSCROLL | WB_NOHSCROLL)) )
574 	{
575 		Size aRealOutputSize( pView->GetOutputSizePixel() );
576 		if( aVirtOutputSize.Width() < aRealOutputSize.Width() ||
577 			aVirtOutputSize.Height() < aRealOutputSize.Height() )
578 		{
579 			sal_uLong nGridCount = IcnGridMap_Impl::GetGridCount(
580 				aRealOutputSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
581 			if( nGridCount < nCount )
582 			{
583 				if( nWinBits & WB_ALIGN_TOP )
584 					nMaxVirtWidth = aRealOutputSize.Width() - nVerSBarWidth;
585 				else // WB_ALIGN_LEFT
586 					nMaxVirtHeight = aRealOutputSize.Height() - nHorSBarHeight;
587 			}
588 		}
589 	}
590 
591 	pImpCursor->Clear();
592 	pGridMap->Clear();
593 	VisRectChanged();
594 }
595 
596 void SvxIconChoiceCtrl_Impl::AdjustVirtSize( const Rectangle& rRect )
597 {
598 	long nHeightOffs = 0;
599 	long nWidthOffs = 0;
600 
601 	if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
602 		nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
603 
604 	if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
605 		nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
606 
607 	if( nWidthOffs || nHeightOffs )
608 	{
609 		Range aRange;
610 		aVirtOutputSize.Width() += nWidthOffs;
611 		aRange.Max() = aVirtOutputSize.Width();
612 		aHorSBar.SetRange( aRange );
613 
614 		aVirtOutputSize.Height() += nHeightOffs;
615 		aRange.Max() = aVirtOutputSize.Height();
616 		aVerSBar.SetRange( aRange );
617 
618 		pImpCursor->Clear();
619 		pGridMap->OutputSizeChanged();
620 		AdjustScrollBars();
621 		DocRectChanged();
622 	}
623 }
624 
625 void SvxIconChoiceCtrl_Impl::InitPredecessors()
626 {
627 	DBG_ASSERT(!pHead,"SvxIconChoiceCtrl_Impl::InitPredecessors() >> Already initialized");
628 	sal_uLong nCount = aEntries.Count();
629 	if( nCount )
630 	{
631 		SvxIconChoiceCtrlEntry* pPrev = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
632 		for( sal_uLong nCur = 1; nCur <= nCount; nCur++ )
633 		{
634 			pPrev->ClearFlags( ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED |
635 								ICNVIEW_FLAG_PRED_SET);
636 
637 			SvxIconChoiceCtrlEntry* pNext;
638 			if( nCur == nCount )
639 				pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
640 			else
641 				pNext = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
642 			pPrev->pflink = pNext;
643 			pNext->pblink = pPrev;
644 			pPrev = pNext;
645 		}
646 		pHead = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
647 	}
648 	else
649 		pHead = 0;
650 	nFlags &= ~F_MOVED_ENTRIES;
651 }
652 
653 void SvxIconChoiceCtrl_Impl::ClearPredecessors()
654 {
655 	if( pHead )
656 	{
657 		sal_uLong nCount = aEntries.Count();
658 		for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
659 		{
660 			SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
661 			pCur->pflink = 0;
662 			pCur->pblink = 0;
663 			pCur->ClearFlags( ICNVIEW_FLAG_PRED_SET );
664 		}
665 		pHead = 0;
666 	}
667 }
668 
669 void SvxIconChoiceCtrl_Impl::Arrange( sal_Bool bKeepPredecessors, long nSetMaxVirtWidth, long nSetMaxVirtHeight )
670 {
671 	if ( nSetMaxVirtWidth != 0 )
672 		nMaxVirtWidth = nSetMaxVirtWidth;
673 	else
674 		nMaxVirtWidth = aOutputSize.Width();
675 
676 	if ( nSetMaxVirtHeight != 0 )
677 		nMaxVirtHeight = nSetMaxVirtHeight;
678 	else
679 		nMaxVirtHeight = aOutputSize.Height();
680 
681 	ImpArrange( bKeepPredecessors );
682 }
683 
684 void SvxIconChoiceCtrl_Impl::ImpArrange( sal_Bool bKeepPredecessors )
685 {
686 	static Point aEmptyPoint;
687 
688 	sal_Bool bOldUpdate = bUpdateMode;
689 	Rectangle aCurOutputArea( GetOutputRect() );
690 	if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
691 		bUpdateMode = sal_False;
692 	aAutoArrangeTimer.Stop();
693 	nFlags &= ~F_MOVED_ENTRIES;
694 	nFlags |= F_ARRANGING;
695 	StopEditTimer();
696 	ShowCursor( sal_False );
697 	ResetVirtSize();
698 	if( !bKeepPredecessors )
699 		ClearPredecessors();
700 	bBoundRectsDirty = sal_False;
701 	SetOrigin( Point() );
702 	VisRectChanged();
703 	RecalcAllBoundingRectsSmart();
704 	// in der Detailsview muss das Invalidieren intelligenter erfolgen
705 	//if( !(nWinBits & WB_DETAILS ))
706 		pView->Invalidate( INVALIDATE_NOCHILDREN );
707 	nFlags &= ~F_ARRANGING;
708 	if( (nWinBits & WB_SMART_ARRANGE) && aCurOutputArea.TopLeft() != aEmptyPoint )
709 	{
710 		MakeVisible( aCurOutputArea );
711 		SetUpdateMode( bOldUpdate );
712 	}
713 	ShowCursor( sal_True );
714 }
715 
716 void SvxIconChoiceCtrl_Impl::Paint( const Rectangle& rRect )
717 {
718 	bEndScrollInvalidate = sal_False;
719 
720 #if defined(OV_DRAWGRID)
721 	Color aOldColor ( pView->GetLineColor() );
722 	Color aColor( COL_BLACK );
723 	pView->SetLineColor( aColor );
724 	Point aOffs( pView->GetMapMode().GetOrigin());
725 	Size aXSize( pView->GetOutputSizePixel() );
726 
727 	{
728 	Point aStart( LROFFS_WINBORDER, 0 );
729 	Point aEnd( LROFFS_WINBORDER, aXSize.Height());
730 	aStart -= aOffs;
731 	aEnd -= aOffs;
732 	pView->DrawLine( aStart, aEnd );
733 	}
734 	{
735 	Point aStart( 0, TBOFFS_WINBORDER );
736 	Point aEnd( aXSize.Width(), TBOFFS_WINBORDER );
737 	aStart -= aOffs;
738 	aEnd -= aOffs;
739 	pView->DrawLine( aStart, aEnd );
740 	}
741 
742 	for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
743 	{
744 		Point aStart( nDX+LROFFS_WINBORDER, 0 );
745 		Point aEnd( nDX+LROFFS_WINBORDER, aXSize.Height());
746 		aStart -= aOffs;
747 		aEnd -= aOffs;
748 		pView->DrawLine( aStart, aEnd );
749 	}
750 	for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
751 	{
752 		Point aStart( 0, nDY+TBOFFS_WINBORDER );
753 		Point aEnd( aXSize.Width(), nDY+TBOFFS_WINBORDER );
754 		aStart -= aOffs;
755 		aEnd -= aOffs;
756 		pView->DrawLine( aStart, aEnd );
757 	}
758 	pView->SetLineColor( aOldColor );
759 #endif
760 	nFlags |= F_PAINTED;
761 
762 	if( !aEntries.Count() )
763 		return;
764 	if( !pCursor )
765 	{
766 		// set cursor to item with focus-flag
767 		sal_Bool bfound = sal_False;
768 		for ( sal_uLong i = 0; i < pView->GetEntryCount() && !bfound; i++)
769 		{
770 			SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry ( i );
771 			if( pEntry->IsFocused() )
772 			{
773 				pCursor = pEntry;
774 				bfound=sal_True;
775 			}
776 		}
777 
778 		if( !bfound )
779 			pCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
780 	}
781 
782 	// Show Focus at Init-Time
783 	if ( pView->HasFocus() )
784 		GetFocus();
785 
786 	sal_uLong nCount = pZOrderList->Count();
787 	if( !nCount )
788 		return;
789 
790 	sal_Bool bResetClipRegion = sal_False;
791 	if( !pView->IsClipRegion() )
792 	{
793 		Rectangle aOutputArea( GetOutputRect() );
794 		bResetClipRegion = sal_True;
795 		pView->SetClipRegion( aOutputArea );
796 	}
797 
798 	const sal_uInt16 nListInitSize = aEntries.Count() > USHRT_MAX ?
799 		USHRT_MAX : (sal_uInt16)aEntries.Count();
800 	List* pNewZOrderList = new List( nListInitSize );
801 	List* pPaintedEntries = new List( nListInitSize );
802 
803 	sal_uLong nPos = 0;
804 	while( nCount )
805 	{
806 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
807 		const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
808 		if( rRect.IsOver( rBoundRect ) )
809 		{
810 			PaintEntry( pEntry, rBoundRect.TopLeft(), pView, sal_True );
811 			// Eintraege, die neu gezeichnet werden, auf Top setzen
812 			pPaintedEntries->Insert( pEntry, LIST_APPEND );
813 		}
814 		else
815 			pNewZOrderList->Insert( pEntry, LIST_APPEND );
816 
817 		nCount--;
818 		nPos++;
819 	}
820 	delete pZOrderList;
821 	pZOrderList = pNewZOrderList;
822 	nCount = pPaintedEntries->Count();
823 	if( nCount )
824 	{
825 		for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
826 			pZOrderList->Insert( pPaintedEntries->GetObject(nCur), LIST_APPEND);
827 	}
828 	delete pPaintedEntries;
829 
830 	if( bResetClipRegion )
831 		pView->SetClipRegion();
832 }
833 
834 void SvxIconChoiceCtrl_Impl::RepaintEntries( sal_uInt16 nEntryFlagsMask )
835 {
836 	const sal_uLong nCount = pZOrderList->Count();
837 	if( !nCount )
838 		return;
839 
840 	sal_Bool bResetClipRegion = sal_False;
841 	Rectangle aOutRect( GetOutputRect() );
842 	if( !pView->IsClipRegion() )
843 	{
844 		bResetClipRegion = sal_True;
845 		pView->SetClipRegion( aOutRect );
846 	}
847 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
848 	{
849 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
850 		if( pEntry->GetFlags() & nEntryFlagsMask )
851 		{
852 			const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
853 			if( aOutRect.IsOver( rBoundRect ) )
854 				PaintEntry( pEntry, rBoundRect.TopLeft() );
855 		}
856 	}
857 	if( bResetClipRegion )
858 		pView->SetClipRegion();
859 }
860 
861 
862 void SvxIconChoiceCtrl_Impl::InitScrollBarBox()
863 {
864 	aScrBarBox.SetSizePixel( Size(nVerSBarWidth-1, nHorSBarHeight-1) );
865 	Size aSize( pView->GetOutputSizePixel() );
866 	aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth+1, aSize.Height()-nHorSBarHeight+1));
867 }
868 
869 IcnViewFieldType SvxIconChoiceCtrl_Impl::GetItem( SvxIconChoiceCtrlEntry* pEntry,
870 	const Point& rAbsPos )
871 {
872 	Rectangle aRect( CalcTextRect( pEntry ) );
873 	if( aRect.IsInside( rAbsPos ) )
874 		return IcnViewFieldTypeText;
875 
876 	aRect = CalcBmpRect( pEntry );
877 	if( aRect.IsInside( rAbsPos ) )
878 		return IcnViewFieldTypeImage;
879 
880 	return IcnViewFieldTypeDontknow;
881 }
882 
883 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonDown( const MouseEvent& rMEvt)
884 {
885 	sal_Bool bHandled = sal_True;
886 	bHighlightFramePressed = sal_False;
887 	StopEditTimer();
888 	sal_Bool bGotFocus = (sal_Bool)(!pView->HasFocus() && !(nWinBits & WB_NOPOINTERFOCUS));
889 	if( !(nWinBits & WB_NOPOINTERFOCUS) )
890 		pView->GrabFocus();
891 
892 	Point aDocPos( rMEvt.GetPosPixel() );
893 	if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
894 		return sal_False;
895 	ToDocPos( aDocPos );
896 	SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
897 	if( pEntry )
898 		MakeEntryVisible( pEntry, sal_False );
899 
900 	if( rMEvt.IsShift() && eSelectionMode != SINGLE_SELECTION )
901 	{
902 		if( pEntry )
903 			SetCursor_Impl( pCursor, pEntry, rMEvt.IsMod1(), rMEvt.IsShift(), sal_True);
904 		return sal_True;
905 	}
906 
907 	if( pAnchor && (rMEvt.IsShift() || rMEvt.IsMod1())) // Tastaturselektion?
908 	{
909 		DBG_ASSERT(eSelectionMode != SINGLE_SELECTION,"Invalid selection mode");
910 		if( rMEvt.IsMod1() )
911 			nFlags |= F_ADD_MODE;
912 
913 		if( rMEvt.IsShift() )
914 		{
915 			Rectangle aRect( GetEntryBoundRect( pAnchor ));
916 			if( pEntry )
917 				aRect.Union( GetEntryBoundRect( pEntry ) );
918 			else
919 			{
920 				Rectangle aTempRect( aDocPos, Size(1,1));
921 				aRect.Union( aTempRect );
922 			}
923 			aCurSelectionRect = aRect;
924 			SelectRect( aRect, (nFlags & F_ADD_MODE)!=0, &aSelectedRectList );
925 		}
926 		else if( rMEvt.IsMod1() )
927 		{
928 			AddSelectedRect( aCurSelectionRect );
929 			pAnchor = 0;
930 			aCurSelectionRect.SetPos( aDocPos );
931 		}
932 
933 		if( !pEntry && !(nWinBits & WB_NODRAGSELECTION))
934 			pView->StartTracking( STARTTRACK_SCROLLREPEAT );
935 		return sal_True;
936 	}
937 	else
938 	{
939 		if( !pEntry )
940 		{
941 			if( eSelectionMode == MULTIPLE_SELECTION )
942 			{
943 				if( !rMEvt.IsMod1() )  // Ctrl
944 				{
945 					if( !bGotFocus )
946 					{
947 						SetNoSelection();
948 						ClearSelectedRectList();
949 					}
950 				}
951 				else
952 					nFlags |= F_ADD_MODE;
953 				aCurSelectionRect.SetPos( aDocPos );
954 				pView->StartTracking( STARTTRACK_SCROLLREPEAT );
955 			}
956 			else
957 				bHandled = sal_False;
958 			return bHandled;
959 		}
960 	}
961 	sal_Bool bSelected = pEntry->IsSelected();
962 	sal_Bool bEditingEnabled = IsEntryEditingEnabled();
963 
964 	if( rMEvt.GetClicks() == 2 )
965 	{
966 		DeselectAllBut( pEntry );
967 		SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
968 		pHdlEntry = pEntry;
969 		pView->ClickIcon();
970 	}
971 	else
972 	{
973 		// Inplace-Editing ?
974 		if( rMEvt.IsMod2() )  // Alt?
975 		{
976 			if( bEntryEditingEnabled && pEntry &&
977 				pEntry->IsSelected())
978 			{
979 				if( pView->EditingEntry( pEntry ))
980 					EditEntry( pEntry );
981 			}
982 		}
983 		else if( eSelectionMode == SINGLE_SELECTION )
984 		{
985 			DeselectAllBut( pEntry );
986 			SetCursor( pEntry );
987 			if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
988 				rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
989 			{
990 				nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
991 			}
992 		}
993 		else if( eSelectionMode == NO_SELECTION )
994 		{
995 			if( rMEvt.IsLeft() && (nWinBits & WB_HIGHLIGHTFRAME) )
996 			{
997 				pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
998 				bHighlightFramePressed = sal_True;
999 				SetEntryHighlightFrame( pEntry, sal_True );
1000 			}
1001 		}
1002 		else
1003 		{
1004 			if( !rMEvt.GetModifier() && rMEvt.IsLeft() )
1005 			{
1006 				if( !bSelected )
1007 				{
1008 					DeselectAllBut( pEntry, sal_True /* Synchron painten */ );
1009 					SetCursor( pEntry );
1010 					SelectEntry( pEntry, sal_True, sal_True, sal_False, sal_True );
1011 				}
1012 				else
1013 				{
1014 					// erst im Up deselektieren, falls Move per D&D!
1015 					nFlags |= F_DOWN_DESELECT;
1016 					if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
1017 						rMEvt.IsLeft())
1018 					{
1019 						nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1020 					}
1021 				}
1022 			}
1023 			else if( rMEvt.IsMod1() )
1024 				nFlags |= F_DOWN_CTRL;
1025 		}
1026 	}
1027 	return bHandled;
1028 }
1029 
1030 sal_Bool SvxIconChoiceCtrl_Impl::MouseButtonUp( const MouseEvent& rMEvt )
1031 {
1032 	sal_Bool bHandled = sal_False;
1033 	if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
1034 	{
1035 		nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1036 		bHandled = sal_True;
1037 	}
1038 
1039 	Point aDocPos( rMEvt.GetPosPixel() );
1040 	ToDocPos( aDocPos );
1041 	SvxIconChoiceCtrlEntry* pDocEntry = GetEntry( aDocPos );
1042 	if( pDocEntry )
1043 	{
1044 		if( nFlags & F_DOWN_CTRL )
1045 		{
1046 			// Ctrl & MultiSelection
1047 			ToggleSelection( pDocEntry );
1048 			SetCursor( pDocEntry );
1049 			bHandled = sal_True;
1050 		}
1051 		else if( nFlags & F_DOWN_DESELECT )
1052 		{
1053 			DeselectAllBut( pDocEntry );
1054 			SetCursor( pDocEntry );
1055 			SelectEntry( pDocEntry, sal_True, sal_True, sal_False, sal_True );
1056 			bHandled = sal_True;
1057 		}
1058 	}
1059 
1060 	nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1061 	if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
1062 	{
1063 		bHandled = sal_True;
1064 		StartEditTimer();
1065 		nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
1066 	}
1067 
1068 	if((nWinBits & WB_HIGHLIGHTFRAME) && bHighlightFramePressed && pCurHighlightFrame)
1069 	{
1070 		bHandled = sal_True;
1071 		SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
1072 		pCurHighlightFrame = 0; // Neues painten des Frames erzwingen
1073 		bHighlightFramePressed = sal_False;
1074 		SetEntryHighlightFrame( pEntry, sal_True );
1075 #if 0
1076 		CallSelectHandler( pCurHighlightFrame );
1077 #else
1078 		pHdlEntry = pCurHighlightFrame;
1079 		pView->ClickIcon();
1080 
1081 		// set focus on Icon
1082 		SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1083 		SetCursor_Impl( pOldCursor, pHdlEntry, sal_False, sal_False, sal_True );
1084 #endif
1085 		pHdlEntry = 0;
1086 	}
1087 	return bHandled;
1088 }
1089 
1090 sal_Bool SvxIconChoiceCtrl_Impl::MouseMove( const MouseEvent& rMEvt )
1091 {
1092 	const Point aDocPos( pView->PixelToLogic(rMEvt.GetPosPixel()) );
1093 
1094 	if( pView->IsTracking() )
1095 		return sal_False;
1096 	else if( nWinBits & WB_HIGHLIGHTFRAME )
1097 	{
1098 		SvxIconChoiceCtrlEntry* pEntry = GetEntry( aDocPos, sal_True );
1099 		SetEntryHighlightFrame( pEntry );
1100 	}
1101 	else
1102 		return sal_False;
1103 	return sal_True;
1104 }
1105 
1106 void SvxIconChoiceCtrl_Impl::Tracking( const TrackingEvent& rTEvt )
1107 {
1108 	if ( rTEvt.IsTrackingEnded() )
1109 	{
1110 		// Das Rechteck darf nicht "justified" sein, da seine
1111 		// TopLeft-Position u.U. zur Berechnung eines Ankers
1112 		// benutzt wird.
1113 		AddSelectedRect( aCurSelectionRect );
1114 		pView->HideTracking();
1115 		nFlags &= ~(F_ADD_MODE);
1116 		if( rTEvt.IsTrackingCanceled() )
1117 			SetNoSelection();
1118 	}
1119 	else
1120 	{
1121 		Point aPosPixel = rTEvt.GetMouseEvent().GetPosPixel();
1122 		Point aDocPos( aPosPixel );
1123 		ToDocPos( aDocPos );
1124 
1125 		long nScrollDX, nScrollDY;
1126 
1127 		CalcScrollOffsets( aPosPixel, nScrollDX, nScrollDY, sal_False );
1128 		if( nScrollDX || nScrollDY )
1129 		{
1130 			pView->HideTracking();
1131 			pView->Scroll( nScrollDX, nScrollDY );
1132 		}
1133 		Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
1134 		if( aRect != aCurSelectionRect )
1135 		{
1136 			pView->HideTracking();
1137 			sal_Bool bAdd = (nFlags & F_ADD_MODE) ? sal_True : sal_False;
1138 			SelectRect( aRect, bAdd, &aSelectedRectList );
1139 		}
1140 		pView->ShowTracking( aRect, SHOWTRACK_SMALL | SHOWTRACK_CLIP );
1141 	}
1142 }
1143 
1144 void SvxIconChoiceCtrl_Impl::SetCursor_Impl( SvxIconChoiceCtrlEntry* pOldCursor,
1145 	SvxIconChoiceCtrlEntry* pNewCursor, sal_Bool bMod1, sal_Bool bShift, sal_Bool bPaintSync )
1146 {
1147 	if( pNewCursor )
1148 	{
1149 		SvxIconChoiceCtrlEntry* pFilterEntry = 0;
1150 		sal_Bool bDeselectAll = sal_False;
1151 		if( eSelectionMode != SINGLE_SELECTION )
1152 		{
1153 			if( !bMod1 && !bShift )
1154 				bDeselectAll = sal_True;
1155 			else if( bShift && !bMod1 && !pAnchor )
1156 			{
1157 				bDeselectAll = sal_True;
1158 				pFilterEntry = pOldCursor;
1159 			}
1160 		}
1161 		if( bDeselectAll )
1162 			DeselectAllBut( pFilterEntry, bPaintSync );
1163 		ShowCursor( sal_False );
1164 		MakeEntryVisible( pNewCursor );
1165 		SetCursor( pNewCursor );
1166 		if( bMod1 && !bShift )
1167 		{
1168 			if( pAnchor )
1169 			{
1170 				AddSelectedRect( pAnchor, pOldCursor );
1171 				pAnchor = 0;
1172 			}
1173 		}
1174 		else if( bShift )
1175 		{
1176 			if( !pAnchor )
1177 				pAnchor = pOldCursor;
1178 			if ( nWinBits & WB_ALIGN_LEFT )
1179 				SelectRange( pAnchor, pNewCursor, (nFlags & F_ADD_MODE)!=0 );
1180 			else
1181 				SelectRect(pAnchor,pNewCursor,(nFlags & F_ADD_MODE)!=0,&aSelectedRectList);
1182 		}
1183 		else
1184 		{
1185 			SelectEntry( pCursor, sal_True, sal_True,  sal_False, bPaintSync );
1186 			aCurSelectionRect = GetEntryBoundRect( pCursor );
1187 		}
1188 	}
1189 }
1190 
1191 sal_Bool SvxIconChoiceCtrl_Impl::KeyInput( const KeyEvent& rKEvt )
1192 {
1193 	StopEditTimer();
1194 
1195 	sal_Bool bMod2 = rKEvt.GetKeyCode().IsMod2();
1196 	sal_Unicode cChar = rKEvt.GetCharCode();
1197 	sal_uLong nPos = (sal_uLong)-1;
1198 	if ( bMod2 && cChar && IsMnemonicChar( cChar, nPos ) )
1199 	{
1200 		// shortcut is clicked
1201 		SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
1202 		SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1203 		if ( pNewCursor != pOldCursor )
1204 			SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
1205 		return sal_True;
1206 	}
1207 
1208 	if ( bMod2 )
1209 		// no actions with <ALT>
1210 		return sal_False;
1211 
1212 	sal_Bool bKeyUsed = sal_True;
1213 	sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1214 	sal_Bool bShift = rKEvt.GetKeyCode().IsShift();
1215 
1216 	if( eSelectionMode == SINGLE_SELECTION || eSelectionMode == NO_SELECTION)
1217 	{
1218 		bShift = sal_False;
1219 		bMod1 = sal_False;
1220 	}
1221 
1222 	if( bMod1 )
1223 		nFlags |= F_ADD_MODE;
1224 	sal_Bool bDeselectAll = sal_False;
1225 	if( eSelectionMode != SINGLE_SELECTION )
1226 	{
1227 		if( !bMod1 && !bShift )
1228 			bDeselectAll = sal_True;
1229 		if( bShift && !bMod1 && !pAnchor )
1230 			bDeselectAll = sal_True;
1231 	}
1232 
1233 	SvxIconChoiceCtrlEntry* pNewCursor;
1234 	SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
1235 
1236 	sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1237 	switch( nCode )
1238 	{
1239 		case KEY_UP:
1240 		case KEY_PAGEUP:
1241 			if( pCursor )
1242 			{
1243 				MakeEntryVisible( pCursor );
1244 				if( nCode == KEY_UP )
1245 					pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1246 				else
1247 					pNewCursor = pImpCursor->GoPageUpDown(pCursor,sal_False);
1248 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1249 				if( !pNewCursor )
1250 				{
1251 					Rectangle aRect( GetEntryBoundRect( pCursor ) );
1252 					if( aRect.Top())
1253 					{
1254 						aRect.Bottom() -= aRect.Top();
1255 						aRect.Top() = 0;
1256 						MakeVisible( aRect );
1257 					}
1258 				}
1259 
1260 				if ( bChooseWithCursor && pNewCursor != NULL )
1261 				{
1262 					pHdlEntry = pNewCursor;//GetCurEntry();
1263 					pCurHighlightFrame = pHdlEntry;
1264 					pView->ClickIcon();
1265 					pCurHighlightFrame = NULL;
1266 				}
1267 			}
1268 			break;
1269 
1270 		case KEY_DOWN:
1271 		case KEY_PAGEDOWN:
1272 			if( pCursor )
1273 			{
1274 				if( nCode == KEY_DOWN )
1275 					pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1276 				else
1277 					pNewCursor=pImpCursor->GoPageUpDown( pCursor,sal_True );
1278 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1279 
1280 				if ( bChooseWithCursor && pNewCursor != NULL)
1281 				{
1282 					pHdlEntry = pNewCursor;//GetCurEntry();
1283 					pCurHighlightFrame = pHdlEntry;
1284 					pView->ClickIcon();
1285 					pCurHighlightFrame = NULL;
1286 				}
1287 			}
1288 			break;
1289 
1290 		case KEY_RIGHT:
1291 			if( pCursor )
1292 			{
1293 				pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1294 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1295 			}
1296 			break;
1297 
1298 		case KEY_LEFT:
1299 			if( pCursor )
1300 			{
1301 				MakeEntryVisible( pCursor );
1302 				pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1303 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1304 				if( !pNewCursor )
1305 				{
1306 					Rectangle aRect( GetEntryBoundRect(pCursor));
1307 					if( aRect.Left() )
1308 					{
1309 						aRect.Right() -= aRect.Left();
1310 						aRect.Left() = 0;
1311 						MakeVisible( aRect );
1312 					}
1313 				}
1314 			}
1315 			break;
1316 
1317 // wird vom VCL-Tracking gesteuert
1318 #if 0
1319 		case KEY_ESCAPE:
1320 			if( pView->IsTracking() )
1321 			{
1322 				HideSelectionRect();
1323 				//SelectAll( sal_False );
1324 				SetNoSelection();
1325 				ClearSelectedRectList();
1326 				nFlags &= ~F_TRACKING;
1327 			}
1328 			else
1329 				bKeyUsed = sal_False;
1330 			break;
1331 #endif
1332 
1333 
1334 		case KEY_F2:
1335 			if( !bMod1 && !bShift )
1336 				EditTimeoutHdl( 0 );
1337 			else
1338 				bKeyUsed = sal_False;
1339 			break;
1340 
1341 		case KEY_F8:
1342 			if( rKEvt.GetKeyCode().IsShift() )
1343 			{
1344 				if( nFlags & F_ADD_MODE )
1345 					nFlags &= (~F_ADD_MODE);
1346 				else
1347 					nFlags |= F_ADD_MODE;
1348 			}
1349 			else
1350 				bKeyUsed = sal_False;
1351 			break;
1352 
1353 		case KEY_SPACE:
1354 			if( pCursor && eSelectionMode != SINGLE_SELECTION )
1355 			{
1356 				if( !bMod1 )
1357 				{
1358 					//SelectAll( sal_False );
1359 					SetNoSelection();
1360 					ClearSelectedRectList();
1361 
1362 					// click Icon with spacebar
1363 					SetEntryHighlightFrame( GetCurEntry(), sal_True );
1364 					pView->ClickIcon();
1365 					pHdlEntry = pCurHighlightFrame;
1366 					pCurHighlightFrame=0;
1367 				}
1368 				else
1369 					ToggleSelection( pCursor );
1370 			}
1371 			break;
1372 
1373 #ifdef DBG_UTIL
1374 		case KEY_F10:
1375 			if( rKEvt.GetKeyCode().IsShift() )
1376 			{
1377 				if( pCursor )
1378 					pView->SetEntryTextMode( IcnShowTextFull, pCursor );
1379 			}
1380 			if( rKEvt.GetKeyCode().IsMod1() )
1381 			{
1382 				if( pCursor )
1383 					pView->SetEntryTextMode( IcnShowTextShort, pCursor );
1384 			}
1385 			break;
1386 #endif
1387 
1388 		case KEY_ADD:
1389 		case KEY_DIVIDE :
1390 		case KEY_A:
1391 			if( bMod1 && (eSelectionMode != SINGLE_SELECTION))
1392 				SelectAll( sal_True );
1393 			else
1394 				bKeyUsed = sal_False;
1395 			break;
1396 
1397 		case KEY_SUBTRACT:
1398 		case KEY_COMMA :
1399 			if( bMod1 )
1400 				SetNoSelection();
1401 			else
1402 				bKeyUsed = sal_False;
1403 			break;
1404 
1405 		case KEY_RETURN:
1406 			if( bMod1 )
1407 			{
1408 				if( pCursor && bEntryEditingEnabled )
1409 					/*pView->*/EditEntry( pCursor );
1410 			}
1411 			else
1412 				bKeyUsed = sal_False;
1413 			break;
1414 
1415 		case KEY_END:
1416 			if( pCursor )
1417 			{
1418 				pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( aEntries.Count() - 1 );
1419 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1420 			}
1421 			break;
1422 
1423 		case KEY_HOME:
1424 			if( pCursor )
1425 			{
1426 				pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( 0 );
1427 				SetCursor_Impl( pOldCursor, pNewCursor, bMod1, bShift, sal_True );
1428 			}
1429 			break;
1430 
1431 		default:
1432 			bKeyUsed = sal_False;
1433 
1434 	}
1435 	return bKeyUsed;
1436 }
1437 
1438 // Berechnet TopLeft der Scrollbars (nicht ihre Groessen!)
1439 void SvxIconChoiceCtrl_Impl::PositionScrollBars( long nRealWidth, long nRealHeight )
1440 {
1441 	// hor scrollbar
1442 	Point aPos( 0, nRealHeight );
1443 	aPos.Y() -= nHorSBarHeight;
1444 
1445 	if( aHorSBar.GetPosPixel() != aPos )
1446 		aHorSBar.SetPosPixel( aPos );
1447 
1448 	// ver scrollbar
1449 	aPos.X() = nRealWidth; aPos.Y() = 0;
1450 	aPos.X() -= nVerSBarWidth;
1451 	aPos.X()++;
1452 	aPos.Y()--;
1453 
1454 	if( aVerSBar.GetPosPixel() != aPos )
1455 		aVerSBar.SetPosPixel( aPos );
1456 }
1457 
1458 void SvxIconChoiceCtrl_Impl::AdjustScrollBars( sal_Bool )
1459 {
1460 	Rectangle aOldOutRect( GetOutputRect() );
1461 	long nVirtHeight = aVirtOutputSize.Height();
1462 	long nVirtWidth = aVirtOutputSize.Width();
1463 
1464 	Size aOSize( pView->Control::GetOutputSizePixel() );
1465 	long nRealHeight = aOSize.Height();
1466 	long nRealWidth = aOSize.Width();
1467 
1468 	PositionScrollBars( nRealWidth, nRealHeight );
1469 
1470 	const MapMode& rMapMode = pView->GetMapMode();
1471 	Point aOrigin( rMapMode.GetOrigin() );
1472 
1473 	long nVisibleWidth;
1474 	if( nRealWidth > nVirtWidth )
1475 		nVisibleWidth = nVirtWidth + aOrigin.X();
1476 	else
1477 		nVisibleWidth = nRealWidth;
1478 
1479 	long nVisibleHeight;
1480 	if( nRealHeight > nVirtHeight )
1481 		nVisibleHeight = nVirtHeight + aOrigin.Y();
1482 	else
1483 		nVisibleHeight = nRealHeight;
1484 
1485 	sal_Bool bVerSBar = ( nWinBits & WB_VSCROLL ) != 0;
1486 	sal_Bool bHorSBar = ( nWinBits & WB_HSCROLL ) != 0;
1487 	sal_Bool bNoVerSBar = ( nWinBits & WB_NOVSCROLL ) != 0;
1488 	sal_Bool bNoHorSBar = ( nWinBits & WB_NOHSCROLL ) != 0;
1489 
1490 	sal_uInt16 nResult = 0;
1491 	if( nVirtHeight )
1492 	{
1493 		// activate ver scrollbar ?
1494 		if( !bNoVerSBar && (bVerSBar || ( nVirtHeight > nVisibleHeight)) )
1495 		{
1496 			nResult = 0x0001;
1497 			nRealWidth -= nVerSBarWidth;
1498 
1499 			if( nRealWidth > nVirtWidth )
1500 				nVisibleWidth = nVirtWidth + aOrigin.X();
1501 			else
1502 				nVisibleWidth = nRealWidth;
1503 
1504 			nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1505 		}
1506 		// activate hor scrollbar ?
1507 		if( !bNoHorSBar && (bHorSBar || (nVirtWidth > nVisibleWidth)) )
1508 		{
1509 			nResult |= 0x0002;
1510 			nRealHeight -= nHorSBarHeight;
1511 
1512 			if( nRealHeight > nVirtHeight )
1513 				nVisibleHeight = nVirtHeight + aOrigin.Y();
1514 			else
1515 				nVisibleHeight = nRealHeight;
1516 
1517 			// brauchen wir jetzt doch eine senkrechte Scrollbar ?
1518 			if( !(nResult & 0x0001) &&  // nur wenn nicht schon da
1519 				( !bNoVerSBar && ((nVirtHeight > nVisibleHeight) || bVerSBar)) )
1520 			{
1521 				nResult = 3; // beide sind an
1522 				nRealWidth -= nVerSBarWidth;
1523 
1524 				if( nRealWidth > nVirtWidth )
1525 					nVisibleWidth = nVirtWidth + aOrigin.X();
1526 				else
1527 					nVisibleWidth = nRealWidth;
1528 
1529 				nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1530 			}
1531 		}
1532 	}
1533 
1534 	// size ver scrollbar
1535 	long nThumb = aVerSBar.GetThumbPos();
1536 	Size aSize( nVerSBarWidth, nRealHeight );
1537 	aSize.Height() += 2;
1538 	if( aSize != aVerSBar.GetSizePixel() )
1539 		aVerSBar.SetSizePixel( aSize );
1540 	aVerSBar.SetVisibleSize( nVisibleHeight );
1541 	aVerSBar.SetPageSize( GetScrollBarPageSize( nVisibleHeight ));
1542 
1543 	if( nResult & 0x0001 )
1544 	{
1545 		aVerSBar.SetThumbPos( nThumb );
1546 		aVerSBar.Show();
1547 	}
1548 	else
1549 	{
1550 		aVerSBar.SetThumbPos( 0 );
1551 		aVerSBar.Hide();
1552 	}
1553 
1554 	// size hor scrollbar
1555 	nThumb = aHorSBar.GetThumbPos();
1556 	aSize.Width() = nRealWidth;
1557 	aSize.Height() = nHorSBarHeight;
1558 	aSize.Width()++;
1559 	if( nResult & 0x0001 ) // vertikale Scrollbar ?
1560 	{
1561 		aSize.Width()++;
1562 		nRealWidth++;
1563 	}
1564 	if( aSize != aHorSBar.GetSizePixel() )
1565 		aHorSBar.SetSizePixel( aSize );
1566 	aHorSBar.SetVisibleSize( nVisibleWidth );
1567 	aHorSBar.SetPageSize( GetScrollBarPageSize(nVisibleWidth ));
1568 	if( nResult & 0x0002 )
1569 	{
1570 		aHorSBar.SetThumbPos( nThumb );
1571 		aHorSBar.Show();
1572 	}
1573 	else
1574 	{
1575 		aHorSBar.SetThumbPos( 0 );
1576 		aHorSBar.Hide();
1577 	}
1578 
1579 	aOutputSize.Width() = nRealWidth;
1580 	if( nResult & 0x0002 ) // hor scrollbar ?
1581 		nRealHeight++; // weil unterer Rand geclippt wird
1582 	aOutputSize.Height() = nRealHeight;
1583 
1584 	Rectangle aNewOutRect( GetOutputRect() );
1585 	if( aNewOutRect != aOldOutRect && pView->HasBackground() )
1586 	{
1587 		Wallpaper aPaper( pView->GetBackground() );
1588 		aPaper.SetRect( aNewOutRect );
1589 		pView->SetBackground( aPaper );
1590 	}
1591 
1592 	if( (nResult & (0x0001|0x0002)) == (0x0001|0x0002) )
1593 		aScrBarBox.Show();
1594 	else
1595 		aScrBarBox.Hide();
1596 }
1597 
1598 void SvxIconChoiceCtrl_Impl::Resize()
1599 {
1600 	StopEditTimer();
1601 	InitScrollBarBox();
1602 	aOutputSize = pView->GetOutputSizePixel();
1603 	pImpCursor->Clear();
1604 	pGridMap->OutputSizeChanged();
1605 
1606 	const Size& rSize = pView->Control::GetOutputSizePixel();
1607 	PositionScrollBars( rSize.Width(), rSize.Height() );
1608 	// Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1609 	// Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1610 	// die ScrollBars aufblitzen
1611 	// Wenn schon ein Event unterwegs ist, dann braucht kein neues verschickt werden,
1612 	// zumindest, solange es nur einen EventTypen gibt
1613 	if ( ! nUserEventAdjustScrBars )
1614 		nUserEventAdjustScrBars =
1615 			Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
1616 				EVENTID_ADJUST_SCROLLBARS);
1617 
1618 	if( pView->HasBackground() && !pView->GetBackground().IsScrollable() )
1619 	{
1620 		Rectangle aRect( GetOutputRect());
1621 		Wallpaper aPaper( pView->GetBackground() );
1622 		aPaper.SetRect( aRect );
1623 		pView->SetBackground( aPaper );
1624 	}
1625 	VisRectChanged();
1626 }
1627 
1628 sal_Bool SvxIconChoiceCtrl_Impl::CheckHorScrollBar()
1629 {
1630 	if( !pZOrderList || !aHorSBar.IsVisible() )
1631 		return sal_False;
1632 	const MapMode& rMapMode = pView->GetMapMode();
1633 	Point aOrigin( rMapMode.GetOrigin() );
1634 	if(!( nWinBits & WB_HSCROLL) && !aOrigin.X() )
1635 	{
1636 		long nWidth = aOutputSize.Width();
1637 		const sal_uLong nCount = pZOrderList->Count();
1638 		long nMostRight = 0;
1639 		for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1640 		{
1641 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1642 			long nRight = GetEntryBoundRect(pEntry).Right();
1643 			if( nRight > nWidth )
1644 				return sal_False;
1645 			if( nRight > nMostRight )
1646 				nMostRight = nRight;
1647 		}
1648 		aHorSBar.Hide();
1649 		aOutputSize.Height() += nHorSBarHeight;
1650 		aVirtOutputSize.Width() = nMostRight;
1651 		aHorSBar.SetThumbPos( 0 );
1652 		Range aRange;
1653 		aRange.Max() = nMostRight - 1;
1654 		aHorSBar.SetRange( aRange  );
1655 		if( aVerSBar.IsVisible() )
1656 		{
1657 			Size aSize( aVerSBar.GetSizePixel());
1658 			aSize.Height() += nHorSBarHeight;
1659 			aVerSBar.SetSizePixel( aSize );
1660 		}
1661 		return sal_True;
1662 	}
1663 	return sal_False;
1664 }
1665 
1666 sal_Bool SvxIconChoiceCtrl_Impl::CheckVerScrollBar()
1667 {
1668 	if( !pZOrderList || !aVerSBar.IsVisible() )
1669 		return sal_False;
1670 	const MapMode& rMapMode = pView->GetMapMode();
1671 	Point aOrigin( rMapMode.GetOrigin() );
1672 	if(!( nWinBits & WB_VSCROLL) && !aOrigin.Y() )
1673 	{
1674 		long nDeepest = 0;
1675 		long nHeight = aOutputSize.Height();
1676 		const sal_uLong nCount = pZOrderList->Count();
1677 		for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
1678 		{
1679 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pZOrderList->GetObject(nCur);
1680 			long nBottom = GetEntryBoundRect(pEntry).Bottom();
1681 			if( nBottom > nHeight )
1682 				return sal_False;
1683 			if( nBottom > nDeepest )
1684 				nDeepest = nBottom;
1685 		}
1686 		aVerSBar.Hide();
1687 		aOutputSize.Width() += nVerSBarWidth;
1688 		aVirtOutputSize.Height() = nDeepest;
1689 		aVerSBar.SetThumbPos( 0 );
1690 		Range aRange;
1691 		aRange.Max() = nDeepest - 1;
1692 		aVerSBar.SetRange( aRange  );
1693 		if( aHorSBar.IsVisible() )
1694 		{
1695 			Size aSize( aHorSBar.GetSizePixel());
1696 			aSize.Width() += nVerSBarWidth;
1697 			aHorSBar.SetSizePixel( aSize );
1698 		}
1699 		return sal_True;
1700 	}
1701 	return sal_False;
1702 }
1703 
1704 
1705 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1706 void SvxIconChoiceCtrl_Impl::CheckScrollBars()
1707 {
1708 	CheckVerScrollBar();
1709 	if( CheckHorScrollBar() )
1710 		CheckVerScrollBar();
1711 	if( aVerSBar.IsVisible() && aHorSBar.IsVisible() )
1712 		aScrBarBox.Show();
1713 	else
1714 		aScrBarBox.Hide();
1715 }
1716 
1717 
1718 void SvxIconChoiceCtrl_Impl::GetFocus()
1719 {
1720 	RepaintEntries( ICNVIEW_FLAG_SELECTED );
1721 	if( pCursor )
1722 	{
1723 		pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
1724 		ShowCursor( sal_True );
1725 	}
1726 }
1727 
1728 void SvxIconChoiceCtrl_Impl::LoseFocus()
1729 {
1730 	StopEditTimer();
1731 	if( pCursor )
1732 		pCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
1733 	ShowCursor( sal_False );
1734 
1735 //	HideFocus ();
1736 //	pView->Invalidate ( aFocus.aRect );
1737 
1738 	RepaintEntries( ICNVIEW_FLAG_SELECTED );
1739 }
1740 
1741 void SvxIconChoiceCtrl_Impl::SetUpdateMode( sal_Bool bUpdate )
1742 {
1743 	if( bUpdate != bUpdateMode )
1744 	{
1745 		bUpdateMode = bUpdate;
1746 		if( bUpdate )
1747 		{
1748 			AdjustScrollBars();
1749 			pImpCursor->Clear();
1750 			pGridMap->Clear();
1751 			pView->Invalidate(INVALIDATE_NOCHILDREN);
1752 		}
1753 	}
1754 }
1755 
1756 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bIsBackgroundPainted )
1757 {
1758 	Point aPos( GetEntryPos( pEntry ) );
1759 	PaintEntry( pEntry, aPos, 0, bIsBackgroundPainted );
1760 }
1761 
1762 // Prios der Emphasis:  bDropTarget => bCursored => bSelected
1763 void SvxIconChoiceCtrl_Impl::PaintEmphasis(
1764 	const Rectangle& rTextRect, const Rectangle& rImageRect,
1765 	sal_Bool bSelected, sal_Bool bDropTarget, sal_Bool bCursored, OutputDevice* pOut,
1766 	sal_Bool bIsBackgroundPainted )
1767 {
1768 	static Color aTransparent( COL_TRANSPARENT );
1769 
1770 	if( !pOut )
1771 		pOut = pView;
1772 
1773 #ifdef OV_CHECK_EMPH_RECTS
1774 	{
1775 		Color aXOld( pOut->GetFillColor() );
1776 		pOut->SetFillColor( Color( COL_GREEN ));
1777 		pOut->DrawRect( rTextRect );
1778 		pOut->DrawRect( rImageRect );
1779 		pOut->SetFillColor( aXOld );
1780 	}
1781 #endif
1782 
1783 	const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1784 	Color aOldFillColor( pOut->GetFillColor() );
1785 
1786 	sal_Bool bSolidTextRect = sal_False;
1787 	sal_Bool bSolidImageRect = sal_False;
1788 
1789 	if( bDropTarget && ( eSelectionMode != NO_SELECTION ) )
1790 	{
1791 		pOut->SetFillColor( rSettings.GetHighlightColor() );
1792 		bSolidTextRect = sal_True;
1793 		bSolidImageRect = sal_True;
1794 	}
1795 	else
1796 	{
1797 		if ( !bSelected || bCursored )
1798 		{
1799 			if( !pView->HasFontFillColor() )
1800 				pOut->SetFillColor( pOut->GetBackground().GetColor() );
1801 			else
1802 			{
1803 				const Color& rFillColor = pView->GetFont().GetFillColor();
1804 				pOut->SetFillColor( rFillColor );
1805 				if( rFillColor != aTransparent )
1806 					bSolidTextRect = sal_True;
1807 			}
1808 		}
1809 	}
1810 
1811 	// Textrechteck zeichnen
1812 	if( !bSolidTextRect )
1813 	{
1814 		if( !bIsBackgroundPainted )
1815 			pOut->Erase( rTextRect );
1816 	}
1817 	else
1818 	{
1819 		Color aOldLineColor;
1820 		if( bCursored )
1821 		{
1822 			aOldLineColor = pOut->GetLineColor();
1823 			pOut->SetLineColor( Color( COL_GRAY ) );
1824 		}
1825 		pOut->DrawRect( rTextRect );
1826 		if( bCursored )
1827 			pOut->SetLineColor( aOldLineColor );
1828 	}
1829 
1830 	// Bildrechteck zeichnen
1831 	if( !bSolidImageRect )
1832 	{
1833 		if( !bIsBackgroundPainted )
1834 			pOut->Erase( rImageRect );
1835 	}
1836 // die Emphasis des Images muss von der abgeleiteten Klasse gezeichnet werden
1837 // (in der virtuellen Funktion DrawEntryImage)
1838 //	else
1839 //		pOut->DrawRect( rImageRect );
1840 
1841 	pOut->SetFillColor( aOldFillColor );
1842 }
1843 
1844 
1845 void SvxIconChoiceCtrl_Impl::PaintItem( const Rectangle& rRect,
1846 	IcnViewFieldType eItem, SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nPaintFlags,
1847 	OutputDevice* pOut, const String* pStr, ::vcl::ControlLayoutData* _pLayoutData )
1848 {
1849 	if( eItem == IcnViewFieldTypeText )
1850 	{
1851 		String aText;
1852 		if( !pStr )
1853 			aText = pView->GetEntryText( pEntry, sal_False );
1854 		else
1855 			aText = *pStr;
1856 
1857 		if ( _pLayoutData )
1858 		{
1859 			pOut->DrawText( rRect, aText, nCurTextDrawFlags,
1860 				&_pLayoutData->m_aUnicodeBoundRects, &_pLayoutData->m_aDisplayText );
1861 		}
1862 		else
1863 		{
1864 			Color aOldFontColor = pOut->GetTextColor();
1865 			if ( pView->AutoFontColor() )
1866 			{
1867 				Color aBkgColor( pOut->GetBackground().GetColor() );
1868 				Color aFontColor;
1869 				sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
1870 				if ( nColor > 127 )
1871 					aFontColor.SetColor ( COL_BLACK );
1872 				else
1873 					aFontColor.SetColor( COL_WHITE );
1874 				pOut->SetTextColor( aFontColor );
1875 			}
1876 
1877 			pOut->DrawText( rRect, aText, nCurTextDrawFlags );
1878 
1879 			if ( pView->AutoFontColor() )
1880 				pOut->SetTextColor( aOldFontColor );
1881 
1882 			if( pEntry->IsFocused() )
1883 			{
1884 				Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
1885 				/*pView->*/ShowFocus( aRect );
1886 				DrawFocusRect( pOut );
1887 			}
1888 		}
1889 	}
1890 	else
1891 	{
1892 		Point aPos( rRect.TopLeft() );
1893 		if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
1894 			aPos.X() += (rRect.GetWidth() - aImageSize.Width() ) / 2;
1895 		if( nPaintFlags & PAINTFLAG_VER_CENTERED )
1896 			aPos.Y() += (rRect.GetHeight() - aImageSize.Height() ) / 2;
1897 		pView->DrawEntryImage( pEntry, aPos, *pOut );
1898 	}
1899 }
1900 
1901 void SvxIconChoiceCtrl_Impl::PaintEntryVirtOutDev( SvxIconChoiceCtrlEntry* pEntry )
1902 {
1903 #ifdef OV_NO_VIRT_OUTDEV
1904 	PaintEntry( pEntry );
1905 #else
1906 	if( !pEntryPaintDev )
1907 	{
1908 		pEntryPaintDev = new VirtualDevice( *pView );
1909 		pEntryPaintDev->SetFont( pView->GetFont() );
1910 		pEntryPaintDev->SetLineColor();
1911 		//pEntryPaintDev->SetBackground( pView->GetBackground() );
1912 	}
1913 	const Rectangle& rRect = GetEntryBoundRect( pEntry );
1914 	Rectangle aOutRect( GetOutputRect() );
1915 	if( !rRect.IsOver( aOutRect ) )
1916 		return;
1917 	Wallpaper aPaper( pView->GetBackground() );
1918 	Rectangle aRect( aPaper.GetRect() );
1919 
1920 	// Rechteck verschieben, so dass das Boundrect des Entries im
1921 	// VirtOut-Dev bei 0,0 liegt.
1922 	aRect.Move( -rRect.Left(), -rRect.Top() );
1923 	aPaper.SetRect( aRect );
1924 	pEntryPaintDev->SetBackground( aPaper );
1925 	pEntryPaintDev->SetFont( pView->GetFont() );
1926 	Rectangle aPix ( pEntryPaintDev->LogicToPixel(aRect) );
1927 
1928 
1929 	Size aSize( rRect.GetSize() );
1930 	pEntryPaintDev->SetOutputSizePixel( aSize );
1931 	pEntryPaintDev->DrawOutDev(
1932 		Point(), aSize, rRect.TopLeft(), aSize, *pView );
1933 
1934 	PaintEntry( pEntry, Point(), pEntryPaintDev );
1935 
1936 	pView->DrawOutDev(
1937 		rRect.TopLeft(),
1938 		aSize,
1939 		Point(),
1940 		aSize,
1941 		*pEntryPaintDev );
1942 #endif
1943 }
1944 
1945 
1946 void SvxIconChoiceCtrl_Impl::PaintEntry( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
1947 	OutputDevice* pOut, sal_Bool bIsBackgroundPainted )
1948 {
1949 	if( !pOut )
1950 		pOut = pView;
1951 
1952 	sal_Bool bSelected = sal_False;
1953 
1954 	if( eSelectionMode != NO_SELECTION )
1955 		bSelected = pEntry->IsSelected();
1956 
1957 	sal_Bool bCursored = pEntry->IsCursored();
1958 	sal_Bool bDropTarget = pEntry->IsDropTarget();
1959 	sal_Bool bNoEmphasis = pEntry->IsBlockingEmphasis();
1960 
1961 	Font aTempFont( pOut->GetFont() );
1962 
1963 	// AutoFontColor
1964 	/*
1965 	if ( pView->AutoFontColor() )
1966 	{
1967 		aTempFont.SetColor ( aFontColor );
1968 	}
1969 	*/
1970 
1971 	String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
1972 	Rectangle aTextRect( CalcTextRect(pEntry,&rPos,sal_False,&aEntryText));
1973 	Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos ) );
1974 
1975 	sal_Bool	bShowSelection =
1976 		(	(	( bSelected && !bCursored )
1977 			||	bDropTarget
1978 			)
1979 		&&	!bNoEmphasis
1980 		&&	( eSelectionMode != NO_SELECTION )
1981 		);
1982 	sal_Bool bActiveSelection = ( 0 != ( nWinBits & WB_NOHIDESELECTION ) ) || pView->HasFocus();
1983 
1984 	if ( bShowSelection )
1985 	{
1986 		const StyleSettings& rSettings = pOut->GetSettings().GetStyleSettings();
1987 		Font aNewFont( aTempFont );
1988 
1989 		// bei hart attributierter Font-Fuellcolor muessen wir diese
1990 		// hart auf die Highlight-Color setzen
1991 		if( pView->HasFontFillColor() )
1992 		{
1993 			if( (nWinBits & WB_NOHIDESELECTION) || pView->HasFocus() )
1994 				aNewFont.SetFillColor( rSettings.GetHighlightColor() );
1995 			else
1996 				aNewFont.SetFillColor( rSettings.GetDeactiveColor() );
1997 		}
1998 
1999 		Color aWinCol = rSettings.GetWindowTextColor();
2000 		if ( !bActiveSelection && rSettings.GetFaceColor().IsBright() == aWinCol.IsBright() )
2001 			aNewFont.SetColor( rSettings.GetWindowTextColor() );
2002 		else
2003 			aNewFont.SetColor( rSettings.GetHighlightTextColor() );
2004 
2005 		pOut->SetFont( aNewFont );
2006 
2007 		pOut->SetFillColor( pOut->GetBackground().GetColor() );
2008 		pOut->DrawRect( CalcFocusRect( pEntry ) );
2009 		pOut->SetFillColor( );
2010 	}
2011 
2012 	sal_Bool bResetClipRegion = sal_False;
2013 	if( !pView->IsClipRegion() && (aVerSBar.IsVisible() || aHorSBar.IsVisible()) )
2014 	{
2015 		Rectangle aOutputArea( GetOutputRect() );
2016 		if( aOutputArea.IsOver(aTextRect) || aOutputArea.IsOver(aBmpRect) )
2017 		{
2018 			pView->SetClipRegion( aOutputArea );
2019 			bResetClipRegion = sal_True;
2020 		}
2021 	}
2022 
2023 #ifdef OV_DRAWBOUNDRECT
2024 	{
2025 		Color aXOldColor = pOut->GetLineColor();
2026 		pOut->SetLineColor( Color( COL_LIGHTRED ) );
2027 		Rectangle aXRect( pEntry->aRect );
2028 		aXRect.SetPos( rPos );
2029 		pOut->DrawRect( aXRect );
2030 		pOut->SetLineColor( aXOldColor );
2031 	}
2032 #endif
2033 
2034 	sal_Bool bLargeIconMode = WB_ICON == ( nWinBits & (VIEWMODE_MASK) );
2035 	sal_uInt16 nBmpPaintFlags = PAINTFLAG_VER_CENTERED;
2036 	if ( bLargeIconMode )
2037 		nBmpPaintFlags |= PAINTFLAG_HOR_CENTERED;
2038 	sal_uInt16 nTextPaintFlags = bLargeIconMode ? PAINTFLAG_HOR_CENTERED : PAINTFLAG_VER_CENTERED;
2039 
2040 	if( !bNoEmphasis )
2041 		PaintEmphasis(aTextRect,aBmpRect,bSelected,bDropTarget,bCursored,pOut,bIsBackgroundPainted);
2042 
2043 	if ( bShowSelection )
2044 		pView->DrawSelectionBackground( CalcFocusRect( pEntry ),
2045 		bActiveSelection ? 1 : 2 /* highlight */, sal_False /* check */, sal_True /* border */, sal_False /* ext border only */ );
2046 
2047 	PaintItem( aBmpRect, IcnViewFieldTypeImage, pEntry, nBmpPaintFlags, pOut );
2048 
2049 	PaintItem( aTextRect, IcnViewFieldTypeText, pEntry,
2050 		nTextPaintFlags, pOut );
2051 
2052 	// Highlight-Frame zeichnen
2053 	if( pEntry == pCurHighlightFrame && !bNoEmphasis )
2054 		DrawHighlightFrame( pOut, CalcFocusRect( pEntry ), sal_False );
2055 
2056 	pOut->SetFont( aTempFont );
2057 	if( bResetClipRegion )
2058 		pView->SetClipRegion();
2059 }
2060 
2061 void SvxIconChoiceCtrl_Impl::SetEntryPos( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2062 	sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars, sal_Bool bKeepGridMap )
2063 {
2064 	ShowCursor( sal_False );
2065 	Rectangle aBoundRect( GetEntryBoundRect( pEntry ));
2066 	pView->Invalidate( aBoundRect );
2067 	ToTop( pEntry );
2068 	if( !IsAutoArrange() )
2069 	{
2070 		sal_Bool bAdjustVirtSize = sal_False;
2071 		if( rPos != aBoundRect.TopLeft() )
2072 		{
2073 			Point aGridOffs(
2074 				pEntry->aGridRect.TopLeft() - pEntry->aRect.TopLeft() );
2075 			pImpCursor->Clear();
2076 			if( !bKeepGridMap )
2077 				pGridMap->Clear();
2078 			aBoundRect.SetPos( rPos );
2079 			pEntry->aRect = aBoundRect;
2080 			pEntry->aGridRect.SetPos( rPos + aGridOffs );
2081 			bAdjustVirtSize = sal_True;
2082 		}
2083 		if( bAdjustAtGrid )
2084 		{
2085 			if( bAdjustVirtSize )
2086 			{
2087 				// Durch das Ausrichten des (ggf. gerade neu positionierten) Eintrags,
2088 				// kann er wieder komplett
2089 				// in den sichtbaren Bereich rutschen, so dass u.U. doch keine Scrollbar
2090 				// eingeblendet werden muss. Um deshalb ein 'Aufblitzen' der
2091 				// Scrollbar(s) zu vermeiden, wird zum Aufplustern der virtuellen
2092 				// Ausgabegroesse bereits das ausgerichtete Boundrect des
2093 				// Eintrags genommen. Die virtuelle Groesse muss angepasst werden,
2094 				// da AdjustEntryAtGrid von ihr abhaengt.
2095 				const Rectangle& rBoundRect = GetEntryBoundRect( pEntry );
2096 				Rectangle aCenterRect( CalcBmpRect( pEntry, 0 ));
2097 				Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
2098 				Rectangle aNewBoundRect( aNewPos, pEntry->aRect.GetSize());
2099 				AdjustVirtSize( aNewBoundRect );
2100 				bAdjustVirtSize = sal_False;
2101 			}
2102 			AdjustEntryAtGrid( pEntry );
2103 			ToTop( pEntry );
2104 		}
2105 		if( bAdjustVirtSize )
2106 			AdjustVirtSize( pEntry->aRect );
2107 
2108 		if( bCheckScrollBars && bUpdateMode )
2109 			CheckScrollBars();
2110 
2111 		pView->Invalidate( pEntry->aRect );
2112 		pGridMap->OccupyGrids( pEntry );
2113 	}
2114 	else
2115 	{
2116 		SvxIconChoiceCtrlEntry*	pPrev = FindEntryPredecessor( pEntry, rPos );
2117 		SetEntryPredecessor( pEntry, pPrev );
2118 		aAutoArrangeTimer.Start();
2119 	}
2120 	ShowCursor( sal_True );
2121 }
2122 
2123 void SvxIconChoiceCtrl_Impl::SetNoSelection()
2124 {
2125 	// rekursive Aufrufe ueber SelectEntry abblocken
2126 	if( !(nFlags & F_CLEARING_SELECTION ))
2127 	{
2128 		nFlags |= F_CLEARING_SELECTION;
2129 		DeselectAllBut( 0, sal_True );
2130 		nFlags &= ~F_CLEARING_SELECTION;
2131 	}
2132 }
2133 
2134 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetEntry( const Point& rDocPos, sal_Bool bHit )
2135 {
2136 	CheckBoundingRects();
2137 	// Z-Order-Liste vom Ende her absuchen
2138 	sal_uLong nCount = pZOrderList->Count();
2139 	while( nCount )
2140 	{
2141 		nCount--;
2142 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCount));
2143 		if( pEntry->aRect.IsInside( rDocPos ) )
2144 		{
2145 			if( bHit )
2146 			{
2147 				Rectangle aRect = CalcBmpRect( pEntry );
2148 				aRect.Top() -= 3;
2149 				aRect.Bottom() += 3;
2150 				aRect.Left() -= 3;
2151 				aRect.Right() += 3;
2152 				if( aRect.IsInside( rDocPos ) )
2153 					return pEntry;
2154 				aRect = CalcTextRect( pEntry );
2155 				if( aRect.IsInside( rDocPos ) )
2156 					return pEntry;
2157 			}
2158 			else
2159 				return pEntry;
2160 		}
2161 	}
2162 	return 0;
2163 }
2164 
2165 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2166 {
2167 	CheckBoundingRects();
2168 	SvxIconChoiceCtrlEntry* pTarget = 0;
2169 	const sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2170 	if( nStartPos != LIST_ENTRY_NOTFOUND )
2171 	{
2172 		const sal_uLong nCount = pZOrderList->Count();
2173 		for( sal_uLong nCur = nStartPos+1; nCur < nCount; nCur++ )
2174 		{
2175 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nCur));
2176 			if( pEntry->aRect.IsInside( rDocPos ) )
2177 			{
2178 				pTarget = pEntry;
2179 				break;
2180 			}
2181 		}
2182 	}
2183 	return pTarget;
2184 }
2185 
2186 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetPrevEntry( const Point& rDocPos, SvxIconChoiceCtrlEntry* pCurEntry )
2187 {
2188 	CheckBoundingRects();
2189 	SvxIconChoiceCtrlEntry* pTarget = 0;
2190 	sal_uLong nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2191 	if( nStartPos != LIST_ENTRY_NOTFOUND && nStartPos != 0 )
2192 	{
2193 		nStartPos--;
2194 		do
2195 		{
2196 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nStartPos));
2197 			if( pEntry->aRect.IsInside( rDocPos ) )
2198 			{
2199 				pTarget = pEntry;
2200 				break;
2201 			}
2202 		} while( nStartPos > 0 );
2203 	}
2204 	return pTarget;
2205 }
2206 
2207 Point SvxIconChoiceCtrl_Impl::GetEntryPos( SvxIconChoiceCtrlEntry* pEntry )
2208 {
2209 	return pEntry->aRect.TopLeft();
2210 }
2211 
2212 void SvxIconChoiceCtrl_Impl::MakeEntryVisible( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bBound )
2213 {
2214 	if ( bBound )
2215 	{
2216 		const Rectangle& rRect = GetEntryBoundRect( pEntry );
2217 		MakeVisible( rRect );
2218 	}
2219 	else
2220 	{
2221 		Rectangle aRect = CalcBmpRect( pEntry );
2222 		aRect.Union( CalcTextRect( pEntry ) );
2223 		aRect.Top() += TBOFFS_BOUND;
2224 		aRect.Bottom() += TBOFFS_BOUND;
2225 		aRect.Left() += LROFFS_BOUND;
2226 		aRect.Right() += LROFFS_BOUND;
2227 		MakeVisible( aRect );
2228 	}
2229 }
2230 
2231 const Rectangle& SvxIconChoiceCtrl_Impl::GetEntryBoundRect( SvxIconChoiceCtrlEntry* pEntry )
2232 {
2233 	if( !IsBoundingRectValid( pEntry->aRect ))
2234 		FindBoundingRect( pEntry );
2235 	return pEntry->aRect;
2236 }
2237 
2238 Rectangle SvxIconChoiceCtrl_Impl::CalcBmpRect( SvxIconChoiceCtrlEntry* pEntry, const Point* pPos )
2239 {
2240 	Rectangle aBound = GetEntryBoundRect( pEntry );
2241 	if( pPos )
2242 		aBound.SetPos( *pPos );
2243 	Point aPos( aBound.TopLeft() );
2244 
2245 	switch( nWinBits & (VIEWMODE_MASK) )
2246 	{
2247 		case WB_ICON:
2248 		{
2249 			aPos.X() += ( aBound.GetWidth() - aImageSize.Width() ) / 2;
2250 			return Rectangle( aPos, aImageSize );
2251 		}
2252 
2253 		case WB_SMALLICON:
2254 		case WB_DETAILS:
2255 			aPos.Y() += ( aBound.GetHeight() - aImageSize.Height() ) / 2;
2256 			//todo: hor. Abstand zum BoundRect?
2257 			return Rectangle( aPos, aImageSize );
2258 
2259 		default:
2260 			DBG_ERROR("IconView: Viewmode not set");
2261 			return aBound;
2262 	}
2263 }
2264 
2265 Rectangle SvxIconChoiceCtrl_Impl::CalcTextRect( SvxIconChoiceCtrlEntry* pEntry,
2266 	const Point* pEntryPos, sal_Bool bEdit, const String* pStr )
2267 {
2268 	String aEntryText;
2269 	if( !pStr )
2270 		aEntryText = pView->GetEntryText( pEntry, bEdit );
2271 	else
2272 		aEntryText = *pStr;
2273 
2274 	const Rectangle aMaxTextRect( CalcMaxTextRect( pEntry ) );
2275 	Rectangle aBound( GetEntryBoundRect( pEntry ) );
2276 	if( pEntryPos )
2277 		aBound.SetPos( *pEntryPos );
2278 
2279 	Rectangle aTextRect( aMaxTextRect );
2280 	if( !bEdit )
2281 		aTextRect = pView->GetTextRect( aTextRect, aEntryText, nCurTextDrawFlags );
2282 
2283 	Size aTextSize( aTextRect.GetSize() );
2284 
2285 	Point aPos( aBound.TopLeft() );
2286 	long nBoundWidth = aBound.GetWidth();
2287 	long nBoundHeight = aBound.GetHeight();
2288 
2289 	switch( nWinBits & (VIEWMODE_MASK) )
2290 	{
2291 		case WB_ICON:
2292 			aPos.Y() += aImageSize.Height();
2293 			aPos.Y() += VER_DIST_BMP_STRING;
2294 			// beim Editieren etwas mehr Platz
2295 			if( bEdit )
2296 			{
2297 				// 20% rauf
2298 				long nMinWidth = (( (aImageSize.Width()*10) / 100 ) * 2 ) +
2299 								 aImageSize.Width();
2300 				if( nMinWidth > nBoundWidth )
2301 					nMinWidth = nBoundWidth;
2302 
2303 				if( aTextSize.Width() < nMinWidth )
2304 					aTextSize.Width() = nMinWidth;
2305 
2306 				// beim Editieren ist Ueberlappung nach unten erlaubt
2307 				Size aOptSize = aMaxTextRect.GetSize();
2308 				if( aOptSize.Height() > aTextSize.Height() )
2309 					aTextSize.Height() = aOptSize.Height();
2310 			}
2311 			aPos.X() += (nBoundWidth - aTextSize.Width()) / 2;
2312 			break;
2313 
2314 		case WB_SMALLICON:
2315 		case WB_DETAILS:
2316 			aPos.X() += aImageSize.Width();
2317 			aPos.X() += HOR_DIST_BMP_STRING;
2318 			aPos.Y() += (nBoundHeight - aTextSize.Height()) / 2;
2319 			break;
2320 	}
2321 	return Rectangle( aPos, aTextSize );
2322 }
2323 
2324 
2325 long SvxIconChoiceCtrl_Impl::CalcBoundingWidth( SvxIconChoiceCtrlEntry* pEntry ) const
2326 {
2327 	long nStringWidth = GetItemSize( pEntry, IcnViewFieldTypeText ).Width();
2328 //	nStringWidth += 2*LROFFS_TEXT;
2329 	long nWidth = 0;
2330 
2331 	switch( nWinBits & (VIEWMODE_MASK) )
2332 	{
2333 		case WB_ICON:
2334 			nWidth = Max( nStringWidth, aImageSize.Width() );
2335 			break;
2336 
2337 		case WB_SMALLICON:
2338 		case WB_DETAILS:
2339 			nWidth = aImageSize.Width();
2340 			nWidth += HOR_DIST_BMP_STRING;
2341 			nWidth += nStringWidth;
2342 			break;
2343 	}
2344 	return nWidth;
2345 }
2346 
2347 long SvxIconChoiceCtrl_Impl::CalcBoundingHeight( SvxIconChoiceCtrlEntry* pEntry ) const
2348 {
2349 	long nStringHeight = GetItemSize( pEntry, IcnViewFieldTypeText).Height();
2350 	long nHeight = 0;
2351 
2352 	switch( nWinBits & (VIEWMODE_MASK) )
2353 	{
2354 		case WB_ICON:
2355 			nHeight = aImageSize.Height();
2356 			nHeight += VER_DIST_BMP_STRING;
2357 			nHeight += nStringHeight;
2358 			break;
2359 
2360 		case WB_SMALLICON:
2361 		case WB_DETAILS:
2362 			nHeight = Max( aImageSize.Height(), nStringHeight );
2363 			break;
2364 	}
2365 	if( nHeight > nMaxBoundHeight )
2366 	{
2367 		((SvxIconChoiceCtrl_Impl*)this)->nMaxBoundHeight = nHeight;
2368 		((SvxIconChoiceCtrl_Impl*)this)->aHorSBar.SetLineSize( GetScrollBarLineSize() );
2369 		((SvxIconChoiceCtrl_Impl*)this)->aVerSBar.SetLineSize( GetScrollBarLineSize() );
2370 	}
2371 	return nHeight;
2372 }
2373 
2374 Size SvxIconChoiceCtrl_Impl::CalcBoundingSize( SvxIconChoiceCtrlEntry* pEntry ) const
2375 {
2376 	return Size( CalcBoundingWidth( pEntry ),
2377 				 CalcBoundingHeight( pEntry ) );
2378 }
2379 
2380 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRects()
2381 {
2382 	nMaxBoundHeight	= 0;
2383 	pZOrderList->Clear();
2384 	sal_uLong nCount = aEntries.Count();
2385 	sal_uLong nCur;
2386 	SvxIconChoiceCtrlEntry* pEntry;
2387 
2388 	if( !IsAutoArrange() || !pHead )
2389 	{
2390 		for( nCur = 0; nCur < nCount; nCur++ )
2391 		{
2392 			pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2393 			FindBoundingRect( pEntry );
2394 			pZOrderList->Insert( pEntry, LIST_APPEND );
2395 		}
2396 	}
2397 	else
2398 	{
2399 		nCur = 0;
2400 		pEntry = pHead;
2401 		while( nCur != nCount )
2402 		{
2403 			DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2404 			FindBoundingRect( pEntry );
2405 			pZOrderList->Insert( pEntry, pZOrderList->Count() );
2406 			pEntry = pEntry->pflink;
2407 			nCur++;
2408 		}
2409 	}
2410 	bBoundRectsDirty = sal_False;
2411 	AdjustScrollBars();
2412 }
2413 
2414 void SvxIconChoiceCtrl_Impl::RecalcAllBoundingRectsSmart()
2415 {
2416 	nMaxBoundHeight	= 0;
2417 	pZOrderList->Clear();
2418 	sal_uLong nCur;
2419 	SvxIconChoiceCtrlEntry* pEntry;
2420 	const sal_uLong nCount = aEntries.Count();
2421 
2422 	if( !IsAutoArrange() || !pHead )
2423 	{
2424 		for( nCur = 0; nCur < nCount; nCur++ )
2425 		{
2426 			pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2427 			if( IsBoundingRectValid( pEntry->aRect ))
2428 			{
2429 				Size aBoundSize( pEntry->aRect.GetSize() );
2430 				if( aBoundSize.Height() > nMaxBoundHeight )
2431 					nMaxBoundHeight = aBoundSize.Height();
2432 			}
2433 			else
2434 				FindBoundingRect( pEntry );
2435 			pZOrderList->Insert( pEntry, LIST_APPEND );
2436 		}
2437 	}
2438 	else
2439 	{
2440 		nCur = 0;
2441 		pEntry = pHead;
2442 		while( nCur != nCount )
2443 		{
2444 			DBG_ASSERT(pEntry->pflink&&pEntry->pblink,"SvxIconChoiceCtrl_Impl::RecalcAllBoundingRect > Bad link(s)");
2445 			if( IsBoundingRectValid( pEntry->aRect ))
2446 			{
2447 				Size aBoundSize( pEntry->aRect.GetSize() );
2448 				if( aBoundSize.Height() > nMaxBoundHeight )
2449 					nMaxBoundHeight = aBoundSize.Height();
2450 			}
2451 			else
2452 				FindBoundingRect( pEntry );
2453 			pZOrderList->Insert( pEntry, LIST_APPEND );
2454 			pEntry = pEntry->pflink;
2455 			nCur++;
2456 		}
2457 	}
2458 	AdjustScrollBars();
2459 }
2460 
2461 void SvxIconChoiceCtrl_Impl::UpdateBoundingRects()
2462 {
2463 	const sal_uLong nCount = aEntries.Count();
2464 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2465 	{
2466 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2467 		GetEntryBoundRect( pEntry );
2468 	}
2469 }
2470 
2471 void SvxIconChoiceCtrl_Impl::FindBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2472 {
2473 	DBG_ASSERT(!pEntry->IsPosLocked(),"Locked entry pos in FindBoundingRect");
2474 	if( pEntry->IsPosLocked() && IsBoundingRectValid( pEntry->aRect) )
2475 	{
2476 		AdjustVirtSize( pEntry->aRect );
2477 		return;
2478 	}
2479 	Size aSize( CalcBoundingSize( pEntry ) );
2480 	Point aPos(pGridMap->GetGridRect(pGridMap->GetUnoccupiedGrid(sal_True)).TopLeft());
2481 	SetBoundingRect_Impl( pEntry, aPos, aSize );
2482 }
2483 
2484 void SvxIconChoiceCtrl_Impl::SetBoundingRect_Impl( SvxIconChoiceCtrlEntry* pEntry, const Point& rPos,
2485 	const Size& /*rBoundingSize*/ )
2486 {
2487 	Rectangle aGridRect( rPos, Size(nGridDX, nGridDY) );
2488 	pEntry->aGridRect = aGridRect;
2489 	Center( pEntry );
2490 	AdjustVirtSize( pEntry->aRect );
2491 	pGridMap->OccupyGrids( pEntry );
2492 }
2493 
2494 
2495 void SvxIconChoiceCtrl_Impl::SetCursor( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bSyncSingleSelection,
2496 	sal_Bool bShowFocusAsync )
2497 {
2498 	if( pEntry == pCursor )
2499 	{
2500 		if( pCursor && eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection &&
2501 				!pCursor->IsSelected() )
2502 			SelectEntry( pCursor, sal_True, sal_True );
2503 		return;
2504 	}
2505 	ShowCursor( sal_False );
2506 	SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
2507 	pCursor = pEntry;
2508 	if( pOldCursor )
2509 	{
2510 		pOldCursor->ClearFlags( ICNVIEW_FLAG_FOCUSED );
2511 		if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2512 			SelectEntry( pOldCursor, sal_False, sal_True ); // alten Cursor deselektieren
2513 	}
2514 	if( pCursor )
2515 	{
2516 		ToTop( pCursor );
2517 		pCursor->SetFlags( ICNVIEW_FLAG_FOCUSED );
2518 		if( eSelectionMode == SINGLE_SELECTION && bSyncSingleSelection )
2519 			SelectEntry( pCursor, sal_True, sal_True );
2520 		if( !bShowFocusAsync )
2521 			ShowCursor( sal_True );
2522 		else
2523 		{
2524 			if( !nUserEventShowCursor )
2525 				nUserEventShowCursor =
2526 					Application::PostUserEvent( LINK( this, SvxIconChoiceCtrl_Impl, UserEventHdl),
2527 						EVENTID_SHOW_CURSOR );
2528 		}
2529 	}
2530 }
2531 
2532 
2533 void SvxIconChoiceCtrl_Impl::ShowCursor( sal_Bool bShow )
2534 {
2535 	if( !pCursor || !bShow || !pView->HasFocus() )
2536 	{
2537 		pView->HideFocus();
2538 		return;
2539 	}
2540 	Rectangle aRect ( CalcFocusRect( pCursor ) );
2541 	/*pView->*/ShowFocus( aRect );
2542 }
2543 
2544 
2545 void SvxIconChoiceCtrl_Impl::HideDDIcon()
2546 {
2547 	pView->Update();
2548 	ImpHideDDIcon();
2549 	pDDBufDev = pDDDev;
2550 	pDDDev = 0;
2551 }
2552 
2553 void SvxIconChoiceCtrl_Impl::ImpHideDDIcon()
2554 {
2555 	if( pDDDev )
2556 	{
2557 		Size aSize( pDDDev->GetOutputSizePixel() );
2558 		// pView restaurieren
2559 		pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2560 	}
2561 }
2562 
2563 
2564 void SvxIconChoiceCtrl_Impl::ShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2565 {
2566 	pView->Update();
2567 	if( pRefEntry != pDDRefEntry )
2568 	{
2569 		DELETEZ(pDDDev);
2570 		DELETEZ(pDDBufDev);
2571 	}
2572 	sal_Bool bSelected = pRefEntry->IsSelected();
2573 	pRefEntry->ClearFlags( ICNVIEW_FLAG_SELECTED );
2574 	if( !pDDDev )
2575 	{
2576 		if( pDDBufDev )
2577 		{
2578 			// nicht bei jedem Move ein Device anlegen, da dies besonders
2579 			// auf Remote-Clients zu langsam ist
2580 			pDDDev = pDDBufDev;
2581 			pDDBufDev = 0;
2582 		}
2583 		else
2584 		{
2585 			pDDDev = new VirtualDevice( *pView );
2586 			pDDDev->SetFont( pView->GetFont() );
2587 		}
2588 	}
2589 	else
2590 	{
2591 		ImpHideDDIcon();
2592 	}
2593 	const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2594 	pDDDev->SetOutputSizePixel( rRect.GetSize() );
2595 
2596 	Point aPos( rPosPix );
2597 	ToDocPos( aPos );
2598 
2599 	Size aSize( pDDDev->GetOutputSizePixel() );
2600 	pDDRefEntry = pRefEntry;
2601 	aDDLastEntryPos = aPos;
2602 	aDDLastRectPos = aPos;
2603 
2604 	// Hintergrund sichern
2605 	pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2606 	// Icon in pView malen
2607 	pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2608 	PaintEntry( pRefEntry, aPos );
2609 	pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2610 	if( bSelected )
2611 		pRefEntry->SetFlags( ICNVIEW_FLAG_SELECTED );
2612 }
2613 
2614 void SvxIconChoiceCtrl_Impl::HideShowDDIcon( SvxIconChoiceCtrlEntry* pRefEntry, const Point& rPosPix )
2615 {
2616 /*  In Notfaellen folgenden flackernden Code aktivieren:
2617 
2618 		HideDDIcon();
2619 		ShowDDIcon( pRefEntry, rPosPix );
2620 		return;
2621 */
2622 	if( !pDDDev )
2623 	{
2624 		ShowDDIcon( pRefEntry, rPosPix );
2625 		return;
2626 	}
2627 
2628 	if( pRefEntry != pDDRefEntry )
2629 	{
2630 		HideDDIcon();
2631 		ShowDDIcon( pRefEntry, rPosPix );
2632 		return;
2633 	}
2634 
2635 	Point aEmptyPoint;
2636 
2637 	Point aCurEntryPos( rPosPix );
2638 	ToDocPos( aCurEntryPos );
2639 
2640 	const Rectangle& rRect = GetEntryBoundRect( pRefEntry );
2641 	Size aEntrySize( rRect.GetSize() );
2642 	Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2643 	Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2644 
2645 	if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2646 	{
2647 		HideDDIcon();
2648 		ShowDDIcon( pRefEntry, rPosPix );
2649 		return;
2650 	}
2651 
2652 	// Ueberlappung des neuen und alten D&D-Pointers!
2653 
2654 	Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2655 	if( !pDDTempDev )
2656 	{
2657 		pDDTempDev = new VirtualDevice( *pView );
2658 		pDDTempDev->SetFont( pView->GetFont() );
2659 	}
2660 
2661 	Size aFullSize( aFullRect.GetSize() );
2662 	Point aFullPos( aFullRect.TopLeft() );
2663 
2664 	pDDTempDev->SetOutputSizePixel( aFullSize );
2665 
2666 	// Hintergrund (mit dem alten D&D-Pointer!) sichern
2667 	pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2668 	// den alten Buffer in den neuen Buffer pasten
2669 	aDDLastRectPos = aDDLastRectPos - aFullPos;
2670 
2671 	pDDTempDev->DrawOutDev(
2672 		aDDLastRectPos,
2673 		pDDDev->GetOutputSizePixel(),
2674 		aEmptyPoint,
2675 		pDDDev->GetOutputSizePixel(),
2676 		*pDDDev );
2677 
2678 	// Swap
2679 	VirtualDevice* pTemp = pDDDev;
2680 	pDDDev = pDDTempDev;
2681 	pDDTempDev = pTemp;
2682 
2683 	// in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2684 	pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2685 	pDDTempDev->DrawOutDev(
2686 		aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2687 	Point aRelPos = aCurEntryPos - aFullPos;
2688 	pRefEntry->SetFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2689 	PaintEntry( pRefEntry, aRelPos, pDDTempDev );
2690 	pRefEntry->ClearFlags( ICNVIEW_FLAG_BLOCK_EMPHASIS );
2691 
2692 	aDDLastRectPos = aFullPos;
2693 	aDDLastEntryPos = aCurEntryPos;
2694 
2695 	pView->DrawOutDev(
2696 		aDDLastRectPos,
2697 		pDDDev->GetOutputSizePixel(),
2698 		aEmptyPoint,
2699 		pDDDev->GetOutputSizePixel(),
2700 		*pDDTempDev );
2701 }
2702 
2703 void SvxIconChoiceCtrl_Impl::InvalidateBoundingRect( SvxIconChoiceCtrlEntry* pEntry )
2704 {
2705 	InvalidateBoundingRect( pEntry->aRect );
2706 }
2707 
2708 
2709 sal_Bool SvxIconChoiceCtrl_Impl::HandleScrollCommand( const CommandEvent& rCmd )
2710 {
2711 	Rectangle aDocRect(	GetDocumentRect() );
2712 	Rectangle aVisRect( GetVisibleRect() );
2713 	if( aVisRect.IsInside( aDocRect ))
2714 		return sal_False;
2715 	Size aDocSize( aDocRect.GetSize() );
2716 	Size aVisSize( aVisRect.GetSize() );
2717 	sal_Bool bHor = aDocSize.Width() > aVisSize.Width();
2718 	sal_Bool bVer = aDocSize.Height() > aVisSize.Height();
2719 
2720 	long nScrollDX = 0, nScrollDY = 0;
2721 
2722 	switch( rCmd.GetCommand() )
2723 	{
2724 		case COMMAND_STARTAUTOSCROLL:
2725 		{
2726 			pView->EndTracking();
2727 			sal_uInt16 nScrollFlags = 0;
2728 			if( bHor )
2729 				nScrollFlags |= AUTOSCROLL_HORZ;
2730 			if( bVer )
2731 				nScrollFlags |= AUTOSCROLL_VERT;
2732 			if( nScrollFlags )
2733 			{
2734 				pView->StartAutoScroll( nScrollFlags );
2735 				return sal_True;
2736 			}
2737 		}
2738 		break;
2739 
2740 		case COMMAND_WHEEL:
2741 		{
2742 			const CommandWheelData* pData = rCmd.GetWheelData();
2743 			if( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
2744 			{
2745 				sal_uLong nScrollLines = pData->GetScrollLines();
2746 				if( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
2747 				{
2748 					nScrollDY = GetScrollBarPageSize( aVisSize.Width() );
2749 					if( pData->GetDelta() < 0 )
2750 						nScrollDY *= -1;
2751 				}
2752 				else
2753 				{
2754 					nScrollDY = pData->GetNotchDelta() * (long)nScrollLines;
2755 					nScrollDY *= GetScrollBarLineSize();
2756 				}
2757 			}
2758 		}
2759 		break;
2760 
2761 		case COMMAND_AUTOSCROLL:
2762 		{
2763 			const CommandScrollData* pData = rCmd.GetAutoScrollData();
2764 			if( pData )
2765 			{
2766 				nScrollDX = pData->GetDeltaX() * GetScrollBarLineSize();
2767 				nScrollDY = pData->GetDeltaY() * GetScrollBarLineSize();
2768 			}
2769 		}
2770 		break;
2771 	}
2772 
2773 	if( nScrollDX || nScrollDY )
2774 	{
2775 		aVisRect.Top() -= nScrollDY;
2776 		aVisRect.Bottom() -= nScrollDY;
2777 		aVisRect.Left() -= nScrollDX;
2778 		aVisRect.Right() -= nScrollDX;
2779 		MakeVisible( aVisRect );
2780 		return sal_True;
2781 	}
2782 	return sal_False;
2783 }
2784 
2785 
2786 void SvxIconChoiceCtrl_Impl::Command( const CommandEvent& rCEvt )
2787 {
2788 	// Rollmaus-Event?
2789 	if( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
2790 		(rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
2791 		(rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
2792 	{
2793 #if 1
2794 		if( HandleScrollCommand( rCEvt ) )
2795 			return;
2796 #else
2797 		ScrollBar* pHor = aHorSBar.IsVisible() ? &aHorSBar : 0;
2798 		ScrollBar* pVer = aVerSBar.IsVisible() ? &aVerSBar : 0;
2799 		if( pView->HandleScrollCommand( rCEvt, pHor, pVer ) )
2800 			return;
2801 #endif
2802 	}
2803 }
2804 
2805 void SvxIconChoiceCtrl_Impl::ToTop( SvxIconChoiceCtrlEntry* pEntry )
2806 {
2807 	if( pZOrderList->GetObject( pZOrderList->Count() - 1 ) != pEntry )
2808 	{
2809 		sal_uLong nPos = pZOrderList->GetPos( (void*)pEntry );
2810 		pZOrderList->Remove( nPos );
2811 		pZOrderList->Insert( pEntry, LIST_APPEND );
2812 	}
2813 }
2814 
2815 void SvxIconChoiceCtrl_Impl::ClipAtVirtOutRect( Rectangle& rRect ) const
2816 {
2817 	if( rRect.Bottom() >= aVirtOutputSize.Height() )
2818 		rRect.Bottom() = aVirtOutputSize.Height() - 1;
2819 	if( rRect.Right() >= aVirtOutputSize.Width() )
2820 		rRect.Right() = aVirtOutputSize.Width() - 1;
2821 	if( rRect.Top() < 0 )
2822 		rRect.Top() = 0;
2823 	if( rRect.Left() < 0 )
2824 		rRect.Left() = 0;
2825 }
2826 
2827 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2828 // sichtbar gemacht werden soll.
2829 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2830 
2831 void SvxIconChoiceCtrl_Impl::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar,
2832 	sal_Bool bCallRectChangedHdl )
2833 {
2834 	Rectangle aVirtRect( rRect );
2835 	ClipAtVirtOutRect( aVirtRect );
2836 	Point aOrigin( pView->GetMapMode().GetOrigin() );
2837 	// in Dokumentkoordinate umwandeln
2838 	aOrigin *= -1;
2839 	Rectangle aOutputArea( GetOutputRect() );
2840 	if( aOutputArea.IsInside( aVirtRect ) )
2841 		return;	// ist schon sichtbar
2842 
2843 	long nDy;
2844 	if( aVirtRect.Top() < aOutputArea.Top() )
2845 	{
2846 		// nach oben scrollen (nDy < 0)
2847 		nDy = aVirtRect.Top() - aOutputArea.Top();
2848 	}
2849 	else if( aVirtRect.Bottom() > aOutputArea.Bottom() )
2850 	{
2851 		// nach unten scrollen (nDy > 0)
2852 		nDy = aVirtRect.Bottom() - aOutputArea.Bottom();
2853 	}
2854 	else
2855 		nDy = 0;
2856 
2857 	long nDx;
2858 	if( aVirtRect.Left() < aOutputArea.Left() )
2859 	{
2860 		// nach links scrollen (nDx < 0)
2861 		nDx = aVirtRect.Left() - aOutputArea.Left();
2862 	}
2863 	else if( aVirtRect.Right() > aOutputArea.Right() )
2864 	{
2865 		// nach rechts scrollen (nDx > 0)
2866 		nDx = aVirtRect.Right() - aOutputArea.Right();
2867 	}
2868 	else
2869 		nDx = 0;
2870 
2871 	aOrigin.X() += nDx;
2872 	aOrigin.Y() += nDy;
2873 	aOutputArea.SetPos( aOrigin );
2874 	if( GetUpdateMode() )
2875 	{
2876 		HideDDIcon();
2877 		pView->Update();
2878 		ShowCursor( sal_False );
2879 	}
2880 
2881 	// Origin fuer SV invertieren (damit wir in
2882 	// Dokumentkoordinaten scrollen/painten koennen)
2883 	aOrigin *= -1;
2884 	SetOrigin( aOrigin );
2885 
2886 	sal_Bool bScrollable = pView->GetBackground().IsScrollable();
2887 	if( pView->HasBackground() && !bScrollable )
2888 	{
2889 		Rectangle aRect( GetOutputRect());
2890 		Wallpaper aPaper( pView->GetBackground() );
2891 		aPaper.SetRect( aRect );
2892 		pView->SetBackground( aPaper );
2893 	}
2894 
2895 	if( bScrollable && GetUpdateMode() )
2896 	{
2897 		// in umgekehrte Richtung scrollen!
2898 		pView->Control::Scroll( -nDx, -nDy, aOutputArea,
2899 			SCROLL_NOCHILDREN | SCROLL_USECLIPREGION | SCROLL_CLIP );
2900 	}
2901 	else
2902 		pView->Invalidate(INVALIDATE_NOCHILDREN);
2903 
2904 	if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2905 	{
2906 		if( !bScrBar )
2907 		{
2908 			aOrigin *= -1;
2909 			// Thumbs korrigieren
2910 			if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2911 				aHorSBar.SetThumbPos( aOrigin.X() );
2912 			if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2913 				aVerSBar.SetThumbPos( aOrigin.Y() );
2914 		}
2915 	}
2916 
2917 	if( GetUpdateMode() )
2918 		ShowCursor( sal_True );
2919 
2920 	// pruefen, ob ScrollBars noch benoetigt werden
2921 	CheckScrollBars();
2922 	if( bScrollable && GetUpdateMode() )
2923 		pView->Update();
2924 
2925 	// kann der angeforderte Bereich nicht komplett sichtbar gemacht werden,
2926 	// wird auf jeden Fall der Vis-Rect-Changed-Handler gerufen. Eintreten kann der
2927 	// Fall z.B. wenn nur wenige Pixel des unteren Randes nicht sichtbar sind,
2928 	// eine ScrollBar aber eine groessere Line-Size eingestellt hat.
2929 	if( bCallRectChangedHdl || GetOutputRect() != rRect )
2930 		VisRectChanged();
2931 }
2932 
2933 
2934 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::FindNewCursor()
2935 {
2936 	SvxIconChoiceCtrlEntry* pNewCursor;
2937 	if( pCursor )
2938 	{
2939 		pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False );
2940 		if( !pNewCursor )
2941 		{
2942 			pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True );
2943 			if( !pNewCursor )
2944 			{
2945 				pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False );
2946 				if( !pNewCursor )
2947 					pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True );
2948 			}
2949 		}
2950 	}
2951 	else
2952 		pNewCursor = (SvxIconChoiceCtrlEntry*)aEntries.First();
2953 	DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"FindNewCursor failed");
2954 	return pNewCursor;
2955 }
2956 
2957 sal_uLong SvxIconChoiceCtrl_Impl::GetSelectionCount() const
2958 {
2959 	if( (nWinBits & WB_HIGHLIGHTFRAME) && pCurHighlightFrame )
2960 		return 1;
2961 	return nSelectionCount;
2962 }
2963 
2964 void SvxIconChoiceCtrl_Impl::ToggleSelection( SvxIconChoiceCtrlEntry* pEntry )
2965 {
2966 	sal_Bool bSel;
2967 	if( pEntry->IsSelected() )
2968 		bSel = sal_False;
2969 	else
2970 		bSel = sal_True;
2971 	SelectEntry( pEntry, bSel, sal_True, sal_True );
2972 }
2973 
2974 void SvxIconChoiceCtrl_Impl::DeselectAllBut( SvxIconChoiceCtrlEntry* pThisEntryNot,
2975 	sal_Bool bPaintSync )
2976 {
2977 	ClearSelectedRectList();
2978 	//
2979 	// !!!!!!! Todo: Evtl. Z-Orderlist abarbeiten !!!!!!!
2980 	//
2981 	sal_uLong nCount = aEntries.Count();
2982 	for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2983 	{
2984 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
2985 		if( pEntry != pThisEntryNot && pEntry->IsSelected() )
2986 			SelectEntry( pEntry, sal_False, sal_True, sal_True, bPaintSync );
2987 	}
2988 	pAnchor = 0;
2989 	nFlags &= (~F_ADD_MODE);
2990 }
2991 
2992 Size SvxIconChoiceCtrl_Impl::GetMinGrid() const
2993 {
2994 	Size aMinSize( aImageSize );
2995 	aMinSize.Width() += 2 * LROFFS_BOUND;
2996 	aMinSize.Height() += TBOFFS_BOUND;	// PB: einmal Offset reicht (FileDlg)
2997 	String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "XXX" ) );
2998 	Size aTextSize( pView->GetTextWidth( aStrDummy ), pView->GetTextHeight() );
2999 	if( nWinBits & WB_ICON )
3000 	{
3001 		aMinSize.Height() += VER_DIST_BMP_STRING;
3002 		aMinSize.Height() += aTextSize.Height();
3003 	}
3004 	else
3005 	{
3006 		aMinSize.Width() += HOR_DIST_BMP_STRING;
3007 		aMinSize.Width() += aTextSize.Width();
3008 	}
3009 	return aMinSize;
3010 }
3011 
3012 void SvxIconChoiceCtrl_Impl::SetGrid( const Size& rSize )
3013 {
3014 	Size aSize( rSize );
3015 	Size aMinSize( GetMinGrid() );
3016 	if( aSize.Width() < aMinSize.Width() )
3017 		aSize.Width() = aMinSize.Width();
3018 	if( aSize.Height() < aMinSize.Height() )
3019 		aSize.Height() = aMinSize.Height();
3020 
3021 	nGridDX = aSize.Width();
3022 	// HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
3023 	// dieses Workaround bringts mit einer Spalte zum Fliegen
3024 	if( nWinBits & WB_DETAILS )
3025 	{
3026 		const SvxIconChoiceCtrlColumnInfo* pCol = GetColumn( 0 );
3027 		if( pCol )
3028 			((SvxIconChoiceCtrlColumnInfo*)pCol)->SetWidth( nGridDX );
3029 	}
3030 	nGridDY = aSize.Height();
3031 	SetDefaultTextSize();
3032 }
3033 
3034 // berechnet die maximale Groesse, die das Textrechteck innerhalb des
3035 // umschliessenden Rechtecks einnehmen kann. Im Modus WB_ICON und
3036 // IcnShowTextFull wird Bottom auf LONG_MAX gesetzt
3037 
3038 Rectangle SvxIconChoiceCtrl_Impl::CalcMaxTextRect( const SvxIconChoiceCtrlEntry* pEntry ) const
3039 {
3040 	Rectangle aBoundRect;
3041 	// keine Endlosrekursion! deshalb das Bound-Rect hier nicht berechnen
3042 	if( IsBoundingRectValid( pEntry->aRect ) )
3043 		aBoundRect = pEntry->aRect;
3044 	else
3045 		aBoundRect = pEntry->aGridRect;
3046 
3047 	Rectangle aBmpRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect(
3048 		(SvxIconChoiceCtrlEntry*)pEntry ) );
3049 	if( nWinBits & WB_ICON )
3050 	{
3051 		aBoundRect.Top() = aBmpRect.Bottom();
3052 		aBoundRect.Top() += VER_DIST_BMP_STRING;
3053 		if( aBoundRect.Top() > aBoundRect.Bottom())
3054 			aBoundRect.Top() = aBoundRect.Bottom();
3055 		aBoundRect.Left() += LROFFS_BOUND;
3056 		aBoundRect.Left()++;
3057 		aBoundRect.Right() -= LROFFS_BOUND;
3058 		aBoundRect.Right()--;
3059 		if( aBoundRect.Left() > aBoundRect.Right())
3060 			aBoundRect.Left() = aBoundRect.Right();
3061 		if( GetEntryTextModeSmart( pEntry ) == IcnShowTextFull )
3062 			aBoundRect.Bottom() = LONG_MAX;
3063 	}
3064 	else
3065 	{
3066 		aBoundRect.Left() = aBmpRect.Right();
3067 		aBoundRect.Left() += HOR_DIST_BMP_STRING;
3068 		aBoundRect.Right() -= LROFFS_BOUND;
3069 		if( aBoundRect.Left() > aBoundRect.Right() )
3070 			aBoundRect.Left() = aBoundRect.Right();
3071 		long nHeight = aBoundRect.GetSize().Height();
3072 		nHeight = nHeight - aDefaultTextSize.Height();
3073 		nHeight /= 2;
3074 		aBoundRect.Top() += nHeight;
3075 		aBoundRect.Bottom() -= nHeight;
3076 	}
3077 	return aBoundRect;
3078 }
3079 
3080 void SvxIconChoiceCtrl_Impl::SetDefaultTextSize()
3081 {
3082 	long nDY = nGridDY;
3083 	nDY -= aImageSize.Height();
3084 	nDY -= VER_DIST_BMP_STRING;
3085 	nDY -= 2*TBOFFS_BOUND;
3086 	if( nDY <= 0 )
3087 		nDY = 2;
3088 
3089 	long nDX = nGridDX;
3090 	nDX -= 2*LROFFS_BOUND;
3091 	nDX -= 2;
3092 	if( nDX <= 0 )
3093 		nDX = 2;
3094 
3095 	String aStrDummy( RTL_CONSTASCII_USTRINGPARAM( "X" ) );
3096 	long nHeight = pView->GetTextHeight();
3097 	if( nDY < nHeight )
3098 		nDY = nHeight;
3099 	aDefaultTextSize = Size( nDX, nDY );
3100 }
3101 
3102 
3103 void SvxIconChoiceCtrl_Impl::Center( SvxIconChoiceCtrlEntry* pEntry ) const
3104 {
3105 	pEntry->aRect = pEntry->aGridRect;
3106 	Size aSize( CalcBoundingSize( pEntry ) );
3107 	if( nWinBits & WB_ICON )
3108 	{
3109 		// horizontal zentrieren
3110 		long nBorder = pEntry->aGridRect.GetWidth() - aSize.Width();
3111 		pEntry->aRect.Left() += nBorder / 2;
3112 		pEntry->aRect.Right() -= nBorder / 2;
3113 	}
3114 	// vertikal zentrieren
3115 	pEntry->aRect.Bottom() = pEntry->aRect.Top() + aSize.Height();
3116 }
3117 
3118 
3119 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3120 // links, hoch: Offsets < 0
3121 // rechts, runter: Offsets > 0
3122 void SvxIconChoiceCtrl_Impl::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
3123 {
3124 	const MapMode& rMapMode = pView->GetMapMode();
3125 	Point aOrigin( rMapMode.GetOrigin() );
3126 	// in Dokumentkoordinate umwandeln
3127 	aOrigin *= -1;
3128 	aOrigin.Y() += nDeltaY;
3129 	aOrigin.X() += nDeltaX;
3130 	Rectangle aRect( aOrigin, aOutputSize );
3131 	MakeVisible( aRect, bScrollBar );
3132 }
3133 
3134 
3135 const Size& SvxIconChoiceCtrl_Impl::GetItemSize( SvxIconChoiceCtrlEntry*,
3136 	IcnViewFieldType eItem ) const
3137 {
3138 	if( eItem == IcnViewFieldTypeText )
3139 		return aDefaultTextSize;
3140 	return aImageSize;
3141 }
3142 
3143 Rectangle SvxIconChoiceCtrl_Impl::CalcFocusRect( SvxIconChoiceCtrlEntry* pEntry )
3144 {
3145 	Rectangle aBmpRect( CalcBmpRect( pEntry ) );
3146 	Rectangle aTextRect( CalcTextRect( pEntry ) );
3147 	Rectangle aBoundRect( GetEntryBoundRect( pEntry ) );
3148 	Rectangle aFocusRect( aBoundRect.Left(), aBmpRect.Top() - 1,
3149 						  aBoundRect.Right() - 4, aTextRect.Bottom() + 1 );
3150 	// Das Fokusrechteck soll nicht den Text beruehren
3151 	if( aFocusRect.Left() - 1 >= pEntry->aRect.Left() )
3152 		aFocusRect.Left()--;
3153 	if( aFocusRect.Right() + 1 <= pEntry->aRect.Right() )
3154 		aFocusRect.Right()++;
3155 
3156 	return aFocusRect;
3157 }
3158 
3159 // Der 'Hot Spot' sind die inneren 50% der Rechteckflaeche
3160 static Rectangle GetHotSpot( const Rectangle& rRect )
3161 {
3162 	Rectangle aResult( rRect );
3163 	aResult.Justify();
3164 	Size aSize( rRect.GetSize() );
3165 	long nDelta = aSize.Width() / 4;
3166 	aResult.Left() += nDelta;
3167 	aResult.Right() -= nDelta;
3168 	nDelta = aSize.Height() / 4;
3169 	aResult.Top() += nDelta;
3170 	aResult.Bottom() -= nDelta;
3171 	return aResult;
3172 }
3173 
3174 void SvxIconChoiceCtrl_Impl::SelectRect( SvxIconChoiceCtrlEntry* pEntry1, SvxIconChoiceCtrlEntry* pEntry2,
3175 	sal_Bool bAdd, SvPtrarr* pOtherRects )
3176 {
3177 	DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3178 	Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3179 	aRect.Union( GetEntryBoundRect( pEntry2 ) );
3180 	SelectRect( aRect, bAdd, pOtherRects );
3181 }
3182 
3183 void SvxIconChoiceCtrl_Impl::SelectRect( const Rectangle& rRect, sal_Bool bAdd,
3184 	SvPtrarr* pOtherRects )
3185 {
3186 	aCurSelectionRect = rRect;
3187 	if( !pZOrderList || !pZOrderList->Count() )
3188 		return;
3189 
3190 	// Flag setzen, damit im Select kein ToTop gerufen wird
3191 	sal_Bool bAlreadySelectingRect = nFlags & F_SELECTING_RECT ? sal_True : sal_False;
3192 	nFlags |= F_SELECTING_RECT;
3193 
3194 	CheckBoundingRects();
3195 	pView->Update();
3196 	const sal_uLong nCount = pZOrderList->Count();
3197 
3198 	Rectangle aRect( rRect );
3199 	aRect.Justify();
3200 	sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False;
3201 
3202 	sal_Bool bResetClipRegion = sal_False;
3203 	if( !pView->IsClipRegion() )
3204 	{
3205 		bResetClipRegion = sal_True;
3206 		pView->SetClipRegion( GetOutputRect() );
3207 	}
3208 
3209 	for( sal_uLong nPos = 0; nPos < nCount; nPos++ )
3210 	{
3211 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pZOrderList->GetObject(nPos ));
3212 
3213 		if( !IsBoundingRectValid( pEntry->aRect ))
3214 			FindBoundingRect( pEntry );
3215 		Rectangle aBoundRect( GetHotSpot( pEntry->aRect ) );
3216 		sal_Bool bSelected = pEntry->IsSelected();
3217 
3218 		sal_Bool bOverlaps;
3219 		if( bCalcOverlap )
3220 			bOverlaps = IsOver( pOtherRects, aBoundRect );
3221 		else
3222 			bOverlaps = sal_False;
3223 		sal_Bool bOver = aRect.IsOver( aBoundRect );
3224 
3225 		if( bOver && !bOverlaps )
3226 		{
3227 			// Ist im neuen Selektionsrechteck und in keinem alten
3228 			// => selektieren
3229 			if( !bSelected )
3230 				SelectEntry( pEntry, sal_True, sal_True, sal_True );
3231 		}
3232 		else if( !bAdd )
3233 		{
3234 			// ist ausserhalb des Selektionsrechtecks
3235 			// => Selektion entfernen
3236 			if( bSelected )
3237 				SelectEntry( pEntry, sal_False, sal_True, sal_True );
3238 		}
3239 		else if( bAdd && bOverlaps )
3240 		{
3241 			// Der Eintrag befindet sich in einem alten (=>Aufspannen
3242 			// mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3243 
3244 			// Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3245 			// in einem vorherigen Rechteck, muss restauriert werden, wenn
3246 			// er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3247 			// nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3248 			// pauschal davon aus, dass die Eintraege in den alten Rechtecken
3249 			// alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3250 			// nur zu deselektieren.
3251 			// Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3252 			// spannen des Rechtecks merken
3253 			if( aBoundRect.IsOver( rRect))
3254 			{
3255 				// Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3256 				if( bSelected )
3257 					SelectEntry( pEntry, sal_False, sal_True, sal_True );
3258 			}
3259 			else
3260 			{
3261 				// Eintrag eines alten Rects selektieren
3262 				if( !bSelected )
3263 					SelectEntry( pEntry, sal_True, sal_True, sal_True );
3264 			}
3265 		}
3266 		else if( !bOver && bSelected )
3267 		{
3268 			// Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3269 			SelectEntry( pEntry, sal_False, sal_True, sal_True );
3270 		}
3271 	}
3272 
3273 	if( !bAlreadySelectingRect )
3274 		nFlags &= ~F_SELECTING_RECT;
3275 
3276 	pView->Update();
3277 	if( bResetClipRegion )
3278 		pView->SetClipRegion();
3279 }
3280 
3281 void SvxIconChoiceCtrl_Impl::SelectRange(
3282 						SvxIconChoiceCtrlEntry* pStart,
3283 						SvxIconChoiceCtrlEntry* pEnd,
3284 						sal_Bool bAdd )
3285 {
3286 	sal_uLong nFront = GetEntryListPos( pStart );
3287 	sal_uLong nBack	 = GetEntryListPos( pEnd );
3288 	sal_uLong nFirst = std::min( nFront, nBack );
3289 	sal_uLong nLast	 = std::max( nFront, nBack );
3290 	sal_uLong i;
3291 	SvxIconChoiceCtrlEntry* pEntry;
3292 
3293 	if ( ! bAdd )
3294 	{
3295 		// deselect everything before the first entry if not in
3296 		// adding mode
3297 		for ( i=0; i<nFirst; i++ )
3298 		{
3299 			pEntry = GetEntry( i );
3300 			if( pEntry->IsSelected() )
3301 				SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3302 		}
3303 	}
3304 
3305 	// select everything between nFirst and nLast
3306 	for ( i=nFirst; i<=nLast; i++ )
3307 	{
3308 		pEntry = GetEntry( i );
3309 		if( ! pEntry->IsSelected() )
3310 			SelectEntry( pEntry, sal_True, sal_True,  sal_True, sal_True );
3311 	}
3312 
3313 	if ( ! bAdd )
3314 	{
3315 		// deselect everything behind the last entry if not in
3316 		// adding mode
3317 		sal_uLong nEnd = GetEntryCount();
3318 		for ( ; i<nEnd; i++ )
3319 		{
3320 			pEntry = GetEntry( i );
3321 			if( pEntry->IsSelected() )
3322 				SelectEntry( pEntry, sal_False, sal_True, sal_True, sal_True );
3323 		}
3324 	}
3325 }
3326 
3327 sal_Bool SvxIconChoiceCtrl_Impl::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3328 {
3329 	const sal_uInt16 nCount = pRectList->Count();
3330 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3331 	{
3332 		Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3333 		if( rBoundRect.IsOver( *pRect ))
3334 			return sal_True;
3335 	}
3336 	return sal_False;
3337 }
3338 
3339 void SvxIconChoiceCtrl_Impl::AddSelectedRect( SvxIconChoiceCtrlEntry* pEntry1,
3340 	SvxIconChoiceCtrlEntry* pEntry2 )
3341 {
3342 	DBG_ASSERT(pEntry1 && pEntry2,"SelectEntry: Invalid Entry-Ptr");
3343 	Rectangle aRect( GetEntryBoundRect( pEntry1 ) );
3344 	aRect.Union( GetEntryBoundRect( pEntry2 ) );
3345 	AddSelectedRect( aRect );
3346 }
3347 
3348 void SvxIconChoiceCtrl_Impl::AddSelectedRect( const Rectangle& rRect )
3349 {
3350 	Rectangle* pRect = new Rectangle( rRect );
3351 	pRect->Justify();
3352 	aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3353 }
3354 
3355 void SvxIconChoiceCtrl_Impl::ClearSelectedRectList()
3356 {
3357 	const sal_uInt16 nCount = aSelectedRectList.Count();
3358 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3359 	{
3360 		Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3361 		delete pRect;
3362 	}
3363 	aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3364 }
3365 
3366 void SvxIconChoiceCtrl_Impl::CalcScrollOffsets( const Point& rPosPixel,
3367 	long& rX, long& rY, sal_Bool isInDragDrop, sal_uInt16 nBorderWidth)
3368 {
3369 	// Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3370 	// Fensters befindet
3371 	long nPixelToScrollX = 0;
3372 	long nPixelToScrollY = 0;
3373 	Size aWndSize = aOutputSize;
3374 
3375 	nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3376 	nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3377 
3378 	if ( rPosPixel.X() < nBorderWidth )
3379 	{
3380 		if( isInDragDrop )
3381 			nPixelToScrollX = -DD_SCROLL_PIXEL;
3382 		else
3383 			nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3384 	}
3385 	else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3386 	{
3387 		if( isInDragDrop )
3388 			nPixelToScrollX = DD_SCROLL_PIXEL;
3389 		else
3390 			nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3391 	}
3392 	if ( rPosPixel.Y() < nBorderWidth )
3393 	{
3394 		if( isInDragDrop )
3395 			nPixelToScrollY = -DD_SCROLL_PIXEL;
3396 		else
3397 			nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3398 	}
3399 	else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3400 	{
3401 		if( isInDragDrop )
3402 			nPixelToScrollY = DD_SCROLL_PIXEL;
3403 		else
3404 			nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3405 	}
3406 
3407 	rX = nPixelToScrollX;
3408 	rY = nPixelToScrollY;
3409 }
3410 
3411 IMPL_LINK(SvxIconChoiceCtrl_Impl, AutoArrangeHdl, void*, EMPTYARG )
3412 {
3413 	aAutoArrangeTimer.Stop();
3414 	Arrange( IsAutoArrange() );
3415 	return 0;
3416 }
3417 
3418 IMPL_LINK(SvxIconChoiceCtrl_Impl, VisRectChangedHdl, void*, EMPTYARG )
3419 {
3420 	aVisRectChangedTimer.Stop();
3421 	pView->VisibleRectChanged();
3422 	return 0;
3423 }
3424 
3425 IMPL_LINK(SvxIconChoiceCtrl_Impl, DocRectChangedHdl, void*, EMPTYARG )
3426 {
3427 	aDocRectChangedTimer.Stop();
3428 	pView->DocumentRectChanged();
3429 	return 0;
3430 }
3431 
3432 void SvxIconChoiceCtrl_Impl::PrepareCommandEvent( const CommandEvent& rCEvt )
3433 {
3434 	StopEditTimer();
3435 	SvxIconChoiceCtrlEntry* pEntry = pView->GetEntry( rCEvt.GetMousePosPixel() );
3436 	if( (nFlags & F_DOWN_CTRL) && pEntry && !pEntry->IsSelected() )
3437 		SelectEntry( pEntry, sal_True, sal_True );
3438 	nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
3439 }
3440 
3441 sal_Bool SvxIconChoiceCtrl_Impl::IsTextHit( SvxIconChoiceCtrlEntry* pEntry, const Point& rDocPos )
3442 {
3443 	Rectangle aRect( CalcTextRect( pEntry ));
3444 	if( aRect.IsInside( rDocPos ) )
3445 		return sal_True;
3446 	return sal_False;
3447 }
3448 
3449 IMPL_LINK(SvxIconChoiceCtrl_Impl, EditTimeoutHdl, Timer*, EMPTYARG )
3450 {
3451 	SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
3452 	if( bEntryEditingEnabled && pEntry &&
3453 		pEntry->IsSelected())
3454 	{
3455 		if( pView->EditingEntry( pEntry ))
3456 			EditEntry( pEntry );
3457 	}
3458 	return 0;
3459 }
3460 
3461 
3462 //
3463 // Funktionen zum Ausrichten der Eintraege am Grid
3464 //
3465 
3466 // pStart == 0: Alle Eintraege werden ausgerichtet
3467 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
3468 void SvxIconChoiceCtrl_Impl::AdjustEntryAtGrid( SvxIconChoiceCtrlEntry* pStart )
3469 {
3470 	SvPtrarr aLists;
3471 	pImpCursor->CreateGridAjustData( aLists, pStart );
3472 	const sal_uInt16 nCount = aLists.Count();
3473 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3474 		AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
3475 	IcnCursor_Impl::DestroyGridAdjustData( aLists );
3476 	CheckScrollBars();
3477 }
3478 
3479 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
3480 void SvxIconChoiceCtrl_Impl::AdjustAtGrid( const SvPtrarr& rRow, SvxIconChoiceCtrlEntry* pStart )
3481 {
3482 	if( !rRow.Count() )
3483 		return;
3484 
3485 	sal_Bool bGo;
3486 	if( !pStart )
3487 		bGo = sal_True;
3488 	else
3489 		bGo = sal_False;
3490 
3491 	long nCurRight = 0;
3492 	for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ )
3493 	{
3494 		SvxIconChoiceCtrlEntry* pCur = (SvxIconChoiceCtrlEntry*)rRow[ nCur ];
3495 		if( !bGo && pCur == pStart )
3496 			bGo = sal_True;
3497 
3498 		//SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
3499 		// Massgebend (fuer unser Auge) ist die Bitmap, da sonst
3500 		// durch lange Texte der Eintrag stark springen kann
3501 		const Rectangle& rBoundRect = GetEntryBoundRect( pCur );
3502 		Rectangle aCenterRect( CalcBmpRect( pCur, 0 ));
3503 		if( bGo && !pCur->IsPosLocked() )
3504 		{
3505 			long nWidth = aCenterRect.GetSize().Width();
3506 			Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
3507 			while( aNewPos.X() < nCurRight )
3508 				aNewPos.X() += nGridDX;
3509 			if( aNewPos != rBoundRect.TopLeft() )
3510 			{
3511 				SetEntryPos( pCur, aNewPos );
3512 				pCur->SetFlags( ICNVIEW_FLAG_POS_MOVED );
3513 				nFlags |= F_MOVED_ENTRIES;
3514 			}
3515 			nCurRight = aNewPos.X() + nWidth;
3516 		}
3517 		else
3518 		{
3519 			nCurRight = rBoundRect.Right();
3520 		}
3521 	}
3522 }
3523 
3524 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
3525 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
3526 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
3527 // die Berechnung des Ziel-Rechtecks verwendet wird.
3528 Point SvxIconChoiceCtrl_Impl::AdjustAtGrid( const Rectangle& rCenterRect,
3529 	const Rectangle& rBoundRect ) const
3530 {
3531 	Point aPos( rCenterRect.TopLeft() );
3532 	Size aSize( rCenterRect.GetSize() );
3533 
3534 	aPos.X() -= LROFFS_WINBORDER;
3535 	aPos.Y() -= TBOFFS_WINBORDER;
3536 
3537 	// align (ref ist mitte des rects)
3538 	short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
3539 	short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
3540 	aPos.X() = nGridX * nGridDX;
3541 	aPos.Y() = nGridY * nGridDY;
3542 	// hor. center
3543 	aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
3544 
3545 	aPos.X() += LROFFS_WINBORDER;
3546 	aPos.Y() += TBOFFS_WINBORDER;
3547 
3548 	return aPos;
3549 }
3550 
3551 void SvxIconChoiceCtrl_Impl::SetEntryTextMode( SvxIconChoiceCtrlTextMode eMode, SvxIconChoiceCtrlEntry* pEntry )
3552 {
3553 	if( !pEntry )
3554 	{
3555 		if( eTextMode != eMode )
3556 		{
3557 			if( eTextMode == IcnShowTextDontKnow )
3558 				eTextMode = IcnShowTextShort;
3559 			eTextMode = eMode;
3560 			Arrange( sal_True );
3561 		}
3562 	}
3563 	else
3564 	{
3565 		if( pEntry->eTextMode != eMode )
3566 		{
3567 			pEntry->eTextMode = eMode;
3568 			InvalidateEntry( pEntry );
3569 			pView->Invalidate( GetEntryBoundRect( pEntry ) );
3570 			AdjustVirtSize( pEntry->aRect );
3571 		}
3572 	}
3573 }
3574 
3575 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetTextMode( const SvxIconChoiceCtrlEntry* pEntry ) const
3576 {
3577 	if( !pEntry )
3578 		return eTextMode;
3579 	return pEntry->GetTextMode();
3580 }
3581 
3582 SvxIconChoiceCtrlTextMode SvxIconChoiceCtrl_Impl::GetEntryTextModeSmart( const SvxIconChoiceCtrlEntry* pEntry ) const
3583 {
3584 	DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
3585 	SvxIconChoiceCtrlTextMode eMode = pEntry->GetTextMode();
3586 	if( eMode == IcnShowTextDontKnow )
3587 		return eTextMode;
3588 	return eMode;
3589 }
3590 
3591 void SvxIconChoiceCtrl_Impl::ShowEntryFocusRect( const SvxIconChoiceCtrlEntry* pEntry )
3592 {
3593 	if( !pEntry )
3594 	{
3595 		pView->HideFocus();
3596 	}
3597 	else
3598 	{
3599 		Rectangle aRect ( CalcFocusRect( (SvxIconChoiceCtrlEntry*)pEntry ) );
3600 		/*pView->*/ShowFocus( aRect );
3601 	}
3602 }
3603 
3604 ////////////////////////////////////////////////////////////////////////////////////////////////
3605 //
3606 // Draw my own focusrect, because the focusrect of the outputdevice has got the inverted color
3607 // of the background. But what will we see, if the the backgroundcolor is gray ? - We will see
3608 // a gray focusrect on a gray background !!!
3609 //
3610 void SvxIconChoiceCtrl_Impl::ShowFocus ( Rectangle& rRect )
3611 {
3612 	Color aBkgColor ( pView->GetBackground().GetColor() );
3613 	Color aPenColor;
3614 	sal_uInt16 nColor = ( aBkgColor.GetRed() + aBkgColor.GetGreen() + aBkgColor.GetBlue() ) / 3;
3615 	if ( nColor > 128 )
3616 		aPenColor.SetColor ( COL_BLACK );
3617 	else
3618 		aPenColor.SetColor( COL_WHITE );
3619 
3620 	aFocus.bOn = sal_True;
3621 	aFocus.aPenColor = aPenColor;
3622 	aFocus.aRect = rRect;
3623 }
3624 
3625 void SvxIconChoiceCtrl_Impl::HideFocus ()
3626 {
3627 	aFocus.bOn = sal_False;
3628 }
3629 
3630 void SvxIconChoiceCtrl_Impl::DrawFocusRect ( OutputDevice* pOut )
3631 {
3632 	pOut->SetLineColor( aFocus.aPenColor );
3633 	pOut->SetFillColor();
3634 	Polygon aPolygon ( aFocus.aRect );
3635 
3636 	LineInfo aLineInfo ( LINE_DASH );
3637 
3638 	aLineInfo.SetDashLen ( 1 );
3639 
3640 	aLineInfo.SetDotLen ( 1L );
3641 	aLineInfo.SetDistance ( 1L );
3642 	aLineInfo.SetDotCount ( 1 );
3643 
3644 	pOut->DrawPolyLine ( aPolygon, aLineInfo );
3645 }
3646 
3647 sal_Bool SvxIconChoiceCtrl_Impl::IsMnemonicChar( sal_Unicode cChar, sal_uLong& rPos ) const
3648 {
3649 	sal_Bool bRet = sal_False;
3650     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
3651 	sal_uLong nEntryCount = GetEntryCount();
3652 	for ( sal_uLong i = 0; i < nEntryCount; ++i )
3653 	{
3654 		if ( rI18nHelper.MatchMnemonic( GetEntry( i )->GetText(), cChar ) )
3655 		{
3656 			bRet = sal_True;
3657 			rPos = i;
3658 			break;
3659 		}
3660 	}
3661 
3662 	return bRet;
3663 }
3664 
3665 //
3666 ////////////////////////////////////////////////////////////////////////////////////////////////
3667 
3668 IMPL_LINK(SvxIconChoiceCtrl_Impl, UserEventHdl, void*, nId )
3669 {
3670 	if( nId == EVENTID_ADJUST_SCROLLBARS )
3671 	{
3672 		nUserEventAdjustScrBars = 0;
3673 		AdjustScrollBars();
3674 	}
3675 	else if( nId == EVENTID_SHOW_CURSOR )
3676 	{
3677 		nUserEventShowCursor = 0;
3678 		ShowCursor( sal_True );
3679 	}
3680 	return 0;
3681 }
3682 
3683 void SvxIconChoiceCtrl_Impl::CancelUserEvents()
3684 {
3685 	if( nUserEventAdjustScrBars )
3686 	{
3687 		Application::RemoveUserEvent( nUserEventAdjustScrBars );
3688 		nUserEventAdjustScrBars = 0;
3689 	}
3690 	if( nUserEventShowCursor )
3691 	{
3692 		Application::RemoveUserEvent( nUserEventShowCursor );
3693 		nUserEventShowCursor = 0;
3694 	}
3695 }
3696 
3697 void SvxIconChoiceCtrl_Impl::InvalidateEntry( SvxIconChoiceCtrlEntry* pEntry )
3698 {
3699 	if( pEntry == pCursor )
3700 		ShowCursor( sal_False );
3701 	pView->Invalidate( pEntry->aRect );
3702 	Center( pEntry );
3703 	pView->Invalidate( pEntry->aRect );
3704 	if( pEntry == pCursor )
3705 		ShowCursor( sal_True );
3706 }
3707 
3708 void SvxIconChoiceCtrl_Impl::EditEntry( SvxIconChoiceCtrlEntry* pEntry )
3709 {
3710 	DBG_ASSERT(pEntry,"EditEntry: Entry not set");
3711 	if( !pEntry )
3712 		return;
3713 
3714 	StopEntryEditing( sal_True );
3715 	DELETEZ(pEdit);
3716 	SetNoSelection();
3717 
3718 	pCurEditedEntry = pEntry;
3719 	String aEntryText( pView->GetEntryText( pEntry, sal_True ) );
3720 	Rectangle aRect( CalcTextRect( pEntry, 0, sal_True, &aEntryText ) );
3721 	MakeVisible( aRect );
3722 	Point aPos( aRect.TopLeft() );
3723 	aPos = pView->GetPixelPos( aPos );
3724 	aRect.SetPos( aPos );
3725 	pView->HideFocus();
3726 	pEdit = new IcnViewEdit_Impl(
3727 		pView,
3728 		aRect.TopLeft(),
3729 		aRect.GetSize(),
3730 		aEntryText,
3731 		LINK( this, SvxIconChoiceCtrl_Impl, TextEditEndedHdl ) );
3732 }
3733 
3734 IMPL_LINK( SvxIconChoiceCtrl_Impl, TextEditEndedHdl, IcnViewEdit_Impl*, EMPTYARG )
3735 {
3736 	DBG_ASSERT(pEdit,"TextEditEnded: pEdit not set");
3737 	if( !pEdit )
3738 	{
3739 		pCurEditedEntry = 0;
3740 		return 0;
3741 	}
3742 	DBG_ASSERT(pCurEditedEntry,"TextEditEnded: pCurEditedEntry not set");
3743 
3744 	if( !pCurEditedEntry )
3745 	{
3746 		pEdit->Hide();
3747 		if( pEdit->IsGrabFocus() )
3748 			pView->GrabFocus();
3749 		return 0;
3750 	}
3751 
3752 	String aText;
3753 	if ( !pEdit->EditingCanceled() )
3754 		aText = pEdit->GetText();
3755 	else
3756 		aText = pEdit->GetSavedValue();
3757 
3758 	if( pView->EditedEntry( pCurEditedEntry, aText, pEdit->EditingCanceled() ) )
3759 		InvalidateEntry( pCurEditedEntry );
3760 	if( !GetSelectionCount() )
3761 		SelectEntry( pCurEditedEntry, sal_True );
3762 
3763 	pEdit->Hide();
3764 	if( pEdit->IsGrabFocus() )
3765 		pView->GrabFocus();
3766 	// Das Edit kann nicht hier geloescht werden, weil es noch in einem
3767 	// Handler steht. Es wird im Dtor oder im naechsten EditEntry geloescht.
3768 	pCurEditedEntry = 0;
3769 	return 0;
3770 }
3771 
3772 void SvxIconChoiceCtrl_Impl::StopEntryEditing( sal_Bool bCancel )
3773 {
3774 	if( pEdit )
3775 		pEdit->StopEditing( bCancel );
3776 }
3777 
3778 void SvxIconChoiceCtrl_Impl::LockEntryPos( SvxIconChoiceCtrlEntry* pEntry, sal_Bool bLock )
3779 {
3780 	if( bLock )
3781 		pEntry->SetFlags( ICNVIEW_FLAG_POS_LOCKED );
3782 	else
3783 		pEntry->ClearFlags( ICNVIEW_FLAG_POS_LOCKED );
3784 }
3785 
3786 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry( sal_uLong& rPos ) const
3787 {
3788 	if( !GetSelectionCount() )
3789 		return 0;
3790 
3791 	if( (nWinBits & WB_HIGHLIGHTFRAME) && (eSelectionMode == NO_SELECTION) )
3792 	{
3793 		rPos = pView->GetEntryListPos( pCurHighlightFrame );
3794 		return pCurHighlightFrame;
3795 	}
3796 
3797 	sal_uLong nCount = aEntries.Count();
3798 	if( !pHead )
3799 	{
3800 		for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
3801 		{
3802 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3803 			if( pEntry->IsSelected() )
3804 			{
3805 				rPos = nCur;
3806 				return pEntry;
3807 			}
3808 		}
3809 	}
3810 	else
3811 	{
3812 		SvxIconChoiceCtrlEntry* pEntry = pHead;
3813 		while( nCount-- )
3814 		{
3815 			if( pEntry->IsSelected() )
3816 			{
3817 				rPos = GetEntryListPos( pEntry );
3818 				return pEntry;
3819 			}
3820 			pEntry = pEntry->pflink;
3821 			if( nCount && pEntry == pHead )
3822 			{
3823 				DBG_ERROR("SvxIconChoiceCtrl_Impl::GetFirstSelectedEntry > Endlosschleife!");
3824 				return 0;
3825 			}
3826 		}
3827 	}
3828 	return 0;
3829 }
3830 
3831 // kein Round Robin!
3832 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GetNextSelectedEntry( sal_uLong& rStartPos ) const
3833 {
3834 	sal_uLong nCount = aEntries.Count();
3835 	if( rStartPos > nCount || !GetSelectionCount() )
3836 		return 0;
3837 	if( !pHead )
3838 	{
3839 		for( sal_uLong nCur = rStartPos+1; nCur < nCount; nCur++ )
3840 		{
3841 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3842 			if( pEntry->IsSelected() )
3843 			{
3844 				rStartPos = nCur;
3845 				return pEntry;
3846 			}
3847 		}
3848 	}
3849 	else
3850 	{
3851 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( rStartPos );
3852 		pEntry = pEntry->pflink;
3853 		while( pEntry != pHead )
3854 		{
3855 			if( pEntry->IsSelected() )
3856 			{
3857 				rStartPos = GetEntryListPos( pEntry );
3858 				return pEntry;
3859 			}
3860 			pEntry = pEntry->pflink;
3861 		}
3862 	}
3863 
3864 	rStartPos = 0xffffffff;
3865 	return 0;
3866 }
3867 
3868 void SvxIconChoiceCtrl_Impl::SelectAll( sal_Bool bSelect, sal_Bool bPaint )
3869 {
3870 	bPaint = sal_True;
3871 
3872 	sal_uLong nCount = aEntries.Count();
3873 	for( sal_uLong nCur = 0; nCur < nCount && (bSelect || GetSelectionCount() ); nCur++ )
3874 	{
3875 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
3876 		SelectEntry( pEntry, bSelect, sal_True, sal_True, bPaint );
3877 	}
3878 	nFlags &= (~F_ADD_MODE);
3879 	pAnchor = 0;
3880 }
3881 
3882 void SvxIconChoiceCtrl_Impl::SaveSelection( List** ppList )
3883 {
3884 	if( !*ppList )
3885 		*ppList = new List;
3886 	sal_uLong nPos;
3887 	SvxIconChoiceCtrlEntry* pEntry = GetFirstSelectedEntry( nPos );
3888 	while( pEntry && GetSelectionCount() != (*ppList)->Count() )
3889 	{
3890 		(*ppList)->Insert( pEntry, LIST_APPEND );
3891 		pEntry = GetNextSelectedEntry( nPos );
3892 	}
3893 }
3894 
3895 IcnViewEdit_Impl::IcnViewEdit_Impl( SvtIconChoiceCtrl* pParent, const Point& rPos,
3896 	const Size& rSize, const XubString& rData, const Link& rNotifyEditEnd ) :
3897 	MultiLineEdit( pParent, (pParent->GetStyle() & WB_ICON) ? WB_CENTER : WB_LEFT),
3898 	aCallBackHdl( rNotifyEditEnd ),
3899 	bCanceled( sal_False ),
3900 	bAlreadyInCallback( sal_False ),
3901 	bGrabFocus( sal_False )
3902 {
3903 	Font aFont( pParent->GetPointFont() );
3904 	aFont.SetTransparent( sal_False );
3905 	SetControlFont( aFont );
3906 	if( !pParent->HasFontFillColor() )
3907 	{
3908 		Color aColor( pParent->GetBackground().GetColor() );
3909 		SetControlBackground( aColor );
3910 	}
3911 	else
3912 		SetControlBackground( aFont.GetFillColor() );
3913 	SetControlForeground( aFont.GetColor() );
3914 	SetPosPixel( rPos );
3915 	SetSizePixel( CalcAdjustedSize(rSize) );
3916 	SetText( rData );
3917 	SaveValue();
3918 
3919 	aAccReturn.InsertItem( IMPICNVIEW_ACC_RETURN, KeyCode(KEY_RETURN) );
3920 	aAccEscape.InsertItem( IMPICNVIEW_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
3921 
3922 	aAccReturn.SetActivateHdl( LINK( this, IcnViewEdit_Impl, ReturnHdl_Impl) );
3923 	aAccEscape.SetActivateHdl( LINK( this, IcnViewEdit_Impl, EscapeHdl_Impl) );
3924 	GetpApp()->InsertAccel( &aAccReturn);//, ACCEL_ALWAYS );
3925 	GetpApp()->InsertAccel( &aAccEscape);//, ACCEL_ALWAYS );
3926 	Show();
3927 	GrabFocus();
3928 }
3929 
3930 IcnViewEdit_Impl::~IcnViewEdit_Impl()
3931 {
3932 	if( !bAlreadyInCallback )
3933 	{
3934 		GetpApp()->RemoveAccel( &aAccReturn );
3935 		GetpApp()->RemoveAccel( &aAccEscape );
3936 	}
3937 }
3938 
3939 void IcnViewEdit_Impl::CallCallBackHdl_Impl()
3940 {
3941 	aTimer.Stop();
3942 	if ( !bAlreadyInCallback )
3943 	{
3944 		bAlreadyInCallback = sal_True;
3945 		GetpApp()->RemoveAccel( &aAccReturn );
3946 		GetpApp()->RemoveAccel( &aAccEscape );
3947 		Hide();
3948 		aCallBackHdl.Call( this );
3949 	}
3950 }
3951 
3952 IMPL_LINK( IcnViewEdit_Impl, Timeout_Impl, Timer*, EMPTYARG )
3953 {
3954 	CallCallBackHdl_Impl();
3955 	return 0;
3956 }
3957 
3958 IMPL_LINK( IcnViewEdit_Impl, ReturnHdl_Impl, Accelerator*, EMPTYARG  )
3959 {
3960 	bCanceled = sal_False;
3961 	bGrabFocus = sal_True;
3962 	CallCallBackHdl_Impl();
3963 	return 1;
3964 }
3965 
3966 IMPL_LINK( IcnViewEdit_Impl, EscapeHdl_Impl, Accelerator*, EMPTYARG  )
3967 {
3968 	bCanceled = sal_True;
3969 	bGrabFocus = sal_True;
3970 	CallCallBackHdl_Impl();
3971 	return 1;
3972 }
3973 
3974 void IcnViewEdit_Impl::KeyInput( const KeyEvent& rKEvt )
3975 {
3976 	KeyCode aCode = rKEvt.GetKeyCode();
3977 	sal_uInt16 nCode = aCode.GetCode();
3978 
3979 	switch ( nCode )
3980 	{
3981 		case KEY_ESCAPE:
3982 			bCanceled = sal_True;
3983 			bGrabFocus = sal_True;
3984 			CallCallBackHdl_Impl();
3985 			break;
3986 
3987 		case KEY_RETURN:
3988 			bCanceled = sal_False;
3989 			bGrabFocus = sal_True;
3990 			CallCallBackHdl_Impl();
3991 			break;
3992 
3993 		default:
3994 			MultiLineEdit::KeyInput( rKEvt );
3995 	}
3996 }
3997 
3998 long IcnViewEdit_Impl::PreNotify( NotifyEvent& rNEvt )
3999 {
4000 	if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4001 	{
4002 		if ( !bAlreadyInCallback &&
4003 			((!Application::GetFocusWindow()) || !IsChild(Application::GetFocusWindow())))
4004 		{
4005 			bCanceled = sal_False;
4006 			aTimer.SetTimeout(10);
4007 			aTimer.SetTimeoutHdl(LINK(this,IcnViewEdit_Impl,Timeout_Impl));
4008 			aTimer.Start();
4009 		}
4010 	}
4011 	return 0;
4012 }
4013 
4014 void IcnViewEdit_Impl::StopEditing( sal_Bool bCancel )
4015 {
4016 	if ( !bAlreadyInCallback )
4017 	{
4018 		bCanceled = bCancel;
4019 		CallCallBackHdl_Impl();
4020 	}
4021 }
4022 
4023 sal_uLong SvxIconChoiceCtrl_Impl::GetEntryListPos( SvxIconChoiceCtrlEntry* pEntry ) const
4024 {
4025 	if( !(nFlags & F_ENTRYLISTPOS_VALID ))
4026 		((SvxIconChoiceCtrl_Impl*)this)->SetListPositions();
4027 	return pEntry->nPos;
4028 }
4029 
4030 void SvxIconChoiceCtrl_Impl::SetEntryListPos( SvxIconChoiceCtrlEntry* pListEntry, sal_uLong nNewPos )
4031 {
4032 	sal_uLong nCurPos = GetEntryListPos( pListEntry );
4033 	if( nCurPos == nNewPos )
4034 		return;
4035 	aEntries.List::Remove( nCurPos );
4036 	aEntries.List::Insert( (void*)pListEntry, nNewPos );
4037 	// Eintragspositionen anpassen
4038 	sal_uLong nStart, nEnd;
4039 	if( nNewPos < nCurPos )
4040 	{
4041 		nStart = nNewPos;
4042 		nEnd = nCurPos;
4043 	}
4044 	else
4045 	{
4046 		nStart = nCurPos;
4047 		nEnd = nNewPos;
4048 	}
4049 	for( ; nStart <= nEnd; nStart++ )
4050 	{
4051 		SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nStart );
4052 		pEntry->nPos = nStart;
4053 	}
4054 }
4055 
4056 void SvxIconChoiceCtrl_Impl::SetEntryFlags( SvxIconChoiceCtrlEntry* pEntry, sal_uInt16 nEntryFlags )
4057 {
4058 	pEntry->nFlags = nEntryFlags;
4059 	if( nEntryFlags & ICNVIEW_FLAG_POS_MOVED )
4060 		nFlags |= F_MOVED_ENTRIES;
4061 }
4062 
4063 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pStart, sal_Bool bRight )
4064 {
4065 	return pImpCursor->GoLeftRight( pStart, bRight );
4066 }
4067 
4068 SvxIconChoiceCtrlEntry* SvxIconChoiceCtrl_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown )
4069 {
4070 	return pImpCursor->GoUpDown( pStart, bDown );
4071 }
4072 
4073 void SvxIconChoiceCtrl_Impl::InitSettings()
4074 {
4075 	const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
4076 
4077 	if( !pView->HasFont() )
4078 	{
4079 		// Unit aus den Settings ist Point
4080 		Font aFont( rStyleSettings.GetFieldFont() );
4081 		//const Font& rFont = pView->GetFont();
4082 		//if( pView->HasFontTextColor() )
4083 			aFont.SetColor( rStyleSettings.GetWindowTextColor() );
4084 		//if( pView->HasFontFillColor() )
4085 			//aFont.SetFillColor( rFont.GetFillColor() );
4086 		pView->SetPointFont( aFont );
4087 		SetDefaultTextSize();
4088 	}
4089 
4090 	//if( !pView->HasFontTextColor() )
4091 		pView->SetTextColor( rStyleSettings.GetFieldTextColor() );
4092 	//if( !pView->HasFontFillColor() )
4093 		pView->SetTextFillColor();
4094 
4095 	//if( !pView->HasBackground() )
4096 		pView->SetBackground( rStyleSettings.GetFieldColor());
4097 
4098 	long nScrBarSize = rStyleSettings.GetScrollBarSize();
4099 	if( nScrBarSize != nHorSBarHeight || nScrBarSize != nVerSBarWidth )
4100 	{
4101 		nHorSBarHeight = nScrBarSize;
4102 		Size aSize( aHorSBar.GetSizePixel() );
4103 		aSize.Height() = nScrBarSize;
4104 		aHorSBar.Hide();
4105 		aHorSBar.SetSizePixel( aSize );
4106 
4107 		nVerSBarWidth = nScrBarSize;
4108 		aSize = aVerSBar.GetSizePixel();
4109 		aSize.Width() = nScrBarSize;
4110 		aVerSBar.Hide();
4111 		aVerSBar.SetSizePixel( aSize );
4112 
4113 		Size aOSize( pView->Control::GetOutputSizePixel() );
4114 		PositionScrollBars( aOSize.Width(), aOSize.Height() );
4115 		AdjustScrollBars();
4116 	}
4117 }
4118 
4119 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nInitSize , sal_uInt16 _nReSize ) :
4120 	List( _nInitSize, _nReSize ),
4121 	_pOwner( pOwner )
4122 {
4123 	_pOwner->pHead = 0;
4124 }
4125 
4126 EntryList_Impl::EntryList_Impl( SvxIconChoiceCtrl_Impl* pOwner, sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) :
4127 	List( _nBlockSize, _nInitSize, _nReSize ),
4128 	_pOwner( pOwner )
4129 {
4130 	_pOwner->pHead = 0;
4131 }
4132 
4133 EntryList_Impl::~EntryList_Impl()
4134 {
4135 	_pOwner->pHead = 0;
4136 }
4137 
4138 void EntryList_Impl::Clear()
4139 {
4140 	_pOwner->pHead = 0;
4141 	List::Clear();
4142 }
4143 
4144 void EntryList_Impl::Insert( SvxIconChoiceCtrlEntry* pEntry, sal_uLong nPos )
4145 {
4146 	List::Insert( pEntry, nPos );
4147 	if( _pOwner->pHead )
4148 		pEntry->SetBacklink( _pOwner->pHead->pblink );
4149 }
4150 
4151 SvxIconChoiceCtrlEntry* EntryList_Impl::Remove( sal_uLong nPos )
4152 {
4153 	SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)List::Remove( nPos );
4154 	DBG_ASSERT(pEntry,"EntryList_Impl::Remove > Entry not found");
4155 	Removed_Impl( pEntry );
4156 	return pEntry;
4157 }
4158 
4159 void EntryList_Impl::Remove( SvxIconChoiceCtrlEntry* pEntry )
4160 {
4161 	List::Remove( (void*)pEntry );
4162 	Removed_Impl( pEntry );
4163 }
4164 
4165 void EntryList_Impl::Removed_Impl( SvxIconChoiceCtrlEntry* pEntry )
4166 {
4167 	if( _pOwner->pHead )
4168 	{
4169 		if( _pOwner->pHead == pEntry )
4170 		{
4171 			if( _pOwner->pHead != pEntry->pflink )
4172 				_pOwner->pHead = pEntry->pflink;
4173 			else
4174 			{
4175 				DBG_ASSERT(!Count(),"EntryList_Impl::Remove > Invalid predecessor" );
4176 				_pOwner->pHead = 0;
4177 			}
4178 		}
4179 		pEntry->Unlink();
4180 	}
4181 }
4182 
4183 void SvxIconChoiceCtrl_Impl::SetPositionMode( SvxIconChoiceCtrlPositionMode eMode )
4184 {
4185 	sal_uLong nCur;
4186 
4187 	if( eMode == ePositionMode )
4188 		return;
4189 
4190 	SvxIconChoiceCtrlPositionMode eOldMode = ePositionMode;
4191 	ePositionMode = eMode;
4192 	sal_uLong nCount = aEntries.Count();
4193 
4194 	if( eOldMode == IcnViewPositionModeAutoArrange )
4195 	{
4196 		// positionieren wir verschobene Eintraege 'hart' gibts noch Probleme
4197 		// mit ungewollten Ueberlappungen, da diese Eintrage im Arrange
4198 		// nicht beruecksichtigt werden.
4199 #if 1
4200 		if( aEntries.Count() )
4201 			aAutoArrangeTimer.Start();
4202 #else
4203 		if( pHead )
4204 		{
4205 			// verschobene Eintraege 'hart' auf ihre Position setzen
4206 			nCur = nCount;
4207 			SvxIconChoiceCtrlEntry* pEntry = pHead;
4208 			while( nCur )
4209 			{
4210 				SvxIconChoiceCtrlEntry* pPred;
4211 				if( GetEntryPredecessor( pEntry, &pPred ))
4212 					SetEntryFlags( pEntry, ICNVIEW_FLAG_POS_MOVED );
4213 				pEntry = pEntry->pflink;
4214 				nCur--;
4215 			}
4216 			ClearPredecessors();
4217 		}
4218 #endif
4219 		return;
4220 	}
4221 
4222 	if( ePositionMode == IcnViewPositionModeAutoArrange )
4223 	{
4224 		List aMovedEntries;
4225 		for( nCur = 0; nCur < nCount; nCur++ )
4226 		{
4227 			SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nCur );
4228 			if( pEntry->GetFlags() & (ICNVIEW_FLAG_POS_LOCKED | ICNVIEW_FLAG_POS_MOVED))
4229 			{
4230 				SvxIconChoiceCtrlEntry_Impl* pE = new SvxIconChoiceCtrlEntry_Impl(
4231 						pEntry, GetEntryBoundRect( pEntry ));
4232 				aMovedEntries.Insert( pE, LIST_APPEND );
4233 			}
4234 		}
4235 		nCount = aMovedEntries.Count();
4236 		for( nCur = 0; nCur < nCount; nCur++ )
4237 		{
4238 			SvxIconChoiceCtrlEntry_Impl* pE = (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject(nCur);
4239 			SetEntryPos( pE->_pEntry, pE->_aPos );
4240 		}
4241 		for( nCur = 0; nCur < nCount; nCur++ )
4242 			delete (SvxIconChoiceCtrlEntry_Impl*)aMovedEntries.GetObject( nCur );
4243 		if( aEntries.Count() )
4244 			aAutoArrangeTimer.Start();
4245 	}
4246 	else if( ePositionMode == IcnViewPositionModeAutoAdjust )
4247 	{
4248 		AdjustEntryAtGrid( 0 );
4249 	}
4250 }
4251 
4252 void SvxIconChoiceCtrl_Impl::SetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4253 	SvxIconChoiceCtrlEntry* pPredecessor )
4254 {
4255 	if( !IsAutoArrange() )
4256 		return;
4257 
4258 	if( pEntry == pPredecessor )
4259 		return;
4260 
4261 	sal_uLong nPos1 = GetEntryListPos( pEntry );
4262 	if( !pHead )
4263 	{
4264 		if( pPredecessor )
4265 		{
4266 			sal_uLong nPos2 = GetEntryListPos( pPredecessor );
4267 			if( nPos1 == (nPos2 + 1) )
4268 				return; // ist schon Vorgaenger
4269 		}
4270 		else if( !nPos1 )
4271 			return;
4272 	}
4273 
4274 	if( !pHead )
4275 		InitPredecessors();
4276 
4277 	if( !pPredecessor && pHead == pEntry )
4278 		return; // ist schon der Erste
4279 
4280 	sal_Bool bSetHead = sal_False;
4281 	if( !pPredecessor )
4282 	{
4283 		bSetHead = sal_True;
4284 		pPredecessor = pHead->pblink;
4285 	}
4286 	if( pEntry == pHead )
4287 	{
4288 		pHead = pHead->pflink;
4289 		bSetHead = sal_False;
4290 	}
4291 	if( pEntry != pPredecessor )
4292 	{
4293 		pEntry->Unlink();
4294 		pEntry->SetBacklink( pPredecessor );
4295 	}
4296 	if( bSetHead )
4297 		pHead = pEntry;
4298 	pEntry->SetFlags( ICNVIEW_FLAG_PRED_SET );
4299 	aAutoArrangeTimer.Start();
4300 }
4301 
4302 sal_Bool SvxIconChoiceCtrl_Impl::GetEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4303 	SvxIconChoiceCtrlEntry** ppPredecessor )
4304 {
4305 	*ppPredecessor = 0;
4306 	if( !pHead )
4307 		return sal_False;
4308 	DBG_ASSERT(pEntry->pblink,"GetEntryPredecessor: Backward link not set");
4309 	DBG_ASSERT(pEntry->pflink,"GetEntryPredecessor: Forward link not set");
4310 
4311 	if( pEntry == pHead )
4312 	{
4313 		SvxIconChoiceCtrlEntry* pFirst = (SvxIconChoiceCtrlEntry*)aEntries.GetObject(0);
4314 		if( pFirst != pEntry )
4315 			return sal_True;
4316 		return sal_False;
4317 	}
4318 	*ppPredecessor = pEntry->pblink;
4319 	if( !(pEntry->nFlags & ICNVIEW_FLAG_PRED_SET) &&
4320 		(GetEntryListPos( *ppPredecessor ) + 1) == GetEntryListPos( pEntry ))
4321 		return sal_False;
4322 	return sal_True;
4323 }
4324 
4325 SvxIconChoiceCtrlEntry*	SvxIconChoiceCtrl_Impl::FindEntryPredecessor( SvxIconChoiceCtrlEntry* pEntry,
4326 	const Point& rPosTopLeft )
4327 {
4328 	Point aPos( rPosTopLeft ); //TopLeft
4329 	Rectangle aCenterRect( CalcBmpRect( pEntry, &aPos ));
4330 	Point aNewPos( aCenterRect.Center() );
4331 	sal_uLong nGrid = GetPredecessorGrid( aNewPos );
4332 	sal_uLong nCount = aEntries.Count();
4333 	if( nGrid == ULONG_MAX )
4334 		return 0;
4335 	if( nGrid >= nCount )
4336 		nGrid = nCount - 1;
4337 	if( !pHead )
4338 		return (SvxIconChoiceCtrlEntry*)aEntries.GetObject( nGrid );
4339 
4340 	SvxIconChoiceCtrlEntry* pCur = pHead; // Grid 0
4341 	// todo: Liste von hinten aufrollen wenn nGrid > nCount/2
4342 	for( sal_uLong nCur = 0; nCur < nGrid; nCur++ )
4343 		pCur = pCur->pflink;
4344 
4345 	return pCur;
4346 }
4347 
4348 sal_uLong SvxIconChoiceCtrl_Impl::GetPredecessorGrid( const Point& rPos) const
4349 {
4350 	Point aPos( rPos );
4351 	aPos.X() -= LROFFS_WINBORDER;
4352 	aPos.Y() -= TBOFFS_WINBORDER;
4353 	sal_uInt16 nMaxCol = (sal_uInt16)(aVirtOutputSize.Width() / nGridDX);
4354 	if( nMaxCol )
4355 		nMaxCol--;
4356 	sal_uInt16 nGridX = (sal_uInt16)(aPos.X() / nGridDX);
4357 	if( nGridX > nMaxCol )
4358 		nGridX = nMaxCol;
4359 	sal_uInt16 nGridY = (sal_uInt16)(aPos.Y() / nGridDY);
4360 	sal_uInt16 nGridsX = (sal_uInt16)(aOutputSize.Width() / nGridDX);
4361 	sal_uLong nGrid = (nGridY * nGridsX) + nGridX;
4362 	long nMiddle = (nGridX * nGridDX) + (nGridDX / 2);
4363 	if( rPos.X() < nMiddle )
4364 	{
4365 		if( !nGrid )
4366 			nGrid = ULONG_MAX;
4367 		else
4368 			nGrid--;
4369 	}
4370 	return nGrid;
4371 }
4372 
4373 void SvxIconChoiceCtrl_Impl::Flush()
4374 {
4375 	if( aAutoArrangeTimer.IsActive() )
4376 	{
4377 		AutoArrangeHdl( 0 );
4378 	}
4379 }
4380 
4381 sal_Bool SvxIconChoiceCtrl_Impl::RequestHelp( const HelpEvent& rHEvt )
4382 {
4383 	if ( !(rHEvt.GetMode() & HELPMODE_QUICK ) )
4384 		return sal_False;
4385 
4386 	Point aPos( pView->ScreenToOutputPixel(rHEvt.GetMousePosPixel() ) );
4387 	aPos -= pView->GetMapMode().GetOrigin();
4388 	SvxIconChoiceCtrlEntry* pEntry = GetEntry( aPos, sal_True );
4389 
4390 	if ( !pEntry )
4391 		return sal_False;
4392 
4393 	String sQuickHelpText = pEntry->GetQuickHelpText();
4394 	String aEntryText( pView->GetEntryText( pEntry, sal_False ) );
4395 	Rectangle aTextRect( CalcTextRect( pEntry, 0, sal_False, &aEntryText ) );
4396 	if ( ( !aTextRect.IsInside( aPos ) || !aEntryText.Len() ) && !sQuickHelpText.Len() )
4397 		return sal_False;
4398 
4399 	Rectangle aOptTextRect( aTextRect );
4400 	aOptTextRect.Bottom() = LONG_MAX;
4401 	sal_uInt16 nNewFlags = nCurTextDrawFlags;
4402 	nNewFlags &= ~( TEXT_DRAW_CLIP | TEXT_DRAW_ENDELLIPSIS );
4403 	aOptTextRect = pView->GetTextRect( aOptTextRect, aEntryText, nNewFlags );
4404 	if ( aOptTextRect != aTextRect || sQuickHelpText.Len() > 0 )
4405 	{
4406 		//aTextRect.Right() = aTextRect.Left() + aRealSize.Width() + 4;
4407 		Point aPt( aOptTextRect.TopLeft() );
4408 		aPt += pView->GetMapMode().GetOrigin();
4409 		aPt = pView->OutputToScreenPixel( aPt );
4410 		// Border der Tiphilfe abziehen
4411 		aPt.Y() -= 1;
4412 		aPt.X() -= 3;
4413 		aOptTextRect.SetPos( aPt );
4414 		String sHelpText;
4415 		if ( sQuickHelpText.Len() > 0 )
4416 			sHelpText = sQuickHelpText;
4417 		else
4418 			sHelpText = aEntryText;
4419 		Help::ShowQuickHelp( (Window*)pView, aOptTextRect, sHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER );
4420 	}
4421 
4422 	return sal_True;
4423 }
4424 
4425 void SvxIconChoiceCtrl_Impl::ClearColumnList()
4426 {
4427 	if( !pColumns )
4428 		return;
4429 
4430 	const sal_uInt16 nCount = pColumns->Count();
4431 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4432 	{
4433 		SvxIconChoiceCtrlColumnInfo* pInfo = (SvxIconChoiceCtrlColumnInfo*)
4434 			pColumns->GetObject( nCur );
4435 		delete pInfo;
4436 	}
4437 	DELETEZ(pColumns);
4438 }
4439 
4440 void SvxIconChoiceCtrl_Impl::SetColumn( sal_uInt16 nIndex, const SvxIconChoiceCtrlColumnInfo& rInfo)
4441 {
4442 	if( !pColumns )
4443 		pColumns = new SvPtrarr;
4444 	while( pColumns->Count() < nIndex + 1 )
4445 		pColumns->Insert( (void*)0, pColumns->Count() );
4446 
4447 	SvxIconChoiceCtrlColumnInfo* pInfo =
4448 		(SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject(nIndex);
4449 	if( !pInfo )
4450 	{
4451 		pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4452 		pColumns->Insert( (void*)pInfo, nIndex );
4453 	}
4454 	else
4455 	{
4456 		delete pInfo;
4457 		pInfo = new SvxIconChoiceCtrlColumnInfo( rInfo );
4458 		pColumns->Replace( pInfo, nIndex );
4459 	}
4460 
4461 	// HACK(Detail-Modus ist noch nicht vollstaendig implementiert!)
4462 	// dieses Workaround bringts mit einer Spalte zum Fliegen
4463 	if( !nIndex && (nWinBits & WB_DETAILS) )
4464 		nGridDX = pInfo->GetWidth();
4465 
4466 	if( GetUpdateMode() )
4467 		Arrange( IsAutoArrange() );
4468 }
4469 
4470 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetColumn( sal_uInt16 nIndex ) const
4471 {
4472 	if( !pColumns || nIndex >= pColumns->Count() )
4473 		return 0;
4474 	return (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nIndex );
4475 }
4476 
4477 const SvxIconChoiceCtrlColumnInfo* SvxIconChoiceCtrl_Impl::GetItemColumn( sal_uInt16 nSubItem,
4478 	long& rLeft ) const
4479 {
4480 	rLeft = 0;
4481 	if( !pColumns )
4482 		return 0;
4483 	const sal_uInt16 nCount = pColumns->Count();
4484 	const SvxIconChoiceCtrlColumnInfo* pCol = 0;
4485 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4486 	{
4487 		 pCol = (const SvxIconChoiceCtrlColumnInfo*)pColumns->GetObject( nCur );
4488 		if( !pCol || pCol->GetSubItem() == nSubItem )
4489 			return pCol;
4490 		rLeft += pCol->GetWidth();
4491 	}
4492 	return pCol;
4493 }
4494 
4495 void SvxIconChoiceCtrl_Impl::DrawHighlightFrame(
4496 	OutputDevice* pOut, const Rectangle& rBmpRect, sal_Bool bHide )
4497 {
4498 	Rectangle aBmpRect( rBmpRect );
4499 	long nBorder = 2;
4500 	if( aImageSize.Width() < 32 )
4501 		nBorder = 1;
4502 	aBmpRect.Right() += nBorder;
4503 	aBmpRect.Left() -= nBorder;
4504 	aBmpRect.Bottom() += nBorder;
4505 	aBmpRect.Top() -= nBorder;
4506 
4507 	if ( bHide )
4508 		pView->Invalidate( aBmpRect );
4509 	else
4510 	{
4511 		DecorationView aDecoView( pOut );
4512 		sal_uInt16 nDecoFlags;
4513 		if ( bHighlightFramePressed )
4514 			nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_IN;
4515 		else
4516 			nDecoFlags = FRAME_HIGHLIGHT_TESTBACKGROUND | FRAME_HIGHLIGHT_OUT;
4517 		aDecoView.DrawHighlightFrame( aBmpRect, nDecoFlags );
4518 	}
4519 }
4520 
4521 void SvxIconChoiceCtrl_Impl::SetEntryHighlightFrame( SvxIconChoiceCtrlEntry* pEntry,
4522 	sal_Bool bKeepHighlightFlags )
4523 {
4524 	if( pEntry == pCurHighlightFrame )
4525 		return;
4526 
4527 	if( !bKeepHighlightFlags )
4528 		bHighlightFramePressed = sal_False;
4529 
4530 	HideEntryHighlightFrame();
4531 	pCurHighlightFrame = pEntry;
4532 	if( pEntry )
4533 	{
4534 		Rectangle aBmpRect( CalcFocusRect(pEntry) );
4535 		DrawHighlightFrame( pView, aBmpRect, sal_False );
4536 	}
4537 }
4538 
4539 void SvxIconChoiceCtrl_Impl::HideEntryHighlightFrame()
4540 {
4541 	if( !pCurHighlightFrame )
4542 		return;
4543 
4544 	SvxIconChoiceCtrlEntry* pEntry = pCurHighlightFrame;
4545 	pCurHighlightFrame = 0;
4546 	Rectangle aBmpRect( CalcFocusRect(pEntry) );
4547 	DrawHighlightFrame( pView, aBmpRect, sal_True );
4548 }
4549 
4550 void SvxIconChoiceCtrl_Impl::CallSelectHandler( SvxIconChoiceCtrlEntry* )
4551 {
4552 	// Bei aktiviertem Single-Click-Modus sollte der Selektionshandler
4553 	// synchron gerufen werden, weil die Selektion automatisch
4554 	// weggenommen wird, wenn der Mauszeiger nicht mehr das Objekt
4555 	// beruehrt. Es kann sonst zu fehlenden Select-Aufrufen kommen,
4556 	// wenn das Objekt aus einer Mausbewegung heraus selektiert wird,
4557 	// weil beim Ausloesen des Timers der Mauszeiger das Objekt u.U.
4558 	// schon verlassen hat.
4559 	// Fuer spezielle Faelle (=>SfxFileDialog!) koennen synchrone
4560 	// Aufrufe auch per WB_NOASYNCSELECTHDL erzwungen werden.
4561 	if( nWinBits & (WB_NOASYNCSELECTHDL | WB_HIGHLIGHTFRAME) )
4562 	{
4563 		pHdlEntry = 0;
4564 		pView->ClickIcon();
4565 		//pView->Select();
4566 	}
4567 	else
4568 		aCallSelectHdlTimer.Start();
4569 }
4570 
4571 IMPL_LINK( SvxIconChoiceCtrl_Impl, CallSelectHdlHdl, void*, EMPTYARG )
4572 {
4573 	pHdlEntry = 0;
4574 	pView->ClickIcon();
4575 	//pView->Select();
4576 	return 0;
4577 }
4578 
4579 Point SvxIconChoiceCtrl_Impl::GetPopupMenuPosPixel() const
4580 {
4581 	Point aResult;
4582 	if( !GetSelectionCount() )
4583 		return aResult;
4584 
4585 	SvxIconChoiceCtrlEntry* pEntry = GetCurEntry();
4586 	if( !pEntry || !pEntry->IsSelected() )
4587 	{
4588 		sal_uLong nNext;
4589 		pEntry = GetFirstSelectedEntry( nNext );
4590 	}
4591 	if( pEntry )
4592 	{
4593 		Rectangle aRect( ((SvxIconChoiceCtrl_Impl*)this)->CalcBmpRect( pEntry ) );
4594 		aResult = aRect.Center();
4595 		aResult = pView->GetPixelPos( aResult );
4596 	}
4597 	return aResult;
4598 }
4599 
4600 void SvxIconChoiceCtrl_Impl::SetOrigin( const Point& rPos, sal_Bool bDoNotUpdateWallpaper )
4601 {
4602 	MapMode aMapMode( pView->GetMapMode() );
4603 	aMapMode.SetOrigin( rPos );
4604 	pView->SetMapMode( aMapMode );
4605 	if( !bDoNotUpdateWallpaper )
4606 	{
4607 		sal_Bool bScrollable = pView->GetBackground().IsScrollable();
4608 		if( pView->HasBackground() && !bScrollable )
4609 		{
4610 			Rectangle aRect( GetOutputRect());
4611 			Wallpaper aPaper( pView->GetBackground() );
4612 			aPaper.SetRect( aRect );
4613 			pView->SetBackground( aPaper );
4614 		}
4615 	}
4616 }
4617 
4618 sal_uLong SvxIconChoiceCtrl_Impl::GetGridCount( const Size& rSize, sal_Bool bCheckScrBars,
4619 	sal_Bool bSmartScrBar ) const
4620 {
4621 	Size aSize( rSize );
4622 	if( bCheckScrBars && aHorSBar.IsVisible() )
4623 		aSize.Height() -= nHorSBarHeight;
4624 	else if( bSmartScrBar && (nWinBits & WB_ALIGN_LEFT) )
4625 		aSize.Height() -= nHorSBarHeight;
4626 
4627 	if( bCheckScrBars && aVerSBar.IsVisible() )
4628 		aSize.Width() -= nVerSBarWidth;
4629 	else if( bSmartScrBar && (nWinBits & WB_ALIGN_TOP) )
4630 		aSize.Width() -= nVerSBarWidth;
4631 
4632 	if( aSize.Width() < 0 )
4633 		aSize.Width() = 0;
4634 	if( aSize.Height() < 0 )
4635 		aSize.Height() = 0;
4636 
4637 	return IcnGridMap_Impl::GetGridCount( aSize, (sal_uInt16)nGridDX, (sal_uInt16)nGridDY );
4638 }
4639 
4640 sal_Bool SvxIconChoiceCtrl_Impl::HandleShortCutKey( const KeyEvent& rKEvt )
4641 {
4642 	StopEditTimer();
4643 
4644 	sal_Bool		bRet = sal_False;
4645 
4646 	DBG_ASSERT( rKEvt.GetKeyCode().IsMod2(), "*SvxIconChoiceCtrl_Impl::HandleShortCutKey(): no <ALT> pressed!?" );
4647 
4648 	sal_Unicode	cChar = rKEvt.GetCharCode();
4649 	sal_uLong		nPos = (sal_uLong)-1;
4650 
4651 	if( cChar && IsMnemonicChar( cChar, nPos ) )
4652 	{
4653 		// shortcut is clicked
4654 		SvxIconChoiceCtrlEntry* pNewCursor = GetEntry( nPos );
4655 		SvxIconChoiceCtrlEntry* pOldCursor = pCursor;
4656 		if( pNewCursor != pOldCursor )
4657 		{
4658 			SetCursor_Impl( pOldCursor, pNewCursor, sal_False, sal_False, sal_False );
4659 
4660 			if( pNewCursor != NULL )
4661 			{
4662 				pHdlEntry = pNewCursor;
4663 				pCurHighlightFrame = pHdlEntry;
4664 				pView->ClickIcon();
4665 				pCurHighlightFrame = NULL;
4666 			}
4667 		}
4668 		bRet = sal_True;
4669 	}
4670 
4671 	return bRet;
4672 }
4673 
4674 // -----------------------------------------------------------------------
4675 
4676 void SvxIconChoiceCtrl_Impl::CallEventListeners( sal_uLong nEvent, void* pData )
4677 {
4678     pView->CallImplEventListeners( nEvent, pData );
4679 }
4680 
4681 
4682