Update ooo320-m1
[ooovba.git] / svtools / source / contnr / svimpicn.cxx
blobe654a9066b2e35704e9e04433b2e96ee22e3b481
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svimpicn.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <limits.h>
35 #ifndef _METRIC_HXX
36 #include <vcl/metric.hxx>
37 #endif
38 #include <vcl/svapp.hxx>
39 #ifdef DBG_UTIL
40 #include <vcl/sound.hxx>
41 #endif
43 #include <svtools/svlbox.hxx>
44 #include <svtools/svicnvw.hxx>
45 #include <svimpicn.hxx>
46 #ifndef _SVLBITM_HXX
47 #include <svtools/svlbitm.hxx>
48 #endif
49 #include <svtools/svarray.hxx>
53 #define VIEWMODE_ICON 0x0001 // Text unter Bitmap
54 #define VIEWMODE_NAME 0x0002 // Text rechts neben Bitmap
55 #define VIEWMODE_TEXT 0x0004 // Text ohne Bitmap
57 #define DD_SCROLL_PIXEL 10
59 // alle Angaben in Pixel
61 #define ICONVIEW_OFFS_BMP_STRING 3
63 // fuer das Bounding-Rectangle
64 #define LROFFS_BOUND 2
65 #define TBOFFS_BOUND 2
67 // fuer das Focus-Rectangle um Icons
68 #define LROFFS_ICON 2
69 #define TBOFFS_ICON 2
71 #define NAMEVIEW_OFFS_BMP_STRING 3
73 // Abstaende von Fensterraendern
74 #define LROFFS_WINBORDER 4
75 #define TBOFFS_WINBORDER 4
77 // Breitenoffset Highlight-Rect bei Text
78 #define LROFFS_TEXT 2
81 #define ICNVIEWDATA(xPtr) (SvIcnVwDataEntry*)(pView->GetViewDataEntry(xPtr))
82 #define ICNVIEWDATA2(xPtr) (SvIcnVwDataEntry*)(pView->pView->GetViewDataEntry(xPtr))
84 //--------------------------------------------------------------------------
85 //--------------------------------------------------------------------------
86 //--------------------------------------------------------------------------
87 // -------------------------------------------------------------------------
88 // Hilfsfunktionen von Thomas Hosemann zur mehrzeiligen Ausgabe von
89 // Strings. Die Funktionen werden spaeter in StarView integriert.
90 // -------------------------------------------------------------------------
91 //--------------------------------------------------------------------------
92 //--------------------------------------------------------------------------
93 //--------------------------------------------------------------------------
95 // keine doppelten Defines
96 #ifdef TEXT_DRAW_CLIP
97 #undef TEXT_DRAW_CLIP
98 #endif
99 #ifdef TEXT_DRAW_MULTILINE
100 #undef TEXT_DRAW_MULTILINE
101 #endif
102 #ifdef TEXT_DRAW_WORDBREAK
103 #undef TEXT_DRAW_WORDBREAK
104 #endif
106 // #define TEXT_DRAW_DISABLE ((USHORT)0x0001)
107 // #define TEXT_DRAW_3DLOOK ((USHORT)0x0002)
108 // #define TEXT_DRAW_MNEMONIC ((USHORT)0x0004)
109 #define TEXT_DRAW_LEFT ((USHORT)0x0010)
110 #define TEXT_DRAW_CENTER ((USHORT)0x0020)
111 #define TEXT_DRAW_RIGHT ((USHORT)0x0040)
112 #define TEXT_DRAW_TOP ((USHORT)0x0080)
113 #define TEXT_DRAW_VCENTER ((USHORT)0x0100)
114 #define TEXT_DRAW_BOTTOM ((USHORT)0x0200)
115 #define TEXT_DRAW_ENDELLIPSIS ((USHORT)0x0400)
116 #define TEXT_DRAW_PATHELLIPSIS ((USHORT)0x0800)
117 #define TEXT_DRAW_CLIP ((USHORT)0x1000)
118 #define TEXT_DRAW_MULTILINE ((USHORT)0x2000)
119 #define TEXT_DRAW_WORDBREAK ((USHORT)0x4000)
121 XubString GetEllipsisString( OutputDevice* pDev,
122 const XubString& rStr, long nMaxWidth,
123 USHORT nStyle = TEXT_DRAW_ENDELLIPSIS )
125 XubString aStr = rStr;
127 if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
129 USHORT nIndex = pDev->GetTextBreak( rStr, nMaxWidth );
130 if ( nIndex != STRING_LEN )
132 aStr.Erase( nIndex );
133 if ( nIndex > 1 )
135 aStr.AppendAscii("...");
136 while ( aStr.Len() &&
137 (pDev->GetTextWidth( aStr ) > nMaxWidth) )
139 if ( (nIndex > 1) || (nIndex == aStr.Len()) )
140 nIndex--;
141 aStr.Erase( nIndex, 1 );
145 if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) )
146 aStr += rStr.GetChar( 0 );
150 return aStr;
153 class TextLineInfo
155 private:
156 long mnWidth;
157 USHORT mnIndex;
158 USHORT mnLen;
160 public:
161 TextLineInfo( long nWidth, USHORT nIndex, USHORT nLen )
163 mnWidth = nWidth;
164 mnIndex = nIndex;
165 mnLen = nLen;
168 long GetWidth() const { return mnWidth; }
169 USHORT GetIndex() const { return mnIndex; }
170 USHORT GetLen() const { return mnLen; }
173 #define MULTITEXTLINEINFO_RESIZE 16
174 typedef TextLineInfo* PTextLineInfo;
176 class MultiTextLineInfo
178 private:
179 PTextLineInfo* mpLines;
180 USHORT mnLines;
181 USHORT mnSize;
183 public:
184 MultiTextLineInfo();
185 ~MultiTextLineInfo();
187 void AddLine( TextLineInfo* pLine );
188 void Clear();
190 TextLineInfo* GetLine( USHORT nLine ) const
191 { return mpLines[nLine]; }
192 USHORT Count() const { return mnLines; }
194 private:
195 MultiTextLineInfo( const MultiTextLineInfo& );
196 MultiTextLineInfo& operator=( const MultiTextLineInfo& );
199 MultiTextLineInfo::MultiTextLineInfo()
201 mpLines = new PTextLineInfo[MULTITEXTLINEINFO_RESIZE];
202 mnLines = 0;
203 mnSize = MULTITEXTLINEINFO_RESIZE;
206 MultiTextLineInfo::~MultiTextLineInfo()
208 for ( USHORT i = 0; i < mnLines; i++ )
209 delete mpLines[i];
210 delete [] mpLines;
213 void MultiTextLineInfo::AddLine( TextLineInfo* pLine )
215 if ( mnSize == mnLines )
217 mnSize += MULTITEXTLINEINFO_RESIZE;
218 PTextLineInfo* pNewLines = new PTextLineInfo[mnSize];
219 memcpy( pNewLines, mpLines, mnLines*sizeof(PTextLineInfo) );
220 mpLines = pNewLines;
223 mpLines[mnLines] = pLine;
224 mnLines++;
227 void MultiTextLineInfo::Clear()
229 for ( USHORT i = 0; i < mnLines; i++ )
230 delete mpLines[i];
231 mnLines = 0;
234 // -----------------------------------------------------------------------
236 long GetTextLines( OutputDevice* pDev, MultiTextLineInfo& rLineInfo,
237 long nWidth, const XubString& rStr,
238 USHORT nStyle = TEXT_DRAW_WORDBREAK )
240 rLineInfo.Clear();
241 if ( !rStr.Len() )
242 return 0;
243 if ( nWidth <= 0 )
244 nWidth = 1;
246 USHORT nStartPos = 0; // Start-Position der Zeile
247 USHORT nLastLineLen = 0; // Zeilenlaenge bis zum vorherigen Wort
248 USHORT nLastWordPos = 0; // Position des letzten Wortanfangs
249 USHORT i = 0;
250 USHORT nPos; // StartPositon der Zeile (nur Temp)
251 USHORT nLen; // Laenge der Zeile (nur Temp)
252 USHORT nStrLen = rStr.Len();
253 long nMaxLineWidth = 0; // Maximale Zeilenlaenge
254 long nLineWidth; // Aktuelle Zeilenlaenge
255 long nLastLineWidth = 0; // Zeilenlaenge der letzten Zeile
256 xub_Unicode c;
257 xub_Unicode c2;
258 const xub_Unicode* pStr = rStr.GetBuffer();
259 BOOL bHardBreak = FALSE;
263 c = pStr[i];
265 // Auf Zeilenende ermitteln
266 if ( (c == _CR) || (c == _LF) )
267 bHardBreak = TRUE;
268 else
269 bHardBreak = FALSE;
271 // Testen, ob ein Wortende erreicht ist
272 if ( bHardBreak || (i == nStrLen) ||
273 (((c == ' ') || (c == '-')) && (nStyle & TEXT_DRAW_WORDBREAK)) )
275 nLen = i-nStartPos;
276 if ( c == '-' )
277 nLen++;
278 nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
280 // Findet ein Zeilenumbruch statt
281 if ( bHardBreak || (i == nStrLen) ||
282 ((nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK)) )
284 nPos = nStartPos;
286 if ( (nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK) )
288 nLineWidth = nLastLineWidth;
289 nLen = nLastLineLen;
290 nStartPos = nLastWordPos;
291 nLastLineLen = i-nStartPos;
292 nLastWordPos = nStartPos+nLastLineLen+1;
293 if ( c == '-' )
294 nLastLineLen++;
295 else if ( bHardBreak && (i > nStartPos) )
296 i--;
298 else
300 nStartPos = i;
301 // Zeilenende-Zeichen und '-' beruecksichtigen
302 if ( bHardBreak )
304 nStartPos++;
305 c2 = pStr[i+1];
306 if ( (c != c2) && ((c2 == _CR) || (c2 == _LF)) )
308 nStartPos++;
309 i++;
312 else if ( c != '-' )
313 nStartPos++;
314 nLastWordPos = nStartPos;
315 nLastLineLen = 0;
318 if ( nLineWidth > nMaxLineWidth )
319 nMaxLineWidth = nLineWidth;
321 if ( nLen || bHardBreak )
322 rLineInfo.AddLine( new TextLineInfo( nLineWidth, nPos, nLen ) );
324 // Testen, ob aktuelles Wort noch auf die Zeile passt,
325 // denn ansonsten mueessen wir es auftrennen
326 if ( nLastLineLen )
328 nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
329 if ( nLineWidth > nWidth )
331 // Wenn ein Wortumbruch in einem Wort stattfindet,
332 // ist die maximale Zeilenlaenge die Laenge
333 // des laengsten Wortes
334 if ( nLineWidth > nMaxLineWidth )
335 nMaxLineWidth = nLineWidth;
337 // Solange Wort auftrennen, bis es auf eine Zeile passt
340 nPos = pDev->GetTextBreak( rStr, nWidth, nStartPos, nLastLineLen );
341 nLen = nPos-nStartPos;
342 if ( !nLen )
344 nPos++;
345 nLen++;
347 nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen );
348 rLineInfo.AddLine( new TextLineInfo( nLineWidth, nStartPos, nLen ) );
349 nStartPos = nPos;
350 nLastLineLen = nLastLineLen - nLen;
351 nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen );
353 while ( nLineWidth > nWidth );
355 nLastLineWidth = nLineWidth;
357 // Bei Stringende muessen wir die letzte Zeile auch noch
358 // dranhaengen
359 if ( (i == nStrLen) && nLastLineLen )
360 rLineInfo.AddLine( new TextLineInfo( nLastLineWidth, nStartPos, nLastLineLen ) );
362 else
363 nLastLineWidth = 0;
365 else
367 nLastLineWidth = nLineWidth;
368 nLastLineLen = nLen;
369 nLastWordPos = nStartPos+nLastLineLen;
370 if ( c != '-' )
371 nLastWordPos++;
375 i++;
377 while ( i <= nStrLen );
379 return nMaxLineWidth;
382 // -----------------------------------------------------------------------
384 USHORT GetTextLines( OutputDevice* pDev, const Rectangle& rRect,
385 const XubString& rStr,
386 USHORT nStyle = TEXT_DRAW_WORDBREAK,
387 long* pMaxWidth = NULL )
389 MultiTextLineInfo aMultiLineInfo;
390 long nMaxWidth = GetTextLines( pDev, aMultiLineInfo,
391 rRect.GetWidth(), rStr, nStyle );
392 if ( pMaxWidth )
393 *pMaxWidth = nMaxWidth;
394 return aMultiLineInfo.Count();
397 // -----------------------------------------------------------------------
399 Rectangle GetTextRect( OutputDevice* pDev, const Rectangle& rRect,
400 const XubString& rStr,
401 USHORT nStyle = TEXT_DRAW_WORDBREAK )
403 Rectangle aRect = rRect;
404 USHORT nLines;
405 long nWidth = rRect.GetWidth();
406 long nMaxWidth;
407 long nTextHeight;
409 if ( nStyle & TEXT_DRAW_MULTILINE )
411 MultiTextLineInfo aMultiLineInfo;
412 TextLineInfo* pLineInfo;
413 USHORT nFormatLines;
415 nMaxWidth = 0;
416 GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
417 nFormatLines = aMultiLineInfo.Count();
418 nTextHeight = pDev->GetTextHeight();
419 nLines = (USHORT)(aRect.GetHeight()/nTextHeight);
420 if ( nFormatLines <= nLines )
421 nLines = nFormatLines;
422 else
424 if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) )
425 nLines = nFormatLines;
426 else
427 nMaxWidth = nWidth;
429 for ( USHORT i = 0; i < nLines; i++ )
431 pLineInfo = aMultiLineInfo.GetLine( i );
432 if ( pLineInfo->GetWidth() > nMaxWidth )
433 nMaxWidth = pLineInfo->GetWidth();
436 else
438 nLines = 1;
439 nMaxWidth = pDev->GetTextWidth( rStr );
440 nTextHeight = pDev->GetTextHeight();
441 if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ENDELLIPSIS) )
442 nMaxWidth = nWidth;
445 if ( nStyle & TEXT_DRAW_RIGHT )
446 aRect.Left() = aRect.Right()-nMaxWidth+1;
447 else if ( nStyle & TEXT_DRAW_CENTER )
449 aRect.Left() += (nWidth-nMaxWidth)/2;
450 aRect.Right() = aRect.Left()+nMaxWidth-1;
452 else
453 aRect.Right() = aRect.Left()+nMaxWidth-1;
455 if ( nStyle & TEXT_DRAW_BOTTOM )
456 aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1;
457 else if ( nStyle & TEXT_DRAW_VCENTER )
459 aRect.Top() += (aRect.GetHeight()-(nTextHeight*nLines))/2;
460 aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
462 else
463 aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
465 return aRect;
468 // -----------------------------------------------------------------------
470 void DrawText( OutputDevice* pDev, const Rectangle& rRect,
471 const XubString& rStr, USHORT nStyle = 0 )
473 if ( !rStr.Len() || rRect.IsEmpty() )
474 return;
476 Point aPos = rRect.TopLeft();
477 long nWidth = rRect.GetWidth();
478 long nHeight = rRect.GetHeight();
479 FontAlign eAlign = pDev->GetFont().GetAlign();
481 if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) )
482 return;
484 // Mehrzeiligen Text behandeln wir anders
485 if ( nStyle & TEXT_DRAW_MULTILINE )
487 String aLastLine;
488 Region aOldRegion;
489 MultiTextLineInfo aMultiLineInfo;
490 TextLineInfo* pLineInfo;
491 long nTextHeight = pDev->GetTextHeight();
492 long nMaxTextWidth;
493 USHORT i;
494 USHORT nLines = (USHORT)(nHeight/nTextHeight);
495 USHORT nFormatLines;
496 BOOL bIsClipRegion = FALSE;
497 nMaxTextWidth = GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle );
499 nFormatLines = aMultiLineInfo.Count();
500 if ( nFormatLines > nLines )
502 if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
504 // Letzte Zeile zusammenbauen und kuerzen
505 nFormatLines = nLines-1;
506 pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
507 aLastLine = rStr.Copy( pLineInfo->GetIndex() );
508 aLastLine.ConvertLineEnd( LINEEND_LF );
509 aLastLine.SearchAndReplace( _LF, ' ' );
510 aLastLine = GetEllipsisString( pDev, aLastLine, nWidth, nStyle );
511 nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
512 nStyle |= TEXT_DRAW_TOP;
515 else
517 if ( nMaxTextWidth <= nWidth )
518 nStyle &= ~TEXT_DRAW_CLIP;
521 // Clipping setzen
522 if ( nStyle & TEXT_DRAW_CLIP )
524 bIsClipRegion = pDev->IsClipRegion();
525 if ( bIsClipRegion )
527 aOldRegion = pDev->GetClipRegion();
528 pDev->IntersectClipRegion( rRect );
530 else
532 Region aRegion( rRect );
533 pDev->SetClipRegion( aRegion );
537 // Vertikales Alignment
538 if ( nStyle & TEXT_DRAW_BOTTOM )
539 aPos.Y() += nHeight-(nFormatLines*nTextHeight);
540 else if ( nStyle & TEXT_DRAW_VCENTER )
541 aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
543 // Font Alignment
544 if ( eAlign == ALIGN_BOTTOM )
545 aPos.Y() += nTextHeight;
546 else if ( eAlign == ALIGN_BASELINE )
547 aPos.Y() += pDev->GetFontMetric().GetAscent();
549 // Alle Zeilen ausgeben, bis auf die letzte
550 for ( i = 0; i < nFormatLines; i++ )
552 pLineInfo = aMultiLineInfo.GetLine( i );
553 if ( nStyle & TEXT_DRAW_RIGHT )
554 aPos.X() += nWidth-pLineInfo->GetWidth();
555 else if ( nStyle & TEXT_DRAW_CENTER )
556 aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
557 pDev->DrawText( aPos, rStr, pLineInfo->GetIndex(), pLineInfo->GetLen() );
558 aPos.Y() += nTextHeight;
559 aPos.X() = rRect.Left();
562 // Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
563 // da die Zeile gekuerzt wurde
564 if ( aLastLine.Len() )
565 pDev->DrawText( aPos, aLastLine );
567 // Clipping zuruecksetzen
568 if ( nStyle & TEXT_DRAW_CLIP )
570 if ( bIsClipRegion )
571 pDev->SetClipRegion( aOldRegion );
572 else
573 pDev->SetClipRegion();
576 else
578 XubString aStr = rStr;
579 Size aTextSize(pDev->GetTextWidth( aStr ), pDev->GetTextHeight());
581 // Evt. Text kuerzen
582 if ( aTextSize.Width() > nWidth )
584 if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
586 aStr = GetEllipsisString( pDev, rStr, nWidth, nStyle );
587 nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
588 nStyle |= TEXT_DRAW_LEFT;
589 aTextSize.Width() = pDev->GetTextWidth(aStr);
592 else
594 if ( aTextSize.Height() <= nHeight )
595 nStyle &= ~TEXT_DRAW_CLIP;
598 // Vertikales Alignment
599 if ( nStyle & TEXT_DRAW_RIGHT )
600 aPos.X() += nWidth-aTextSize.Width();
601 else if ( nStyle & TEXT_DRAW_CENTER )
602 aPos.X() += (nWidth-aTextSize.Width())/2;
604 // Font Alignment
605 if ( eAlign == ALIGN_BOTTOM )
606 aPos.Y() += aTextSize.Height();
607 else if ( eAlign == ALIGN_BASELINE )
608 aPos.Y() += pDev->GetFontMetric().GetAscent();
610 if ( nStyle & TEXT_DRAW_BOTTOM )
611 aPos.Y() += nHeight-aTextSize.Height();
612 else if ( nStyle & TEXT_DRAW_VCENTER )
613 aPos.Y() += (nHeight-aTextSize.Height())/2;
615 if ( nStyle & TEXT_DRAW_CLIP )
617 BOOL bIsClipRegion = pDev->IsClipRegion();
618 if ( bIsClipRegion )
620 Region aOldRegion = pDev->GetClipRegion();
621 pDev->IntersectClipRegion( rRect );
622 pDev->DrawText( aPos, aStr );
623 pDev->SetClipRegion( aOldRegion );
625 else
627 Region aRegion( rRect );
628 pDev->SetClipRegion( aRegion );
629 pDev->DrawText( aPos, aStr );
630 pDev->SetClipRegion();
633 else
634 pDev->DrawText( aPos, aStr );
638 // -----------------------------------------------------------------------
641 //--------------------------------------------------------------------------
642 //--------------------------------------------------------------------------
643 //--------------------------------------------------------------------------
646 #define DRAWTEXT_FLAGS (TEXT_DRAW_CENTER|TEXT_DRAW_TOP|TEXT_DRAW_ENDELLIPSIS|\
647 TEXT_DRAW_CLIP|TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK)
650 class ImpIcnCursor
652 SvImpIconView* pView;
653 SvPtrarr* pColumns;
654 SvPtrarr* pRows;
655 BOOL* pGridMap;
656 long nGridDX, nGridDY;
657 long nGridCols, nGridRows;
658 long nCols;
659 long nRows;
660 short nDeltaWidth;
661 short nDeltaHeight;
662 SvLBoxEntry* pCurEntry;
663 void SetDeltas();
664 void ImplCreate();
665 void Create() { if( !pColumns ) ImplCreate(); }
667 USHORT GetSortListPos( SvPtrarr* pList, long nValue, int bVertical);
668 SvLBoxEntry* SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,USHORT nPref,
669 BOOL bDown, BOOL bSimple );
670 SvLBoxEntry* SearchRow(USHORT nRow,USHORT nRight,USHORT nLeft,USHORT nPref,
671 BOOL bRight, BOOL bSimple );
673 void ExpandGrid();
674 void CreateGridMap();
675 // Rueckgabe FALSE: Eintrag liegt nicht in der GridMap. rGridx,y werden
676 // dann an nGridCols, nGridRows geclippt
677 BOOL GetGrid( const Point& rDocPos, USHORT& rGridX, USHORT& rGridY ) const;
678 void SetGridUsed( USHORT nDX, USHORT nDY, BOOL bUsed )
680 pGridMap[ (nDY * nGridCols) + nDX ] = bUsed;
682 BOOL IsGridUsed( USHORT nDX, USHORT nDY )
684 return pGridMap[ (nDY * nGridCols) + nDX ];
686 public:
687 ImpIcnCursor( SvImpIconView* pOwner );
688 ~ImpIcnCursor();
689 void Clear( BOOL bGridToo = TRUE );
691 // fuer Cursortravelling usw.
692 SvLBoxEntry* GoLeftRight( SvLBoxEntry*, BOOL bRight );
693 SvLBoxEntry* GoUpDown( SvLBoxEntry*, BOOL bDown );
695 // Rueckgaebe: FALSE == Das leere Rect steht hinter dem letzten
696 // Eintrag; d.h. beim naechsten Einfuegen ergibt sich das naechste
697 // leere Rechteck durch Addition. Hinweis: Das Rechteck kann dann
698 // ausserhalb des View-Space liegen
699 BOOL FindEmptyGridRect( Rectangle& rRect );
701 // Erzeugt fuer jede Zeile (Hoehe=nGridDY) eine nach BoundRect.Left()
702 // sortierte Liste der Eintraege, die in ihr stehen. Eine Liste kann
703 // leer sein. Die Listen gehen in das Eigentum des Rufenden ueber und
704 // muessen mit DestroyGridAdjustData geloescht werden
705 void CreateGridAjustData( SvPtrarr& pLists, SvLBoxEntry* pRow=0);
706 static void DestroyGridAdjustData( SvPtrarr& rLists );
707 void SetGridUsed( const Rectangle&, BOOL bUsed = TRUE );
713 SvImpIconView::SvImpIconView( SvIconView* pCurView, SvLBoxTreeList* pTree,
714 WinBits nWinStyle ) :
715 aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ),
716 aHorSBar( pCurView, WB_DRAG | WB_HSCROLL )
718 pView = pCurView;
719 pModel = pTree;
720 pCurParent = 0;
721 pZOrderList = new SvPtrarr;
722 SetWindowBits( nWinStyle );
723 nHorDist = 0;
724 nVerDist = 0;
725 nFlags = 0;
726 nCurUserEvent = 0;
727 nMaxVirtWidth = 200;
728 pDDRefEntry = 0;
729 pDDDev = 0;
730 pDDBufDev = 0;
731 pDDTempDev = 0;
732 eTextMode = ShowTextShort;
733 pImpCursor = new ImpIcnCursor( this );
735 aVerSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollUpDownHdl ) );
736 aHorSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollLeftRightHdl ) );
737 nHorSBarHeight = aHorSBar.GetSizePixel().Height();
738 nVerSBarWidth = aVerSBar.GetSizePixel().Width();
740 aMouseMoveTimer.SetTimeout( 20 );
741 aMouseMoveTimer.SetTimeoutHdl(LINK(this,SvImpIconView,MouseMoveTimeoutHdl));
743 aEditTimer.SetTimeout( 800 );
744 aEditTimer.SetTimeoutHdl(LINK(this,SvImpIconView,EditTimeoutHdl));
746 Clear( TRUE );
749 SvImpIconView::~SvImpIconView()
751 StopEditTimer();
752 CancelUserEvent();
753 delete pZOrderList;
754 delete pImpCursor;
755 delete pDDDev;
756 delete pDDBufDev;
757 delete pDDTempDev;
758 ClearSelectedRectList();
761 void SvImpIconView::Clear( BOOL bInCtor )
763 StopEditTimer();
764 CancelUserEvent();
765 nMaxBmpWidth = 0;
766 nMaxBmpHeight = 0;
767 nMaxTextWidth = 0;
768 bMustRecalcBoundingRects = FALSE;
769 nMaxBoundHeight = 0;
771 //XXX
772 nFlags |= F_GRID_INSERT;
773 nFlags &= ~F_PAINTED;
774 SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
775 pCursor = 0;
776 if( !bInCtor )
778 pImpCursor->Clear();
779 aVirtOutputSize.Width() = 0;
780 aVirtOutputSize.Height() = 0;
781 pZOrderList->Remove(0,pZOrderList->Count());
782 MapMode aMapMode( pView->GetMapMode());
783 aMapMode.SetOrigin( Point() );
784 pView->SetMapMode( aMapMode );
785 if( pView->IsUpdateMode() )
786 pView->Invalidate();
788 AdjustScrollBars();
791 void SvImpIconView::SetWindowBits( WinBits nWinStyle )
793 nWinBits = nWinStyle;
794 nViewMode = VIEWMODE_TEXT;
795 if( nWinStyle & WB_NAME )
796 nViewMode = VIEWMODE_NAME;
797 if( nWinStyle & WB_ICON )
798 nViewMode = VIEWMODE_ICON;
802 IMPL_LINK( SvImpIconView, ScrollUpDownHdl, ScrollBar *, pScrollBar )
804 pView->EndEditing( TRUE );
805 // Pfeil hoch: delta=-1; Pfeil runter: delta=+1
806 Scroll( 0, pScrollBar->GetDelta(), TRUE );
807 return 0;
810 IMPL_LINK( SvImpIconView, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
812 pView->EndEditing( TRUE );
813 // Pfeil links: delta=-1; Pfeil rechts: delta=+1
814 Scroll( pScrollBar->GetDelta(), 0, TRUE );
815 return 0;
818 void SvImpIconView::ChangedFont()
820 StopEditTimer();
821 ImpArrange();
825 void SvImpIconView::CheckAllSizes()
827 nMaxTextWidth = 0;
828 nMaxBmpWidth = 0;
829 nMaxBmpHeight = 0;
830 SvLBoxEntry* pEntry = pModel->First();
831 while( pEntry )
833 CheckSizes( pEntry );
834 pEntry = pModel->Next( pEntry );
838 void SvImpIconView::CheckSizes( SvLBoxEntry* pEntry,
839 const SvIcnVwDataEntry* pViewData )
841 Size aSize;
843 if( !pViewData )
844 pViewData = ICNVIEWDATA(pEntry);
846 SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
847 if( pStringItem )
849 aSize = GetItemSize( pView, pEntry, pStringItem, pViewData );
850 if( aSize.Width() > nMaxTextWidth )
852 nMaxTextWidth = aSize.Width();
853 if( !(nFlags & F_GRIDMODE ) )
854 bMustRecalcBoundingRects = TRUE;
857 SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
858 if( pBmpItem )
860 aSize = GetItemSize( pView, pEntry, pBmpItem, pViewData );
861 if( aSize.Width() > nMaxBmpWidth )
863 nMaxBmpWidth = aSize.Width();
864 nMaxBmpWidth += (2*LROFFS_ICON);
865 if( !(nFlags & F_GRIDMODE ) )
866 bMustRecalcBoundingRects = TRUE;
868 if( aSize.Height() > nMaxBmpHeight )
870 nMaxBmpHeight = aSize.Height();
871 nMaxBmpHeight += (2*TBOFFS_ICON);;
872 if( !(nFlags & F_GRIDMODE ) )
873 bMustRecalcBoundingRects = TRUE;
878 void SvImpIconView::EntryInserted( SvLBoxEntry* pEntry )
880 if( pModel->GetParent(pEntry) == pCurParent )
882 StopEditTimer();
883 DBG_ASSERT(pZOrderList->GetPos(pEntry)==0xffff,"EntryInserted:ZOrder?");
884 pZOrderList->Insert( pEntry, pZOrderList->Count() );
885 if( nFlags & F_GRIDMODE )
886 pImpCursor->Clear( FALSE );
887 else
888 pImpCursor->Clear( TRUE );
889 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
890 CheckSizes( pEntry, pViewData );
891 if( pView->IsUpdateMode() )
893 FindBoundingRect( pEntry, pViewData );
894 PaintEntry( pEntry, pViewData );
896 else
897 InvalidateBoundingRect( pViewData->aRect );
901 void SvImpIconView::RemovingEntry( SvLBoxEntry* pEntry )
903 if( pModel->GetParent(pEntry) == pCurParent)
905 StopEditTimer();
906 DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"RemovingEntry:ZOrder?");
907 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
908 if( IsBoundingRectValid( pViewData->aRect ) )
910 // bei gueltigem Bounding-Rect muss in EntryRemoved eine
911 // Sonderbehandlung erfolgen
912 nFlags |= F_ENTRY_REMOVED;
913 pView->Invalidate( pViewData->aRect );
915 if( pEntry == pCursor )
917 SvLBoxEntry* pNewCursor = GetNewCursor();
918 ShowCursor( FALSE );
919 pCursor = 0; // damit er nicht deselektiert wird
920 SetCursor( pNewCursor );
922 USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
923 pZOrderList->Remove( nPos, 1 );
924 pImpCursor->Clear();
928 void SvImpIconView::EntryRemoved()
930 if( (nFlags & (F_ENTRY_REMOVED | F_PAINTED)) == (F_ENTRY_REMOVED | F_PAINTED))
932 // Ein Eintrag mit gueltigem BoundRect wurde geloescht und wir
933 // haben schon mal gepaintet. In diesem Fall muessen wir die
934 // Position des naechsten Eintrags, der eingefuegt wird oder noch
935 // kein gueltiges BoundRect hat, "suchen" d.h. ein "Loch" in
936 // der View auffuellen.
937 nFlags &= ~( F_ENTRY_REMOVED | F_GRID_INSERT );
942 void SvImpIconView::MovingEntry( SvLBoxEntry* pEntry )
944 DBG_ASSERT(pEntry,"MovingEntry: 0!");
945 pNextCursor = 0;
946 StopEditTimer();
947 if( pModel->GetParent(pEntry) == pCurParent )
949 DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"MovingEntry:ZOrder?");
950 nFlags |= F_MOVING_SIBLING;
951 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
952 if( IsBoundingRectValid( pViewData->aRect ) )
953 pView->Invalidate( pViewData->aRect );
954 // falls Eintrag seinen Parent wechselt vorsichtshalber
955 // die neue Cursorposition berechnen
956 if( pEntry == pCursor )
957 pNextCursor = GetNewCursor();
958 pImpCursor->Clear();
963 void SvImpIconView::EntryMoved( SvLBoxEntry* pEntry )
965 ShowCursor( FALSE );
966 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
967 if( pModel->GetParent(pEntry)==pCurParent )
969 if( nFlags & F_MOVING_SIBLING )
971 // die Neu-Positionierung eines Eintrags bei D&D innerhalb
972 // einer IconView findet bereits in NotifyMoving statt
973 // (MovingEntry/EntryMoved wird dann nicht mehr gerufen)
974 ToTop( pEntry );
976 else
978 pImpCursor->Clear();
979 pZOrderList->Insert( pEntry, pZOrderList->Count() );
980 DBG_ASSERT(pZOrderList->Count()==pModel->GetChildCount(pCurParent),"EntryMoved:Bad zorder count");
981 FindBoundingRect( pEntry, pViewData );
983 PaintEntry( pEntry, pViewData );
985 else
987 if( pEntry == pCursor )
989 DBG_ASSERT(pNextCursor,"EntryMoved: Next cursor bad");
990 SetCursor( pNextCursor );
992 pImpCursor->Clear();
993 USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
994 pZOrderList->Remove( nPos, 1 );
995 pView->Select( pEntry, FALSE );
996 // wenn er nochmal in dieser View auftaucht, muss sein
997 // Bounding-Rect neu berechnet werden
998 InvalidateBoundingRect( pViewData->aRect );
1000 nFlags &= (~F_MOVING_SIBLING);
1003 void SvImpIconView::TreeInserted( SvLBoxEntry* pEntry )
1005 EntryMoved( pEntry ); // vorlaeufig
1008 void SvImpIconView::EntryExpanded( SvLBoxEntry* )
1012 void SvImpIconView::EntryCollapsed( SvLBoxEntry*)
1016 void SvImpIconView::CollapsingEntry( SvLBoxEntry* )
1020 void SvImpIconView::EntrySelected( SvLBoxEntry* pEntry, BOOL bSelect )
1022 if( pModel->GetParent(pEntry) != pCurParent )
1023 return;
1025 // bei SingleSelection dafuer sorgen, dass der Cursor immer
1026 // auf dem (einzigen) selektierten Eintrag steht
1027 if( bSelect && pCursor &&
1028 pView->GetSelectionMode() == SINGLE_SELECTION &&
1029 pEntry != pCursor )
1031 SetCursor( pEntry );
1032 DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1034 // bei Gummibandselektion ist uns das zu teuer
1035 if( !(nFlags & F_RUBBERING ))
1036 ToTop( pEntry );
1037 if( pView->IsUpdateMode() )
1039 if( pEntry == pCursor )
1040 ShowCursor( FALSE );
1041 if( nFlags & F_RUBBERING )
1042 PaintEntry( pEntry );
1043 else
1044 pView->Invalidate( GetBoundingRect( pEntry ) );
1045 if( pEntry == pCursor )
1046 ShowCursor( TRUE );
1050 void SvImpIconView::SetNextEntryPos(const Point& rPos)
1052 aPrevBoundRect.SetPos( rPos );
1053 aPrevBoundRect.Right() = LONG_MAX; // dont know
1056 Point SvImpIconView::FindNextEntryPos( const Size& rBoundSize )
1058 if( nFlags & F_GRIDMODE )
1060 if( nFlags & F_GRID_INSERT )
1062 if( aPrevBoundRect.Right() != LONG_MAX )
1064 // passt der naechste Entry noch in die Zeile ?
1065 long nNextWidth = aPrevBoundRect.Right() + nGridDX + LROFFS_WINBORDER;
1066 if( nNextWidth > aVirtOutputSize.Width() )
1068 // darf aVirtOutputSize verbreitert werden ?
1069 if( nNextWidth < nMaxVirtWidth )
1071 // verbreitern & in Zeile aufnehmen
1072 aPrevBoundRect.Left() += nGridDX;
1074 else
1076 // erhoehen & neue Zeile beginnen
1077 aPrevBoundRect.Top() += nGridDY;
1078 aPrevBoundRect.Left() = LROFFS_WINBORDER;
1081 else
1083 // in die Zeile aufnehmen
1084 aPrevBoundRect.Left() += nGridDX;
1087 aPrevBoundRect.SetSize( Size( nGridDX, nGridDY ) );
1089 else
1091 if( !pImpCursor->FindEmptyGridRect( aPrevBoundRect ) )
1093 // mitten in den Entries gibts keine Loecher mehr,
1094 // wir koennen also wieder ins "Fast Insert" springen
1095 nFlags |= F_GRID_INSERT;
1099 else
1101 if( aPrevBoundRect.Right() != LONG_MAX )
1103 // passt der naechste Entry noch in die Zeile ?
1104 long nNextWidth=aPrevBoundRect.Right()+rBoundSize.Width()+LROFFS_BOUND+nHorDist;
1105 if( nNextWidth > aVirtOutputSize.Width() )
1107 // darf aVirtOutputSize verbreitert werden ?
1108 if( nNextWidth < nMaxVirtWidth )
1110 // verbreitern & in Zeile aufnehmen
1111 aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
1112 aPrevBoundRect.Left() += nHorDist;
1114 else
1116 // erhoehen & neue Zeile beginnen
1117 aPrevBoundRect.Top() += nMaxBoundHeight + nVerDist + TBOFFS_BOUND;
1118 aPrevBoundRect.Left() = LROFFS_WINBORDER;
1121 else
1123 // in die Zeile aufnehmen
1124 aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() );
1125 aPrevBoundRect.Left() += nHorDist;
1128 aPrevBoundRect.SetSize( rBoundSize );
1130 return aPrevBoundRect.TopLeft();
1133 void SvImpIconView::ResetVirtSize()
1135 StopEditTimer();
1136 aVirtOutputSize.Width() = 0;
1137 aVirtOutputSize.Height() = 0;
1138 BOOL bLockedEntryFound = FALSE;
1139 nFlags &= (~F_GRID_INSERT);
1140 SvLBoxEntry* pCur = pModel->FirstChild( pCurParent );
1141 while( pCur )
1143 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
1144 if( pViewData->IsEntryPosLocked() )
1146 // VirtSize u.a. anpassen
1147 if( !IsBoundingRectValid( pViewData->aRect ) )
1148 FindBoundingRect( pCur, pViewData );
1149 else
1150 AdjustVirtSize( pViewData->aRect );
1151 bLockedEntryFound = TRUE;
1153 else
1154 InvalidateBoundingRect( pViewData->aRect );
1156 pCur = pModel->NextSibling( pCur );
1158 if( !bLockedEntryFound )
1160 //XXX
1161 nFlags |= F_GRID_INSERT;
1164 SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) );
1165 pImpCursor->Clear();
1169 void SvImpIconView::AdjustVirtSize( const Rectangle& rRect )
1171 long nHeightOffs = 0;
1172 long nWidthOffs = 0;
1174 if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) )
1175 nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width();
1177 if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) )
1178 nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height();
1180 if( nWidthOffs || nHeightOffs )
1182 Range aRange;
1183 aVirtOutputSize.Width() += nWidthOffs;
1184 aRange.Max() = aVirtOutputSize.Width();
1185 aHorSBar.SetRange( aRange );
1187 aVirtOutputSize.Height() += nHeightOffs;
1188 aRange.Max() = aVirtOutputSize.Height();
1189 aVerSBar.SetRange( aRange );
1191 pImpCursor->Clear();
1192 AdjustScrollBars();
1196 void SvImpIconView::Arrange()
1198 nMaxVirtWidth = aOutputSize.Width();
1199 ImpArrange();
1202 void SvImpIconView::ImpArrange()
1204 StopEditTimer();
1205 ShowCursor( FALSE );
1206 ResetVirtSize();
1207 bMustRecalcBoundingRects = FALSE;
1208 MapMode aMapMode( pView->GetMapMode());
1209 aMapMode.SetOrigin( Point() );
1210 pView->SetMapMode( aMapMode );
1211 CheckAllSizes();
1212 RecalcAllBoundingRectsSmart();
1213 pView->Invalidate();
1214 ShowCursor( TRUE );
1217 void SvImpIconView::Paint( const Rectangle& rRect )
1219 if( !pView->IsUpdateMode() )
1220 return;
1222 #if defined(DBG_UTIL) && defined(OV_DRAWGRID)
1223 if( nFlags & F_GRIDMODE )
1225 Color aOldColor = pView->GetLineColor();
1226 Color aNewColor( COL_BLACK );
1227 pView->SetLineColor( aNewColor );
1228 Point aOffs( pView->GetMapMode().GetOrigin());
1229 Size aXSize( pView->GetOutputSizePixel() );
1230 for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX )
1232 Point aStart( nDX+LROFFS_BOUND, 0 );
1233 Point aEnd( nDX+LROFFS_BOUND, aXSize.Height());
1234 aStart -= aOffs;
1235 aEnd -= aOffs;
1236 pView->DrawLine( aStart, aEnd );
1238 for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY )
1240 Point aStart( 0, nDY+TBOFFS_BOUND );
1241 Point aEnd( aXSize.Width(), nDY+TBOFFS_BOUND );
1242 aStart -= aOffs;
1243 aEnd -= aOffs;
1244 pView->DrawLine( aStart, aEnd );
1246 pView->SetLineColor( aOldColor );
1248 #endif
1249 nFlags |= F_PAINTED;
1251 if( !(pModel->HasChilds( pCurParent ) ))
1252 return;
1253 if( !pCursor )
1254 pCursor = pModel->FirstChild( pCurParent );
1256 USHORT nCount = pZOrderList->Count();
1257 if( !nCount )
1258 return;
1260 SvPtrarr* pNewZOrderList = new SvPtrarr;
1261 SvPtrarr* pPaintedEntries = new SvPtrarr;
1263 USHORT nPos = 0;
1264 while( nCount )
1266 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
1267 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
1268 const Rectangle& rBoundRect = GetBoundingRect( pEntry, pViewData );
1269 if( rRect.IsOver( rBoundRect ) )
1271 PaintEntry( pEntry, rBoundRect.TopLeft(), pViewData );
1272 // Eintraege, die neu gezeichnet werden, auf Top setzen
1273 pPaintedEntries->Insert( pEntry, pPaintedEntries->Count() );
1275 else
1276 pNewZOrderList->Insert( pEntry, pNewZOrderList->Count() );
1278 nCount--;
1279 nPos++;
1281 delete pZOrderList;
1282 pZOrderList = pNewZOrderList;
1283 nCount = pPaintedEntries->Count();
1284 if( nCount )
1286 for( USHORT nCur = 0; nCur < nCount; nCur++ )
1287 pZOrderList->Insert( pPaintedEntries->GetObject( nCur ),pZOrderList->Count());
1289 delete pPaintedEntries;
1291 Rectangle aRect;
1292 if( GetResizeRect( aRect ))
1293 PaintResizeRect( aRect );
1296 BOOL SvImpIconView::GetResizeRect( Rectangle& rRect )
1298 if( aHorSBar.IsVisible() && aVerSBar.IsVisible() )
1300 const MapMode& rMapMode = pView->GetMapMode();
1301 Point aOrigin( rMapMode.GetOrigin());
1302 aOrigin *= -1;
1303 aOrigin.X() += aOutputSize.Width();
1304 aOrigin.Y() += aOutputSize.Height();
1305 rRect.SetPos( aOrigin );
1306 rRect.SetSize( Size( nVerSBarWidth, nHorSBarHeight));
1307 return TRUE;
1309 return FALSE;
1312 void SvImpIconView::PaintResizeRect( const Rectangle& rRect )
1314 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1315 Color aNewColor = rStyleSettings.GetFaceColor();
1316 Color aOldColor = pView->GetFillColor();
1317 pView->SetFillColor( aNewColor );
1318 pView->DrawRect( rRect );
1319 pView->SetFillColor( aOldColor );
1322 void SvImpIconView::RepaintSelectionItems()
1324 DBG_ERROR("RepaintSelectionItems");
1325 pView->Invalidate(); // vorlaeufig
1328 SvLBoxItem* SvImpIconView::GetItem( SvLBoxEntry* pEntry,
1329 const Point& rAbsPos )
1331 Rectangle aRect;
1332 SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
1333 if( pStringItem )
1335 aRect = CalcTextRect( pEntry, pStringItem );
1336 if( aRect.IsInside( rAbsPos ) )
1337 return pStringItem;
1339 SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1340 if( pBmpItem )
1342 aRect = CalcBmpRect( pEntry );
1343 if( aRect.IsInside( rAbsPos ) )
1344 return pBmpItem;
1346 return 0;
1349 void SvImpIconView::CalcDocPos( Point& aMaeuschenPos )
1351 aMaeuschenPos -= pView->GetMapMode().GetOrigin();
1354 void SvImpIconView::MouseButtonDown( const MouseEvent& rMEvt)
1356 StopEditTimer();
1357 pView->GrabFocus();
1358 Point aDocPos( rMEvt.GetPosPixel() );
1359 if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height())
1360 return;
1361 CalcDocPos( aDocPos );
1362 SvLBoxEntry* pEntry = GetEntry( aDocPos );
1363 if( !pEntry )
1365 if( pView->GetSelectionMode() != SINGLE_SELECTION )
1367 if( !rMEvt.IsMod1() ) // Ctrl
1369 pView->SelectAll( FALSE );
1370 ClearSelectedRectList();
1372 else
1373 nFlags |= F_ADD_MODE;
1374 nFlags |= F_RUBBERING;
1375 aCurSelectionRect.SetPos( aDocPos );
1376 pView->CaptureMouse();
1378 return;
1381 BOOL bSelected = pView->IsSelected( pEntry );
1382 BOOL bEditingEnabled = pView->IsInplaceEditingEnabled();
1384 if( rMEvt.GetClicks() == 2 )
1386 DeselectAllBut( pEntry );
1387 pView->pHdlEntry = pEntry;
1388 pView->DoubleClickHdl();
1390 else
1392 // Inplace-Editing ?
1393 if( rMEvt.IsMod2() ) // Alt?
1395 if( bEditingEnabled )
1397 SvLBoxItem* pItem = GetItem(pEntry,aDocPos);
1398 if( pItem )
1399 pView->EditingRequest( pEntry, pItem, aDocPos);
1402 else if( pView->GetSelectionMode() == SINGLE_SELECTION )
1404 DeselectAllBut( pEntry );
1405 SetCursor( pEntry );
1406 pView->Select( pEntry, TRUE );
1407 if( bEditingEnabled && bSelected && !rMEvt.GetModifier() &&
1408 rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) )
1410 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1413 else
1415 if( !rMEvt.GetModifier() )
1417 if( !bSelected )
1419 DeselectAllBut( pEntry );
1420 SetCursor( pEntry );
1421 pView->Select( pEntry, TRUE );
1423 else
1425 // erst im Up deselektieren, falls Move per D&D!
1426 nFlags |= F_DOWN_DESELECT;
1427 if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) &&
1428 rMEvt.IsLeft())
1430 nFlags |= F_START_EDITTIMER_IN_MOUSEUP;
1434 else if( rMEvt.IsMod1() )
1435 nFlags |= F_DOWN_CTRL;
1440 void SvImpIconView::MouseButtonUp( const MouseEvent& rMEvt )
1442 aMouseMoveTimer.Stop();
1443 pView->ReleaseMouse();
1444 // HACK, da Einar noch nicht PrepareCommandEvent aufruft
1445 if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) ))
1446 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1448 if( nFlags & F_RUBBERING )
1450 aMouseMoveTimer.Stop();
1451 AddSelectedRect( aCurSelectionRect );
1452 HideSelectionRect();
1453 nFlags &= ~(F_RUBBERING | F_ADD_MODE);
1456 SvLBoxEntry* pEntry = pView->GetEntry( rMEvt.GetPosPixel(), TRUE );
1457 if( pEntry )
1459 if( nFlags & F_DOWN_CTRL )
1461 // Ctrl & MultiSelection
1462 ToggleSelection( pEntry );
1463 SetCursor( pEntry );
1465 else if( nFlags & F_DOWN_DESELECT )
1467 DeselectAllBut( pEntry );
1468 SetCursor( pEntry );
1469 pView->Select( pEntry, TRUE );
1473 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
1474 if( nFlags & F_START_EDITTIMER_IN_MOUSEUP )
1476 StartEditTimer();
1477 nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP;
1481 void SvImpIconView::MouseMove( const MouseEvent& rMEvt )
1483 if( nFlags & F_RUBBERING )
1485 const Point& rPosPixel = rMEvt.GetPosPixel();
1486 if( !aMouseMoveTimer.IsActive() )
1488 aMouseMoveEvent = rMEvt;
1489 aMouseMoveTimer.Start();
1490 // ausserhalb des Fensters liegende Move-Events muessen
1491 // vom Timer kommen, damit die Scrollgeschwindigkeit
1492 // unabhaengig von Mausbewegungen ist.
1493 if( rPosPixel.X() < 0 || rPosPixel.Y() < 0 )
1494 return;
1495 const Size& rSize = pView->GetOutputSizePixel();
1496 if( rPosPixel.X() > rSize.Width() || rPosPixel.Y() > rSize.Height())
1497 return;
1500 if( &rMEvt != &aMouseMoveEvent )
1501 aMouseMoveEvent = rMEvt;
1503 long nScrollDX, nScrollDY;
1505 CalcScrollOffsets(rMEvt.GetPosPixel(),nScrollDX,nScrollDY,FALSE );
1506 BOOL bSelRectHidden = FALSE;
1507 if( nScrollDX || nScrollDY )
1509 HideSelectionRect();
1510 bSelRectHidden = TRUE;
1511 pView->Scroll( nScrollDX, nScrollDY );
1513 Point aDocPos( rMEvt.GetPosPixel() );
1514 aDocPos = pView->PixelToLogic( aDocPos );
1515 Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos );
1516 if( aRect != aCurSelectionRect )
1518 HideSelectionRect();
1519 bSelRectHidden = TRUE;
1520 BOOL bAdd = (nFlags & F_ADD_MODE) ? TRUE : FALSE;
1521 SelectRect( aRect, bAdd, &aSelectedRectList );
1523 if( bSelRectHidden )
1524 DrawSelectionRect( aRect );
1528 BOOL SvImpIconView::KeyInput( const KeyEvent& rKEvt )
1530 StopEditTimer();
1531 BOOL bKeyUsed = TRUE;
1532 BOOL bMod1 = rKEvt.GetKeyCode().IsMod1();
1533 BOOL bInAddMode = (BOOL)((nFlags & F_ADD_MODE) != 0);
1534 int bDeselAll = (pView->GetSelectionMode() != SINGLE_SELECTION) &&
1535 !bInAddMode;
1536 SvLBoxEntry* pNewCursor;
1537 USHORT nCode = rKEvt.GetKeyCode().GetCode();
1538 switch( nCode )
1540 case KEY_UP:
1541 if( pCursor )
1543 MakeVisible( pCursor );
1544 pNewCursor = pImpCursor->GoUpDown(pCursor,FALSE);
1545 if( pNewCursor )
1547 if( bDeselAll )
1548 pView->SelectAll( FALSE );
1549 ShowCursor( FALSE );
1550 MakeVisible( pNewCursor );
1551 SetCursor( pNewCursor );
1552 if( !bInAddMode )
1553 pView->Select( pCursor, TRUE );
1555 else
1557 Rectangle aRect( GetBoundingRect( pCursor ) );
1558 if( aRect.Top())
1560 aRect.Bottom() -= aRect.Top();
1561 aRect.Top() = 0;
1562 MakeVisible( aRect );
1566 break;
1568 case KEY_DOWN:
1569 if( pCursor )
1571 pNewCursor=pImpCursor->GoUpDown( pCursor,TRUE );
1572 if( pNewCursor )
1574 MakeVisible( pCursor );
1575 if( bDeselAll )
1576 pView->SelectAll( FALSE );
1577 ShowCursor( FALSE );
1578 MakeVisible( pNewCursor );
1579 SetCursor( pNewCursor );
1580 if( !bInAddMode )
1581 pView->Select( pCursor, TRUE );
1584 break;
1586 case KEY_RIGHT:
1587 if( pCursor )
1589 pNewCursor=pImpCursor->GoLeftRight(pCursor,TRUE );
1590 if( pNewCursor )
1592 MakeVisible( pCursor );
1593 if( bDeselAll )
1594 pView->SelectAll( FALSE );
1595 ShowCursor( FALSE );
1596 MakeVisible( pNewCursor );
1597 SetCursor( pNewCursor );
1598 if( !bInAddMode )
1599 pView->Select( pCursor, TRUE );
1602 break;
1604 case KEY_LEFT:
1605 if( pCursor )
1607 MakeVisible( pCursor );
1608 pNewCursor = pImpCursor->GoLeftRight(pCursor,FALSE );
1609 if( pNewCursor )
1611 if( bDeselAll )
1612 pView->SelectAll( FALSE );
1613 ShowCursor( FALSE );
1614 MakeVisible( pNewCursor );
1615 SetCursor( pNewCursor );
1616 if( !bInAddMode )
1617 pView->Select( pCursor, TRUE );
1619 else
1621 Rectangle aRect( GetBoundingRect(pCursor));
1622 if( aRect.Left() )
1624 aRect.Right() -= aRect.Left();
1625 aRect.Left() = 0;
1626 MakeVisible( aRect );
1630 break;
1632 case KEY_ESCAPE:
1633 if( nFlags & F_RUBBERING )
1635 HideSelectionRect();
1636 pView->SelectAll( FALSE );
1637 nFlags &= ~F_RUBBERING;
1639 break;
1641 case KEY_F8:
1642 if( rKEvt.GetKeyCode().IsShift() )
1644 if( nFlags & F_ADD_MODE )
1645 nFlags &= (~F_ADD_MODE);
1646 else
1647 nFlags |= F_ADD_MODE;
1649 break;
1651 #ifdef OS2
1652 case KEY_F9:
1653 if( rKEvt.GetKeyCode().IsShift() )
1655 if( pCursor && pView->IsInplaceEditingEnabled() )
1656 pView->EditEntry( pCursor );
1658 break;
1659 #endif
1661 case KEY_SPACE:
1662 if( pCursor )
1664 ToggleSelection( pCursor );
1666 break;
1669 case KEY_PAGEDOWN:
1670 break;
1671 case KEY_PAGEUP:
1672 break;
1674 case KEY_ADD:
1675 case KEY_DIVIDE :
1676 if( bMod1 )
1677 pView->SelectAll( TRUE );
1678 break;
1680 case KEY_SUBTRACT:
1681 case KEY_COMMA :
1682 if( bMod1 )
1683 pView->SelectAll( FALSE );
1684 break;
1686 case KEY_RETURN:
1687 if( bMod1 )
1689 if( pCursor && pView->IsInplaceEditingEnabled() )
1690 pView->EditEntry( pCursor );
1692 break;
1694 default:
1695 bKeyUsed = FALSE;
1698 return bKeyUsed;
1702 void SvImpIconView::PositionScrollBars( long nRealWidth, long nRealHeight )
1704 // hor scrollbar
1705 Point aPos( 0, nRealHeight );
1706 aPos.Y() -= nHorSBarHeight;
1708 #ifdef WIN
1709 // vom linken und unteren Rand ein Pixel abschneiden
1710 aPos.Y()++;
1711 aPos.X()--;
1712 #endif
1713 #ifdef OS2
1714 aPos.Y()++;
1715 #endif
1716 if( aHorSBar.GetPosPixel() != aPos )
1717 aHorSBar.SetPosPixel( aPos );
1719 // ver scrollbar
1720 aPos.X() = nRealWidth; aPos.Y() = 0;
1721 aPos.X() -= nVerSBarWidth;
1723 #if defined(WIN) || defined(WNT)
1724 aPos.X()++;
1725 aPos.Y()--;
1726 #endif
1728 #ifdef OS2
1729 aPos.Y()--;
1730 aPos.X()++;
1731 #endif
1733 if( aVerSBar.GetPosPixel() != aPos )
1734 aVerSBar.SetPosPixel( aPos );
1739 void SvImpIconView::AdjustScrollBars()
1741 long nVirtHeight = aVirtOutputSize.Height();
1742 long nVirtWidth = aVirtOutputSize.Width();
1744 Size aOSize( pView->Control::GetOutputSizePixel() );
1745 long nRealHeight = aOSize.Height();
1746 long nRealWidth = aOSize.Width();
1748 PositionScrollBars( nRealWidth, nRealHeight );
1750 const MapMode& rMapMode = pView->GetMapMode();
1751 Point aOrigin( rMapMode.GetOrigin() );
1753 long nVisibleWidth;
1754 if( nRealWidth > nVirtWidth )
1755 nVisibleWidth = nVirtWidth + aOrigin.X();
1756 else
1757 nVisibleWidth = nRealWidth;
1759 long nVisibleHeight;
1760 if( nRealHeight > nVirtHeight )
1761 nVisibleHeight = nVirtHeight + aOrigin.Y();
1762 else
1763 nVisibleHeight = nRealHeight;
1765 bool bVerSBar = (pView->nWindowStyle & WB_VSCROLL) ? true : false;
1766 bool bHorSBar = (pView->nWindowStyle & WB_HSCROLL) ? true : false;
1768 USHORT nResult = 0;
1769 if( nVirtHeight )
1771 // activate ver scrollbar ?
1772 if( bVerSBar || ( nVirtHeight > nVisibleHeight) )
1774 nResult = 0x0001;
1775 nRealWidth -= nVerSBarWidth;
1777 if( nRealWidth > nVirtWidth )
1778 nVisibleWidth = nVirtWidth + aOrigin.X();
1779 else
1780 nVisibleWidth = nRealWidth;
1782 nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1784 // activate hor scrollbar ?
1785 if( bHorSBar || (nVirtWidth > nVisibleWidth) )
1787 nResult |= 0x0002;
1788 nRealHeight -= nHorSBarHeight;
1790 if( nRealHeight > nVirtHeight )
1791 nVisibleHeight = nVirtHeight + aOrigin.Y();
1792 else
1793 nVisibleHeight = nRealHeight;
1795 // brauchen wir jetzt doch eine senkrechte Scrollbar ?
1796 if( !(nResult & 0x0001) && // nur wenn nicht schon da
1797 ( (nVirtHeight > nVisibleHeight) || bVerSBar) )
1799 nResult = 3; // both are active
1800 nRealWidth -= nVerSBarWidth;
1802 if( nRealWidth > nVirtWidth )
1803 nVisibleWidth = nVirtWidth + aOrigin.X();
1804 else
1805 nVisibleWidth = nRealWidth;
1807 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1812 // size ver scrollbar
1813 long nThumb = aVerSBar.GetThumbPos();
1814 Size aSize( nVerSBarWidth, nRealHeight );
1815 #if defined(WIN) || defined(WNT)
1816 aSize.Height() += 2;
1817 #endif
1818 #ifdef OS2
1819 aSize.Height() += 3;
1820 #endif
1821 if( aSize != aVerSBar.GetSizePixel() )
1822 aVerSBar.SetSizePixel( aSize );
1823 aVerSBar.SetVisibleSize( nVisibleHeight );
1824 aVerSBar.SetPageSize( (nVisibleHeight*75)/100 );
1825 if( nResult & 0x0001 )
1827 aVerSBar.SetThumbPos( nThumb );
1828 aVerSBar.Show();
1830 else
1832 aVerSBar.SetThumbPos( 0 );
1833 aVerSBar.Hide();
1836 // size hor scrollbar
1837 nThumb = aHorSBar.GetThumbPos();
1838 aSize.Width() = nRealWidth;
1839 aSize.Height() = nHorSBarHeight;
1840 #if defined(WIN) || defined(WNT)
1841 aSize.Width()++;
1842 #endif
1843 #ifdef OS2
1844 aSize.Width() += 3;
1845 if( nResult & 0x0001 ) // vertikale Scrollbar ?
1846 aSize.Width()--;
1847 #endif
1848 #if defined(WIN) || defined(WNT)
1849 if( nResult & 0x0001 ) // vertikale Scrollbar ?
1851 aSize.Width()++;
1852 nRealWidth++;
1854 #endif
1855 if( aSize != aHorSBar.GetSizePixel() )
1856 aHorSBar.SetSizePixel( aSize );
1857 aHorSBar.SetVisibleSize( nVisibleWidth ); //nRealWidth );
1858 aHorSBar.SetPageSize( (nVisibleWidth*75)/100 );
1859 if( nResult & 0x0002 )
1861 aHorSBar.SetThumbPos( nThumb );
1862 aHorSBar.Show();
1864 else
1866 aHorSBar.SetThumbPos( 0 );
1867 aHorSBar.Hide();
1870 #ifdef OS2
1871 nRealWidth++;
1872 #endif
1873 aOutputSize.Width() = nRealWidth;
1874 #if defined(WIN) || defined(WNT)
1875 if( nResult & 0x0002 ) // hor scrollbar ?
1876 nRealHeight++; // weil unterer Rand geclippt wird
1877 #endif
1878 #ifdef OS2
1879 if( nResult & 0x0002 ) // hor scrollbar ?
1880 nRealHeight++;
1881 #endif
1882 aOutputSize.Height() = nRealHeight;
1885 void __EXPORT SvImpIconView::Resize()
1887 StopEditTimer();
1888 Rectangle aRect;
1889 if( GetResizeRect(aRect) )
1890 pView->Invalidate( aRect );
1891 aOutputSize = pView->GetOutputSizePixel();
1892 pImpCursor->Clear();
1894 #if 1
1895 const Size& rSize = pView->Control::GetOutputSizePixel();
1896 PositionScrollBars( rSize.Width(), rSize.Height() );
1897 // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete
1898 // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass
1899 // die ScrollBars aufblitzen (SfxExplorerIconView!)
1900 nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpIconView,UserEventHdl),0);
1901 #else
1902 AdjustScrollBars();
1903 if( GetResizeRect(aRect) )
1904 PaintResizeRect( aRect );
1905 #endif
1908 BOOL SvImpIconView::CheckHorScrollBar()
1910 if( !pZOrderList || !aHorSBar.IsVisible() )
1911 return FALSE;
1912 const MapMode& rMapMode = pView->GetMapMode();
1913 Point aOrigin( rMapMode.GetOrigin() );
1914 if(!(pView->nWindowStyle & WB_HSCROLL) && !aOrigin.X() )
1916 long nWidth = aOutputSize.Width();
1917 USHORT nCount = pZOrderList->Count();
1918 long nMostRight = 0;
1919 for( USHORT nCur = 0; nCur < nCount; nCur++ )
1921 SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
1922 long nRight = GetBoundingRect(pEntry).Right();
1923 if( nRight > nWidth )
1924 return FALSE;
1925 if( nRight > nMostRight )
1926 nMostRight = nRight;
1928 aHorSBar.Hide();
1929 aOutputSize.Height() += nHorSBarHeight;
1930 aVirtOutputSize.Width() = nMostRight;
1931 aHorSBar.SetThumbPos( 0 );
1932 Range aRange;
1933 aRange.Max() = nMostRight - 1;
1934 aHorSBar.SetRange( aRange );
1935 if( aVerSBar.IsVisible() )
1937 Size aSize( aVerSBar.GetSizePixel());
1938 aSize.Height() += nHorSBarHeight;
1939 aVerSBar.SetSizePixel( aSize );
1941 return TRUE;
1943 return FALSE;
1946 BOOL SvImpIconView::CheckVerScrollBar()
1948 if( !pZOrderList || !aVerSBar.IsVisible() )
1949 return FALSE;
1950 const MapMode& rMapMode = pView->GetMapMode();
1951 Point aOrigin( rMapMode.GetOrigin() );
1952 if(!(pView->nWindowStyle & WB_VSCROLL) && !aOrigin.Y() )
1954 long nDeepest = 0;
1955 long nHeight = aOutputSize.Height();
1956 USHORT nCount = pZOrderList->Count();
1957 for( USHORT nCur = 0; nCur < nCount; nCur++ )
1959 SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur);
1960 long nBottom = GetBoundingRect(pEntry).Bottom();
1961 if( nBottom > nHeight )
1962 return FALSE;
1963 if( nBottom > nDeepest )
1964 nDeepest = nBottom;
1966 aVerSBar.Hide();
1967 aOutputSize.Width() += nVerSBarWidth;
1968 aVirtOutputSize.Height() = nDeepest;
1969 aVerSBar.SetThumbPos( 0 );
1970 Range aRange;
1971 aRange.Max() = nDeepest - 1;
1972 aVerSBar.SetRange( aRange );
1973 if( aHorSBar.IsVisible() )
1975 Size aSize( aHorSBar.GetSizePixel());
1976 aSize.Width() += nVerSBarWidth;
1977 aHorSBar.SetSizePixel( aSize );
1979 return TRUE;
1981 return FALSE;
1985 // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden
1986 void SvImpIconView::CheckScrollBars()
1988 CheckVerScrollBar();
1989 if( CheckHorScrollBar() )
1990 CheckVerScrollBar();
1994 void __EXPORT SvImpIconView::GetFocus()
1996 if( pCursor )
1998 pView->SetEntryFocus( pCursor, TRUE );
1999 ShowCursor( TRUE );
2003 void __EXPORT SvImpIconView::LoseFocus()
2005 StopEditTimer();
2006 if( pCursor )
2007 pView->SetEntryFocus( pCursor,FALSE );
2008 ShowCursor( FALSE );
2011 void SvImpIconView::UpdateAll()
2013 AdjustScrollBars();
2014 pImpCursor->Clear();
2015 pView->Invalidate();
2018 void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
2020 Point aPos( GetEntryPosition( pEntry ) );
2021 PaintEntry( pEntry, aPos, pViewData );
2024 void SvImpIconView::PaintEmphasis( const Rectangle& rRect, BOOL bSelected,
2025 BOOL bCursored, OutputDevice* pOut )
2027 // HACK fuer D&D
2028 if( nFlags & F_NO_EMPHASIS )
2029 return;
2031 if( !pOut )
2032 pOut = pView;
2034 // Selektion painten
2035 Color aOldFillColor = pOut->GetFillColor();
2036 Color aOldLineColor = pOut->GetLineColor();
2037 Color aNewColor;
2038 const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
2039 if( bSelected )
2041 aNewColor = rStyleSettings.GetHighlightColor();
2043 else
2045 #ifndef OS2
2046 aNewColor =rStyleSettings.GetFieldColor();
2047 #else
2048 aNewColor = pOut->GetBackground().GetColor();
2049 #endif
2052 if( bCursored )
2054 pOut->SetLineColor( Color( COL_BLACK ) );
2056 pOut->SetFillColor( aNewColor );
2057 pOut->DrawRect( rRect );
2058 pOut->SetFillColor( aOldFillColor );
2059 pOut->SetLineColor( aOldLineColor );
2062 void SvImpIconView::PaintItem( const Rectangle& rRect,
2063 SvLBoxItem* pItem, SvLBoxEntry* pEntry, USHORT nPaintFlags,
2064 OutputDevice* pOut )
2066 if( nViewMode == VIEWMODE_ICON && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
2068 const String& rStr = ((SvLBoxString*)pItem)->GetText();
2069 DrawText( pOut, rRect, rStr, DRAWTEXT_FLAGS );
2071 else
2073 Point aPos( rRect.TopLeft() );
2074 const Size& rSize = GetItemSize( pView, pEntry, pItem );
2075 if( nPaintFlags & PAINTFLAG_HOR_CENTERED )
2076 aPos.X() += (rRect.GetWidth() - rSize.Width() ) / 2;
2077 if( nPaintFlags & PAINTFLAG_VER_CENTERED )
2078 aPos.Y() += (rRect.GetHeight() - rSize.Height() ) / 2;
2079 pItem->Paint( aPos, *(SvLBox*)pOut, 0, pEntry );
2083 void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, const Point& rPos,
2084 SvIcnVwDataEntry* pViewData, OutputDevice* pOut )
2086 if( !pView->IsUpdateMode() )
2087 return;
2089 if( !pOut )
2090 pOut = pView;
2092 SvLBoxContextBmp* pBmpItem;
2094 pView->PreparePaint( pEntry );
2096 if( !pViewData )
2097 pViewData = ICNVIEWDATA(pEntry);
2099 SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
2101 BOOL bSelected = pViewData->IsSelected();
2102 BOOL bCursored = pViewData->IsCursored();
2104 Font aTempFont( pOut->GetFont() );
2105 // waehrend D&D nicht die Fontfarbe wechseln, da sonst auch die
2106 // Emphasis gezeichnet werden muss! (weisser Adler auf weissem Grund)
2107 if( bSelected && !(nFlags & F_NO_EMPHASIS) )
2109 const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings();
2110 Font aNewFont( aTempFont );
2111 aNewFont.SetColor( rStyleSettings.GetHighlightTextColor() );
2112 pOut->SetFont( aNewFont );
2114 Rectangle aTextRect( CalcTextRect(pEntry,pStringItem,&rPos,FALSE,pViewData));
2115 Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos, pViewData ) );
2117 switch( nViewMode )
2119 case VIEWMODE_ICON:
2120 pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
2121 PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
2122 PaintItem( aBmpRect, pBmpItem, pEntry,
2123 PAINTFLAG_HOR_CENTERED | PAINTFLAG_VER_CENTERED, pOut );
2124 PaintEmphasis( aTextRect, bSelected, FALSE, pOut );
2125 PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_HOR_CENTERED, pOut );
2126 break;
2128 case VIEWMODE_NAME:
2129 pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
2130 PaintEmphasis( aBmpRect, bSelected, bCursored, pOut );
2131 PaintItem( aBmpRect, pBmpItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
2132 PaintEmphasis( aTextRect, bSelected, FALSE, pOut );
2133 PaintItem( aTextRect, pStringItem, pEntry,PAINTFLAG_VER_CENTERED, pOut );
2134 break;
2136 case VIEWMODE_TEXT:
2137 PaintEmphasis( aTextRect, bSelected, bCursored, pOut );
2138 PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_VER_CENTERED, pOut );
2139 break;
2141 pOut->SetFont( aTempFont );
2144 void SvImpIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos,
2145 BOOL bAdjustAtGrid, BOOL bCheckScrollBars )
2147 if( pModel->GetParent(pEntry) == pCurParent )
2149 ShowCursor( FALSE );
2150 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2151 Rectangle aBoundRect( GetBoundingRect( pEntry, pViewData ));
2152 pView->Invalidate( aBoundRect );
2153 ToTop( pEntry );
2154 if( rPos != aBoundRect.TopLeft() )
2156 Point aGridOffs = pViewData->aGridRect.TopLeft() -
2157 pViewData->aRect.TopLeft();
2158 pImpCursor->Clear();
2159 nFlags &= ~F_GRID_INSERT;
2160 aBoundRect.SetPos( rPos );
2161 pViewData->aRect = aBoundRect;
2162 pViewData->aGridRect.SetPos( rPos + aGridOffs );
2163 AdjustVirtSize( aBoundRect );
2165 //HACK(Billigloesung, die noch verbessert werden muss)
2166 if( bAdjustAtGrid )
2168 AdjustAtGrid( pEntry );
2169 ToTop( pEntry );
2171 if( bCheckScrollBars && pView->IsUpdateMode() )
2172 CheckScrollBars();
2174 PaintEntry( pEntry, pViewData );
2175 ShowCursor( TRUE );
2179 void SvImpIconView::ViewDataInitialized( SvLBoxEntry*)
2183 void SvImpIconView::ModelHasEntryInvalidated( SvListEntry* pEntry )
2185 if( pEntry == pCursor )
2186 ShowCursor( FALSE );
2187 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2188 pView->Invalidate( pViewData->aRect );
2190 if( nFlags & F_GRIDMODE )
2191 Center( (SvLBoxEntry*)pEntry, pViewData );
2192 else
2193 pViewData->aRect.SetSize( CalcBoundingSize(
2194 (SvLBoxEntry*)pEntry, pViewData ) );
2196 ViewDataInitialized( (SvLBoxEntry*)pEntry );
2197 pView->Invalidate( pViewData->aRect );
2198 if( pEntry == pCursor )
2199 ShowCursor( TRUE );
2203 void SvImpIconView::InvalidateEntry( SvLBoxEntry* pEntry )
2205 const Rectangle& rRect = GetBoundingRect( pEntry );
2206 pView->Invalidate( rRect );
2209 void SvImpIconView::SetNoSelection()
2213 void SvImpIconView::SetDragDropMode( DragDropMode )
2217 void SvImpIconView::SetSelectionMode( SelectionMode )
2221 BOOL SvImpIconView::IsEntryInView( SvLBoxEntry* )
2223 return FALSE;
2226 SvLBoxEntry* SvImpIconView::GetDropTarget( const Point& rPos )
2228 Point aDocPos( rPos );
2229 CalcDocPos( aDocPos );
2230 SvLBoxEntry* pTarget = GetEntry( aDocPos );
2231 if( !pTarget || !pTarget->HasChilds() )
2232 pTarget = pCurParent;
2233 return pTarget;
2236 SvLBoxEntry* SvImpIconView::GetEntry( const Point& rDocPos )
2238 CheckBoundingRects();
2239 SvLBoxEntry* pTarget = 0;
2240 // Z-Order-Liste vom Ende her absuchen
2241 USHORT nCount = pZOrderList->Count();
2242 while( nCount )
2244 nCount--;
2245 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCount));
2246 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2247 if( pViewData->aRect.IsInside( rDocPos ) )
2249 pTarget = pEntry;
2250 break;
2253 return pTarget;
2256 SvLBoxEntry* SvImpIconView::GetNextEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
2258 CheckBoundingRects();
2259 SvLBoxEntry* pTarget = 0;
2260 USHORT nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2261 if( nStartPos != USHRT_MAX )
2263 USHORT nCount = pZOrderList->Count();
2264 for( USHORT nCur = nStartPos+1; nCur < nCount; nCur++ )
2266 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCur));
2267 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2268 if( pViewData->aRect.IsInside( rDocPos ) )
2270 pTarget = pEntry;
2271 break;
2275 return pTarget;
2278 SvLBoxEntry* SvImpIconView::GetPrevEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry )
2280 CheckBoundingRects();
2281 SvLBoxEntry* pTarget = 0;
2282 USHORT nStartPos = pZOrderList->GetPos( (void*)pCurEntry );
2283 if( nStartPos != USHRT_MAX && nStartPos != 0 )
2285 nStartPos--;
2288 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nStartPos));
2289 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2290 if( pViewData->aRect.IsInside( rDocPos ) )
2292 pTarget = pEntry;
2293 break;
2295 } while( nStartPos > 0 );
2297 return pTarget;
2301 Point SvImpIconView::GetEntryPosition( SvLBoxEntry* pEntry )
2303 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2304 DBG_ASSERT(pViewData,"Entry not in model");
2305 return pViewData->aRect.TopLeft();
2308 const Rectangle& SvImpIconView::GetBoundingRect( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData )
2310 if( !pViewData )
2311 pViewData = ICNVIEWDATA(pEntry);
2312 DBG_ASSERT(pViewData,"Entry not in model");
2313 if( !IsBoundingRectValid( pViewData->aRect ))
2314 FindBoundingRect( pEntry, pViewData );
2315 return pViewData->aRect;
2318 void SvImpIconView::SetSpaceBetweenEntries( long nHor, long nVer )
2320 nHorDist = nHor;
2321 nVerDist = nVer;
2324 Rectangle SvImpIconView::CalcBmpRect( SvLBoxEntry* pEntry, const Point* pPos,
2325 SvIcnVwDataEntry* pViewData )
2327 if( !pViewData )
2328 pViewData = ICNVIEWDATA(pEntry);
2330 Rectangle aBound = GetBoundingRect( pEntry, pViewData );
2331 if( pPos )
2332 aBound.SetPos( *pPos );
2333 Point aPos( aBound.TopLeft() );
2335 switch( nViewMode )
2337 case VIEWMODE_ICON:
2339 aPos.X() += ( aBound.GetWidth() - nMaxBmpWidth ) / 2;
2340 Size aSize( nMaxBmpWidth, nMaxBmpHeight );
2341 // das Bitmap-Rechteck soll nicht das TextRect beruehren
2342 aSize.Height() -= 3;
2343 return Rectangle( aPos, aSize );
2346 case VIEWMODE_NAME:
2347 return Rectangle( aPos,
2348 Size( nMaxBmpWidth, aBound.GetHeight() ));
2350 case VIEWMODE_TEXT:
2351 return Rectangle( aPos, aBound.GetSize() );
2353 default:
2355 Rectangle aRect;
2356 return aRect;
2361 Rectangle SvImpIconView::CalcTextRect( SvLBoxEntry* pEntry,
2362 SvLBoxString* pItem, const Point* pPos, BOOL bForInplaceEdit,
2363 SvIcnVwDataEntry* pViewData )
2365 long nBmpHeight, nBmpWidth;
2367 if( !pItem )
2368 pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
2370 if( !pViewData )
2371 pViewData = ICNVIEWDATA(pEntry);
2373 Size aTextSize( GetItemSize( pView, pEntry, pItem, pViewData ));
2374 aTextSize.Width() += 2*LROFFS_TEXT;
2376 Size aContextBmpSize(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry));
2377 Rectangle aBound = GetBoundingRect( pEntry, pViewData );
2378 if( pPos )
2379 aBound.SetPos( *pPos );
2380 Point aPos( aBound.TopLeft() );
2382 switch( nViewMode )
2384 case VIEWMODE_ICON:
2385 nBmpHeight = aContextBmpSize.Height();
2386 if( nBmpHeight < nMaxBmpHeight )
2387 nBmpHeight = nMaxBmpHeight;
2388 aPos.Y() += nBmpHeight;
2390 // beim Inplace-Editieren, spendieren wir ein bisschen mehr Platz
2391 if( bForInplaceEdit )
2393 // 20% rauf
2394 long nMinWidth = (( (aContextBmpSize.Width()*10) / 100 ) * 2 ) +
2395 aContextBmpSize.Width();
2396 if( nMinWidth > aBound.GetWidth() )
2397 nMinWidth = aBound.GetWidth();
2399 if( aTextSize.Width() < nMinWidth )
2400 aTextSize.Width() = nMinWidth;
2402 // beim Inplace-Ed. darfs auch untere Eintraege ueberlappen
2403 Rectangle aMaxGridTextRect = CalcMaxTextRect(pEntry, pViewData);
2404 Size aOptSize = aMaxGridTextRect.GetSize();
2405 if( aOptSize.Height() > aTextSize.Height() )
2406 aTextSize.Height() = aOptSize.Height();
2410 aPos.X() += ( aBound.GetWidth() - aTextSize.Width() ) / 2;
2411 break;
2413 case VIEWMODE_NAME:
2414 nBmpWidth = aContextBmpSize.Width();
2415 if( nBmpWidth < nMaxBmpWidth )
2416 nBmpWidth = nMaxBmpWidth;
2417 aPos.X() += nBmpWidth;
2418 // vertikal ausrichten
2419 aPos.Y() += ( nBmpWidth - aTextSize.Height() ) / 2;
2420 break;
2423 Rectangle aRect( aPos, aTextSize );
2424 // KNALLT BEIM D&D, WENN GECLIPPT WIRD (In DrawText von Thomas)
2425 // ClipAtVirtOutRect( aRect );
2426 return aRect;
2430 long SvImpIconView::CalcBoundingWidth( SvLBoxEntry* pEntry,
2431 const SvIcnVwDataEntry* pViewData ) const
2433 DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
2434 DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
2435 long nStringWidth = GetItemSize( pView, pEntry, pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Width();
2436 nStringWidth += 2*LROFFS_TEXT;
2437 long nBmpWidth = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Width();
2438 long nWidth = 0;
2440 switch( nViewMode )
2442 case VIEWMODE_ICON:
2443 nWidth = Max( nStringWidth, nBmpWidth );
2444 nWidth = Max( nWidth, nMaxBmpWidth );
2445 break;
2447 case VIEWMODE_NAME:
2448 nWidth = Max( nBmpWidth, nMaxBmpWidth );
2449 nWidth += NAMEVIEW_OFFS_BMP_STRING; // Abstand Bitmap String
2450 nWidth += nStringWidth;
2451 break;
2453 case VIEWMODE_TEXT:
2454 nWidth = nStringWidth;
2455 break;
2457 return nWidth;
2460 long SvImpIconView::CalcBoundingHeight( SvLBoxEntry* pEntry,
2461 const SvIcnVwDataEntry* pViewData ) const
2463 DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps");
2464 DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text");
2465 long nStringHeight = GetItemSize(pView,pEntry,pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Height();
2466 long nBmpHeight = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Height();
2467 long nHeight = 0;
2469 switch( nViewMode )
2471 case VIEWMODE_ICON:
2472 nHeight = Max( nBmpHeight, nMaxBmpHeight );
2473 nHeight += ICONVIEW_OFFS_BMP_STRING; // Abstand Bitmap String
2474 nHeight += nStringHeight;
2475 break;
2477 case VIEWMODE_NAME:
2478 nHeight = Max( nBmpHeight, nMaxBmpHeight );
2479 nHeight = Max( nHeight, nStringHeight );
2480 break;
2482 case VIEWMODE_TEXT:
2483 nHeight = nStringHeight;
2484 break;
2486 if( nHeight > nMaxBoundHeight )
2488 ((SvImpIconView*)this)->nMaxBoundHeight = nHeight;
2489 ((SvImpIconView*)this)->aHorSBar.SetLineSize( nHeight / 2 );
2490 ((SvImpIconView*)this)->aVerSBar.SetLineSize( nHeight / 2 );
2492 return nHeight;
2495 Size SvImpIconView::CalcBoundingSize( SvLBoxEntry* pEntry,
2496 SvIcnVwDataEntry* pViewData ) const
2498 if( !pViewData )
2499 pViewData = ICNVIEWDATA(pEntry);
2500 return Size( CalcBoundingWidth(pEntry,pViewData),
2501 CalcBoundingHeight(pEntry,pViewData) );
2504 void SvImpIconView::RecalcAllBoundingRects()
2506 nMaxBoundHeight = 0;
2507 pZOrderList->Remove(0, pZOrderList->Count() );
2508 SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2509 while( pEntry )
2511 FindBoundingRect( pEntry );
2512 pZOrderList->Insert( pEntry, pZOrderList->Count() );
2513 pEntry = pModel->NextSibling( pEntry );
2515 bMustRecalcBoundingRects = FALSE;
2516 AdjustScrollBars();
2519 void SvImpIconView::RecalcAllBoundingRectsSmart()
2521 nMaxBoundHeight = 0;
2522 pZOrderList->Remove(0, pZOrderList->Count() );
2523 SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2524 while( pEntry )
2526 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2527 if( IsBoundingRectValid( pViewData->aRect ))
2529 Size aBoundSize( pViewData->aRect.GetSize() );
2530 if( aBoundSize.Height() > nMaxBoundHeight )
2531 nMaxBoundHeight = aBoundSize.Height();
2532 pZOrderList->Insert( pEntry, pZOrderList->Count() );
2534 else
2536 FindBoundingRect( pEntry, pViewData );
2538 pZOrderList->Insert( pEntry, pZOrderList->Count() );
2539 pEntry = pModel->NextSibling( pEntry );
2541 AdjustScrollBars();
2544 void SvImpIconView::UpdateBoundingRects()
2546 SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
2547 while( pEntry )
2549 GetBoundingRect( pEntry );
2550 pEntry = pModel->NextSibling( pEntry );
2554 void SvImpIconView::FindBoundingRect( SvLBoxEntry* pEntry,
2555 SvIcnVwDataEntry* pViewData )
2557 if( !pViewData )
2558 pViewData = ICNVIEWDATA(pEntry);
2560 Size aSize( CalcBoundingSize( pEntry, pViewData ) );
2561 Point aPos;
2563 DBG_ASSERT(!pViewData->IsEntryPosLocked(),"Locked entry pos in FindBoundingRect");
2564 // damits in der IconView nicht drunter & drueber geht
2565 if( pViewData->IsEntryPosLocked() && IsBoundingRectValid(pViewData->aRect) )
2567 AdjustVirtSize( pViewData->aRect );
2568 return;
2571 aPos = FindNextEntryPos( aSize );
2573 if( nFlags & F_GRIDMODE )
2575 Rectangle aGridRect( aPos, Size(nGridDX, nGridDY) );
2576 pViewData->aGridRect = aGridRect;
2577 Center( pEntry, pViewData );
2578 AdjustVirtSize( pViewData->aRect );
2579 pImpCursor->SetGridUsed( pViewData->aRect );
2581 else
2583 pViewData->aRect = Rectangle( aPos, aSize );
2584 AdjustVirtSize( pViewData->aRect );
2589 void SvImpIconView::SetCursor( SvLBoxEntry* pEntry )
2591 if( pEntry == pCursor )
2592 return;
2594 ShowCursor( FALSE );
2595 if( pCursor )
2597 pView->SetEntryFocus( pCursor, FALSE );
2598 if( pView->GetSelectionMode() == SINGLE_SELECTION )
2599 pView->Select( pCursor, FALSE );
2601 pCursor = pEntry;
2602 ToTop( pCursor );
2603 if( pCursor )
2605 pView->SetEntryFocus(pCursor, TRUE );
2606 if( pView->GetSelectionMode() == SINGLE_SELECTION )
2607 pView->Select( pCursor, TRUE );
2608 ShowCursor( TRUE );
2613 void SvImpIconView::ShowCursor( BOOL bShow )
2615 if( !pCursor || !bShow || !pView->HasFocus() )
2617 pView->HideFocus();
2618 return;
2620 Rectangle aRect ( CalcFocusRect( pCursor ) );
2621 pView->ShowFocus( aRect );
2625 void SvImpIconView::HideDDIcon()
2627 pView->Update();
2628 ImpHideDDIcon();
2629 pDDBufDev = pDDDev;
2630 pDDDev = 0;
2633 void SvImpIconView::ImpHideDDIcon()
2635 if( pDDDev )
2637 Size aSize( pDDDev->GetOutputSizePixel() );
2638 // pView restaurieren
2639 pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev );
2644 void SvImpIconView::ShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
2646 pView->Update();
2647 if( pRefEntry != pDDRefEntry )
2649 DELETEZ(pDDDev);
2650 DELETEZ(pDDBufDev);
2652 BOOL bSelected = pView->SvListView::Select( pRefEntry, FALSE );
2653 if( !pDDDev )
2655 if( pDDBufDev )
2657 // nicht bei jedem Move ein Device anlegen, da dies besonders
2658 // auf Remote-Clients zu langsam ist
2659 pDDDev = pDDBufDev;
2660 pDDBufDev = 0;
2662 else
2664 pDDDev = new VirtualDevice( *pView );
2665 pDDDev->SetFont( pView->GetFont() );
2668 else
2670 ImpHideDDIcon();
2672 const Rectangle& rRect = GetBoundingRect( pRefEntry );
2673 pDDDev->SetOutputSizePixel( rRect.GetSize() );
2675 Point aPos( rPosPix );
2676 CalcDocPos( aPos );
2678 Size aSize( pDDDev->GetOutputSizePixel() );
2679 pDDRefEntry = pRefEntry;
2680 aDDLastEntryPos = aPos;
2681 aDDLastRectPos = aPos;
2683 // Hintergrund sichern
2684 pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView );
2685 // Icon in pView malen
2686 nFlags |= F_NO_EMPHASIS;
2687 PaintEntry( pRefEntry, aPos );
2688 nFlags &= ~F_NO_EMPHASIS;
2689 if( bSelected )
2690 pView->SvListView::Select( pRefEntry, TRUE );
2693 void SvImpIconView::HideShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix )
2695 /* In Notfaellen folgenden flackernden Code aktivieren:
2697 HideDDIcon();
2698 ShowDDIcon( pRefEntry, rPosPix );
2699 return;
2701 if( !pDDDev )
2703 ShowDDIcon( pRefEntry, rPosPix );
2704 return;
2707 if( pRefEntry != pDDRefEntry )
2709 HideDDIcon();
2710 ShowDDIcon( pRefEntry, rPosPix );
2711 return;
2714 Point aEmptyPoint;
2716 Point aCurEntryPos( rPosPix );
2717 CalcDocPos( aCurEntryPos );
2719 const Rectangle& rRect = GetBoundingRect( pRefEntry );
2720 Size aEntrySize( rRect.GetSize() );
2721 Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize );
2722 Rectangle aCurEntryRect( aCurEntryPos, aEntrySize );
2724 if( !aPrevEntryRect.IsOver( aCurEntryRect ) )
2726 HideDDIcon();
2727 ShowDDIcon( pRefEntry, rPosPix );
2728 return;
2731 // Ueberlappung des neuen und alten D&D-Pointers!
2733 Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) );
2734 if( !pDDTempDev )
2736 pDDTempDev = new VirtualDevice( *pView );
2737 pDDTempDev->SetFont( pView->GetFont() );
2740 Size aFullSize( aFullRect.GetSize() );
2741 Point aFullPos( aFullRect.TopLeft() );
2743 pDDTempDev->SetOutputSizePixel( aFullSize );
2745 // Hintergrund (mit dem alten D&D-Pointer!) sichern
2746 pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView );
2747 // den alten Buffer in den neuen Buffer pasten
2748 aDDLastRectPos = aDDLastRectPos - aFullPos;
2750 pDDTempDev->DrawOutDev(
2751 aDDLastRectPos,
2752 pDDDev->GetOutputSizePixel(),
2753 aEmptyPoint,
2754 pDDDev->GetOutputSizePixel(),
2755 *pDDDev );
2757 // Swap
2758 VirtualDevice* pTemp = pDDDev;
2759 pDDDev = pDDTempDev;
2760 pDDTempDev = pTemp;
2762 // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen
2763 pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() );
2764 pDDTempDev->DrawOutDev(
2765 aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev );
2766 Point aRelPos = aCurEntryPos - aFullPos;
2767 nFlags |= F_NO_EMPHASIS;
2768 PaintEntry( pRefEntry, aRelPos, 0, pDDTempDev );
2769 nFlags &= ~F_NO_EMPHASIS;
2771 aDDLastRectPos = aFullPos;
2772 aDDLastEntryPos = aCurEntryPos;
2774 pView->DrawOutDev(
2775 aDDLastRectPos,
2776 pDDDev->GetOutputSizePixel(),
2777 aEmptyPoint,
2778 pDDDev->GetOutputSizePixel(),
2779 *pDDTempDev );
2781 BOOL bSelected = pView->SvListView::Select( pRefEntry, FALSE );
2782 if( bSelected )
2783 pView->SvListView::Select( pRefEntry, TRUE );
2786 void SvImpIconView::ShowTargetEmphasis( SvLBoxEntry* pEntry, BOOL )
2788 CheckBoundingRects();
2789 Rectangle aRect;
2790 if( pEntry != pCurParent &&
2791 (pEntry->HasChilds() || pEntry->HasChildsOnDemand()) )
2792 aRect = CalcBmpRect( pEntry );
2793 else
2795 aRect.SetSize( aOutputSize );
2796 const MapMode& rMapMode = pView->GetMapMode();
2797 Point aOrigin( rMapMode.GetOrigin());
2798 aOrigin *= -1; // in Doc-Koord wandeln
2799 aRect.SetPos( aOrigin );
2800 aRect.Left()++; aRect.Top()++;
2801 aRect.Right()--; aRect.Bottom()--;
2803 ImpDrawXORRect( aRect );
2806 BOOL SvImpIconView::NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
2807 SvLBoxEntry*& rpNewPar, ULONG& rNewChildPos )
2809 if( pTarget == pCurParent && pModel->GetParent(pEntry) == pCurParent )
2811 // D&D innerhalb einer Childlist
2812 StopEditTimer();
2813 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2814 Size aSize( pViewData->aRect.GetSize() );
2815 Point aNewPos = FindNextEntryPos( aSize );
2816 AdjustVirtSize( Rectangle( aNewPos, aSize ) );
2817 SetEntryPosition( pEntry, aNewPos, FALSE, TRUE );
2818 return FALSE;
2820 return pView->SvLBox::NotifyMoving(pTarget,pEntry,rpNewPar,rNewChildPos);
2823 BOOL SvImpIconView::NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry,
2824 SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos )
2826 return pView->SvLBox::NotifyCopying(pTarget,pEntry,rpNewParent,rNewChildPos);
2829 void SvImpIconView::WriteDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo)
2831 SvLBoxEntry* pCurEntry = GetCurEntry();
2832 Point aEntryPos;
2833 if( pCurEntry )
2835 aEntryPos = rPos;
2836 aEntryPos -= GetEntryPosition( pCurEntry );
2838 pInfo->nMouseRelX = aEntryPos.X();
2839 pInfo->nMouseRelY = aEntryPos.Y();
2842 void SvImpIconView::ReadDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo )
2844 Point aDropPos( rPos );
2845 aDropPos.X() -= pInfo->nMouseRelX;
2846 aDropPos.Y() -= pInfo->nMouseRelY;
2847 SetNextEntryPos( aDropPos );
2850 void SvImpIconView::InvalidateBoundingRect( SvLBoxEntry* pEntry )
2852 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
2853 InvalidateBoundingRect( pViewData->aRect );
2856 void SvImpIconView::PrepareCommandEvent( const Point& rPt )
2858 aMouseMoveTimer.Stop();
2859 StopEditTimer();
2860 nFlags |= F_CMD_ARRIVED;
2861 SvLBoxEntry* pEntry = pView->GetEntry( rPt, TRUE );
2862 if( (nFlags & F_DOWN_CTRL) && pEntry && !pView->IsSelected(pEntry) )
2863 pView->Select( pEntry, TRUE );
2864 nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT);
2867 void SvImpIconView::SttDrag( const Point& rPos )
2869 PrepareCommandEvent( rPos );
2871 nFlags |= F_DRAG_SOURCE;
2872 ShowCursor( FALSE );
2875 void SvImpIconView::EndDrag()
2877 ShowCursor( TRUE );
2878 nFlags &= (~F_DRAG_SOURCE);
2881 void SvImpIconView::ToTop( SvLBoxEntry* pEntry )
2883 DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"ToTop:ZOrder?");
2884 if( pZOrderList->GetObject( pZOrderList->Count() -1 ) != pEntry )
2886 USHORT nPos = pZOrderList->GetPos( (void*)pEntry );
2887 pZOrderList->Remove( nPos, 1 );
2888 pZOrderList->Insert( pEntry, pZOrderList->Count() );
2892 void SvImpIconView::SetCurParent( SvLBoxEntry* pNewParent )
2894 Clear();
2895 pCurParent = pNewParent;
2896 ImpArrange();
2899 void SvImpIconView::ClipAtVirtOutRect( Rectangle& rRect ) const
2901 if( rRect.Bottom() >= aVirtOutputSize.Height() )
2902 rRect.Bottom() = aVirtOutputSize.Height() - 1;
2903 if( rRect.Right() >= aVirtOutputSize.Width() )
2904 rRect.Right() = aVirtOutputSize.Width() - 1;
2905 if( rRect.Top() < 0 )
2906 rRect.Top() = 0;
2907 if( rRect.Left() < 0 )
2908 rRect.Left() = 0;
2911 // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der
2912 // sichtbar gemacht werden soll.
2913 // bScrBar == TRUE: Das Rect wurde aufgrund eines ScrollBar-Events berechnet
2915 void SvImpIconView::MakeVisible( const Rectangle& rRect, BOOL bScrBar )
2917 Rectangle aRect( rRect );
2918 ClipAtVirtOutRect( aRect );
2919 MapMode aMapMode( pView->GetMapMode() );
2920 Point aOrigin( aMapMode.GetOrigin() );
2921 // in Dokumentkoordinate umwandeln
2922 aOrigin *= -1;
2924 Rectangle aOutputArea( aOrigin, aOutputSize );
2925 if( aOutputArea.IsInside( aRect ) )
2926 return; // ist schon sichtbar
2928 long nDy;
2929 if( aRect.Top() < aOutputArea.Top() )
2931 // nach oben scrollen (nDy < 0)
2932 nDy = aRect.Top() - aOutputArea.Top();
2934 else if( aRect.Bottom() > aOutputArea.Bottom() )
2936 // nach unten scrollen (nDy > 0)
2937 nDy = aRect.Bottom() - aOutputArea.Bottom();
2939 else
2940 nDy = 0;
2942 long nDx;
2943 if( aRect.Left() < aOutputArea.Left() )
2945 // nach links scrollen (nDx < 0)
2946 nDx = aRect.Left() - aOutputArea.Left();
2948 else if( aRect.Right() > aOutputArea.Right() )
2950 // nach rechts scrollen (nDx > 0)
2951 nDx = aRect.Right() - aOutputArea.Right();
2953 else
2954 nDx = 0;
2956 aOrigin.X() += nDx;
2957 aOrigin.Y() += nDy;
2958 aOutputArea.SetPos( aOrigin );
2960 pView->Update();
2962 // Origin fuer SV invertieren (damit wir in
2963 // Dokumentkoordinaten scrollen/painten koennen)
2964 aOrigin *= -1;
2965 aMapMode.SetOrigin( aOrigin );
2966 pView->SetMapMode( aMapMode );
2968 // in umgekehrte Richtung scrollen!
2969 pView->Control::Scroll( -nDx, -nDy, aOutputArea, TRUE );
2970 if( aHorSBar.IsVisible() || aVerSBar.IsVisible() )
2972 if( !bScrBar )
2974 aOrigin *= -1;
2975 // Thumbs korrigieren
2976 if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X())
2977 aHorSBar.SetThumbPos( aOrigin.X() );
2978 if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y())
2979 aVerSBar.SetThumbPos( aOrigin.Y() );
2982 // pruefen, ob ScrollBars noch benoetigt werden
2983 CheckScrollBars();
2984 pView->Update();
2988 SvLBoxEntry* SvImpIconView::GetNewCursor()
2990 SvLBoxEntry* pNewCursor;
2991 if( pCursor )
2993 pNewCursor = pImpCursor->GoLeftRight( pCursor, FALSE );
2994 if( !pNewCursor )
2996 pNewCursor = pImpCursor->GoLeftRight( pCursor, TRUE );
2997 if( !pNewCursor )
2999 pNewCursor = pImpCursor->GoUpDown( pCursor, FALSE );
3000 if( !pNewCursor )
3001 pNewCursor = pImpCursor->GoUpDown( pCursor, TRUE );
3005 else
3006 pNewCursor = pModel->FirstChild( pCurParent );
3007 DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"GetNewCursor failed");
3008 return pNewCursor;
3012 USHORT SvImpIconView:: GetSelectionCount() const
3014 USHORT nSelected = 0;
3015 SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent);
3016 while( pEntry )
3018 if( pView->IsSelected( pEntry ) )
3019 nSelected++;
3020 pEntry = pModel->NextSibling( pEntry );
3022 return nSelected;
3026 void SvImpIconView::ToggleSelection( SvLBoxEntry* pEntry )
3028 BOOL bSel;
3029 if( pView->IsSelected( pEntry ) )
3030 bSel = FALSE;
3031 else
3032 bSel = TRUE;
3033 pView->Select( pEntry, bSel );
3036 void SvImpIconView::DeselectAllBut( SvLBoxEntry* pThisEntryNot )
3038 ClearSelectedRectList();
3039 SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent );
3040 while( pEntry )
3042 if( pEntry != pThisEntryNot && pView->IsSelected( pEntry ))
3043 pView->Select( pEntry, FALSE );
3044 pEntry = pModel->NextSibling( pEntry );
3048 #define ICN_ROWS 50
3049 #define ICN_COLS 30
3051 ImpIcnCursor::ImpIcnCursor( SvImpIconView* pOwner )
3053 pView = pOwner;
3054 pColumns = 0;
3055 pRows = 0;
3056 pCurEntry = 0;
3057 nDeltaWidth = 0;
3058 nDeltaHeight= 0;
3059 nCols = 0;
3060 nRows = 0;
3061 nGridCols = 0;
3062 nGridRows = 0;
3063 pGridMap = 0;
3066 ImpIcnCursor::~ImpIcnCursor()
3068 delete[] pColumns;
3069 delete[] pRows;
3070 delete pGridMap;
3073 USHORT ImpIcnCursor::GetSortListPos( SvPtrarr* pList, long nValue,
3074 int bVertical )
3076 USHORT nCount = (USHORT)pList->Count();
3077 if( !nCount )
3078 return 0;
3080 USHORT nCurPos = 0;
3081 long nPrevValue = LONG_MIN;
3082 while( nCount )
3084 const Rectangle& rRect=
3085 pView->GetBoundingRect((SvLBoxEntry*)(pList->GetObject(nCurPos)));
3086 long nCurValue;
3087 if( bVertical )
3088 nCurValue = rRect.Top();
3089 else
3090 nCurValue = rRect.Left();
3091 if( nValue >= nPrevValue && nValue <= nCurValue )
3092 return (USHORT)nCurPos;
3093 nPrevValue = nCurValue;
3094 nCount--;
3095 nCurPos++;
3097 return pList->Count();
3100 void ImpIcnCursor::ImplCreate()
3102 pView->CheckBoundingRects();
3103 DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared");
3105 SetDeltas();
3107 pColumns = new SvPtrarr[ nCols ];
3108 pRows = new SvPtrarr[ nRows ];
3110 DELETEZ(pGridMap);
3112 SvLBoxTreeList* pModel = pView->pModel;
3113 SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
3114 while( pEntry )
3116 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3117 // const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3118 Rectangle rRect( pView->CalcBmpRect( pEntry,0,pViewData ) );
3119 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight );
3120 short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth );
3122 // Rundungsfehler abfangen
3123 if( nY >= nRows )
3124 nY = sal::static_int_cast< short >(nRows - 1);
3125 if( nX >= nCols )
3126 nX = sal::static_int_cast< short >(nCols - 1);
3128 USHORT nIns = GetSortListPos( &pColumns[nX], rRect.Top(), TRUE );
3129 pColumns[ nX ].Insert( pEntry, nIns );
3131 nIns = GetSortListPos( &pRows[nY], rRect.Left(), FALSE );
3132 pRows[ nY ].Insert( pEntry, nIns );
3134 pViewData->nX = nX;
3135 pViewData->nY = nY;
3137 pEntry = pModel->NextSibling( pEntry );
3141 void ImpIcnCursor::CreateGridMap()
3143 if( pGridMap )
3144 return;
3146 const Size& rSize = pView->aVirtOutputSize;
3147 long nWidth = rSize.Width();
3148 if( nWidth < pView->nMaxVirtWidth )
3149 nWidth = pView->nMaxVirtWidth;
3150 nWidth -= 2*LROFFS_WINBORDER;
3151 if( nWidth <= 0 )
3152 nWidth = 1;
3154 nGridDX = pView->nGridDX;
3155 nGridDY = pView->nGridDY;
3157 // Hinweis: Wegen der Abrundung bei Berechnung von nGridCols
3158 // ist es moeglich, dass Eintrage nicht im Grid liegen. Diese
3159 // wurden typischerweise manuell verschoben und gelockt
3160 nGridCols = nWidth / nGridDX;
3161 if( !nGridCols ) nGridCols = 1;
3163 nGridRows = rSize.Height() / nGridDY;
3164 // nRows nicht abrunden, da zur Vermeidung von Ueberlappungen
3165 // das gesamte BoundingRect des Eintrags zur Markierung im Grid
3166 // herangezogen wird.
3167 if( (nGridRows * nGridDY) < rSize.Height() )
3168 nGridRows++;
3169 else if( !nGridRows )
3170 nGridRows = 1;
3172 //XXX
3173 //nGridRows += 50; // in fuenfziger-Schritten
3175 pGridMap = new BOOL[ nGridRows*nGridCols];
3176 memset( (void*)pGridMap, 0, nGridRows*nGridCols );
3178 SvLBoxTreeList* pModel = pView->pModel;
3179 SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent );
3180 while( pEntry )
3182 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3183 const Rectangle& rRect = pViewData->aRect;
3184 // nur, wenn der Entry schon plaziert ist
3185 if( pView->IsBoundingRectValid( rRect ))
3187 // Alle vom Eintrag beruehrten Grids kennzeichnen
3188 SetGridUsed( pView->GetBoundingRect( pEntry, pViewData ) );
3190 pEntry = pModel->NextSibling( pEntry );
3194 BOOL ImpIcnCursor::GetGrid( const Point& rDocPos, USHORT& rGridX, USHORT& rGridY ) const
3196 Point aPos( rDocPos );
3197 aPos.X() -= LROFFS_WINBORDER;
3198 aPos.Y() -= TBOFFS_WINBORDER;
3199 rGridX = (USHORT)(aPos.X() / nGridDX);
3200 rGridY = (USHORT)(aPos.Y() / nGridDY);
3201 BOOL bInGrid = TRUE;
3202 if( rGridX >= nGridCols )
3204 rGridX = sal::static_int_cast< USHORT >(nGridCols - 1);
3205 bInGrid = FALSE;
3207 if( rGridY >= nGridRows )
3209 rGridY = sal::static_int_cast< USHORT >(nGridRows - 1);
3210 if( !bInGrid )
3211 return FALSE; // beide Koordinaten nicht im Grid
3213 return TRUE;
3216 void ImpIcnCursor::SetGridUsed( const Rectangle& rRect, BOOL bUsed )
3218 CreateGridMap();
3219 USHORT nTLX, nTLY, nBRX, nBRY;
3221 BOOL bTLInGrid = GetGrid( rRect.TopLeft(), nTLX, nTLY );
3222 BOOL bBRInGrid = GetGrid( rRect.BottomRight(), nBRX, nBRY );
3224 if( !bTLInGrid && !bBRInGrid )
3225 return;
3227 for( USHORT nCurY = nTLY; nCurY <= nBRY; nCurY++ )
3229 for( USHORT nCurX = nTLX; nCurX <= nBRX; nCurX++ )
3231 SetGridUsed( nCurX, nCurY, bUsed );
3236 void ImpIcnCursor::Clear( BOOL bGridToo )
3238 if( pColumns )
3240 delete[] pColumns;
3241 delete[] pRows;
3242 pColumns = 0;
3243 pRows = 0;
3244 pCurEntry = 0;
3245 nDeltaWidth = 0;
3246 nDeltaHeight = 0;
3248 if( bGridToo && pGridMap )
3250 DELETEZ(pGridMap);
3251 nGridRows = 0;
3252 nGridCols = 0;
3256 SvLBoxEntry* ImpIcnCursor::SearchCol(USHORT nCol,USHORT nTop,USHORT nBottom,
3257 USHORT, BOOL bDown, BOOL bSimple )
3259 DBG_ASSERT(pCurEntry,"SearchCol: No reference entry");
3260 SvPtrarr* pList = &(pColumns[ nCol ]);
3261 USHORT nCount = pList->Count();
3262 if( !nCount )
3263 return 0;
3265 const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
3267 if( bSimple )
3269 USHORT nListPos = pList->GetPos( pCurEntry );
3270 DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List");
3271 if( bDown )
3273 while( nListPos < nCount-1 )
3275 nListPos++;
3276 SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3277 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3278 if( rRect.Top() > rRefRect.Top() )
3279 return pEntry;
3281 return 0;
3283 else
3285 while( nListPos )
3287 nListPos--;
3288 if( nListPos < nCount )
3290 SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3291 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3292 if( rRect.Top() < rRefRect.Top() )
3293 return pEntry;
3296 return 0;
3300 if( nTop > nBottom )
3302 USHORT nTemp = nTop;
3303 nTop = nBottom;
3304 nBottom = nTemp;
3306 long nMinDistance = LONG_MAX;
3307 SvLBoxEntry* pResult = 0;
3308 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3310 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
3311 if( pEntry != pCurEntry )
3313 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3314 USHORT nY = pViewData->nY;
3315 if( nY >= nTop && nY <= nBottom )
3317 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3318 long nDistance = rRect.Top() - rRefRect.Top();
3319 if( nDistance < 0 )
3320 nDistance *= -1;
3321 if( nDistance && nDistance < nMinDistance )
3323 nMinDistance = nDistance;
3324 pResult = pEntry;
3329 return pResult;
3332 SvLBoxEntry* ImpIcnCursor::SearchRow(USHORT nRow,USHORT nLeft,USHORT nRight,
3333 USHORT, BOOL bRight, BOOL bSimple )
3335 DBG_ASSERT(pCurEntry,"SearchRow: No reference entry");
3336 SvPtrarr* pList = &(pRows[ nRow ]);
3337 USHORT nCount = pList->Count();
3338 if( !nCount )
3339 return 0;
3341 const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry);
3343 if( bSimple )
3345 USHORT nListPos = pList->GetPos( pCurEntry );
3346 DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List");
3347 if( bRight )
3349 while( nListPos < nCount-1 )
3351 nListPos++;
3352 SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3353 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3354 if( rRect.Left() > rRefRect.Left() )
3355 return pEntry;
3357 return 0;
3359 else
3361 while( nListPos )
3363 nListPos--;
3364 if( nListPos < nCount )
3366 SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos );
3367 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3368 if( rRect.Left() < rRefRect.Left() )
3369 return pEntry;
3372 return 0;
3376 if( nRight < nLeft )
3378 USHORT nTemp = nRight;
3379 nRight = nLeft;
3380 nLeft = nTemp;
3382 long nMinDistance = LONG_MAX;
3383 SvLBoxEntry* pResult = 0;
3384 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3386 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur ));
3387 if( pEntry != pCurEntry )
3389 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry);
3390 USHORT nX = pViewData->nX;
3391 if( nX >= nLeft && nX <= nRight )
3393 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3394 long nDistance = rRect.Left() - rRefRect.Left();
3395 if( nDistance < 0 )
3396 nDistance *= -1;
3397 if( nDistance && nDistance < nMinDistance )
3399 nMinDistance = nDistance;
3400 pResult = pEntry;
3405 return pResult;
3411 Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw.
3412 linksstehenden. Suchverfahren am Beispiel bRight = TRUE:
3416 a b c
3417 S 1 1 1 ====> Suchrichtung
3418 a b c
3422 S : Startposition
3423 1 : erstes Suchrechteck
3424 a,b,c : 2., 3., 4. Suchrechteck
3427 SvLBoxEntry* ImpIcnCursor::GoLeftRight( SvLBoxEntry* pIcnEntry, BOOL bRight )
3429 SvLBoxEntry* pResult;
3430 pCurEntry = pIcnEntry;
3431 Create();
3432 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
3433 USHORT nY = pViewData->nY;
3434 USHORT nX = pViewData->nX;
3435 DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column");
3436 DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row");
3437 // Nachbar auf gleicher Zeile ?
3438 if( bRight )
3439 pResult = SearchRow(
3440 nY, nX, sal::static_int_cast< USHORT >(nCols-1), nX, TRUE, TRUE );
3441 else
3442 pResult = SearchRow( nY, nX ,0, nX, FALSE, TRUE );
3443 if( pResult )
3444 return pResult;
3446 long nCurCol = nX;
3448 long nColOffs, nLastCol;
3449 if( bRight )
3451 nColOffs = 1;
3452 nLastCol = nCols;
3454 else
3456 nColOffs = -1;
3457 nLastCol = -1; // 0-1
3460 USHORT nRowMin = nY;
3461 USHORT nRowMax = nY;
3464 SvLBoxEntry* pEntry = SearchCol((USHORT)nCurCol,nRowMin,nRowMax,nY,TRUE, FALSE);
3465 if( pEntry )
3466 return pEntry;
3467 if( nRowMin )
3468 nRowMin--;
3469 if( nRowMax < (nRows-1))
3470 nRowMax++;
3471 nCurCol += nColOffs;
3472 } while( nCurCol != nLastCol );
3473 return 0;
3476 SvLBoxEntry* ImpIcnCursor::GoUpDown( SvLBoxEntry* pIcnEntry, BOOL bDown)
3478 SvLBoxEntry* pResult;
3479 pCurEntry = pIcnEntry;
3480 Create();
3481 SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry);
3482 USHORT nY = pViewData->nY;
3483 USHORT nX = pViewData->nX;
3484 DBG_ASSERT(nY<nRows,"GoUpDown:Bad column");
3485 DBG_ASSERT(nX<nCols,"GoUpDown:Bad row");
3487 // Nachbar in gleicher Spalte ?
3488 if( bDown )
3489 pResult = SearchCol(
3490 nX, nY, sal::static_int_cast< USHORT >(nRows-1), nY, TRUE, TRUE );
3491 else
3492 pResult = SearchCol( nX, nY ,0, nY, FALSE, TRUE );
3493 if( pResult )
3494 return pResult;
3496 long nCurRow = nY;
3498 long nRowOffs, nLastRow;
3499 if( bDown )
3501 nRowOffs = 1;
3502 nLastRow = nRows;
3504 else
3506 nRowOffs = -1;
3507 nLastRow = -1; // 0-1
3510 USHORT nColMin = nX;
3511 USHORT nColMax = nX;
3514 SvLBoxEntry* pEntry = SearchRow((USHORT)nCurRow,nColMin,nColMax,nX,TRUE, FALSE);
3515 if( pEntry )
3516 return pEntry;
3517 if( nColMin )
3518 nColMin--;
3519 if( nColMax < (nCols-1))
3520 nColMax++;
3521 nCurRow += nRowOffs;
3522 } while( nCurRow != nLastRow );
3523 return 0;
3526 void ImpIcnCursor::SetDeltas()
3528 const Size& rSize = pView->aVirtOutputSize;
3529 if( pView->nFlags & F_GRIDMODE )
3531 nGridDX = pView->nGridDX;
3532 nGridDY = pView->nGridDY;
3534 else
3536 nGridDX = 20;
3537 nGridDY = 20;
3539 nCols = rSize.Width() / nGridDX;
3540 if( !nCols )
3541 nCols = 1;
3542 nRows = rSize.Height() / nGridDY;
3543 if( (nRows * nGridDY) < rSize.Height() )
3544 nRows++;
3545 if( !nRows )
3546 nRows = 1;
3548 nDeltaWidth = (short)(rSize.Width() / nCols);
3549 nDeltaHeight = (short)(rSize.Height() / nRows);
3550 if( !nDeltaHeight )
3552 nDeltaHeight = 1;
3553 DBG_WARNING("SetDeltas:Bad height");
3555 if( !nDeltaWidth )
3557 nDeltaWidth = 1;
3558 DBG_WARNING("SetDeltas:Bad width");
3563 void ImpIcnCursor::ExpandGrid()
3565 if( pGridMap )
3567 long nNewGridRows = nGridRows + 20;
3568 unsigned char* pTempMap = new unsigned char[ nNewGridRows * nGridCols ];
3569 memcpy( pTempMap, pGridMap, nGridRows * nGridCols );
3570 delete pGridMap;
3571 pGridMap = pTempMap;
3572 nGridRows = nNewGridRows;
3576 BOOL ImpIcnCursor::FindEmptyGridRect( Rectangle& rRect )
3578 CreateGridMap();
3579 USHORT nCount = (USHORT)(nGridCols * nGridRows);
3580 if( !nCount )
3581 return FALSE;
3582 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3584 if( !pGridMap[ nCur ] )
3586 USHORT nCol = (USHORT)(nCur % nGridCols);
3587 USHORT nRow = (USHORT)(nCur / nGridCols);
3588 rRect.Top() = nRow * nGridDY + TBOFFS_WINBORDER;
3589 rRect.Bottom() = rRect.Top() + nGridDY;
3590 rRect.Left() = nCol * nGridDX+ LROFFS_WINBORDER;
3591 rRect.Right() = rRect.Left() + nGridDX;
3592 SetGridUsed( nCol, nRow, TRUE );
3594 //XXX
3595 //if( nRow + 5 > nGridRows )
3596 // ExpandGrid();
3597 DBG_ASSERT(pGridMap[nCur],"SetGridUsed failed");
3598 return TRUE;
3601 // Gridmap ist voll: Um eine Zeile erweitern
3602 rRect.Top() = nGridRows * nGridDY + TBOFFS_WINBORDER;
3603 rRect.Bottom() = rRect.Top() + nGridDY;
3604 rRect.Left() = LROFFS_WINBORDER;
3605 rRect.Right() = rRect.Left() + nGridDX;
3606 return FALSE;
3607 //XXX
3608 //ExpandGrid();
3609 //return TRUE;
3612 void ImpIcnCursor::CreateGridAjustData( SvPtrarr& rLists, SvLBoxEntry* pRefEntry)
3614 if( !pRefEntry )
3616 USHORT nAdjustRows = (USHORT)(pView->aVirtOutputSize.Height() / pView->nGridDY);
3617 nAdjustRows++; // wg. Abrundung!
3619 if( !nAdjustRows )
3620 return;
3621 for( USHORT nCurList = 0; nCurList < nAdjustRows; nCurList++ )
3623 SvPtrarr* pRow = new SvPtrarr;
3624 rLists.Insert( (void*)pRow, nCurList );
3626 SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
3627 while( pEntry )
3629 const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3630 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
3631 USHORT nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),FALSE);
3632 ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns );
3633 pEntry = pView->pModel->NextSibling( pEntry );
3636 else
3638 // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile
3640 // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen???
3642 Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) );
3643 //const Rectangle& rRefRect = pView->GetBoundingRect( pRefEntry );
3644 short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY );
3645 SvPtrarr* pRow = new SvPtrarr;
3646 rLists.Insert( (void*)pRow, 0 );
3647 SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent );
3648 while( pEntry )
3650 Rectangle rRect( pView->CalcBmpRect(pEntry) );
3651 //const Rectangle& rRect = pView->GetBoundingRect( pEntry );
3652 short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY );
3653 if( nY == nRefRow )
3655 USHORT nIns = GetSortListPos( pRow, rRect.Left(), FALSE );
3656 pRow->Insert( pEntry, nIns );
3658 pEntry = pView->pModel->NextSibling( pEntry );
3663 //static
3664 void ImpIcnCursor::DestroyGridAdjustData( SvPtrarr& rLists )
3666 USHORT nCount = rLists.Count();
3667 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3669 SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ];
3670 delete pArr;
3672 rLists.Remove( 0, rLists.Count() );
3675 void SvImpIconView::SetGrid( long nDX, long nDY )
3677 nGridDX = nDX;
3678 nGridDY = nDY;
3679 nFlags |= F_GRIDMODE;
3682 Rectangle SvImpIconView::CalcMaxTextRect( const SvLBoxEntry* pEntry,
3683 const SvIcnVwDataEntry* pViewData ) const
3685 Rectangle aRect = pViewData->aGridRect;
3686 long nBmpHeight = ((SvLBoxEntry*)pEntry)->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,(SvLBoxEntry*)pEntry).Height();
3687 aRect.Top() += nBmpHeight;
3688 aRect.Top() += ICONVIEW_OFFS_BMP_STRING;
3689 if( aRect.Top() > aRect.Bottom())
3690 aRect.Top() = aRect.Bottom();
3691 aRect.Left() += LROFFS_BOUND;
3692 aRect.Left()++;
3693 aRect.Right() -= LROFFS_BOUND;
3694 aRect.Right()--;
3695 if( aRect.Left() > aRect.Right())
3696 aRect.Left() = aRect.Right();
3697 if( GetTextMode( pEntry, pViewData ) == ShowTextFull )
3698 aRect.Bottom() = LONG_MAX;
3699 return aRect;
3702 void SvImpIconView::Center( SvLBoxEntry* pEntry,
3703 SvIcnVwDataEntry* pViewData ) const
3705 SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3706 const String& rEntryText = pStringItem->GetText();
3708 Rectangle aTextRect = CalcMaxTextRect(pEntry,pViewData);
3709 aTextRect = GetTextRect( pView, aTextRect, rEntryText, DRAWTEXT_FLAGS );
3710 pViewData->aTextSize = aTextRect.GetSize();
3712 pViewData->aRect = pViewData->aGridRect;
3713 Size aSize( CalcBoundingSize( pEntry, pViewData ) );
3714 long nBorder = pViewData->aGridRect.GetWidth() - aSize.Width();
3715 pViewData->aRect.Left() += nBorder / 2;
3716 pViewData->aRect.Right() -= nBorder / 2;
3717 pViewData->aRect.Bottom() = pViewData->aRect.Top() + aSize.Height();
3721 // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird
3722 // links, hoch: Offsets < 0
3723 // rechts, runter: Offsets > 0
3724 void SvImpIconView::Scroll( long nDeltaX, long nDeltaY, BOOL bScrollBar )
3726 const MapMode& rMapMode = pView->GetMapMode();
3727 Point aOrigin( rMapMode.GetOrigin() );
3728 // in Dokumentkoordinate umwandeln
3729 aOrigin *= -1;
3730 aOrigin.Y() += nDeltaY;
3731 aOrigin.X() += nDeltaX;
3732 Rectangle aRect( aOrigin, aOutputSize );
3733 MakeVisible( aRect, bScrollBar );
3737 const Size& SvImpIconView::GetItemSize( SvIconView* pIconView,
3738 SvLBoxEntry* pEntry, SvLBoxItem* pItem, const SvIcnVwDataEntry* pViewData) const
3740 if( (nFlags & F_GRIDMODE) && pItem->IsA() == SV_ITEM_ID_LBOXSTRING )
3742 if( !pViewData )
3743 pViewData = ICNVIEWDATA(pEntry);
3744 return pViewData->aTextSize;
3746 else
3747 return pItem->GetSize( pIconView, pEntry );
3750 Rectangle SvImpIconView::CalcFocusRect( SvLBoxEntry* pEntry )
3752 #if !defined(OS2)
3753 SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3754 DBG_ASSERT(pStringItem,"Text not set");
3755 return CalcTextRect( pEntry, pStringItem );
3756 #else
3757 return CalcBmpRect( pEntry );
3758 #endif
3762 void SvImpIconView::SelectRect( const Rectangle& rRect, BOOL bAdd,
3763 SvPtrarr* pOtherRects, short nBorderOffs )
3765 if( !pZOrderList || !pZOrderList->Count() )
3766 return;
3768 CheckBoundingRects();
3769 pView->Update();
3770 USHORT nCount = pZOrderList->Count();
3772 Rectangle aRect( rRect );
3773 aRect.Justify();
3774 if( nBorderOffs )
3776 aRect.Left() -= nBorderOffs;
3777 aRect.Right() += nBorderOffs;
3778 aRect.Top() -= nBorderOffs;
3779 aRect.Bottom() += nBorderOffs;
3781 BOOL bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? TRUE : FALSE;
3783 for( USHORT nPos = 0; nPos < nCount; nPos++ )
3785 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos ));
3787 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
3788 DBG_ASSERT(pViewData,"Entry not in model");
3789 if( !IsBoundingRectValid( pViewData->aRect ))
3790 FindBoundingRect( pEntry, pViewData );
3791 const Rectangle& rBoundRect = pViewData->aRect;
3792 BOOL bSelected = pViewData->IsSelected();
3794 BOOL bOverlaps;
3795 if( bCalcOverlap )
3796 bOverlaps = IsOver( pOtherRects, rBoundRect );
3797 else
3798 bOverlaps = FALSE;
3799 BOOL bOver = aRect.IsOver( rBoundRect );
3801 if( bOver && !bOverlaps )
3803 // Ist im neuen Selektionsrechteck und in keinem alten
3804 // => selektieren
3805 if( !bSelected )
3806 pView->Select( pEntry, TRUE );
3808 else if( !bAdd )
3810 // ist ausserhalb des Selektionsrechtecks
3811 // => Selektion entfernen
3812 if( bSelected )
3813 pView->Select( pEntry, FALSE );
3815 else if( bAdd && bOverlaps )
3817 // Der Eintrag befindet sich in einem alten (=>Aufspannen
3818 // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck
3820 // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags
3821 // in einem vorherigen Rechteck, muss restauriert werden, wenn
3822 // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber
3823 // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber
3824 // pauschal davon aus, dass die Eintraege in den alten Rechtecken
3825 // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge
3826 // nur zu deselektieren.
3827 // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf-
3828 // spannen des Rechtecks merken
3829 if( rBoundRect.IsOver( rRect))
3831 // Schnittmenge zwischen alten Rects & aktuellem Rect desel.
3832 if( bSelected )
3833 pView->Select( pEntry, FALSE );
3835 else
3837 // Eintrag eines alten Rects selektieren
3838 if( !bSelected )
3839 pView->Select( pEntry, TRUE );
3842 else if( !bOver && bSelected )
3844 // Der Eintrag liegt voellig ausserhalb und wird deshalb desel.
3845 pView->Select( pEntry, FALSE );
3848 pView->Update();
3851 BOOL SvImpIconView::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const
3853 USHORT nCount = pRectList->Count();
3854 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3856 Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur );
3857 if( rBoundRect.IsOver( *pRect ))
3858 return TRUE;
3860 return FALSE;
3863 void SvImpIconView::AddSelectedRect( const Rectangle& rRect, short nBorderOffs )
3865 Rectangle* pRect = new Rectangle( rRect );
3866 pRect->Justify();
3867 if( nBorderOffs )
3869 pRect->Left() -= nBorderOffs;
3870 pRect->Right() += nBorderOffs;
3871 pRect->Top() -= nBorderOffs;
3872 pRect->Bottom() += nBorderOffs;
3874 aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() );
3877 void SvImpIconView::ClearSelectedRectList()
3879 USHORT nCount = aSelectedRectList.Count();
3880 for( USHORT nCur = 0; nCur < nCount; nCur++ )
3882 Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur );
3883 delete pRect;
3885 aSelectedRectList.Remove( 0, aSelectedRectList.Count() );
3889 void SvImpIconView::DrawSelectionRect( const Rectangle& rRect )
3891 pView->HideTracking();
3892 nFlags |= F_SELRECT_VISIBLE;
3893 pView->ShowTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
3894 aCurSelectionRect = rRect;
3897 void SvImpIconView::HideSelectionRect()
3899 if( nFlags & F_SELRECT_VISIBLE )
3901 pView->HideTracking();
3902 nFlags &= ~F_SELRECT_VISIBLE;
3906 void SvImpIconView::ImpDrawXORRect( const Rectangle& rRect )
3908 RasterOp eOldOp = pView->GetRasterOp();
3909 pView->SetRasterOp( ROP_XOR );
3910 Color aOldColor = pView->GetFillColor();
3911 pView->SetFillColor();
3912 pView->DrawRect( rRect );
3913 pView->SetFillColor( aOldColor );
3914 pView->SetRasterOp( eOldOp );
3917 void SvImpIconView::CalcScrollOffsets( const Point& rPosPixel,
3918 long& rX, long& rY, BOOL bInDragDrop, USHORT nBorderWidth)
3920 // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des
3921 // Fensters befindet
3922 long nPixelToScrollX = 0;
3923 long nPixelToScrollY = 0;
3924 Size aWndSize = aOutputSize;
3926 nBorderWidth = (USHORT)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth ));
3927 nBorderWidth = (USHORT)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth ));
3929 if ( rPosPixel.X() < nBorderWidth )
3931 if( bInDragDrop )
3932 nPixelToScrollX = -DD_SCROLL_PIXEL;
3933 else
3934 nPixelToScrollX = rPosPixel.X()- nBorderWidth;
3936 else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth )
3938 if( bInDragDrop )
3939 nPixelToScrollX = DD_SCROLL_PIXEL;
3940 else
3941 nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth);
3943 if ( rPosPixel.Y() < nBorderWidth )
3945 if( bInDragDrop )
3946 nPixelToScrollY = -DD_SCROLL_PIXEL;
3947 else
3948 nPixelToScrollY = rPosPixel.Y() - nBorderWidth;
3950 else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth )
3952 if( bInDragDrop )
3953 nPixelToScrollY = DD_SCROLL_PIXEL;
3954 else
3955 nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth);
3958 rX = nPixelToScrollX;
3959 rY = nPixelToScrollY;
3962 IMPL_LINK(SvImpIconView, MouseMoveTimeoutHdl, Timer*, pTimer )
3964 pTimer->Start();
3965 MouseMove( aMouseMoveEvent );
3966 return 0;
3969 void SvImpIconView::EndTracking()
3971 pView->ReleaseMouse();
3972 if( nFlags & F_RUBBERING )
3974 aMouseMoveTimer.Stop();
3975 nFlags &= ~(F_RUBBERING | F_ADD_MODE);
3979 BOOL SvImpIconView::IsTextHit( SvLBoxEntry* pEntry, const Point& rDocPos )
3981 SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
3982 if( pItem )
3984 Rectangle aRect( CalcTextRect( pEntry, pItem ));
3985 if( aRect.IsInside( rDocPos ) )
3986 return TRUE;
3988 return FALSE;
3991 IMPL_LINK(SvImpIconView, EditTimeoutHdl, Timer*, EMPTYARG )
3993 SvLBoxEntry* pEntry = GetCurEntry();
3994 if( pView->IsInplaceEditingEnabled() && pEntry &&
3995 pView->IsSelected( pEntry ))
3997 pView->EditEntry( pEntry );
3999 return 0;
4004 // Funktionen zum Ausrichten der Eintraege am Grid
4007 // pStart == 0: Alle Eintraege werden ausgerichtet
4008 // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet
4009 void SvImpIconView::AdjustAtGrid( SvLBoxEntry* pStart )
4011 SvPtrarr aLists;
4012 pImpCursor->CreateGridAjustData( aLists, pStart );
4013 USHORT nCount = aLists.Count();
4014 for( USHORT nCur = 0; nCur < nCount; nCur++ )
4016 AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart );
4018 ImpIcnCursor::DestroyGridAdjustData( aLists );
4019 CheckScrollBars();
4022 // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um
4023 void SvImpIconView::AdjustAtGrid( const SvPtrarr& rRow, SvLBoxEntry* pStart )
4025 if( !rRow.Count() )
4026 return;
4028 BOOL bGo;
4029 if( !pStart )
4030 bGo = TRUE;
4031 else
4032 bGo = FALSE;
4034 long nCurRight = 0;
4035 for( USHORT nCur = 0; nCur < rRow.Count(); nCur++ )
4037 SvLBoxEntry* pCur = (SvLBoxEntry*)rRow[ nCur ];
4038 if( !bGo && pCur == pStart )
4039 bGo = TRUE;
4041 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur);
4042 // Massgebend (fuer das menschliche Auge) ist die Bitmap, da sonst
4043 // durch lange Texte der Eintrag stark springen kann
4044 const Rectangle& rBoundRect = GetBoundingRect( pCur, pViewData );
4045 Rectangle aCenterRect( CalcBmpRect( pCur, 0, pViewData ));
4046 if( bGo && !pViewData->IsEntryPosLocked() )
4048 long nWidth = aCenterRect.GetSize().Width();
4049 Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) );
4050 while( aNewPos.X() < nCurRight )
4051 aNewPos.X() += nGridDX;
4052 if( aNewPos != rBoundRect.TopLeft() )
4053 SetEntryPosition( pCur, aNewPos );
4054 nCurRight = aNewPos.X() + nWidth;
4056 else
4058 nCurRight = rBoundRect.Right();
4063 // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die
4064 // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden.
4065 // Das CenterRect beschreibt den Teil des BoundRects, der fuer
4066 // die Berechnung des Ziel-Rechtecks verwendet wird.
4067 Point SvImpIconView::AdjustAtGrid( const Rectangle& rCenterRect,
4068 const Rectangle& rBoundRect ) const
4070 Point aPos( rCenterRect.TopLeft() );
4071 Size aSize( rCenterRect.GetSize() );
4073 aPos.X() -= LROFFS_WINBORDER;
4074 aPos.Y() -= TBOFFS_WINBORDER;
4076 // align (ref ist mitte des rects)
4077 short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX);
4078 short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY);
4079 aPos.X() = nGridX * nGridDX;
4080 aPos.Y() = nGridY * nGridDY;
4081 // hor. center
4082 aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2;
4084 aPos.X() += LROFFS_WINBORDER;
4085 aPos.Y() += TBOFFS_WINBORDER;
4087 return aPos;
4091 void SvImpIconView::SetTextMode( SvIconViewTextMode eMode, SvLBoxEntry* pEntry )
4093 if( !pEntry )
4095 if( eTextMode != eMode )
4097 if( eTextMode == ShowTextDontKnow )
4098 eTextMode = ShowTextShort;
4099 eTextMode = eMode;
4100 pView->Arrange();
4103 else
4105 SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry);
4106 if( pViewData->eTextMode != eMode )
4108 pViewData->eTextMode = eMode;
4109 pModel->InvalidateEntry( pEntry );
4110 AdjustVirtSize( pViewData->aRect );
4115 SvIconViewTextMode SvImpIconView::GetTextMode( const SvLBoxEntry* pEntry,
4116 const SvIcnVwDataEntry* pViewData ) const
4118 if( !pEntry )
4119 return eTextMode;
4120 else
4122 if( !pViewData )
4123 pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
4124 return pViewData->GetTextMode();
4128 SvIconViewTextMode SvImpIconView::GetEntryTextModeSmart( const SvLBoxEntry* pEntry,
4129 const SvIcnVwDataEntry* pViewData ) const
4131 DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set");
4132 if( !pViewData )
4133 pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry));
4134 SvIconViewTextMode eMode = pViewData->GetTextMode();
4135 if( eMode == ShowTextDontKnow )
4136 return eTextMode;
4137 return eMode;
4140 void SvImpIconView::ShowFocusRect( const SvLBoxEntry* pEntry )
4142 if( !pEntry )
4143 pView->HideFocus();
4144 else
4146 Rectangle aRect ( CalcFocusRect( (SvLBoxEntry*)pEntry ) );
4147 pView->ShowFocus( aRect );
4151 IMPL_LINK(SvImpIconView, UserEventHdl, void*, EMPTYARG )
4153 nCurUserEvent = 0;
4154 AdjustScrollBars();
4155 Rectangle aRect;
4156 if( GetResizeRect(aRect) )
4157 PaintResizeRect( aRect );
4158 return 0;
4161 void SvImpIconView::CancelUserEvent()
4163 if( nCurUserEvent )
4165 Application::RemoveUserEvent( nCurUserEvent );
4166 nCurUserEvent = 0;