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