xref: /aoo41x/main/svtools/source/contnr/svimpicn.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 #ifndef _METRIC_HXX
33 #include <vcl/metric.hxx>
34 #endif
35 #include <vcl/svapp.hxx>
36 #ifdef DBG_UTIL
37 #include <vcl/sound.hxx>
38 #endif
39 
40 #include <svtools/svlbox.hxx>
41 #include <svtools/svicnvw.hxx>
42 #include <svimpicn.hxx>
43 #ifndef _SVLBITM_HXX
44 #include <svtools/svlbitm.hxx>
45 #endif
46 #include <svl/svarray.hxx>
47 
48 
49 
50 #define VIEWMODE_ICON 	0x0001	// Text unter Bitmap
51 #define VIEWMODE_NAME 	0x0002  // Text rechts neben Bitmap
52 #define VIEWMODE_TEXT 	0x0004  // Text ohne Bitmap
53 
54 #define DD_SCROLL_PIXEL 10
55 
56 // alle Angaben in Pixel
57 
58 #define ICONVIEW_OFFS_BMP_STRING	3
59 
60 // fuer das Bounding-Rectangle
61 #define LROFFS_BOUND				2
62 #define TBOFFS_BOUND				2
63 
64 // fuer das Focus-Rectangle um Icons
65 #define LROFFS_ICON					2
66 #define TBOFFS_ICON					2
67 
68 #define NAMEVIEW_OFFS_BMP_STRING	3
69 
70 // Abstaende von Fensterraendern
71 #define LROFFS_WINBORDER			4
72 #define TBOFFS_WINBORDER			4
73 
74 // Breitenoffset Highlight-Rect bei Text
75 #define LROFFS_TEXT					2
76 
77 
78 #define ICNVIEWDATA(xPtr) (SvIcnVwDataEntry*)(pView->GetViewDataEntry(xPtr))
79 #define ICNVIEWDATA2(xPtr) (SvIcnVwDataEntry*)(pView->pView->GetViewDataEntry(xPtr))
80 
81 //--------------------------------------------------------------------------
82 //--------------------------------------------------------------------------
83 //--------------------------------------------------------------------------
84 // -------------------------------------------------------------------------
85 // Hilfsfunktionen von Thomas Hosemann zur mehrzeiligen Ausgabe von
86 // Strings. Die Funktionen werden spaeter in StarView integriert.
87 // -------------------------------------------------------------------------
88 //--------------------------------------------------------------------------
89 //--------------------------------------------------------------------------
90 //--------------------------------------------------------------------------
91 
92 // keine doppelten Defines
93 #ifdef TEXT_DRAW_CLIP
94 #undef TEXT_DRAW_CLIP
95 #endif
96 #ifdef TEXT_DRAW_MULTILINE
97 #undef TEXT_DRAW_MULTILINE
98 #endif
99 #ifdef TEXT_DRAW_WORDBREAK
100 #undef TEXT_DRAW_WORDBREAK
101 #endif
102 
103 // #define TEXT_DRAW_DISABLE           ((sal_uInt16)0x0001)
104 // #define TEXT_DRAW_3DLOOK            ((sal_uInt16)0x0002)
105 // #define TEXT_DRAW_MNEMONIC          ((sal_uInt16)0x0004)
106 #define TEXT_DRAW_LEFT              ((sal_uInt16)0x0010)
107 #define TEXT_DRAW_CENTER            ((sal_uInt16)0x0020)
108 #define TEXT_DRAW_RIGHT             ((sal_uInt16)0x0040)
109 #define TEXT_DRAW_TOP               ((sal_uInt16)0x0080)
110 #define TEXT_DRAW_VCENTER           ((sal_uInt16)0x0100)
111 #define TEXT_DRAW_BOTTOM            ((sal_uInt16)0x0200)
112 #define TEXT_DRAW_ENDELLIPSIS       ((sal_uInt16)0x0400)
113 #define TEXT_DRAW_PATHELLIPSIS      ((sal_uInt16)0x0800)
114 #define TEXT_DRAW_CLIP              ((sal_uInt16)0x1000)
115 #define TEXT_DRAW_MULTILINE         ((sal_uInt16)0x2000)
116 #define TEXT_DRAW_WORDBREAK         ((sal_uInt16)0x4000)
117 
118 XubString GetEllipsisString( OutputDevice* pDev,
119 							const XubString& rStr, long nMaxWidth,
120 							sal_uInt16 nStyle = TEXT_DRAW_ENDELLIPSIS )
121 {
122 	XubString aStr = rStr;
123 
124 	if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
125 	{
126 		sal_uInt16 nIndex = pDev->GetTextBreak( rStr, nMaxWidth );
127 		if ( nIndex != STRING_LEN )
128 		{
129 			aStr.Erase( nIndex );
130 			if ( nIndex > 1 )
131 			{
132 				aStr.AppendAscii("...");
133 				while ( aStr.Len() &&
134 						(pDev->GetTextWidth( aStr ) > nMaxWidth) )
135 				{
136 					if ( (nIndex > 1) || (nIndex == aStr.Len()) )
137 						nIndex--;
138 					aStr.Erase( nIndex, 1 );
139 				}
140 			}
141 
142 			if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) )
143 				aStr += rStr.GetChar( 0 );
144 		}
145 	}
146 
147 	return aStr;
148 }
149 
150 class TextLineInfo
151 {
152 private:
153 	long        mnWidth;
154 	sal_uInt16      mnIndex;
155 	sal_uInt16      mnLen;
156 
157 public:
158 				TextLineInfo( long nWidth, sal_uInt16 nIndex, sal_uInt16 nLen )
159 				{
160 					mnWidth = nWidth;
161 					mnIndex = nIndex;
162 					mnLen   = nLen;
163 				}
164 
165 	long        GetWidth() const { return mnWidth; }
166 	sal_uInt16      GetIndex() const { return mnIndex; }
167 	sal_uInt16      GetLen() const { return mnLen; }
168 };
169 
170 #define MULTITEXTLINEINFO_RESIZE    16
171 typedef TextLineInfo* PTextLineInfo;
172 
173 class MultiTextLineInfo
174 {
175 private:
176 	PTextLineInfo*      mpLines;
177 	sal_uInt16              mnLines;
178 	sal_uInt16              mnSize;
179 
180 public:
181 						MultiTextLineInfo();
182 						~MultiTextLineInfo();
183 
184 	void                AddLine( TextLineInfo* pLine );
185 	void                Clear();
186 
187 	TextLineInfo*       GetLine( sal_uInt16 nLine ) const
188 							{ return mpLines[nLine]; }
189 	sal_uInt16              Count() const { return mnLines; }
190 
191 private:
192 						MultiTextLineInfo( const MultiTextLineInfo& );
193 	MultiTextLineInfo&  operator=( const MultiTextLineInfo& );
194 };
195 
196 MultiTextLineInfo::MultiTextLineInfo()
197 {
198 	mpLines         = new PTextLineInfo[MULTITEXTLINEINFO_RESIZE];
199 	mnLines         = 0;
200 	mnSize          = MULTITEXTLINEINFO_RESIZE;
201 }
202 
203 MultiTextLineInfo::~MultiTextLineInfo()
204 {
205 	for ( sal_uInt16 i = 0; i < mnLines; i++ )
206 		delete mpLines[i];
207 	delete [] mpLines;
208 }
209 
210 void MultiTextLineInfo::AddLine( TextLineInfo* pLine )
211 {
212 	if ( mnSize == mnLines )
213 	{
214 		mnSize += MULTITEXTLINEINFO_RESIZE;
215 		PTextLineInfo* pNewLines = new PTextLineInfo[mnSize];
216 		memcpy( pNewLines, mpLines, mnLines*sizeof(PTextLineInfo) );
217 		mpLines = pNewLines;
218 	}
219 
220 	mpLines[mnLines] = pLine;
221 	mnLines++;
222 }
223 
224 void MultiTextLineInfo::Clear()
225 {
226 	for ( sal_uInt16 i = 0; i < mnLines; i++ )
227 		delete mpLines[i];
228 	mnLines = 0;
229 }
230 
231 // -----------------------------------------------------------------------
232 
233 long GetTextLines( OutputDevice* pDev, MultiTextLineInfo& rLineInfo,
234 				   long nWidth, const XubString& rStr,
235 				   sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK )
236 {
237 	rLineInfo.Clear();
238 	if ( !rStr.Len() )
239 		return 0;
240 	if ( nWidth <= 0 )
241 		nWidth = 1;
242 
243 	sal_uInt16          nStartPos       = 0;                // Start-Position der Zeile
244 	sal_uInt16          nLastLineLen    = 0;                // Zeilenlaenge bis zum vorherigen Wort
245 	sal_uInt16          nLastWordPos    = 0;                // Position des letzten Wortanfangs
246 	sal_uInt16          i               = 0;
247 	sal_uInt16          nPos;                               // StartPositon der Zeile (nur Temp)
248 	sal_uInt16          nLen;                               // Laenge der Zeile (nur Temp)
249 	sal_uInt16          nStrLen         = rStr.Len();
250 	long            nMaxLineWidth   = 0;                // Maximale Zeilenlaenge
251 	long            nLineWidth;                         // Aktuelle Zeilenlaenge
252 	long            nLastLineWidth  = 0;                // Zeilenlaenge der letzten Zeile
253 	xub_Unicode          c;
254 	xub_Unicode          c2;
255 	const xub_Unicode*   pStr       = rStr.GetBuffer();
256 	sal_Bool            bHardBreak      = sal_False;
257 
258 	do
259 	{
260 		c = pStr[i];
261 
262 		// Auf Zeilenende ermitteln
263 		if ( (c == _CR) || (c == _LF) )
264 			bHardBreak = sal_True;
265 		else
266 			bHardBreak = sal_False;
267 
268 		// Testen, ob ein Wortende erreicht ist
269 		if ( bHardBreak || (i == nStrLen) ||
270 			 (((c == ' ') || (c == '-')) && (nStyle & TEXT_DRAW_WORDBREAK)) )
271 		{
272 			nLen = i-nStartPos;
273 			if ( c == '-' )
274 				nLen++;
275 			nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
276 
277 			// Findet ein Zeilenumbruch statt
278 			if ( bHardBreak || (i == nStrLen) ||
279 				((nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK)) )
280 			{
281 				nPos = nStartPos;
282 
283 				if ( (nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK) )
284 				{
285 					nLineWidth      = nLastLineWidth;
286 					nLen            = nLastLineLen;
287 					nStartPos       = nLastWordPos;
288 					nLastLineLen    = i-nStartPos;
289 					nLastWordPos    = nStartPos+nLastLineLen+1;
290 					if ( c == '-' )
291 						nLastLineLen++;
292 					else if ( bHardBreak && (i > nStartPos) )
293 						i--;
294 				}
295 				else
296 				{
297 					nStartPos = i;
298 					// Zeilenende-Zeichen und '-' beruecksichtigen
299 					if ( bHardBreak )
300 					{
301 						nStartPos++;
302 						c2 = pStr[i+1];
303 						if ( (c != c2) && ((c2 == _CR) || (c2 == _LF)) )
304 						{
305 							nStartPos++;
306 							i++;
307 						}
308 					}
309 					else if ( c != '-' )
310 						nStartPos++;
311 					nLastWordPos    = nStartPos;
312 					nLastLineLen    = 0;
313 				}
314 
315 				if ( nLineWidth > nMaxLineWidth )
316 					nMaxLineWidth = nLineWidth;
317 
318 				if ( nLen || bHardBreak  )
319 					rLineInfo.AddLine( new TextLineInfo( nLineWidth, nPos, nLen ) );
320 
321 				// Testen, ob aktuelles Wort noch auf die Zeile passt,
322 				// denn ansonsten mueessen wir es auftrennen
323 				if ( nLastLineLen )
324 				{
325 					nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
326 					if ( nLineWidth > nWidth )
327 					{
328 						// Wenn ein Wortumbruch in einem Wort stattfindet,
329 						// ist die maximale Zeilenlaenge die Laenge
330 						// des laengsten Wortes
331 						if ( nLineWidth > nMaxLineWidth )
332 							nMaxLineWidth = nLineWidth;
333 
334 						// Solange Wort auftrennen, bis es auf eine Zeile passt
335 						do
336 						{
337 							nPos = pDev->GetTextBreak( rStr, nWidth, nStartPos, nLastLineLen );
338 							nLen = nPos-nStartPos;
339 							if ( !nLen )
340 							{
341 								nPos++;
342 								nLen++;
343 							}
344 							nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
345 							rLineInfo.AddLine( new TextLineInfo( nLineWidth, nStartPos, nLen ) );
346 							nStartPos       = nPos;
347 							nLastLineLen = nLastLineLen - nLen;
348 							nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
349 						}
350 						while ( nLineWidth > nWidth );
351 					}
352 					nLastLineWidth = nLineWidth;
353 
354 					// Bei Stringende muessen wir die letzte Zeile auch noch
355 					// dranhaengen
356 					if ( (i == nStrLen) && nLastLineLen )
357 						rLineInfo.AddLine( new TextLineInfo( nLastLineWidth, nStartPos, nLastLineLen ) );
358 				}
359 				else
360 					nLastLineWidth = 0;
361 			}
362 			else
363 			{
364 				nLastLineWidth  = nLineWidth;
365 				nLastLineLen    = nLen;
366 				nLastWordPos    = nStartPos+nLastLineLen;
367 				if ( c != '-' )
368 					nLastWordPos++;
369 			}
370 		}
371 
372 		i++;
373 	}
374 	while ( i <= nStrLen );
375 
376 	return nMaxLineWidth;
377 }
378 
379 // -----------------------------------------------------------------------
380 
381 sal_uInt16 GetTextLines( OutputDevice* pDev, const Rectangle& rRect,
382 					 const XubString& rStr,
383 					 sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK,
384 					 long* pMaxWidth = NULL )
385 {
386 	MultiTextLineInfo aMultiLineInfo;
387 	long nMaxWidth = GetTextLines( pDev, aMultiLineInfo,
388 								   rRect.GetWidth(), rStr, nStyle );
389 	if ( pMaxWidth )
390 		*pMaxWidth = nMaxWidth;
391 	return aMultiLineInfo.Count();
392 }
393 
394 // -----------------------------------------------------------------------
395 
396 Rectangle GetTextRect( OutputDevice* pDev, const Rectangle& rRect,
397 					   const XubString& rStr,
398 					   sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK )
399 {
400 	Rectangle           aRect = rRect;
401 	sal_uInt16              nLines;
402 	long                nWidth = rRect.GetWidth();
403 	long                nMaxWidth;
404 	long                nTextHeight;
405 
406 	if ( nStyle & TEXT_DRAW_MULTILINE )
407 	{
408 		MultiTextLineInfo   aMultiLineInfo;
409 		TextLineInfo*       pLineInfo;
410 		sal_uInt16              nFormatLines;
411 
412 		nMaxWidth = 0;
413 		GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
414 		nFormatLines = aMultiLineInfo.Count();
415 		nTextHeight = pDev->GetTextHeight();
416 		nLines = (sal_uInt16)(aRect.GetHeight()/nTextHeight);
417 		if ( nFormatLines <= nLines )
418 			nLines = nFormatLines;
419 		else
420 		{
421 			if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) )
422 				nLines = nFormatLines;
423 			else
424 				nMaxWidth = nWidth;
425 		}
426 		for ( sal_uInt16 i = 0; i < nLines; i++ )
427 		{
428 			pLineInfo = aMultiLineInfo.GetLine( i );
429 			if ( pLineInfo->GetWidth() > nMaxWidth )
430 				nMaxWidth = pLineInfo->GetWidth();
431 		}
432 	}
433 	else
434 	{
435 		nLines          = 1;
436 		nMaxWidth       = pDev->GetTextWidth( rStr );
437 		nTextHeight     = pDev->GetTextHeight();
438 		if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ENDELLIPSIS) )
439 			nMaxWidth = nWidth;
440 	}
441 
442 	if ( nStyle & TEXT_DRAW_RIGHT )
443 		aRect.Left() = aRect.Right()-nMaxWidth+1;
444 	else if ( nStyle & TEXT_DRAW_CENTER )
445 	{
446 		aRect.Left() += (nWidth-nMaxWidth)/2;
447 		aRect.Right() = aRect.Left()+nMaxWidth-1;
448 	}
449 	else
450 		aRect.Right() = aRect.Left()+nMaxWidth-1;
451 
452 	if ( nStyle & TEXT_DRAW_BOTTOM )
453 		aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1;
454 	else if ( nStyle & TEXT_DRAW_VCENTER )
455 	{
456 		aRect.Top()   += (aRect.GetHeight()-(nTextHeight*nLines))/2;
457 		aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
458 	}
459 	else
460 		aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
461 
462 	return aRect;
463 }
464 
465 // -----------------------------------------------------------------------
466 
467 void DrawText( OutputDevice* pDev, const Rectangle& rRect,
468 			   const XubString& rStr, sal_uInt16 nStyle = 0 )
469 {
470 	if ( !rStr.Len() || rRect.IsEmpty() )
471 		return;
472 
473 	Point       aPos    = rRect.TopLeft();
474 	long        nWidth  = rRect.GetWidth();
475 	long        nHeight = rRect.GetHeight();
476 	FontAlign   eAlign  = pDev->GetFont().GetAlign();
477 
478 	if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) )
479 		return;
480 
481 	// Mehrzeiligen Text behandeln wir anders
482 	if ( nStyle & TEXT_DRAW_MULTILINE )
483 	{
484 		String              aLastLine;
485 		Region              aOldRegion;
486 		MultiTextLineInfo   aMultiLineInfo;
487 		TextLineInfo*       pLineInfo;
488 		long                nTextHeight     = pDev->GetTextHeight();
489 		long                nMaxTextWidth;
490 		sal_uInt16              i;
491 		sal_uInt16              nLines          = (sal_uInt16)(nHeight/nTextHeight);
492 		sal_uInt16              nFormatLines;
493 		sal_Bool                bIsClipRegion = sal_False;
494 		nMaxTextWidth = GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
495 
496 		nFormatLines = aMultiLineInfo.Count();
497 		if ( nFormatLines > nLines )
498 		{
499 			if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
500 			{
501 				// Letzte Zeile zusammenbauen und kuerzen
502 				nFormatLines = nLines-1;
503 				pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
504 				aLastLine = rStr.Copy( pLineInfo->GetIndex() );
505 				aLastLine.ConvertLineEnd( LINEEND_LF );
506 				aLastLine.SearchAndReplace( _LF, ' ' );
507 				aLastLine = GetEllipsisString( pDev, aLastLine, nWidth, nStyle );
508 				nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
509 				nStyle |= TEXT_DRAW_TOP;
510 			}
511 		}
512 		else
513 		{
514 			if ( nMaxTextWidth <= nWidth )
515 				nStyle &= ~TEXT_DRAW_CLIP;
516 		}
517 
518 		// Clipping setzen
519 		if ( nStyle & TEXT_DRAW_CLIP )
520 		{
521 			bIsClipRegion = pDev->IsClipRegion();
522 			if ( bIsClipRegion )
523 			{
524 				aOldRegion = pDev->GetClipRegion();
525 				pDev->IntersectClipRegion( rRect );
526 			}
527 			else
528 			{
529 				Region aRegion( rRect );
530 				pDev->SetClipRegion( aRegion );
531 			}
532 		}
533 
534 		// Vertikales Alignment
535 		if ( nStyle & TEXT_DRAW_BOTTOM )
536 			aPos.Y() += nHeight-(nFormatLines*nTextHeight);
537 		else if ( nStyle & TEXT_DRAW_VCENTER )
538 			aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
539 
540 		// Font Alignment
541 		if ( eAlign == ALIGN_BOTTOM )
542 			aPos.Y() += nTextHeight;
543 		else if ( eAlign == ALIGN_BASELINE )
544 			aPos.Y() += pDev->GetFontMetric().GetAscent();
545 
546 		// Alle Zeilen ausgeben, bis auf die letzte
547 		for ( i = 0; i < nFormatLines; i++ )
548 		{
549 			pLineInfo = aMultiLineInfo.GetLine( i );
550 			if ( nStyle & TEXT_DRAW_RIGHT )
551 				aPos.X() += nWidth-pLineInfo->GetWidth();
552 			else if ( nStyle & TEXT_DRAW_CENTER )
553 				aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
554 			pDev->DrawText( aPos, rStr, pLineInfo->GetIndex(), pLineInfo->GetLen() );
555 			aPos.Y() += nTextHeight;
556 			aPos.X() = rRect.Left();
557 		}
558 
559 		// Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
560 		// da die Zeile gekuerzt wurde
561 		if ( aLastLine.Len() )
562 			pDev->DrawText( aPos, aLastLine );
563 
564 		// Clipping zuruecksetzen
565 		if ( nStyle & TEXT_DRAW_CLIP )
566 		{
567 			if ( bIsClipRegion )
568 				pDev->SetClipRegion( aOldRegion );
569 			else
570 				pDev->SetClipRegion();
571 		}
572 	}
573 	else
574 	{
575 		XubString    aStr = rStr;
576 		Size        aTextSize(pDev->GetTextWidth( aStr ), pDev->GetTextHeight());
577 
578 		// Evt. Text kuerzen
579 		if ( aTextSize.Width() > nWidth )
580 		{
581 			if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
582 			{
583 				aStr = GetEllipsisString( pDev, rStr, nWidth, nStyle );
584 				nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
585 				nStyle |= TEXT_DRAW_LEFT;
586 				aTextSize.Width() = pDev->GetTextWidth(aStr);
587 			}
588 		}
589 		else
590 		{
591 			if ( aTextSize.Height() <= nHeight )
592 				nStyle &= ~TEXT_DRAW_CLIP;
593 		}
594 
595 		// Vertikales Alignment
596 		if ( nStyle & TEXT_DRAW_RIGHT )
597 			aPos.X() += nWidth-aTextSize.Width();
598 		else if ( nStyle & TEXT_DRAW_CENTER )
599 			aPos.X() += (nWidth-aTextSize.Width())/2;
600 
601 		// Font Alignment
602 		if ( eAlign == ALIGN_BOTTOM )
603 			aPos.Y() += aTextSize.Height();
604 		else if ( eAlign == ALIGN_BASELINE )
605 			aPos.Y() += pDev->GetFontMetric().GetAscent();
606 
607 		if ( nStyle & TEXT_DRAW_BOTTOM )
608 			aPos.Y() += nHeight-aTextSize.Height();
609 		else if ( nStyle & TEXT_DRAW_VCENTER )
610 			aPos.Y() += (nHeight-aTextSize.Height())/2;
611 
612 		if ( nStyle & TEXT_DRAW_CLIP )
613 		{
614 			sal_Bool bIsClipRegion = pDev->IsClipRegion();
615 			if ( bIsClipRegion )
616 			{
617 				Region aOldRegion = pDev->GetClipRegion();
618 				pDev->IntersectClipRegion( rRect );
619 				pDev->DrawText( aPos, aStr );
620 				pDev->SetClipRegion( aOldRegion );
621 			}
622 			else
623 			{
624 				Region aRegion( rRect );
625 				pDev->SetClipRegion( aRegion );
626 				pDev->DrawText( aPos, aStr );
627 				pDev->SetClipRegion();
628 			}
629 		}
630 		else
631 			pDev->DrawText( aPos, aStr );
632 	}
633 }
634 
635 // -----------------------------------------------------------------------
636 
637 
638 //--------------------------------------------------------------------------
639 //--------------------------------------------------------------------------
640 //--------------------------------------------------------------------------
641 
642 
643 #define DRAWTEXT_FLAGS (TEXT_DRAW_CENTER|TEXT_DRAW_TOP|TEXT_DRAW_ENDELLIPSIS|\
644 						TEXT_DRAW_CLIP|TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK)
645 
646 
647 class ImpIcnCursor
648 {
649 	SvImpIconView*	pView;
650 	SvPtrarr* 		pColumns;
651 	SvPtrarr* 		pRows;
652 	sal_Bool*			pGridMap;
653 	long			nGridDX, nGridDY;
654 	long			nGridCols, nGridRows;
655 	long			nCols;
656 	long			nRows;
657 	short 			nDeltaWidth;
658 	short 			nDeltaHeight;
659 	SvLBoxEntry* 	pCurEntry;
660 	void 			SetDeltas();
661 	void 			ImplCreate();
662 	void 			Create() {	if( !pColumns )	ImplCreate(); }
663 
664 	sal_uInt16 			GetSortListPos( SvPtrarr* pList, long nValue, int bVertical);
665 	SvLBoxEntry* 	SearchCol(sal_uInt16 nCol,sal_uInt16 nTop,sal_uInt16 nBottom,sal_uInt16 nPref,
666 						sal_Bool bDown, sal_Bool bSimple );
667 	SvLBoxEntry* 	SearchRow(sal_uInt16 nRow,sal_uInt16 nRight,sal_uInt16 nLeft,sal_uInt16 nPref,
668 						sal_Bool bRight, sal_Bool bSimple );
669 
670 	void			ExpandGrid();
671 	void			CreateGridMap();
672 	// Rueckgabe sal_False: Eintrag liegt nicht in der GridMap. rGridx,y werden
673 	// dann an nGridCols, nGridRows geclippt
674 	sal_Bool	 		GetGrid( const Point& rDocPos, sal_uInt16& rGridX, sal_uInt16& rGridY ) const;
675 	void			SetGridUsed( sal_uInt16 nDX, sal_uInt16 nDY, sal_Bool bUsed )
676 					{
677 						pGridMap[ (nDY * nGridCols) + nDX ] = bUsed;
678 					}
679 	sal_Bool			IsGridUsed( sal_uInt16 nDX, sal_uInt16 nDY )
680 					{
681 						return pGridMap[ (nDY * nGridCols) + nDX ];
682 					}
683 public:
684 					ImpIcnCursor( SvImpIconView* pOwner );
685 					~ImpIcnCursor();
686 	void 			Clear( sal_Bool bGridToo = sal_True );
687 
688 	// fuer Cursortravelling usw.
689 	SvLBoxEntry* 	GoLeftRight( SvLBoxEntry*, sal_Bool bRight );
690 	SvLBoxEntry* 	GoUpDown( SvLBoxEntry*, sal_Bool bDown );
691 
692 	// Rueckgaebe: sal_False == Das leere Rect steht hinter dem letzten
693 	// Eintrag; d.h. beim naechsten Einfuegen ergibt sich das naechste
694 	// leere Rechteck durch Addition. Hinweis: Das Rechteck kann dann
695 	// ausserhalb des View-Space liegen
696 	sal_Bool			FindEmptyGridRect( Rectangle& rRect );
697 
698 	// Erzeugt fuer jede Zeile (Hoehe=nGridDY) eine nach BoundRect.Left()
699 	// sortierte Liste der Eintraege, die in ihr stehen. Eine Liste kann
700 	// leer sein. Die Listen gehen in das Eigentum des Rufenden ueber und
701 	// muessen mit DestroyGridAdjustData geloescht werden
702 	void			CreateGridAjustData( SvPtrarr& pLists, SvLBoxEntry* pRow=0);
703 	static void 	DestroyGridAdjustData( SvPtrarr& rLists );
704 	void			SetGridUsed( const Rectangle&, sal_Bool bUsed = sal_True );
705 };
706 
707 
708 
709 
710 SvImpIconView::SvImpIconView( SvIconView* pCurView, SvLBoxTreeList* pTree,
711 	WinBits i_nWinStyle ) :
712 	aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
713 	aHorSBar( pCurView, WB_DRAG | WB_HSCROLL )
714 {
715 	pView = pCurView;
716 	pModel = pTree;
717 	pCurParent = 0;
718 	pZOrderList = new SvPtrarr;
719 	SetStyle( i_nWinStyle );
720 	nHorDist = 0;
721 	nVerDist = 0;
722 	nFlags = 0;
723 	nCurUserEvent = 0;
724 	nMaxVirtWidth = 200;
725 	pDDRefEntry = 0;
726 	pDDDev = 0;
727 	pDDBufDev = 0;
728 	pDDTempDev = 0;
729 	eTextMode = ShowTextShort;
730 	pImpCursor = new ImpIcnCursor( this );
731 
732 	aVerSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollUpDownHdl ) );
733 	aHorSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollLeftRightHdl ) );
734 	nHorSBarHeight = aHorSBar.GetSizePixel().Height();
735 	nVerSBarWidth = aVerSBar.GetSizePixel().Width();
736 
737 	aMouseMoveTimer.SetTimeout( 20 );
738 	aMouseMoveTimer.SetTimeoutHdl(LINK(this,SvImpIconView,MouseMoveTimeoutHdl));
739 
740 	aEditTimer.SetTimeout( 800 );
741 	aEditTimer.SetTimeoutHdl(LINK(this,SvImpIconView,EditTimeoutHdl));
742 
743 	Clear( sal_True );
744 }
745 
746 SvImpIconView::~SvImpIconView()
747 {
748 	StopEditTimer();
749 	CancelUserEvent();
750 	delete pZOrderList;
751 	delete pImpCursor;
752 	delete pDDDev;
753 	delete pDDBufDev;
754 	delete pDDTempDev;
755 	ClearSelectedRectList();
756 }
757 
758 void SvImpIconView::Clear( sal_Bool bInCtor )
759 {
760 	StopEditTimer();
761 	CancelUserEvent();
762 	nMaxBmpWidth = 0;
763 	nMaxBmpHeight = 0;
764 	nMaxTextWidth = 0;
765 	bMustRecalcBoundingRects = sal_False;
766 	nMaxBoundHeight = 0;
767 
768 	//XXX
769 	nFlags |= F_GRID_INSERT;
770 	nFlags &= ~F_PAINTED;
771 	SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
772 	pCursor = 0;
773 	if( !bInCtor )
774 	{
775 		pImpCursor->Clear();
776 		aVirtOutputSize.Width() = 0;
777 		aVirtOutputSize.Height() = 0;
778 		pZOrderList->Remove(0,pZOrderList->Count());
779 		MapMode aMapMode( pView->GetMapMode());
780 		aMapMode.SetOrigin( Point() );
781 		pView->SetMapMode( aMapMode );
782 		if( pView->IsUpdateMode() )
783 			pView->Invalidate();
784 	}
785 	AdjustScrollBars();
786 }
787 
788 void SvImpIconView::SetStyle( const WinBits i_nWinStyle )
789 {
790 	nViewMode = VIEWMODE_TEXT;
791 	if( i_nWinStyle & WB_NAME )
792 		nViewMode = VIEWMODE_NAME;
793 	if( i_nWinStyle & WB_ICON )
794 		nViewMode = VIEWMODE_ICON;
795 }
796 
797 
798 IMPL_LINK( SvImpIconView, ScrollUpDownHdl, ScrollBar *, pScrollBar )
799 {
800 	pView->EndEditing( sal_True );
801 	// Pfeil hoch: delta=-1; Pfeil runter: delta=+1
802 	Scroll( 0, pScrollBar->GetDelta(), sal_True );
803 	return 0;
804 }
805 
806 IMPL_LINK( SvImpIconView, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
807 {
808 	pView->EndEditing( sal_True );
809 	// Pfeil links: delta=-1; Pfeil rechts: delta=+1
810 	Scroll( pScrollBar->GetDelta(), 0, sal_True );
811 	return 0;
812 }
813 
814 void SvImpIconView::ChangedFont()
815 {
816 	StopEditTimer();
817 	ImpArrange();
818 }
819 
820 
821 void SvImpIconView::CheckAllSizes()
822 {
823 	nMaxTextWidth = 0;
824 	nMaxBmpWidth = 0;
825 	nMaxBmpHeight = 0;
826 	SvLBoxEntry* pEntry = pModel->First();
827 	while( pEntry )
828 	{
829 		CheckSizes( pEntry );
830 		pEntry = pModel->Next( pEntry );
831 	}
832 }
833 
834 void SvImpIconView::CheckSizes( SvLBoxEntry* pEntry,
835 	const SvIcnVwDataEntry* pViewData )
836 {
837 	Size aSize;
838 
839 	if( !pViewData )
840 		pViewData = ICNVIEWDATA(pEntry);
841 
842 	SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
843 	if( pStringItem )
844 	{
845 		aSize = GetItemSize( pView, pEntry, pStringItem, pViewData );
846 		if( aSize.Width() > nMaxTextWidth )
847 		{
848 			nMaxTextWidth = aSize.Width();
849 			if( !(nFlags & F_GRIDMODE ) )
850 				bMustRecalcBoundingRects = sal_True;
851 		}
852 	}
853 	SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
854 	if( pBmpItem )
855 	{
856 		aSize = GetItemSize( pView, pEntry, pBmpItem, pViewData );
857 		if( aSize.Width() > nMaxBmpWidth )
858 		{
859 			nMaxBmpWidth = aSize.Width();
860 			nMaxBmpWidth += (2*LROFFS_ICON);
861 			if( !(nFlags & F_GRIDMODE ) )
862 				bMustRecalcBoundingRects = sal_True;
863 		}
864 		if( aSize.Height() > nMaxBmpHeight )
865 		{
866 			nMaxBmpHeight = aSize.Height();
867 			nMaxBmpHeight += (2*TBOFFS_ICON);;
868 			if( !(nFlags & F_GRIDMODE ) )
869 				bMustRecalcBoundingRects = sal_True;
870 		}
871 	}
872 }
873 
874 void SvImpIconView::EntryInserted( SvLBoxEntry* pEntry )
875 {
876 	if( pModel->GetParent(pEntry) == pCurParent )
877 	{
878 		StopEditTimer();
879 		DBG_ASSERT(pZOrderList->GetPos(pEntry)==0xffff,"EntryInserted:ZOrder?");
880 		pZOrderList->Insert( pEntry, pZOrderList->Count() );
881 		if( nFlags & F_GRIDMODE	)
882 			pImpCursor->Clear( sal_False );
883 		else
884 			pImpCursor->Clear( sal_True );
885 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
886 		CheckSizes( pEntry, pViewData );
887 		if( pView->IsUpdateMode() )
888 		{
889 			FindBoundingRect( pEntry, pViewData );
890 			PaintEntry( pEntry, pViewData );
891 		}
892 		else
893 			InvalidateBoundingRect( pViewData->aRect );
894 	}
895 }
896 
897 void SvImpIconView::RemovingEntry( SvLBoxEntry* pEntry )
898 {
899 	if( pModel->GetParent(pEntry) == pCurParent)
900 	{
901 		StopEditTimer();
902 		DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"RemovingEntry:ZOrder?");
903 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
904 		if( IsBoundingRectValid( pViewData->aRect ) )
905 		{
906 			// bei gueltigem Bounding-Rect muss in EntryRemoved eine
907 			// Sonderbehandlung erfolgen
908 			nFlags |= F_ENTRY_REMOVED;
909 			pView->Invalidate( pViewData->aRect );
910 		}
911 		if( pEntry == pCursor )
912 		{
913 			SvLBoxEntry* pNewCursor = GetNewCursor();
914 			ShowCursor( sal_False );
915 			pCursor = 0; // damit er nicht deselektiert wird
916 			SetCursor( pNewCursor );
917 		}
918 		sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry );
919 		pZOrderList->Remove( nPos, 1 );
920 		pImpCursor->Clear();
921 	}
922 }
923 
924 void SvImpIconView::EntryRemoved()
925 {
926 	if( (nFlags & (F_ENTRY_REMOVED | F_PAINTED)) == (F_ENTRY_REMOVED | F_PAINTED))
927 	{
928 		// Ein Eintrag mit gueltigem BoundRect wurde geloescht und wir
929 		// haben schon mal gepaintet. In diesem Fall muessen wir die
930 		// Position des naechsten Eintrags, der eingefuegt wird oder noch
931 		// kein gueltiges BoundRect hat, "suchen" d.h. ein "Loch" in
932 		// der View auffuellen.
933 		nFlags &= ~( F_ENTRY_REMOVED | F_GRID_INSERT );
934 	}
935 }
936 
937 
938 void SvImpIconView::MovingEntry( SvLBoxEntry* pEntry )
939 {
940 	DBG_ASSERT(pEntry,"MovingEntry: 0!");
941 	pNextCursor = 0;
942 	StopEditTimer();
943 	if( pModel->GetParent(pEntry) == pCurParent )
944 	{
945 		DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"MovingEntry:ZOrder?");
946 		nFlags |= F_MOVING_SIBLING;
947 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
948 		if( IsBoundingRectValid( pViewData->aRect ) )
949 			pView->Invalidate( pViewData->aRect );
950 		// falls Eintrag seinen Parent wechselt vorsichtshalber
951 		// die neue Cursorposition berechnen
952 		if( pEntry == pCursor )
953 			pNextCursor = GetNewCursor();
954 		pImpCursor->Clear();
955 	}
956 }
957 
958 
959 void SvImpIconView::EntryMoved( SvLBoxEntry* pEntry )
960 {
961 	ShowCursor( sal_False );
962 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
963 	if( pModel->GetParent(pEntry)==pCurParent )
964 	{
965 		if( nFlags & F_MOVING_SIBLING )
966 		{
967 			// die Neu-Positionierung eines Eintrags bei D&D innerhalb
968 			// einer IconView findet bereits in NotifyMoving statt
969 			// (MovingEntry/EntryMoved wird dann nicht mehr gerufen)
970 			ToTop( pEntry );
971 		}
972 		else
973 		{
974 			pImpCursor->Clear();
975 			pZOrderList->Insert( pEntry, pZOrderList->Count() );
976 			DBG_ASSERT(pZOrderList->Count()==pModel->GetChildCount(pCurParent),"EntryMoved:Bad zorder count");
977 			FindBoundingRect( pEntry, pViewData );
978 		}
979 		PaintEntry( pEntry, pViewData );
980 	}
981 	else
982 	{
983 		if( pEntry == pCursor )
984 		{
985 			DBG_ASSERT(pNextCursor,"EntryMoved: Next cursor bad");
986 			SetCursor( pNextCursor );
987 		}
988 		pImpCursor->Clear();
989 		sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry );
990 		pZOrderList->Remove( nPos, 1 );
991 		pView->Select( pEntry, sal_False );
992 		// wenn er nochmal in dieser View auftaucht, muss sein
993 		// Bounding-Rect neu berechnet werden
994 		InvalidateBoundingRect( pViewData->aRect );
995 	}
996 	nFlags &= (~F_MOVING_SIBLING);
997 }
998 
999 void SvImpIconView::TreeInserted( SvLBoxEntry* pEntry )
1000 {
1001 	EntryMoved( pEntry ); // vorlaeufig
1002 }
1003 
1004 void SvImpIconView::EntryExpanded( SvLBoxEntry* )
1005 {
1006 }
1007 
1008 void SvImpIconView::EntryCollapsed( SvLBoxEntry*)
1009 {
1010 }
1011 
1012 void SvImpIconView::CollapsingEntry( SvLBoxEntry* )
1013 {
1014 }
1015 
1016 void SvImpIconView::EntrySelected( SvLBoxEntry* pEntry, sal_Bool bSelect )
1017 {
1018 	if( pModel->GetParent(pEntry) != pCurParent  )
1019 		return;
1020 
1021 	// bei SingleSelection dafuer sorgen, dass der Cursor immer
1022 	// auf dem (einzigen) selektierten Eintrag steht
1023 	if( bSelect && pCursor &&
1024 		pView->GetSelectionMode() == SINGLE_SELECTION &&
1025 		pEntry != pCursor )
1026 	{
1027 		SetCursor( pEntry );
1028 		DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1029 	}
1030 	// bei Gummibandselektion ist uns das zu teuer
1031 	if( !(nFlags & F_RUBBERING ))
1032 		ToTop( pEntry );
1033 	if( pView->IsUpdateMode() )
1034 	{
1035 		if( pEntry == pCursor )
1036 			ShowCursor( sal_False );
1037 		if( nFlags & F_RUBBERING )
1038 			PaintEntry( pEntry );
1039 		else
1040 			pView->Invalidate( GetBoundingRect( pEntry ) );
1041 		if( pEntry == pCursor )
1042 			ShowCursor( sal_True );
1043 	}
1044 }
1045 
1046 void SvImpIconView::SetNextEntryPos(const Point& rPos)
1047 {
1048 	aPrevBoundRect.SetPos( rPos );
1049 	aPrevBoundRect.Right() = LONG_MAX;	// dont know
1050 }
1051 
1052 Point SvImpIconView::FindNextEntryPos( const Size& rBoundSize )
1053 {
1054 	if( nFlags & F_GRIDMODE )
1055 	{
1056 		if( nFlags & F_GRID_INSERT )
1057 		{
1058 			if( aPrevBoundRect.Right() != LONG_MAX )
1059 			{
1060 				// passt der naechste Entry noch in die Zeile ?
1061 				long nNextWidth = aPrevBoundRect.Right() + nGridDX + LROFFS_WINBORDER;
1062 				if( nNextWidth > aVirtOutputSize.Width() )
1063 				{
1064 					// darf aVirtOutputSize verbreitert werden ?
1065 					if( nNextWidth < nMaxVirtWidth )
1066 					{
1067 						// verbreitern & in Zeile aufnehmen
1068 						aPrevBoundRect.Left() += nGridDX;
1069 					}
1070 					else
1071 					{
1072 						// erhoehen & neue Zeile beginnen
1073 						aPrevBoundRect.Top() += nGridDY;
1074 						aPrevBoundRect.Left() = LROFFS_WINBORDER;
1075 					}
1076 				}
1077 				else
1078 				{
1079 					// in die Zeile aufnehmen
1080 					aPrevBoundRect.Left() += nGridDX;
1081 				}
1082 			}
1083 			aPrevBoundRect.SetSize( Size( nGridDX, nGridDY ) );
1084 		}
1085 		else
1086 		{
1087 			if( !pImpCursor->FindEmptyGridRect( aPrevBoundRect ) )
1088 			{
1089 				// mitten in den Entries gibts keine Loecher mehr,
1090 				// wir koennen also wieder ins "Fast Insert" springen
1091 				nFlags |= F_GRID_INSERT;
1092 			}
1093 		}
1094 	}
1095 	else
1096 	{
1097 		if( aPrevBoundRect.Right() != LONG_MAX )
1098 		{
1099 			// passt der naechste Entry noch in die Zeile ?
1100 			long nNextWidth=aPrevBoundRect.Right()+rBoundSize.Width()+LROFFS_BOUND+nHorDist;
1101 			if( nNextWidth > aVirtOutputSize.Width() )
1102 			{
1103 				// darf aVirtOutputSize verbreitert werden ?
1104 				if( nNextWidth < nMaxVirtWidth )
1105 				{
1106 					// verbreitern & in Zeile aufnehmen
1107 					aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
1108 					aPrevBoundRect.Left() += nHorDist;
1109 				}
1110 				else
1111 				{
1112 					// erhoehen & neue Zeile beginnen
1113 					aPrevBoundRect.Top() += nMaxBoundHeight + nVerDist + TBOFFS_BOUND;
1114 					aPrevBoundRect.Left() = LROFFS_WINBORDER;
1115 				}
1116 			}
1117 			else
1118 			{
1119 				// in die Zeile aufnehmen
1120 				aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
1121 				aPrevBoundRect.Left() += nHorDist;
1122 			}
1123 		}
1124 		aPrevBoundRect.SetSize( rBoundSize );
1125 	}
1126 	return aPrevBoundRect.TopLeft();
1127 }
1128 
1129 void SvImpIconView::ResetVirtSize()
1130 {
1131 	StopEditTimer();
1132 	aVirtOutputSize.Width() = 0;
1133 	aVirtOutputSize.Height() = 0;
1134 	sal_Bool bLockedEntryFound = sal_False;
1135 	nFlags &= (~F_GRID_INSERT);
1136 	SvLBoxEntry* pCur = pModel->FirstChild( pCurParent );
1137 	while( pCur )
1138 	{
1139 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
1140 		if( pViewData->IsEntryPosLocked() )
1141 		{
1142 			// VirtSize u.a. anpassen
1143 			if( !IsBoundingRectValid( pViewData->aRect ) )
1144 				FindBoundingRect( pCur, pViewData );
1145 			else
1146 				AdjustVirtSize( pViewData->aRect );
1147 			bLockedEntryFound = sal_True;
1148 		}
1149 		else
1150 			InvalidateBoundingRect( pViewData->aRect );
1151 
1152 		pCur = pModel->NextSibling( pCur );
1153 	}
1154 	if( !bLockedEntryFound )
1155 	{
1156 		//XXX
1157 		nFlags |= F_GRID_INSERT;
1158 	}
1159 
1160 	SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
1161 	pImpCursor->Clear();
1162 }
1163 
1164 
1165 void SvImpIconView::AdjustVirtSize( const Rectangle& rRect )
1166 {
1167 	long nHeightOffs = 0;
1168 	long nWidthOffs = 0;
1169 
1170 	if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
1171 		nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
1172 
1173 	if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
1174 		nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
1175 
1176 	if( nWidthOffs || nHeightOffs )
1177 	{
1178 		Range aRange;
1179 		aVirtOutputSize.Width() += nWidthOffs;
1180 		aRange.Max() = aVirtOutputSize.Width();
1181 		aHorSBar.SetRange( aRange );
1182 
1183 		aVirtOutputSize.Height() += nHeightOffs;
1184 		aRange.Max() = aVirtOutputSize.Height();
1185 		aVerSBar.SetRange( aRange );
1186 
1187 		pImpCursor->Clear();
1188 		AdjustScrollBars();
1189 	}
1190 }
1191 
1192 void SvImpIconView::Arrange()
1193 {
1194 	nMaxVirtWidth = aOutputSize.Width();
1195 	ImpArrange();
1196 }
1197 
1198 void SvImpIconView::ImpArrange()
1199 {
1200 	StopEditTimer();
1201 	ShowCursor( sal_False );
1202 	ResetVirtSize();
1203 	bMustRecalcBoundingRects = sal_False;
1204 	MapMode aMapMode( pView->GetMapMode());
1205 	aMapMode.SetOrigin( Point() );
1206 	pView->SetMapMode( aMapMode );
1207 	CheckAllSizes();
1208 	RecalcAllBoundingRectsSmart();
1209 	pView->Invalidate();
1210 	ShowCursor( sal_True );
1211 }
1212 
1213 void SvImpIconView::Paint( const Rectangle& rRect )
1214 {
1215 	if( !pView->IsUpdateMode() )
1216 		return;
1217 
1218 #if defined(DBG_UTIL) && defined(OV_DRAWGRID)
1219 	if( nFlags & F_GRIDMODE )
1220 	{
1221 		Color aOldColor = pView->GetLineColor();
1222 		Color aNewColor( COL_BLACK );
1223 		pView->SetLineColor( aNewColor );
1224 		Point aOffs( pView->GetMapMode().GetOrigin());
1225 		Size aXSize( pView->GetOutputSizePixel() );
1226 		for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
1227 		{
1228 			Point aStart( nDX+LROFFS_BOUND, 0 );
1229 			Point aEnd( nDX+LROFFS_BOUND, aXSize.Height());
1230 			aStart -= aOffs;
1231 			aEnd -= aOffs;
1232 			pView->DrawLine( aStart, aEnd );
1233 		}
1234 		for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
1235 		{
1236 			Point aStart( 0, nDY+TBOFFS_BOUND );
1237 			Point aEnd( aXSize.Width(), nDY+TBOFFS_BOUND );
1238 			aStart -= aOffs;
1239 			aEnd -= aOffs;
1240 			pView->DrawLine( aStart, aEnd );
1241 		}
1242 		pView->SetLineColor( aOldColor );
1243 	}
1244 #endif
1245 	nFlags |= F_PAINTED;
1246 
1247 	if( !(pModel->HasChilds( pCurParent ) ))
1248 		return;
1249 	if( !pCursor )
1250 		pCursor = pModel->FirstChild( pCurParent );
1251 
1252 	sal_uInt16 nCount = pZOrderList->Count();
1253 	if( !nCount )
1254 		return;
1255 
1256 	SvPtrarr* pNewZOrderList = new SvPtrarr;
1257 	SvPtrarr* pPaintedEntries = new SvPtrarr;
1258 
1259 	sal_uInt16 nPos = 0;
1260 	while( nCount )
1261 	{
1262 		SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
1263 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
1264 		const Rectangle& rBoundRect = GetBoundingRect( pEntry, pViewData );
1265 		if( rRect.IsOver( rBoundRect ) )
1266 		{
1267 			PaintEntry( pEntry, rBoundRect.TopLeft(), pViewData );
1268 			// Eintraege, die neu gezeichnet werden, auf Top setzen
1269 			pPaintedEntries->Insert( pEntry, pPaintedEntries->Count() );
1270 		}
1271 		else
1272 			pNewZOrderList->Insert( pEntry, pNewZOrderList->Count() );
1273 
1274 		nCount--;
1275 		nPos++;
1276 	}
1277 	delete pZOrderList;
1278 	pZOrderList = pNewZOrderList;
1279 	nCount = pPaintedEntries->Count();
1280 	if( nCount )
1281 	{
1282 		for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
1283 			pZOrderList->Insert( pPaintedEntries->GetObject( nCur ),pZOrderList->Count());
1284 	}
1285 	delete pPaintedEntries;
1286 
1287 	Rectangle aRect;
1288 	if( GetResizeRect( aRect ))
1289 		PaintResizeRect( aRect );
1290 }
1291 
1292 sal_Bool SvImpIconView::GetResizeRect( Rectangle& rRect )
1293 {
1294 	if( aHorSBar.IsVisible() && aVerSBar.IsVisible() )
1295 	{
1296 		const MapMode& rMapMode = pView->GetMapMode();
1297 		Point aOrigin( rMapMode.GetOrigin());
1298 		aOrigin *= -1;
1299 		aOrigin.X() += aOutputSize.Width();
1300 		aOrigin.Y() += aOutputSize.Height();
1301 		rRect.SetPos( aOrigin );
1302 		rRect.SetSize( Size( nVerSBarWidth, nHorSBarHeight));
1303 		return sal_True;
1304 	}
1305 	return sal_False;
1306 }
1307 
1308 void SvImpIconView::PaintResizeRect( const Rectangle& rRect )
1309 {
1310 	const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1311 	Color aNewColor = rStyleSettings.GetFaceColor();
1312 	Color aOldColor = pView->GetFillColor();
1313 	pView->SetFillColor( aNewColor );
1314 	pView->DrawRect( rRect );
1315 	pView->SetFillColor( aOldColor );
1316 }
1317 
1318 void SvImpIconView::RepaintSelectionItems()
1319 {
1320 	DBG_ERROR("RepaintSelectionItems");
1321 	pView->Invalidate(); // vorlaeufig
1322 }
1323 
1324 SvLBoxItem* SvImpIconView::GetItem( SvLBoxEntry* pEntry,
1325 					const Point& rAbsPos )
1326 {
1327 	Rectangle aRect;
1328 	SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
1329 	if( pStringItem )
1330 	{
1331 		aRect = CalcTextRect( pEntry, pStringItem );
1332 		if( aRect.IsInside( rAbsPos ) )
1333 			return pStringItem;
1334 	}
1335 	SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1336 	if( pBmpItem )
1337 	{
1338 		aRect = CalcBmpRect( pEntry );
1339 		if( aRect.IsInside( rAbsPos ) )
1340 			return pBmpItem;
1341 	}
1342 	return 0;
1343 }
1344 
1345 void SvImpIconView::CalcDocPos( Point& aMaeuschenPos )
1346 {
1347 	aMaeuschenPos -= pView->GetMapMode().GetOrigin();
1348 }
1349 
1350 void SvImpIconView::MouseButtonDown( const MouseEvent& rMEvt)
1351 {
1352 	StopEditTimer();
1353 	pView->GrabFocus();
1354 	Point aDocPos( rMEvt.GetPosPixel() );
1355 	if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
1356 		return;
1357 	CalcDocPos( aDocPos );
1358 	SvLBoxEntry* pEntry = GetEntry( aDocPos );
1359 	if( !pEntry )
1360 	{
1361 		if( pView->GetSelectionMode() != SINGLE_SELECTION )
1362 		{
1363 			if( !rMEvt.IsMod1() )  // Ctrl
1364 			{
1365 				pView->SelectAll( sal_False );
1366 				ClearSelectedRectList();
1367 			}
1368 			else
1369 				nFlags |= F_ADD_MODE;
1370 			nFlags |= F_RUBBERING;
1371 			aCurSelectionRect.SetPos( aDocPos );
1372 			pView->CaptureMouse();
1373 		}
1374 		return;
1375 	}
1376 
1377 	sal_Bool bSelected = pView->IsSelected( pEntry );
1378 	sal_Bool bEditingEnabled = pView->IsInplaceEditingEnabled();
1379 
1380 	if( rMEvt.GetClicks() == 2 )
1381 	{
1382 		DeselectAllBut( pEntry );
1383 		pView->pHdlEntry = pEntry;
1384 		pView->DoubleClickHdl();
1385 	}
1386 	else
1387 	{
1388 		// Inplace-Editing ?
1389 		if( rMEvt.IsMod2() )  // Alt?
1390 		{
1391 			if( bEditingEnabled )
1392 			{
1393 				SvLBoxItem* pItem = GetItem(pEntry,aDocPos);
1394 				if( pItem )
1395 					pView->EditingRequest( pEntry, pItem, aDocPos);
1396 			}
1397 		}
1398 		else if( pView->GetSelectionMode() == SINGLE_SELECTION )
1399 		{
1400 			DeselectAllBut( pEntry );
1401 			SetCursor( pEntry );
1402 			pView->Select( pEntry, sal_True );
1403 			if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
1404 				rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
1405 			{
1406 				nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1407 			}
1408 		}
1409 		else
1410 		{
1411 			if( !rMEvt.GetModifier() )
1412 			{
1413 				if( !bSelected )
1414 				{
1415 					DeselectAllBut( pEntry );
1416 					SetCursor( pEntry );
1417 					pView->Select( pEntry, sal_True );
1418 				}
1419 				else
1420 				{
1421 					// erst im Up deselektieren, falls Move per D&D!
1422 					nFlags |= F_DOWN_DESELECT;
1423 					if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
1424 						rMEvt.IsLeft())
1425 					{
1426 						nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1427 					}
1428 				}
1429 			}
1430 			else if( rMEvt.IsMod1() )
1431 				nFlags |= F_DOWN_CTRL;
1432 		}
1433 	}
1434 }
1435 
1436 void SvImpIconView::MouseButtonUp( const MouseEvent& rMEvt )
1437 {
1438 	aMouseMoveTimer.Stop();
1439 	pView->ReleaseMouse();
1440 	// HACK, da Einar noch nicht PrepareCommandEvent aufruft
1441 	if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
1442 		nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1443 
1444 	if( nFlags & F_RUBBERING )
1445 	{
1446 		aMouseMoveTimer.Stop();
1447 		AddSelectedRect( aCurSelectionRect );
1448 		HideSelectionRect();
1449 		nFlags &= ~(F_RUBBERING | F_ADD_MODE);
1450 	}
1451 
1452 	SvLBoxEntry* pEntry = pView->GetEntry( rMEvt.GetPosPixel(), sal_True );
1453 	if( pEntry )
1454 	{
1455 		if( nFlags & F_DOWN_CTRL )
1456 		{
1457 			// Ctrl & MultiSelection
1458 			ToggleSelection( pEntry );
1459 			SetCursor( pEntry );
1460 		}
1461 		else if( nFlags & F_DOWN_DESELECT )
1462 		{
1463 			DeselectAllBut( pEntry );
1464 			SetCursor( pEntry );
1465 			pView->Select( pEntry, sal_True );
1466 		}
1467 	}
1468 
1469 	nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1470 	if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
1471 	{
1472 		StartEditTimer();
1473 		nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
1474 	}
1475 }
1476 
1477 void SvImpIconView::MouseMove( const MouseEvent& rMEvt )
1478 {
1479 	if( nFlags & F_RUBBERING )
1480 	{
1481 		const Point& rPosPixel = rMEvt.GetPosPixel();
1482 		if( !aMouseMoveTimer.IsActive() )
1483 		{
1484 			aMouseMoveEvent = rMEvt;
1485 			aMouseMoveTimer.Start();
1486 			// ausserhalb des Fensters liegende Move-Events muessen
1487 			// vom Timer kommen, damit die Scrollgeschwindigkeit
1488 			// unabhaengig von Mausbewegungen ist.
1489 			if( rPosPixel.X() < 0 || rPosPixel.Y() < 0 )
1490 				return;
1491 			const Size& rSize = pView->GetOutputSizePixel();
1492 			if( rPosPixel.X() > rSize.Width() || rPosPixel.Y() > rSize.Height())
1493 				return;
1494 		}
1495 
1496 		if( &rMEvt != &aMouseMoveEvent )
1497 			aMouseMoveEvent = rMEvt;
1498 
1499 		long nScrollDX, nScrollDY;
1500 
1501 		CalcScrollOffsets(rMEvt.GetPosPixel(),nScrollDX,nScrollDY,sal_False );
1502 		sal_Bool bSelRectHidden = sal_False;
1503 		if( nScrollDX || nScrollDY )
1504 		{
1505 			HideSelectionRect();
1506 			bSelRectHidden = sal_True;
1507 			pView->Scroll( nScrollDX, nScrollDY );
1508 		}
1509 		Point aDocPos( rMEvt.GetPosPixel() );
1510 		aDocPos = pView->PixelToLogic( aDocPos );
1511 		Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
1512 		if( aRect != aCurSelectionRect )
1513 		{
1514 			HideSelectionRect();
1515 			bSelRectHidden = sal_True;
1516 			sal_Bool bAdd = (nFlags & F_ADD_MODE) ? sal_True : sal_False;
1517 			SelectRect( aRect, bAdd, &aSelectedRectList );
1518 		}
1519 		if( bSelRectHidden )
1520 			DrawSelectionRect( aRect );
1521 	}
1522 }
1523 
1524 sal_Bool SvImpIconView::KeyInput( const KeyEvent& rKEvt )
1525 {
1526 	StopEditTimer();
1527 	sal_Bool bKeyUsed = sal_True;
1528 	sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1();
1529 	sal_Bool bInAddMode = (sal_Bool)((nFlags & F_ADD_MODE) != 0);
1530 	int bDeselAll = (pView->GetSelectionMode() != SINGLE_SELECTION) &&
1531 					!bInAddMode;
1532 	SvLBoxEntry* pNewCursor;
1533 	sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1534 	switch( nCode )
1535 	{
1536 		case KEY_UP:
1537 			if( pCursor )
1538 			{
1539 				MakeVisible( pCursor );
1540 				pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False);
1541 				if( pNewCursor )
1542 				{
1543 					if( bDeselAll )
1544 						pView->SelectAll( sal_False );
1545 					ShowCursor( sal_False );
1546 					MakeVisible( pNewCursor );
1547 					SetCursor( pNewCursor );
1548 					if( !bInAddMode )
1549 						pView->Select( pCursor, sal_True );
1550 				}
1551 				else
1552 				{
1553 					Rectangle aRect( GetBoundingRect( pCursor ) );
1554 					if( aRect.Top())
1555 					{
1556 						aRect.Bottom() -= aRect.Top();
1557 						aRect.Top() = 0;
1558 						MakeVisible( aRect );
1559 					}
1560 				}
1561 			}
1562 			break;
1563 
1564 		case KEY_DOWN:
1565 			if( pCursor )
1566 			{
1567 				pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True );
1568 				if( pNewCursor )
1569 				{
1570 					MakeVisible( pCursor );
1571 					if( bDeselAll )
1572 						pView->SelectAll( sal_False );
1573 					ShowCursor( sal_False );
1574 					MakeVisible( pNewCursor );
1575 					SetCursor( pNewCursor );
1576 					if( !bInAddMode )
1577 						pView->Select( pCursor, sal_True );
1578 				}
1579 			}
1580 			break;
1581 
1582 		case KEY_RIGHT:
1583 			if( pCursor )
1584 			{
1585 				pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True );
1586 				if( pNewCursor )
1587 				{
1588 					MakeVisible( pCursor );
1589 					if( bDeselAll )
1590 						pView->SelectAll( sal_False );
1591 					ShowCursor( sal_False );
1592 					MakeVisible( pNewCursor );
1593 					SetCursor( pNewCursor );
1594 					if( !bInAddMode )
1595 						pView->Select( pCursor, sal_True );
1596 				}
1597 			}
1598 			break;
1599 
1600 		case KEY_LEFT:
1601 			if( pCursor )
1602 			{
1603 				MakeVisible( pCursor );
1604 				pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False );
1605 				if( pNewCursor )
1606 				{
1607 					if( bDeselAll )
1608 						pView->SelectAll( sal_False );
1609 					ShowCursor( sal_False );
1610 					MakeVisible( pNewCursor );
1611 					SetCursor( pNewCursor );
1612 					if( !bInAddMode )
1613 						pView->Select( pCursor, sal_True );
1614 				}
1615 				else
1616 				{
1617 					Rectangle aRect( GetBoundingRect(pCursor));
1618 					if( aRect.Left() )
1619 					{
1620 						aRect.Right() -= aRect.Left();
1621 						aRect.Left() = 0;
1622 						MakeVisible( aRect );
1623 					}
1624 				}
1625 			}
1626 			break;
1627 
1628 		case KEY_ESCAPE:
1629 			if( nFlags & F_RUBBERING )
1630 			{
1631 				HideSelectionRect();
1632 				pView->SelectAll( sal_False );
1633 				nFlags &= ~F_RUBBERING;
1634 			}
1635 			break;
1636 
1637 		case KEY_F8:
1638 			if( rKEvt.GetKeyCode().IsShift() )
1639 			{
1640 				if( nFlags & F_ADD_MODE )
1641 					nFlags &= (~F_ADD_MODE);
1642 				else
1643 					nFlags |= F_ADD_MODE;
1644 			}
1645 			break;
1646 
1647 #ifdef OS2
1648 		case KEY_F9:
1649 			if( rKEvt.GetKeyCode().IsShift() )
1650 			{
1651 				if( pCursor && pView->IsInplaceEditingEnabled() )
1652 					pView->EditEntry( pCursor );
1653 			}
1654 			break;
1655 #endif
1656 
1657 		case KEY_SPACE:
1658 			if( pCursor )
1659 			{
1660 				ToggleSelection( pCursor );
1661 			}
1662 			break;
1663 
1664 
1665 		case KEY_PAGEDOWN:
1666 			break;
1667 		case KEY_PAGEUP:
1668 			break;
1669 
1670 		case KEY_ADD:
1671 		case KEY_DIVIDE :
1672 			if( bMod1 )
1673 				pView->SelectAll( sal_True );
1674 			break;
1675 
1676 		case KEY_SUBTRACT:
1677 		case KEY_COMMA :
1678 			if( bMod1 )
1679 				pView->SelectAll( sal_False );
1680 			break;
1681 
1682 		case KEY_RETURN:
1683 			if( bMod1 )
1684 			{
1685 				if( pCursor && pView->IsInplaceEditingEnabled() )
1686 					pView->EditEntry( pCursor );
1687 			}
1688 			break;
1689 
1690 		default:
1691 			bKeyUsed = sal_False;
1692 
1693 	}
1694 	return bKeyUsed;
1695 }
1696 
1697 
1698 void SvImpIconView::PositionScrollBars( long nRealWidth, long nRealHeight )
1699 {
1700 	// hor scrollbar
1701 	Point aPos( 0, nRealHeight );
1702 	aPos.Y() -= nHorSBarHeight;
1703 
1704 #ifdef OS2
1705 	aPos.Y()++;
1706 #endif
1707 	if( aHorSBar.GetPosPixel() != aPos )
1708 		aHorSBar.SetPosPixel( aPos );
1709 
1710 	// ver scrollbar
1711 	aPos.X() = nRealWidth; aPos.Y() = 0;
1712 	aPos.X() -= nVerSBarWidth;
1713 
1714 #if defined(WNT)
1715 	aPos.X()++;
1716 	aPos.Y()--;
1717 #endif
1718 
1719 #ifdef OS2
1720 	aPos.Y()--;
1721 	aPos.X()++;
1722 #endif
1723 
1724 	if( aVerSBar.GetPosPixel() != aPos )
1725 		aVerSBar.SetPosPixel( aPos );
1726 }
1727 
1728 
1729 
1730 void SvImpIconView::AdjustScrollBars()
1731 {
1732 	long nVirtHeight = aVirtOutputSize.Height();
1733 	long nVirtWidth = aVirtOutputSize.Width();
1734 
1735 	Size aOSize( pView->Control::GetOutputSizePixel() );
1736 	long nRealHeight = aOSize.Height();
1737 	long nRealWidth = aOSize.Width();
1738 
1739 	PositionScrollBars( nRealWidth, nRealHeight );
1740 
1741 	const MapMode& rMapMode = pView->GetMapMode();
1742 	Point aOrigin( rMapMode.GetOrigin() );
1743 
1744 	long nVisibleWidth;
1745 	if( nRealWidth > nVirtWidth )
1746 		nVisibleWidth = nVirtWidth + aOrigin.X();
1747 	else
1748 		nVisibleWidth = nRealWidth;
1749 
1750 	long nVisibleHeight;
1751 	if( nRealHeight > nVirtHeight )
1752 		nVisibleHeight = nVirtHeight + aOrigin.Y();
1753 	else
1754 		nVisibleHeight = nRealHeight;
1755 
1756 	bool bVerSBar = (pView->GetStyle() & WB_VSCROLL) ? true : false;
1757 	bool bHorSBar = (pView->GetStyle() & WB_HSCROLL) ? true : false;
1758 
1759 	sal_uInt16 nResult = 0;
1760 	if( nVirtHeight )
1761 	{
1762 		// activate ver scrollbar ?
1763 		if( bVerSBar || ( nVirtHeight > nVisibleHeight) )
1764 		{
1765 			nResult = 0x0001;
1766 			nRealWidth -= nVerSBarWidth;
1767 
1768 			if( nRealWidth > nVirtWidth )
1769 				nVisibleWidth = nVirtWidth + aOrigin.X();
1770 			else
1771 				nVisibleWidth = nRealWidth;
1772 
1773 			nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1774 		}
1775 		// activate hor scrollbar ?
1776 		if( bHorSBar || (nVirtWidth > nVisibleWidth) )
1777 		{
1778 			nResult |= 0x0002;
1779 			nRealHeight -= nHorSBarHeight;
1780 
1781 			if( nRealHeight > nVirtHeight )
1782 				nVisibleHeight = nVirtHeight + aOrigin.Y();
1783 			else
1784 				nVisibleHeight = nRealHeight;
1785 
1786 			// brauchen wir jetzt doch eine senkrechte Scrollbar ?
1787 			if( !(nResult & 0x0001) &&  // nur wenn nicht schon da
1788 				( (nVirtHeight > nVisibleHeight) || bVerSBar) )
1789 			{
1790 				nResult = 3; // both are active
1791 				nRealWidth -= nVerSBarWidth;
1792 
1793 				if( nRealWidth > nVirtWidth )
1794 					nVisibleWidth = nVirtWidth + aOrigin.X();
1795 				else
1796 					nVisibleWidth = nRealWidth;
1797 
1798 				nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1799 			}
1800 		}
1801 	}
1802 
1803 	// size ver scrollbar
1804 	long nThumb = aVerSBar.GetThumbPos();
1805 	Size aSize( nVerSBarWidth, nRealHeight );
1806 #if defined(WNT)
1807 	aSize.Height() += 2;
1808 #endif
1809 #ifdef OS2
1810 	aSize.Height() += 3;
1811 #endif
1812 	if( aSize != aVerSBar.GetSizePixel() )
1813 		aVerSBar.SetSizePixel( aSize );
1814 	aVerSBar.SetVisibleSize( nVisibleHeight );
1815 	aVerSBar.SetPageSize( (nVisibleHeight*75)/100 );
1816 	if( nResult & 0x0001 )
1817 	{
1818 		aVerSBar.SetThumbPos( nThumb );
1819 		aVerSBar.Show();
1820 	}
1821 	else
1822 	{
1823 		aVerSBar.SetThumbPos( 0 );
1824 		aVerSBar.Hide();
1825 	}
1826 
1827 	// size hor scrollbar
1828 	nThumb = aHorSBar.GetThumbPos();
1829 	aSize.Width() = nRealWidth;
1830 	aSize.Height() = nHorSBarHeight;
1831 #if defined(WNT)
1832 	aSize.Width()++;
1833 #endif
1834 #ifdef OS2
1835 	aSize.Width() += 3;
1836 	if( nResult & 0x0001 ) // vertikale Scrollbar ?
1837 		aSize.Width()--;
1838 #endif
1839 #if defined(WNT)
1840 	if( nResult & 0x0001 ) // vertikale Scrollbar ?
1841 	{
1842 		aSize.Width()++;
1843 		nRealWidth++;
1844 	}
1845 #endif
1846 	if( aSize != aHorSBar.GetSizePixel() )
1847 		aHorSBar.SetSizePixel( aSize );
1848 	aHorSBar.SetVisibleSize( nVisibleWidth ); //nRealWidth );
1849 	aHorSBar.SetPageSize( (nVisibleWidth*75)/100 );
1850 	if( nResult & 0x0002 )
1851 	{
1852 		aHorSBar.SetThumbPos( nThumb );
1853 		aHorSBar.Show();
1854 	}
1855 	else
1856 	{
1857 		aHorSBar.SetThumbPos( 0 );
1858 		aHorSBar.Hide();
1859 	}
1860 
1861 #ifdef OS2
1862 	nRealWidth++;
1863 #endif
1864 	aOutputSize.Width() = nRealWidth;
1865 #if defined(WNT)
1866 	if( nResult & 0x0002 ) // hor scrollbar ?
1867 		nRealHeight++; // weil unterer Rand geclippt wird
1868 #endif
1869 #ifdef OS2
1870 	if( nResult & 0x0002 ) // hor scrollbar ?
1871 		nRealHeight++;
1872 #endif
1873 	aOutputSize.Height() = nRealHeight;
1874 }
1875 
1876 void __EXPORT SvImpIconView::Resize()
1877 {
1878 	StopEditTimer();
1879 	Rectangle aRect;
1880 	if( GetResizeRect(aRect) )
1881 		pView->Invalidate( aRect );
1882 	aOutputSize = pView->GetOutputSizePixel();
1883 	pImpCursor->Clear();
1884 
1885 #if 1
1886 	const Size& rSize = pView->Control::GetOutputSizePixel();
1887 	PositionScrollBars( rSize.Width(), rSize.Height() );
1888 	// Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1889 	// Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1890 	// die ScrollBars aufblitzen (SfxExplorerIconView!)
1891 	nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpIconView,UserEventHdl),0);
1892 #else
1893 	AdjustScrollBars();
1894 	if( GetResizeRect(aRect) )
1895 		PaintResizeRect( aRect );
1896 #endif
1897 }
1898 
1899 sal_Bool SvImpIconView::CheckHorScrollBar()
1900 {
1901 	if( !pZOrderList || !aHorSBar.IsVisible() )
1902 		return sal_False;
1903 	const MapMode& rMapMode = pView->GetMapMode();
1904 	Point aOrigin( rMapMode.GetOrigin() );
1905 	if(!(pView->GetStyle() & WB_HSCROLL) && !aOrigin.X() )
1906 	{
1907 		long nWidth = aOutputSize.Width();
1908 		sal_uInt16 nCount = pZOrderList->Count();
1909 		long nMostRight = 0;
1910 		for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
1911 		{
1912 			SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
1913 			long nRight = GetBoundingRect(pEntry).Right();
1914 			if( nRight > nWidth )
1915 				return sal_False;
1916 			if( nRight > nMostRight )
1917 				nMostRight = nRight;
1918 		}
1919 		aHorSBar.Hide();
1920 		aOutputSize.Height() += nHorSBarHeight;
1921 		aVirtOutputSize.Width() = nMostRight;
1922 		aHorSBar.SetThumbPos( 0 );
1923 		Range aRange;
1924 		aRange.Max() = nMostRight - 1;
1925 		aHorSBar.SetRange( aRange  );
1926 		if( aVerSBar.IsVisible() )
1927 		{
1928 			Size aSize( aVerSBar.GetSizePixel());
1929 			aSize.Height() += nHorSBarHeight;
1930 			aVerSBar.SetSizePixel( aSize );
1931 		}
1932 		return sal_True;
1933 	}
1934 	return sal_False;
1935 }
1936 
1937 sal_Bool SvImpIconView::CheckVerScrollBar()
1938 {
1939 	if( !pZOrderList || !aVerSBar.IsVisible() )
1940 		return sal_False;
1941 	const MapMode& rMapMode = pView->GetMapMode();
1942 	Point aOrigin( rMapMode.GetOrigin() );
1943 	if(!(pView->GetStyle() & WB_VSCROLL) && !aOrigin.Y() )
1944 	{
1945 		long nDeepest = 0;
1946 		long nHeight = aOutputSize.Height();
1947 		sal_uInt16 nCount = pZOrderList->Count();
1948 		for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
1949 		{
1950 			SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
1951 			long nBottom = GetBoundingRect(pEntry).Bottom();
1952 			if( nBottom > nHeight )
1953 				return sal_False;
1954 			if( nBottom > nDeepest )
1955 				nDeepest = nBottom;
1956 		}
1957 		aVerSBar.Hide();
1958 		aOutputSize.Width() += nVerSBarWidth;
1959 		aVirtOutputSize.Height() = nDeepest;
1960 		aVerSBar.SetThumbPos( 0 );
1961 		Range aRange;
1962 		aRange.Max() = nDeepest - 1;
1963 		aVerSBar.SetRange( aRange  );
1964 		if( aHorSBar.IsVisible() )
1965 		{
1966 			Size aSize( aHorSBar.GetSizePixel());
1967 			aSize.Width() += nVerSBarWidth;
1968 			aHorSBar.SetSizePixel( aSize );
1969 		}
1970 		return sal_True;
1971 	}
1972 	return sal_False;
1973 }
1974 
1975 
1976 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1977 void SvImpIconView::CheckScrollBars()
1978 {
1979 	CheckVerScrollBar();
1980 	if( CheckHorScrollBar() )
1981 		CheckVerScrollBar();
1982 }
1983 
1984 
1985 void __EXPORT SvImpIconView::GetFocus()
1986 {
1987 	if( pCursor )
1988 	{
1989 		pView->SetEntryFocus( pCursor, sal_True );
1990 		ShowCursor( sal_True );
1991 	}
1992 }
1993 
1994 void __EXPORT SvImpIconView::LoseFocus()
1995 {
1996 	StopEditTimer();
1997 	if( pCursor )
1998 		pView->SetEntryFocus( pCursor,sal_False );
1999 	ShowCursor( sal_False );
2000 }
2001 
2002 void SvImpIconView::UpdateAll()
2003 {
2004 	AdjustScrollBars();
2005 	pImpCursor->Clear();
2006 	pView->Invalidate();
2007 }
2008 
2009 void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
2010 {
2011 	Point aPos( GetEntryPosition( pEntry ) );
2012 	PaintEntry( pEntry, aPos, pViewData );
2013 }
2014 
2015 void SvImpIconView::PaintEmphasis( const Rectangle& rRect, sal_Bool bSelected,
2016 								   sal_Bool bCursored, OutputDevice* pOut )
2017 {
2018 	// HACK fuer D&D
2019 	if( nFlags & F_NO_EMPHASIS )
2020 		return;
2021 
2022 	if( !pOut )
2023 		pOut = pView;
2024 
2025 	// Selektion painten
2026 	Color aOldFillColor =  pOut->GetFillColor();
2027 	Color aOldLineColor =  pOut->GetLineColor();
2028 	Color aNewColor;
2029 	const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
2030 	if( bSelected )
2031 	{
2032 		aNewColor = rStyleSettings.GetHighlightColor();
2033 	}
2034 	else
2035 	{
2036 #ifndef OS2
2037 		aNewColor =rStyleSettings.GetFieldColor();
2038 #else
2039 		aNewColor = pOut->GetBackground().GetColor();
2040 #endif
2041 	}
2042 
2043 	if( bCursored )
2044 	{
2045 		pOut->SetLineColor( Color( COL_BLACK ) );
2046 	}
2047 	pOut->SetFillColor( aNewColor );
2048 	pOut->DrawRect( rRect );
2049 	pOut->SetFillColor( aOldFillColor );
2050 	pOut->SetLineColor( aOldLineColor );
2051 }
2052 
2053 void SvImpIconView::PaintItem( const Rectangle& rRect,
2054 	SvLBoxItem* pItem, SvLBoxEntry* pEntry, sal_uInt16 nPaintFlags,
2055 	OutputDevice* pOut )
2056 {
2057 	if( nViewMode == VIEWMODE_ICON && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
2058 	{
2059 		const String& rStr = ((SvLBoxString*)pItem)->GetText();
2060 		DrawText( pOut, rRect, rStr, DRAWTEXT_FLAGS );
2061 	}
2062 	else
2063 	{
2064 		Point aPos( rRect.TopLeft() );
2065 		const Size& rSize = GetItemSize( pView, pEntry, pItem );
2066 		if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
2067 			aPos.X() += (rRect.GetWidth() - rSize.Width() ) / 2;
2068 		if( nPaintFlags & PAINTFLAG_VER_CENTERED )
2069 			aPos.Y() += (rRect.GetHeight() - rSize.Height() ) / 2;
2070 		pItem->Paint( aPos, *(SvLBox*)pOut, 0, pEntry );
2071 	}
2072 }
2073 
2074 void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, const Point& rPos,
2075 	SvIcnVwDataEntry* pViewData, OutputDevice* pOut )
2076 {
2077 	if( !pView->IsUpdateMode() )
2078 		return;
2079 
2080 	if( !pOut )
2081 		pOut = pView;
2082 
2083 	SvLBoxContextBmp* pBmpItem;
2084 
2085 	pView->PreparePaint( pEntry );
2086 
2087 	if( !pViewData )
2088 		pViewData = ICNVIEWDATA(pEntry);
2089 
2090 	SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
2091 
2092 	sal_Bool bSelected	= pViewData->IsSelected();
2093 	sal_Bool bCursored	= pViewData->IsCursored();
2094 
2095 	Font aTempFont( pOut->GetFont() );
2096 	// waehrend D&D nicht die Fontfarbe wechseln, da sonst auch die
2097 	// Emphasis gezeichnet werden muss! (weisser Adler auf weissem Grund)
2098 	if( bSelected && !(nFlags & F_NO_EMPHASIS) )
2099 	{
2100 		const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
2101 		Font aNewFont( aTempFont );
2102 		aNewFont.SetColor( rStyleSettings.GetHighlightTextColor() );
2103 		pOut->SetFont( aNewFont );
2104 	}
2105 	Rectangle aTextRect( CalcTextRect(pEntry,pStringItem,&rPos,sal_False,pViewData));
2106 	Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos, pViewData ) );
2107 
2108 	switch( nViewMode )
2109 	{
2110 		case VIEWMODE_ICON:
2111 			pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
2112 			PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
2113 			PaintItem( aBmpRect, pBmpItem, pEntry,
2114 				PAINTFLAG_HOR_CENTERED | PAINTFLAG_VER_CENTERED, pOut );
2115 			PaintEmphasis( aTextRect, bSelected, sal_False, pOut );
2116 			PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_HOR_CENTERED, pOut );
2117 			break;
2118 
2119 		case VIEWMODE_NAME:
2120 			pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
2121 			PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
2122 			PaintItem( aBmpRect, pBmpItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
2123 			PaintEmphasis( aTextRect, bSelected, sal_False, pOut );
2124 			PaintItem( aTextRect, pStringItem, pEntry,PAINTFLAG_VER_CENTERED, pOut );
2125 			break;
2126 
2127 		case VIEWMODE_TEXT:
2128 			PaintEmphasis( aTextRect, bSelected, bCursored, pOut );
2129 			PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
2130 			break;
2131 	}
2132 	pOut->SetFont( aTempFont );
2133 }
2134 
2135 void SvImpIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos,
2136 	sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars )
2137 {
2138 	if( pModel->GetParent(pEntry) == pCurParent )
2139 	{
2140 		ShowCursor( sal_False );
2141 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2142 		Rectangle aBoundRect( GetBoundingRect( pEntry, pViewData ));
2143 		pView->Invalidate( aBoundRect );
2144 		ToTop( pEntry );
2145 		if( rPos != aBoundRect.TopLeft() )
2146 		{
2147 			Point aGridOffs = pViewData->aGridRect.TopLeft() -
2148 							  pViewData->aRect.TopLeft();
2149 			pImpCursor->Clear();
2150 			nFlags &= ~F_GRID_INSERT;
2151 			aBoundRect.SetPos( rPos );
2152 			pViewData->aRect = aBoundRect;
2153 			pViewData->aGridRect.SetPos( rPos + aGridOffs );
2154 			AdjustVirtSize( aBoundRect );
2155 		}
2156 		//HACK(Billigloesung, die noch verbessert werden muss)
2157 		if( bAdjustAtGrid )
2158 		{
2159 			AdjustAtGrid( pEntry );
2160 			ToTop( pEntry );
2161 		}
2162 		if( bCheckScrollBars && pView->IsUpdateMode() )
2163 			CheckScrollBars();
2164 
2165 		PaintEntry( pEntry, pViewData );
2166 		ShowCursor( sal_True );
2167 	}
2168 }
2169 
2170 void SvImpIconView::ViewDataInitialized( SvLBoxEntry*)
2171 {
2172 }
2173 
2174 void SvImpIconView::ModelHasEntryInvalidated( SvListEntry* pEntry )
2175 {
2176 	if( pEntry == pCursor )
2177 		ShowCursor( sal_False );
2178 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2179 	pView->Invalidate( pViewData->aRect );
2180 
2181 	if( nFlags & F_GRIDMODE )
2182 		Center( (SvLBoxEntry*)pEntry, pViewData );
2183 	else
2184 		pViewData->aRect.SetSize( CalcBoundingSize(
2185 			(SvLBoxEntry*)pEntry, pViewData ) );
2186 
2187 	ViewDataInitialized( (SvLBoxEntry*)pEntry );
2188 	pView->Invalidate( pViewData->aRect );
2189 	if( pEntry == pCursor )
2190 		ShowCursor( sal_True );
2191 }
2192 
2193 
2194 void SvImpIconView::InvalidateEntry( SvLBoxEntry* pEntry )
2195 {
2196 	const Rectangle& rRect = GetBoundingRect( pEntry );
2197 	pView->Invalidate( rRect );
2198 }
2199 
2200 void SvImpIconView::SetNoSelection()
2201 {
2202 }
2203 
2204 void SvImpIconView::SetDragDropMode( DragDropMode )
2205 {
2206 }
2207 
2208 void SvImpIconView::SetSelectionMode( SelectionMode )
2209 {
2210 }
2211 
2212 sal_Bool SvImpIconView::IsEntryInView( SvLBoxEntry* )
2213 {
2214 	return sal_False;
2215 }
2216 
2217 SvLBoxEntry* SvImpIconView::GetDropTarget( const Point& rPos )
2218 {
2219 	Point aDocPos( rPos );
2220 	CalcDocPos( aDocPos );
2221 	SvLBoxEntry* pTarget = GetEntry( aDocPos );
2222 	if( !pTarget || !pTarget->HasChilds() )
2223 		pTarget = pCurParent;
2224 	return pTarget;
2225 }
2226 
2227 SvLBoxEntry* SvImpIconView::GetEntry( const Point& rDocPos )
2228 {
2229 	CheckBoundingRects();
2230 	SvLBoxEntry* pTarget = 0;
2231 	// Z-Order-Liste vom Ende her absuchen
2232 	sal_uInt16 nCount = pZOrderList->Count();
2233 	while( nCount )
2234 	{
2235 		nCount--;
2236 		SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCount));
2237 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2238 		if( pViewData->aRect.IsInside( rDocPos ) )
2239 		{
2240 			pTarget = pEntry;
2241 			break;
2242 		}
2243 	}
2244 	return pTarget;
2245 }
2246 
2247 SvLBoxEntry* SvImpIconView::GetNextEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
2248 {
2249 	CheckBoundingRects();
2250 	SvLBoxEntry* pTarget = 0;
2251 	sal_uInt16 nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2252 	if( nStartPos != USHRT_MAX )
2253 	{
2254 		sal_uInt16 nCount = pZOrderList->Count();
2255 		for( sal_uInt16 nCur = nStartPos+1; nCur < nCount; nCur++ )
2256 		{
2257 			SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCur));
2258 			SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2259 			if( pViewData->aRect.IsInside( rDocPos ) )
2260 			{
2261 				pTarget = pEntry;
2262 				break;
2263 			}
2264 		}
2265 	}
2266 	return pTarget;
2267 }
2268 
2269 SvLBoxEntry* SvImpIconView::GetPrevEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
2270 {
2271 	CheckBoundingRects();
2272 	SvLBoxEntry* pTarget = 0;
2273 	sal_uInt16 nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2274 	if( nStartPos != USHRT_MAX && nStartPos != 0 )
2275 	{
2276 		nStartPos--;
2277 		do
2278 		{
2279 			SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nStartPos));
2280 			SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2281 			if( pViewData->aRect.IsInside( rDocPos ) )
2282 			{
2283 				pTarget = pEntry;
2284 				break;
2285 			}
2286 		} while( nStartPos > 0 );
2287 	}
2288 	return pTarget;
2289 }
2290 
2291 
2292 Point SvImpIconView::GetEntryPosition( SvLBoxEntry* pEntry )
2293 {
2294 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2295 	DBG_ASSERT(pViewData,"Entry not in model");
2296 	return pViewData->aRect.TopLeft();
2297 }
2298 
2299 const Rectangle& SvImpIconView::GetBoundingRect( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
2300 {
2301 	if( !pViewData )
2302 		pViewData = ICNVIEWDATA(pEntry);
2303 	DBG_ASSERT(pViewData,"Entry not in model");
2304 	if( !IsBoundingRectValid( pViewData->aRect ))
2305 		FindBoundingRect( pEntry, pViewData );
2306 	return pViewData->aRect;
2307 }
2308 
2309 void SvImpIconView::SetSpaceBetweenEntries( long nHor, long nVer )
2310 {
2311 	nHorDist = nHor;
2312 	nVerDist = nVer;
2313 }
2314 
2315 Rectangle SvImpIconView::CalcBmpRect( SvLBoxEntry* pEntry, const Point* pPos,
2316 	SvIcnVwDataEntry* pViewData  )
2317 {
2318 	if( !pViewData )
2319 		pViewData = ICNVIEWDATA(pEntry);
2320 
2321 	Rectangle aBound = GetBoundingRect( pEntry, pViewData );
2322 	if( pPos )
2323 		aBound.SetPos( *pPos );
2324 	Point aPos( aBound.TopLeft() );
2325 
2326 	switch( nViewMode )
2327 	{
2328 		case VIEWMODE_ICON:
2329 		{
2330 			aPos.X() += ( aBound.GetWidth() - nMaxBmpWidth ) / 2;
2331 			Size aSize( nMaxBmpWidth, nMaxBmpHeight );
2332 			// das Bitmap-Rechteck soll nicht das TextRect beruehren
2333 			aSize.Height() -= 3;
2334 			return Rectangle( aPos, aSize );
2335 		}
2336 
2337 		case VIEWMODE_NAME:
2338 			return Rectangle( aPos,
2339 				Size( nMaxBmpWidth, aBound.GetHeight() ));
2340 
2341 		case VIEWMODE_TEXT:
2342 			return Rectangle( aPos, aBound.GetSize() );
2343 
2344 		default:
2345 		{
2346 			Rectangle aRect;
2347 			return aRect;
2348 		}
2349 	}
2350 }
2351 
2352 Rectangle SvImpIconView::CalcTextRect( SvLBoxEntry* pEntry,
2353 	SvLBoxString* pItem, const Point* pPos, sal_Bool bForInplaceEdit,
2354 	SvIcnVwDataEntry* pViewData )
2355 {
2356 	long nBmpHeight, nBmpWidth;
2357 
2358 	if( !pItem )
2359 		pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
2360 
2361 	if( !pViewData )
2362 		pViewData = ICNVIEWDATA(pEntry);
2363 
2364 	Size aTextSize( GetItemSize( pView, pEntry, pItem, pViewData ));
2365 	aTextSize.Width() += 2*LROFFS_TEXT;
2366 
2367 	Size aContextBmpSize(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry));
2368 	Rectangle aBound = GetBoundingRect( pEntry, pViewData );
2369 	if( pPos )
2370 		aBound.SetPos( *pPos );
2371 	Point aPos( aBound.TopLeft() );
2372 
2373 	switch( nViewMode )
2374 	{
2375 		case VIEWMODE_ICON:
2376 			nBmpHeight = aContextBmpSize.Height();
2377 			if( nBmpHeight < nMaxBmpHeight )
2378 				nBmpHeight = nMaxBmpHeight;
2379 			aPos.Y() += nBmpHeight;
2380 
2381 			// beim Inplace-Editieren, spendieren wir ein bisschen mehr Platz
2382 			if( bForInplaceEdit )
2383 			{
2384 				// 20% rauf
2385 				long nMinWidth = (( (aContextBmpSize.Width()*10) / 100 ) * 2 ) +
2386 								 aContextBmpSize.Width();
2387 				if( nMinWidth > aBound.GetWidth() )
2388 					nMinWidth = aBound.GetWidth();
2389 
2390 				if( aTextSize.Width() < nMinWidth )
2391 					aTextSize.Width() = nMinWidth;
2392 
2393 				// beim Inplace-Ed. darfs auch untere Eintraege ueberlappen
2394 				Rectangle aMaxGridTextRect = CalcMaxTextRect(pEntry, pViewData);
2395 				Size aOptSize = aMaxGridTextRect.GetSize();
2396 				if( aOptSize.Height() > aTextSize.Height() )
2397 					aTextSize.Height() = aOptSize.Height();
2398 			}
2399 
2400 
2401 			aPos.X() += ( aBound.GetWidth() - aTextSize.Width() ) / 2;
2402 			break;
2403 
2404 		case VIEWMODE_NAME:
2405 			nBmpWidth = aContextBmpSize.Width();
2406 			if( nBmpWidth < nMaxBmpWidth )
2407 				nBmpWidth = nMaxBmpWidth;
2408 			aPos.X() += nBmpWidth;
2409 			// vertikal ausrichten
2410 			aPos.Y() += ( nBmpWidth - aTextSize.Height() ) / 2;
2411 			break;
2412 	}
2413 
2414 	Rectangle aRect( aPos, aTextSize );
2415 // KNALLT BEIM D&D, WENN GECLIPPT WIRD (In DrawText von Thomas)
2416 //	ClipAtVirtOutRect( aRect );
2417 	return aRect;
2418 }
2419 
2420 
2421 long SvImpIconView::CalcBoundingWidth( SvLBoxEntry* pEntry,
2422 	const SvIcnVwDataEntry* pViewData ) const
2423 {
2424 	DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
2425 	DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
2426 	long nStringWidth = GetItemSize( pView, pEntry, pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Width();
2427 	nStringWidth += 2*LROFFS_TEXT;
2428 	long nBmpWidth = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Width();
2429 	long nWidth = 0;
2430 
2431 	switch( nViewMode )
2432 	{
2433 		case VIEWMODE_ICON:
2434 			nWidth = Max( nStringWidth, nBmpWidth );
2435 			nWidth = Max( nWidth, nMaxBmpWidth );
2436 			break;
2437 
2438 		case VIEWMODE_NAME:
2439 			nWidth = Max( nBmpWidth, nMaxBmpWidth );
2440 			nWidth += NAMEVIEW_OFFS_BMP_STRING;  // Abstand Bitmap String
2441 			nWidth += nStringWidth;
2442 			break;
2443 
2444 		case VIEWMODE_TEXT:
2445 			nWidth = nStringWidth;
2446 			break;
2447 	}
2448 	return nWidth;
2449 }
2450 
2451 long SvImpIconView::CalcBoundingHeight( SvLBoxEntry* pEntry,
2452 	const SvIcnVwDataEntry* pViewData ) const
2453 {
2454 	DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
2455 	DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
2456 	long nStringHeight = GetItemSize(pView,pEntry,pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Height();
2457 	long nBmpHeight = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Height();
2458 	long nHeight = 0;
2459 
2460 	switch( nViewMode )
2461 	{
2462 		case VIEWMODE_ICON:
2463 			nHeight = Max( nBmpHeight, nMaxBmpHeight );
2464 			nHeight += ICONVIEW_OFFS_BMP_STRING; // Abstand Bitmap String
2465 			nHeight += nStringHeight;
2466 			break;
2467 
2468 		case VIEWMODE_NAME:
2469 			nHeight = Max( nBmpHeight, nMaxBmpHeight );
2470 			nHeight = Max( nHeight, nStringHeight );
2471 			break;
2472 
2473 		case VIEWMODE_TEXT:
2474 			nHeight = nStringHeight;
2475 			break;
2476 	}
2477 	if( nHeight > nMaxBoundHeight )
2478 	{
2479 		((SvImpIconView*)this)->nMaxBoundHeight = nHeight;
2480 		((SvImpIconView*)this)->aHorSBar.SetLineSize( nHeight / 2 );
2481 		((SvImpIconView*)this)->aVerSBar.SetLineSize( nHeight / 2 );
2482 	}
2483 	return nHeight;
2484 }
2485 
2486 Size SvImpIconView::CalcBoundingSize( SvLBoxEntry* pEntry,
2487 	SvIcnVwDataEntry* pViewData ) const
2488 {
2489 	if( !pViewData )
2490 		pViewData = ICNVIEWDATA(pEntry);
2491 	return Size( CalcBoundingWidth(pEntry,pViewData),
2492 				 CalcBoundingHeight(pEntry,pViewData) );
2493 }
2494 
2495 void SvImpIconView::RecalcAllBoundingRects()
2496 {
2497 	nMaxBoundHeight	= 0;
2498 	pZOrderList->Remove(0, pZOrderList->Count() );
2499 	SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2500 	while( pEntry )
2501 	{
2502 		FindBoundingRect( pEntry );
2503 		pZOrderList->Insert( pEntry, pZOrderList->Count() );
2504 		pEntry = pModel->NextSibling( pEntry );
2505 	}
2506 	bMustRecalcBoundingRects = sal_False;
2507 	AdjustScrollBars();
2508 }
2509 
2510 void SvImpIconView::RecalcAllBoundingRectsSmart()
2511 {
2512 	nMaxBoundHeight	= 0;
2513 	pZOrderList->Remove(0, pZOrderList->Count() );
2514 	SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2515 	while( pEntry )
2516 	{
2517 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2518 		if( IsBoundingRectValid( pViewData->aRect ))
2519 		{
2520 			Size aBoundSize( pViewData->aRect.GetSize() );
2521 			if( aBoundSize.Height() > nMaxBoundHeight )
2522 				nMaxBoundHeight = aBoundSize.Height();
2523 			pZOrderList->Insert( pEntry, pZOrderList->Count() );
2524 		}
2525 		else
2526 		{
2527 			FindBoundingRect( pEntry, pViewData );
2528 		}
2529 		pZOrderList->Insert( pEntry, pZOrderList->Count() );
2530 		pEntry = pModel->NextSibling( pEntry );
2531 	}
2532 	AdjustScrollBars();
2533 }
2534 
2535 void SvImpIconView::UpdateBoundingRects()
2536 {
2537 	SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2538 	while( pEntry )
2539 	{
2540 		GetBoundingRect( pEntry );
2541 		pEntry = pModel->NextSibling( pEntry );
2542 	}
2543 }
2544 
2545 void SvImpIconView::FindBoundingRect( SvLBoxEntry* pEntry,
2546 	SvIcnVwDataEntry* pViewData )
2547 {
2548 	if( !pViewData )
2549 		pViewData = ICNVIEWDATA(pEntry);
2550 
2551 	Size aSize( CalcBoundingSize( pEntry, pViewData ) );
2552 	Point aPos;
2553 
2554 	DBG_ASSERT(!pViewData->IsEntryPosLocked(),"Locked entry pos in FindBoundingRect");
2555 	// damits in der IconView nicht drunter & drueber geht
2556 	if( pViewData->IsEntryPosLocked() && IsBoundingRectValid(pViewData->aRect) )
2557 	{
2558 		AdjustVirtSize( pViewData->aRect );
2559 		return;
2560 	}
2561 
2562 	aPos = FindNextEntryPos( aSize );
2563 
2564 	if( nFlags & F_GRIDMODE )
2565 	{
2566 		Rectangle aGridRect( aPos, Size(nGridDX, nGridDY) );
2567 		pViewData->aGridRect = aGridRect;
2568 		Center( pEntry, pViewData );
2569 		AdjustVirtSize( pViewData->aRect );
2570 		pImpCursor->SetGridUsed( pViewData->aRect );
2571 	}
2572 	else
2573 	{
2574 		pViewData->aRect = Rectangle( aPos, aSize );
2575 		AdjustVirtSize( pViewData->aRect );
2576 	}
2577 }
2578 
2579 
2580 void SvImpIconView::SetCursor( SvLBoxEntry* pEntry )
2581 {
2582 	if( pEntry == pCursor )
2583 		return;
2584 
2585 	ShowCursor( sal_False );
2586 	if( pCursor )
2587 	{
2588 		pView->SetEntryFocus( pCursor, sal_False );
2589 		if( pView->GetSelectionMode() == SINGLE_SELECTION )
2590 			pView->Select( pCursor, sal_False );
2591 	}
2592 	pCursor = pEntry;
2593 	ToTop( pCursor );
2594 	if( pCursor )
2595 	{
2596 		pView->SetEntryFocus(pCursor, sal_True );
2597 		if( pView->GetSelectionMode() == SINGLE_SELECTION )
2598 			pView->Select( pCursor, sal_True );
2599 		ShowCursor( sal_True );
2600 	}
2601 }
2602 
2603 
2604 void SvImpIconView::ShowCursor( sal_Bool bShow )
2605 {
2606 	if( !pCursor || !bShow || !pView->HasFocus() )
2607 	{
2608 		pView->HideFocus();
2609 		return;
2610 	}
2611 	Rectangle aRect ( CalcFocusRect( pCursor ) );
2612 	pView->ShowFocus( aRect );
2613 }
2614 
2615 
2616 void SvImpIconView::HideDDIcon()
2617 {
2618 	pView->Update();
2619 	ImpHideDDIcon();
2620 	pDDBufDev = pDDDev;
2621 	pDDDev = 0;
2622 }
2623 
2624 void SvImpIconView::ImpHideDDIcon()
2625 {
2626 	if( pDDDev )
2627 	{
2628 		Size aSize( pDDDev->GetOutputSizePixel() );
2629 		// pView restaurieren
2630 		pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2631 	}
2632 }
2633 
2634 
2635 void SvImpIconView::ShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
2636 {
2637 	pView->Update();
2638 	if( pRefEntry != pDDRefEntry )
2639 	{
2640 		DELETEZ(pDDDev);
2641 		DELETEZ(pDDBufDev);
2642 	}
2643 	sal_Bool bSelected = pView->SvListView::Select( pRefEntry, sal_False );
2644 	if( !pDDDev )
2645 	{
2646 		if( pDDBufDev )
2647 		{
2648 			// nicht bei jedem Move ein Device anlegen, da dies besonders
2649 			// auf Remote-Clients zu langsam ist
2650 			pDDDev = pDDBufDev;
2651 			pDDBufDev = 0;
2652 		}
2653 		else
2654 		{
2655 			pDDDev = new VirtualDevice( *pView );
2656 			pDDDev->SetFont( pView->GetFont() );
2657 		}
2658 	}
2659 	else
2660 	{
2661 		ImpHideDDIcon();
2662 	}
2663 	const Rectangle& rRect = GetBoundingRect( pRefEntry );
2664 	pDDDev->SetOutputSizePixel( rRect.GetSize() );
2665 
2666 	Point aPos( rPosPix );
2667 	CalcDocPos( aPos );
2668 
2669 	Size aSize( pDDDev->GetOutputSizePixel() );
2670 	pDDRefEntry = pRefEntry;
2671 	aDDLastEntryPos = aPos;
2672 	aDDLastRectPos = aPos;
2673 
2674 	// Hintergrund sichern
2675 	pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2676 	// Icon in pView malen
2677 	nFlags |= F_NO_EMPHASIS;
2678 	PaintEntry( pRefEntry, aPos );
2679 	nFlags &= ~F_NO_EMPHASIS;
2680 	if( bSelected )
2681 		pView->SvListView::Select( pRefEntry, sal_True );
2682 }
2683 
2684 void SvImpIconView::HideShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
2685 {
2686 /*  In Notfaellen folgenden flackernden Code aktivieren:
2687 
2688 		HideDDIcon();
2689 		ShowDDIcon( pRefEntry, rPosPix );
2690 		return;
2691 */
2692 	if( !pDDDev )
2693 	{
2694 		ShowDDIcon( pRefEntry, rPosPix );
2695 		return;
2696 	}
2697 
2698 	if( pRefEntry != pDDRefEntry )
2699 	{
2700 		HideDDIcon();
2701 		ShowDDIcon( pRefEntry, rPosPix );
2702 		return;
2703 	}
2704 
2705 	Point aEmptyPoint;
2706 
2707 	Point aCurEntryPos( rPosPix );
2708 	CalcDocPos( aCurEntryPos );
2709 
2710 	const Rectangle& rRect = GetBoundingRect( pRefEntry );
2711 	Size aEntrySize( rRect.GetSize() );
2712 	Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2713 	Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2714 
2715 	if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2716 	{
2717 		HideDDIcon();
2718 		ShowDDIcon( pRefEntry, rPosPix );
2719 		return;
2720 	}
2721 
2722 	// Ueberlappung des neuen und alten D&D-Pointers!
2723 
2724 	Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2725 	if( !pDDTempDev )
2726 	{
2727 		pDDTempDev = new VirtualDevice( *pView );
2728 		pDDTempDev->SetFont( pView->GetFont() );
2729 	}
2730 
2731 	Size aFullSize( aFullRect.GetSize() );
2732 	Point aFullPos( aFullRect.TopLeft() );
2733 
2734 	pDDTempDev->SetOutputSizePixel( aFullSize );
2735 
2736 	// Hintergrund (mit dem alten D&D-Pointer!) sichern
2737 	pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2738 	// den alten Buffer in den neuen Buffer pasten
2739 	aDDLastRectPos = aDDLastRectPos - aFullPos;
2740 
2741 	pDDTempDev->DrawOutDev(
2742 		aDDLastRectPos,
2743 		pDDDev->GetOutputSizePixel(),
2744 		aEmptyPoint,
2745 		pDDDev->GetOutputSizePixel(),
2746 		*pDDDev );
2747 
2748 	// Swap
2749 	VirtualDevice* pTemp = pDDDev;
2750 	pDDDev = pDDTempDev;
2751 	pDDTempDev = pTemp;
2752 
2753 	// in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2754 	pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2755 	pDDTempDev->DrawOutDev(
2756 		aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2757 	Point aRelPos = aCurEntryPos - aFullPos;
2758 	nFlags |= F_NO_EMPHASIS;
2759 	PaintEntry( pRefEntry, aRelPos, 0, pDDTempDev );
2760 	nFlags &= ~F_NO_EMPHASIS;
2761 
2762 	aDDLastRectPos = aFullPos;
2763 	aDDLastEntryPos = aCurEntryPos;
2764 
2765 	pView->DrawOutDev(
2766 		aDDLastRectPos,
2767 		pDDDev->GetOutputSizePixel(),
2768 		aEmptyPoint,
2769 		pDDDev->GetOutputSizePixel(),
2770 		*pDDTempDev );
2771 
2772 	sal_Bool bSelected = pView->SvListView::Select( pRefEntry, sal_False );
2773 	if( bSelected )
2774 		pView->SvListView::Select( pRefEntry, sal_True );
2775 }
2776 
2777 void SvImpIconView::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool )
2778 {
2779 	CheckBoundingRects();
2780 	Rectangle aRect;
2781 	if( pEntry != pCurParent &&
2782 		(pEntry->HasChilds() || pEntry->HasChildsOnDemand()) )
2783 		aRect = CalcBmpRect( pEntry );
2784 	else
2785 	{
2786 		aRect.SetSize( aOutputSize );
2787 		const MapMode& rMapMode = pView->GetMapMode();
2788 		Point aOrigin( rMapMode.GetOrigin());
2789 		aOrigin *= -1; // in Doc-Koord wandeln
2790 		aRect.SetPos( aOrigin );
2791 		aRect.Left()++; aRect.Top()++;
2792 		aRect.Right()--; aRect.Bottom()--;
2793 	}
2794 	ImpDrawXORRect( aRect );
2795 }
2796 
2797 sal_Bool SvImpIconView::NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
2798 	SvLBoxEntry*& rpNewPar, sal_uLong& rNewChildPos )
2799 {
2800 	if( pTarget == pCurParent && pModel->GetParent(pEntry) == pCurParent )
2801 	{
2802 		// D&D innerhalb einer Childlist
2803 		StopEditTimer();
2804 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2805 		Size aSize( pViewData->aRect.GetSize() );
2806 		Point aNewPos = FindNextEntryPos( aSize );
2807 		AdjustVirtSize( Rectangle( aNewPos, aSize ) );
2808 		SetEntryPosition( pEntry, aNewPos, sal_False, sal_True );
2809 		return sal_False;
2810 	}
2811 	return pView->SvLBox::NotifyMoving(pTarget,pEntry,rpNewPar,rNewChildPos);
2812 }
2813 
2814 sal_Bool SvImpIconView::NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
2815 	SvLBoxEntry*& rpNewParent, sal_uLong& rNewChildPos )
2816 {
2817 	return pView->SvLBox::NotifyCopying(pTarget,pEntry,rpNewParent,rNewChildPos);
2818 }
2819 
2820 void SvImpIconView::WriteDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo)
2821 {
2822 	SvLBoxEntry* pCurEntry = GetCurEntry();
2823 	Point aEntryPos;
2824 	if( pCurEntry )
2825 	{
2826 		aEntryPos = rPos;
2827 		aEntryPos -= GetEntryPosition( pCurEntry );
2828 	}
2829 	pInfo->nMouseRelX = aEntryPos.X();
2830 	pInfo->nMouseRelY = aEntryPos.Y();
2831 }
2832 
2833 void SvImpIconView::ReadDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo )
2834 {
2835 	Point aDropPos( rPos );
2836 	aDropPos.X() -= pInfo->nMouseRelX;
2837 	aDropPos.Y() -= pInfo->nMouseRelY;
2838 	SetNextEntryPos( aDropPos );
2839 }
2840 
2841 void SvImpIconView::InvalidateBoundingRect( SvLBoxEntry* pEntry )
2842 {
2843 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2844 	InvalidateBoundingRect( pViewData->aRect );
2845 }
2846 
2847 void SvImpIconView::PrepareCommandEvent( const Point& rPt )
2848 {
2849 	aMouseMoveTimer.Stop();
2850 	StopEditTimer();
2851 	nFlags |= F_CMD_ARRIVED;
2852 	SvLBoxEntry* pEntry = pView->GetEntry( rPt, sal_True );
2853 	if( (nFlags & F_DOWN_CTRL) && pEntry && !pView->IsSelected(pEntry) )
2854 		pView->Select( pEntry, sal_True );
2855 	nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
2856 }
2857 
2858 void SvImpIconView::SttDrag( const Point& rPos )
2859 {
2860 	PrepareCommandEvent( rPos );
2861 
2862 	nFlags |= F_DRAG_SOURCE;
2863 	ShowCursor( sal_False );
2864 }
2865 
2866 void SvImpIconView::EndDrag()
2867 {
2868 	ShowCursor( sal_True );
2869 	nFlags &= (~F_DRAG_SOURCE);
2870 }
2871 
2872 void SvImpIconView::ToTop( SvLBoxEntry* pEntry )
2873 {
2874 	DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"ToTop:ZOrder?");
2875 	if( pZOrderList->GetObject( pZOrderList->Count() -1 ) != pEntry )
2876 	{
2877 		sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry );
2878 		pZOrderList->Remove( nPos, 1 );
2879 		pZOrderList->Insert( pEntry, pZOrderList->Count() );
2880 	}
2881 }
2882 
2883 void SvImpIconView::SetCurParent( SvLBoxEntry* pNewParent )
2884 {
2885 	Clear();
2886 	pCurParent = pNewParent;
2887 	ImpArrange();
2888 }
2889 
2890 void SvImpIconView::ClipAtVirtOutRect( Rectangle& rRect ) const
2891 {
2892 	if( rRect.Bottom() >= aVirtOutputSize.Height() )
2893 		rRect.Bottom() = aVirtOutputSize.Height() - 1;
2894 	if( rRect.Right() >= aVirtOutputSize.Width() )
2895 		rRect.Right() = aVirtOutputSize.Width() - 1;
2896 	if( rRect.Top() < 0 )
2897 		rRect.Top() = 0;
2898 	if( rRect.Left() < 0 )
2899 		rRect.Left() = 0;
2900 }
2901 
2902 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2903 // sichtbar gemacht werden soll.
2904 // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2905 
2906 void SvImpIconView::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar )
2907 {
2908 	Rectangle aRect( rRect );
2909 	ClipAtVirtOutRect( aRect );
2910 	MapMode aMapMode( pView->GetMapMode() );
2911 	Point aOrigin( aMapMode.GetOrigin() );
2912 	// in Dokumentkoordinate umwandeln
2913 	aOrigin *= -1;
2914 
2915 	Rectangle aOutputArea( aOrigin, aOutputSize );
2916 	if( aOutputArea.IsInside( aRect ) )
2917 		return;	// ist schon sichtbar
2918 
2919 	long nDy;
2920 	if( aRect.Top() < aOutputArea.Top() )
2921 	{
2922 		// nach oben scrollen (nDy < 0)
2923 		nDy = aRect.Top() - aOutputArea.Top();
2924 	}
2925 	else if( aRect.Bottom() > aOutputArea.Bottom() )
2926 	{
2927 		// nach unten scrollen (nDy > 0)
2928 		nDy = aRect.Bottom() - aOutputArea.Bottom();
2929 	}
2930 	else
2931 		nDy = 0;
2932 
2933 	long nDx;
2934 	if( aRect.Left() < aOutputArea.Left() )
2935 	{
2936 		// nach links scrollen (nDx < 0)
2937 		nDx = aRect.Left() - aOutputArea.Left();
2938 	}
2939 	else if( aRect.Right() > aOutputArea.Right() )
2940 	{
2941 		// nach rechts scrollen (nDx > 0)
2942 		nDx = aRect.Right() - aOutputArea.Right();
2943 	}
2944 	else
2945 		nDx = 0;
2946 
2947 	aOrigin.X() += nDx;
2948 	aOrigin.Y() += nDy;
2949 	aOutputArea.SetPos( aOrigin );
2950 
2951 	pView->Update();
2952 
2953 	// Origin fuer SV invertieren (damit wir in
2954 	// Dokumentkoordinaten scrollen/painten koennen)
2955 	aOrigin *= -1;
2956 	aMapMode.SetOrigin( aOrigin );
2957 	pView->SetMapMode( aMapMode );
2958 
2959 	// in umgekehrte Richtung scrollen!
2960 	pView->Control::Scroll( -nDx, -nDy, aOutputArea, sal_True );
2961 	if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2962 	{
2963 		if( !bScrBar )
2964 		{
2965 			aOrigin *= -1;
2966 			// Thumbs korrigieren
2967 			if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2968 				aHorSBar.SetThumbPos( aOrigin.X() );
2969 			if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2970 				aVerSBar.SetThumbPos( aOrigin.Y() );
2971 		}
2972 	}
2973 	// pruefen, ob ScrollBars noch benoetigt werden
2974 	CheckScrollBars();
2975 	pView->Update();
2976 }
2977 
2978 
2979 SvLBoxEntry* SvImpIconView::GetNewCursor()
2980 {
2981 	SvLBoxEntry* pNewCursor;
2982 	if( pCursor )
2983 	{
2984 		pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False );
2985 		if( !pNewCursor )
2986 		{
2987 			pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True );
2988 			if( !pNewCursor )
2989 			{
2990 				pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False );
2991 				if( !pNewCursor )
2992 					pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True );
2993 			}
2994 		}
2995 	}
2996 	else
2997 		pNewCursor = pModel->FirstChild( pCurParent );
2998 	DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"GetNewCursor failed");
2999 	return pNewCursor;
3000 }
3001 
3002 
3003 sal_uInt16 SvImpIconView:: GetSelectionCount() const
3004 {
3005 	sal_uInt16 nSelected = 0;
3006 	SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent);
3007 	while( pEntry )
3008 	{
3009 		if( pView->IsSelected( pEntry ) )
3010 			nSelected++;
3011 		pEntry = pModel->NextSibling( pEntry );
3012 	}
3013 	return nSelected;
3014 }
3015 
3016 
3017 void SvImpIconView::ToggleSelection( SvLBoxEntry* pEntry )
3018 {
3019 	sal_Bool bSel;
3020 	if( pView->IsSelected( pEntry ) )
3021 		bSel = sal_False;
3022 	else
3023 		bSel = sal_True;
3024 	pView->Select( pEntry, bSel );
3025 }
3026 
3027 void SvImpIconView::DeselectAllBut( SvLBoxEntry* pThisEntryNot )
3028 {
3029 	ClearSelectedRectList();
3030 	SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
3031 	while( pEntry )
3032 	{
3033 		if( pEntry != pThisEntryNot && pView->IsSelected( pEntry ))
3034 			pView->Select( pEntry, sal_False );
3035 		pEntry = pModel->NextSibling( pEntry );
3036 	}
3037 }
3038 
3039 #define ICN_ROWS	50
3040 #define ICN_COLS	30
3041 
3042 ImpIcnCursor::ImpIcnCursor( SvImpIconView* pOwner )
3043 {
3044 	pView 		= pOwner;
3045 	pColumns	= 0;
3046 	pRows 		= 0;
3047 	pCurEntry 	= 0;
3048 	nDeltaWidth = 0;
3049 	nDeltaHeight= 0;
3050 	nCols		= 0;
3051 	nRows		= 0;
3052 	nGridCols	= 0;
3053 	nGridRows	= 0;
3054 	pGridMap	= 0;
3055 }
3056 
3057 ImpIcnCursor::~ImpIcnCursor()
3058 {
3059 	delete[] pColumns;
3060 	delete[] pRows;
3061 	delete pGridMap;
3062 }
3063 
3064 sal_uInt16 ImpIcnCursor::GetSortListPos( SvPtrarr* pList, long nValue,
3065 	int bVertical )
3066 {
3067 	sal_uInt16 nCount = (sal_uInt16)pList->Count();
3068 	if( !nCount )
3069 		return 0;
3070 
3071 	sal_uInt16 nCurPos = 0;
3072 	long nPrevValue = LONG_MIN;
3073 	while( nCount )
3074 	{
3075 		const Rectangle& rRect=
3076 			pView->GetBoundingRect((SvLBoxEntry*)(pList->GetObject(nCurPos)));
3077 		long nCurValue;
3078 		if( bVertical )
3079 			nCurValue = rRect.Top();
3080 		else
3081 			nCurValue = rRect.Left();
3082 		if( nValue >= nPrevValue && nValue <= nCurValue )
3083 			return (sal_uInt16)nCurPos;
3084 		nPrevValue = nCurValue;
3085 		nCount--;
3086 		nCurPos++;
3087 	}
3088 	return pList->Count();
3089 }
3090 
3091 void ImpIcnCursor::ImplCreate()
3092 {
3093 	pView->CheckBoundingRects();
3094 	DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
3095 
3096 	SetDeltas();
3097 
3098 	pColumns = new SvPtrarr[ nCols ];
3099 	pRows = new SvPtrarr[ nRows ];
3100 
3101 	DELETEZ(pGridMap);
3102 
3103 	SvLBoxTreeList* pModel = pView->pModel;
3104 	SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
3105 	while( pEntry )
3106 	{
3107 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3108 		// const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3109 		Rectangle rRect( pView->CalcBmpRect( pEntry,0,pViewData ) );
3110 		short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
3111 		short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
3112 
3113 		// Rundungsfehler abfangen
3114 		if( nY >= nRows )
3115 			nY = sal::static_int_cast< short >(nRows - 1);
3116 		if( nX >= nCols )
3117 			nX = sal::static_int_cast< short >(nCols - 1);
3118 
3119 		sal_uInt16 nIns = GetSortListPos( &pColumns[nX], rRect.Top(), sal_True );
3120 		pColumns[ nX ].Insert( pEntry, nIns );
3121 
3122 		nIns = GetSortListPos( &pRows[nY], rRect.Left(), sal_False );
3123 		pRows[ nY ].Insert( pEntry, nIns );
3124 
3125 		pViewData->nX = nX;
3126 		pViewData->nY = nY;
3127 
3128 		pEntry = pModel->NextSibling( pEntry );
3129 	}
3130 }
3131 
3132 void ImpIcnCursor::CreateGridMap()
3133 {
3134 	if( pGridMap )
3135 		return;
3136 
3137 	const Size& rSize = pView->aVirtOutputSize;
3138 	long nWidth = rSize.Width();
3139 	if( nWidth < pView->nMaxVirtWidth )
3140 		nWidth = pView->nMaxVirtWidth;
3141 	nWidth -= 2*LROFFS_WINBORDER;
3142 	if( nWidth <= 0 )
3143 		nWidth = 1;
3144 
3145 	nGridDX = pView->nGridDX;
3146 	nGridDY = pView->nGridDY;
3147 
3148 	// Hinweis: Wegen der Abrundung bei Berechnung von nGridCols
3149 	// ist es moeglich, dass Eintrage nicht im Grid liegen. Diese
3150 	// wurden typischerweise manuell verschoben und gelockt
3151 	nGridCols = nWidth / nGridDX;
3152 	if( !nGridCols ) nGridCols = 1;
3153 
3154 	nGridRows = rSize.Height() / nGridDY;
3155 	// nRows nicht abrunden, da zur Vermeidung von Ueberlappungen
3156 	// das gesamte BoundingRect des Eintrags zur Markierung im Grid
3157 	// herangezogen wird.
3158 	if( (nGridRows * nGridDY) < rSize.Height() )
3159 		nGridRows++;
3160 	else if( !nGridRows )
3161 		nGridRows = 1;
3162 
3163 	//XXX
3164 	//nGridRows += 50; // in fuenfziger-Schritten
3165 
3166 	pGridMap = new sal_Bool[ nGridRows*nGridCols];
3167 	memset( (void*)pGridMap, 0, nGridRows*nGridCols );
3168 
3169 	SvLBoxTreeList* pModel = pView->pModel;
3170 	SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
3171 	while( pEntry )
3172 	{
3173 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3174 		const Rectangle& rRect = pViewData->aRect;
3175 		// nur, wenn der Entry schon plaziert ist
3176 		if( pView->IsBoundingRectValid( rRect ))
3177 		{
3178 			// Alle vom Eintrag beruehrten Grids kennzeichnen
3179 			SetGridUsed( pView->GetBoundingRect( pEntry, pViewData ) );
3180 		}
3181 		pEntry = pModel->NextSibling( pEntry );
3182 	}
3183 }
3184 
3185 sal_Bool ImpIcnCursor::GetGrid( const Point& rDocPos, sal_uInt16& rGridX, sal_uInt16& rGridY ) const
3186 {
3187 	Point aPos( rDocPos );
3188 	aPos.X() -= LROFFS_WINBORDER;
3189 	aPos.Y() -= TBOFFS_WINBORDER;
3190 	rGridX = (sal_uInt16)(aPos.X() / nGridDX);
3191 	rGridY = (sal_uInt16)(aPos.Y() / nGridDY);
3192 	sal_Bool bInGrid = sal_True;
3193 	if( rGridX >= nGridCols )
3194 	{
3195 		rGridX = sal::static_int_cast< sal_uInt16 >(nGridCols - 1);
3196 		bInGrid = sal_False;
3197 	}
3198 	if( rGridY >= nGridRows )
3199 	{
3200 		rGridY = sal::static_int_cast< sal_uInt16 >(nGridRows - 1);
3201 		if( !bInGrid )
3202 			return sal_False; // beide Koordinaten nicht im Grid
3203 	}
3204 	return sal_True;
3205 }
3206 
3207 void ImpIcnCursor::SetGridUsed( const Rectangle& rRect, sal_Bool bUsed  )
3208 {
3209 	CreateGridMap();
3210 	sal_uInt16 nTLX, nTLY, nBRX, nBRY;
3211 
3212 	sal_Bool bTLInGrid = GetGrid( rRect.TopLeft(), nTLX, nTLY );
3213 	sal_Bool bBRInGrid = GetGrid( rRect.BottomRight(), nBRX, nBRY );
3214 
3215 	if( !bTLInGrid && !bBRInGrid )
3216 		return;
3217 
3218 	for( sal_uInt16 nCurY = nTLY; nCurY <= nBRY; nCurY++ )
3219 	{
3220 		for( sal_uInt16 nCurX = nTLX; nCurX <= nBRX; nCurX++ )
3221 		{
3222 			SetGridUsed( nCurX, nCurY, bUsed );
3223 		}
3224 	}
3225 }
3226 
3227 void ImpIcnCursor::Clear( sal_Bool bGridToo )
3228 {
3229 	if( pColumns )
3230 	{
3231 		delete[] pColumns;
3232 		delete[] pRows;
3233 		pColumns = 0;
3234 		pRows = 0;
3235 		pCurEntry = 0;
3236 		nDeltaWidth = 0;
3237 		nDeltaHeight = 0;
3238 	}
3239 	if( bGridToo && pGridMap )
3240 	{
3241 		DELETEZ(pGridMap);
3242 		nGridRows = 0;
3243 		nGridCols = 0;
3244 	}
3245 }
3246 
3247 SvLBoxEntry* ImpIcnCursor::SearchCol(sal_uInt16 nCol,sal_uInt16 nTop,sal_uInt16 nBottom,
3248 	sal_uInt16, sal_Bool bDown, sal_Bool bSimple  )
3249 {
3250 	DBG_ASSERT(pCurEntry,"SearchCol: No reference entry");
3251 	SvPtrarr* pList = &(pColumns[ nCol ]);
3252 	sal_uInt16 nCount = pList->Count();
3253 	if( !nCount )
3254 		return 0;
3255 
3256 	const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
3257 
3258 	if( bSimple )
3259 	{
3260 		sal_uInt16 nListPos = pList->GetPos( pCurEntry );
3261 		DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List");
3262 		if( bDown )
3263 		{
3264 			while( nListPos < nCount-1 )
3265 			{
3266 				nListPos++;
3267 				SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3268 				const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3269 				if( rRect.Top() > rRefRect.Top() )
3270 					return pEntry;
3271 			}
3272 			return 0;
3273 		}
3274 		else
3275 		{
3276 			while( nListPos )
3277 			{
3278 				nListPos--;
3279 				if( nListPos < nCount )
3280 				{
3281 					SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3282 					const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3283 					if( rRect.Top() < rRefRect.Top() )
3284 						return pEntry;
3285 				}
3286 			}
3287 			return 0;
3288 		}
3289 	}
3290 
3291 	if( nTop > nBottom )
3292 	{
3293 		sal_uInt16 nTemp = nTop;
3294 		nTop = nBottom;
3295 		nBottom = nTemp;
3296 	}
3297 	long nMinDistance = LONG_MAX;
3298 	SvLBoxEntry* pResult = 0;
3299 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3300 	{
3301 		SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
3302 		if( pEntry != pCurEntry )
3303 		{
3304 			SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3305 			sal_uInt16 nY = pViewData->nY;
3306 			if( nY >= nTop && nY <= nBottom )
3307 			{
3308 				const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3309 				long nDistance = rRect.Top() - rRefRect.Top();
3310 				if( nDistance < 0 )
3311 					nDistance *= -1;
3312 				if( nDistance && nDistance < nMinDistance )
3313 				{
3314 					nMinDistance = nDistance;
3315 					pResult = pEntry;
3316 				}
3317 			}
3318 		}
3319 	}
3320 	return pResult;
3321 }
3322 
3323 SvLBoxEntry* ImpIcnCursor::SearchRow(sal_uInt16 nRow,sal_uInt16 nLeft,sal_uInt16 nRight,
3324 	sal_uInt16, sal_Bool bRight, sal_Bool bSimple )
3325 {
3326 	DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
3327 	SvPtrarr* pList = &(pRows[ nRow ]);
3328 	sal_uInt16 nCount = pList->Count();
3329 	if( !nCount )
3330 		return 0;
3331 
3332 	const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
3333 
3334 	if( bSimple )
3335 	{
3336 		sal_uInt16 nListPos = pList->GetPos( pCurEntry );
3337 		DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List");
3338 		if( bRight )
3339 		{
3340 			while( nListPos < nCount-1 )
3341 			{
3342 				nListPos++;
3343 				SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3344 				const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3345 				if( rRect.Left() > rRefRect.Left() )
3346 					return pEntry;
3347 			}
3348 			return 0;
3349 		}
3350 		else
3351 		{
3352 			while( nListPos )
3353 			{
3354 				nListPos--;
3355 				if( nListPos < nCount )
3356 				{
3357 					SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3358 					const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3359 					if( rRect.Left() < rRefRect.Left() )
3360 						return pEntry;
3361 				}
3362 			}
3363 			return 0;
3364 		}
3365 
3366 	}
3367 	if( nRight < nLeft )
3368 	{
3369 		sal_uInt16 nTemp = nRight;
3370 		nRight = nLeft;
3371 		nLeft = nTemp;
3372 	}
3373 	long nMinDistance = LONG_MAX;
3374 	SvLBoxEntry* pResult = 0;
3375 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3376 	{
3377 		SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
3378 		if( pEntry != pCurEntry )
3379 		{
3380 			SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3381 			sal_uInt16 nX = pViewData->nX;
3382 			if( nX >= nLeft && nX <= nRight )
3383 			{
3384 				const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3385 				long nDistance = rRect.Left() - rRefRect.Left();
3386 				if( nDistance < 0 )
3387 					nDistance *= -1;
3388 				if( nDistance && nDistance < nMinDistance )
3389 				{
3390 					nMinDistance = nDistance;
3391 					pResult = pEntry;
3392 				}
3393 			}
3394 		}
3395 	}
3396 	return pResult;
3397 }
3398 
3399 
3400 
3401 /*
3402 	Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw.
3403 	linksstehenden. Suchverfahren am Beispiel bRight = sal_True:
3404 
3405 				  c
3406 				b c
3407 			  a b c
3408 			S 1 1 1      ====> Suchrichtung
3409 			  a b c
3410 				b c
3411 				  c
3412 
3413 	S : Startposition
3414 	1 : erstes Suchrechteck
3415 	a,b,c : 2., 3., 4. Suchrechteck
3416 */
3417 
3418 SvLBoxEntry* ImpIcnCursor::GoLeftRight( SvLBoxEntry* pIcnEntry, sal_Bool bRight )
3419 {
3420 	SvLBoxEntry* pResult;
3421 	pCurEntry = pIcnEntry;
3422 	Create();
3423 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
3424 	sal_uInt16 nY = pViewData->nY;
3425 	sal_uInt16 nX = pViewData->nX;
3426 	DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
3427 	DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
3428 	// Nachbar auf gleicher Zeile ?
3429 	if( bRight )
3430 		pResult = SearchRow(
3431             nY, nX, sal::static_int_cast< sal_uInt16 >(nCols-1), nX, sal_True, sal_True );
3432 	else
3433 		pResult = SearchRow( nY, nX ,0, nX, sal_False, sal_True );
3434 	if( pResult )
3435 		return pResult;
3436 
3437 	long nCurCol = nX;
3438 
3439 	long nColOffs, nLastCol;
3440 	if( bRight )
3441 	{
3442 		nColOffs = 1;
3443 		nLastCol = nCols;
3444 	}
3445 	else
3446 	{
3447 		nColOffs = -1;
3448 		nLastCol = -1;   // 0-1
3449 	}
3450 
3451 	sal_uInt16 nRowMin = nY;
3452 	sal_uInt16 nRowMax = nY;
3453 	do
3454 	{
3455 		SvLBoxEntry* pEntry = SearchCol((sal_uInt16)nCurCol,nRowMin,nRowMax,nY,sal_True, sal_False);
3456 		if( pEntry )
3457 			return pEntry;
3458 		if( nRowMin )
3459 			nRowMin--;
3460 		if( nRowMax < (nRows-1))
3461 			nRowMax++;
3462 		nCurCol += nColOffs;
3463 	} while( nCurCol != nLastCol );
3464 	return 0;
3465 }
3466 
3467 SvLBoxEntry* ImpIcnCursor::GoUpDown( SvLBoxEntry* pIcnEntry, sal_Bool bDown)
3468 {
3469 	SvLBoxEntry* pResult;
3470 	pCurEntry = pIcnEntry;
3471 	Create();
3472 	SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
3473 	sal_uInt16 nY = pViewData->nY;
3474 	sal_uInt16 nX = pViewData->nX;
3475 	DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
3476 	DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
3477 
3478 	// Nachbar in gleicher Spalte ?
3479 	if( bDown )
3480 		pResult = SearchCol(
3481             nX, nY, sal::static_int_cast< sal_uInt16 >(nRows-1), nY, sal_True, sal_True );
3482 	else
3483 		pResult = SearchCol( nX, nY ,0, nY, sal_False, sal_True );
3484 	if( pResult )
3485 		return pResult;
3486 
3487 	long nCurRow = nY;
3488 
3489 	long nRowOffs, nLastRow;
3490 	if( bDown )
3491 	{
3492 		nRowOffs = 1;
3493 		nLastRow = nRows;
3494 	}
3495 	else
3496 	{
3497 		nRowOffs = -1;
3498 		nLastRow = -1;   // 0-1
3499 	}
3500 
3501 	sal_uInt16 nColMin = nX;
3502 	sal_uInt16 nColMax = nX;
3503 	do
3504 	{
3505 		SvLBoxEntry* pEntry = SearchRow((sal_uInt16)nCurRow,nColMin,nColMax,nX,sal_True, sal_False);
3506 		if( pEntry )
3507 			return pEntry;
3508 		if( nColMin )
3509 			nColMin--;
3510 		if( nColMax < (nCols-1))
3511 			nColMax++;
3512 		nCurRow += nRowOffs;
3513 	} while( nCurRow != nLastRow );
3514 	return 0;
3515 }
3516 
3517 void ImpIcnCursor::SetDeltas()
3518 {
3519 	const Size& rSize = pView->aVirtOutputSize;
3520 	if( pView->nFlags & F_GRIDMODE )
3521 	{
3522 		nGridDX = pView->nGridDX;
3523 		nGridDY = pView->nGridDY;
3524 	}
3525 	else
3526 	{
3527 		nGridDX = 20;
3528 		nGridDY = 20;
3529 	}
3530 	nCols = rSize.Width() / nGridDX;
3531 	if( !nCols )
3532 		nCols = 1;
3533 	nRows = rSize.Height() / nGridDY;
3534 	if( (nRows * nGridDY) < rSize.Height() )
3535 		nRows++;
3536 	if( !nRows )
3537 		nRows = 1;
3538 
3539 	nDeltaWidth = (short)(rSize.Width() / nCols);
3540 	nDeltaHeight = (short)(rSize.Height() / nRows);
3541 	if( !nDeltaHeight )
3542 	{
3543 		nDeltaHeight = 1;
3544 		DBG_WARNING("SetDeltas:Bad height");
3545 	}
3546 	if( !nDeltaWidth )
3547 	{
3548 		nDeltaWidth = 1;
3549 		DBG_WARNING("SetDeltas:Bad width");
3550 	}
3551 }
3552 
3553 
3554 void ImpIcnCursor::ExpandGrid()
3555 {
3556 	if( pGridMap )
3557 	{
3558 		long nNewGridRows = nGridRows + 20;
3559 		unsigned char* pTempMap = new unsigned char[ nNewGridRows * nGridCols ];
3560 		memcpy( pTempMap, pGridMap, nGridRows * nGridCols );
3561 		delete pGridMap;
3562 		pGridMap = pTempMap;
3563 		nGridRows = nNewGridRows;
3564 	}
3565 }
3566 
3567 sal_Bool ImpIcnCursor::FindEmptyGridRect( Rectangle& rRect )
3568 {
3569 	CreateGridMap();
3570 	sal_uInt16 nCount = (sal_uInt16)(nGridCols * nGridRows);
3571 	if( !nCount )
3572 		return sal_False;
3573 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3574 	{
3575 		if( !pGridMap[ nCur ] )
3576 		{
3577 			sal_uInt16 nCol = (sal_uInt16)(nCur % nGridCols);
3578 			sal_uInt16 nRow = (sal_uInt16)(nCur / nGridCols);
3579 			rRect.Top() = nRow * nGridDY + TBOFFS_WINBORDER;
3580 			rRect.Bottom() = rRect.Top() + nGridDY;
3581 			rRect.Left() = nCol * nGridDX+ LROFFS_WINBORDER;
3582 			rRect.Right() = rRect.Left() + nGridDX;
3583 			SetGridUsed( nCol, nRow, sal_True );
3584 
3585 			//XXX
3586 			//if( nRow + 5 > nGridRows )
3587 			//	ExpandGrid();
3588 			DBG_ASSERT(pGridMap[nCur],"SetGridUsed failed");
3589 			return sal_True;
3590 		}
3591 	}
3592 	// Gridmap ist voll: Um eine Zeile erweitern
3593 	rRect.Top() = nGridRows * nGridDY + TBOFFS_WINBORDER;
3594 	rRect.Bottom() = rRect.Top() + nGridDY;
3595 	rRect.Left() = LROFFS_WINBORDER;
3596 	rRect.Right() = rRect.Left() + nGridDX;
3597 	return sal_False;
3598 	//XXX
3599 	//ExpandGrid();
3600 	//return sal_True;
3601 }
3602 
3603 void ImpIcnCursor::CreateGridAjustData( SvPtrarr& rLists, SvLBoxEntry* pRefEntry)
3604 {
3605 	if( !pRefEntry )
3606 	{
3607 		sal_uInt16 nAdjustRows = (sal_uInt16)(pView->aVirtOutputSize.Height() / pView->nGridDY);
3608 		nAdjustRows++; // wg. Abrundung!
3609 
3610 		if( !nAdjustRows )
3611 			return;
3612 		for( sal_uInt16 nCurList = 0; nCurList < nAdjustRows; nCurList++ )
3613 		{
3614 			SvPtrarr* pRow = new SvPtrarr;
3615 			rLists.Insert( (void*)pRow, nCurList );
3616 		}
3617 		SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
3618 		while( pEntry )
3619 		{
3620 			const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3621 			short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
3622 			sal_uInt16 nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),sal_False);
3623 			((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns );
3624 			pEntry = pView->pModel->NextSibling( pEntry );
3625 		}
3626 	}
3627 	else
3628 	{
3629 		// Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile
3630 
3631 		// UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen???
3632 
3633 		Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
3634 		//const Rectangle& rRefRect = pView->GetBoundingRect( pRefEntry );
3635 		short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
3636 		SvPtrarr* pRow = new SvPtrarr;
3637 		rLists.Insert( (void*)pRow, 0 );
3638 		SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
3639 		while( pEntry )
3640 		{
3641 			Rectangle rRect( pView->CalcBmpRect(pEntry) );
3642 			//const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3643 			short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
3644 			if( nY == nRefRow )
3645 			{
3646 				sal_uInt16 nIns = GetSortListPos( pRow, rRect.Left(), sal_False );
3647 				pRow->Insert( pEntry, nIns );
3648 			}
3649 			pEntry = pView->pModel->NextSibling( pEntry );
3650 		}
3651 	}
3652 }
3653 
3654 //static
3655 void ImpIcnCursor::DestroyGridAdjustData( SvPtrarr& rLists )
3656 {
3657 	sal_uInt16 nCount = rLists.Count();
3658 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3659 	{
3660 		SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ];
3661 		delete pArr;
3662 	}
3663 	rLists.Remove( 0, rLists.Count() );
3664 }
3665 
3666 void SvImpIconView::SetGrid( long nDX, long nDY )
3667 {
3668 	nGridDX = nDX;
3669 	nGridDY = nDY;
3670 	nFlags |= F_GRIDMODE;
3671 }
3672 
3673 Rectangle SvImpIconView::CalcMaxTextRect( const SvLBoxEntry* pEntry,
3674 	const SvIcnVwDataEntry* pViewData ) const
3675 {
3676 	Rectangle aRect = pViewData->aGridRect;
3677 	long nBmpHeight = ((SvLBoxEntry*)pEntry)->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,(SvLBoxEntry*)pEntry).Height();
3678 	aRect.Top() += nBmpHeight;
3679 	aRect.Top() += ICONVIEW_OFFS_BMP_STRING;
3680 	if( aRect.Top() > aRect.Bottom())
3681 		aRect.Top() = aRect.Bottom();
3682 	aRect.Left() += LROFFS_BOUND;
3683 	aRect.Left()++;
3684 	aRect.Right() -= LROFFS_BOUND;
3685 	aRect.Right()--;
3686 	if( aRect.Left() > aRect.Right())
3687 		aRect.Left() = aRect.Right();
3688 	if( GetTextMode( pEntry, pViewData ) == ShowTextFull )
3689 		aRect.Bottom() = LONG_MAX;
3690 	return aRect;
3691 }
3692 
3693 void SvImpIconView::Center( SvLBoxEntry* pEntry,
3694 	SvIcnVwDataEntry* pViewData ) const
3695 {
3696 	SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3697 	const String& rEntryText = pStringItem->GetText();
3698 
3699 	Rectangle aTextRect = CalcMaxTextRect(pEntry,pViewData);
3700 	aTextRect = GetTextRect( pView, aTextRect, rEntryText, DRAWTEXT_FLAGS );
3701 	pViewData->aTextSize = aTextRect.GetSize();
3702 
3703 	pViewData->aRect = pViewData->aGridRect;
3704 	Size aSize( CalcBoundingSize( pEntry, pViewData ) );
3705 	long nBorder = pViewData->aGridRect.GetWidth() - aSize.Width();
3706 	pViewData->aRect.Left() += nBorder / 2;
3707 	pViewData->aRect.Right() -= nBorder / 2;
3708 	pViewData->aRect.Bottom() = pViewData->aRect.Top() + aSize.Height();
3709 }
3710 
3711 
3712 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3713 // links, hoch: Offsets < 0
3714 // rechts, runter: Offsets > 0
3715 void SvImpIconView::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar )
3716 {
3717 	const MapMode& rMapMode = pView->GetMapMode();
3718 	Point aOrigin( rMapMode.GetOrigin() );
3719 	// in Dokumentkoordinate umwandeln
3720 	aOrigin *= -1;
3721 	aOrigin.Y() += nDeltaY;
3722 	aOrigin.X() += nDeltaX;
3723 	Rectangle aRect( aOrigin, aOutputSize );
3724 	MakeVisible( aRect, bScrollBar );
3725 }
3726 
3727 
3728 const Size& SvImpIconView::GetItemSize( SvIconView* pIconView,
3729 	SvLBoxEntry* pEntry, SvLBoxItem* pItem, const SvIcnVwDataEntry* pViewData) const
3730 {
3731 	if( (nFlags & F_GRIDMODE) && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
3732 	{
3733 		if( !pViewData )
3734 			pViewData = ICNVIEWDATA(pEntry);
3735 		return pViewData->aTextSize;
3736 	}
3737 	else
3738 		return pItem->GetSize( pIconView, pEntry );
3739 }
3740 
3741 Rectangle SvImpIconView::CalcFocusRect( SvLBoxEntry* pEntry )
3742 {
3743 #if !defined(OS2)
3744 	SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3745 	DBG_ASSERT(pStringItem,"Text not set");
3746 	return CalcTextRect( pEntry, pStringItem );
3747 #else
3748 	return CalcBmpRect( pEntry );
3749 #endif
3750 }
3751 
3752 
3753 void SvImpIconView::SelectRect( const Rectangle& rRect, sal_Bool bAdd,
3754 	SvPtrarr* pOtherRects, short nBorderOffs )
3755 {
3756 	if( !pZOrderList || !pZOrderList->Count() )
3757 		return;
3758 
3759 	CheckBoundingRects();
3760 	pView->Update();
3761 	sal_uInt16 nCount = pZOrderList->Count();
3762 
3763 	Rectangle aRect( rRect );
3764 	aRect.Justify();
3765 	if( nBorderOffs )
3766 	{
3767 		aRect.Left() -= nBorderOffs;
3768 		aRect.Right() += nBorderOffs;
3769 		aRect.Top() -= nBorderOffs;
3770 		aRect.Bottom() += nBorderOffs;
3771 	}
3772 	sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False;
3773 
3774 	for( sal_uInt16 nPos = 0; nPos < nCount; nPos++ )
3775 	{
3776 		SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
3777 
3778 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
3779 		DBG_ASSERT(pViewData,"Entry not in model");
3780 		if( !IsBoundingRectValid( pViewData->aRect ))
3781 			FindBoundingRect( pEntry, pViewData );
3782 		const Rectangle& rBoundRect = pViewData->aRect;
3783 		sal_Bool bSelected = pViewData->IsSelected();
3784 
3785 		sal_Bool bOverlaps;
3786 		if( bCalcOverlap )
3787 			bOverlaps = IsOver( pOtherRects, rBoundRect );
3788 		else
3789 			bOverlaps = sal_False;
3790 		sal_Bool bOver = aRect.IsOver( rBoundRect );
3791 
3792 		if( bOver && !bOverlaps )
3793 		{
3794 			// Ist im neuen Selektionsrechteck und in keinem alten
3795 			// => selektieren
3796 			if( !bSelected )
3797 				pView->Select( pEntry, sal_True );
3798 		}
3799 		else if( !bAdd )
3800 		{
3801 			// ist ausserhalb des Selektionsrechtecks
3802 			// => Selektion entfernen
3803 			if( bSelected )
3804 				pView->Select( pEntry, sal_False );
3805 		}
3806 		else if( bAdd && bOverlaps )
3807 		{
3808 			// Der Eintrag befindet sich in einem alten (=>Aufspannen
3809 			// mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3810 
3811 			// Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3812 			// in einem vorherigen Rechteck, muss restauriert werden, wenn
3813 			// er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3814 			// nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3815 			// pauschal davon aus, dass die Eintraege in den alten Rechtecken
3816 			// alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3817 			// nur zu deselektieren.
3818 			// Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3819 			// spannen des Rechtecks merken
3820 			if( rBoundRect.IsOver( rRect))
3821 			{
3822 				// Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3823 				if( bSelected )
3824 					pView->Select( pEntry, sal_False );
3825 			}
3826 			else
3827 			{
3828 				// Eintrag eines alten Rects selektieren
3829 				if( !bSelected )
3830 					pView->Select( pEntry, sal_True );
3831 			}
3832 		}
3833 		else if( !bOver && bSelected )
3834 		{
3835 			// Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3836 			pView->Select( pEntry, sal_False );
3837 		}
3838 	}
3839 	pView->Update();
3840 }
3841 
3842 sal_Bool SvImpIconView::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3843 {
3844 	sal_uInt16 nCount = pRectList->Count();
3845 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3846 	{
3847 		Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3848 		if( rBoundRect.IsOver( *pRect ))
3849 			return sal_True;
3850 	}
3851 	return sal_False;
3852 }
3853 
3854 void SvImpIconView::AddSelectedRect( const Rectangle& rRect, short nBorderOffs )
3855 {
3856 	Rectangle* pRect = new Rectangle( rRect );
3857 	pRect->Justify();
3858 	if( nBorderOffs )
3859 	{
3860 		pRect->Left() -= nBorderOffs;
3861 		pRect->Right() += nBorderOffs;
3862 		pRect->Top() -= nBorderOffs;
3863 		pRect->Bottom() += nBorderOffs;
3864 	}
3865 	aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3866 }
3867 
3868 void SvImpIconView::ClearSelectedRectList()
3869 {
3870 	sal_uInt16 nCount = aSelectedRectList.Count();
3871 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
3872 	{
3873 		Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3874 		delete pRect;
3875 	}
3876 	aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3877 }
3878 
3879 
3880 void SvImpIconView::DrawSelectionRect( const Rectangle& rRect )
3881 {
3882 	pView->HideTracking();
3883 	nFlags |= F_SELRECT_VISIBLE;
3884 	pView->ShowTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
3885 	aCurSelectionRect = rRect;
3886 }
3887 
3888 void SvImpIconView::HideSelectionRect()
3889 {
3890 	if( nFlags & F_SELRECT_VISIBLE )
3891 	{
3892 		pView->HideTracking();
3893 		nFlags &= ~F_SELRECT_VISIBLE;
3894 	}
3895 }
3896 
3897 void SvImpIconView::ImpDrawXORRect( const Rectangle& rRect )
3898 {
3899 	RasterOp eOldOp = pView->GetRasterOp();
3900 	pView->SetRasterOp( ROP_XOR );
3901 	Color aOldColor = pView->GetFillColor();
3902 	pView->SetFillColor();
3903 	pView->DrawRect( rRect );
3904 	pView->SetFillColor( aOldColor );
3905 	pView->SetRasterOp( eOldOp );
3906 }
3907 
3908 void SvImpIconView::CalcScrollOffsets( const Point& rPosPixel,
3909 	long& rX, long& rY, sal_Bool bInDragDrop, sal_uInt16 nBorderWidth)
3910 {
3911 	// Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3912 	// Fensters befindet
3913 	long nPixelToScrollX = 0;
3914 	long nPixelToScrollY = 0;
3915 	Size aWndSize = aOutputSize;
3916 
3917 	nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3918 	nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3919 
3920 	if ( rPosPixel.X() < nBorderWidth )
3921 	{
3922 		if( bInDragDrop )
3923 			nPixelToScrollX = -DD_SCROLL_PIXEL;
3924 		else
3925 			nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3926 	}
3927 	else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3928 	{
3929 		if( bInDragDrop )
3930 			nPixelToScrollX = DD_SCROLL_PIXEL;
3931 		else
3932 			nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3933 	}
3934 	if ( rPosPixel.Y() < nBorderWidth )
3935 	{
3936 		if( bInDragDrop )
3937 			nPixelToScrollY = -DD_SCROLL_PIXEL;
3938 		else
3939 			nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3940 	}
3941 	else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3942 	{
3943 		if( bInDragDrop )
3944 			nPixelToScrollY = DD_SCROLL_PIXEL;
3945 		else
3946 			nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3947 	}
3948 
3949 	rX = nPixelToScrollX;
3950 	rY = nPixelToScrollY;
3951 }
3952 
3953 IMPL_LINK(SvImpIconView, MouseMoveTimeoutHdl, Timer*, pTimer )
3954 {
3955 	pTimer->Start();
3956 	MouseMove( aMouseMoveEvent );
3957 	return 0;
3958 }
3959 
3960 void SvImpIconView::EndTracking()
3961 {
3962 	pView->ReleaseMouse();
3963 	if( nFlags & F_RUBBERING )
3964 	{
3965 		aMouseMoveTimer.Stop();
3966 		nFlags &= ~(F_RUBBERING | F_ADD_MODE);
3967 	}
3968 }
3969 
3970 sal_Bool SvImpIconView::IsTextHit( SvLBoxEntry* pEntry, const Point& rDocPos )
3971 {
3972 	SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3973 	if( pItem )
3974 	{
3975 		Rectangle aRect( CalcTextRect( pEntry, pItem ));
3976 		if( aRect.IsInside( rDocPos ) )
3977 			return sal_True;
3978 	}
3979 	return sal_False;
3980 }
3981 
3982 IMPL_LINK(SvImpIconView, EditTimeoutHdl, Timer*, EMPTYARG )
3983 {
3984 	SvLBoxEntry* pEntry = GetCurEntry();
3985 	if( pView->IsInplaceEditingEnabled() && pEntry &&
3986 		pView->IsSelected( pEntry ))
3987 	{
3988 		pView->EditEntry( pEntry );
3989 	}
3990 	return 0;
3991 }
3992 
3993 
3994 //
3995 // Funktionen zum Ausrichten der Eintraege am Grid
3996 //
3997 
3998 // pStart == 0: Alle Eintraege werden ausgerichtet
3999 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
4000 void SvImpIconView::AdjustAtGrid( SvLBoxEntry* pStart )
4001 {
4002 	SvPtrarr aLists;
4003 	pImpCursor->CreateGridAjustData( aLists, pStart );
4004 	sal_uInt16 nCount = aLists.Count();
4005 	for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ )
4006 	{
4007 		AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
4008 	}
4009 	ImpIcnCursor::DestroyGridAdjustData( aLists );
4010 	CheckScrollBars();
4011 }
4012 
4013 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
4014 void SvImpIconView::AdjustAtGrid( const SvPtrarr& rRow, SvLBoxEntry* pStart )
4015 {
4016 	if( !rRow.Count() )
4017 		return;
4018 
4019 	sal_Bool bGo;
4020 	if( !pStart )
4021 		bGo = sal_True;
4022 	else
4023 		bGo = sal_False;
4024 
4025 	long nCurRight = 0;
4026 	for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ )
4027 	{
4028 		SvLBoxEntry* pCur = (SvLBoxEntry*)rRow[ nCur ];
4029 		if( !bGo && pCur == pStart )
4030 			bGo = sal_True;
4031 
4032 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
4033 		// Massgebend (fuer das menschliche Auge) ist die Bitmap, da sonst
4034 		// durch lange Texte der Eintrag stark springen kann
4035 		const Rectangle& rBoundRect = GetBoundingRect( pCur, pViewData );
4036 		Rectangle aCenterRect( CalcBmpRect( pCur, 0, pViewData ));
4037 		if( bGo && !pViewData->IsEntryPosLocked() )
4038 		{
4039 			long nWidth = aCenterRect.GetSize().Width();
4040 			Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
4041 			while( aNewPos.X() < nCurRight )
4042 				aNewPos.X() += nGridDX;
4043 			if( aNewPos != rBoundRect.TopLeft() )
4044 				SetEntryPosition( pCur, aNewPos );
4045 			nCurRight = aNewPos.X() + nWidth;
4046 		}
4047 		else
4048 		{
4049 			nCurRight = rBoundRect.Right();
4050 		}
4051 	}
4052 }
4053 
4054 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
4055 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
4056 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
4057 // die Berechnung des Ziel-Rechtecks verwendet wird.
4058 Point SvImpIconView::AdjustAtGrid( const Rectangle& rCenterRect,
4059 	const Rectangle& rBoundRect ) const
4060 {
4061 	Point aPos( rCenterRect.TopLeft() );
4062 	Size aSize( rCenterRect.GetSize() );
4063 
4064 	aPos.X() -= LROFFS_WINBORDER;
4065 	aPos.Y() -= TBOFFS_WINBORDER;
4066 
4067 	// align (ref ist mitte des rects)
4068 	short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
4069 	short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
4070 	aPos.X() = nGridX * nGridDX;
4071 	aPos.Y() = nGridY * nGridDY;
4072 	// hor. center
4073 	aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
4074 
4075 	aPos.X() += LROFFS_WINBORDER;
4076 	aPos.Y() += TBOFFS_WINBORDER;
4077 
4078 	return aPos;
4079 }
4080 
4081 
4082 void SvImpIconView::SetTextMode( SvIconViewTextMode eMode, SvLBoxEntry* pEntry )
4083 {
4084 	if( !pEntry )
4085 	{
4086 		if( eTextMode != eMode )
4087 		{
4088 			if( eTextMode == ShowTextDontKnow )
4089 				eTextMode = ShowTextShort;
4090 			eTextMode = eMode;
4091 			pView->Arrange();
4092 		}
4093 	}
4094 	else
4095 	{
4096 		SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
4097 		if( pViewData->eTextMode != eMode )
4098 		{
4099 			pViewData->eTextMode = eMode;
4100 			pModel->InvalidateEntry( pEntry );
4101 			AdjustVirtSize( pViewData->aRect );
4102 		}
4103 	}
4104 }
4105 
4106 SvIconViewTextMode SvImpIconView::GetTextMode( const SvLBoxEntry* pEntry,
4107 	const SvIcnVwDataEntry* pViewData ) const
4108 {
4109 	if( !pEntry )
4110 		return eTextMode;
4111 	else
4112 	{
4113 		if( !pViewData )
4114 			pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
4115 		return pViewData->GetTextMode();
4116 	}
4117 }
4118 
4119 SvIconViewTextMode SvImpIconView::GetEntryTextModeSmart( const SvLBoxEntry* pEntry,
4120 	const SvIcnVwDataEntry* pViewData ) const
4121 {
4122 	DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
4123 	if( !pViewData )
4124 		pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
4125 	SvIconViewTextMode eMode = pViewData->GetTextMode();
4126 	if( eMode == ShowTextDontKnow )
4127 		return eTextMode;
4128 	return eMode;
4129 }
4130 
4131 void SvImpIconView::ShowFocusRect( const SvLBoxEntry* pEntry )
4132 {
4133 	if( !pEntry )
4134 		pView->HideFocus();
4135 	else
4136 	{
4137 		Rectangle aRect ( CalcFocusRect( (SvLBoxEntry*)pEntry ) );
4138 		pView->ShowFocus( aRect );
4139 	}
4140 }
4141 
4142 IMPL_LINK(SvImpIconView, UserEventHdl, void*, EMPTYARG )
4143 {
4144 	nCurUserEvent = 0;
4145 	AdjustScrollBars();
4146 	Rectangle aRect;
4147 	if( GetResizeRect(aRect) )
4148 		PaintResizeRect( aRect );
4149 	return 0;
4150 }
4151 
4152 void SvImpIconView::CancelUserEvent()
4153 {
4154 	if( nCurUserEvent )
4155 	{
4156 		Application::RemoveUserEvent( nCurUserEvent );
4157 		nCurUserEvent = 0;
4158 	}
4159 }
4160 
4161 
4162