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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sc.hxx" 24 25 // INCLUDE --------------------------------------------------------------- 26 27 #include <sfx2/dispatch.hxx> 28 #include <vcl/help.hxx> 29 #include <tools/poly.hxx> 30 #include <svtools/colorcfg.hxx> 31 32 #include "scresid.hxx" 33 #include "sc.hrc" 34 #include "tabvwsh.hxx" 35 #include "hdrcont.hxx" 36 #include "scmod.hxx" // Optionen 37 #include "inputopt.hxx" // Optionen 38 #include "gridmerg.hxx" 39 #include "document.hxx" 40 41 // ----------------------------------------------------------------------- 42 43 #define SC_DRAG_MIN 2 44 45 // passes in paint 46 // (selection left/right must be first because the continuous lines 47 // are partly overwritten later) 48 49 #define SC_HDRPAINT_SEL_RIGHT 0 50 #define SC_HDRPAINT_SEL_LEFT 1 51 #define SC_HDRPAINT_TOP 2 52 #define SC_HDRPAINT_SEL_TOP 3 53 #define SC_HDRPAINT_SEL_BOTTOM 4 54 #define SC_HDRPAINT_BOTTOM 5 55 #define SC_HDRPAINT_TEXT 6 56 #define SC_HDRPAINT_COUNT 7 57 58 //================================================================== 59 60 ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEngine, 61 SCCOLROW nNewSize, sal_uInt16 nNewFlags ) : 62 Window ( pParent ), 63 pSelEngine ( pSelectionEngine ), 64 nFlags ( nNewFlags ), 65 bVertical ( (nNewFlags & HDR_VERTICAL) != 0 ), 66 nSize ( nNewSize ), 67 nMarkStart ( 0 ), 68 nMarkEnd ( 0 ), 69 bMarkRange ( sal_False ), 70 bDragging ( sal_False ), 71 bIgnoreMove ( sal_False ) 72 { 73 // --- RTL --- no default mirroring for this window, the spreadsheet itself 74 // is also not mirrored 75 // #107811# mirror the vertical window for correct border drawing 76 // #106948# table layout depends on sheet format, not UI setting, so the 77 // borders of the vertical window have to be handled manually, too. 78 EnableRTL( sal_False ); 79 80 aNormFont = GetFont(); 81 aNormFont.SetTransparent( sal_True ); //! WEIGHT_NORMAL hart setzen ??? 82 aBoldFont = aNormFont; 83 aBoldFont.SetWeight( WEIGHT_BOLD ); 84 85 SetFont(aBoldFont); 86 bBoldSet = sal_True; 87 88 Size aSize = LogicToPixel( Size( 89 GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888")) ), 90 GetTextHeight() ) ); 91 aSize.Width() += 4; // Platz fuer hervorgehobene Umrandung 92 aSize.Height() += 3; 93 SetSizePixel( aSize ); 94 95 nWidth = nSmallWidth = aSize.Width(); 96 nBigWidth = LogicToPixel( Size( GetTextWidth( 97 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5; 98 99 SetBackground(); // sonst Probleme auf OS/2 !?!?! 100 } 101 102 void ScHeaderControl::SetWidth( long nNew ) 103 { 104 DBG_ASSERT( bVertical, "SetDigits nur fuer Zeilenkoepfe erlaubt" ); 105 if ( nNew != nWidth ) 106 { 107 Size aSize( nNew, GetSizePixel().Height() ); // Hoehe nicht aendern 108 SetSizePixel( aSize ); 109 110 nWidth = nNew; 111 112 Invalidate(); // neu zentrieren 113 } 114 } 115 116 ScHeaderControl::~ScHeaderControl() 117 { 118 } 119 120 void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd ) 121 { 122 sal_Bool bLayoutRTL = IsLayoutRTL(); 123 long nLayoutSign = bLayoutRTL ? -1 : 1; 124 125 Rectangle aRect( Point(0,0), GetOutputSizePixel() ); 126 if ( bVertical ) 127 { 128 aRect.Top() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line at top of selection 129 aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign; 130 } 131 else 132 { 133 aRect.Left() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line left of selection 134 aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign; 135 } 136 Invalidate(aRect); 137 } 138 139 void ScHeaderControl::SetMark( sal_Bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd ) 140 { 141 sal_Bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader(); //! cachen? 142 if (!bEnabled) 143 bNewSet = sal_False; 144 145 // Variablen setzen 146 147 sal_Bool bOldSet = bMarkRange; 148 SCCOLROW nOldStart = nMarkStart; 149 SCCOLROW nOldEnd = nMarkEnd; 150 PutInOrder( nNewStart, nNewEnd ); 151 bMarkRange = bNewSet; 152 nMarkStart = nNewStart; 153 nMarkEnd = nNewEnd; 154 155 // Paint 156 157 if ( bNewSet ) 158 { 159 if ( bOldSet ) 160 { 161 if ( nNewStart == nOldStart ) 162 { 163 if ( nNewEnd != nOldEnd ) 164 DoPaint( Min( nNewEnd, nOldEnd ) + 1, Max( nNewEnd, nOldEnd ) ); 165 // sonst nix 166 } 167 else if ( nNewEnd == nOldEnd ) 168 DoPaint( Min( nNewStart, nOldStart ), Max( nNewStart, nOldStart ) - 1 ); 169 else if ( nNewStart > nOldEnd || nNewEnd < nOldStart ) 170 { 171 // zwei Bereiche... 172 DoPaint( nOldStart, nOldEnd ); 173 DoPaint( nNewStart, nNewEnd ); 174 } 175 else // irgendwie ueberlappend... (kommt eh nicht oft vor) 176 DoPaint( Min( nNewStart, nOldStart ), Max( nNewEnd, nOldEnd ) ); 177 } 178 else 179 DoPaint( nNewStart, nNewEnd ); // komplett neu 180 } 181 else if ( bOldSet ) 182 DoPaint( nOldStart, nOldEnd ); // komplett aufheben 183 184 // sonst war nix, is nix 185 } 186 187 long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo ) 188 { 189 long nScrPos; 190 191 long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1; 192 if (nEntryNo >= nSize) 193 nScrPos = nMax; 194 else 195 { 196 nScrPos = 0; 197 for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++) 198 { 199 sal_uInt16 nAdd = GetEntrySize(i); 200 if (nAdd) 201 nScrPos += nAdd; 202 else 203 { 204 SCCOLROW nHidden = GetHiddenCount(i); 205 if (nHidden > 0) 206 i += nHidden - 1; 207 } 208 } 209 } 210 211 if ( IsLayoutRTL() ) 212 nScrPos = nMax - nScrPos - 2; 213 214 return nScrPos; 215 } 216 217 // Paint 218 219 void ScHeaderControl::Paint( const Rectangle& rRect ) 220 { 221 // fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren 222 // Linien zusammengefasst 223 224 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 225 sal_Bool bHighContrast = rStyleSettings.GetHighContrastMode(); 226 sal_Bool bDark = rStyleSettings.GetFaceColor().IsDark(); 227 // Use the same distinction for bDark as in Window::DrawSelectionBackground 228 229 Color aTextColor = rStyleSettings.GetButtonTextColor(); 230 Color aSelTextColor = rStyleSettings.GetHighlightTextColor(); 231 aNormFont.SetColor( aTextColor ); 232 if ( bHighContrast ) 233 aBoldFont.SetColor( aTextColor ); 234 else 235 aBoldFont.SetColor( aSelTextColor ); 236 SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor ); 237 238 Color aBlack( COL_BLACK ); 239 Color aSelLineColor = rStyleSettings.GetHighlightColor(); 240 aSelLineColor.Merge( aBlack, 0xe0 ); // darken just a little bit 241 242 sal_Bool bLayoutRTL = IsLayoutRTL(); 243 long nLayoutSign = bLayoutRTL ? -1 : 1; 244 sal_Bool bMirrored = IsMirrored(); 245 246 // const FunctionSet* pFuncSet = pSelEngine->GetFunctionSet(); 247 String aString; 248 sal_uInt16 nBarSize; 249 Point aScrPos; 250 Size aTextSize; 251 // Size aSize = GetOutputSizePixel(); 252 253 if (bVertical) 254 nBarSize = (sal_uInt16) GetSizePixel().Width(); 255 else 256 nBarSize = (sal_uInt16) GetSizePixel().Height(); 257 258 SCCOLROW nPos = GetPos(); 259 260 long nPStart = bVertical ? rRect.Top() : rRect.Left(); 261 long nPEnd = bVertical ? rRect.Bottom() : rRect.Right(); 262 263 long nTransStart = nPEnd + 1; 264 long nTransEnd = 0; 265 266 long nInitScrPos = 0; 267 if ( bLayoutRTL ) 268 { 269 long nTemp = nPStart; // swap nPStart / nPEnd 270 nPStart = nPEnd; 271 nPEnd = nTemp; 272 nTemp = nTransStart; // swap nTransStart / nTransEnd 273 nTransStart = nTransEnd; 274 nTransEnd = nTemp; 275 if ( bVertical ) // start loops from the end 276 nInitScrPos = GetSizePixel().Height() - 1; 277 else 278 nInitScrPos = GetSizePixel().Width() - 1; 279 } 280 281 // aeussere Linien komplett durchzeichnen 282 // Zuerst Ende der letzten Zelle finden 283 284 // long nLineEnd = -1; 285 long nLineEnd = nInitScrPos - nLayoutSign; 286 287 for (SCCOLROW i=nPos; i<nSize; i++) 288 { 289 sal_uInt16 nSizePix = GetEntrySize( i ); 290 if (nSizePix) 291 { 292 nLineEnd += nSizePix * nLayoutSign; 293 294 if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd ) 295 { 296 long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign; 297 if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign ) 298 nTransStart = nLineStart; 299 if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign ) 300 nTransEnd = nLineEnd; 301 } 302 303 if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign ) 304 { 305 nLineEnd = nPEnd; 306 break; 307 } 308 } 309 else 310 { 311 SCCOLROW nHidden = GetHiddenCount(i); 312 if (nHidden > 0) 313 i += nHidden - 1; 314 } 315 } 316 317 // background is different for entry area and behind the entries 318 319 Rectangle aFillRect; 320 SetLineColor(); 321 322 if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign ) 323 { 324 SetFillColor( rStyleSettings.GetFaceColor() ); 325 if ( bVertical ) 326 aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd ); 327 else 328 aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 ); 329 DrawRect( aFillRect ); 330 } 331 332 if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign ) 333 { 334 SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor ); 335 if ( bVertical ) 336 aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd ); 337 else 338 aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 ); 339 DrawRect( aFillRect ); 340 } 341 342 if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign ) 343 { 344 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign ) 345 { 346 if ( bHighContrast ) 347 { 348 if ( bDark ) 349 { 350 // solid gray background for dark face color is drawn before lines 351 SetLineColor(); 352 SetFillColor( COL_LIGHTGRAY ); 353 if (bVertical) 354 DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) ); 355 else 356 DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) ); 357 } 358 } 359 else 360 { 361 // background for selection 362 SetLineColor(); 363 SetFillColor( rStyleSettings.GetHighlightColor() ); 364 if (bVertical) 365 DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) ); 366 else 367 DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) ); 368 } 369 } 370 371 #if 0 372 // 3D border is no longer used 373 SetLineColor( rStyleSettings.GetLightColor() ); 374 if (bVertical) 375 DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) ); 376 else 377 DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) ); 378 #endif 379 380 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 381 if (bVertical) 382 { 383 long nDarkPos = bMirrored ? 0 : nBarSize-1; 384 DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) ); 385 } 386 else 387 DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) ); 388 389 // line in different color for selection 390 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast ) 391 { 392 SetLineColor( aSelLineColor ); 393 if (bVertical) 394 { 395 long nDarkPos = bMirrored ? 0 : nBarSize-1; 396 DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) ); 397 } 398 else 399 DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) ); 400 } 401 } 402 403 // loop through entries several times to avoid changing the line color too often 404 // and to allow merging of lines 405 406 ScGridMerger aGrid( this, 1, 1 ); 407 408 // start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different 409 // borders, light border at top isn't used anymore 410 // use SC_HDRPAINT_SEL_BOTTOM for different color 411 412 for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++) 413 { 414 // set line color etc. before entry loop 415 switch ( nPass ) 416 { 417 case SC_HDRPAINT_SEL_BOTTOM: 418 // same as non-selected for high contrast 419 SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor ); 420 break; 421 case SC_HDRPAINT_BOTTOM: 422 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 423 break; 424 case SC_HDRPAINT_TEXT: 425 // DrawSelectionBackground is used only for high contrast on light background 426 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark ) 427 { 428 // Transparent selection background is drawn after lines, before text. 429 // #109814# Use DrawSelectionBackground to make sure there is a visible 430 // difference. The case of a dark face color, where DrawSelectionBackground 431 // would just paint over the lines, is handled separately (bDark). 432 // Otherwise, GetHighlightColor is used with 80% transparency. 433 // The window's background color (SetBackground) has to be the background 434 // of the cell area, for the contrast comparison in DrawSelectionBackground. 435 436 Rectangle aTransRect; 437 if (bVertical) 438 aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ); 439 else 440 aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ); 441 SetBackground( Color( rStyleSettings.GetFaceColor() ) ); 442 DrawSelectionBackground( aTransRect, 0, sal_True, sal_False, sal_False ); 443 SetBackground(); 444 } 445 break; 446 } 447 448 SCCOLROW nCount=0; 449 long nScrPos=nInitScrPos; 450 do 451 { 452 if (bVertical) 453 aScrPos = Point( 0, nScrPos ); 454 else 455 aScrPos = Point( nScrPos, 0 ); 456 457 SCCOLROW nEntryNo = nCount + nPos; 458 if ( nEntryNo >= nSize ) // MAXCOL/MAXROW 459 nScrPos = nPEnd + nLayoutSign; // beyond nPEnd -> stop 460 else 461 { 462 sal_uInt16 nSizePix = GetEntrySize( nEntryNo ); 463 464 if (nSizePix == 0) 465 { 466 SCCOLROW nHidden = GetHiddenCount(nEntryNo); 467 if (nHidden > 0) 468 nCount += nHidden - 1; 469 } 470 else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign) 471 { 472 Point aEndPos(aScrPos); 473 if (bVertical) 474 aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign ); 475 else 476 aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 ); 477 478 sal_Bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd; 479 sal_Bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd; 480 481 switch ( nPass ) 482 { 483 case SC_HDRPAINT_SEL_BOTTOM: 484 case SC_HDRPAINT_BOTTOM: 485 if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) ) 486 { 487 if (bVertical) 488 aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() ); 489 else 490 aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() ); 491 492 // thick bottom for hidden rows 493 // (drawn directly, without aGrid) 494 if ( nEntryNo+1 < nSize ) 495 if ( GetEntrySize(nEntryNo+1)==0 ) 496 { 497 if (bVertical) 498 DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign), 499 Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) ); 500 else 501 DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()), 502 Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) ); 503 } 504 } 505 break; 506 507 case SC_HDRPAINT_TEXT: 508 if ( nSizePix > 1 ) // minimal check for small columns/rows 509 { 510 if ( bMark != bBoldSet ) 511 { 512 if (bMark) 513 SetFont(aBoldFont); 514 else 515 SetFont(aNormFont); 516 bBoldSet = bMark; 517 } 518 aString = GetEntryText( nEntryNo ); 519 aTextSize.Width() = GetTextWidth( aString ); 520 aTextSize.Height() = GetTextHeight(); 521 522 Point aTxtPos(aScrPos); 523 if (bVertical) 524 { 525 aTxtPos.X() += (nBarSize-aTextSize.Width())/2; 526 aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2; 527 if ( bMirrored ) 528 aTxtPos.X() += 1; // dark border is left instead of right 529 } 530 else 531 { 532 aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2; 533 aTxtPos.Y() += (nBarSize-aTextSize.Height())/2; 534 } 535 DrawText( aTxtPos, aString ); 536 } 537 break; 538 } 539 540 // bei Selektion der ganzen Zeile/Spalte: 541 // InvertRect( Rectangle( aScrPos, aEndPos ) ); 542 } 543 nScrPos += nSizePix * nLayoutSign; // also if before the visible area 544 } 545 ++nCount; 546 } 547 while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign ); 548 549 aGrid.Flush(); 550 } 551 } 552 553 // 554 // Maus - Handling 555 // 556 557 SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, sal_Bool& rBorder ) 558 { 559 sal_Bool bFound=sal_False; 560 SCCOLROW nCount = 1; 561 SCCOLROW nPos = GetPos(); 562 SCCOLROW nHitNo = nPos; 563 long nScrPos; 564 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); 565 long nDif; 566 Size aSize = GetOutputSizePixel(); 567 long nWinSize = bVertical ? aSize.Height() : aSize.Width(); 568 569 sal_Bool bLayoutRTL = IsLayoutRTL(); 570 long nLayoutSign = bLayoutRTL ? -1 : 1; 571 long nEndPos = bLayoutRTL ? -1 : nWinSize; 572 573 nScrPos = GetScrPos( nPos ) - nLayoutSign; 574 do 575 { 576 SCCOLROW nEntryNo = nCount + nPos; 577 578 // nScrPos = GetScrPos( nEntryNo ) - 1; 579 580 if (nEntryNo > nSize) 581 nScrPos = nEndPos + nLayoutSign; 582 else 583 nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign; //! GetHiddenCount() ?? 584 585 nDif = nMousePos - nScrPos; 586 if (nDif >= -2 && nDif <= 2 && nCount > 0) 587 { 588 bFound=sal_True; 589 nHitNo=nEntryNo-1; 590 } 591 else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize) 592 nHitNo = nEntryNo; 593 ++nCount; 594 } 595 while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 ); 596 597 rBorder = bFound; 598 return nHitNo; 599 } 600 601 bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const 602 { 603 ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); 604 if (!pViewSh) 605 return false; 606 607 ScViewData* pViewData = pViewSh->GetViewData(); 608 sal_uInt16 nTab = pViewData->GetTabNo(); 609 ScDocument* pDoc = pViewData->GetDocument(); 610 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 611 bool bSelectAllowed = true; 612 if ( pProtect && pProtect->isProtected() ) 613 { 614 // This sheet is protected. Check if a context menu is allowed on this cell. 615 bool bCellsProtected = false; 616 if (bVertical) 617 { 618 // row header 619 SCROW nRPos = static_cast<SCROW>(nPos); 620 bCellsProtected = pDoc->HasAttrib(0, nRPos, nTab, MAXCOL, nRPos, nTab, HASATTR_PROTECTED); 621 } 622 else 623 { 624 // column header 625 SCCOL nCPos = static_cast<SCCOL>(nPos); 626 bCellsProtected = pDoc->HasAttrib(nCPos, 0, nTab, nCPos, MAXROW, nTab, HASATTR_PROTECTED); 627 } 628 629 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); 630 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); 631 632 if (bCellsProtected) 633 bSelectAllowed = bSelProtected; 634 else 635 bSelectAllowed = bSelUnprotected; 636 } 637 return bSelectAllowed; 638 } 639 640 void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt ) 641 { 642 if (IsDisabled()) 643 return; 644 645 bIgnoreMove = sal_False; 646 SelectWindow(); 647 648 sal_Bool bFound; 649 SCCOLROW nHitNo = GetMousePos( rMEvt, bFound ); 650 if (!IsSelectionAllowed(nHitNo)) 651 return; 652 653 if ( bFound && rMEvt.IsLeft() && ResizeAllowed() ) 654 { 655 nDragNo = nHitNo; 656 sal_uInt16 nClicks = rMEvt.GetClicks(); 657 if ( nClicks && nClicks%2==0 ) 658 { 659 SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM ); 660 SetPointer( Pointer( POINTER_ARROW ) ); 661 } 662 else 663 { 664 if (bVertical) 665 nDragStart = rMEvt.GetPosPixel().Y(); 666 else 667 nDragStart = rMEvt.GetPosPixel().X(); 668 nDragPos = nDragStart; 669 ShowDragHelp(); 670 DrawInvert( nDragPos ); 671 672 // CaptureMouse(); 673 StartTracking(); 674 bDragging = sal_True; 675 bDragMoved = sal_False; 676 } 677 } 678 else if (rMEvt.IsLeft()) 679 { 680 pSelEngine->SetWindow( this ); 681 Point aPoint; 682 Rectangle aVis( aPoint,GetOutputSizePixel() ); 683 if (bVertical) 684 aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX; 685 else 686 aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX; 687 pSelEngine->SetVisibleArea( aVis ); 688 689 SetMarking( sal_True ); // muss vor SelMouseButtonDown sein 690 pSelEngine->SelMouseButtonDown( rMEvt ); 691 692 // #74215# In column/row headers a simple click already is a selection. 693 // -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor 694 // if the next click is somewhere else with Control key). 695 pSelEngine->SelMouseMove( rMEvt ); 696 697 if (IsMouseCaptured()) 698 { 699 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann 700 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! 701 ReleaseMouse(); 702 StartTracking(); 703 } 704 } 705 } 706 707 void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt ) 708 { 709 if ( IsDisabled() ) 710 return; 711 712 SetMarking( sal_False ); 713 bIgnoreMove = sal_False; 714 // sal_Bool bFound; 715 // SCCOLROW nHitNo = GetMousePos( rMEvt, bFound ); 716 717 if ( bDragging ) 718 { 719 DrawInvert( nDragPos ); 720 ReleaseMouse(); 721 bDragging = sal_False; 722 723 long nScrPos = GetScrPos( nDragNo ); 724 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); 725 sal_Bool bLayoutRTL = IsLayoutRTL(); 726 long nNewWidth = bLayoutRTL ? ( nScrPos - nMousePos + 1 ) 727 : ( nMousePos + 2 - nScrPos ); 728 729 if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ ) 730 { 731 SCCOLROW nStart = 0; 732 SCCOLROW nEnd = nDragNo; 733 while (nNewWidth < 0) 734 { 735 nStart = nDragNo; 736 if (nDragNo>0) 737 { 738 --nDragNo; 739 nNewWidth += GetEntrySize( nDragNo ); //! GetHiddenCount() ??? 740 } 741 else 742 nNewWidth = 0; 743 } 744 HideEntries( nStart, nEnd ); 745 } 746 else 747 { 748 if (nNewWidth<0) nNewWidth=0; 749 if (bDragMoved) 750 SetEntrySize( nDragNo, (sal_uInt16) nNewWidth ); 751 } 752 } 753 else 754 { 755 pSelEngine->SelMouseButtonUp( rMEvt ); 756 ReleaseMouse(); 757 } 758 } 759 760 void ScHeaderControl::MouseMove( const MouseEvent& rMEvt ) 761 { 762 if ( IsDisabled() ) 763 { 764 SetPointer( Pointer( POINTER_ARROW ) ); 765 return; 766 } 767 768 sal_Bool bFound; 769 (void)GetMousePos( rMEvt, bFound ); 770 771 if ( bDragging ) 772 { 773 long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); 774 if ( nNewPos != nDragPos ) 775 { 776 DrawInvert( nDragPos ); 777 nDragPos = nNewPos; 778 ShowDragHelp(); 779 DrawInvert( nDragPos ); 780 781 if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN) 782 bDragMoved = sal_True; 783 } 784 } 785 else 786 { 787 if ( bFound && rMEvt.GetButtons()==0 && ResizeAllowed() ) 788 SetPointer( Pointer( bVertical ? POINTER_VSIZEBAR : POINTER_HSIZEBAR ) ); 789 else 790 SetPointer( Pointer( POINTER_ARROW ) ); 791 792 if (!bIgnoreMove) 793 pSelEngine->SelMouseMove( rMEvt ); 794 } 795 } 796 797 void ScHeaderControl::Tracking( const TrackingEvent& rTEvt ) 798 { 799 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf 800 // die verschiedenen MouseHandler verteilen... 801 802 if ( rTEvt.IsTrackingCanceled() ) 803 StopMarking(); 804 else if ( rTEvt.IsTrackingEnded() ) 805 MouseButtonUp( rTEvt.GetMouseEvent() ); 806 else 807 MouseMove( rTEvt.GetMouseEvent() ); 808 } 809 810 void ScHeaderControl::Command( const CommandEvent& rCEvt ) 811 { 812 sal_uInt16 nCmd = rCEvt.GetCommand(); 813 if ( nCmd == COMMAND_CONTEXTMENU ) 814 { 815 StopMarking(); // Selektion / Dragging beenden 816 817 // Popup ausfuehren 818 819 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, 820 SfxViewShell::Current() ); 821 if ( pViewSh ) 822 { 823 if ( rCEvt.IsMouseEvent() ) 824 { 825 // #i18735# select the column/row under the mouse pointer 826 ScViewData* pViewData = pViewSh->GetViewData(); 827 828 SelectWindow(); // also deselects drawing objects, stops draw text edit 829 if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) 830 SC_MOD()->InputEnterHandler(); // always end edit mode 831 832 MouseEvent aMEvt( rCEvt.GetMousePosPixel() ); 833 sal_Bool bBorder; 834 SCCOLROW nPos = GetMousePos( aMEvt, bBorder ); 835 if (!IsSelectionAllowed(nPos)) 836 // Selecting this cell is not allowed, neither is context menu. 837 return; 838 839 SCTAB nTab = pViewData->GetTabNo(); 840 ScRange aNewRange; 841 if ( bVertical ) 842 aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab, 843 MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab ); 844 else 845 aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab, 846 sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab ); 847 848 // see if any part of the range is already selected 849 sal_Bool bSelected = sal_False; 850 ScRangeList aRanges; 851 pViewData->GetMarkData().FillRangeListWithMarks( &aRanges, sal_False ); 852 sal_uLong nRangeCount = aRanges.Count(); 853 for (sal_uLong i=0; i<nRangeCount && !bSelected; i++) 854 if ( aRanges.GetObject(i)->Intersects( aNewRange ) ) 855 bSelected = sal_True; 856 857 // select the range if no part of it was selected 858 if ( !bSelected ) 859 pViewSh->MarkRange( aNewRange ); 860 } 861 862 ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER ); 863 pViewSh->GetDispatcher()->ExecutePopup( aResId ); 864 } 865 } 866 else if ( nCmd == COMMAND_STARTDRAG ) 867 { 868 pSelEngine->Command( rCEvt ); 869 } 870 } 871 872 void ScHeaderControl::StopMarking() 873 { 874 if ( bDragging ) 875 { 876 DrawInvert( nDragPos ); 877 bDragging = sal_False; 878 } 879 880 SetMarking( sal_False ); 881 bIgnoreMove = sal_True; 882 883 // #86260# don't call pSelEngine->Reset, so selection across the parts of 884 // a split/frozen view is possible 885 886 ReleaseMouse(); 887 } 888 889 void ScHeaderControl::ShowDragHelp() 890 { 891 if (Help::IsQuickHelpEnabled()) 892 { 893 long nScrPos = GetScrPos( nDragNo ); 894 sal_Bool bLayoutRTL = IsLayoutRTL(); 895 long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 ) 896 : ( nDragPos + 2 - nScrPos ); 897 898 String aHelpStr = GetDragHelp( nVal ); 899 Point aPos = OutputToScreenPixel( Point(0,0) ); 900 Size aSize = GetSizePixel(); 901 902 Point aMousePos = OutputToScreenPixel(GetPointerPosPixel()); 903 904 Rectangle aRect; 905 sal_uInt16 nAlign; 906 if (!bVertical) 907 { 908 // oberhalb 909 aRect.Left() = aMousePos.X(); 910 aRect.Top() = aPos.Y() - 4; 911 nAlign = QUICKHELP_BOTTOM|QUICKHELP_CENTER; 912 } 913 else 914 { 915 // rechts oben 916 aRect.Left() = aPos.X() + aSize.Width() + 8; 917 aRect.Top() = aMousePos.Y() - 2; 918 nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM; 919 } 920 921 aRect.Right() = aRect.Left(); 922 aRect.Bottom() = aRect.Top(); 923 924 Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign); 925 } 926 } 927 928 void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt ) 929 { 930 // Wenn eigene QuickHelp angezeigt wird, nicht durch RequestHelp 931 // wieder wegnehmen lassen 932 933 sal_Bool bOwn = bDragging && Help::IsQuickHelpEnabled(); 934 if (!bOwn) 935 Window::RequestHelp(rHEvt); 936 } 937 938 // ----------------------------------------------------------------------- 939 // Dummys fuer virtuelle Methoden 940 // ----------------------------------------------------------------------- 941 942 SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo ) 943 { 944 SCCOLROW nHidden = 0; 945 while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 ) 946 { 947 ++nEntryNo; 948 ++nHidden; 949 } 950 return nHidden; 951 } 952 953 sal_Bool ScHeaderControl::IsLayoutRTL() 954 { 955 return sal_False; 956 } 957 958 sal_Bool ScHeaderControl::IsMirrored() 959 { 960 return sal_False; 961 } 962 963 sal_Bool ScHeaderControl::IsDisabled() 964 { 965 return sal_False; 966 } 967 968 sal_Bool ScHeaderControl::ResizeAllowed() 969 { 970 return sal_True; 971 } 972 973 void ScHeaderControl::SelectWindow() 974 { 975 } 976 977 void ScHeaderControl::DrawInvert( long /* nDragPos */ ) 978 { 979 } 980 981 String ScHeaderControl::GetDragHelp( long /* nVal */ ) 982 { 983 return EMPTY_STRING; 984 } 985 986 void ScHeaderControl::SetMarking( sal_Bool /* bSet */ ) 987 { 988 } 989 990 /* vim: set noet sw=4 ts=4: */ 991