xref: /AOO41X/main/svtools/source/contnr/svimpicn.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
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