1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 // INCLUDE --------------------------------------------------------------- 34 35 #include <tools/urlobj.hxx> 36 #include <vcl/sound.hxx> 37 #include <sfx2/docfile.hxx> 38 39 #include "select.hxx" 40 #include "sc.hrc" 41 #include "tabvwsh.hxx" 42 #include "scmod.hxx" 43 #include "document.hxx" 44 //#include "dataobj.hxx" 45 #include "transobj.hxx" 46 #include "docsh.hxx" 47 #include "tabprotection.hxx" 48 49 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx 50 51 using namespace com::sun::star; 52 53 // STATIC DATA ----------------------------------------------------------- 54 55 static Point aSwitchPos; //! Member 56 static sal_Bool bDidSwitch = sal_False; 57 58 // ----------------------------------------------------------------------- 59 60 // 61 // View (Gridwin / Tastatur) 62 // 63 64 ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) : 65 pViewData( pNewViewData ), 66 pEngine( NULL ), 67 bAnchor( sal_False ), 68 bStarted( sal_False ) 69 { 70 DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet"); 71 } 72 73 ScSplitPos ScViewFunctionSet::GetWhich() 74 { 75 if (pEngine) 76 return pEngine->GetWhich(); 77 else 78 return pViewData->GetActivePart(); 79 } 80 81 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine ) 82 { 83 pEngine = pSelEngine; 84 } 85 86 // Drag & Drop 87 88 void __EXPORT ScViewFunctionSet::BeginDrag() 89 { 90 SCTAB nTab = pViewData->GetTabNo(); 91 92 SCsCOL nPosX; 93 SCsROW nPosY; 94 if (pEngine) 95 { 96 Point aMPos = pEngine->GetMousePosPixel(); 97 pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY ); 98 } 99 else 100 { 101 nPosX = pViewData->GetCurX(); 102 nPosY = pViewData->GetCurY(); 103 } 104 105 ScModule* pScMod = SC_MOD(); 106 sal_Bool bRefMode = pScMod->IsFormulaMode(); 107 if (!bRefMode) 108 { 109 pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp wird verschluckt 110 111 ScMarkData& rMark = pViewData->GetMarkData(); 112 // rMark.SetMarking(sal_False); // es fehlt ein ButtonUp 113 rMark.MarkToSimple(); 114 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 115 { 116 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); 117 // bApi = sal_True -> no error mesages 118 sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True ); 119 if ( bCopied ) 120 { 121 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ? 122 ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) : 123 ( DND_ACTION_COPY | DND_ACTION_LINK ); 124 125 ScDocShell* pDocSh = pViewData->GetDocShell(); 126 TransferableObjectDescriptor aObjDesc; 127 pDocSh->FillTransferableObjectDescriptor( aObjDesc ); 128 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); 129 // maSize is set in ScTransferObj ctor 130 131 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); 132 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); 133 134 // set position of dragged cell within range 135 ScRange aMarkRange = pTransferObj->GetRange(); 136 SCCOL nStartX = aMarkRange.aStart.Col(); 137 SCROW nStartY = aMarkRange.aStart.Row(); 138 SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0; 139 SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0; 140 pTransferObj->SetDragHandlePos( nHandleX, nHandleY ); 141 pTransferObj->SetVisibleTab( nTab ); 142 143 pTransferObj->SetDragSource( pDocSh, rMark ); 144 145 Window* pWindow = pViewData->GetActiveWin(); 146 if ( pWindow->IsTracking() ) 147 pWindow->EndTracking( ENDTRACK_CANCEL ); // abort selecting 148 149 SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D 150 pTransferObj->StartDrag( pWindow, nDragActions ); 151 152 return; // dragging started 153 } 154 else 155 delete pClipDoc; 156 } 157 } 158 159 Sound::Beep(); // can't drag 160 } 161 162 // Selektion 163 164 void __EXPORT ScViewFunctionSet::CreateAnchor() 165 { 166 if (bAnchor) return; 167 168 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 169 if (bRefMode) 170 SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() ); 171 else 172 SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() ); 173 } 174 175 void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY ) 176 { 177 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 178 ScTabView* pView = pViewData->GetView(); 179 SCTAB nTab = pViewData->GetTabNo(); 180 181 if (bRefMode) 182 { 183 pView->DoneRefMode( sal_False ); 184 aAnchorPos.Set( nPosX, nPosY, nTab ); 185 pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(), 186 SC_REFTYPE_REF ); 187 bStarted = sal_True; 188 } 189 else if (pViewData->IsAnyFillMode()) 190 { 191 aAnchorPos.Set( nPosX, nPosY, nTab ); 192 bStarted = sal_True; 193 } 194 else 195 { 196 // nicht weg und gleich wieder hin 197 if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) ) 198 { 199 // nix 200 } 201 else 202 { 203 pView->DoneBlockMode( sal_True ); 204 aAnchorPos.Set( nPosX, nPosY, nTab ); 205 ScMarkData& rMark = pViewData->GetMarkData(); 206 if ( rMark.IsMarked() || rMark.IsMultiMarked() ) 207 { 208 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(), 209 aAnchorPos.Tab(), sal_True ); 210 bStarted = sal_True; 211 } 212 else 213 bStarted = sal_False; 214 } 215 } 216 bAnchor = sal_True; 217 } 218 219 void __EXPORT ScViewFunctionSet::DestroyAnchor() 220 { 221 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 222 if (bRefMode) 223 pViewData->GetView()->DoneRefMode( sal_True ); 224 else 225 pViewData->GetView()->DoneBlockMode( sal_True ); 226 227 bAnchor = sal_False; 228 } 229 230 void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet ) 231 { 232 bAnchor = bSet; 233 } 234 235 sal_Bool __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ ) 236 { 237 if ( bDidSwitch ) 238 { 239 if ( rPointPixel == aSwitchPos ) 240 return sal_False; // nicht auf falschem Fenster scrollen 241 else 242 bDidSwitch = sal_False; 243 } 244 aSwitchPos = rPointPixel; // nur wichtig, wenn bDidSwitch 245 246 // treat position 0 as -1, so scrolling is always possible 247 // (with full screen and hidden headers, the top left border may be at 0) 248 // (moved from ScViewData::GetPosFromPixel) 249 250 Point aEffPos = rPointPixel; 251 if ( aEffPos.X() == 0 ) 252 aEffPos.X() = -1; 253 if ( aEffPos.Y() == 0 ) 254 aEffPos.Y() = -1; 255 256 // Scrolling 257 258 Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel(); 259 sal_Bool bRightScroll = ( aEffPos.X() >= aWinSize.Width() ); 260 sal_Bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() ); 261 sal_Bool bNegScroll = ( aEffPos.X() < 0 || aEffPos.Y() < 0 ); 262 sal_Bool bScroll = bRightScroll || bBottomScroll || bNegScroll; 263 264 SCsCOL nPosX; 265 SCsROW nPosY; 266 pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(), 267 nPosX, nPosY, sal_True, sal_True ); // mit Repair 268 269 // fuer AutoFill in der Mitte der Zelle umschalten 270 // dabei aber nicht das Scrolling nach rechts/unten verhindern 271 if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX ) 272 { 273 sal_Bool bLeft, bTop; 274 pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop ); 275 ScDocument* pDoc = pViewData->GetDocument(); 276 SCTAB nTab = pViewData->GetTabNo(); 277 if ( bLeft && !bRightScroll ) 278 do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) ); 279 if ( bTop && !bBottomScroll ) 280 { 281 if (--nPosY >= 0) 282 { 283 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab); 284 if (!ValidRow(nPosY)) 285 nPosY = -1; 286 } 287 } 288 // negativ ist erlaubt 289 } 290 291 // ueber Fixier-Grenze bewegt? 292 293 ScSplitPos eWhich = GetWhich(); 294 if ( eWhich == pViewData->GetActivePart() ) 295 { 296 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) 297 if ( aEffPos.X() >= aWinSize.Width() ) 298 { 299 if ( eWhich == SC_SPLIT_TOPLEFT ) 300 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; 301 else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) 302 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; 303 } 304 305 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) 306 if ( aEffPos.Y() >= aWinSize.Height() ) 307 { 308 if ( eWhich == SC_SPLIT_TOPLEFT ) 309 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = sal_False, bDidSwitch = sal_True; 310 else if ( eWhich == SC_SPLIT_TOPRIGHT ) 311 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; 312 } 313 } 314 315 pViewData->ResetOldCursor(); 316 return SetCursorAtCell( nPosX, nPosY, bScroll ); 317 } 318 319 sal_Bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, sal_Bool bScroll ) 320 { 321 ScTabView* pView = pViewData->GetView(); 322 SCTAB nTab = pViewData->GetTabNo(); 323 ScDocument* pDoc = pViewData->GetDocument(); 324 325 if ( pDoc->IsTabProtected(nTab) ) 326 { 327 if (nPosX < 0 || nPosY < 0) 328 return false; 329 330 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 331 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); 332 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); 333 334 if ( bSkipProtected && bSkipUnprotected ) 335 return sal_False; 336 337 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); 338 if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) 339 // Don't select this cell! 340 return sal_False; 341 } 342 343 ScModule* pScMod = SC_MOD(); 344 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 345 bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false ); 346 347 sal_Bool bHide = !bRefMode && !pViewData->IsAnyFillMode() && 348 ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() ); 349 350 if (bHide) 351 pView->HideAllCursors(); 352 353 if (bScroll) 354 { 355 if (bRefMode) 356 { 357 ScSplitPos eWhich = GetWhich(); 358 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich ); 359 } 360 else 361 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE ); 362 } 363 364 if (bRefMode) 365 { 366 // #90910# if no input is possible from this doc, don't move the reference cursor around 367 if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) ) 368 { 369 if (!bAnchor) 370 { 371 pView->DoneRefMode( sal_True ); 372 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF ); 373 } 374 375 pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() ); 376 } 377 } 378 else if (pViewData->IsFillMode() || 379 (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) )) 380 { 381 // Wenn eine Matrix angefasst wurde, kann mit Ctrl auf AutoFill zurueckgeschaltet werden 382 383 SCCOL nStartX, nEndX; 384 SCROW nStartY, nEndY; // Block 385 SCTAB nDummy; 386 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy ); 387 388 if (pViewData->GetRefType() != SC_REFTYPE_FILL) 389 { 390 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); 391 CreateAnchor(); 392 } 393 394 ScRange aDelRange; 395 sal_Bool bOldDelMark = pViewData->GetDelMark( aDelRange ); 396 397 if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX && 398 nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY && 399 ( nPosX != nEndX || nPosY != nEndY ) ) // verkleinern ? 400 { 401 // Richtung (links oder oben) 402 403 long nSizeX = 0; 404 for (SCCOL i=nPosX+1; i<=nEndX; i++) 405 nSizeX += pDoc->GetColWidth( i, nTab ); 406 long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab ); 407 408 SCCOL nDelStartX = nStartX; 409 SCROW nDelStartY = nStartY; 410 if ( nSizeX > nSizeY ) 411 nDelStartX = nPosX + 1; 412 else 413 nDelStartY = nPosY + 1; 414 // 0 braucht nicht mehr getrennt abgefragt zu werden, weil nPosX/Y auch negativ wird 415 416 if ( nDelStartX < nStartX ) 417 nDelStartX = nStartX; 418 if ( nDelStartY < nStartY ) 419 nDelStartY = nStartY; 420 421 // Bereich setzen 422 423 pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab, 424 nEndX,nEndY,nTab ) ); 425 pViewData->GetView()->UpdateShrinkOverlay(); 426 427 #if 0 428 if ( bOldDelMark ) 429 { 430 ScUpdateRect aRect( aDelRange.aStart.Col(), aDelRange.aStart.Row(), 431 aDelRange.aEnd.Col(), aDelRange.aEnd.Row() ); 432 aRect.SetNew( nDelStartX,nDelStartY, nEndX,nEndY ); 433 SCCOL nPaintStartX; 434 SCROW nPaintStartY; 435 SCCOL nPaintEndX; 436 SCROW nPaintEndY; 437 if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY )) 438 pViewData->GetView()-> 439 PaintArea( nPaintStartX, nPaintStartY, 440 nPaintEndX, nPaintEndY, SC_UPDATE_MARKS ); 441 } 442 else 443 #endif 444 pViewData->GetView()-> 445 PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS ); 446 447 nPosX = nEndX; // roten Rahmen um ganzen Bereich lassen 448 nPosY = nEndY; 449 450 // Referenz wieder richtigherum, falls unten umgedreht 451 if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() ) 452 { 453 pViewData->GetView()->DoneRefMode(); 454 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); 455 } 456 } 457 else 458 { 459 if ( bOldDelMark ) 460 { 461 pViewData->ResetDelMark(); 462 pViewData->GetView()->UpdateShrinkOverlay(); 463 464 #if 0 465 pViewData->GetView()-> 466 PaintArea( aDelRange.aStart.Col(), aDelRange.aStart.Row(), 467 aDelRange.aEnd.Col(), aDelRange.aEnd.Row(), SC_UPDATE_MARKS ); 468 #endif 469 } 470 471 sal_Bool bNegX = ( nPosX < (SCsCOL) nStartX ); 472 sal_Bool bNegY = ( nPosY < (SCsROW) nStartY ); 473 474 long nSizeX = 0; 475 if ( bNegX ) 476 { 477 // #94321# in SetCursorAtPoint hidden columns are skipped. 478 // They must be skipped here too, or the result will always be the first hidden column. 479 do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) ); 480 for (SCCOL i=nPosX; i<nStartX; i++) 481 nSizeX += pDoc->GetColWidth( i, nTab ); 482 } 483 else 484 for (SCCOL i=nEndX+1; i<=nPosX; i++) 485 nSizeX += pDoc->GetColWidth( i, nTab ); 486 487 long nSizeY = 0; 488 if ( bNegY ) 489 { 490 // #94321# in SetCursorAtPoint hidden rows are skipped. 491 // They must be skipped here too, or the result will always be the first hidden row. 492 if (++nPosY < nStartY) 493 { 494 nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab); 495 if (!ValidRow(nPosY)) 496 nPosY = nStartY; 497 } 498 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab ); 499 } 500 else 501 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab ); 502 503 if ( nSizeX > nSizeY ) // Fill immer nur in einer Richtung 504 { 505 nPosY = nEndY; 506 bNegY = sal_False; 507 } 508 else 509 { 510 nPosX = nEndX; 511 bNegX = sal_False; 512 } 513 514 SCCOL nRefStX = bNegX ? nEndX : nStartX; 515 SCROW nRefStY = bNegY ? nEndY : nStartY; 516 if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() ) 517 { 518 pViewData->GetView()->DoneRefMode(); 519 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL ); 520 } 521 } 522 523 pView->UpdateRef( nPosX, nPosY, nTab ); 524 } 525 else if (pViewData->IsAnyFillMode()) 526 { 527 sal_uInt8 nMode = pViewData->GetFillMode(); 528 if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB ) 529 { 530 DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" ); 531 ScRange aRange; 532 pDoc->GetEmbedded( aRange); 533 ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB; 534 if (pViewData->GetRefType() != eRefMode) 535 { 536 if ( nMode == SC_FILL_EMBED_LT ) 537 pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode ); 538 else 539 pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode ); 540 CreateAnchor(); 541 } 542 543 pView->UpdateRef( nPosX, nPosY, nTab ); 544 } 545 else if ( nMode == SC_FILL_MATRIX ) 546 { 547 SCCOL nStartX, nEndX; 548 SCROW nStartY, nEndY; // Block 549 SCTAB nDummy; 550 pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy ); 551 552 if (pViewData->GetRefType() != SC_REFTYPE_FILL) 553 { 554 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); 555 CreateAnchor(); 556 } 557 558 if ( nPosX < nStartX ) nPosX = nStartX; 559 if ( nPosY < nStartY ) nPosY = nStartY; 560 561 pView->UpdateRef( nPosX, nPosY, nTab ); 562 } 563 // else neue Modi 564 } 565 else // normales Markieren 566 { 567 sal_Bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() || 568 (SCROW)nPosY != pViewData->GetCurY() ); 569 if (bHideCur) 570 pView->HideAllCursors(); // sonst zweimal: Block und SetCursor 571 572 if (bAnchor) 573 { 574 if (!bStarted) 575 { 576 sal_Bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() || 577 nPosY != (SCsROW) aAnchorPos.Row() ); 578 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) ) 579 { 580 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(), 581 aAnchorPos.Tab(), sal_True ); 582 bStarted = sal_True; 583 } 584 } 585 if (bStarted) 586 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, sal_False, sal_False, sal_True ); 587 } 588 else 589 { 590 ScMarkData& rMark = pViewData->GetMarkData(); 591 if (rMark.IsMarked() || rMark.IsMultiMarked()) 592 { 593 pView->DoneBlockMode(sal_True); 594 pView->InitBlockMode( nPosX, nPosY, nTab, sal_True ); 595 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab ); 596 597 aAnchorPos.Set( nPosX, nPosY, nTab ); 598 bStarted = sal_True; 599 } 600 // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells, 601 // it highlights that new cell as well as the old cell where the cursor is 602 // positioned prior to the click. A selection mode via Shift-F8 should also 603 // follow the same behavior. 604 else if ( pViewData->IsSelCtrlMouseClick() ) 605 { 606 SCCOL nOldX = pViewData->GetCurX(); 607 SCROW nOldY = pViewData->GetCurY(); 608 609 pView->InitBlockMode( nOldX, nOldY, nTab, sal_True ); 610 pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab ); 611 612 if ( nOldX != nPosX || nOldY != nPosY ) 613 { 614 pView->DoneBlockMode( sal_True ); 615 pView->InitBlockMode( nPosX, nPosY, nTab, sal_True ); 616 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab ); 617 aAnchorPos.Set( nPosX, nPosY, nTab ); 618 } 619 620 bStarted = sal_True; 621 } 622 } 623 624 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY ); 625 pViewData->SetRefStart( nPosX, nPosY, nTab ); 626 if (bHideCur) 627 pView->ShowAllCursors(); 628 } 629 630 if (bHide) 631 pView->ShowAllCursors(); 632 633 return sal_True; 634 } 635 636 sal_Bool __EXPORT ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) 637 { 638 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 639 if (bRefMode) 640 return sal_False; 641 642 if (pViewData->IsAnyFillMode()) 643 return sal_False; 644 645 ScMarkData& rMark = pViewData->GetMarkData(); 646 if (bAnchor || !rMark.IsMultiMarked()) 647 { 648 SCsCOL nPosX; 649 SCsROW nPosY; 650 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY ); 651 return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY ); 652 } 653 654 return sal_False; 655 } 656 657 void __EXPORT ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ ) 658 { 659 // gibt's nicht 660 } 661 662 void __EXPORT ScViewFunctionSet::DeselectAll() 663 { 664 if (pViewData->IsAnyFillMode()) 665 return; 666 667 sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); 668 if (bRefMode) 669 { 670 pViewData->GetView()->DoneRefMode( sal_False ); 671 } 672 else 673 { 674 pViewData->GetView()->DoneBlockMode( sal_False ); 675 pViewData->GetViewShell()->UpdateInputHandler(); 676 } 677 678 bAnchor = sal_False; 679 } 680 681 //------------------------------------------------------------------------ 682 683 ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView, 684 ScSplitPos eSplitPos ) : 685 SelectionEngine( pWindow, pView->GetFunctionSet() ), 686 eWhich( eSplitPos ) 687 { 688 // Parameter einstellen 689 SetSelectionMode( MULTIPLE_SELECTION ); 690 EnableDrag( sal_True ); 691 } 692 693 694 //------------------------------------------------------------------------ 695 696 // 697 // Spalten- / Zeilenheader 698 // 699 700 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) : 701 pViewData( pNewViewData ), 702 bColumn( sal_False ), 703 eWhich( SC_SPLIT_TOPLEFT ), 704 bAnchor( sal_False ), 705 nCursorPos( 0 ) 706 { 707 DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet"); 708 } 709 710 void ScHeaderFunctionSet::SetColumn( sal_Bool bSet ) 711 { 712 bColumn = bSet; 713 } 714 715 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew ) 716 { 717 eWhich = eNew; 718 } 719 720 void __EXPORT ScHeaderFunctionSet::BeginDrag() 721 { 722 // gippsnich 723 } 724 725 void __EXPORT ScHeaderFunctionSet::CreateAnchor() 726 { 727 if (bAnchor) 728 return; 729 730 ScTabView* pView = pViewData->GetView(); 731 pView->DoneBlockMode( sal_True ); 732 if (bColumn) 733 { 734 pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), sal_True, sal_True, sal_False ); 735 pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() ); 736 } 737 else 738 { 739 pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), sal_True, sal_False, sal_True ); 740 pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() ); 741 } 742 bAnchor = sal_True; 743 } 744 745 void __EXPORT ScHeaderFunctionSet::DestroyAnchor() 746 { 747 pViewData->GetView()->DoneBlockMode( sal_True ); 748 bAnchor = sal_False; 749 } 750 751 sal_Bool __EXPORT ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ ) 752 { 753 if ( bDidSwitch ) 754 { 755 // die naechste gueltige Position muss vom anderen Fenster kommen 756 if ( rPointPixel == aSwitchPos ) 757 return sal_False; // nicht auf falschem Fenster scrollen 758 else 759 bDidSwitch = sal_False; 760 } 761 762 // Scrolling 763 764 Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel(); 765 sal_Bool bScroll; 766 if (bColumn) 767 bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() ); 768 else 769 bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() ); 770 771 // ueber Fixier-Grenze bewegt? 772 773 sal_Bool bSwitched = sal_False; 774 if ( bColumn ) 775 { 776 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) 777 { 778 if ( rPointPixel.X() > aWinSize.Width() ) 779 { 780 if ( eWhich == SC_SPLIT_TOPLEFT ) 781 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = sal_True; 782 else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) 783 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True; 784 } 785 } 786 } 787 else // Zeilenkoepfe 788 { 789 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) 790 { 791 if ( rPointPixel.Y() > aWinSize.Height() ) 792 { 793 if ( eWhich == SC_SPLIT_TOPLEFT ) 794 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = sal_True; 795 else if ( eWhich == SC_SPLIT_TOPRIGHT ) 796 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True; 797 } 798 } 799 } 800 if (bSwitched) 801 { 802 aSwitchPos = rPointPixel; 803 bDidSwitch = sal_True; 804 return sal_False; // nicht mit falschen Positionen rechnen 805 } 806 807 // 808 809 SCsCOL nPosX; 810 SCsROW nPosY; 811 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(), 812 nPosX, nPosY, sal_False ); 813 if (bColumn) 814 { 815 nCursorPos = static_cast<SCCOLROW>(nPosX); 816 nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart())); 817 } 818 else 819 { 820 nCursorPos = static_cast<SCCOLROW>(nPosY); 821 nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart())); 822 } 823 824 ScTabView* pView = pViewData->GetView(); 825 sal_Bool bHide = pViewData->GetCurX() != nPosX || 826 pViewData->GetCurY() != nPosY; 827 if (bHide) 828 pView->HideAllCursors(); 829 830 if (bScroll) 831 pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE ); 832 pView->SetCursor( nPosX, nPosY ); 833 834 if ( !bAnchor || !pView->IsBlockMode() ) 835 { 836 pView->DoneBlockMode( sal_True ); 837 pViewData->GetMarkData().MarkToMulti(); //! wer verstellt das ??? 838 pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), sal_True, bColumn, !bColumn ); 839 840 bAnchor = sal_True; 841 } 842 843 pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn ); 844 845 // SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark 846 pView->SelectionChanged(); 847 848 if (bHide) 849 pView->ShowAllCursors(); 850 851 return sal_True; 852 } 853 854 sal_Bool __EXPORT ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) 855 { 856 SCsCOL nPosX; 857 SCsROW nPosY; 858 pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(), 859 nPosX, nPosY, sal_False ); 860 861 ScMarkData& rMark = pViewData->GetMarkData(); 862 if (bColumn) 863 return rMark.IsColumnMarked( nPosX ); 864 else 865 return rMark.IsRowMarked( nPosY ); 866 } 867 868 void __EXPORT ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ ) 869 { 870 } 871 872 void __EXPORT ScHeaderFunctionSet::DeselectAll() 873 { 874 pViewData->GetView()->DoneBlockMode( sal_False ); 875 bAnchor = sal_False; 876 } 877 878 //------------------------------------------------------------------------ 879 880 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) : 881 SelectionEngine( pWindow, pFuncSet ) 882 { 883 // Parameter einstellen 884 SetSelectionMode( MULTIPLE_SELECTION ); 885 EnableDrag( sal_False ); 886 } 887 888 889 890 891 892