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