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