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