1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 22 #include <formdata.hxx> 23 24 #include <sfx2/app.hxx> 25 #include <svx/dialogs.hrc> 26 #include <svx/extrusionbar.hxx> 27 #include <svx/fontworkbar.hxx> 28 #include <editeng/borderline.hxx> 29 #include <svx/fmshell.hxx> 30 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx> 31 #include <sfx2/printer.hxx> 32 #include <sfx2/dispatch.hxx> 33 #include <sfx2/ipclient.hxx> 34 #include <tools/urlobj.hxx> 35 #include <sfx2/docfile.hxx> 36 #include <tools/svborder.hxx> 37 38 #include <IAnyRefDialog.hxx> 39 #include <tabvwsh.hxx> 40 #include <sc.hrc> 41 #include <globstr.hrc> 42 #include <docsh.hxx> 43 #include <scmod.hxx> 44 #include <appoptio.hxx> 45 #include <drawsh.hxx> 46 #include <drformsh.hxx> 47 #include <editsh.hxx> 48 #include <pivotsh.hxx> 49 #include <auditsh.hxx> 50 #include <drtxtob.hxx> 51 #include <inputhdl.hxx> 52 #include <editutil.hxx> 53 #include <inputopt.hxx> 54 #include <inputwin.hxx> 55 #include <dbdata.hxx> 56 #include <reffact.hxx> 57 #include <viewuno.hxx> 58 #include <dispuno.hxx> 59 #include <chgtrack.hxx> 60 #include <cellsh.hxx> 61 #include <oleobjsh.hxx> 62 #include <chartsh.hxx> 63 #include <graphsh.hxx> 64 #include <mediash.hxx> 65 #include <pgbrksh.hxx> 66 #include <dpobject.hxx> 67 #include <prevwsh.hxx> 68 #include <scextopt.hxx> 69 #include <drawview.hxx> 70 #include <fupoor.hxx> 71 #include <navsett.hxx> 72 #include <scabstdlg.hxx> 73 #include <externalrefmgr.hxx> 74 #include <defaultsoptions.hxx> 75 #include <markdata.hxx> 76 #include <preview.hxx> 77 #include <docoptio.hxx> 78 #include <documentlinkmgr.hxx> 79 #include <gridwin.hxx> 80 81 #include <com/sun/star/document/XDocumentProperties.hpp> 82 #include <sfx2/lokhelper.hxx> 83 #include <comphelper/flagguard.hxx> 84 #include <LibreOfficeKit/LibreOfficeKitEnums.h> 85 #include <comphelper/lok.hxx> 86 #include <sfx2/sidebar/SidebarController.hxx> 87 88 using namespace com::sun::star; 89 using namespace sfx2::sidebar; 90 91 namespace { 92 93 bool inChartContext(const ScTabViewShell* pViewShell) 94 { 95 SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell); 96 if (pSidebar) 97 return pSidebar->hasChartContextCurrently(); 98 99 return false; 100 } 101 102 } // anonymous namespace 103 104 void ScTabViewShell::Activate(bool bMDI) 105 { 106 SfxViewShell::Activate(bMDI); 107 bIsActive = true; 108 // here no GrabFocus, otherwise there will be problems when something is edited inplace! 109 110 if ( bMDI ) 111 { 112 // for input row (ClearCache) 113 ScModule* pScMod = SC_MOD(); 114 pScMod->ViewShellChanged(/*bStopEditing=*/ !comphelper::LibreOfficeKit::isActive()); 115 116 ActivateView( true, bFirstActivate ); 117 118 // update AutoCorrect, if Writer has newly created this 119 UpdateDrawTextOutliner(); 120 121 // RegisterNewTargetNames does not exist anymore 122 123 SfxViewFrame* pThisFrame = GetViewFrame(); 124 if ( mpInputHandler && pThisFrame->HasChildWindow(FID_INPUTLINE_STATUS) ) 125 { 126 // actually only required for Reload (last version): 127 // The InputWindow remains, but the View along with the InputHandler is newly created, 128 // that is why the InputHandler must be set at the InputWindow. 129 SfxChildWindow* pChild = pThisFrame->GetChildWindow(FID_INPUTLINE_STATUS); 130 if (pChild) 131 { 132 ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow()); 133 if (pWin && pWin->IsVisible()) 134 { 135 136 ScInputHandler* pOldHdl=pWin->GetInputHandler(); 137 138 SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> ); 139 while ( pSh!=nullptr && pOldHdl!=nullptr) 140 { 141 // Hmm, what if pSh is a shell for a different document? But as this code 142 // does not seem to be LibreOfficeKit-specific, probably that doesn't 143 // happen, because having multiple documents open simultaneously has of 144 // course not been a problem at all in traditional desktop LibreOffice. 145 // (Unlike in a LibreOfficeKit-based process where it has been a problem.) 146 if (static_cast<ScTabViewShell*>(pSh)->GetInputHandler() == pOldHdl) 147 { 148 pOldHdl->ResetDelayTimer(); 149 break; 150 } 151 pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> ); 152 } 153 154 pWin->SetInputHandler( mpInputHandler.get() ); 155 } 156 } 157 } 158 159 UpdateInputHandler( /*bForce=*/ true, /*bStopEditing=*/ !comphelper::LibreOfficeKit::isActive() ); 160 161 if ( bFirstActivate ) 162 { 163 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScNavigatorUpdateAll ) ); 164 bFirstActivate = false; 165 166 // ReadExtOptions (view settings from Excel import) must also be done 167 // after the ctor, because of the potential calls to Window::Show. 168 // Even after a bugfix (Window::Show no longer notifies the access 169 // bridge, it's done in ImplSetReallyVisible), there are problems if Window::Show 170 // is called during the ViewShell ctor and reschedules asynchronous calls 171 // (for example from the FmFormShell ctor). 172 ScExtDocOptions* pExtOpt = GetViewData().GetDocument().GetExtDocOptions(); 173 if ( pExtOpt && pExtOpt->IsChanged() ) 174 { 175 GetViewData().ReadExtOptions(*pExtOpt); // Excel view settings 176 SetTabNo( GetViewData().GetTabNo(), true ); 177 pExtOpt->SetChanged( false ); 178 } 179 } 180 181 pScActiveViewShell = this; 182 183 ScInputHandler* pHdl = pScMod->GetInputHdl(this); 184 if (pHdl) 185 { 186 pHdl->SetRefScale( GetViewData().GetZoomX(), GetViewData().GetZoomY() ); 187 } 188 189 // update change dialog 190 191 if ( pThisFrame->HasChildWindow(FID_CHG_ACCEPT) ) 192 { 193 SfxChildWindow* pChild = pThisFrame->GetChildWindow(FID_CHG_ACCEPT); 194 if (pChild) 195 { 196 static_cast<ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg(); 197 } 198 } 199 200 if(pScMod->IsRefDialogOpen()) 201 { 202 sal_uInt16 nModRefDlgId=pScMod->GetCurRefDlgId(); 203 SfxChildWindow* pChildWnd = pThisFrame->GetChildWindow( nModRefDlgId ); 204 if ( pChildWnd ) 205 { 206 if (auto pController = pChildWnd->GetController()) 207 { 208 IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pController.get()); 209 if (pRefDlg) 210 pRefDlg->ViewShellChanged(); 211 } 212 } 213 } 214 } 215 216 // don't call CheckSelectionTransfer here - activating a view should not change the 217 // primary selection (may be happening just because the mouse was moved over the window) 218 219 if (!inChartContext(this)) 220 { 221 ContextChangeEventMultiplexer::NotifyContextChange( 222 GetController(), 223 vcl::EnumContext::Context::Default); 224 } 225 } 226 227 void ScTabViewShell::Deactivate(bool bMDI) 228 { 229 HideTip(); 230 231 ScDocument& rDoc = GetViewData().GetDocument(); 232 233 ScChangeTrack* pChanges = rDoc.GetChangeTrack(); 234 235 if(pChanges!=nullptr) 236 { 237 Link<ScChangeTrack&,void> aLink; 238 pChanges->SetModifiedLink(aLink); 239 } 240 241 SfxViewShell::Deactivate(bMDI); 242 bIsActive = false; 243 ScInputHandler* pHdl = SC_MOD()->GetInputHdl(this); 244 245 if( bMDI && !comphelper::LibreOfficeKit::isActive()) 246 { 247 // during shell deactivation, shells must not be switched, or the loop 248 // through the shell stack (in SfxDispatcher::DoDeactivate_Impl) will not work 249 bool bOldDontSwitch = bDontSwitch; 250 bDontSwitch = true; 251 252 ActivateView( false, false ); 253 254 if ( GetViewFrame()->GetFrame().IsInPlace() ) // inplace 255 GetViewData().GetDocShell()->UpdateOle(GetViewData(), true); 256 257 if ( pHdl ) 258 pHdl->NotifyChange( nullptr, true ); // timer-delayed due to document switching 259 260 if (pScActiveViewShell == this) 261 pScActiveViewShell = nullptr; 262 263 bDontSwitch = bOldDontSwitch; 264 } 265 else 266 { 267 HideNoteMarker(); // note marker 268 269 if ( pHdl ) 270 pHdl->HideTip(); // Hide formula auto input tip 271 } 272 } 273 274 void ScTabViewShell::SetActive() 275 { 276 // SFX-View would like to activate itself, since then magical things would happen 277 // (eg else the designer may crash) 278 ActiveGrabFocus(); 279 } 280 281 bool ScTabViewShell::PrepareClose(bool bUI) 282 { 283 comphelper::FlagRestorationGuard aFlagGuard(bInPrepareClose, true); 284 285 // Call EnterHandler even in formula mode here, 286 // so a formula change in an embedded object isn't lost 287 // (ScDocShell::PrepareClose isn't called then). 288 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( this ); 289 if ( pHdl && pHdl->IsInputMode() ) 290 { 291 pHdl->EnterHandler(); 292 } 293 294 // draw text edit mode must be closed 295 FuPoor* pPoor = GetDrawFuncPtr(); 296 if (pPoor && IsDrawTextShell()) 297 { 298 // "clean" end of text edit, including note handling, subshells and draw func switching, 299 // as in FuDraw and ScTabView::DrawDeselectAll 300 GetViewData().GetDispatcher().Execute( pPoor->GetSlotID(), SfxCallMode::SLOT | SfxCallMode::RECORD ); 301 } 302 ScDrawView* pDrView = GetScDrawView(); 303 if ( pDrView ) 304 { 305 // force end of text edit, to be safe 306 // ScEndTextEdit must always be used, to ensure correct UndoManager 307 pDrView->ScEndTextEdit(); 308 } 309 310 if ( pFormShell ) 311 { 312 bool bRet = pFormShell->PrepareClose(bUI); 313 if (!bRet) 314 return bRet; 315 } 316 return SfxViewShell::PrepareClose(bUI); 317 } 318 319 // calculate zoom for in-place 320 // from the ratio of VisArea and window size of GridWin 321 322 void ScTabViewShell::UpdateOleZoom() 323 { 324 ScDocShell* pDocSh = GetViewData().GetDocShell(); 325 if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) 326 { 327 //TODO/LATER: is there a difference between the two GetVisArea methods? 328 Size aObjSize = static_cast<const SfxObjectShell*>(pDocSh)->GetVisArea().GetSize(); 329 if ( !aObjSize.IsEmpty() ) 330 { 331 vcl::Window* pWin = GetActiveWin(); 332 Size aWinHMM = pWin->PixelToLogic(pWin->GetOutputSizePixel(), MapMode(MapUnit::Map100thMM)); 333 SetZoomFactor( Fraction( aWinHMM.Width(),aObjSize.Width() ), 334 Fraction( aWinHMM.Height(),aObjSize.Height() ) ); 335 } 336 } 337 } 338 339 void ScTabViewShell::InnerResizePixel( const Point &rOfs, const Size &rSize, bool inplaceEditModeChange ) 340 { 341 Size aNewSize( rSize ); 342 if ( GetViewFrame()->GetFrame().IsInPlace() ) 343 { 344 SvBorder aBorder; 345 GetBorderSize( aBorder, rSize ); 346 SetBorderPixel( aBorder ); 347 348 Size aObjSize = GetObjectShell()->GetVisArea().GetSize(); 349 350 Size aSize( rSize ); 351 aSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) ); 352 aSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) ); 353 354 if ( !aObjSize.IsEmpty() ) 355 { 356 Size aLogicSize = GetWindow()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM)); 357 SfxViewShell::SetZoomFactor( Fraction( aLogicSize.Width(),aObjSize.Width() ), 358 Fraction( aLogicSize.Height(),aObjSize.Height() ) ); 359 } 360 361 Point aPos( rOfs ); 362 aPos.AdjustX(aBorder.Left() ); 363 aPos.AdjustY(aBorder.Top() ); 364 GetWindow()->SetPosSizePixel( aPos, aSize ); 365 } 366 else 367 { 368 SvBorder aBorder; 369 GetBorderSize( aBorder, rSize ); 370 SetBorderPixel( aBorder ); 371 aNewSize.AdjustWidth(aBorder.Left() + aBorder.Right() ); 372 aNewSize.AdjustHeight(aBorder.Top() + aBorder.Bottom() ); 373 } 374 375 DoResize( rOfs, aNewSize, true ); // rSize = size of gridwin 376 377 UpdateOleZoom(); // calculate zoom for in-place 378 379 if (!inplaceEditModeChange) 380 { 381 GetViewData().GetDocShell()->SetDocumentModified(); 382 } 383 } 384 385 void ScTabViewShell::OuterResizePixel( const Point &rOfs, const Size &rSize ) 386 { 387 SvBorder aBorder; 388 GetBorderSize( aBorder, rSize ); 389 SetBorderPixel( aBorder ); 390 391 DoResize( rOfs, rSize ); // position and size of tabview as passed 392 393 // ForceMove as replacement for Sfx-Move mechanism 394 // (aWinPos must be kept current, so that ForceMove works for Ole deactivation) 395 396 ForceMove(); 397 } 398 399 void ScTabViewShell::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY ) 400 { 401 // for OLE... 402 403 Fraction aFrac20( 1,5 ); 404 Fraction aFrac400( 4,1 ); 405 406 Fraction aNewX( rZoomX ); 407 if ( aNewX < aFrac20 ) 408 aNewX = aFrac20; 409 if ( aNewX > aFrac400 ) 410 aNewX = aFrac400; 411 Fraction aNewY( rZoomY ); 412 if ( aNewY < aFrac20 ) 413 aNewY = aFrac20; 414 if ( aNewY > aFrac400 ) 415 aNewY = aFrac400; 416 417 GetViewData().UpdateScreenZoom( aNewX, aNewY ); 418 SetZoom( aNewX, aNewY, true ); 419 420 PaintGrid(); 421 PaintTop(); 422 PaintLeft(); 423 424 SfxViewShell::SetZoomFactor( rZoomX, rZoomY ); 425 } 426 427 void ScTabViewShell::QueryObjAreaPixel( tools::Rectangle& rRect ) const 428 { 429 // adjust to entire cells (in 1/100 mm) 430 431 Size aPixelSize = rRect.GetSize(); 432 vcl::Window* pWin = const_cast<ScTabViewShell*>(this)->GetActiveWin(); 433 Size aLogicSize = pWin->PixelToLogic( aPixelSize ); 434 435 const ScViewData& rViewData = GetViewData(); 436 ScDocument& rDoc = rViewData.GetDocument(); 437 ScSplitPos ePos = rViewData.GetActivePart(); 438 SCCOL nCol = rViewData.GetPosX(WhichH(ePos)); 439 SCROW nRow = rViewData.GetPosY(WhichV(ePos)); 440 SCTAB nTab = rViewData.GetTabNo(); 441 bool bNegativePage = rDoc.IsNegativePage( nTab ); 442 443 tools::Rectangle aLogicRect = rDoc.GetMMRect( nCol, nRow, nCol, nRow, nTab ); 444 if ( bNegativePage ) 445 { 446 // use right edge of aLogicRect, and aLogicSize 447 aLogicRect.SetLeft( aLogicRect.Right() - aLogicSize.Width() + 1 ); // Right() is set below 448 } 449 aLogicRect.SetSize( aLogicSize ); 450 451 rViewData.GetDocShell()->SnapVisArea( aLogicRect ); 452 453 rRect.SetSize( pWin->LogicToPixel( aLogicRect.GetSize() ) ); 454 } 455 456 void ScTabViewShell::Move() 457 { 458 Point aNewPos = GetViewFrame()->GetWindow().OutputToScreenPixel(Point()); 459 460 if (aNewPos != aWinPos) 461 { 462 StopMarking(); 463 aWinPos = aNewPos; 464 } 465 } 466 467 void ScTabViewShell::ShowCursor(bool /* bOn */) 468 { 469 /*!!! ShowCursor is not called as a pair as in gridwin. 470 here the CursorLockCount for Gridwin must be set directly to 0 471 472 if (bOn) 473 ShowAllCursors(); 474 else 475 HideAllCursors(); 476 */ 477 } 478 479 void ScTabViewShell::WriteUserData(OUString& rData, bool /* bBrowse */) 480 { 481 GetViewData().WriteUserData(rData); 482 } 483 484 void ScTabViewShell::WriteUserDataSequence (uno::Sequence < beans::PropertyValue >& rSettings ) 485 { 486 GetViewData().WriteUserDataSequence(rSettings); 487 } 488 489 void ScTabViewShell::ReadUserData(const OUString& rData, bool /* bBrowse */) 490 { 491 if ( !GetViewData().GetDocShell()->IsPreview() ) 492 DoReadUserData( rData ); 493 } 494 495 void ScTabViewShell::ReadUserDataSequence (const uno::Sequence < beans::PropertyValue >& rSettings ) 496 { 497 if ( !GetViewData().GetDocShell()->IsPreview() ) 498 DoReadUserDataSequence( rSettings ); 499 } 500 501 void ScTabViewShell::DoReadUserDataSequence( const uno::Sequence < beans::PropertyValue >& rSettings ) 502 { 503 vcl::Window* pOldWin = GetActiveWin(); 504 bool bFocus = pOldWin && pOldWin->HasFocus(); 505 506 GetViewData().ReadUserDataSequence(rSettings); 507 SetTabNo( GetViewData().GetTabNo(), true ); 508 509 if ( GetViewData().IsPagebreakMode() ) 510 SetCurSubShell( GetCurObjectSelectionType(), true ); 511 512 vcl::Window* pNewWin = GetActiveWin(); 513 if (pNewWin && pNewWin != pOldWin) 514 { 515 SetWindow( pNewWin ); //! is this ViewShell always active??? 516 if (bFocus) 517 pNewWin->GrabFocus(); 518 WindowChanged(); // drawing layer (for instance #56771#) 519 } 520 521 if (GetViewData().GetHSplitMode() == SC_SPLIT_FIX || 522 GetViewData().GetVSplitMode() == SC_SPLIT_FIX) 523 { 524 InvalidateSplit(); 525 } 526 527 ZoomChanged(); 528 529 TestHintWindow(); 530 531 //! if ViewData has more tables than document, remove tables in ViewData 532 } 533 534 // DoReadUserData is also called from ctor when switching from print preview 535 536 void ScTabViewShell::DoReadUserData( const OUString& rData ) 537 { 538 vcl::Window* pOldWin = GetActiveWin(); 539 bool bFocus = pOldWin && pOldWin->HasFocus(); 540 541 GetViewData().ReadUserData(rData); 542 SetTabNo( GetViewData().GetTabNo(), true ); 543 544 if ( GetViewData().IsPagebreakMode() ) 545 SetCurSubShell( GetCurObjectSelectionType(), true ); 546 547 vcl::Window* pNewWin = GetActiveWin(); 548 if (pNewWin && pNewWin != pOldWin) 549 { 550 SetWindow( pNewWin ); //! is this ViewShell always active??? 551 if (bFocus) 552 pNewWin->GrabFocus(); 553 WindowChanged(); // drawing layer (for instance #56771#) 554 } 555 556 if (GetViewData().GetHSplitMode() == SC_SPLIT_FIX || 557 GetViewData().GetVSplitMode() == SC_SPLIT_FIX) 558 { 559 InvalidateSplit(); 560 } 561 562 ZoomChanged(); 563 564 TestHintWindow(); 565 566 //! if ViewData has more tables than document, remove tables in ViewData 567 } 568 569 void ScTabViewShell::UpdateDrawShell() 570 { 571 // Called after user interaction that may delete the selected drawing object. 572 // Remove DrawShell if nothing is selected. 573 574 SdrView* pDrView = GetScDrawView(); 575 if ( pDrView && !pDrView->AreObjectsMarked() && !IsDrawSelMode() ) 576 SetDrawShell( false ); 577 } 578 579 void ScTabViewShell::SetDrawShellOrSub() 580 { 581 bActiveDrawSh = true; 582 583 if(bActiveDrawFormSh) 584 { 585 SetCurSubShell(OST_DrawForm); 586 } 587 else if(bActiveGraphicSh) 588 { 589 SetCurSubShell(OST_Graphic); 590 } 591 else if(bActiveMediaSh) 592 { 593 SetCurSubShell(OST_Media); 594 } 595 else if(bActiveChartSh) 596 { 597 SetCurSubShell(OST_Chart); 598 } 599 else if(bActiveOleObjectSh) 600 { 601 SetCurSubShell(OST_OleObject); 602 } 603 else 604 { 605 SetCurSubShell(OST_Drawing, true /* force: different toolbars are 606 visible concerning shape type 607 and shape state */); 608 } 609 } 610 611 void ScTabViewShell::SetDrawShell( bool bActive ) 612 { 613 if(bActive) 614 { 615 SetCurSubShell(OST_Drawing, true /* force: different toolbars are 616 visible concerning shape type 617 and shape state */); 618 } 619 else 620 { 621 if(bActiveDrawFormSh || bActiveDrawSh || 622 bActiveGraphicSh || bActiveMediaSh || bActiveOleObjectSh|| 623 bActiveChartSh || bActiveDrawTextSh) 624 { 625 SetCurSubShell(OST_Cell); 626 } 627 bActiveDrawFormSh=false; 628 bActiveGraphicSh=false; 629 bActiveMediaSh=false; 630 bActiveOleObjectSh=false; 631 bActiveChartSh=false; 632 } 633 634 bool bWasDraw = bActiveDrawSh || bActiveDrawTextSh; 635 636 bActiveDrawSh = bActive; 637 bActiveDrawTextSh = false; 638 639 if ( !bActive ) 640 { 641 ResetDrawDragMode(); // switch off Mirror / Rotate 642 643 if (bWasDraw && (GetViewData().GetHSplitMode() == SC_SPLIT_FIX || 644 GetViewData().GetVSplitMode() == SC_SPLIT_FIX)) 645 { 646 // adjust active part to cursor, etc. 647 MoveCursorAbs( GetViewData().GetCurX(), GetViewData().GetCurY(), 648 SC_FOLLOW_NONE, false, false, true ); 649 } 650 } 651 } 652 653 void ScTabViewShell::SetDrawTextShell( bool bActive ) 654 { 655 bActiveDrawTextSh = bActive; 656 if ( bActive ) 657 { 658 bActiveDrawFormSh=false; 659 bActiveGraphicSh=false; 660 bActiveMediaSh=false; 661 bActiveOleObjectSh=false; 662 bActiveChartSh=false; 663 bActiveDrawSh = false; 664 SetCurSubShell(OST_DrawText); 665 } 666 else 667 SetCurSubShell(OST_Cell); 668 669 } 670 671 void ScTabViewShell::SetPivotShell( bool bActive ) 672 { 673 // SetPivotShell is called from CursorPosChanged every time 674 // -> don't change anything except switching between cell and pivot shell 675 676 if (eCurOST != OST_Pivot && eCurOST != OST_Cell) 677 return; 678 679 if ( bActive ) 680 { 681 bActiveDrawTextSh = bActiveDrawSh = false; 682 bActiveDrawFormSh=false; 683 bActiveGraphicSh=false; 684 bActiveMediaSh=false; 685 bActiveOleObjectSh=false; 686 bActiveChartSh=false; 687 SetCurSubShell(OST_Pivot); 688 } 689 else 690 SetCurSubShell(OST_Cell); 691 } 692 693 void ScTabViewShell::SetAuditShell( bool bActive ) 694 { 695 if ( bActive ) 696 { 697 bActiveDrawTextSh = bActiveDrawSh = false; 698 bActiveDrawFormSh=false; 699 bActiveGraphicSh=false; 700 bActiveMediaSh=false; 701 bActiveOleObjectSh=false; 702 bActiveChartSh=false; 703 SetCurSubShell(OST_Auditing); 704 } 705 else 706 SetCurSubShell(OST_Cell); 707 } 708 709 void ScTabViewShell::SetDrawFormShell( bool bActive ) 710 { 711 bActiveDrawFormSh = bActive; 712 713 if(bActiveDrawFormSh) 714 SetCurSubShell(OST_DrawForm); 715 } 716 void ScTabViewShell::SetChartShell( bool bActive ) 717 { 718 bActiveChartSh = bActive; 719 720 if(bActiveChartSh) 721 SetCurSubShell(OST_Chart); 722 } 723 724 void ScTabViewShell::SetGraphicShell( bool bActive ) 725 { 726 bActiveGraphicSh = bActive; 727 728 if(bActiveGraphicSh) 729 SetCurSubShell(OST_Graphic); 730 } 731 732 void ScTabViewShell::SetMediaShell( bool bActive ) 733 { 734 bActiveMediaSh = bActive; 735 736 if(bActiveMediaSh) 737 SetCurSubShell(OST_Media); 738 } 739 740 void ScTabViewShell::SetOleObjectShell( bool bActive ) 741 { 742 bActiveOleObjectSh = bActive; 743 744 if(bActiveOleObjectSh) 745 SetCurSubShell(OST_OleObject); 746 else 747 SetCurSubShell(OST_Cell); 748 } 749 750 void ScTabViewShell::SetEditShell(EditView* pView, bool bActive ) 751 { 752 if(bActive) 753 { 754 if (pEditShell) 755 pEditShell->SetEditView( pView ); 756 else 757 pEditShell.reset( new ScEditShell(pView, GetViewData()) ); 758 759 SetCurSubShell(OST_Editing); 760 } 761 else if(bActiveEditSh) 762 { 763 SetCurSubShell(OST_Cell); 764 } 765 bActiveEditSh = bActive; 766 } 767 768 void ScTabViewShell::SetCurSubShell(ObjectSelectionType eOST, bool bForce) 769 { 770 ScViewData& rViewData = GetViewData(); 771 ScDocShell* pDocSh = rViewData.GetDocShell(); 772 773 if(bDontSwitch) return; 774 775 if(!pCellShell) // is anyway always used 776 { 777 pCellShell.reset(new ScCellShell(GetViewData(), GetFrameWin())); 778 pCellShell->SetRepeatTarget( &aTarget ); 779 } 780 781 bool bPgBrk = rViewData.IsPagebreakMode(); 782 783 if(bPgBrk && !pPageBreakShell) 784 { 785 pPageBreakShell.reset( new ScPageBreakShell( this ) ); 786 pPageBreakShell->SetRepeatTarget( &aTarget ); 787 } 788 789 if ( !(eOST!=eCurOST || bForce) ) 790 return; 791 792 bool bCellBrush = false; // "format paint brush" allowed for cells 793 bool bDrawBrush = false; // "format paint brush" allowed for drawing objects 794 795 if(eCurOST!=OST_NONE) RemoveSubShell(); 796 797 if (pFormShell && !bFormShellAtTop) 798 AddSubShell(*pFormShell); // add below own subshells 799 800 switch(eOST) 801 { 802 case OST_Cell: 803 { 804 AddSubShell(*pCellShell); 805 if(bPgBrk) AddSubShell(*pPageBreakShell); 806 bCellBrush = true; 807 } 808 break; 809 case OST_Editing: 810 { 811 AddSubShell(*pCellShell); 812 if(bPgBrk) AddSubShell(*pPageBreakShell); 813 814 if(pEditShell) 815 { 816 AddSubShell(*pEditShell); 817 } 818 } 819 break; 820 case OST_DrawText: 821 { 822 if ( !pDrawTextShell ) 823 { 824 pDocSh->MakeDrawLayer(); 825 pDrawTextShell.reset( new ScDrawTextObjectBar(GetViewData()) ); 826 } 827 AddSubShell(*pDrawTextShell); 828 } 829 break; 830 case OST_Drawing: 831 { 832 if (svx::checkForSelectedCustomShapes( 833 GetScDrawView(), true /* bOnlyExtruded */ )) { 834 if (pExtrusionBarShell == nullptr) 835 pExtrusionBarShell.reset( new svx::ExtrusionBar(this) ); 836 AddSubShell( *pExtrusionBarShell ); 837 } 838 839 if (svx::checkForSelectedFontWork( 840 GetScDrawView() )) { 841 if (pFontworkBarShell == nullptr) 842 pFontworkBarShell.reset( new svx::FontworkBar(this) ); 843 AddSubShell( *pFontworkBarShell ); 844 } 845 846 if ( !pDrawShell ) 847 { 848 pDocSh->MakeDrawLayer(); 849 pDrawShell.reset(new ScDrawShell(GetViewData())); 850 pDrawShell->SetRepeatTarget( &aTarget ); 851 } 852 AddSubShell(*pDrawShell); 853 bDrawBrush = true; 854 } 855 break; 856 857 case OST_DrawForm: 858 { 859 if ( !pDrawFormShell ) 860 { 861 pDocSh->MakeDrawLayer(); 862 pDrawFormShell.reset( new ScDrawFormShell(GetViewData()) ); 863 pDrawFormShell->SetRepeatTarget( &aTarget ); 864 } 865 AddSubShell(*pDrawFormShell); 866 bDrawBrush = true; 867 } 868 break; 869 870 case OST_Chart: 871 { 872 if ( !pChartShell ) 873 { 874 pDocSh->MakeDrawLayer(); 875 pChartShell.reset( new ScChartShell(GetViewData()) ); 876 pChartShell->SetRepeatTarget( &aTarget ); 877 } 878 AddSubShell(*pChartShell); 879 bDrawBrush = true; 880 } 881 break; 882 883 case OST_OleObject: 884 { 885 if ( !pOleObjectShell ) 886 { 887 pDocSh->MakeDrawLayer(); 888 pOleObjectShell.reset( new ScOleObjectShell(GetViewData()) ); 889 pOleObjectShell->SetRepeatTarget( &aTarget ); 890 } 891 AddSubShell(*pOleObjectShell); 892 bDrawBrush = true; 893 } 894 break; 895 896 case OST_Graphic: 897 { 898 if ( !pGraphicShell) 899 { 900 pDocSh->MakeDrawLayer(); 901 pGraphicShell.reset( new ScGraphicShell(GetViewData()) ); 902 pGraphicShell->SetRepeatTarget( &aTarget ); 903 } 904 AddSubShell(*pGraphicShell); 905 bDrawBrush = true; 906 } 907 break; 908 909 case OST_Media: 910 { 911 if ( !pMediaShell) 912 { 913 pDocSh->MakeDrawLayer(); 914 pMediaShell.reset( new ScMediaShell(GetViewData()) ); 915 pMediaShell->SetRepeatTarget( &aTarget ); 916 } 917 AddSubShell(*pMediaShell); 918 } 919 break; 920 921 case OST_Pivot: 922 { 923 AddSubShell(*pCellShell); 924 if(bPgBrk) AddSubShell(*pPageBreakShell); 925 926 if ( !pPivotShell ) 927 { 928 pPivotShell.reset( new ScPivotShell( this ) ); 929 pPivotShell->SetRepeatTarget( &aTarget ); 930 } 931 AddSubShell(*pPivotShell); 932 bCellBrush = true; 933 } 934 break; 935 case OST_Auditing: 936 { 937 AddSubShell(*pCellShell); 938 if(bPgBrk) AddSubShell(*pPageBreakShell); 939 940 if ( !pAuditingShell ) 941 { 942 pDocSh->MakeDrawLayer(); // the waiting time rather now as on the click 943 944 pAuditingShell.reset( new ScAuditingShell(GetViewData()) ); 945 pAuditingShell->SetRepeatTarget( &aTarget ); 946 } 947 AddSubShell(*pAuditingShell); 948 bCellBrush = true; 949 } 950 break; 951 default: 952 OSL_FAIL("wrong shell requested"); 953 break; 954 } 955 956 if (pFormShell && bFormShellAtTop) 957 AddSubShell(*pFormShell); // add on top of own subshells 958 959 eCurOST=eOST; 960 961 // abort "format paint brush" when switching to an incompatible shell 962 if ( ( GetBrushDocument() && !bCellBrush ) || ( GetDrawBrushSet() && !bDrawBrush ) ) 963 ResetBrushDocument(); 964 } 965 966 void ScTabViewShell::SetFormShellAtTop( bool bSet ) 967 { 968 if ( pFormShell && !bSet ) 969 pFormShell->ForgetActiveControl(); // let the FormShell know it no longer has the focus 970 971 if ( bFormShellAtTop != bSet ) 972 { 973 bFormShellAtTop = bSet; 974 SetCurSubShell( GetCurObjectSelectionType(), true ); 975 } 976 } 977 978 IMPL_LINK_NOARG(ScTabViewShell, FormControlActivated, LinkParamNone*, void) 979 { 980 // a form control got the focus, so the form shell has to be on top 981 SetFormShellAtTop( true ); 982 } 983 984 // GetMySubShell / SetMySubShell: simulate old behavior, 985 // so that there is only one SubShell (only within the 5 own SubShells) 986 987 SfxShell* ScTabViewShell::GetMySubShell() const 988 { 989 // GetSubShell() was const before, and GetSubShell(sal_uInt16) should also be const... 990 991 sal_uInt16 nPos = 0; 992 SfxShell* pSub = const_cast<ScTabViewShell*>(this)->GetSubShell(nPos); 993 while (pSub) 994 { 995 if ( pSub == pDrawShell.get() || pSub == pDrawTextShell.get() || pSub == pEditShell.get() || 996 pSub == pPivotShell.get() || pSub == pAuditingShell.get() || pSub == pDrawFormShell.get() || 997 pSub == pCellShell.get() || pSub == pOleObjectShell.get() || pSub == pChartShell.get() || 998 pSub == pGraphicShell.get() || pSub == pMediaShell.get() || pSub == pPageBreakShell.get()) 999 return pSub; // found 1000 1001 pSub = const_cast<ScTabViewShell*>(this)->GetSubShell(++nPos); 1002 } 1003 return nullptr; // none from mine present 1004 } 1005 1006 bool ScTabViewShell::IsDrawTextShell() const 1007 { 1008 return ( pDrawTextShell && ( GetMySubShell() == pDrawTextShell.get() ) ); 1009 } 1010 1011 bool ScTabViewShell::IsAuditShell() const 1012 { 1013 return ( pAuditingShell && ( GetMySubShell() == pAuditingShell.get() ) ); 1014 } 1015 1016 void ScTabViewShell::SetDrawTextUndo( SfxUndoManager* pNewUndoMgr ) 1017 { 1018 // Default: undo manager for DocShell 1019 if (!pNewUndoMgr) 1020 pNewUndoMgr = GetViewData().GetDocShell()->GetUndoManager(); 1021 1022 if (pDrawTextShell) 1023 { 1024 pDrawTextShell->SetUndoManager(pNewUndoMgr); 1025 ScDocShell* pDocSh = GetViewData().GetDocShell(); 1026 if ( pNewUndoMgr == pDocSh->GetUndoManager() && 1027 !pDocSh->GetDocument().IsUndoEnabled() ) 1028 { 1029 pNewUndoMgr->SetMaxUndoActionCount( 0 ); 1030 } 1031 } 1032 else 1033 { 1034 OSL_FAIL("SetDrawTextUndo without DrawTextShell"); 1035 } 1036 } 1037 1038 ScTabViewShell* ScTabViewShell::GetActiveViewShell() 1039 { 1040 return dynamic_cast< ScTabViewShell *>( Current() ); 1041 } 1042 1043 SfxPrinter* ScTabViewShell::GetPrinter( bool bCreate ) 1044 { 1045 // printer is always present (is created for the FontList already on start-up) 1046 return GetViewData().GetDocShell()->GetPrinter(bCreate); 1047 } 1048 1049 sal_uInt16 ScTabViewShell::SetPrinter( SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags ) 1050 { 1051 return GetViewData().GetDocShell()->SetPrinter( pNewPrinter, nDiffFlags ); 1052 } 1053 1054 bool ScTabViewShell::HasPrintOptionsPage() const 1055 { 1056 return true; 1057 } 1058 1059 std::unique_ptr<SfxTabPage> ScTabViewShell::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rOptions ) 1060 { 1061 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); 1062 ::CreateTabPage ScTpPrintOptionsCreate = pFact->GetTabPageCreatorFunc(RID_SC_TP_PRINT); 1063 if ( ScTpPrintOptionsCreate ) 1064 return ScTpPrintOptionsCreate(pPage, pController, &rOptions); 1065 return nullptr; 1066 } 1067 1068 void ScTabViewShell::StopEditShell() 1069 { 1070 if ( pEditShell != nullptr && !bDontSwitch ) 1071 SetEditShell(nullptr, false ); 1072 } 1073 1074 // close handler to ensure function of dialog: 1075 1076 IMPL_LINK_NOARG(ScTabViewShell, SimpleRefClose, const OUString*, void) 1077 { 1078 SfxInPlaceClient* pClient = GetIPClient(); 1079 if ( pClient && pClient->IsObjectInPlaceActive() ) 1080 { 1081 // If range selection was started with an active embedded object, 1082 // switch back to original sheet (while the dialog is still open). 1083 1084 SetTabNo( GetViewData().GetRefTabNo() ); 1085 } 1086 1087 ScSimpleRefDlgWrapper::SetAutoReOpen( true ); 1088 } 1089 1090 // handlers to call UNO listeners: 1091 1092 static ScTabViewObj* lcl_GetViewObj( const ScTabViewShell& rShell ) 1093 { 1094 ScTabViewObj* pRet = nullptr; 1095 SfxViewFrame* pViewFrame = rShell.GetViewFrame(); 1096 if (pViewFrame) 1097 { 1098 SfxFrame& rFrame = pViewFrame->GetFrame(); 1099 uno::Reference<frame::XController> xController = rFrame.GetController(); 1100 if (xController.is()) 1101 pRet = comphelper::getFromUnoTunnel<ScTabViewObj>( xController ); 1102 } 1103 return pRet; 1104 } 1105 1106 IMPL_LINK( ScTabViewShell, SimpleRefDone, const OUString&, aResult, void ) 1107 { 1108 ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); 1109 if ( pImpObj ) 1110 pImpObj->RangeSelDone( aResult ); 1111 } 1112 1113 IMPL_LINK( ScTabViewShell, SimpleRefAborted, const OUString&, rResult, void ) 1114 { 1115 ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); 1116 if ( pImpObj ) 1117 pImpObj->RangeSelAborted( rResult ); 1118 } 1119 1120 IMPL_LINK( ScTabViewShell, SimpleRefChange, const OUString&, rResult, void ) 1121 { 1122 ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); 1123 if ( pImpObj ) 1124 pImpObj->RangeSelChanged( rResult ); 1125 } 1126 1127 void ScTabViewShell::StartSimpleRefDialog( 1128 const OUString& rTitle, const OUString& rInitVal, 1129 bool bCloseOnButtonUp, bool bSingleCell, bool bMultiSelection ) 1130 { 1131 SfxViewFrame* pViewFrm = GetViewFrame(); 1132 1133 if ( GetActiveViewShell() != this ) 1134 { 1135 // #i18833# / #i34499# The API method can be called for a view that's not active. 1136 // Then the view has to be activated first, the same way as in Execute for SID_CURRENTDOC. 1137 // Can't use GrabFocus here, because it needs to take effect immediately. 1138 1139 pViewFrm->GetFrame().Appear(); 1140 } 1141 1142 sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId(); 1143 1144 SC_MOD()->SetRefDialog( nId, true, pViewFrm ); 1145 1146 ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(pViewFrm->GetChildWindow( nId )); 1147 if (!pWnd) 1148 return; 1149 1150 pWnd->SetCloseHdl( LINK( this, ScTabViewShell, SimpleRefClose ) ); 1151 pWnd->SetUnoLinks( LINK( this, ScTabViewShell, SimpleRefDone ), 1152 LINK( this, ScTabViewShell, SimpleRefAborted ), 1153 LINK( this, ScTabViewShell, SimpleRefChange ) ); 1154 pWnd->SetRefString( rInitVal ); 1155 pWnd->SetFlags( bCloseOnButtonUp, bSingleCell, bMultiSelection ); 1156 ScSimpleRefDlgWrapper::SetAutoReOpen( false ); 1157 if (auto xWin = pWnd->GetController()) 1158 xWin->set_title(rTitle); 1159 pWnd->StartRefInput(); 1160 } 1161 1162 void ScTabViewShell::StopSimpleRefDialog() 1163 { 1164 SfxViewFrame* pViewFrm = GetViewFrame(); 1165 sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId(); 1166 1167 ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(pViewFrm->GetChildWindow( nId )); 1168 if (pWnd) 1169 { 1170 if (auto pWin = pWnd->GetController()) 1171 pWin->response(RET_CLOSE); 1172 } 1173 } 1174 1175 bool ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt) 1176 { 1177 ScModule* pScMod = SC_MOD(); 1178 1179 SfxViewFrame* pThisFrame = GetViewFrame(); 1180 if ( pThisFrame->GetChildWindow( SID_OPENDLG_FUNCTION ) ) 1181 return false; 1182 1183 vcl::KeyCode aCode = rKEvt.GetKeyCode(); 1184 bool bShift = aCode.IsShift(); 1185 bool bControl = aCode.IsMod1(); 1186 bool bAlt = aCode.IsMod2(); 1187 sal_uInt16 nCode = aCode.GetCode(); 1188 bool bUsed = false; 1189 bool bInPlace = pScMod->IsEditMode(); // Editengine gets all 1190 bool bAnyEdit = pScMod->IsInputMode(); // only characters & backspace 1191 bool bDraw = IsDrawTextEdit(); 1192 1193 HideNoteMarker(); // note marker 1194 1195 // don't do extra HideCursor/ShowCursor calls if EnterHandler will switch to a different sheet 1196 bool bOnRefSheet = ( GetViewData().GetRefTabNo() == GetViewData().GetTabNo() ); 1197 bool bHideCursor = ( ( nCode == KEY_RETURN && bInPlace ) || nCode == KEY_TAB ) && bOnRefSheet; 1198 1199 if (bHideCursor) 1200 HideAllCursors(); 1201 1202 ScDocument& rDoc = GetViewData().GetDocument(); 1203 rDoc.KeyInput(); // TimerDelays etc. 1204 1205 if( bInPlace ) 1206 { 1207 bUsed = pScMod->InputKeyEvent( rKEvt ); // input 1208 if( !bUsed ) 1209 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators 1210 } 1211 else if( bAnyEdit ) 1212 { 1213 bool bIsType = false; 1214 sal_uInt16 nModi = aCode.GetModifier(); 1215 sal_uInt16 nGroup = aCode.GetGroup(); 1216 1217 if ( nGroup == KEYGROUP_NUM || nGroup == KEYGROUP_ALPHA || nGroup == 0 ) 1218 if ( !bControl && !bAlt ) 1219 bIsType = true; 1220 1221 if ( nGroup == KEYGROUP_MISC ) 1222 switch ( nCode ) 1223 { 1224 case KEY_RETURN: 1225 bIsType = bControl && !bAlt; // Control, Shift-Control-Return 1226 if ( !bIsType && nModi == 0 ) 1227 { 1228 // Does the Input Handler also want a simple Return? 1229 1230 ScInputHandler* pHdl = pScMod->GetInputHdl(this); 1231 bIsType = pHdl && pHdl->TakesReturn(); 1232 } 1233 break; 1234 case KEY_SPACE: 1235 bIsType = !bControl && !bAlt; // without modifier or Shift-Space 1236 break; 1237 case KEY_ESCAPE: 1238 bIsType = (nModi == 0); // only without modifier 1239 break; 1240 default: 1241 bIsType = true; 1242 } 1243 else if (nCode == KEY_RIGHT && !bControl && !bShift && !bAlt) 1244 { 1245 ScInputHandler* pHdl = pScMod->GetInputHdl(this); 1246 bIsType = pHdl && pHdl->HasPartialComplete(); 1247 } 1248 1249 if( bIsType ) 1250 bUsed = pScMod->InputKeyEvent( rKEvt ); // input 1251 1252 if( !bUsed ) 1253 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators 1254 1255 if ( !bUsed && !bIsType && nCode != KEY_RETURN ) // input once again afterwards 1256 bUsed = pScMod->InputKeyEvent( rKEvt ); 1257 } 1258 else 1259 { 1260 // special case: copy/cut for multiselect -> error message 1261 // (Slot is disabled, so SfxViewShell::KeyInput would be swallowed without a comment) 1262 KeyFuncType eFunc = aCode.GetFunction(); 1263 if ( eFunc == KeyFuncType::CUT ) 1264 { 1265 ScRange aDummy; 1266 ScMarkType eMarkType = GetViewData().GetSimpleArea( aDummy ); 1267 if (eMarkType != SC_MARK_SIMPLE) 1268 { 1269 ErrorMessage(STR_NOMULTISELECT); 1270 bUsed = true; 1271 } 1272 } 1273 if (!bUsed) 1274 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators 1275 1276 // during inplace editing, some slots are handled by the 1277 // container app and are executed during Window::KeyInput. 1278 // -> don't pass keys to input handler that would be used there 1279 // but should call slots instead. 1280 bool bParent = ( GetViewFrame()->GetFrame().IsInPlace() && eFunc != KeyFuncType::DONTKNOW ); 1281 1282 if( !bUsed && !bDraw && nCode != KEY_RETURN && !bParent ) 1283 bUsed = pScMod->InputKeyEvent( rKEvt, true ); // input 1284 } 1285 1286 if (!bInPlace && !bUsed && !bDraw) 1287 { 1288 switch (nCode) 1289 { 1290 case KEY_RETURN: 1291 { 1292 bool bNormal = !bControl && !bAlt; 1293 if ( !bAnyEdit && bNormal ) 1294 { 1295 // Depending on options, Enter switches to edit mode. 1296 const ScInputOptions& rOpt = pScMod->GetInputOptions(); 1297 if ( rOpt.GetEnterEdit() ) 1298 { 1299 pScMod->SetInputMode( SC_INPUT_TABLE ); 1300 bUsed = true; 1301 } 1302 } 1303 1304 bool bEditReturn = bControl && !bShift; // pass on to edit engine 1305 if ( !bUsed && !bEditReturn ) 1306 { 1307 if ( bOnRefSheet ) 1308 HideAllCursors(); 1309 1310 ScEnterMode nMode = ScEnterMode::NORMAL; 1311 if ( bShift && bControl ) 1312 nMode = ScEnterMode::MATRIX; 1313 else if ( bAlt ) 1314 nMode = ScEnterMode::BLOCK; 1315 pScMod->InputEnterHandler(nMode); 1316 1317 if (nMode == ScEnterMode::NORMAL) 1318 { 1319 if( bShift ) 1320 GetViewData().GetDispatcher().Execute( SID_CURSORENTERUP, 1321 SfxCallMode::SLOT | SfxCallMode::RECORD ); 1322 else 1323 GetViewData().GetDispatcher().Execute( SID_CURSORENTERDOWN, 1324 SfxCallMode::SLOT | SfxCallMode::RECORD ); 1325 } 1326 else 1327 UpdateInputHandler(true); 1328 1329 if ( bOnRefSheet ) 1330 ShowAllCursors(); 1331 1332 // here no UpdateInputHandler, since during reference input on another 1333 // document this ViewShell is not the one that is used for input. 1334 1335 bUsed = true; 1336 } 1337 } 1338 break; 1339 } 1340 } 1341 1342 // hard-code Alt-Cursor key, since Alt is not configurable 1343 1344 if ( !bUsed && bAlt && !bControl ) 1345 { 1346 sal_uInt16 nSlotId = 0; 1347 switch (nCode) 1348 { 1349 case KEY_UP: 1350 ModifyCellSize( DIR_TOP, bShift ); 1351 bUsed = true; 1352 break; 1353 case KEY_DOWN: 1354 ModifyCellSize( DIR_BOTTOM, bShift ); 1355 bUsed = true; 1356 break; 1357 case KEY_LEFT: 1358 ModifyCellSize( DIR_LEFT, bShift ); 1359 bUsed = true; 1360 break; 1361 case KEY_RIGHT: 1362 ModifyCellSize( DIR_RIGHT, bShift ); 1363 bUsed = true; 1364 break; 1365 case KEY_PAGEUP: 1366 nSlotId = bShift ? SID_CURSORPAGELEFT_SEL : SID_CURSORPAGELEFT_; 1367 break; 1368 case KEY_PAGEDOWN: 1369 nSlotId = bShift ? SID_CURSORPAGERIGHT_SEL : SID_CURSORPAGERIGHT_; 1370 break; 1371 case KEY_EQUAL: 1372 { 1373 // #tdf39302: Use "Alt + =" for autosum 1374 if ( !bAnyEdit ) // Ignore shortcut if currently editing a cell 1375 { 1376 ScInputHandler* pHdl = pScMod->GetInputHdl(this); 1377 if ( pHdl ) 1378 { 1379 ScInputWindow* pWin = pHdl->GetInputWindow(); 1380 if ( pWin ) 1381 { 1382 bool bRangeFinder = false; 1383 bool bSubTotal = false; 1384 pWin->AutoSum( bRangeFinder, bSubTotal, ocSum ); 1385 } 1386 } 1387 1388 bUsed = true; 1389 break; 1390 } 1391 } 1392 } 1393 if ( nSlotId ) 1394 { 1395 GetViewData().GetDispatcher().Execute( nSlotId, SfxCallMode::SLOT | SfxCallMode::RECORD ); 1396 bUsed = true; 1397 } 1398 } 1399 1400 // use Ctrl+Alt+Shift+arrow keys to move the cursor in cells 1401 // while keeping the last selection 1402 if ( !bUsed && bAlt && bControl && bShift) 1403 { 1404 sal_uInt16 nSlotId = 0; 1405 switch (nCode) 1406 { 1407 case KEY_UP: 1408 nSlotId = SID_CURSORUP; 1409 break; 1410 case KEY_DOWN: 1411 nSlotId = SID_CURSORDOWN; 1412 break; 1413 case KEY_LEFT: 1414 nSlotId = SID_CURSORLEFT; 1415 break; 1416 case KEY_RIGHT: 1417 nSlotId = SID_CURSORRIGHT; 1418 break; 1419 case KEY_PAGEUP: 1420 nSlotId = SID_CURSORPAGEUP; 1421 break; 1422 case KEY_PAGEDOWN: 1423 nSlotId = SID_CURSORPAGEDOWN; 1424 break; 1425 case KEY_HOME: 1426 nSlotId = SID_CURSORHOME; 1427 break; 1428 case KEY_END: 1429 nSlotId = SID_CURSOREND; 1430 break; 1431 default: 1432 nSlotId = 0; 1433 break; 1434 } 1435 if ( nSlotId ) 1436 { 1437 sal_uInt16 nMode = GetLockedModifiers(); 1438 LockModifiers(KEY_MOD1); 1439 GetViewData().GetDispatcher().Execute( nSlotId, SfxCallMode::SLOT | SfxCallMode::RECORD ); 1440 LockModifiers(nMode); 1441 bUsed = true; 1442 } 1443 } 1444 if (bHideCursor) 1445 ShowAllCursors(); 1446 1447 return bUsed; 1448 } 1449 1450 bool ScTabViewShell::SfxKeyInput(const KeyEvent& rKeyEvent) 1451 { 1452 return SfxViewShell::KeyInput( rKeyEvent ); 1453 } 1454 1455 bool ScTabViewShell::KeyInput( const KeyEvent &rKeyEvent ) 1456 { 1457 return TabKeyInput( rKeyEvent ); 1458 } 1459 1460 void ScTabViewShell::Construct( TriState nForceDesignMode ) 1461 { 1462 SfxApplication* pSfxApp = SfxGetpApp(); 1463 ScDocShell* pDocSh = GetViewData().GetDocShell(); 1464 ScDocument& rDoc = pDocSh->GetDocument(); 1465 bReadOnly = pDocSh->IsReadOnly(); 1466 bIsActive = false; 1467 1468 EnableAutoSpell(rDoc.GetDocOptions().IsAutoSpell()); 1469 1470 SetName("View"); // for SBX 1471 Color aColBlack( COL_BLACK ); 1472 SetPool( &SC_MOD()->GetPool() ); 1473 SetWindow( GetActiveWin() ); 1474 1475 pCurFrameLine.reset( new ::editeng::SvxBorderLine(&aColBlack, 20, SvxBorderLineStyle::SOLID) ); 1476 StartListening(*GetViewData().GetDocShell(), DuplicateHandling::Prevent); 1477 StartListening(*GetViewFrame(), DuplicateHandling::Prevent); 1478 StartListening(*pSfxApp, DuplicateHandling::Prevent); // #i62045# #i62046# application is needed for Calc's own hints 1479 1480 SfxViewFrame* pFirst = SfxViewFrame::GetFirst(pDocSh); 1481 bool bFirstView = !pFirst 1482 || (pFirst == GetViewFrame() && !SfxViewFrame::GetNext(*pFirst,pDocSh)); 1483 1484 if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) 1485 { 1486 //TODO/LATER: is there a difference between the two GetVisArea methods? 1487 tools::Rectangle aVisArea = static_cast<const SfxObjectShell*>(pDocSh)->GetVisArea(); 1488 1489 SCTAB nVisTab = rDoc.GetVisibleTab(); 1490 if (!rDoc.HasTable(nVisTab)) 1491 { 1492 nVisTab = 0; 1493 rDoc.SetVisibleTab(nVisTab); 1494 } 1495 SetTabNo( nVisTab ); 1496 bool bNegativePage = rDoc.IsNegativePage( nVisTab ); 1497 // show the right cells 1498 GetViewData().SetScreenPos( bNegativePage ? aVisArea.TopRight() : aVisArea.TopLeft() ); 1499 1500 if ( GetViewFrame()->GetFrame().IsInPlace() ) // inplace 1501 { 1502 pDocSh->SetInplace( true ); // already initiated like this 1503 if (rDoc.IsEmbedded()) 1504 rDoc.ResetEmbedded(); // no blue mark 1505 } 1506 else if ( bFirstView ) 1507 { 1508 pDocSh->SetInplace( false ); 1509 GetViewData().RefreshZoom(); // recalculate PPT 1510 if (!rDoc.IsEmbedded()) 1511 rDoc.SetEmbedded( rDoc.GetVisibleTab(), aVisArea ); // mark VisArea 1512 } 1513 } 1514 1515 // ViewInputHandler 1516 // Each task now has its own InputWindow, 1517 // therefore either should each task get its own InputHandler, 1518 // or the InputWindow should create its own InputHandler 1519 // (then always search via InputWindow and only if not found 1520 // use the InputHandler of the App). 1521 // As an intermediate solution each View gets its own InputHandler, 1522 // which only yields problems if two Views are in one task window. 1523 mpInputHandler.reset(new ScInputHandler); 1524 1525 // old version: 1526 // if ( !GetViewFrame()->ISA(SfxTopViewFrame) ) // OLE or Plug-In 1527 // pInputHandler = new ScInputHandler; 1528 1529 // create FormShell before MakeDrawView, so that DrawView can be registered at the 1530 // FormShell in every case 1531 // the FormShell is pushed in the first activate 1532 pFormShell.reset( new FmFormShell(this) ); 1533 pFormShell->SetControlActivationHandler( LINK( this, ScTabViewShell, FormControlActivated ) ); 1534 1535 // DrawView must not be created in TabView - ctor, 1536 // if the ViewShell is not yet constructed... 1537 if (rDoc.GetDrawLayer()) 1538 MakeDrawView( nForceDesignMode ); 1539 ViewOptionsHasChanged(false, false); // possibly also creates DrawView 1540 1541 SfxUndoManager* pMgr = pDocSh->GetUndoManager(); 1542 SetUndoManager( pMgr ); 1543 pFormShell->SetUndoManager( pMgr ); 1544 if ( !rDoc.IsUndoEnabled() ) 1545 { 1546 pMgr->SetMaxUndoActionCount( 0 ); 1547 } 1548 SetRepeatTarget( &aTarget ); 1549 pFormShell->SetRepeatTarget( &aTarget ); 1550 1551 if ( bFirstView ) // first view? 1552 { 1553 rDoc.SetDocVisible( true ); // used when creating new sheets 1554 if ( pDocSh->IsEmpty() ) 1555 { 1556 // set first sheet's RTL flag (following will already be initialized because of SetDocVisible) 1557 rDoc.SetLayoutRTL( 0, ScGlobal::IsSystemRTL() ); 1558 1559 // append additional sheets (not for OLE object) 1560 if ( pDocSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) 1561 { 1562 // Get the customized initial tab count 1563 const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions(); 1564 SCTAB nInitTabCount = rOpt.GetInitTabCount(); 1565 1566 for (SCTAB i=1; i<nInitTabCount; i++) 1567 rDoc.MakeTable(i,false); 1568 } 1569 1570 pDocSh->SetEmpty( false ); // #i6232# make sure this is done only once 1571 } 1572 1573 // ReadExtOptions is now in Activate 1574 1575 // link update no nesting 1576 if ( pDocSh->GetCreateMode() != SfxObjectCreateMode::INTERNAL && 1577 pDocSh->IsUpdateEnabled() ) // #105575#; update only in the first creation of the ViewShell 1578 { 1579 // Check if there are any external data. 1580 bool bLink = rDoc.GetExternalRefManager()->hasExternalData(); 1581 if (!bLink) 1582 { 1583 // #i100042# sheet links can still exist independently from external formula references 1584 SCTAB nTabCount = rDoc.GetTableCount(); 1585 for (SCTAB i=0; i<nTabCount && !bLink; i++) 1586 if (rDoc.IsLinked(i)) 1587 bLink = true; 1588 } 1589 if (!bLink) 1590 { 1591 const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager(); 1592 if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasDdeOrOleOrWebServiceLinks()) 1593 bLink = true; 1594 } 1595 if (bLink) 1596 { 1597 if ( !pFirst ) 1598 pFirst = GetViewFrame(); 1599 1600 if(SC_MOD()->GetCurRefDlgId()==0) 1601 { 1602 pFirst->GetDispatcher()->Execute( SID_UPDATETABLINKS, 1603 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); 1604 } 1605 } 1606 else 1607 { 1608 // No links yet, but loading an existing document may have 1609 // disabled link update but there's no "Allow updating" infobar 1610 // that could enable it again. So in order to enable the user 1611 // to add formulas with external references allow link updates 1612 // again. 1613 pDocSh->AllowLinkUpdate(); 1614 } 1615 1616 bool bReImport = false; // update imported data 1617 ScDBCollection* pDBColl = rDoc.GetDBCollection(); 1618 if ( pDBColl ) 1619 { 1620 const ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs(); 1621 bReImport = std::any_of(rDBs.begin(), rDBs.end(), 1622 [](const std::unique_ptr<ScDBData>& rxDB) { return rxDB->IsStripData() && rxDB->HasImportParam() && !rxDB->HasImportSelection(); }); 1623 } 1624 if (bReImport) 1625 { 1626 if ( !pFirst ) 1627 pFirst = GetViewFrame(); 1628 if(SC_MOD()->GetCurRefDlgId()==0) 1629 { 1630 pFirst->GetDispatcher()->Execute( SID_REIMPORT_AFTER_LOAD, 1631 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); 1632 } 1633 } 1634 } 1635 } 1636 1637 UpdateAutoFillMark(); 1638 1639 // ScDispatchProviderInterceptor registers itself in ctor 1640 xDisProvInterceptor = new ScDispatchProviderInterceptor( this ); 1641 1642 bFirstActivate = true; // delay NavigatorUpdate until Activate() 1643 1644 // #105575#; update only in the first creation of the ViewShell 1645 pDocSh->SetUpdateEnabled(false); 1646 1647 if ( GetViewFrame()->GetFrame().IsInPlace() ) 1648 UpdateHeaderWidth(); // The inplace activation requires headers to be calculated 1649 1650 SvBorder aBorder; 1651 GetBorderSize( aBorder, Size() ); 1652 SetBorderPixel( aBorder ); 1653 } 1654 1655 ScTabViewShell::ScTabViewShell( SfxViewFrame* pViewFrame, 1656 SfxViewShell* pOldSh ) : 1657 SfxViewShell( pViewFrame, SfxViewShellFlags::HAS_PRINTOPTIONS ), 1658 ScDBFunc( &pViewFrame->GetWindow(), static_cast<ScDocShell&>(*pViewFrame->GetObjectShell()), this ), 1659 eCurOST(OST_NONE), 1660 nDrawSfxId(0), 1661 aTarget(this), 1662 bActiveDrawSh(false), 1663 bActiveDrawTextSh(false), 1664 bActiveDrawFormSh(false), 1665 bActiveOleObjectSh(false), 1666 bActiveChartSh(false), 1667 bActiveGraphicSh(false), 1668 bActiveMediaSh(false), 1669 bFormShellAtTop(false), 1670 bDontSwitch(false), 1671 bInFormatDialog(false), 1672 bReadOnly(false), 1673 bForceFocusOnCurCell(false), 1674 bInPrepareClose(false), 1675 bInDispose(false), 1676 nCurRefDlgId(0), 1677 mbInSwitch(false) 1678 { 1679 const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions(); 1680 1681 // if switching back from print preview, 1682 // restore the view settings that were active when creating the preview 1683 // ReadUserData must not happen from ctor, because the view's edit window 1684 // has to be shown by the sfx. ReadUserData is deferred until the first Activate call. 1685 // old DesignMode state from form layer must be restored, too 1686 1687 TriState nForceDesignMode = TRISTATE_INDET; 1688 if ( auto pPreviewShell = dynamic_cast<ScPreviewShell*>( pOldSh) ) 1689 { 1690 nForceDesignMode = pPreviewShell->GetSourceDesignMode(); 1691 ScPreview* p = pPreviewShell->GetPreview(); 1692 if (p) 1693 GetViewData().GetMarkData().SetSelectedTabs(p->GetSelectedTabs()); 1694 } 1695 1696 Construct( nForceDesignMode ); 1697 1698 // make Controller known to SFX 1699 new ScTabViewObj( this ); 1700 1701 // Resolves: tdf#53899 if there is no controller, register the above 1702 // ScTabViewObj as the current controller for the duration of the first 1703 // round of calculations triggered here by SetZoom. That way any StarBasic 1704 // macros triggered while the document is loading have a CurrentController 1705 // available to them. 1706 bool bInstalledScTabViewObjAsTempController = false; 1707 uno::Reference<frame::XController> xCurrentController(GetViewData().GetDocShell()->GetModel()->getCurrentController()); 1708 if (!xCurrentController) 1709 { 1710 //GetController here returns the ScTabViewObj above 1711 GetViewData().GetDocShell()->GetModel()->setCurrentController(GetController()); 1712 bInstalledScTabViewObjAsTempController = true; 1713 } 1714 xCurrentController.clear(); 1715 1716 if ( GetViewData().GetDocShell()->IsPreview() ) 1717 { 1718 // preview for template dialog: always show whole page 1719 SetZoomType( SvxZoomType::WHOLEPAGE, true ); // zoom value is recalculated at next Resize 1720 } 1721 else 1722 { 1723 Fraction aFract( rAppOpt.GetZoom(), 100 ); 1724 SetZoom( aFract, aFract, true ); 1725 SetZoomType( rAppOpt.GetZoomType(), true ); 1726 } 1727 1728 SetCurSubShell(OST_Cell); 1729 SvBorder aBorder; 1730 GetBorderSize( aBorder, Size() ); 1731 SetBorderPixel( aBorder ); 1732 1733 MakeDrawLayer(); 1734 1735 //put things back as we found them 1736 if (bInstalledScTabViewObjAsTempController) 1737 GetViewData().GetDocShell()->GetModel()->setCurrentController(nullptr); 1738 1739 // formula mode in online is not usable in collaborative mode, 1740 // this is a workaround for disabling formula mode in online 1741 // when there is more than a single view 1742 if (!comphelper::LibreOfficeKit::isActive()) 1743 return; 1744 1745 SfxViewShell* pViewShell = SfxViewShell::GetFirst(); 1746 // have we already one view ? 1747 if (!pViewShell) 1748 return; 1749 1750 // this view is not yet visible at this stage, so we look for not visible views, too, for this same document 1751 SfxViewShell* pViewShell2 = pViewShell; 1752 do 1753 { 1754 pViewShell2 = SfxViewShell::GetNext(*pViewShell2, /*only visible shells*/ false); 1755 } while (pViewShell2 && pViewShell2->GetDocId() != pViewShell->GetDocId()); 1756 // if the second view is not this one, it means that there is 1757 // already more than one active view and so the formula mode 1758 // has already been disabled 1759 if (pViewShell2 && pViewShell2 == this) 1760 { 1761 ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); 1762 assert(pTabViewShell); 1763 ScInputHandler* pInputHdl = pTabViewShell->GetInputHandler(); 1764 if (pInputHdl && pInputHdl->IsFormulaMode()) 1765 { 1766 pInputHdl->SetMode(SC_INPUT_NONE); 1767 } 1768 } 1769 } 1770 1771 ScTabViewShell::~ScTabViewShell() 1772 { 1773 bInDispose = true; 1774 1775 // Notify other LOK views that we are going away. 1776 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false"); 1777 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""); 1778 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"); 1779 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", "EMPTY"); 1780 1781 // all to NULL, in case the TabView-dtor tries to access them 1782 //! (should not really! ??!?!) 1783 if (mpInputHandler) 1784 { 1785 mpInputHandler->SetDocumentDisposing(true); 1786 } 1787 1788 ScDocShell* pDocSh = GetViewData().GetDocShell(); 1789 EndListening(*pDocSh); 1790 EndListening(*GetViewFrame()); 1791 EndListening(*SfxGetpApp()); // #i62045# #i62046# needed now - SfxViewShell no longer does it 1792 1793 SC_MOD()->ViewShellGone(this); 1794 1795 RemoveSubShell(); // all 1796 SetWindow(nullptr); 1797 1798 // need kill editview or we will touch the editengine after it has been freed by the ScInputHandler 1799 KillEditView(true); 1800 1801 pFontworkBarShell.reset(); 1802 pExtrusionBarShell.reset(); 1803 pCellShell.reset(); 1804 pPageBreakShell.reset(); 1805 pDrawShell.reset(); 1806 pDrawFormShell.reset(); 1807 pOleObjectShell.reset(); 1808 pChartShell.reset(); 1809 pGraphicShell.reset(); 1810 pMediaShell.reset(); 1811 pDrawTextShell.reset(); 1812 pEditShell.reset(); 1813 pPivotShell.reset(); 1814 pAuditingShell.reset(); 1815 pCurFrameLine.reset(); 1816 mpFormEditData.reset(); 1817 mpInputHandler.reset(); 1818 pDialogDPObject.reset(); 1819 pNavSettings.reset(); 1820 1821 pFormShell.reset(); 1822 pAccessibilityBroadcaster.reset(); 1823 } 1824 1825 void ScTabViewShell::SetDialogDPObject( std::unique_ptr<ScDPObject> pObj ) 1826 { 1827 pDialogDPObject = std::move(pObj); 1828 } 1829 1830 void ScTabViewShell::FillFieldData( ScHeaderFieldData& rData ) 1831 { 1832 ScDocShell* pDocShell = GetViewData().GetDocShell(); 1833 ScDocument& rDoc = pDocShell->GetDocument(); 1834 SCTAB nTab = GetViewData().GetTabNo(); 1835 OUString aTmp; 1836 rDoc.GetName(nTab, aTmp); 1837 rData.aTabName = aTmp; 1838 1839 if( pDocShell->getDocProperties()->getTitle().getLength() != 0 ) 1840 rData.aTitle = pDocShell->getDocProperties()->getTitle(); 1841 else 1842 rData.aTitle = pDocShell->GetTitle(); 1843 1844 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject(); 1845 rData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ); 1846 if ( !rData.aLongDocName.isEmpty() ) 1847 rData.aShortDocName = rURLObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous); 1848 else 1849 rData.aShortDocName = rData.aLongDocName = rData.aTitle; 1850 rData.nPageNo = 1; 1851 rData.nTotalPages = 99; 1852 1853 // eNumType is known by the dialog 1854 } 1855 1856 ScNavigatorSettings* ScTabViewShell::GetNavigatorSettings() 1857 { 1858 if( !pNavSettings ) 1859 pNavSettings.reset(new ScNavigatorSettings); 1860 return pNavSettings.get(); 1861 } 1862 1863 tools::Rectangle ScTabViewShell::getLOKVisibleArea() const 1864 { 1865 return GetViewData().getLOKVisibleArea(); 1866 } 1867 1868 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1869
