| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| #include <limits.h> |
| #ifndef _METRIC_HXX |
| #include <vcl/metric.hxx> |
| #endif |
| #include <vcl/svapp.hxx> |
| #ifdef DBG_UTIL |
| #include <vcl/sound.hxx> |
| #endif |
| |
| #include <svtools/svlbox.hxx> |
| #include <svtools/svicnvw.hxx> |
| #include <svimpicn.hxx> |
| #ifndef _SVLBITM_HXX |
| #include <svtools/svlbitm.hxx> |
| #endif |
| #include <svl/svarray.hxx> |
| |
| |
| |
| #define VIEWMODE_ICON 0x0001 // Text unter Bitmap |
| #define VIEWMODE_NAME 0x0002 // Text rechts neben Bitmap |
| #define VIEWMODE_TEXT 0x0004 // Text ohne Bitmap |
| |
| #define DD_SCROLL_PIXEL 10 |
| |
| // alle Angaben in Pixel |
| |
| #define ICONVIEW_OFFS_BMP_STRING 3 |
| |
| // fuer das Bounding-Rectangle |
| #define LROFFS_BOUND 2 |
| #define TBOFFS_BOUND 2 |
| |
| // fuer das Focus-Rectangle um Icons |
| #define LROFFS_ICON 2 |
| #define TBOFFS_ICON 2 |
| |
| #define NAMEVIEW_OFFS_BMP_STRING 3 |
| |
| // Abstaende von Fensterraendern |
| #define LROFFS_WINBORDER 4 |
| #define TBOFFS_WINBORDER 4 |
| |
| // Breitenoffset Highlight-Rect bei Text |
| #define LROFFS_TEXT 2 |
| |
| |
| #define ICNVIEWDATA(xPtr) (SvIcnVwDataEntry*)(pView->GetViewDataEntry(xPtr)) |
| #define ICNVIEWDATA2(xPtr) (SvIcnVwDataEntry*)(pView->pView->GetViewDataEntry(xPtr)) |
| |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| // ------------------------------------------------------------------------- |
| // Hilfsfunktionen von Thomas Hosemann zur mehrzeiligen Ausgabe von |
| // Strings. Die Funktionen werden spaeter in StarView integriert. |
| // ------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| |
| // keine doppelten Defines |
| #ifdef TEXT_DRAW_CLIP |
| #undef TEXT_DRAW_CLIP |
| #endif |
| #ifdef TEXT_DRAW_MULTILINE |
| #undef TEXT_DRAW_MULTILINE |
| #endif |
| #ifdef TEXT_DRAW_WORDBREAK |
| #undef TEXT_DRAW_WORDBREAK |
| #endif |
| |
| // #define TEXT_DRAW_DISABLE ((sal_uInt16)0x0001) |
| // #define TEXT_DRAW_3DLOOK ((sal_uInt16)0x0002) |
| // #define TEXT_DRAW_MNEMONIC ((sal_uInt16)0x0004) |
| #define TEXT_DRAW_LEFT ((sal_uInt16)0x0010) |
| #define TEXT_DRAW_CENTER ((sal_uInt16)0x0020) |
| #define TEXT_DRAW_RIGHT ((sal_uInt16)0x0040) |
| #define TEXT_DRAW_TOP ((sal_uInt16)0x0080) |
| #define TEXT_DRAW_VCENTER ((sal_uInt16)0x0100) |
| #define TEXT_DRAW_BOTTOM ((sal_uInt16)0x0200) |
| #define TEXT_DRAW_ENDELLIPSIS ((sal_uInt16)0x0400) |
| #define TEXT_DRAW_PATHELLIPSIS ((sal_uInt16)0x0800) |
| #define TEXT_DRAW_CLIP ((sal_uInt16)0x1000) |
| #define TEXT_DRAW_MULTILINE ((sal_uInt16)0x2000) |
| #define TEXT_DRAW_WORDBREAK ((sal_uInt16)0x4000) |
| |
| XubString GetEllipsisString( OutputDevice* pDev, |
| const XubString& rStr, long nMaxWidth, |
| sal_uInt16 nStyle = TEXT_DRAW_ENDELLIPSIS ) |
| { |
| XubString aStr = rStr; |
| |
| if ( nStyle & TEXT_DRAW_ENDELLIPSIS ) |
| { |
| sal_uInt16 nIndex = pDev->GetTextBreak( rStr, nMaxWidth ); |
| if ( nIndex != STRING_LEN ) |
| { |
| aStr.Erase( nIndex ); |
| if ( nIndex > 1 ) |
| { |
| aStr.AppendAscii("..."); |
| while ( aStr.Len() && |
| (pDev->GetTextWidth( aStr ) > nMaxWidth) ) |
| { |
| if ( (nIndex > 1) || (nIndex == aStr.Len()) ) |
| nIndex--; |
| aStr.Erase( nIndex, 1 ); |
| } |
| } |
| |
| if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) ) |
| aStr += rStr.GetChar( 0 ); |
| } |
| } |
| |
| return aStr; |
| } |
| |
| class TextLineInfo |
| { |
| private: |
| long mnWidth; |
| sal_uInt16 mnIndex; |
| sal_uInt16 mnLen; |
| |
| public: |
| TextLineInfo( long nWidth, sal_uInt16 nIndex, sal_uInt16 nLen ) |
| { |
| mnWidth = nWidth; |
| mnIndex = nIndex; |
| mnLen = nLen; |
| } |
| |
| long GetWidth() const { return mnWidth; } |
| sal_uInt16 GetIndex() const { return mnIndex; } |
| sal_uInt16 GetLen() const { return mnLen; } |
| }; |
| |
| #define MULTITEXTLINEINFO_RESIZE 16 |
| typedef TextLineInfo* PTextLineInfo; |
| |
| class MultiTextLineInfo |
| { |
| private: |
| PTextLineInfo* mpLines; |
| sal_uInt16 mnLines; |
| sal_uInt16 mnSize; |
| |
| public: |
| MultiTextLineInfo(); |
| ~MultiTextLineInfo(); |
| |
| void AddLine( TextLineInfo* pLine ); |
| void Clear(); |
| |
| TextLineInfo* GetLine( sal_uInt16 nLine ) const |
| { return mpLines[nLine]; } |
| sal_uInt16 Count() const { return mnLines; } |
| |
| private: |
| MultiTextLineInfo( const MultiTextLineInfo& ); |
| MultiTextLineInfo& operator=( const MultiTextLineInfo& ); |
| }; |
| |
| MultiTextLineInfo::MultiTextLineInfo() |
| { |
| mpLines = new PTextLineInfo[MULTITEXTLINEINFO_RESIZE]; |
| mnLines = 0; |
| mnSize = MULTITEXTLINEINFO_RESIZE; |
| } |
| |
| MultiTextLineInfo::~MultiTextLineInfo() |
| { |
| for ( sal_uInt16 i = 0; i < mnLines; i++ ) |
| delete mpLines[i]; |
| delete [] mpLines; |
| } |
| |
| void MultiTextLineInfo::AddLine( TextLineInfo* pLine ) |
| { |
| if ( mnSize == mnLines ) |
| { |
| mnSize += MULTITEXTLINEINFO_RESIZE; |
| PTextLineInfo* pNewLines = new PTextLineInfo[mnSize]; |
| memcpy( pNewLines, mpLines, mnLines*sizeof(PTextLineInfo) ); |
| mpLines = pNewLines; |
| } |
| |
| mpLines[mnLines] = pLine; |
| mnLines++; |
| } |
| |
| void MultiTextLineInfo::Clear() |
| { |
| for ( sal_uInt16 i = 0; i < mnLines; i++ ) |
| delete mpLines[i]; |
| mnLines = 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long GetTextLines( OutputDevice* pDev, MultiTextLineInfo& rLineInfo, |
| long nWidth, const XubString& rStr, |
| sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK ) |
| { |
| rLineInfo.Clear(); |
| if ( !rStr.Len() ) |
| return 0; |
| if ( nWidth <= 0 ) |
| nWidth = 1; |
| |
| sal_uInt16 nStartPos = 0; // Start-Position der Zeile |
| sal_uInt16 nLastLineLen = 0; // Zeilenlaenge bis zum vorherigen Wort |
| sal_uInt16 nLastWordPos = 0; // Position des letzten Wortanfangs |
| sal_uInt16 i = 0; |
| sal_uInt16 nPos; // StartPositon der Zeile (nur Temp) |
| sal_uInt16 nLen; // Laenge der Zeile (nur Temp) |
| sal_uInt16 nStrLen = rStr.Len(); |
| long nMaxLineWidth = 0; // Maximale Zeilenlaenge |
| long nLineWidth; // Aktuelle Zeilenlaenge |
| long nLastLineWidth = 0; // Zeilenlaenge der letzten Zeile |
| xub_Unicode c; |
| xub_Unicode c2; |
| const xub_Unicode* pStr = rStr.GetBuffer(); |
| sal_Bool bHardBreak = sal_False; |
| |
| do |
| { |
| c = pStr[i]; |
| |
| // Auf Zeilenende ermitteln |
| if ( (c == _CR) || (c == _LF) ) |
| bHardBreak = sal_True; |
| else |
| bHardBreak = sal_False; |
| |
| // Testen, ob ein Wortende erreicht ist |
| if ( bHardBreak || (i == nStrLen) || |
| (((c == ' ') || (c == '-')) && (nStyle & TEXT_DRAW_WORDBREAK)) ) |
| { |
| nLen = i-nStartPos; |
| if ( c == '-' ) |
| nLen++; |
| nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen ); |
| |
| // Findet ein Zeilenumbruch statt |
| if ( bHardBreak || (i == nStrLen) || |
| ((nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK)) ) |
| { |
| nPos = nStartPos; |
| |
| if ( (nLineWidth >= nWidth) && (nStyle & TEXT_DRAW_WORDBREAK) ) |
| { |
| nLineWidth = nLastLineWidth; |
| nLen = nLastLineLen; |
| nStartPos = nLastWordPos; |
| nLastLineLen = i-nStartPos; |
| nLastWordPos = nStartPos+nLastLineLen+1; |
| if ( c == '-' ) |
| nLastLineLen++; |
| else if ( bHardBreak && (i > nStartPos) ) |
| i--; |
| } |
| else |
| { |
| nStartPos = i; |
| // Zeilenende-Zeichen und '-' beruecksichtigen |
| if ( bHardBreak ) |
| { |
| nStartPos++; |
| c2 = pStr[i+1]; |
| if ( (c != c2) && ((c2 == _CR) || (c2 == _LF)) ) |
| { |
| nStartPos++; |
| i++; |
| } |
| } |
| else if ( c != '-' ) |
| nStartPos++; |
| nLastWordPos = nStartPos; |
| nLastLineLen = 0; |
| } |
| |
| if ( nLineWidth > nMaxLineWidth ) |
| nMaxLineWidth = nLineWidth; |
| |
| if ( nLen || bHardBreak ) |
| rLineInfo.AddLine( new TextLineInfo( nLineWidth, nPos, nLen ) ); |
| |
| // Testen, ob aktuelles Wort noch auf die Zeile passt, |
| // denn ansonsten mueessen wir es auftrennen |
| if ( nLastLineLen ) |
| { |
| nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen ); |
| if ( nLineWidth > nWidth ) |
| { |
| // Wenn ein Wortumbruch in einem Wort stattfindet, |
| // ist die maximale Zeilenlaenge die Laenge |
| // des laengsten Wortes |
| if ( nLineWidth > nMaxLineWidth ) |
| nMaxLineWidth = nLineWidth; |
| |
| // Solange Wort auftrennen, bis es auf eine Zeile passt |
| do |
| { |
| nPos = pDev->GetTextBreak( rStr, nWidth, nStartPos, nLastLineLen ); |
| nLen = nPos-nStartPos; |
| if ( !nLen ) |
| { |
| nPos++; |
| nLen++; |
| } |
| nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLen ); |
| rLineInfo.AddLine( new TextLineInfo( nLineWidth, nStartPos, nLen ) ); |
| nStartPos = nPos; |
| nLastLineLen = nLastLineLen - nLen; |
| nLineWidth = pDev->GetTextWidth( rStr, nStartPos, nLastLineLen ); |
| } |
| while ( nLineWidth > nWidth ); |
| } |
| nLastLineWidth = nLineWidth; |
| |
| // Bei Stringende muessen wir die letzte Zeile auch noch |
| // dranhaengen |
| if ( (i == nStrLen) && nLastLineLen ) |
| rLineInfo.AddLine( new TextLineInfo( nLastLineWidth, nStartPos, nLastLineLen ) ); |
| } |
| else |
| nLastLineWidth = 0; |
| } |
| else |
| { |
| nLastLineWidth = nLineWidth; |
| nLastLineLen = nLen; |
| nLastWordPos = nStartPos+nLastLineLen; |
| if ( c != '-' ) |
| nLastWordPos++; |
| } |
| } |
| |
| i++; |
| } |
| while ( i <= nStrLen ); |
| |
| return nMaxLineWidth; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 GetTextLines( OutputDevice* pDev, const Rectangle& rRect, |
| const XubString& rStr, |
| sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK, |
| long* pMaxWidth = NULL ) |
| { |
| MultiTextLineInfo aMultiLineInfo; |
| long nMaxWidth = GetTextLines( pDev, aMultiLineInfo, |
| rRect.GetWidth(), rStr, nStyle ); |
| if ( pMaxWidth ) |
| *pMaxWidth = nMaxWidth; |
| return aMultiLineInfo.Count(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle GetTextRect( OutputDevice* pDev, const Rectangle& rRect, |
| const XubString& rStr, |
| sal_uInt16 nStyle = TEXT_DRAW_WORDBREAK ) |
| { |
| Rectangle aRect = rRect; |
| sal_uInt16 nLines; |
| long nWidth = rRect.GetWidth(); |
| long nMaxWidth; |
| long nTextHeight; |
| |
| if ( nStyle & TEXT_DRAW_MULTILINE ) |
| { |
| MultiTextLineInfo aMultiLineInfo; |
| TextLineInfo* pLineInfo; |
| sal_uInt16 nFormatLines; |
| |
| nMaxWidth = 0; |
| GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle ); |
| nFormatLines = aMultiLineInfo.Count(); |
| nTextHeight = pDev->GetTextHeight(); |
| nLines = (sal_uInt16)(aRect.GetHeight()/nTextHeight); |
| if ( nFormatLines <= nLines ) |
| nLines = nFormatLines; |
| else |
| { |
| if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) ) |
| nLines = nFormatLines; |
| else |
| nMaxWidth = nWidth; |
| } |
| for ( sal_uInt16 i = 0; i < nLines; i++ ) |
| { |
| pLineInfo = aMultiLineInfo.GetLine( i ); |
| if ( pLineInfo->GetWidth() > nMaxWidth ) |
| nMaxWidth = pLineInfo->GetWidth(); |
| } |
| } |
| else |
| { |
| nLines = 1; |
| nMaxWidth = pDev->GetTextWidth( rStr ); |
| nTextHeight = pDev->GetTextHeight(); |
| if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ENDELLIPSIS) ) |
| nMaxWidth = nWidth; |
| } |
| |
| if ( nStyle & TEXT_DRAW_RIGHT ) |
| aRect.Left() = aRect.Right()-nMaxWidth+1; |
| else if ( nStyle & TEXT_DRAW_CENTER ) |
| { |
| aRect.Left() += (nWidth-nMaxWidth)/2; |
| aRect.Right() = aRect.Left()+nMaxWidth-1; |
| } |
| else |
| aRect.Right() = aRect.Left()+nMaxWidth-1; |
| |
| if ( nStyle & TEXT_DRAW_BOTTOM ) |
| aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1; |
| else if ( nStyle & TEXT_DRAW_VCENTER ) |
| { |
| aRect.Top() += (aRect.GetHeight()-(nTextHeight*nLines))/2; |
| aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1; |
| } |
| else |
| aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1; |
| |
| return aRect; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void DrawText( OutputDevice* pDev, const Rectangle& rRect, |
| const XubString& rStr, sal_uInt16 nStyle = 0 ) |
| { |
| if ( !rStr.Len() || rRect.IsEmpty() ) |
| return; |
| |
| Point aPos = rRect.TopLeft(); |
| long nWidth = rRect.GetWidth(); |
| long nHeight = rRect.GetHeight(); |
| FontAlign eAlign = pDev->GetFont().GetAlign(); |
| |
| if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) ) |
| return; |
| |
| // Mehrzeiligen Text behandeln wir anders |
| if ( nStyle & TEXT_DRAW_MULTILINE ) |
| { |
| String aLastLine; |
| Region aOldRegion; |
| MultiTextLineInfo aMultiLineInfo; |
| TextLineInfo* pLineInfo; |
| long nTextHeight = pDev->GetTextHeight(); |
| long nMaxTextWidth; |
| sal_uInt16 i; |
| sal_uInt16 nLines = (sal_uInt16)(nHeight/nTextHeight); |
| sal_uInt16 nFormatLines; |
| sal_Bool bIsClipRegion = sal_False; |
| nMaxTextWidth = GetTextLines( pDev, aMultiLineInfo, nWidth, rStr, nStyle ); |
| |
| nFormatLines = aMultiLineInfo.Count(); |
| if ( nFormatLines > nLines ) |
| { |
| if ( nStyle & TEXT_DRAW_ENDELLIPSIS ) |
| { |
| // Letzte Zeile zusammenbauen und kuerzen |
| nFormatLines = nLines-1; |
| pLineInfo = aMultiLineInfo.GetLine( nFormatLines ); |
| aLastLine = rStr.Copy( pLineInfo->GetIndex() ); |
| aLastLine.ConvertLineEnd( LINEEND_LF ); |
| aLastLine.SearchAndReplace( _LF, ' ' ); |
| aLastLine = GetEllipsisString( pDev, aLastLine, nWidth, nStyle ); |
| nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM); |
| nStyle |= TEXT_DRAW_TOP; |
| } |
| } |
| else |
| { |
| if ( nMaxTextWidth <= nWidth ) |
| nStyle &= ~TEXT_DRAW_CLIP; |
| } |
| |
| // Clipping setzen |
| if ( nStyle & TEXT_DRAW_CLIP ) |
| { |
| bIsClipRegion = pDev->IsClipRegion(); |
| if ( bIsClipRegion ) |
| { |
| aOldRegion = pDev->GetClipRegion(); |
| pDev->IntersectClipRegion( rRect ); |
| } |
| else |
| { |
| Region aRegion( rRect ); |
| pDev->SetClipRegion( aRegion ); |
| } |
| } |
| |
| // Vertikales Alignment |
| if ( nStyle & TEXT_DRAW_BOTTOM ) |
| aPos.Y() += nHeight-(nFormatLines*nTextHeight); |
| else if ( nStyle & TEXT_DRAW_VCENTER ) |
| aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2; |
| |
| // Font Alignment |
| if ( eAlign == ALIGN_BOTTOM ) |
| aPos.Y() += nTextHeight; |
| else if ( eAlign == ALIGN_BASELINE ) |
| aPos.Y() += pDev->GetFontMetric().GetAscent(); |
| |
| // Alle Zeilen ausgeben, bis auf die letzte |
| for ( i = 0; i < nFormatLines; i++ ) |
| { |
| pLineInfo = aMultiLineInfo.GetLine( i ); |
| if ( nStyle & TEXT_DRAW_RIGHT ) |
| aPos.X() += nWidth-pLineInfo->GetWidth(); |
| else if ( nStyle & TEXT_DRAW_CENTER ) |
| aPos.X() += (nWidth-pLineInfo->GetWidth())/2; |
| pDev->DrawText( aPos, rStr, pLineInfo->GetIndex(), pLineInfo->GetLen() ); |
| aPos.Y() += nTextHeight; |
| aPos.X() = rRect.Left(); |
| } |
| |
| // Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben, |
| // da die Zeile gekuerzt wurde |
| if ( aLastLine.Len() ) |
| pDev->DrawText( aPos, aLastLine ); |
| |
| // Clipping zuruecksetzen |
| if ( nStyle & TEXT_DRAW_CLIP ) |
| { |
| if ( bIsClipRegion ) |
| pDev->SetClipRegion( aOldRegion ); |
| else |
| pDev->SetClipRegion(); |
| } |
| } |
| else |
| { |
| XubString aStr = rStr; |
| Size aTextSize(pDev->GetTextWidth( aStr ), pDev->GetTextHeight()); |
| |
| // Evt. Text kuerzen |
| if ( aTextSize.Width() > nWidth ) |
| { |
| if ( nStyle & TEXT_DRAW_ENDELLIPSIS ) |
| { |
| aStr = GetEllipsisString( pDev, rStr, nWidth, nStyle ); |
| nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT); |
| nStyle |= TEXT_DRAW_LEFT; |
| aTextSize.Width() = pDev->GetTextWidth(aStr); |
| } |
| } |
| else |
| { |
| if ( aTextSize.Height() <= nHeight ) |
| nStyle &= ~TEXT_DRAW_CLIP; |
| } |
| |
| // Vertikales Alignment |
| if ( nStyle & TEXT_DRAW_RIGHT ) |
| aPos.X() += nWidth-aTextSize.Width(); |
| else if ( nStyle & TEXT_DRAW_CENTER ) |
| aPos.X() += (nWidth-aTextSize.Width())/2; |
| |
| // Font Alignment |
| if ( eAlign == ALIGN_BOTTOM ) |
| aPos.Y() += aTextSize.Height(); |
| else if ( eAlign == ALIGN_BASELINE ) |
| aPos.Y() += pDev->GetFontMetric().GetAscent(); |
| |
| if ( nStyle & TEXT_DRAW_BOTTOM ) |
| aPos.Y() += nHeight-aTextSize.Height(); |
| else if ( nStyle & TEXT_DRAW_VCENTER ) |
| aPos.Y() += (nHeight-aTextSize.Height())/2; |
| |
| if ( nStyle & TEXT_DRAW_CLIP ) |
| { |
| sal_Bool bIsClipRegion = pDev->IsClipRegion(); |
| if ( bIsClipRegion ) |
| { |
| Region aOldRegion = pDev->GetClipRegion(); |
| pDev->IntersectClipRegion( rRect ); |
| pDev->DrawText( aPos, aStr ); |
| pDev->SetClipRegion( aOldRegion ); |
| } |
| else |
| { |
| Region aRegion( rRect ); |
| pDev->SetClipRegion( aRegion ); |
| pDev->DrawText( aPos, aStr ); |
| pDev->SetClipRegion(); |
| } |
| } |
| else |
| pDev->DrawText( aPos, aStr ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| //-------------------------------------------------------------------------- |
| |
| |
| #define DRAWTEXT_FLAGS (TEXT_DRAW_CENTER|TEXT_DRAW_TOP|TEXT_DRAW_ENDELLIPSIS|\ |
| TEXT_DRAW_CLIP|TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK) |
| |
| |
| class ImpIcnCursor |
| { |
| SvImpIconView* pView; |
| SvPtrarr* pColumns; |
| SvPtrarr* pRows; |
| sal_Bool* pGridMap; |
| long nGridDX, nGridDY; |
| long nGridCols, nGridRows; |
| long nCols; |
| long nRows; |
| short nDeltaWidth; |
| short nDeltaHeight; |
| SvLBoxEntry* pCurEntry; |
| void SetDeltas(); |
| void ImplCreate(); |
| void Create() { if( !pColumns ) ImplCreate(); } |
| |
| sal_uInt16 GetSortListPos( SvPtrarr* pList, long nValue, int bVertical); |
| SvLBoxEntry* SearchCol(sal_uInt16 nCol,sal_uInt16 nTop,sal_uInt16 nBottom,sal_uInt16 nPref, |
| sal_Bool bDown, sal_Bool bSimple ); |
| SvLBoxEntry* SearchRow(sal_uInt16 nRow,sal_uInt16 nRight,sal_uInt16 nLeft,sal_uInt16 nPref, |
| sal_Bool bRight, sal_Bool bSimple ); |
| |
| void ExpandGrid(); |
| void CreateGridMap(); |
| // Rueckgabe sal_False: Eintrag liegt nicht in der GridMap. rGridx,y werden |
| // dann an nGridCols, nGridRows geclippt |
| sal_Bool GetGrid( const Point& rDocPos, sal_uInt16& rGridX, sal_uInt16& rGridY ) const; |
| void SetGridUsed( sal_uInt16 nDX, sal_uInt16 nDY, sal_Bool bUsed ) |
| { |
| pGridMap[ (nDY * nGridCols) + nDX ] = bUsed; |
| } |
| sal_Bool IsGridUsed( sal_uInt16 nDX, sal_uInt16 nDY ) |
| { |
| return pGridMap[ (nDY * nGridCols) + nDX ]; |
| } |
| public: |
| ImpIcnCursor( SvImpIconView* pOwner ); |
| ~ImpIcnCursor(); |
| void Clear( sal_Bool bGridToo = sal_True ); |
| |
| // fuer Cursortravelling usw. |
| SvLBoxEntry* GoLeftRight( SvLBoxEntry*, sal_Bool bRight ); |
| SvLBoxEntry* GoUpDown( SvLBoxEntry*, sal_Bool bDown ); |
| |
| // Rueckgaebe: sal_False == Das leere Rect steht hinter dem letzten |
| // Eintrag; d.h. beim naechsten Einfuegen ergibt sich das naechste |
| // leere Rechteck durch Addition. Hinweis: Das Rechteck kann dann |
| // ausserhalb des View-Space liegen |
| sal_Bool FindEmptyGridRect( Rectangle& rRect ); |
| |
| // Erzeugt fuer jede Zeile (Hoehe=nGridDY) eine nach BoundRect.Left() |
| // sortierte Liste der Eintraege, die in ihr stehen. Eine Liste kann |
| // leer sein. Die Listen gehen in das Eigentum des Rufenden ueber und |
| // muessen mit DestroyGridAdjustData geloescht werden |
| void CreateGridAjustData( SvPtrarr& pLists, SvLBoxEntry* pRow=0); |
| static void DestroyGridAdjustData( SvPtrarr& rLists ); |
| void SetGridUsed( const Rectangle&, sal_Bool bUsed = sal_True ); |
| }; |
| |
| |
| |
| |
| SvImpIconView::SvImpIconView( SvIconView* pCurView, SvLBoxTreeList* pTree, |
| WinBits i_nWinStyle ) : |
| aVerSBar( pCurView, WB_DRAG | WB_VSCROLL ), |
| aHorSBar( pCurView, WB_DRAG | WB_HSCROLL ) |
| { |
| pView = pCurView; |
| pModel = pTree; |
| pCurParent = 0; |
| pZOrderList = new SvPtrarr; |
| SetStyle( i_nWinStyle ); |
| nHorDist = 0; |
| nVerDist = 0; |
| nFlags = 0; |
| nCurUserEvent = 0; |
| nMaxVirtWidth = 200; |
| pDDRefEntry = 0; |
| pDDDev = 0; |
| pDDBufDev = 0; |
| pDDTempDev = 0; |
| eTextMode = ShowTextShort; |
| pImpCursor = new ImpIcnCursor( this ); |
| |
| aVerSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollUpDownHdl ) ); |
| aHorSBar.SetScrollHdl( LINK( this, SvImpIconView, ScrollLeftRightHdl ) ); |
| nHorSBarHeight = aHorSBar.GetSizePixel().Height(); |
| nVerSBarWidth = aVerSBar.GetSizePixel().Width(); |
| |
| aMouseMoveTimer.SetTimeout( 20 ); |
| aMouseMoveTimer.SetTimeoutHdl(LINK(this,SvImpIconView,MouseMoveTimeoutHdl)); |
| |
| aEditTimer.SetTimeout( 800 ); |
| aEditTimer.SetTimeoutHdl(LINK(this,SvImpIconView,EditTimeoutHdl)); |
| |
| Clear( sal_True ); |
| } |
| |
| SvImpIconView::~SvImpIconView() |
| { |
| StopEditTimer(); |
| CancelUserEvent(); |
| delete pZOrderList; |
| delete pImpCursor; |
| delete pDDDev; |
| delete pDDBufDev; |
| delete pDDTempDev; |
| ClearSelectedRectList(); |
| } |
| |
| void SvImpIconView::Clear( sal_Bool bInCtor ) |
| { |
| StopEditTimer(); |
| CancelUserEvent(); |
| nMaxBmpWidth = 0; |
| nMaxBmpHeight = 0; |
| nMaxTextWidth = 0; |
| bMustRecalcBoundingRects = sal_False; |
| nMaxBoundHeight = 0; |
| |
| //XXX |
| nFlags |= F_GRID_INSERT; |
| nFlags &= ~F_PAINTED; |
| SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) ); |
| pCursor = 0; |
| if( !bInCtor ) |
| { |
| pImpCursor->Clear(); |
| aVirtOutputSize.Width() = 0; |
| aVirtOutputSize.Height() = 0; |
| pZOrderList->Remove(0,pZOrderList->Count()); |
| MapMode aMapMode( pView->GetMapMode()); |
| aMapMode.SetOrigin( Point() ); |
| pView->SetMapMode( aMapMode ); |
| if( pView->IsUpdateMode() ) |
| pView->Invalidate(); |
| } |
| AdjustScrollBars(); |
| } |
| |
| void SvImpIconView::SetStyle( const WinBits i_nWinStyle ) |
| { |
| nViewMode = VIEWMODE_TEXT; |
| if( i_nWinStyle & WB_NAME ) |
| nViewMode = VIEWMODE_NAME; |
| if( i_nWinStyle & WB_ICON ) |
| nViewMode = VIEWMODE_ICON; |
| } |
| |
| |
| IMPL_LINK( SvImpIconView, ScrollUpDownHdl, ScrollBar *, pScrollBar ) |
| { |
| pView->EndEditing( sal_True ); |
| // Pfeil hoch: delta=-1; Pfeil runter: delta=+1 |
| Scroll( 0, pScrollBar->GetDelta(), sal_True ); |
| return 0; |
| } |
| |
| IMPL_LINK( SvImpIconView, ScrollLeftRightHdl, ScrollBar *, pScrollBar ) |
| { |
| pView->EndEditing( sal_True ); |
| // Pfeil links: delta=-1; Pfeil rechts: delta=+1 |
| Scroll( pScrollBar->GetDelta(), 0, sal_True ); |
| return 0; |
| } |
| |
| void SvImpIconView::ChangedFont() |
| { |
| StopEditTimer(); |
| ImpArrange(); |
| } |
| |
| |
| void SvImpIconView::CheckAllSizes() |
| { |
| nMaxTextWidth = 0; |
| nMaxBmpWidth = 0; |
| nMaxBmpHeight = 0; |
| SvLBoxEntry* pEntry = pModel->First(); |
| while( pEntry ) |
| { |
| CheckSizes( pEntry ); |
| pEntry = pModel->Next( pEntry ); |
| } |
| } |
| |
| void SvImpIconView::CheckSizes( SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) |
| { |
| Size aSize; |
| |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| |
| SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| if( pStringItem ) |
| { |
| aSize = GetItemSize( pView, pEntry, pStringItem, pViewData ); |
| if( aSize.Width() > nMaxTextWidth ) |
| { |
| nMaxTextWidth = aSize.Width(); |
| if( !(nFlags & F_GRIDMODE ) ) |
| bMustRecalcBoundingRects = sal_True; |
| } |
| } |
| SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); |
| if( pBmpItem ) |
| { |
| aSize = GetItemSize( pView, pEntry, pBmpItem, pViewData ); |
| if( aSize.Width() > nMaxBmpWidth ) |
| { |
| nMaxBmpWidth = aSize.Width(); |
| nMaxBmpWidth += (2*LROFFS_ICON); |
| if( !(nFlags & F_GRIDMODE ) ) |
| bMustRecalcBoundingRects = sal_True; |
| } |
| if( aSize.Height() > nMaxBmpHeight ) |
| { |
| nMaxBmpHeight = aSize.Height(); |
| nMaxBmpHeight += (2*TBOFFS_ICON);; |
| if( !(nFlags & F_GRIDMODE ) ) |
| bMustRecalcBoundingRects = sal_True; |
| } |
| } |
| } |
| |
| void SvImpIconView::EntryInserted( SvLBoxEntry* pEntry ) |
| { |
| if( pModel->GetParent(pEntry) == pCurParent ) |
| { |
| StopEditTimer(); |
| DBG_ASSERT(pZOrderList->GetPos(pEntry)==0xffff,"EntryInserted:ZOrder?"); |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| if( nFlags & F_GRIDMODE ) |
| pImpCursor->Clear( sal_False ); |
| else |
| pImpCursor->Clear( sal_True ); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| CheckSizes( pEntry, pViewData ); |
| if( pView->IsUpdateMode() ) |
| { |
| FindBoundingRect( pEntry, pViewData ); |
| PaintEntry( pEntry, pViewData ); |
| } |
| else |
| InvalidateBoundingRect( pViewData->aRect ); |
| } |
| } |
| |
| void SvImpIconView::RemovingEntry( SvLBoxEntry* pEntry ) |
| { |
| if( pModel->GetParent(pEntry) == pCurParent) |
| { |
| StopEditTimer(); |
| DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"RemovingEntry:ZOrder?"); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( IsBoundingRectValid( pViewData->aRect ) ) |
| { |
| // bei gueltigem Bounding-Rect muss in EntryRemoved eine |
| // Sonderbehandlung erfolgen |
| nFlags |= F_ENTRY_REMOVED; |
| pView->Invalidate( pViewData->aRect ); |
| } |
| if( pEntry == pCursor ) |
| { |
| SvLBoxEntry* pNewCursor = GetNewCursor(); |
| ShowCursor( sal_False ); |
| pCursor = 0; // damit er nicht deselektiert wird |
| SetCursor( pNewCursor ); |
| } |
| sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry ); |
| pZOrderList->Remove( nPos, 1 ); |
| pImpCursor->Clear(); |
| } |
| } |
| |
| void SvImpIconView::EntryRemoved() |
| { |
| if( (nFlags & (F_ENTRY_REMOVED | F_PAINTED)) == (F_ENTRY_REMOVED | F_PAINTED)) |
| { |
| // Ein Eintrag mit gueltigem BoundRect wurde geloescht und wir |
| // haben schon mal gepaintet. In diesem Fall muessen wir die |
| // Position des naechsten Eintrags, der eingefuegt wird oder noch |
| // kein gueltiges BoundRect hat, "suchen" d.h. ein "Loch" in |
| // der View auffuellen. |
| nFlags &= ~( F_ENTRY_REMOVED | F_GRID_INSERT ); |
| } |
| } |
| |
| |
| void SvImpIconView::MovingEntry( SvLBoxEntry* pEntry ) |
| { |
| DBG_ASSERT(pEntry,"MovingEntry: 0!"); |
| pNextCursor = 0; |
| StopEditTimer(); |
| if( pModel->GetParent(pEntry) == pCurParent ) |
| { |
| DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"MovingEntry:ZOrder?"); |
| nFlags |= F_MOVING_SIBLING; |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( IsBoundingRectValid( pViewData->aRect ) ) |
| pView->Invalidate( pViewData->aRect ); |
| // falls Eintrag seinen Parent wechselt vorsichtshalber |
| // die neue Cursorposition berechnen |
| if( pEntry == pCursor ) |
| pNextCursor = GetNewCursor(); |
| pImpCursor->Clear(); |
| } |
| } |
| |
| |
| void SvImpIconView::EntryMoved( SvLBoxEntry* pEntry ) |
| { |
| ShowCursor( sal_False ); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( pModel->GetParent(pEntry)==pCurParent ) |
| { |
| if( nFlags & F_MOVING_SIBLING ) |
| { |
| // die Neu-Positionierung eines Eintrags bei D&D innerhalb |
| // einer IconView findet bereits in NotifyMoving statt |
| // (MovingEntry/EntryMoved wird dann nicht mehr gerufen) |
| ToTop( pEntry ); |
| } |
| else |
| { |
| pImpCursor->Clear(); |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| DBG_ASSERT(pZOrderList->Count()==pModel->GetChildCount(pCurParent),"EntryMoved:Bad zorder count"); |
| FindBoundingRect( pEntry, pViewData ); |
| } |
| PaintEntry( pEntry, pViewData ); |
| } |
| else |
| { |
| if( pEntry == pCursor ) |
| { |
| DBG_ASSERT(pNextCursor,"EntryMoved: Next cursor bad"); |
| SetCursor( pNextCursor ); |
| } |
| pImpCursor->Clear(); |
| sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry ); |
| pZOrderList->Remove( nPos, 1 ); |
| pView->Select( pEntry, sal_False ); |
| // wenn er nochmal in dieser View auftaucht, muss sein |
| // Bounding-Rect neu berechnet werden |
| InvalidateBoundingRect( pViewData->aRect ); |
| } |
| nFlags &= (~F_MOVING_SIBLING); |
| } |
| |
| void SvImpIconView::TreeInserted( SvLBoxEntry* pEntry ) |
| { |
| EntryMoved( pEntry ); // vorlaeufig |
| } |
| |
| void SvImpIconView::EntryExpanded( SvLBoxEntry* ) |
| { |
| } |
| |
| void SvImpIconView::EntryCollapsed( SvLBoxEntry*) |
| { |
| } |
| |
| void SvImpIconView::CollapsingEntry( SvLBoxEntry* ) |
| { |
| } |
| |
| void SvImpIconView::EntrySelected( SvLBoxEntry* pEntry, sal_Bool bSelect ) |
| { |
| if( pModel->GetParent(pEntry) != pCurParent ) |
| return; |
| |
| // bei SingleSelection dafuer sorgen, dass der Cursor immer |
| // auf dem (einzigen) selektierten Eintrag steht |
| if( bSelect && pCursor && |
| pView->GetSelectionMode() == SINGLE_SELECTION && |
| pEntry != pCursor ) |
| { |
| SetCursor( pEntry ); |
| DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?"); |
| } |
| // bei Gummibandselektion ist uns das zu teuer |
| if( !(nFlags & F_RUBBERING )) |
| ToTop( pEntry ); |
| if( pView->IsUpdateMode() ) |
| { |
| if( pEntry == pCursor ) |
| ShowCursor( sal_False ); |
| if( nFlags & F_RUBBERING ) |
| PaintEntry( pEntry ); |
| else |
| pView->Invalidate( GetBoundingRect( pEntry ) ); |
| if( pEntry == pCursor ) |
| ShowCursor( sal_True ); |
| } |
| } |
| |
| void SvImpIconView::SetNextEntryPos(const Point& rPos) |
| { |
| aPrevBoundRect.SetPos( rPos ); |
| aPrevBoundRect.Right() = LONG_MAX; // dont know |
| } |
| |
| Point SvImpIconView::FindNextEntryPos( const Size& rBoundSize ) |
| { |
| if( nFlags & F_GRIDMODE ) |
| { |
| if( nFlags & F_GRID_INSERT ) |
| { |
| if( aPrevBoundRect.Right() != LONG_MAX ) |
| { |
| // passt der naechste Entry noch in die Zeile ? |
| long nNextWidth = aPrevBoundRect.Right() + nGridDX + LROFFS_WINBORDER; |
| if( nNextWidth > aVirtOutputSize.Width() ) |
| { |
| // darf aVirtOutputSize verbreitert werden ? |
| if( nNextWidth < nMaxVirtWidth ) |
| { |
| // verbreitern & in Zeile aufnehmen |
| aPrevBoundRect.Left() += nGridDX; |
| } |
| else |
| { |
| // erhoehen & neue Zeile beginnen |
| aPrevBoundRect.Top() += nGridDY; |
| aPrevBoundRect.Left() = LROFFS_WINBORDER; |
| } |
| } |
| else |
| { |
| // in die Zeile aufnehmen |
| aPrevBoundRect.Left() += nGridDX; |
| } |
| } |
| aPrevBoundRect.SetSize( Size( nGridDX, nGridDY ) ); |
| } |
| else |
| { |
| if( !pImpCursor->FindEmptyGridRect( aPrevBoundRect ) ) |
| { |
| // mitten in den Entries gibts keine Loecher mehr, |
| // wir koennen also wieder ins "Fast Insert" springen |
| nFlags |= F_GRID_INSERT; |
| } |
| } |
| } |
| else |
| { |
| if( aPrevBoundRect.Right() != LONG_MAX ) |
| { |
| // passt der naechste Entry noch in die Zeile ? |
| long nNextWidth=aPrevBoundRect.Right()+rBoundSize.Width()+LROFFS_BOUND+nHorDist; |
| if( nNextWidth > aVirtOutputSize.Width() ) |
| { |
| // darf aVirtOutputSize verbreitert werden ? |
| if( nNextWidth < nMaxVirtWidth ) |
| { |
| // verbreitern & in Zeile aufnehmen |
| aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() ); |
| aPrevBoundRect.Left() += nHorDist; |
| } |
| else |
| { |
| // erhoehen & neue Zeile beginnen |
| aPrevBoundRect.Top() += nMaxBoundHeight + nVerDist + TBOFFS_BOUND; |
| aPrevBoundRect.Left() = LROFFS_WINBORDER; |
| } |
| } |
| else |
| { |
| // in die Zeile aufnehmen |
| aPrevBoundRect.SetPos( aPrevBoundRect.TopRight() ); |
| aPrevBoundRect.Left() += nHorDist; |
| } |
| } |
| aPrevBoundRect.SetSize( rBoundSize ); |
| } |
| return aPrevBoundRect.TopLeft(); |
| } |
| |
| void SvImpIconView::ResetVirtSize() |
| { |
| StopEditTimer(); |
| aVirtOutputSize.Width() = 0; |
| aVirtOutputSize.Height() = 0; |
| sal_Bool bLockedEntryFound = sal_False; |
| nFlags &= (~F_GRID_INSERT); |
| SvLBoxEntry* pCur = pModel->FirstChild( pCurParent ); |
| while( pCur ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur); |
| if( pViewData->IsEntryPosLocked() ) |
| { |
| // VirtSize u.a. anpassen |
| if( !IsBoundingRectValid( pViewData->aRect ) ) |
| FindBoundingRect( pCur, pViewData ); |
| else |
| AdjustVirtSize( pViewData->aRect ); |
| bLockedEntryFound = sal_True; |
| } |
| else |
| InvalidateBoundingRect( pViewData->aRect ); |
| |
| pCur = pModel->NextSibling( pCur ); |
| } |
| if( !bLockedEntryFound ) |
| { |
| //XXX |
| nFlags |= F_GRID_INSERT; |
| } |
| |
| SetNextEntryPos( Point( LROFFS_WINBORDER, TBOFFS_WINBORDER ) ); |
| pImpCursor->Clear(); |
| } |
| |
| |
| void SvImpIconView::AdjustVirtSize( const Rectangle& rRect ) |
| { |
| long nHeightOffs = 0; |
| long nWidthOffs = 0; |
| |
| if( aVirtOutputSize.Width() < (rRect.Right()+LROFFS_WINBORDER) ) |
| nWidthOffs = (rRect.Right()+LROFFS_WINBORDER) - aVirtOutputSize.Width(); |
| |
| if( aVirtOutputSize.Height() < (rRect.Bottom()+TBOFFS_WINBORDER) ) |
| nHeightOffs = (rRect.Bottom()+TBOFFS_WINBORDER) - aVirtOutputSize.Height(); |
| |
| if( nWidthOffs || nHeightOffs ) |
| { |
| Range aRange; |
| aVirtOutputSize.Width() += nWidthOffs; |
| aRange.Max() = aVirtOutputSize.Width(); |
| aHorSBar.SetRange( aRange ); |
| |
| aVirtOutputSize.Height() += nHeightOffs; |
| aRange.Max() = aVirtOutputSize.Height(); |
| aVerSBar.SetRange( aRange ); |
| |
| pImpCursor->Clear(); |
| AdjustScrollBars(); |
| } |
| } |
| |
| void SvImpIconView::Arrange() |
| { |
| nMaxVirtWidth = aOutputSize.Width(); |
| ImpArrange(); |
| } |
| |
| void SvImpIconView::ImpArrange() |
| { |
| StopEditTimer(); |
| ShowCursor( sal_False ); |
| ResetVirtSize(); |
| bMustRecalcBoundingRects = sal_False; |
| MapMode aMapMode( pView->GetMapMode()); |
| aMapMode.SetOrigin( Point() ); |
| pView->SetMapMode( aMapMode ); |
| CheckAllSizes(); |
| RecalcAllBoundingRectsSmart(); |
| pView->Invalidate(); |
| ShowCursor( sal_True ); |
| } |
| |
| void SvImpIconView::Paint( const Rectangle& rRect ) |
| { |
| if( !pView->IsUpdateMode() ) |
| return; |
| |
| #if defined(DBG_UTIL) && defined(OV_DRAWGRID) |
| if( nFlags & F_GRIDMODE ) |
| { |
| Color aOldColor = pView->GetLineColor(); |
| Color aNewColor( COL_BLACK ); |
| pView->SetLineColor( aNewColor ); |
| Point aOffs( pView->GetMapMode().GetOrigin()); |
| Size aXSize( pView->GetOutputSizePixel() ); |
| for( long nDX = nGridDX; nDX <= aXSize.Width(); nDX += nGridDX ) |
| { |
| Point aStart( nDX+LROFFS_BOUND, 0 ); |
| Point aEnd( nDX+LROFFS_BOUND, aXSize.Height()); |
| aStart -= aOffs; |
| aEnd -= aOffs; |
| pView->DrawLine( aStart, aEnd ); |
| } |
| for( long nDY = nGridDY; nDY <= aXSize.Height(); nDY += nGridDY ) |
| { |
| Point aStart( 0, nDY+TBOFFS_BOUND ); |
| Point aEnd( aXSize.Width(), nDY+TBOFFS_BOUND ); |
| aStart -= aOffs; |
| aEnd -= aOffs; |
| pView->DrawLine( aStart, aEnd ); |
| } |
| pView->SetLineColor( aOldColor ); |
| } |
| #endif |
| nFlags |= F_PAINTED; |
| |
| if( !(pModel->HasChilds( pCurParent ) )) |
| return; |
| if( !pCursor ) |
| pCursor = pModel->FirstChild( pCurParent ); |
| |
| sal_uInt16 nCount = pZOrderList->Count(); |
| if( !nCount ) |
| return; |
| |
| SvPtrarr* pNewZOrderList = new SvPtrarr; |
| SvPtrarr* pPaintedEntries = new SvPtrarr; |
| |
| sal_uInt16 nPos = 0; |
| while( nCount ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos )); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| const Rectangle& rBoundRect = GetBoundingRect( pEntry, pViewData ); |
| if( rRect.IsOver( rBoundRect ) ) |
| { |
| PaintEntry( pEntry, rBoundRect.TopLeft(), pViewData ); |
| // Eintraege, die neu gezeichnet werden, auf Top setzen |
| pPaintedEntries->Insert( pEntry, pPaintedEntries->Count() ); |
| } |
| else |
| pNewZOrderList->Insert( pEntry, pNewZOrderList->Count() ); |
| |
| nCount--; |
| nPos++; |
| } |
| delete pZOrderList; |
| pZOrderList = pNewZOrderList; |
| nCount = pPaintedEntries->Count(); |
| if( nCount ) |
| { |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| pZOrderList->Insert( pPaintedEntries->GetObject( nCur ),pZOrderList->Count()); |
| } |
| delete pPaintedEntries; |
| |
| Rectangle aRect; |
| if( GetResizeRect( aRect )) |
| PaintResizeRect( aRect ); |
| } |
| |
| sal_Bool SvImpIconView::GetResizeRect( Rectangle& rRect ) |
| { |
| if( aHorSBar.IsVisible() && aVerSBar.IsVisible() ) |
| { |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin()); |
| aOrigin *= -1; |
| aOrigin.X() += aOutputSize.Width(); |
| aOrigin.Y() += aOutputSize.Height(); |
| rRect.SetPos( aOrigin ); |
| rRect.SetSize( Size( nVerSBarWidth, nHorSBarHeight)); |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| void SvImpIconView::PaintResizeRect( const Rectangle& rRect ) |
| { |
| const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings(); |
| Color aNewColor = rStyleSettings.GetFaceColor(); |
| Color aOldColor = pView->GetFillColor(); |
| pView->SetFillColor( aNewColor ); |
| pView->DrawRect( rRect ); |
| pView->SetFillColor( aOldColor ); |
| } |
| |
| void SvImpIconView::RepaintSelectionItems() |
| { |
| DBG_ERROR("RepaintSelectionItems"); |
| pView->Invalidate(); // vorlaeufig |
| } |
| |
| SvLBoxItem* SvImpIconView::GetItem( SvLBoxEntry* pEntry, |
| const Point& rAbsPos ) |
| { |
| Rectangle aRect; |
| SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| if( pStringItem ) |
| { |
| aRect = CalcTextRect( pEntry, pStringItem ); |
| if( aRect.IsInside( rAbsPos ) ) |
| return pStringItem; |
| } |
| SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); |
| if( pBmpItem ) |
| { |
| aRect = CalcBmpRect( pEntry ); |
| if( aRect.IsInside( rAbsPos ) ) |
| return pBmpItem; |
| } |
| return 0; |
| } |
| |
| void SvImpIconView::CalcDocPos( Point& aMaeuschenPos ) |
| { |
| aMaeuschenPos -= pView->GetMapMode().GetOrigin(); |
| } |
| |
| void SvImpIconView::MouseButtonDown( const MouseEvent& rMEvt) |
| { |
| StopEditTimer(); |
| pView->GrabFocus(); |
| Point aDocPos( rMEvt.GetPosPixel() ); |
| if(aDocPos.X()>=aOutputSize.Width() || aDocPos.Y()>=aOutputSize.Height()) |
| return; |
| CalcDocPos( aDocPos ); |
| SvLBoxEntry* pEntry = GetEntry( aDocPos ); |
| if( !pEntry ) |
| { |
| if( pView->GetSelectionMode() != SINGLE_SELECTION ) |
| { |
| if( !rMEvt.IsMod1() ) // Ctrl |
| { |
| pView->SelectAll( sal_False ); |
| ClearSelectedRectList(); |
| } |
| else |
| nFlags |= F_ADD_MODE; |
| nFlags |= F_RUBBERING; |
| aCurSelectionRect.SetPos( aDocPos ); |
| pView->CaptureMouse(); |
| } |
| return; |
| } |
| |
| sal_Bool bSelected = pView->IsSelected( pEntry ); |
| sal_Bool bEditingEnabled = pView->IsInplaceEditingEnabled(); |
| |
| if( rMEvt.GetClicks() == 2 ) |
| { |
| DeselectAllBut( pEntry ); |
| pView->pHdlEntry = pEntry; |
| pView->DoubleClickHdl(); |
| } |
| else |
| { |
| // Inplace-Editing ? |
| if( rMEvt.IsMod2() ) // Alt? |
| { |
| if( bEditingEnabled ) |
| { |
| SvLBoxItem* pItem = GetItem(pEntry,aDocPos); |
| if( pItem ) |
| pView->EditingRequest( pEntry, pItem, aDocPos); |
| } |
| } |
| else if( pView->GetSelectionMode() == SINGLE_SELECTION ) |
| { |
| DeselectAllBut( pEntry ); |
| SetCursor( pEntry ); |
| pView->Select( pEntry, sal_True ); |
| if( bEditingEnabled && bSelected && !rMEvt.GetModifier() && |
| rMEvt.IsLeft() && IsTextHit( pEntry, aDocPos ) ) |
| { |
| nFlags |= F_START_EDITTIMER_IN_MOUSEUP; |
| } |
| } |
| else |
| { |
| if( !rMEvt.GetModifier() ) |
| { |
| if( !bSelected ) |
| { |
| DeselectAllBut( pEntry ); |
| SetCursor( pEntry ); |
| pView->Select( pEntry, sal_True ); |
| } |
| else |
| { |
| // erst im Up deselektieren, falls Move per D&D! |
| nFlags |= F_DOWN_DESELECT; |
| if( bEditingEnabled && IsTextHit( pEntry, aDocPos ) && |
| rMEvt.IsLeft()) |
| { |
| nFlags |= F_START_EDITTIMER_IN_MOUSEUP; |
| } |
| } |
| } |
| else if( rMEvt.IsMod1() ) |
| nFlags |= F_DOWN_CTRL; |
| } |
| } |
| } |
| |
| void SvImpIconView::MouseButtonUp( const MouseEvent& rMEvt ) |
| { |
| aMouseMoveTimer.Stop(); |
| pView->ReleaseMouse(); |
| // HACK, da Einar noch nicht PrepareCommandEvent aufruft |
| if( rMEvt.IsRight() && (nFlags & (F_DOWN_CTRL | F_DOWN_DESELECT) )) |
| nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); |
| |
| if( nFlags & F_RUBBERING ) |
| { |
| aMouseMoveTimer.Stop(); |
| AddSelectedRect( aCurSelectionRect ); |
| HideSelectionRect(); |
| nFlags &= ~(F_RUBBERING | F_ADD_MODE); |
| } |
| |
| SvLBoxEntry* pEntry = pView->GetEntry( rMEvt.GetPosPixel(), sal_True ); |
| if( pEntry ) |
| { |
| if( nFlags & F_DOWN_CTRL ) |
| { |
| // Ctrl & MultiSelection |
| ToggleSelection( pEntry ); |
| SetCursor( pEntry ); |
| } |
| else if( nFlags & F_DOWN_DESELECT ) |
| { |
| DeselectAllBut( pEntry ); |
| SetCursor( pEntry ); |
| pView->Select( pEntry, sal_True ); |
| } |
| } |
| |
| nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); |
| if( nFlags & F_START_EDITTIMER_IN_MOUSEUP ) |
| { |
| StartEditTimer(); |
| nFlags &= ~F_START_EDITTIMER_IN_MOUSEUP; |
| } |
| } |
| |
| void SvImpIconView::MouseMove( const MouseEvent& rMEvt ) |
| { |
| if( nFlags & F_RUBBERING ) |
| { |
| const Point& rPosPixel = rMEvt.GetPosPixel(); |
| if( !aMouseMoveTimer.IsActive() ) |
| { |
| aMouseMoveEvent = rMEvt; |
| aMouseMoveTimer.Start(); |
| // ausserhalb des Fensters liegende Move-Events muessen |
| // vom Timer kommen, damit die Scrollgeschwindigkeit |
| // unabhaengig von Mausbewegungen ist. |
| if( rPosPixel.X() < 0 || rPosPixel.Y() < 0 ) |
| return; |
| const Size& rSize = pView->GetOutputSizePixel(); |
| if( rPosPixel.X() > rSize.Width() || rPosPixel.Y() > rSize.Height()) |
| return; |
| } |
| |
| if( &rMEvt != &aMouseMoveEvent ) |
| aMouseMoveEvent = rMEvt; |
| |
| long nScrollDX, nScrollDY; |
| |
| CalcScrollOffsets(rMEvt.GetPosPixel(),nScrollDX,nScrollDY,sal_False ); |
| sal_Bool bSelRectHidden = sal_False; |
| if( nScrollDX || nScrollDY ) |
| { |
| HideSelectionRect(); |
| bSelRectHidden = sal_True; |
| pView->Scroll( nScrollDX, nScrollDY ); |
| } |
| Point aDocPos( rMEvt.GetPosPixel() ); |
| aDocPos = pView->PixelToLogic( aDocPos ); |
| Rectangle aRect( aCurSelectionRect.TopLeft(), aDocPos ); |
| if( aRect != aCurSelectionRect ) |
| { |
| HideSelectionRect(); |
| bSelRectHidden = sal_True; |
| sal_Bool bAdd = (nFlags & F_ADD_MODE) ? sal_True : sal_False; |
| SelectRect( aRect, bAdd, &aSelectedRectList ); |
| } |
| if( bSelRectHidden ) |
| DrawSelectionRect( aRect ); |
| } |
| } |
| |
| sal_Bool SvImpIconView::KeyInput( const KeyEvent& rKEvt ) |
| { |
| StopEditTimer(); |
| sal_Bool bKeyUsed = sal_True; |
| sal_Bool bMod1 = rKEvt.GetKeyCode().IsMod1(); |
| sal_Bool bInAddMode = (sal_Bool)((nFlags & F_ADD_MODE) != 0); |
| int bDeselAll = (pView->GetSelectionMode() != SINGLE_SELECTION) && |
| !bInAddMode; |
| SvLBoxEntry* pNewCursor; |
| sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
| switch( nCode ) |
| { |
| case KEY_UP: |
| if( pCursor ) |
| { |
| MakeVisible( pCursor ); |
| pNewCursor = pImpCursor->GoUpDown(pCursor,sal_False); |
| if( pNewCursor ) |
| { |
| if( bDeselAll ) |
| pView->SelectAll( sal_False ); |
| ShowCursor( sal_False ); |
| MakeVisible( pNewCursor ); |
| SetCursor( pNewCursor ); |
| if( !bInAddMode ) |
| pView->Select( pCursor, sal_True ); |
| } |
| else |
| { |
| Rectangle aRect( GetBoundingRect( pCursor ) ); |
| if( aRect.Top()) |
| { |
| aRect.Bottom() -= aRect.Top(); |
| aRect.Top() = 0; |
| MakeVisible( aRect ); |
| } |
| } |
| } |
| break; |
| |
| case KEY_DOWN: |
| if( pCursor ) |
| { |
| pNewCursor=pImpCursor->GoUpDown( pCursor,sal_True ); |
| if( pNewCursor ) |
| { |
| MakeVisible( pCursor ); |
| if( bDeselAll ) |
| pView->SelectAll( sal_False ); |
| ShowCursor( sal_False ); |
| MakeVisible( pNewCursor ); |
| SetCursor( pNewCursor ); |
| if( !bInAddMode ) |
| pView->Select( pCursor, sal_True ); |
| } |
| } |
| break; |
| |
| case KEY_RIGHT: |
| if( pCursor ) |
| { |
| pNewCursor=pImpCursor->GoLeftRight(pCursor,sal_True ); |
| if( pNewCursor ) |
| { |
| MakeVisible( pCursor ); |
| if( bDeselAll ) |
| pView->SelectAll( sal_False ); |
| ShowCursor( sal_False ); |
| MakeVisible( pNewCursor ); |
| SetCursor( pNewCursor ); |
| if( !bInAddMode ) |
| pView->Select( pCursor, sal_True ); |
| } |
| } |
| break; |
| |
| case KEY_LEFT: |
| if( pCursor ) |
| { |
| MakeVisible( pCursor ); |
| pNewCursor = pImpCursor->GoLeftRight(pCursor,sal_False ); |
| if( pNewCursor ) |
| { |
| if( bDeselAll ) |
| pView->SelectAll( sal_False ); |
| ShowCursor( sal_False ); |
| MakeVisible( pNewCursor ); |
| SetCursor( pNewCursor ); |
| if( !bInAddMode ) |
| pView->Select( pCursor, sal_True ); |
| } |
| else |
| { |
| Rectangle aRect( GetBoundingRect(pCursor)); |
| if( aRect.Left() ) |
| { |
| aRect.Right() -= aRect.Left(); |
| aRect.Left() = 0; |
| MakeVisible( aRect ); |
| } |
| } |
| } |
| break; |
| |
| case KEY_ESCAPE: |
| if( nFlags & F_RUBBERING ) |
| { |
| HideSelectionRect(); |
| pView->SelectAll( sal_False ); |
| nFlags &= ~F_RUBBERING; |
| } |
| break; |
| |
| case KEY_F8: |
| if( rKEvt.GetKeyCode().IsShift() ) |
| { |
| if( nFlags & F_ADD_MODE ) |
| nFlags &= (~F_ADD_MODE); |
| else |
| nFlags |= F_ADD_MODE; |
| } |
| break; |
| |
| #ifdef OS2 |
| case KEY_F9: |
| if( rKEvt.GetKeyCode().IsShift() ) |
| { |
| if( pCursor && pView->IsInplaceEditingEnabled() ) |
| pView->EditEntry( pCursor ); |
| } |
| break; |
| #endif |
| |
| case KEY_SPACE: |
| if( pCursor ) |
| { |
| ToggleSelection( pCursor ); |
| } |
| break; |
| |
| |
| case KEY_PAGEDOWN: |
| break; |
| case KEY_PAGEUP: |
| break; |
| |
| case KEY_ADD: |
| case KEY_DIVIDE : |
| if( bMod1 ) |
| pView->SelectAll( sal_True ); |
| break; |
| |
| case KEY_SUBTRACT: |
| case KEY_COMMA : |
| if( bMod1 ) |
| pView->SelectAll( sal_False ); |
| break; |
| |
| case KEY_RETURN: |
| if( bMod1 ) |
| { |
| if( pCursor && pView->IsInplaceEditingEnabled() ) |
| pView->EditEntry( pCursor ); |
| } |
| break; |
| |
| default: |
| bKeyUsed = sal_False; |
| |
| } |
| return bKeyUsed; |
| } |
| |
| |
| void SvImpIconView::PositionScrollBars( long nRealWidth, long nRealHeight ) |
| { |
| // hor scrollbar |
| Point aPos( 0, nRealHeight ); |
| aPos.Y() -= nHorSBarHeight; |
| |
| #ifdef OS2 |
| aPos.Y()++; |
| #endif |
| if( aHorSBar.GetPosPixel() != aPos ) |
| aHorSBar.SetPosPixel( aPos ); |
| |
| // ver scrollbar |
| aPos.X() = nRealWidth; aPos.Y() = 0; |
| aPos.X() -= nVerSBarWidth; |
| |
| #if defined(WNT) |
| aPos.X()++; |
| aPos.Y()--; |
| #endif |
| |
| #ifdef OS2 |
| aPos.Y()--; |
| aPos.X()++; |
| #endif |
| |
| if( aVerSBar.GetPosPixel() != aPos ) |
| aVerSBar.SetPosPixel( aPos ); |
| } |
| |
| |
| |
| void SvImpIconView::AdjustScrollBars() |
| { |
| long nVirtHeight = aVirtOutputSize.Height(); |
| long nVirtWidth = aVirtOutputSize.Width(); |
| |
| Size aOSize( pView->Control::GetOutputSizePixel() ); |
| long nRealHeight = aOSize.Height(); |
| long nRealWidth = aOSize.Width(); |
| |
| PositionScrollBars( nRealWidth, nRealHeight ); |
| |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin() ); |
| |
| long nVisibleWidth; |
| if( nRealWidth > nVirtWidth ) |
| nVisibleWidth = nVirtWidth + aOrigin.X(); |
| else |
| nVisibleWidth = nRealWidth; |
| |
| long nVisibleHeight; |
| if( nRealHeight > nVirtHeight ) |
| nVisibleHeight = nVirtHeight + aOrigin.Y(); |
| else |
| nVisibleHeight = nRealHeight; |
| |
| bool bVerSBar = (pView->GetStyle() & WB_VSCROLL) ? true : false; |
| bool bHorSBar = (pView->GetStyle() & WB_HSCROLL) ? true : false; |
| |
| sal_uInt16 nResult = 0; |
| if( nVirtHeight ) |
| { |
| // activate ver scrollbar ? |
| if( bVerSBar || ( nVirtHeight > nVisibleHeight) ) |
| { |
| nResult = 0x0001; |
| nRealWidth -= nVerSBarWidth; |
| |
| if( nRealWidth > nVirtWidth ) |
| nVisibleWidth = nVirtWidth + aOrigin.X(); |
| else |
| nVisibleWidth = nRealWidth; |
| |
| nFlags |= F_HOR_SBARSIZE_WITH_VBAR; |
| } |
| // activate hor scrollbar ? |
| if( bHorSBar || (nVirtWidth > nVisibleWidth) ) |
| { |
| nResult |= 0x0002; |
| nRealHeight -= nHorSBarHeight; |
| |
| if( nRealHeight > nVirtHeight ) |
| nVisibleHeight = nVirtHeight + aOrigin.Y(); |
| else |
| nVisibleHeight = nRealHeight; |
| |
| // brauchen wir jetzt doch eine senkrechte Scrollbar ? |
| if( !(nResult & 0x0001) && // nur wenn nicht schon da |
| ( (nVirtHeight > nVisibleHeight) || bVerSBar) ) |
| { |
| nResult = 3; // both are active |
| nRealWidth -= nVerSBarWidth; |
| |
| if( nRealWidth > nVirtWidth ) |
| nVisibleWidth = nVirtWidth + aOrigin.X(); |
| else |
| nVisibleWidth = nRealWidth; |
| |
| nFlags |= F_VER_SBARSIZE_WITH_HBAR; |
| } |
| } |
| } |
| |
| // size ver scrollbar |
| long nThumb = aVerSBar.GetThumbPos(); |
| Size aSize( nVerSBarWidth, nRealHeight ); |
| #if defined(WNT) |
| aSize.Height() += 2; |
| #endif |
| #ifdef OS2 |
| aSize.Height() += 3; |
| #endif |
| if( aSize != aVerSBar.GetSizePixel() ) |
| aVerSBar.SetSizePixel( aSize ); |
| aVerSBar.SetVisibleSize( nVisibleHeight ); |
| aVerSBar.SetPageSize( (nVisibleHeight*75)/100 ); |
| if( nResult & 0x0001 ) |
| { |
| aVerSBar.SetThumbPos( nThumb ); |
| aVerSBar.Show(); |
| } |
| else |
| { |
| aVerSBar.SetThumbPos( 0 ); |
| aVerSBar.Hide(); |
| } |
| |
| // size hor scrollbar |
| nThumb = aHorSBar.GetThumbPos(); |
| aSize.Width() = nRealWidth; |
| aSize.Height() = nHorSBarHeight; |
| #if defined(WNT) |
| aSize.Width()++; |
| #endif |
| #ifdef OS2 |
| aSize.Width() += 3; |
| if( nResult & 0x0001 ) // vertikale Scrollbar ? |
| aSize.Width()--; |
| #endif |
| #if defined(WNT) |
| if( nResult & 0x0001 ) // vertikale Scrollbar ? |
| { |
| aSize.Width()++; |
| nRealWidth++; |
| } |
| #endif |
| if( aSize != aHorSBar.GetSizePixel() ) |
| aHorSBar.SetSizePixel( aSize ); |
| aHorSBar.SetVisibleSize( nVisibleWidth ); //nRealWidth ); |
| aHorSBar.SetPageSize( (nVisibleWidth*75)/100 ); |
| if( nResult & 0x0002 ) |
| { |
| aHorSBar.SetThumbPos( nThumb ); |
| aHorSBar.Show(); |
| } |
| else |
| { |
| aHorSBar.SetThumbPos( 0 ); |
| aHorSBar.Hide(); |
| } |
| |
| #ifdef OS2 |
| nRealWidth++; |
| #endif |
| aOutputSize.Width() = nRealWidth; |
| #if defined(WNT) |
| if( nResult & 0x0002 ) // hor scrollbar ? |
| nRealHeight++; // weil unterer Rand geclippt wird |
| #endif |
| #ifdef OS2 |
| if( nResult & 0x0002 ) // hor scrollbar ? |
| nRealHeight++; |
| #endif |
| aOutputSize.Height() = nRealHeight; |
| } |
| |
| void __EXPORT SvImpIconView::Resize() |
| { |
| StopEditTimer(); |
| Rectangle aRect; |
| if( GetResizeRect(aRect) ) |
| pView->Invalidate( aRect ); |
| aOutputSize = pView->GetOutputSizePixel(); |
| pImpCursor->Clear(); |
| |
| #if 1 |
| const Size& rSize = pView->Control::GetOutputSizePixel(); |
| PositionScrollBars( rSize.Width(), rSize.Height() ); |
| // Die ScrollBars werden asynchron ein/ausgeblendet, damit abgeleitete |
| // Klassen im Resize ein Arrange durchfuehren koennen, ohne dass |
| // die ScrollBars aufblitzen (SfxExplorerIconView!) |
| nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpIconView,UserEventHdl),0); |
| #else |
| AdjustScrollBars(); |
| if( GetResizeRect(aRect) ) |
| PaintResizeRect( aRect ); |
| #endif |
| } |
| |
| sal_Bool SvImpIconView::CheckHorScrollBar() |
| { |
| if( !pZOrderList || !aHorSBar.IsVisible() ) |
| return sal_False; |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin() ); |
| if(!(pView->GetStyle() & WB_HSCROLL) && !aOrigin.X() ) |
| { |
| long nWidth = aOutputSize.Width(); |
| sal_uInt16 nCount = pZOrderList->Count(); |
| long nMostRight = 0; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur); |
| long nRight = GetBoundingRect(pEntry).Right(); |
| if( nRight > nWidth ) |
| return sal_False; |
| if( nRight > nMostRight ) |
| nMostRight = nRight; |
| } |
| aHorSBar.Hide(); |
| aOutputSize.Height() += nHorSBarHeight; |
| aVirtOutputSize.Width() = nMostRight; |
| aHorSBar.SetThumbPos( 0 ); |
| Range aRange; |
| aRange.Max() = nMostRight - 1; |
| aHorSBar.SetRange( aRange ); |
| if( aVerSBar.IsVisible() ) |
| { |
| Size aSize( aVerSBar.GetSizePixel()); |
| aSize.Height() += nHorSBarHeight; |
| aVerSBar.SetSizePixel( aSize ); |
| } |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| sal_Bool SvImpIconView::CheckVerScrollBar() |
| { |
| if( !pZOrderList || !aVerSBar.IsVisible() ) |
| return sal_False; |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin() ); |
| if(!(pView->GetStyle() & WB_VSCROLL) && !aOrigin.Y() ) |
| { |
| long nDeepest = 0; |
| long nHeight = aOutputSize.Height(); |
| sal_uInt16 nCount = pZOrderList->Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pZOrderList->operator[](nCur); |
| long nBottom = GetBoundingRect(pEntry).Bottom(); |
| if( nBottom > nHeight ) |
| return sal_False; |
| if( nBottom > nDeepest ) |
| nDeepest = nBottom; |
| } |
| aVerSBar.Hide(); |
| aOutputSize.Width() += nVerSBarWidth; |
| aVirtOutputSize.Height() = nDeepest; |
| aVerSBar.SetThumbPos( 0 ); |
| Range aRange; |
| aRange.Max() = nDeepest - 1; |
| aVerSBar.SetRange( aRange ); |
| if( aHorSBar.IsVisible() ) |
| { |
| Size aSize( aHorSBar.GetSizePixel()); |
| aSize.Width() += nVerSBarWidth; |
| aHorSBar.SetSizePixel( aSize ); |
| } |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| |
| // blendet Scrollbars aus, wenn sie nicht mehr benoetigt werden |
| void SvImpIconView::CheckScrollBars() |
| { |
| CheckVerScrollBar(); |
| if( CheckHorScrollBar() ) |
| CheckVerScrollBar(); |
| } |
| |
| |
| void __EXPORT SvImpIconView::GetFocus() |
| { |
| if( pCursor ) |
| { |
| pView->SetEntryFocus( pCursor, sal_True ); |
| ShowCursor( sal_True ); |
| } |
| } |
| |
| void __EXPORT SvImpIconView::LoseFocus() |
| { |
| StopEditTimer(); |
| if( pCursor ) |
| pView->SetEntryFocus( pCursor,sal_False ); |
| ShowCursor( sal_False ); |
| } |
| |
| void SvImpIconView::UpdateAll() |
| { |
| AdjustScrollBars(); |
| pImpCursor->Clear(); |
| pView->Invalidate(); |
| } |
| |
| void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData ) |
| { |
| Point aPos( GetEntryPosition( pEntry ) ); |
| PaintEntry( pEntry, aPos, pViewData ); |
| } |
| |
| void SvImpIconView::PaintEmphasis( const Rectangle& rRect, sal_Bool bSelected, |
| sal_Bool bCursored, OutputDevice* pOut ) |
| { |
| // HACK fuer D&D |
| if( nFlags & F_NO_EMPHASIS ) |
| return; |
| |
| if( !pOut ) |
| pOut = pView; |
| |
| // Selektion painten |
| Color aOldFillColor = pOut->GetFillColor(); |
| Color aOldLineColor = pOut->GetLineColor(); |
| Color aNewColor; |
| const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings(); |
| if( bSelected ) |
| { |
| aNewColor = rStyleSettings.GetHighlightColor(); |
| } |
| else |
| { |
| #ifndef OS2 |
| aNewColor =rStyleSettings.GetFieldColor(); |
| #else |
| aNewColor = pOut->GetBackground().GetColor(); |
| #endif |
| } |
| |
| if( bCursored ) |
| { |
| pOut->SetLineColor( Color( COL_BLACK ) ); |
| } |
| pOut->SetFillColor( aNewColor ); |
| pOut->DrawRect( rRect ); |
| pOut->SetFillColor( aOldFillColor ); |
| pOut->SetLineColor( aOldLineColor ); |
| } |
| |
| void SvImpIconView::PaintItem( const Rectangle& rRect, |
| SvLBoxItem* pItem, SvLBoxEntry* pEntry, sal_uInt16 nPaintFlags, |
| OutputDevice* pOut ) |
| { |
| if( nViewMode == VIEWMODE_ICON && pItem->IsA() == SV_ITEM_ID_LBOXSTRING ) |
| { |
| const String& rStr = ((SvLBoxString*)pItem)->GetText(); |
| DrawText( pOut, rRect, rStr, DRAWTEXT_FLAGS ); |
| } |
| else |
| { |
| Point aPos( rRect.TopLeft() ); |
| const Size& rSize = GetItemSize( pView, pEntry, pItem ); |
| if( nPaintFlags & PAINTFLAG_HOR_CENTERED ) |
| aPos.X() += (rRect.GetWidth() - rSize.Width() ) / 2; |
| if( nPaintFlags & PAINTFLAG_VER_CENTERED ) |
| aPos.Y() += (rRect.GetHeight() - rSize.Height() ) / 2; |
| pItem->Paint( aPos, *(SvLBox*)pOut, 0, pEntry ); |
| } |
| } |
| |
| void SvImpIconView::PaintEntry( SvLBoxEntry* pEntry, const Point& rPos, |
| SvIcnVwDataEntry* pViewData, OutputDevice* pOut ) |
| { |
| if( !pView->IsUpdateMode() ) |
| return; |
| |
| if( !pOut ) |
| pOut = pView; |
| |
| SvLBoxContextBmp* pBmpItem; |
| |
| pView->PreparePaint( pEntry ); |
| |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| |
| SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| |
| sal_Bool bSelected = pViewData->IsSelected(); |
| sal_Bool bCursored = pViewData->IsCursored(); |
| |
| Font aTempFont( pOut->GetFont() ); |
| // waehrend D&D nicht die Fontfarbe wechseln, da sonst auch die |
| // Emphasis gezeichnet werden muss! (weisser Adler auf weissem Grund) |
| if( bSelected && !(nFlags & F_NO_EMPHASIS) ) |
| { |
| const StyleSettings& rStyleSettings = pOut->GetSettings().GetStyleSettings(); |
| Font aNewFont( aTempFont ); |
| aNewFont.SetColor( rStyleSettings.GetHighlightTextColor() ); |
| pOut->SetFont( aNewFont ); |
| } |
| Rectangle aTextRect( CalcTextRect(pEntry,pStringItem,&rPos,sal_False,pViewData)); |
| Rectangle aBmpRect( CalcBmpRect(pEntry, &rPos, pViewData ) ); |
| |
| switch( nViewMode ) |
| { |
| case VIEWMODE_ICON: |
| pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); |
| PaintEmphasis( aBmpRect, bSelected, bCursored, pOut ); |
| PaintItem( aBmpRect, pBmpItem, pEntry, |
| PAINTFLAG_HOR_CENTERED | PAINTFLAG_VER_CENTERED, pOut ); |
| PaintEmphasis( aTextRect, bSelected, sal_False, pOut ); |
| PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_HOR_CENTERED, pOut ); |
| break; |
| |
| case VIEWMODE_NAME: |
| pBmpItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); |
| PaintEmphasis( aBmpRect, bSelected, bCursored, pOut ); |
| PaintItem( aBmpRect, pBmpItem, pEntry, PAINTFLAG_VER_CENTERED, pOut ); |
| PaintEmphasis( aTextRect, bSelected, sal_False, pOut ); |
| PaintItem( aTextRect, pStringItem, pEntry,PAINTFLAG_VER_CENTERED, pOut ); |
| break; |
| |
| case VIEWMODE_TEXT: |
| PaintEmphasis( aTextRect, bSelected, bCursored, pOut ); |
| PaintItem( aTextRect, pStringItem, pEntry, PAINTFLAG_VER_CENTERED, pOut ); |
| break; |
| } |
| pOut->SetFont( aTempFont ); |
| } |
| |
| void SvImpIconView::SetEntryPosition( SvLBoxEntry* pEntry, const Point& rPos, |
| sal_Bool bAdjustAtGrid, sal_Bool bCheckScrollBars ) |
| { |
| if( pModel->GetParent(pEntry) == pCurParent ) |
| { |
| ShowCursor( sal_False ); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| Rectangle aBoundRect( GetBoundingRect( pEntry, pViewData )); |
| pView->Invalidate( aBoundRect ); |
| ToTop( pEntry ); |
| if( rPos != aBoundRect.TopLeft() ) |
| { |
| Point aGridOffs = pViewData->aGridRect.TopLeft() - |
| pViewData->aRect.TopLeft(); |
| pImpCursor->Clear(); |
| nFlags &= ~F_GRID_INSERT; |
| aBoundRect.SetPos( rPos ); |
| pViewData->aRect = aBoundRect; |
| pViewData->aGridRect.SetPos( rPos + aGridOffs ); |
| AdjustVirtSize( aBoundRect ); |
| } |
| //HACK(Billigloesung, die noch verbessert werden muss) |
| if( bAdjustAtGrid ) |
| { |
| AdjustAtGrid( pEntry ); |
| ToTop( pEntry ); |
| } |
| if( bCheckScrollBars && pView->IsUpdateMode() ) |
| CheckScrollBars(); |
| |
| PaintEntry( pEntry, pViewData ); |
| ShowCursor( sal_True ); |
| } |
| } |
| |
| void SvImpIconView::ViewDataInitialized( SvLBoxEntry*) |
| { |
| } |
| |
| void SvImpIconView::ModelHasEntryInvalidated( SvListEntry* pEntry ) |
| { |
| if( pEntry == pCursor ) |
| ShowCursor( sal_False ); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| pView->Invalidate( pViewData->aRect ); |
| |
| if( nFlags & F_GRIDMODE ) |
| Center( (SvLBoxEntry*)pEntry, pViewData ); |
| else |
| pViewData->aRect.SetSize( CalcBoundingSize( |
| (SvLBoxEntry*)pEntry, pViewData ) ); |
| |
| ViewDataInitialized( (SvLBoxEntry*)pEntry ); |
| pView->Invalidate( pViewData->aRect ); |
| if( pEntry == pCursor ) |
| ShowCursor( sal_True ); |
| } |
| |
| |
| void SvImpIconView::InvalidateEntry( SvLBoxEntry* pEntry ) |
| { |
| const Rectangle& rRect = GetBoundingRect( pEntry ); |
| pView->Invalidate( rRect ); |
| } |
| |
| void SvImpIconView::SetNoSelection() |
| { |
| } |
| |
| void SvImpIconView::SetDragDropMode( DragDropMode ) |
| { |
| } |
| |
| void SvImpIconView::SetSelectionMode( SelectionMode ) |
| { |
| } |
| |
| sal_Bool SvImpIconView::IsEntryInView( SvLBoxEntry* ) |
| { |
| return sal_False; |
| } |
| |
| SvLBoxEntry* SvImpIconView::GetDropTarget( const Point& rPos ) |
| { |
| Point aDocPos( rPos ); |
| CalcDocPos( aDocPos ); |
| SvLBoxEntry* pTarget = GetEntry( aDocPos ); |
| if( !pTarget || !pTarget->HasChilds() ) |
| pTarget = pCurParent; |
| return pTarget; |
| } |
| |
| SvLBoxEntry* SvImpIconView::GetEntry( const Point& rDocPos ) |
| { |
| CheckBoundingRects(); |
| SvLBoxEntry* pTarget = 0; |
| // Z-Order-Liste vom Ende her absuchen |
| sal_uInt16 nCount = pZOrderList->Count(); |
| while( nCount ) |
| { |
| nCount--; |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCount)); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( pViewData->aRect.IsInside( rDocPos ) ) |
| { |
| pTarget = pEntry; |
| break; |
| } |
| } |
| return pTarget; |
| } |
| |
| SvLBoxEntry* SvImpIconView::GetNextEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry ) |
| { |
| CheckBoundingRects(); |
| SvLBoxEntry* pTarget = 0; |
| sal_uInt16 nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); |
| if( nStartPos != USHRT_MAX ) |
| { |
| sal_uInt16 nCount = pZOrderList->Count(); |
| for( sal_uInt16 nCur = nStartPos+1; nCur < nCount; nCur++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nCur)); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( pViewData->aRect.IsInside( rDocPos ) ) |
| { |
| pTarget = pEntry; |
| break; |
| } |
| } |
| } |
| return pTarget; |
| } |
| |
| SvLBoxEntry* SvImpIconView::GetPrevEntry( const Point& rDocPos, SvLBoxEntry* pCurEntry ) |
| { |
| CheckBoundingRects(); |
| SvLBoxEntry* pTarget = 0; |
| sal_uInt16 nStartPos = pZOrderList->GetPos( (void*)pCurEntry ); |
| if( nStartPos != USHRT_MAX && nStartPos != 0 ) |
| { |
| nStartPos--; |
| do |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nStartPos)); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( pViewData->aRect.IsInside( rDocPos ) ) |
| { |
| pTarget = pEntry; |
| break; |
| } |
| } while( nStartPos > 0 ); |
| } |
| return pTarget; |
| } |
| |
| |
| Point SvImpIconView::GetEntryPosition( SvLBoxEntry* pEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| DBG_ASSERT(pViewData,"Entry not in model"); |
| return pViewData->aRect.TopLeft(); |
| } |
| |
| const Rectangle& SvImpIconView::GetBoundingRect( SvLBoxEntry* pEntry, SvIcnVwDataEntry* pViewData ) |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| DBG_ASSERT(pViewData,"Entry not in model"); |
| if( !IsBoundingRectValid( pViewData->aRect )) |
| FindBoundingRect( pEntry, pViewData ); |
| return pViewData->aRect; |
| } |
| |
| void SvImpIconView::SetSpaceBetweenEntries( long nHor, long nVer ) |
| { |
| nHorDist = nHor; |
| nVerDist = nVer; |
| } |
| |
| Rectangle SvImpIconView::CalcBmpRect( SvLBoxEntry* pEntry, const Point* pPos, |
| SvIcnVwDataEntry* pViewData ) |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| |
| Rectangle aBound = GetBoundingRect( pEntry, pViewData ); |
| if( pPos ) |
| aBound.SetPos( *pPos ); |
| Point aPos( aBound.TopLeft() ); |
| |
| switch( nViewMode ) |
| { |
| case VIEWMODE_ICON: |
| { |
| aPos.X() += ( aBound.GetWidth() - nMaxBmpWidth ) / 2; |
| Size aSize( nMaxBmpWidth, nMaxBmpHeight ); |
| // das Bitmap-Rechteck soll nicht das TextRect beruehren |
| aSize.Height() -= 3; |
| return Rectangle( aPos, aSize ); |
| } |
| |
| case VIEWMODE_NAME: |
| return Rectangle( aPos, |
| Size( nMaxBmpWidth, aBound.GetHeight() )); |
| |
| case VIEWMODE_TEXT: |
| return Rectangle( aPos, aBound.GetSize() ); |
| |
| default: |
| { |
| Rectangle aRect; |
| return aRect; |
| } |
| } |
| } |
| |
| Rectangle SvImpIconView::CalcTextRect( SvLBoxEntry* pEntry, |
| SvLBoxString* pItem, const Point* pPos, sal_Bool bForInplaceEdit, |
| SvIcnVwDataEntry* pViewData ) |
| { |
| long nBmpHeight, nBmpWidth; |
| |
| if( !pItem ) |
| pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| |
| Size aTextSize( GetItemSize( pView, pEntry, pItem, pViewData )); |
| aTextSize.Width() += 2*LROFFS_TEXT; |
| |
| Size aContextBmpSize(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry)); |
| Rectangle aBound = GetBoundingRect( pEntry, pViewData ); |
| if( pPos ) |
| aBound.SetPos( *pPos ); |
| Point aPos( aBound.TopLeft() ); |
| |
| switch( nViewMode ) |
| { |
| case VIEWMODE_ICON: |
| nBmpHeight = aContextBmpSize.Height(); |
| if( nBmpHeight < nMaxBmpHeight ) |
| nBmpHeight = nMaxBmpHeight; |
| aPos.Y() += nBmpHeight; |
| |
| // beim Inplace-Editieren, spendieren wir ein bisschen mehr Platz |
| if( bForInplaceEdit ) |
| { |
| // 20% rauf |
| long nMinWidth = (( (aContextBmpSize.Width()*10) / 100 ) * 2 ) + |
| aContextBmpSize.Width(); |
| if( nMinWidth > aBound.GetWidth() ) |
| nMinWidth = aBound.GetWidth(); |
| |
| if( aTextSize.Width() < nMinWidth ) |
| aTextSize.Width() = nMinWidth; |
| |
| // beim Inplace-Ed. darfs auch untere Eintraege ueberlappen |
| Rectangle aMaxGridTextRect = CalcMaxTextRect(pEntry, pViewData); |
| Size aOptSize = aMaxGridTextRect.GetSize(); |
| if( aOptSize.Height() > aTextSize.Height() ) |
| aTextSize.Height() = aOptSize.Height(); |
| } |
| |
| |
| aPos.X() += ( aBound.GetWidth() - aTextSize.Width() ) / 2; |
| break; |
| |
| case VIEWMODE_NAME: |
| nBmpWidth = aContextBmpSize.Width(); |
| if( nBmpWidth < nMaxBmpWidth ) |
| nBmpWidth = nMaxBmpWidth; |
| aPos.X() += nBmpWidth; |
| // vertikal ausrichten |
| aPos.Y() += ( nBmpWidth - aTextSize.Height() ) / 2; |
| break; |
| } |
| |
| Rectangle aRect( aPos, aTextSize ); |
| // KNALLT BEIM D&D, WENN GECLIPPT WIRD (In DrawText von Thomas) |
| // ClipAtVirtOutRect( aRect ); |
| return aRect; |
| } |
| |
| |
| long SvImpIconView::CalcBoundingWidth( SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) const |
| { |
| DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps"); |
| DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text"); |
| long nStringWidth = GetItemSize( pView, pEntry, pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Width(); |
| nStringWidth += 2*LROFFS_TEXT; |
| long nBmpWidth = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Width(); |
| long nWidth = 0; |
| |
| switch( nViewMode ) |
| { |
| case VIEWMODE_ICON: |
| nWidth = Max( nStringWidth, nBmpWidth ); |
| nWidth = Max( nWidth, nMaxBmpWidth ); |
| break; |
| |
| case VIEWMODE_NAME: |
| nWidth = Max( nBmpWidth, nMaxBmpWidth ); |
| nWidth += NAMEVIEW_OFFS_BMP_STRING; // Abstand Bitmap String |
| nWidth += nStringWidth; |
| break; |
| |
| case VIEWMODE_TEXT: |
| nWidth = nStringWidth; |
| break; |
| } |
| return nWidth; |
| } |
| |
| long SvImpIconView::CalcBoundingHeight( SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) const |
| { |
| DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP),"No Bitmaps"); |
| DBG_ASSERT(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),"No Text"); |
| long nStringHeight = GetItemSize(pView,pEntry,pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING),pViewData).Height(); |
| long nBmpHeight = pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,pEntry).Height(); |
| long nHeight = 0; |
| |
| switch( nViewMode ) |
| { |
| case VIEWMODE_ICON: |
| nHeight = Max( nBmpHeight, nMaxBmpHeight ); |
| nHeight += ICONVIEW_OFFS_BMP_STRING; // Abstand Bitmap String |
| nHeight += nStringHeight; |
| break; |
| |
| case VIEWMODE_NAME: |
| nHeight = Max( nBmpHeight, nMaxBmpHeight ); |
| nHeight = Max( nHeight, nStringHeight ); |
| break; |
| |
| case VIEWMODE_TEXT: |
| nHeight = nStringHeight; |
| break; |
| } |
| if( nHeight > nMaxBoundHeight ) |
| { |
| ((SvImpIconView*)this)->nMaxBoundHeight = nHeight; |
| ((SvImpIconView*)this)->aHorSBar.SetLineSize( nHeight / 2 ); |
| ((SvImpIconView*)this)->aVerSBar.SetLineSize( nHeight / 2 ); |
| } |
| return nHeight; |
| } |
| |
| Size SvImpIconView::CalcBoundingSize( SvLBoxEntry* pEntry, |
| SvIcnVwDataEntry* pViewData ) const |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| return Size( CalcBoundingWidth(pEntry,pViewData), |
| CalcBoundingHeight(pEntry,pViewData) ); |
| } |
| |
| void SvImpIconView::RecalcAllBoundingRects() |
| { |
| nMaxBoundHeight = 0; |
| pZOrderList->Remove(0, pZOrderList->Count() ); |
| SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent ); |
| while( pEntry ) |
| { |
| FindBoundingRect( pEntry ); |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| bMustRecalcBoundingRects = sal_False; |
| AdjustScrollBars(); |
| } |
| |
| void SvImpIconView::RecalcAllBoundingRectsSmart() |
| { |
| nMaxBoundHeight = 0; |
| pZOrderList->Remove(0, pZOrderList->Count() ); |
| SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent ); |
| while( pEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( IsBoundingRectValid( pViewData->aRect )) |
| { |
| Size aBoundSize( pViewData->aRect.GetSize() ); |
| if( aBoundSize.Height() > nMaxBoundHeight ) |
| nMaxBoundHeight = aBoundSize.Height(); |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| } |
| else |
| { |
| FindBoundingRect( pEntry, pViewData ); |
| } |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| AdjustScrollBars(); |
| } |
| |
| void SvImpIconView::UpdateBoundingRects() |
| { |
| SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent ); |
| while( pEntry ) |
| { |
| GetBoundingRect( pEntry ); |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| } |
| |
| void SvImpIconView::FindBoundingRect( SvLBoxEntry* pEntry, |
| SvIcnVwDataEntry* pViewData ) |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| |
| Size aSize( CalcBoundingSize( pEntry, pViewData ) ); |
| Point aPos; |
| |
| DBG_ASSERT(!pViewData->IsEntryPosLocked(),"Locked entry pos in FindBoundingRect"); |
| // damits in der IconView nicht drunter & drueber geht |
| if( pViewData->IsEntryPosLocked() && IsBoundingRectValid(pViewData->aRect) ) |
| { |
| AdjustVirtSize( pViewData->aRect ); |
| return; |
| } |
| |
| aPos = FindNextEntryPos( aSize ); |
| |
| if( nFlags & F_GRIDMODE ) |
| { |
| Rectangle aGridRect( aPos, Size(nGridDX, nGridDY) ); |
| pViewData->aGridRect = aGridRect; |
| Center( pEntry, pViewData ); |
| AdjustVirtSize( pViewData->aRect ); |
| pImpCursor->SetGridUsed( pViewData->aRect ); |
| } |
| else |
| { |
| pViewData->aRect = Rectangle( aPos, aSize ); |
| AdjustVirtSize( pViewData->aRect ); |
| } |
| } |
| |
| |
| void SvImpIconView::SetCursor( SvLBoxEntry* pEntry ) |
| { |
| if( pEntry == pCursor ) |
| return; |
| |
| ShowCursor( sal_False ); |
| if( pCursor ) |
| { |
| pView->SetEntryFocus( pCursor, sal_False ); |
| if( pView->GetSelectionMode() == SINGLE_SELECTION ) |
| pView->Select( pCursor, sal_False ); |
| } |
| pCursor = pEntry; |
| ToTop( pCursor ); |
| if( pCursor ) |
| { |
| pView->SetEntryFocus(pCursor, sal_True ); |
| if( pView->GetSelectionMode() == SINGLE_SELECTION ) |
| pView->Select( pCursor, sal_True ); |
| ShowCursor( sal_True ); |
| } |
| } |
| |
| |
| void SvImpIconView::ShowCursor( sal_Bool bShow ) |
| { |
| if( !pCursor || !bShow || !pView->HasFocus() ) |
| { |
| pView->HideFocus(); |
| return; |
| } |
| Rectangle aRect ( CalcFocusRect( pCursor ) ); |
| pView->ShowFocus( aRect ); |
| } |
| |
| |
| void SvImpIconView::HideDDIcon() |
| { |
| pView->Update(); |
| ImpHideDDIcon(); |
| pDDBufDev = pDDDev; |
| pDDDev = 0; |
| } |
| |
| void SvImpIconView::ImpHideDDIcon() |
| { |
| if( pDDDev ) |
| { |
| Size aSize( pDDDev->GetOutputSizePixel() ); |
| // pView restaurieren |
| pView->DrawOutDev( aDDLastRectPos, aSize, Point(), aSize, *pDDDev ); |
| } |
| } |
| |
| |
| void SvImpIconView::ShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix ) |
| { |
| pView->Update(); |
| if( pRefEntry != pDDRefEntry ) |
| { |
| DELETEZ(pDDDev); |
| DELETEZ(pDDBufDev); |
| } |
| sal_Bool bSelected = pView->SvListView::Select( pRefEntry, sal_False ); |
| if( !pDDDev ) |
| { |
| if( pDDBufDev ) |
| { |
| // nicht bei jedem Move ein Device anlegen, da dies besonders |
| // auf Remote-Clients zu langsam ist |
| pDDDev = pDDBufDev; |
| pDDBufDev = 0; |
| } |
| else |
| { |
| pDDDev = new VirtualDevice( *pView ); |
| pDDDev->SetFont( pView->GetFont() ); |
| } |
| } |
| else |
| { |
| ImpHideDDIcon(); |
| } |
| const Rectangle& rRect = GetBoundingRect( pRefEntry ); |
| pDDDev->SetOutputSizePixel( rRect.GetSize() ); |
| |
| Point aPos( rPosPix ); |
| CalcDocPos( aPos ); |
| |
| Size aSize( pDDDev->GetOutputSizePixel() ); |
| pDDRefEntry = pRefEntry; |
| aDDLastEntryPos = aPos; |
| aDDLastRectPos = aPos; |
| |
| // Hintergrund sichern |
| pDDDev->DrawOutDev( Point(), aSize, aPos, aSize, *pView ); |
| // Icon in pView malen |
| nFlags |= F_NO_EMPHASIS; |
| PaintEntry( pRefEntry, aPos ); |
| nFlags &= ~F_NO_EMPHASIS; |
| if( bSelected ) |
| pView->SvListView::Select( pRefEntry, sal_True ); |
| } |
| |
| void SvImpIconView::HideShowDDIcon( SvLBoxEntry* pRefEntry, const Point& rPosPix ) |
| { |
| /* In Notfaellen folgenden flackernden Code aktivieren: |
| |
| HideDDIcon(); |
| ShowDDIcon( pRefEntry, rPosPix ); |
| return; |
| */ |
| if( !pDDDev ) |
| { |
| ShowDDIcon( pRefEntry, rPosPix ); |
| return; |
| } |
| |
| if( pRefEntry != pDDRefEntry ) |
| { |
| HideDDIcon(); |
| ShowDDIcon( pRefEntry, rPosPix ); |
| return; |
| } |
| |
| Point aEmptyPoint; |
| |
| Point aCurEntryPos( rPosPix ); |
| CalcDocPos( aCurEntryPos ); |
| |
| const Rectangle& rRect = GetBoundingRect( pRefEntry ); |
| Size aEntrySize( rRect.GetSize() ); |
| Rectangle aPrevEntryRect( aDDLastEntryPos, aEntrySize ); |
| Rectangle aCurEntryRect( aCurEntryPos, aEntrySize ); |
| |
| if( !aPrevEntryRect.IsOver( aCurEntryRect ) ) |
| { |
| HideDDIcon(); |
| ShowDDIcon( pRefEntry, rPosPix ); |
| return; |
| } |
| |
| // Ueberlappung des neuen und alten D&D-Pointers! |
| |
| Rectangle aFullRect( aPrevEntryRect.Union( aCurEntryRect ) ); |
| if( !pDDTempDev ) |
| { |
| pDDTempDev = new VirtualDevice( *pView ); |
| pDDTempDev->SetFont( pView->GetFont() ); |
| } |
| |
| Size aFullSize( aFullRect.GetSize() ); |
| Point aFullPos( aFullRect.TopLeft() ); |
| |
| pDDTempDev->SetOutputSizePixel( aFullSize ); |
| |
| // Hintergrund (mit dem alten D&D-Pointer!) sichern |
| pDDTempDev->DrawOutDev( aEmptyPoint, aFullSize, aFullPos, aFullSize, *pView ); |
| // den alten Buffer in den neuen Buffer pasten |
| aDDLastRectPos = aDDLastRectPos - aFullPos; |
| |
| pDDTempDev->DrawOutDev( |
| aDDLastRectPos, |
| pDDDev->GetOutputSizePixel(), |
| aEmptyPoint, |
| pDDDev->GetOutputSizePixel(), |
| *pDDDev ); |
| |
| // Swap |
| VirtualDevice* pTemp = pDDDev; |
| pDDDev = pDDTempDev; |
| pDDTempDev = pTemp; |
| |
| // in den restaurierten Hintergrund den neuen D&D-Pointer zeichnen |
| pDDTempDev->SetOutputSizePixel( pDDDev->GetOutputSizePixel() ); |
| pDDTempDev->DrawOutDev( |
| aEmptyPoint, aFullSize, aEmptyPoint, aFullSize, *pDDDev ); |
| Point aRelPos = aCurEntryPos - aFullPos; |
| nFlags |= F_NO_EMPHASIS; |
| PaintEntry( pRefEntry, aRelPos, 0, pDDTempDev ); |
| nFlags &= ~F_NO_EMPHASIS; |
| |
| aDDLastRectPos = aFullPos; |
| aDDLastEntryPos = aCurEntryPos; |
| |
| pView->DrawOutDev( |
| aDDLastRectPos, |
| pDDDev->GetOutputSizePixel(), |
| aEmptyPoint, |
| pDDDev->GetOutputSizePixel(), |
| *pDDTempDev ); |
| |
| sal_Bool bSelected = pView->SvListView::Select( pRefEntry, sal_False ); |
| if( bSelected ) |
| pView->SvListView::Select( pRefEntry, sal_True ); |
| } |
| |
| void SvImpIconView::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool ) |
| { |
| CheckBoundingRects(); |
| Rectangle aRect; |
| if( pEntry != pCurParent && |
| (pEntry->HasChilds() || pEntry->HasChildsOnDemand()) ) |
| aRect = CalcBmpRect( pEntry ); |
| else |
| { |
| aRect.SetSize( aOutputSize ); |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin()); |
| aOrigin *= -1; // in Doc-Koord wandeln |
| aRect.SetPos( aOrigin ); |
| aRect.Left()++; aRect.Top()++; |
| aRect.Right()--; aRect.Bottom()--; |
| } |
| ImpDrawXORRect( aRect ); |
| } |
| |
| sal_Bool SvImpIconView::NotifyMoving( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry, |
| SvLBoxEntry*& rpNewPar, sal_uLong& rNewChildPos ) |
| { |
| if( pTarget == pCurParent && pModel->GetParent(pEntry) == pCurParent ) |
| { |
| // D&D innerhalb einer Childlist |
| StopEditTimer(); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| Size aSize( pViewData->aRect.GetSize() ); |
| Point aNewPos = FindNextEntryPos( aSize ); |
| AdjustVirtSize( Rectangle( aNewPos, aSize ) ); |
| SetEntryPosition( pEntry, aNewPos, sal_False, sal_True ); |
| return sal_False; |
| } |
| return pView->SvLBox::NotifyMoving(pTarget,pEntry,rpNewPar,rNewChildPos); |
| } |
| |
| sal_Bool SvImpIconView::NotifyCopying( SvLBoxEntry* pTarget, SvLBoxEntry* pEntry, |
| SvLBoxEntry*& rpNewParent, sal_uLong& rNewChildPos ) |
| { |
| return pView->SvLBox::NotifyCopying(pTarget,pEntry,rpNewParent,rNewChildPos); |
| } |
| |
| void SvImpIconView::WriteDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo) |
| { |
| SvLBoxEntry* pCurEntry = GetCurEntry(); |
| Point aEntryPos; |
| if( pCurEntry ) |
| { |
| aEntryPos = rPos; |
| aEntryPos -= GetEntryPosition( pCurEntry ); |
| } |
| pInfo->nMouseRelX = aEntryPos.X(); |
| pInfo->nMouseRelY = aEntryPos.Y(); |
| } |
| |
| void SvImpIconView::ReadDragServerInfo( const Point& rPos, SvLBoxDDInfo* pInfo ) |
| { |
| Point aDropPos( rPos ); |
| aDropPos.X() -= pInfo->nMouseRelX; |
| aDropPos.Y() -= pInfo->nMouseRelY; |
| SetNextEntryPos( aDropPos ); |
| } |
| |
| void SvImpIconView::InvalidateBoundingRect( SvLBoxEntry* pEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| InvalidateBoundingRect( pViewData->aRect ); |
| } |
| |
| void SvImpIconView::PrepareCommandEvent( const Point& rPt ) |
| { |
| aMouseMoveTimer.Stop(); |
| StopEditTimer(); |
| nFlags |= F_CMD_ARRIVED; |
| SvLBoxEntry* pEntry = pView->GetEntry( rPt, sal_True ); |
| if( (nFlags & F_DOWN_CTRL) && pEntry && !pView->IsSelected(pEntry) ) |
| pView->Select( pEntry, sal_True ); |
| nFlags &= ~(F_DOWN_CTRL | F_DOWN_DESELECT); |
| } |
| |
| void SvImpIconView::SttDrag( const Point& rPos ) |
| { |
| PrepareCommandEvent( rPos ); |
| |
| nFlags |= F_DRAG_SOURCE; |
| ShowCursor( sal_False ); |
| } |
| |
| void SvImpIconView::EndDrag() |
| { |
| ShowCursor( sal_True ); |
| nFlags &= (~F_DRAG_SOURCE); |
| } |
| |
| void SvImpIconView::ToTop( SvLBoxEntry* pEntry ) |
| { |
| DBG_ASSERT(pZOrderList->GetPos(pEntry)!=0xffff,"ToTop:ZOrder?"); |
| if( pZOrderList->GetObject( pZOrderList->Count() -1 ) != pEntry ) |
| { |
| sal_uInt16 nPos = pZOrderList->GetPos( (void*)pEntry ); |
| pZOrderList->Remove( nPos, 1 ); |
| pZOrderList->Insert( pEntry, pZOrderList->Count() ); |
| } |
| } |
| |
| void SvImpIconView::SetCurParent( SvLBoxEntry* pNewParent ) |
| { |
| Clear(); |
| pCurParent = pNewParent; |
| ImpArrange(); |
| } |
| |
| void SvImpIconView::ClipAtVirtOutRect( Rectangle& rRect ) const |
| { |
| if( rRect.Bottom() >= aVirtOutputSize.Height() ) |
| rRect.Bottom() = aVirtOutputSize.Height() - 1; |
| if( rRect.Right() >= aVirtOutputSize.Width() ) |
| rRect.Right() = aVirtOutputSize.Width() - 1; |
| if( rRect.Top() < 0 ) |
| rRect.Top() = 0; |
| if( rRect.Left() < 0 ) |
| rRect.Left() = 0; |
| } |
| |
| // rRect: Bereich des Dokumentes (in Dokumentkoordinaten), der |
| // sichtbar gemacht werden soll. |
| // bScrBar == sal_True: Das Rect wurde aufgrund eines ScrollBar-Events berechnet |
| |
| void SvImpIconView::MakeVisible( const Rectangle& rRect, sal_Bool bScrBar ) |
| { |
| Rectangle aRect( rRect ); |
| ClipAtVirtOutRect( aRect ); |
| MapMode aMapMode( pView->GetMapMode() ); |
| Point aOrigin( aMapMode.GetOrigin() ); |
| // in Dokumentkoordinate umwandeln |
| aOrigin *= -1; |
| |
| Rectangle aOutputArea( aOrigin, aOutputSize ); |
| if( aOutputArea.IsInside( aRect ) ) |
| return; // ist schon sichtbar |
| |
| long nDy; |
| if( aRect.Top() < aOutputArea.Top() ) |
| { |
| // nach oben scrollen (nDy < 0) |
| nDy = aRect.Top() - aOutputArea.Top(); |
| } |
| else if( aRect.Bottom() > aOutputArea.Bottom() ) |
| { |
| // nach unten scrollen (nDy > 0) |
| nDy = aRect.Bottom() - aOutputArea.Bottom(); |
| } |
| else |
| nDy = 0; |
| |
| long nDx; |
| if( aRect.Left() < aOutputArea.Left() ) |
| { |
| // nach links scrollen (nDx < 0) |
| nDx = aRect.Left() - aOutputArea.Left(); |
| } |
| else if( aRect.Right() > aOutputArea.Right() ) |
| { |
| // nach rechts scrollen (nDx > 0) |
| nDx = aRect.Right() - aOutputArea.Right(); |
| } |
| else |
| nDx = 0; |
| |
| aOrigin.X() += nDx; |
| aOrigin.Y() += nDy; |
| aOutputArea.SetPos( aOrigin ); |
| |
| pView->Update(); |
| |
| // Origin fuer SV invertieren (damit wir in |
| // Dokumentkoordinaten scrollen/painten koennen) |
| aOrigin *= -1; |
| aMapMode.SetOrigin( aOrigin ); |
| pView->SetMapMode( aMapMode ); |
| |
| // in umgekehrte Richtung scrollen! |
| pView->Control::Scroll( -nDx, -nDy, aOutputArea, sal_True ); |
| if( aHorSBar.IsVisible() || aVerSBar.IsVisible() ) |
| { |
| if( !bScrBar ) |
| { |
| aOrigin *= -1; |
| // Thumbs korrigieren |
| if(aHorSBar.IsVisible() && aHorSBar.GetThumbPos() != aOrigin.X()) |
| aHorSBar.SetThumbPos( aOrigin.X() ); |
| if(aVerSBar.IsVisible() && aVerSBar.GetThumbPos() != aOrigin.Y()) |
| aVerSBar.SetThumbPos( aOrigin.Y() ); |
| } |
| } |
| // pruefen, ob ScrollBars noch benoetigt werden |
| CheckScrollBars(); |
| pView->Update(); |
| } |
| |
| |
| SvLBoxEntry* SvImpIconView::GetNewCursor() |
| { |
| SvLBoxEntry* pNewCursor; |
| if( pCursor ) |
| { |
| pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_False ); |
| if( !pNewCursor ) |
| { |
| pNewCursor = pImpCursor->GoLeftRight( pCursor, sal_True ); |
| if( !pNewCursor ) |
| { |
| pNewCursor = pImpCursor->GoUpDown( pCursor, sal_False ); |
| if( !pNewCursor ) |
| pNewCursor = pImpCursor->GoUpDown( pCursor, sal_True ); |
| } |
| } |
| } |
| else |
| pNewCursor = pModel->FirstChild( pCurParent ); |
| DBG_ASSERT(!pNewCursor|| (pCursor&&pCursor!=pNewCursor),"GetNewCursor failed"); |
| return pNewCursor; |
| } |
| |
| |
| sal_uInt16 SvImpIconView:: GetSelectionCount() const |
| { |
| sal_uInt16 nSelected = 0; |
| SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent); |
| while( pEntry ) |
| { |
| if( pView->IsSelected( pEntry ) ) |
| nSelected++; |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| return nSelected; |
| } |
| |
| |
| void SvImpIconView::ToggleSelection( SvLBoxEntry* pEntry ) |
| { |
| sal_Bool bSel; |
| if( pView->IsSelected( pEntry ) ) |
| bSel = sal_False; |
| else |
| bSel = sal_True; |
| pView->Select( pEntry, bSel ); |
| } |
| |
| void SvImpIconView::DeselectAllBut( SvLBoxEntry* pThisEntryNot ) |
| { |
| ClearSelectedRectList(); |
| SvLBoxEntry* pEntry = pModel->FirstChild( pCurParent ); |
| while( pEntry ) |
| { |
| if( pEntry != pThisEntryNot && pView->IsSelected( pEntry )) |
| pView->Select( pEntry, sal_False ); |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| } |
| |
| #define ICN_ROWS 50 |
| #define ICN_COLS 30 |
| |
| ImpIcnCursor::ImpIcnCursor( SvImpIconView* pOwner ) |
| { |
| pView = pOwner; |
| pColumns = 0; |
| pRows = 0; |
| pCurEntry = 0; |
| nDeltaWidth = 0; |
| nDeltaHeight= 0; |
| nCols = 0; |
| nRows = 0; |
| nGridCols = 0; |
| nGridRows = 0; |
| pGridMap = 0; |
| } |
| |
| ImpIcnCursor::~ImpIcnCursor() |
| { |
| delete[] pColumns; |
| delete[] pRows; |
| delete pGridMap; |
| } |
| |
| sal_uInt16 ImpIcnCursor::GetSortListPos( SvPtrarr* pList, long nValue, |
| int bVertical ) |
| { |
| sal_uInt16 nCount = (sal_uInt16)pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| sal_uInt16 nCurPos = 0; |
| long nPrevValue = LONG_MIN; |
| while( nCount ) |
| { |
| const Rectangle& rRect= |
| pView->GetBoundingRect((SvLBoxEntry*)(pList->GetObject(nCurPos))); |
| long nCurValue; |
| if( bVertical ) |
| nCurValue = rRect.Top(); |
| else |
| nCurValue = rRect.Left(); |
| if( nValue >= nPrevValue && nValue <= nCurValue ) |
| return (sal_uInt16)nCurPos; |
| nPrevValue = nCurValue; |
| nCount--; |
| nCurPos++; |
| } |
| return pList->Count(); |
| } |
| |
| void ImpIcnCursor::ImplCreate() |
| { |
| pView->CheckBoundingRects(); |
| DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared"); |
| |
| SetDeltas(); |
| |
| pColumns = new SvPtrarr[ nCols ]; |
| pRows = new SvPtrarr[ nRows ]; |
| |
| DELETEZ(pGridMap); |
| |
| SvLBoxTreeList* pModel = pView->pModel; |
| SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent ); |
| while( pEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry); |
| // const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| Rectangle rRect( pView->CalcBmpRect( pEntry,0,pViewData ) ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight ); |
| short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth ); |
| |
| // Rundungsfehler abfangen |
| if( nY >= nRows ) |
| nY = sal::static_int_cast< short >(nRows - 1); |
| if( nX >= nCols ) |
| nX = sal::static_int_cast< short >(nCols - 1); |
| |
| sal_uInt16 nIns = GetSortListPos( &pColumns[nX], rRect.Top(), sal_True ); |
| pColumns[ nX ].Insert( pEntry, nIns ); |
| |
| nIns = GetSortListPos( &pRows[nY], rRect.Left(), sal_False ); |
| pRows[ nY ].Insert( pEntry, nIns ); |
| |
| pViewData->nX = nX; |
| pViewData->nY = nY; |
| |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| } |
| |
| void ImpIcnCursor::CreateGridMap() |
| { |
| if( pGridMap ) |
| return; |
| |
| const Size& rSize = pView->aVirtOutputSize; |
| long nWidth = rSize.Width(); |
| if( nWidth < pView->nMaxVirtWidth ) |
| nWidth = pView->nMaxVirtWidth; |
| nWidth -= 2*LROFFS_WINBORDER; |
| if( nWidth <= 0 ) |
| nWidth = 1; |
| |
| nGridDX = pView->nGridDX; |
| nGridDY = pView->nGridDY; |
| |
| // Hinweis: Wegen der Abrundung bei Berechnung von nGridCols |
| // ist es moeglich, dass Eintrage nicht im Grid liegen. Diese |
| // wurden typischerweise manuell verschoben und gelockt |
| nGridCols = nWidth / nGridDX; |
| if( !nGridCols ) nGridCols = 1; |
| |
| nGridRows = rSize.Height() / nGridDY; |
| // nRows nicht abrunden, da zur Vermeidung von Ueberlappungen |
| // das gesamte BoundingRect des Eintrags zur Markierung im Grid |
| // herangezogen wird. |
| if( (nGridRows * nGridDY) < rSize.Height() ) |
| nGridRows++; |
| else if( !nGridRows ) |
| nGridRows = 1; |
| |
| //XXX |
| //nGridRows += 50; // in fuenfziger-Schritten |
| |
| pGridMap = new sal_Bool[ nGridRows*nGridCols]; |
| memset( (void*)pGridMap, 0, nGridRows*nGridCols ); |
| |
| SvLBoxTreeList* pModel = pView->pModel; |
| SvLBoxEntry* pEntry = pModel->FirstChild( pView->pCurParent ); |
| while( pEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry); |
| const Rectangle& rRect = pViewData->aRect; |
| // nur, wenn der Entry schon plaziert ist |
| if( pView->IsBoundingRectValid( rRect )) |
| { |
| // Alle vom Eintrag beruehrten Grids kennzeichnen |
| SetGridUsed( pView->GetBoundingRect( pEntry, pViewData ) ); |
| } |
| pEntry = pModel->NextSibling( pEntry ); |
| } |
| } |
| |
| sal_Bool ImpIcnCursor::GetGrid( const Point& rDocPos, sal_uInt16& rGridX, sal_uInt16& rGridY ) const |
| { |
| Point aPos( rDocPos ); |
| aPos.X() -= LROFFS_WINBORDER; |
| aPos.Y() -= TBOFFS_WINBORDER; |
| rGridX = (sal_uInt16)(aPos.X() / nGridDX); |
| rGridY = (sal_uInt16)(aPos.Y() / nGridDY); |
| sal_Bool bInGrid = sal_True; |
| if( rGridX >= nGridCols ) |
| { |
| rGridX = sal::static_int_cast< sal_uInt16 >(nGridCols - 1); |
| bInGrid = sal_False; |
| } |
| if( rGridY >= nGridRows ) |
| { |
| rGridY = sal::static_int_cast< sal_uInt16 >(nGridRows - 1); |
| if( !bInGrid ) |
| return sal_False; // beide Koordinaten nicht im Grid |
| } |
| return sal_True; |
| } |
| |
| void ImpIcnCursor::SetGridUsed( const Rectangle& rRect, sal_Bool bUsed ) |
| { |
| CreateGridMap(); |
| sal_uInt16 nTLX, nTLY, nBRX, nBRY; |
| |
| sal_Bool bTLInGrid = GetGrid( rRect.TopLeft(), nTLX, nTLY ); |
| sal_Bool bBRInGrid = GetGrid( rRect.BottomRight(), nBRX, nBRY ); |
| |
| if( !bTLInGrid && !bBRInGrid ) |
| return; |
| |
| for( sal_uInt16 nCurY = nTLY; nCurY <= nBRY; nCurY++ ) |
| { |
| for( sal_uInt16 nCurX = nTLX; nCurX <= nBRX; nCurX++ ) |
| { |
| SetGridUsed( nCurX, nCurY, bUsed ); |
| } |
| } |
| } |
| |
| void ImpIcnCursor::Clear( sal_Bool bGridToo ) |
| { |
| if( pColumns ) |
| { |
| delete[] pColumns; |
| delete[] pRows; |
| pColumns = 0; |
| pRows = 0; |
| pCurEntry = 0; |
| nDeltaWidth = 0; |
| nDeltaHeight = 0; |
| } |
| if( bGridToo && pGridMap ) |
| { |
| DELETEZ(pGridMap); |
| nGridRows = 0; |
| nGridCols = 0; |
| } |
| } |
| |
| SvLBoxEntry* ImpIcnCursor::SearchCol(sal_uInt16 nCol,sal_uInt16 nTop,sal_uInt16 nBottom, |
| sal_uInt16, sal_Bool bDown, sal_Bool bSimple ) |
| { |
| DBG_ASSERT(pCurEntry,"SearchCol: No reference entry"); |
| SvPtrarr* pList = &(pColumns[ nCol ]); |
| sal_uInt16 nCount = pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry); |
| |
| if( bSimple ) |
| { |
| sal_uInt16 nListPos = pList->GetPos( pCurEntry ); |
| DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List"); |
| if( bDown ) |
| { |
| while( nListPos < nCount-1 ) |
| { |
| nListPos++; |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| if( rRect.Top() > rRefRect.Top() ) |
| return pEntry; |
| } |
| return 0; |
| } |
| else |
| { |
| while( nListPos ) |
| { |
| nListPos--; |
| if( nListPos < nCount ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| if( rRect.Top() < rRefRect.Top() ) |
| return pEntry; |
| } |
| } |
| return 0; |
| } |
| } |
| |
| if( nTop > nBottom ) |
| { |
| sal_uInt16 nTemp = nTop; |
| nTop = nBottom; |
| nBottom = nTemp; |
| } |
| long nMinDistance = LONG_MAX; |
| SvLBoxEntry* pResult = 0; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur )); |
| if( pEntry != pCurEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry); |
| sal_uInt16 nY = pViewData->nY; |
| if( nY >= nTop && nY <= nBottom ) |
| { |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| long nDistance = rRect.Top() - rRefRect.Top(); |
| if( nDistance < 0 ) |
| nDistance *= -1; |
| if( nDistance && nDistance < nMinDistance ) |
| { |
| nMinDistance = nDistance; |
| pResult = pEntry; |
| } |
| } |
| } |
| } |
| return pResult; |
| } |
| |
| SvLBoxEntry* ImpIcnCursor::SearchRow(sal_uInt16 nRow,sal_uInt16 nLeft,sal_uInt16 nRight, |
| sal_uInt16, sal_Bool bRight, sal_Bool bSimple ) |
| { |
| DBG_ASSERT(pCurEntry,"SearchRow: No reference entry"); |
| SvPtrarr* pList = &(pRows[ nRow ]); |
| sal_uInt16 nCount = pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| const Rectangle& rRefRect = pView->GetBoundingRect(pCurEntry); |
| |
| if( bSimple ) |
| { |
| sal_uInt16 nListPos = pList->GetPos( pCurEntry ); |
| DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List"); |
| if( bRight ) |
| { |
| while( nListPos < nCount-1 ) |
| { |
| nListPos++; |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| if( rRect.Left() > rRefRect.Left() ) |
| return pEntry; |
| } |
| return 0; |
| } |
| else |
| { |
| while( nListPos ) |
| { |
| nListPos--; |
| if( nListPos < nCount ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| if( rRect.Left() < rRefRect.Left() ) |
| return pEntry; |
| } |
| } |
| return 0; |
| } |
| |
| } |
| if( nRight < nLeft ) |
| { |
| sal_uInt16 nTemp = nRight; |
| nRight = nLeft; |
| nLeft = nTemp; |
| } |
| long nMinDistance = LONG_MAX; |
| SvLBoxEntry* pResult = 0; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pList->GetObject( nCur )); |
| if( pEntry != pCurEntry ) |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pEntry); |
| sal_uInt16 nX = pViewData->nX; |
| if( nX >= nLeft && nX <= nRight ) |
| { |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| long nDistance = rRect.Left() - rRefRect.Left(); |
| if( nDistance < 0 ) |
| nDistance *= -1; |
| if( nDistance && nDistance < nMinDistance ) |
| { |
| nMinDistance = nDistance; |
| pResult = pEntry; |
| } |
| } |
| } |
| } |
| return pResult; |
| } |
| |
| |
| |
| /* |
| Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw. |
| linksstehenden. Suchverfahren am Beispiel bRight = sal_True: |
| |
| c |
| b c |
| a b c |
| S 1 1 1 ====> Suchrichtung |
| a b c |
| b c |
| c |
| |
| S : Startposition |
| 1 : erstes Suchrechteck |
| a,b,c : 2., 3., 4. Suchrechteck |
| */ |
| |
| SvLBoxEntry* ImpIcnCursor::GoLeftRight( SvLBoxEntry* pIcnEntry, sal_Bool bRight ) |
| { |
| SvLBoxEntry* pResult; |
| pCurEntry = pIcnEntry; |
| Create(); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry); |
| sal_uInt16 nY = pViewData->nY; |
| sal_uInt16 nX = pViewData->nX; |
| DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column"); |
| DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row"); |
| // Nachbar auf gleicher Zeile ? |
| if( bRight ) |
| pResult = SearchRow( |
| nY, nX, sal::static_int_cast< sal_uInt16 >(nCols-1), nX, sal_True, sal_True ); |
| else |
| pResult = SearchRow( nY, nX ,0, nX, sal_False, sal_True ); |
| if( pResult ) |
| return pResult; |
| |
| long nCurCol = nX; |
| |
| long nColOffs, nLastCol; |
| if( bRight ) |
| { |
| nColOffs = 1; |
| nLastCol = nCols; |
| } |
| else |
| { |
| nColOffs = -1; |
| nLastCol = -1; // 0-1 |
| } |
| |
| sal_uInt16 nRowMin = nY; |
| sal_uInt16 nRowMax = nY; |
| do |
| { |
| SvLBoxEntry* pEntry = SearchCol((sal_uInt16)nCurCol,nRowMin,nRowMax,nY,sal_True, sal_False); |
| if( pEntry ) |
| return pEntry; |
| if( nRowMin ) |
| nRowMin--; |
| if( nRowMax < (nRows-1)) |
| nRowMax++; |
| nCurCol += nColOffs; |
| } while( nCurCol != nLastCol ); |
| return 0; |
| } |
| |
| SvLBoxEntry* ImpIcnCursor::GoUpDown( SvLBoxEntry* pIcnEntry, sal_Bool bDown) |
| { |
| SvLBoxEntry* pResult; |
| pCurEntry = pIcnEntry; |
| Create(); |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA2(pIcnEntry); |
| sal_uInt16 nY = pViewData->nY; |
| sal_uInt16 nX = pViewData->nX; |
| DBG_ASSERT(nY<nRows,"GoUpDown:Bad column"); |
| DBG_ASSERT(nX<nCols,"GoUpDown:Bad row"); |
| |
| // Nachbar in gleicher Spalte ? |
| if( bDown ) |
| pResult = SearchCol( |
| nX, nY, sal::static_int_cast< sal_uInt16 >(nRows-1), nY, sal_True, sal_True ); |
| else |
| pResult = SearchCol( nX, nY ,0, nY, sal_False, sal_True ); |
| if( pResult ) |
| return pResult; |
| |
| long nCurRow = nY; |
| |
| long nRowOffs, nLastRow; |
| if( bDown ) |
| { |
| nRowOffs = 1; |
| nLastRow = nRows; |
| } |
| else |
| { |
| nRowOffs = -1; |
| nLastRow = -1; // 0-1 |
| } |
| |
| sal_uInt16 nColMin = nX; |
| sal_uInt16 nColMax = nX; |
| do |
| { |
| SvLBoxEntry* pEntry = SearchRow((sal_uInt16)nCurRow,nColMin,nColMax,nX,sal_True, sal_False); |
| if( pEntry ) |
| return pEntry; |
| if( nColMin ) |
| nColMin--; |
| if( nColMax < (nCols-1)) |
| nColMax++; |
| nCurRow += nRowOffs; |
| } while( nCurRow != nLastRow ); |
| return 0; |
| } |
| |
| void ImpIcnCursor::SetDeltas() |
| { |
| const Size& rSize = pView->aVirtOutputSize; |
| if( pView->nFlags & F_GRIDMODE ) |
| { |
| nGridDX = pView->nGridDX; |
| nGridDY = pView->nGridDY; |
| } |
| else |
| { |
| nGridDX = 20; |
| nGridDY = 20; |
| } |
| nCols = rSize.Width() / nGridDX; |
| if( !nCols ) |
| nCols = 1; |
| nRows = rSize.Height() / nGridDY; |
| if( (nRows * nGridDY) < rSize.Height() ) |
| nRows++; |
| if( !nRows ) |
| nRows = 1; |
| |
| nDeltaWidth = (short)(rSize.Width() / nCols); |
| nDeltaHeight = (short)(rSize.Height() / nRows); |
| if( !nDeltaHeight ) |
| { |
| nDeltaHeight = 1; |
| DBG_WARNING("SetDeltas:Bad height"); |
| } |
| if( !nDeltaWidth ) |
| { |
| nDeltaWidth = 1; |
| DBG_WARNING("SetDeltas:Bad width"); |
| } |
| } |
| |
| |
| void ImpIcnCursor::ExpandGrid() |
| { |
| if( pGridMap ) |
| { |
| long nNewGridRows = nGridRows + 20; |
| unsigned char* pTempMap = new unsigned char[ nNewGridRows * nGridCols ]; |
| memcpy( pTempMap, pGridMap, nGridRows * nGridCols ); |
| delete pGridMap; |
| pGridMap = pTempMap; |
| nGridRows = nNewGridRows; |
| } |
| } |
| |
| sal_Bool ImpIcnCursor::FindEmptyGridRect( Rectangle& rRect ) |
| { |
| CreateGridMap(); |
| sal_uInt16 nCount = (sal_uInt16)(nGridCols * nGridRows); |
| if( !nCount ) |
| return sal_False; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| if( !pGridMap[ nCur ] ) |
| { |
| sal_uInt16 nCol = (sal_uInt16)(nCur % nGridCols); |
| sal_uInt16 nRow = (sal_uInt16)(nCur / nGridCols); |
| rRect.Top() = nRow * nGridDY + TBOFFS_WINBORDER; |
| rRect.Bottom() = rRect.Top() + nGridDY; |
| rRect.Left() = nCol * nGridDX+ LROFFS_WINBORDER; |
| rRect.Right() = rRect.Left() + nGridDX; |
| SetGridUsed( nCol, nRow, sal_True ); |
| |
| //XXX |
| //if( nRow + 5 > nGridRows ) |
| // ExpandGrid(); |
| DBG_ASSERT(pGridMap[nCur],"SetGridUsed failed"); |
| return sal_True; |
| } |
| } |
| // Gridmap ist voll: Um eine Zeile erweitern |
| rRect.Top() = nGridRows * nGridDY + TBOFFS_WINBORDER; |
| rRect.Bottom() = rRect.Top() + nGridDY; |
| rRect.Left() = LROFFS_WINBORDER; |
| rRect.Right() = rRect.Left() + nGridDX; |
| return sal_False; |
| //XXX |
| //ExpandGrid(); |
| //return sal_True; |
| } |
| |
| void ImpIcnCursor::CreateGridAjustData( SvPtrarr& rLists, SvLBoxEntry* pRefEntry) |
| { |
| if( !pRefEntry ) |
| { |
| sal_uInt16 nAdjustRows = (sal_uInt16)(pView->aVirtOutputSize.Height() / pView->nGridDY); |
| nAdjustRows++; // wg. Abrundung! |
| |
| if( !nAdjustRows ) |
| return; |
| for( sal_uInt16 nCurList = 0; nCurList < nAdjustRows; nCurList++ ) |
| { |
| SvPtrarr* pRow = new SvPtrarr; |
| rLists.Insert( (void*)pRow, nCurList ); |
| } |
| SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent ); |
| while( pEntry ) |
| { |
| const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY ); |
| sal_uInt16 nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),sal_False); |
| ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns ); |
| pEntry = pView->pModel->NextSibling( pEntry ); |
| } |
| } |
| else |
| { |
| // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile |
| |
| // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen??? |
| |
| Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) ); |
| //const Rectangle& rRefRect = pView->GetBoundingRect( pRefEntry ); |
| short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY ); |
| SvPtrarr* pRow = new SvPtrarr; |
| rLists.Insert( (void*)pRow, 0 ); |
| SvLBoxEntry* pEntry = pView->pModel->FirstChild( pView->pCurParent ); |
| while( pEntry ) |
| { |
| Rectangle rRect( pView->CalcBmpRect(pEntry) ); |
| //const Rectangle& rRect = pView->GetBoundingRect( pEntry ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY ); |
| if( nY == nRefRow ) |
| { |
| sal_uInt16 nIns = GetSortListPos( pRow, rRect.Left(), sal_False ); |
| pRow->Insert( pEntry, nIns ); |
| } |
| pEntry = pView->pModel->NextSibling( pEntry ); |
| } |
| } |
| } |
| |
| //static |
| void ImpIcnCursor::DestroyGridAdjustData( SvPtrarr& rLists ) |
| { |
| sal_uInt16 nCount = rLists.Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ]; |
| delete pArr; |
| } |
| rLists.Remove( 0, rLists.Count() ); |
| } |
| |
| void SvImpIconView::SetGrid( long nDX, long nDY ) |
| { |
| nGridDX = nDX; |
| nGridDY = nDY; |
| nFlags |= F_GRIDMODE; |
| } |
| |
| Rectangle SvImpIconView::CalcMaxTextRect( const SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) const |
| { |
| Rectangle aRect = pViewData->aGridRect; |
| long nBmpHeight = ((SvLBoxEntry*)pEntry)->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)->GetSize(pView,(SvLBoxEntry*)pEntry).Height(); |
| aRect.Top() += nBmpHeight; |
| aRect.Top() += ICONVIEW_OFFS_BMP_STRING; |
| if( aRect.Top() > aRect.Bottom()) |
| aRect.Top() = aRect.Bottom(); |
| aRect.Left() += LROFFS_BOUND; |
| aRect.Left()++; |
| aRect.Right() -= LROFFS_BOUND; |
| aRect.Right()--; |
| if( aRect.Left() > aRect.Right()) |
| aRect.Left() = aRect.Right(); |
| if( GetTextMode( pEntry, pViewData ) == ShowTextFull ) |
| aRect.Bottom() = LONG_MAX; |
| return aRect; |
| } |
| |
| void SvImpIconView::Center( SvLBoxEntry* pEntry, |
| SvIcnVwDataEntry* pViewData ) const |
| { |
| SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| const String& rEntryText = pStringItem->GetText(); |
| |
| Rectangle aTextRect = CalcMaxTextRect(pEntry,pViewData); |
| aTextRect = GetTextRect( pView, aTextRect, rEntryText, DRAWTEXT_FLAGS ); |
| pViewData->aTextSize = aTextRect.GetSize(); |
| |
| pViewData->aRect = pViewData->aGridRect; |
| Size aSize( CalcBoundingSize( pEntry, pViewData ) ); |
| long nBorder = pViewData->aGridRect.GetWidth() - aSize.Width(); |
| pViewData->aRect.Left() += nBorder / 2; |
| pViewData->aRect.Right() -= nBorder / 2; |
| pViewData->aRect.Bottom() = pViewData->aRect.Top() + aSize.Height(); |
| } |
| |
| |
| // Die Deltas entsprechen Offsets, um die die View auf dem Doc verschoben wird |
| // links, hoch: Offsets < 0 |
| // rechts, runter: Offsets > 0 |
| void SvImpIconView::Scroll( long nDeltaX, long nDeltaY, sal_Bool bScrollBar ) |
| { |
| const MapMode& rMapMode = pView->GetMapMode(); |
| Point aOrigin( rMapMode.GetOrigin() ); |
| // in Dokumentkoordinate umwandeln |
| aOrigin *= -1; |
| aOrigin.Y() += nDeltaY; |
| aOrigin.X() += nDeltaX; |
| Rectangle aRect( aOrigin, aOutputSize ); |
| MakeVisible( aRect, bScrollBar ); |
| } |
| |
| |
| const Size& SvImpIconView::GetItemSize( SvIconView* pIconView, |
| SvLBoxEntry* pEntry, SvLBoxItem* pItem, const SvIcnVwDataEntry* pViewData) const |
| { |
| if( (nFlags & F_GRIDMODE) && pItem->IsA() == SV_ITEM_ID_LBOXSTRING ) |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(pEntry); |
| return pViewData->aTextSize; |
| } |
| else |
| return pItem->GetSize( pIconView, pEntry ); |
| } |
| |
| Rectangle SvImpIconView::CalcFocusRect( SvLBoxEntry* pEntry ) |
| { |
| #if !defined(OS2) |
| SvLBoxString* pStringItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| DBG_ASSERT(pStringItem,"Text not set"); |
| return CalcTextRect( pEntry, pStringItem ); |
| #else |
| return CalcBmpRect( pEntry ); |
| #endif |
| } |
| |
| |
| void SvImpIconView::SelectRect( const Rectangle& rRect, sal_Bool bAdd, |
| SvPtrarr* pOtherRects, short nBorderOffs ) |
| { |
| if( !pZOrderList || !pZOrderList->Count() ) |
| return; |
| |
| CheckBoundingRects(); |
| pView->Update(); |
| sal_uInt16 nCount = pZOrderList->Count(); |
| |
| Rectangle aRect( rRect ); |
| aRect.Justify(); |
| if( nBorderOffs ) |
| { |
| aRect.Left() -= nBorderOffs; |
| aRect.Right() += nBorderOffs; |
| aRect.Top() -= nBorderOffs; |
| aRect.Bottom() += nBorderOffs; |
| } |
| sal_Bool bCalcOverlap = (bAdd && pOtherRects && pOtherRects->Count()) ? sal_True : sal_False; |
| |
| for( sal_uInt16 nPos = 0; nPos < nCount; nPos++ ) |
| { |
| SvLBoxEntry* pEntry = (SvLBoxEntry*)(pZOrderList->GetObject(nPos )); |
| |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| DBG_ASSERT(pViewData,"Entry not in model"); |
| if( !IsBoundingRectValid( pViewData->aRect )) |
| FindBoundingRect( pEntry, pViewData ); |
| const Rectangle& rBoundRect = pViewData->aRect; |
| sal_Bool bSelected = pViewData->IsSelected(); |
| |
| sal_Bool bOverlaps; |
| if( bCalcOverlap ) |
| bOverlaps = IsOver( pOtherRects, rBoundRect ); |
| else |
| bOverlaps = sal_False; |
| sal_Bool bOver = aRect.IsOver( rBoundRect ); |
| |
| if( bOver && !bOverlaps ) |
| { |
| // Ist im neuen Selektionsrechteck und in keinem alten |
| // => selektieren |
| if( !bSelected ) |
| pView->Select( pEntry, sal_True ); |
| } |
| else if( !bAdd ) |
| { |
| // ist ausserhalb des Selektionsrechtecks |
| // => Selektion entfernen |
| if( bSelected ) |
| pView->Select( pEntry, sal_False ); |
| } |
| else if( bAdd && bOverlaps ) |
| { |
| // Der Eintrag befindet sich in einem alten (=>Aufspannen |
| // mehrerer Rechtecke mit Ctrl!) Selektionsrechteck |
| |
| // Hier ist noch ein Bug! Der Selektionsstatus eines Eintrags |
| // in einem vorherigen Rechteck, muss restauriert werden, wenn |
| // er vom aktuellen Selektionsrechteck beruehrt wurde, jetzt aber |
| // nicht mehr in ihm liegt. Ich gehe hier der Einfachheit halber |
| // pauschal davon aus, dass die Eintraege in den alten Rechtecken |
| // alle selektiert sind. Ebenso ist es falsch, die Schnittmenge |
| // nur zu deselektieren. |
| // Loesungsmoeglichkeit: Snapshot der Selektion vor dem Auf- |
| // spannen des Rechtecks merken |
| if( rBoundRect.IsOver( rRect)) |
| { |
| // Schnittmenge zwischen alten Rects & aktuellem Rect desel. |
| if( bSelected ) |
| pView->Select( pEntry, sal_False ); |
| } |
| else |
| { |
| // Eintrag eines alten Rects selektieren |
| if( !bSelected ) |
| pView->Select( pEntry, sal_True ); |
| } |
| } |
| else if( !bOver && bSelected ) |
| { |
| // Der Eintrag liegt voellig ausserhalb und wird deshalb desel. |
| pView->Select( pEntry, sal_False ); |
| } |
| } |
| pView->Update(); |
| } |
| |
| sal_Bool SvImpIconView::IsOver( SvPtrarr* pRectList, const Rectangle& rBoundRect ) const |
| { |
| sal_uInt16 nCount = pRectList->Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| Rectangle* pRect = (Rectangle*)pRectList->GetObject( nCur ); |
| if( rBoundRect.IsOver( *pRect )) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| void SvImpIconView::AddSelectedRect( const Rectangle& rRect, short nBorderOffs ) |
| { |
| Rectangle* pRect = new Rectangle( rRect ); |
| pRect->Justify(); |
| if( nBorderOffs ) |
| { |
| pRect->Left() -= nBorderOffs; |
| pRect->Right() += nBorderOffs; |
| pRect->Top() -= nBorderOffs; |
| pRect->Bottom() += nBorderOffs; |
| } |
| aSelectedRectList.Insert( (void*)pRect, aSelectedRectList.Count() ); |
| } |
| |
| void SvImpIconView::ClearSelectedRectList() |
| { |
| sal_uInt16 nCount = aSelectedRectList.Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| Rectangle* pRect = (Rectangle*)aSelectedRectList.GetObject( nCur ); |
| delete pRect; |
| } |
| aSelectedRectList.Remove( 0, aSelectedRectList.Count() ); |
| } |
| |
| |
| void SvImpIconView::DrawSelectionRect( const Rectangle& rRect ) |
| { |
| pView->HideTracking(); |
| nFlags |= F_SELRECT_VISIBLE; |
| pView->ShowTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); |
| aCurSelectionRect = rRect; |
| } |
| |
| void SvImpIconView::HideSelectionRect() |
| { |
| if( nFlags & F_SELRECT_VISIBLE ) |
| { |
| pView->HideTracking(); |
| nFlags &= ~F_SELRECT_VISIBLE; |
| } |
| } |
| |
| void SvImpIconView::ImpDrawXORRect( const Rectangle& rRect ) |
| { |
| RasterOp eOldOp = pView->GetRasterOp(); |
| pView->SetRasterOp( ROP_XOR ); |
| Color aOldColor = pView->GetFillColor(); |
| pView->SetFillColor(); |
| pView->DrawRect( rRect ); |
| pView->SetFillColor( aOldColor ); |
| pView->SetRasterOp( eOldOp ); |
| } |
| |
| void SvImpIconView::CalcScrollOffsets( const Point& rPosPixel, |
| long& rX, long& rY, sal_Bool bInDragDrop, sal_uInt16 nBorderWidth) |
| { |
| // Scrolling der View, falls sich der Mauszeiger im Grenzbereich des |
| // Fensters befindet |
| long nPixelToScrollX = 0; |
| long nPixelToScrollY = 0; |
| Size aWndSize = aOutputSize; |
| |
| nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Height()-1), (long)nBorderWidth )); |
| nBorderWidth = (sal_uInt16)(Min( (long)(aWndSize.Width()-1), (long)nBorderWidth )); |
| |
| if ( rPosPixel.X() < nBorderWidth ) |
| { |
| if( bInDragDrop ) |
| nPixelToScrollX = -DD_SCROLL_PIXEL; |
| else |
| nPixelToScrollX = rPosPixel.X()- nBorderWidth; |
| } |
| else if ( rPosPixel.X() > aWndSize.Width() - nBorderWidth ) |
| { |
| if( bInDragDrop ) |
| nPixelToScrollX = DD_SCROLL_PIXEL; |
| else |
| nPixelToScrollX = rPosPixel.X() - (aWndSize.Width() - nBorderWidth); |
| } |
| if ( rPosPixel.Y() < nBorderWidth ) |
| { |
| if( bInDragDrop ) |
| nPixelToScrollY = -DD_SCROLL_PIXEL; |
| else |
| nPixelToScrollY = rPosPixel.Y() - nBorderWidth; |
| } |
| else if ( rPosPixel.Y() > aWndSize.Height() - nBorderWidth ) |
| { |
| if( bInDragDrop ) |
| nPixelToScrollY = DD_SCROLL_PIXEL; |
| else |
| nPixelToScrollY = rPosPixel.Y() - (aWndSize.Height() - nBorderWidth); |
| } |
| |
| rX = nPixelToScrollX; |
| rY = nPixelToScrollY; |
| } |
| |
| IMPL_LINK(SvImpIconView, MouseMoveTimeoutHdl, Timer*, pTimer ) |
| { |
| pTimer->Start(); |
| MouseMove( aMouseMoveEvent ); |
| return 0; |
| } |
| |
| void SvImpIconView::EndTracking() |
| { |
| pView->ReleaseMouse(); |
| if( nFlags & F_RUBBERING ) |
| { |
| aMouseMoveTimer.Stop(); |
| nFlags &= ~(F_RUBBERING | F_ADD_MODE); |
| } |
| } |
| |
| sal_Bool SvImpIconView::IsTextHit( SvLBoxEntry* pEntry, const Point& rDocPos ) |
| { |
| SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); |
| if( pItem ) |
| { |
| Rectangle aRect( CalcTextRect( pEntry, pItem )); |
| if( aRect.IsInside( rDocPos ) ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| IMPL_LINK(SvImpIconView, EditTimeoutHdl, Timer*, EMPTYARG ) |
| { |
| SvLBoxEntry* pEntry = GetCurEntry(); |
| if( pView->IsInplaceEditingEnabled() && pEntry && |
| pView->IsSelected( pEntry )) |
| { |
| pView->EditEntry( pEntry ); |
| } |
| return 0; |
| } |
| |
| |
| // |
| // Funktionen zum Ausrichten der Eintraege am Grid |
| // |
| |
| // pStart == 0: Alle Eintraege werden ausgerichtet |
| // sonst: Alle Eintraege der Zeile ab einschliesslich pStart werden ausgerichtet |
| void SvImpIconView::AdjustAtGrid( SvLBoxEntry* pStart ) |
| { |
| SvPtrarr aLists; |
| pImpCursor->CreateGridAjustData( aLists, pStart ); |
| sal_uInt16 nCount = aLists.Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| AdjustAtGrid( *(SvPtrarr*)aLists[ nCur ], pStart ); |
| } |
| ImpIcnCursor::DestroyGridAdjustData( aLists ); |
| CheckScrollBars(); |
| } |
| |
| // Richtet eine Zeile aus, erweitert ggf. die Breite; Bricht die Zeile nicht um |
| void SvImpIconView::AdjustAtGrid( const SvPtrarr& rRow, SvLBoxEntry* pStart ) |
| { |
| if( !rRow.Count() ) |
| return; |
| |
| sal_Bool bGo; |
| if( !pStart ) |
| bGo = sal_True; |
| else |
| bGo = sal_False; |
| |
| long nCurRight = 0; |
| for( sal_uInt16 nCur = 0; nCur < rRow.Count(); nCur++ ) |
| { |
| SvLBoxEntry* pCur = (SvLBoxEntry*)rRow[ nCur ]; |
| if( !bGo && pCur == pStart ) |
| bGo = sal_True; |
| |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pCur); |
| // Massgebend (fuer das menschliche Auge) ist die Bitmap, da sonst |
| // durch lange Texte der Eintrag stark springen kann |
| const Rectangle& rBoundRect = GetBoundingRect( pCur, pViewData ); |
| Rectangle aCenterRect( CalcBmpRect( pCur, 0, pViewData )); |
| if( bGo && !pViewData->IsEntryPosLocked() ) |
| { |
| long nWidth = aCenterRect.GetSize().Width(); |
| Point aNewPos( AdjustAtGrid( aCenterRect, rBoundRect ) ); |
| while( aNewPos.X() < nCurRight ) |
| aNewPos.X() += nGridDX; |
| if( aNewPos != rBoundRect.TopLeft() ) |
| SetEntryPosition( pCur, aNewPos ); |
| nCurRight = aNewPos.X() + nWidth; |
| } |
| else |
| { |
| nCurRight = rBoundRect.Right(); |
| } |
| } |
| } |
| |
| // Richtet Rect am Grid aus, garantiert jedoch nicht, dass die |
| // neue Pos. frei ist. Die Pos. kann fuer SetEntryPos verwendet werden. |
| // Das CenterRect beschreibt den Teil des BoundRects, der fuer |
| // die Berechnung des Ziel-Rechtecks verwendet wird. |
| Point SvImpIconView::AdjustAtGrid( const Rectangle& rCenterRect, |
| const Rectangle& rBoundRect ) const |
| { |
| Point aPos( rCenterRect.TopLeft() ); |
| Size aSize( rCenterRect.GetSize() ); |
| |
| aPos.X() -= LROFFS_WINBORDER; |
| aPos.Y() -= TBOFFS_WINBORDER; |
| |
| // align (ref ist mitte des rects) |
| short nGridX = (short)((aPos.X()+(aSize.Width()/2)) / nGridDX); |
| short nGridY = (short)((aPos.Y()+(aSize.Height()/2)) / nGridDY); |
| aPos.X() = nGridX * nGridDX; |
| aPos.Y() = nGridY * nGridDY; |
| // hor. center |
| aPos.X() += (nGridDX - rBoundRect.GetSize().Width() ) / 2; |
| |
| aPos.X() += LROFFS_WINBORDER; |
| aPos.Y() += TBOFFS_WINBORDER; |
| |
| return aPos; |
| } |
| |
| |
| void SvImpIconView::SetTextMode( SvIconViewTextMode eMode, SvLBoxEntry* pEntry ) |
| { |
| if( !pEntry ) |
| { |
| if( eTextMode != eMode ) |
| { |
| if( eTextMode == ShowTextDontKnow ) |
| eTextMode = ShowTextShort; |
| eTextMode = eMode; |
| pView->Arrange(); |
| } |
| } |
| else |
| { |
| SvIcnVwDataEntry* pViewData = ICNVIEWDATA(pEntry); |
| if( pViewData->eTextMode != eMode ) |
| { |
| pViewData->eTextMode = eMode; |
| pModel->InvalidateEntry( pEntry ); |
| AdjustVirtSize( pViewData->aRect ); |
| } |
| } |
| } |
| |
| SvIconViewTextMode SvImpIconView::GetTextMode( const SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) const |
| { |
| if( !pEntry ) |
| return eTextMode; |
| else |
| { |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry)); |
| return pViewData->GetTextMode(); |
| } |
| } |
| |
| SvIconViewTextMode SvImpIconView::GetEntryTextModeSmart( const SvLBoxEntry* pEntry, |
| const SvIcnVwDataEntry* pViewData ) const |
| { |
| DBG_ASSERT(pEntry,"GetEntryTextModeSmart: Entry not set"); |
| if( !pViewData ) |
| pViewData = ICNVIEWDATA(((SvLBoxEntry*)pEntry)); |
| SvIconViewTextMode eMode = pViewData->GetTextMode(); |
| if( eMode == ShowTextDontKnow ) |
| return eTextMode; |
| return eMode; |
| } |
| |
| void SvImpIconView::ShowFocusRect( const SvLBoxEntry* pEntry ) |
| { |
| if( !pEntry ) |
| pView->HideFocus(); |
| else |
| { |
| Rectangle aRect ( CalcFocusRect( (SvLBoxEntry*)pEntry ) ); |
| pView->ShowFocus( aRect ); |
| } |
| } |
| |
| IMPL_LINK(SvImpIconView, UserEventHdl, void*, EMPTYARG ) |
| { |
| nCurUserEvent = 0; |
| AdjustScrollBars(); |
| Rectangle aRect; |
| if( GetResizeRect(aRect) ) |
| PaintResizeRect( aRect ); |
| return 0; |
| } |
| |
| void SvImpIconView::CancelUserEvent() |
| { |
| if( nCurUserEvent ) |
| { |
| Application::RemoveUserEvent( nCurUserEvent ); |
| nCurUserEvent = 0; |
| } |
| } |
| |
| |