tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / tabvwsh4.cxx
blob46ed26d6b808d9ba3bbd8bf47936b34de011d74e
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.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <formdata.hxx>
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>
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 <SparklineShell.hxx>
50 #include <auditsh.hxx>
51 #include <drtxtob.hxx>
52 #include <inputhdl.hxx>
53 #include <editutil.hxx>
54 #include <inputopt.hxx>
55 #include <inputwin.hxx>
56 #include <dbdata.hxx>
57 #include <reffact.hxx>
58 #include <viewuno.hxx>
59 #include <dispuno.hxx>
60 #include <chgtrack.hxx>
61 #include <cellsh.hxx>
62 #include <oleobjsh.hxx>
63 #include <chartsh.hxx>
64 #include <graphsh.hxx>
65 #include <mediash.hxx>
66 #include <pgbrksh.hxx>
67 #include <dpobject.hxx>
68 #include <prevwsh.hxx>
69 #include <scextopt.hxx>
70 #include <drawview.hxx>
71 #include <fupoor.hxx>
72 #include <navsett.hxx>
73 #include <scabstdlg.hxx>
74 #include <externalrefmgr.hxx>
75 #include <defaultsoptions.hxx>
76 #include <markdata.hxx>
77 #include <preview.hxx>
78 #include <documentlinkmgr.hxx>
79 #include <gridwin.hxx>
81 #include <com/sun/star/document/XDocumentProperties.hpp>
82 #include <com/sun/star/configuration/theDefaultProvider.hpp>
83 #include <com/sun/star/sheet/XCellRangeMovement.hpp>
84 #include <com/sun/star/sheet/XCellRangeData.hpp>
85 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
86 #include <comphelper/processfactory.hxx>
87 #include <sfx2/lokhelper.hxx>
88 #include <comphelper/flagguard.hxx>
89 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
90 #include <comphelper/lok.hxx>
91 #include <sfx2/sidebar/SidebarController.hxx>
93 using namespace com::sun::star;
94 using namespace sfx2::sidebar;
96 namespace {
98 bool inChartOrMathContext(const ScTabViewShell* pViewShell)
100 SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell);
101 if (pSidebar)
102 return pSidebar->hasChartOrMathContextCurrently();
104 return false;
107 } // anonymous namespace
109 void ScTabViewShell::Activate(bool bMDI)
111 SfxViewShell::Activate(bMDI);
112 bIsActive = true;
113 // here no GrabFocus, otherwise there will be problems when something is edited inplace!
115 if ( bMDI )
117 // for input row (ClearCache)
118 ScModule* pScMod = ScModule::get();
119 pScMod->ViewShellChanged(/*bStopEditing=*/ !comphelper::LibreOfficeKit::isActive());
121 ActivateView( true, bFirstActivate );
123 // update AutoCorrect, if Writer has newly created this
124 UpdateDrawTextOutliner();
126 // RegisterNewTargetNames does not exist anymore
128 SfxViewFrame& rThisFrame = GetViewFrame();
129 if ( mpInputHandler && rThisFrame.HasChildWindow(FID_INPUTLINE_STATUS) )
131 // actually only required for Reload (last version):
132 // The InputWindow remains, but the View along with the InputHandler is newly created,
133 // that is why the InputHandler must be set at the InputWindow.
134 SfxChildWindow* pChild = rThisFrame.GetChildWindow(FID_INPUTLINE_STATUS);
135 if (pChild)
137 ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow());
138 if (pWin && pWin->IsVisible())
140 pWin->NumLinesChanged(); // tdf#150664
141 ScInputHandler* pOldHdl=pWin->GetInputHandler();
143 SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
144 while ( pSh!=nullptr && pOldHdl!=nullptr)
146 // Hmm, what if pSh is a shell for a different document? But as this code
147 // does not seem to be LibreOfficeKit-specific, probably that doesn't
148 // happen, because having multiple documents open simultaneously has of
149 // course not been a problem at all in traditional desktop LibreOffice.
150 // (Unlike in a LibreOfficeKit-based process where it has been a problem.)
151 if (static_cast<ScTabViewShell*>(pSh)->GetInputHandler() == pOldHdl)
153 pOldHdl->ResetDelayTimer();
154 break;
156 pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
159 pWin->SetInputHandler( mpInputHandler.get() );
164 bool isLOK = comphelper::LibreOfficeKit::isActive();
165 UpdateInputHandler( /*bForce=*/ !isLOK, /*bStopEditing=*/ !isLOK );
167 if ( bFirstActivate )
169 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScNavigatorUpdateAll ) );
170 bFirstActivate = false;
172 // ReadExtOptions (view settings from Excel import) must also be done
173 // after the ctor, because of the potential calls to Window::Show.
174 // Even after a bugfix (Window::Show no longer notifies the access
175 // bridge, it's done in ImplSetReallyVisible), there are problems if Window::Show
176 // is called during the ViewShell ctor and reschedules asynchronous calls
177 // (for example from the FmFormShell ctor).
178 ScExtDocOptions* pExtOpt = GetViewData().GetDocument().GetExtDocOptions();
179 if ( pExtOpt && pExtOpt->IsChanged() )
181 GetViewData().ReadExtOptions(*pExtOpt); // Excel view settings
182 SetTabNo( GetViewData().GetTabNo(), true );
183 pExtOpt->SetChanged( false );
187 pScActiveViewShell = this;
189 ScInputHandler* pHdl = pScMod->GetInputHdl(this);
190 if (pHdl)
192 pHdl->SetRefScale( GetViewData().GetZoomX(), GetViewData().GetZoomY() );
195 // update change dialog
197 if ( rThisFrame.HasChildWindow(FID_CHG_ACCEPT) )
199 SfxChildWindow* pChild = rThisFrame.GetChildWindow(FID_CHG_ACCEPT);
200 if (pChild)
202 static_cast<ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg();
206 if(pScMod->IsRefDialogOpen())
208 sal_uInt16 nModRefDlgId=pScMod->GetCurRefDlgId();
209 SfxChildWindow* pChildWnd = rThisFrame.GetChildWindow( nModRefDlgId );
210 if ( pChildWnd )
212 if (auto pController = pChildWnd->GetController())
214 IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pController.get());
215 if (pRefDlg)
216 pRefDlg->ViewShellChanged();
222 // don't call CheckSelectionTransfer here - activating a view should not change the
223 // primary selection (may be happening just because the mouse was moved over the window)
225 if (!inChartOrMathContext(this))
227 ContextChangeEventMultiplexer::NotifyContextChange(
228 GetController(),
229 vcl::EnumContext::Context::Default);
233 void ScTabViewShell::Deactivate(bool bMDI)
235 HideTip();
237 ScDocument& rDoc = GetViewData().GetDocument();
239 ScChangeTrack* pChanges = rDoc.GetChangeTrack();
241 if(pChanges!=nullptr)
243 Link<ScChangeTrack&,void> aLink;
244 pChanges->SetModifiedLink(aLink);
247 SfxViewShell::Deactivate(bMDI);
248 bIsActive = false;
249 ScInputHandler* pHdl = ScModule::get()->GetInputHdl(this);
251 if( bMDI && !comphelper::LibreOfficeKit::isActive())
253 // during shell deactivation, shells must not be switched, or the loop
254 // through the shell stack (in SfxDispatcher::DoDeactivate_Impl) will not work
255 bool bOldDontSwitch = bDontSwitch;
256 bDontSwitch = true;
258 ActivateView( false, false );
260 if ( GetViewFrame().GetFrame().IsInPlace() ) // inplace
261 GetViewData().GetDocShell()->UpdateOle(GetViewData(), true);
263 if ( pHdl )
264 pHdl->NotifyChange( nullptr, true ); // timer-delayed due to document switching
266 if (pScActiveViewShell == this)
267 pScActiveViewShell = nullptr;
269 bDontSwitch = bOldDontSwitch;
271 else
273 HideNoteMarker(); // note marker
275 // in LOK case this could be triggered on every action from other view (doc_setView)
276 // we don't want to hide tooltip only because other view did some action
277 if ( pHdl && !comphelper::LibreOfficeKit::isActive() )
278 pHdl->HideTip(); // Hide formula auto input tip
282 void ScTabViewShell::SetActive()
284 // SFX-View would like to activate itself, since then magical things would happen
285 // (eg else the designer may crash)
286 ActiveGrabFocus();
289 bool ScTabViewShell::PrepareClose(bool bUI)
291 comphelper::FlagRestorationGuard aFlagGuard(bInPrepareClose, true);
293 // Call EnterHandler even in formula mode here,
294 // so a formula change in an embedded object isn't lost
295 // (ScDocShell::PrepareClose isn't called then).
296 ScInputHandler* pHdl = ScModule::get()->GetInputHdl(this);
297 if ( pHdl && pHdl->IsInputMode() )
299 pHdl->EnterHandler();
302 // draw text edit mode must be closed
303 FuPoor* pPoor = GetDrawFuncPtr();
304 if (pPoor && IsDrawTextShell())
306 // "clean" end of text edit, including note handling, subshells and draw func switching,
307 // as in FuDraw and ScTabView::DrawDeselectAll
308 GetViewData().GetDispatcher().Execute( pPoor->GetSlotID(), SfxCallMode::SLOT | SfxCallMode::RECORD );
310 ScDrawView* pDrView = GetScDrawView();
311 if ( pDrView )
313 // force end of text edit, to be safe
314 // ScEndTextEdit must always be used, to ensure correct UndoManager
315 pDrView->ScEndTextEdit();
318 if ( pFormShell )
320 bool bRet = pFormShell->PrepareClose(bUI);
321 if (!bRet)
322 return bRet;
324 return SfxViewShell::PrepareClose(bUI);
327 // calculate zoom for in-place
328 // from the ratio of VisArea and window size of GridWin
330 void ScTabViewShell::UpdateOleZoom()
332 ScDocShell* pDocSh = GetViewData().GetDocShell();
333 if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
335 //TODO/LATER: is there a difference between the two GetVisArea methods?
336 Size aObjSize = static_cast<const SfxObjectShell*>(pDocSh)->GetVisArea().GetSize();
337 if ( !aObjSize.IsEmpty() )
339 vcl::Window* pWin = GetActiveWin();
340 Size aWinHMM = pWin->PixelToLogic(pWin->GetOutputSizePixel(), MapMode(MapUnit::Map100thMM));
341 SetZoomFactor( Fraction( aWinHMM.Width(),aObjSize.Width() ),
342 Fraction( aWinHMM.Height(),aObjSize.Height() ) );
347 void ScTabViewShell::InnerResizePixel( const Point &rOfs, const Size &rSize, bool inplaceEditModeChange )
349 Size aNewSize( rSize );
350 if ( GetViewFrame().GetFrame().IsInPlace() )
352 SvBorder aBorder;
353 GetBorderSize( aBorder, rSize );
354 SetBorderPixel( aBorder );
356 Size aObjSize = GetObjectShell()->GetVisArea().GetSize();
358 Size aSize( rSize );
359 aSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) );
360 aSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) );
362 if ( !aObjSize.IsEmpty() )
364 Size aLogicSize = GetWindow()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM));
365 SfxViewShell::SetZoomFactor( Fraction( aLogicSize.Width(),aObjSize.Width() ),
366 Fraction( aLogicSize.Height(),aObjSize.Height() ) );
369 Point aPos( rOfs );
370 aPos.AdjustX(aBorder.Left() );
371 aPos.AdjustY(aBorder.Top() );
372 GetWindow()->SetPosSizePixel( aPos, aSize );
374 else
376 SvBorder aBorder;
377 GetBorderSize( aBorder, rSize );
378 SetBorderPixel( aBorder );
379 aNewSize.AdjustWidth(aBorder.Left() + aBorder.Right() );
380 aNewSize.AdjustHeight(aBorder.Top() + aBorder.Bottom() );
383 DoResize( rOfs, aNewSize, true ); // rSize = size of gridwin
385 UpdateOleZoom(); // calculate zoom for in-place
387 if (!inplaceEditModeChange)
389 GetViewData().GetDocShell()->SetDocumentModified();
393 void ScTabViewShell::OuterResizePixel( const Point &rOfs, const Size &rSize )
395 SvBorder aBorder;
396 GetBorderSize( aBorder, rSize );
397 SetBorderPixel( aBorder );
399 DoResize( rOfs, rSize ); // position and size of tabview as passed
401 // ForceMove as replacement for Sfx-Move mechanism
402 // (aWinPos must be kept current, so that ForceMove works for Ole deactivation)
404 ForceMove();
407 void ScTabViewShell::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY )
409 // for OLE...
411 Fraction aFrac20( 1,5 );
412 Fraction aFrac400( 4,1 );
414 Fraction aNewX( rZoomX );
415 if ( aNewX < aFrac20 )
416 aNewX = aFrac20;
417 if ( aNewX > aFrac400 )
418 aNewX = aFrac400;
419 Fraction aNewY( rZoomY );
420 if ( aNewY < aFrac20 )
421 aNewY = aFrac20;
422 if ( aNewY > aFrac400 )
423 aNewY = aFrac400;
425 GetViewData().UpdateScreenZoom( aNewX, aNewY );
426 SetZoom( aNewX, aNewY, true );
428 PaintGrid();
429 PaintTop();
430 PaintLeft();
432 SfxViewShell::SetZoomFactor( rZoomX, rZoomY );
435 void ScTabViewShell::QueryObjAreaPixel( tools::Rectangle& rRect ) const
437 // adjust to entire cells (in 1/100 mm)
439 Size aPixelSize = rRect.GetSize();
440 vcl::Window* pWin = const_cast<ScTabViewShell*>(this)->GetActiveWin();
441 Size aLogicSize = pWin->PixelToLogic( aPixelSize );
443 const ScViewData& rViewData = GetViewData();
444 ScDocument& rDoc = rViewData.GetDocument();
445 ScSplitPos ePos = rViewData.GetActivePart();
446 SCCOL nCol = rViewData.GetPosX(WhichH(ePos));
447 SCROW nRow = rViewData.GetPosY(WhichV(ePos));
448 SCTAB nTab = rViewData.GetTabNo();
449 bool bNegativePage = rDoc.IsNegativePage( nTab );
451 tools::Rectangle aLogicRect = rDoc.GetMMRect( nCol, nRow, nCol, nRow, nTab );
452 if ( bNegativePage )
454 // use right edge of aLogicRect, and aLogicSize
455 aLogicRect.SetLeft( aLogicRect.Right() - aLogicSize.Width() + 1 ); // Right() is set below
457 aLogicRect.SetSize( aLogicSize );
459 rViewData.GetDocShell()->SnapVisArea( aLogicRect );
461 rRect.SetSize( pWin->LogicToPixel( aLogicRect.GetSize() ) );
464 void ScTabViewShell::Move()
466 Point aNewPos = GetViewFrame().GetWindow().OutputToScreenPixel(Point());
468 if (aNewPos != aWinPos)
470 StopMarking();
471 aWinPos = aNewPos;
475 void ScTabViewShell::ShowCursor(bool /* bOn */)
477 /*!!! ShowCursor is not called as a pair as in gridwin.
478 here the CursorLockCount for Gridwin must be set directly to 0
480 if (bOn)
481 ShowAllCursors();
482 else
483 HideAllCursors();
487 void ScTabViewShell::WriteUserData(OUString& rData, bool /* bBrowse */)
489 GetViewData().WriteUserData(rData);
492 void ScTabViewShell::WriteUserDataSequence (uno::Sequence < beans::PropertyValue >& rSettings )
494 GetViewData().WriteUserDataSequence(rSettings);
497 void ScTabViewShell::ReadUserData(const OUString& rData, bool /* bBrowse */)
499 if ( !GetViewData().GetDocShell()->IsPreview() )
500 DoReadUserData( rData );
503 void ScTabViewShell::ReadUserDataSequence (const uno::Sequence < beans::PropertyValue >& rSettings )
505 if ( !GetViewData().GetDocShell()->IsPreview() )
506 DoReadUserDataSequence( rSettings );
509 void ScTabViewShell::DoReadUserDataSequence( const uno::Sequence < beans::PropertyValue >& rSettings )
511 vcl::Window* pOldWin = GetActiveWin();
512 bool bFocus = pOldWin && pOldWin->HasFocus();
514 GetViewData().ReadUserDataSequence(rSettings);
515 SetTabNo( GetViewData().GetTabNo(), true );
517 if ( GetViewData().IsPagebreakMode() )
518 SetCurSubShell( GetCurObjectSelectionType(), true );
520 vcl::Window* pNewWin = GetActiveWin();
521 if (pNewWin && pNewWin != pOldWin)
523 SetWindow( pNewWin ); //! is this ViewShell always active???
524 if (bFocus)
525 pNewWin->GrabFocus();
526 WindowChanged(); // drawing layer (for instance #56771#)
529 if (GetViewData().GetHSplitMode() == SC_SPLIT_FIX ||
530 GetViewData().GetVSplitMode() == SC_SPLIT_FIX)
532 InvalidateSplit();
535 ZoomChanged();
537 TestHintWindow();
539 //! if ViewData has more tables than document, remove tables in ViewData
542 // DoReadUserData is also called from ctor when switching from print preview
544 void ScTabViewShell::DoReadUserData( std::u16string_view rData )
546 vcl::Window* pOldWin = GetActiveWin();
547 bool bFocus = pOldWin && pOldWin->HasFocus();
549 GetViewData().ReadUserData(rData);
550 SetTabNo( GetViewData().GetTabNo(), true );
552 if ( GetViewData().IsPagebreakMode() )
553 SetCurSubShell( GetCurObjectSelectionType(), true );
555 vcl::Window* pNewWin = GetActiveWin();
556 if (pNewWin && pNewWin != pOldWin)
558 SetWindow( pNewWin ); //! is this ViewShell always active???
559 if (bFocus)
560 pNewWin->GrabFocus();
561 WindowChanged(); // drawing layer (for instance #56771#)
564 if (GetViewData().GetHSplitMode() == SC_SPLIT_FIX ||
565 GetViewData().GetVSplitMode() == SC_SPLIT_FIX)
567 InvalidateSplit();
570 ZoomChanged();
572 TestHintWindow();
574 //! if ViewData has more tables than document, remove tables in ViewData
577 void ScTabViewShell::UpdateDrawShell()
579 // Called after user interaction that may delete the selected drawing object.
580 // Remove DrawShell if nothing is selected.
582 SdrView* pDrView = GetScDrawView();
583 if ( pDrView && pDrView->GetMarkedObjectList().GetMarkCount() == 0 && !IsDrawSelMode() )
584 SetDrawShell( false );
587 void ScTabViewShell::SetDrawShellOrSub()
589 bActiveDrawSh = true;
591 if(bActiveDrawFormSh)
593 SetCurSubShell(OST_DrawForm);
595 else if(bActiveGraphicSh)
597 SetCurSubShell(OST_Graphic);
599 else if(bActiveMediaSh)
601 SetCurSubShell(OST_Media);
603 else if(bActiveChartSh)
605 SetCurSubShell(OST_Chart);
607 else if(bActiveOleObjectSh)
609 SetCurSubShell(OST_OleObject);
611 else
613 SetCurSubShell(OST_Drawing, true /* force: different toolbars are
614 visible concerning shape type
615 and shape state */);
619 void ScTabViewShell::SetDrawShell( bool bActive )
621 if(bActive)
623 SetCurSubShell(OST_Drawing, true /* force: different toolbars are
624 visible concerning shape type
625 and shape state */);
627 else
629 if(bActiveDrawFormSh || bActiveDrawSh ||
630 bActiveGraphicSh || bActiveMediaSh || bActiveOleObjectSh||
631 bActiveChartSh || bActiveDrawTextSh)
633 SetCurSubShell(OST_Cell);
635 bActiveDrawFormSh=false;
636 bActiveGraphicSh=false;
637 bActiveMediaSh=false;
638 bActiveOleObjectSh=false;
639 bActiveChartSh=false;
642 bool bWasDraw = bActiveDrawSh || bActiveDrawTextSh;
644 bActiveDrawSh = bActive;
645 bActiveDrawTextSh = false;
647 if ( !bActive )
649 ResetDrawDragMode(); // switch off Mirror / Rotate
651 if (bWasDraw && (GetViewData().GetHSplitMode() == SC_SPLIT_FIX ||
652 GetViewData().GetVSplitMode() == SC_SPLIT_FIX))
654 // adjust active part to cursor, etc.
655 MoveCursorAbs( GetViewData().GetCurX(), GetViewData().GetCurY(),
656 SC_FOLLOW_NONE, false, false, true );
661 void ScTabViewShell::SetDrawTextShell( bool bActive )
663 bActiveDrawTextSh = bActive;
664 if ( bActive )
666 bActiveDrawFormSh=false;
667 bActiveGraphicSh=false;
668 bActiveMediaSh=false;
669 bActiveOleObjectSh=false;
670 bActiveChartSh=false;
671 bActiveDrawSh = false;
672 SetCurSubShell(OST_DrawText);
674 else
675 SetCurSubShell(OST_Cell);
679 void ScTabViewShell::SetPivotShell( bool bActive )
681 // SetPivotShell is called from CursorPosChanged every time
682 // -> don't change anything except switching between cell and pivot shell
684 if (eCurOST != OST_Pivot && eCurOST != OST_Cell)
685 return;
687 if ( bActive )
689 bActiveDrawTextSh = bActiveDrawSh = false;
690 bActiveDrawFormSh=false;
691 bActiveGraphicSh=false;
692 bActiveMediaSh=false;
693 bActiveOleObjectSh=false;
694 bActiveChartSh=false;
695 SetCurSubShell(OST_Pivot);
697 else
698 SetCurSubShell(OST_Cell);
701 void ScTabViewShell::SetSparklineShell(bool bActive)
703 if (eCurOST != OST_Sparkline && eCurOST != OST_Cell)
704 return;
706 if (bActive)
708 bActiveDrawTextSh = bActiveDrawSh = false;
709 bActiveDrawFormSh=false;
710 bActiveGraphicSh=false;
711 bActiveMediaSh=false;
712 bActiveOleObjectSh=false;
713 bActiveChartSh=false;
714 SetCurSubShell(OST_Sparkline);
716 else
717 SetCurSubShell(OST_Cell);
720 void ScTabViewShell::SetAuditShell( bool bActive )
722 if ( bActive )
724 bActiveDrawTextSh = bActiveDrawSh = false;
725 bActiveDrawFormSh=false;
726 bActiveGraphicSh=false;
727 bActiveMediaSh=false;
728 bActiveOleObjectSh=false;
729 bActiveChartSh=false;
730 SetCurSubShell(OST_Auditing);
732 else
733 SetCurSubShell(OST_Cell);
736 void ScTabViewShell::SetDrawFormShell( bool bActive )
738 bActiveDrawFormSh = bActive;
740 if(bActiveDrawFormSh)
741 SetCurSubShell(OST_DrawForm);
743 void ScTabViewShell::SetChartShell( bool bActive )
745 bActiveChartSh = bActive;
747 if(bActiveChartSh)
748 SetCurSubShell(OST_Chart);
751 void ScTabViewShell::SetGraphicShell( bool bActive )
753 bActiveGraphicSh = bActive;
755 if(bActiveGraphicSh)
756 SetCurSubShell(OST_Graphic);
759 void ScTabViewShell::SetMediaShell( bool bActive )
761 bActiveMediaSh = bActive;
763 if(bActiveMediaSh)
764 SetCurSubShell(OST_Media);
767 void ScTabViewShell::SetOleObjectShell( bool bActive )
769 bActiveOleObjectSh = bActive;
771 if(bActiveOleObjectSh)
772 SetCurSubShell(OST_OleObject);
773 else
774 SetCurSubShell(OST_Cell);
777 void ScTabViewShell::SetEditShell(EditView* pView, bool bActive )
779 if(bActive)
781 if (pEditShell)
782 pEditShell->SetEditView( pView );
783 else
784 pEditShell.reset( new ScEditShell(pView, GetViewData()) );
786 SetCurSubShell(OST_Editing);
788 else if(bActiveEditSh)
790 SetCurSubShell(OST_Cell);
791 GetViewData().SetEditHighlight(false);
793 bActiveEditSh = bActive;
796 void ScTabViewShell::SetCurSubShell(ObjectSelectionType eOST, bool bForce)
798 ScViewData& rViewData = GetViewData();
799 ScDocShell* pDocSh = rViewData.GetDocShell();
801 if(bDontSwitch) return;
803 if(!pCellShell) // is anyway always used
805 pCellShell.reset(new ScCellShell(GetViewData(), GetFrameWin()));
806 pCellShell->SetRepeatTarget( &aTarget );
809 bool bPgBrk = rViewData.IsPagebreakMode();
811 if(bPgBrk && !pPageBreakShell)
813 pPageBreakShell.reset( new ScPageBreakShell( this ) );
814 pPageBreakShell->SetRepeatTarget( &aTarget );
817 if ( !(eOST!=eCurOST || bForce) )
818 return;
820 bool bCellBrush = false; // "format paint brush" allowed for cells
821 bool bDrawBrush = false; // "format paint brush" allowed for drawing objects
823 if(eCurOST!=OST_NONE) RemoveSubShell();
825 if (pFormShell && !bFormShellAtTop)
826 AddSubShell(*pFormShell); // add below own subshells
828 switch(eOST)
830 case OST_Cell:
832 AddSubShell(*pCellShell);
833 if(bPgBrk) AddSubShell(*pPageBreakShell);
834 bCellBrush = true;
836 break;
837 case OST_Editing:
839 AddSubShell(*pCellShell);
840 if(bPgBrk) AddSubShell(*pPageBreakShell);
842 if(pEditShell)
844 AddSubShell(*pEditShell);
847 break;
848 case OST_DrawText:
850 if ( !pDrawTextShell )
852 pDocSh->MakeDrawLayer();
853 pDrawTextShell.reset( new ScDrawTextObjectBar(GetViewData()) );
855 AddSubShell(*pDrawTextShell);
857 break;
858 case OST_Drawing:
860 if (svx::checkForSelectedCustomShapes(
861 GetScDrawView(), true /* bOnlyExtruded */ )) {
862 if (pExtrusionBarShell == nullptr)
863 pExtrusionBarShell.reset( new svx::ExtrusionBar(this) );
864 AddSubShell( *pExtrusionBarShell );
867 if (svx::checkForSelectedFontWork(
868 GetScDrawView() )) {
869 if (pFontworkBarShell == nullptr)
870 pFontworkBarShell.reset( new svx::FontworkBar(this) );
871 AddSubShell( *pFontworkBarShell );
874 if ( !pDrawShell )
876 pDocSh->MakeDrawLayer();
877 pDrawShell.reset(new ScDrawShell(GetViewData()));
878 pDrawShell->SetRepeatTarget( &aTarget );
880 AddSubShell(*pDrawShell);
881 bDrawBrush = true;
883 break;
885 case OST_DrawForm:
887 if ( !pDrawFormShell )
889 pDocSh->MakeDrawLayer();
890 pDrawFormShell.reset( new ScDrawFormShell(GetViewData()) );
891 pDrawFormShell->SetRepeatTarget( &aTarget );
893 AddSubShell(*pDrawFormShell);
894 bDrawBrush = true;
896 break;
898 case OST_Chart:
900 if ( !pChartShell )
902 pDocSh->MakeDrawLayer();
903 pChartShell.reset( new ScChartShell(GetViewData()) );
904 pChartShell->SetRepeatTarget( &aTarget );
906 AddSubShell(*pChartShell);
907 bDrawBrush = true;
909 break;
911 case OST_OleObject:
913 if ( !pOleObjectShell )
915 pDocSh->MakeDrawLayer();
916 pOleObjectShell.reset( new ScOleObjectShell(GetViewData()) );
917 pOleObjectShell->SetRepeatTarget( &aTarget );
919 AddSubShell(*pOleObjectShell);
920 bDrawBrush = true;
922 break;
924 case OST_Graphic:
926 if ( !pGraphicShell)
928 pDocSh->MakeDrawLayer();
929 pGraphicShell.reset( new ScGraphicShell(GetViewData()) );
930 pGraphicShell->SetRepeatTarget( &aTarget );
932 AddSubShell(*pGraphicShell);
933 bDrawBrush = true;
935 break;
937 case OST_Media:
939 if ( !pMediaShell)
941 pDocSh->MakeDrawLayer();
942 pMediaShell.reset( new ScMediaShell(GetViewData()) );
943 pMediaShell->SetRepeatTarget( &aTarget );
945 AddSubShell(*pMediaShell);
947 break;
949 case OST_Pivot:
951 AddSubShell(*pCellShell);
952 if(bPgBrk) AddSubShell(*pPageBreakShell);
954 if ( !pPivotShell )
956 pPivotShell.reset( new ScPivotShell( this ) );
957 pPivotShell->SetRepeatTarget( &aTarget );
959 AddSubShell(*pPivotShell);
960 bCellBrush = true;
962 break;
963 case OST_Auditing:
965 AddSubShell(*pCellShell);
966 if(bPgBrk) AddSubShell(*pPageBreakShell);
968 if ( !pAuditingShell )
970 pDocSh->MakeDrawLayer(); // the waiting time rather now as on the click
972 pAuditingShell.reset( new ScAuditingShell(GetViewData()) );
973 pAuditingShell->SetRepeatTarget( &aTarget );
975 AddSubShell(*pAuditingShell);
976 bCellBrush = true;
978 break;
979 case OST_Sparkline:
981 AddSubShell(*pCellShell);
982 if(bPgBrk) AddSubShell(*pPageBreakShell);
984 if (!m_pSparklineShell)
986 m_pSparklineShell.reset(new sc::SparklineShell(this));
987 m_pSparklineShell->SetRepeatTarget(&aTarget);
989 AddSubShell(*m_pSparklineShell);
990 bCellBrush = true;
992 break;
993 default:
994 OSL_FAIL("wrong shell requested");
995 break;
998 if (pFormShell && bFormShellAtTop)
999 AddSubShell(*pFormShell); // add on top of own subshells
1001 eCurOST=eOST;
1003 // abort "format paint brush" when switching to an incompatible shell
1004 if ( ( GetBrushDocument() && !bCellBrush ) || ( GetDrawBrushSet() && !bDrawBrush ) )
1005 ResetBrushDocument();
1008 void ScTabViewShell::SetFormShellAtTop( bool bSet )
1010 if ( pFormShell && !bSet )
1011 pFormShell->ForgetActiveControl(); // let the FormShell know it no longer has the focus
1013 if ( bFormShellAtTop != bSet )
1015 bFormShellAtTop = bSet;
1016 SetCurSubShell( GetCurObjectSelectionType(), true );
1020 IMPL_LINK_NOARG(ScTabViewShell, FormControlActivated, LinkParamNone*, void)
1022 // a form control got the focus, so the form shell has to be on top
1023 SetFormShellAtTop( true );
1026 // GetMySubShell / SetMySubShell: simulate old behavior,
1027 // so that there is only one SubShell (only within the 5 own SubShells)
1029 SfxShell* ScTabViewShell::GetMySubShell() const
1031 // GetSubShell() was const before, and GetSubShell(sal_uInt16) should also be const...
1033 sal_uInt16 nPos = 0;
1034 SfxShell* pSub = const_cast<ScTabViewShell*>(this)->GetSubShell(nPos);
1035 while (pSub)
1037 if (pSub == pDrawShell.get() || pSub == pDrawTextShell.get() || pSub == pEditShell.get() ||
1038 pSub == pPivotShell.get() || pSub == pAuditingShell.get() || pSub == pDrawFormShell.get() ||
1039 pSub == pCellShell.get() || pSub == pOleObjectShell.get() || pSub == pChartShell.get() ||
1040 pSub == pGraphicShell.get() || pSub == pMediaShell.get() || pSub == pPageBreakShell.get() ||
1041 pSub == m_pSparklineShell.get())
1043 return pSub; // found
1046 pSub = const_cast<ScTabViewShell*>(this)->GetSubShell(++nPos);
1048 return nullptr; // none from mine present
1051 bool ScTabViewShell::IsDrawTextShell() const
1053 return ( pDrawTextShell && ( GetMySubShell() == pDrawTextShell.get() ) );
1056 bool ScTabViewShell::IsAuditShell() const
1058 return ( pAuditingShell && ( GetMySubShell() == pAuditingShell.get() ) );
1061 void ScTabViewShell::SetDrawTextUndo( SfxUndoManager* pNewUndoMgr )
1063 // Default: undo manager for DocShell
1064 if (!pNewUndoMgr)
1065 pNewUndoMgr = GetViewData().GetDocShell()->GetUndoManager();
1067 if (pDrawTextShell)
1069 pDrawTextShell->SetUndoManager(pNewUndoMgr);
1070 ScDocShell* pDocSh = GetViewData().GetDocShell();
1071 if ( pNewUndoMgr == pDocSh->GetUndoManager() &&
1072 !pDocSh->GetDocument().IsUndoEnabled() )
1074 pNewUndoMgr->SetMaxUndoActionCount( 0 );
1077 else
1079 OSL_FAIL("SetDrawTextUndo without DrawTextShell");
1083 ScTabViewShell* ScTabViewShell::GetActiveViewShell()
1085 return dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() );
1088 SfxPrinter* ScTabViewShell::GetPrinter( bool bCreate )
1090 // printer is always present (is created for the FontList already on start-up)
1091 return GetViewData().GetDocShell()->GetPrinter(bCreate);
1094 sal_uInt16 ScTabViewShell::SetPrinter( SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags )
1096 return GetViewData().GetDocShell()->SetPrinter( pNewPrinter, nDiffFlags );
1099 bool ScTabViewShell::HasPrintOptionsPage() const
1101 return true;
1104 std::unique_ptr<SfxTabPage> ScTabViewShell::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rOptions )
1106 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1107 ::CreateTabPage ScTpPrintOptionsCreate = pFact->GetTabPageCreatorFunc(RID_SC_TP_PRINT);
1108 if ( ScTpPrintOptionsCreate )
1109 return ScTpPrintOptionsCreate(pPage, pController, &rOptions);
1110 return nullptr;
1113 void ScTabViewShell::StopEditShell()
1115 if ( pEditShell != nullptr && !bDontSwitch )
1116 SetEditShell(nullptr, false );
1119 // close handler to ensure function of dialog:
1121 IMPL_LINK_NOARG(ScTabViewShell, SimpleRefClose, const OUString*, void)
1123 SfxInPlaceClient* pClient = GetIPClient();
1124 if ( pClient && pClient->IsObjectInPlaceActive() )
1126 // If range selection was started with an active embedded object,
1127 // switch back to original sheet (while the dialog is still open).
1129 SetTabNo( GetViewData().GetRefTabNo() );
1132 ScSimpleRefDlgWrapper::SetAutoReOpen( true );
1135 // handlers to call UNO listeners:
1137 static ScTabViewObj* lcl_GetViewObj( const ScTabViewShell& rShell )
1139 ScTabViewObj* pRet = nullptr;
1140 SfxViewFrame& rViewFrame = rShell.GetViewFrame();
1141 SfxFrame& rFrame = rViewFrame.GetFrame();
1142 uno::Reference<frame::XController> xController = rFrame.GetController();
1143 if (xController.is())
1144 pRet = dynamic_cast<ScTabViewObj*>( xController.get() );
1145 return pRet;
1148 IMPL_LINK( ScTabViewShell, SimpleRefDone, const OUString&, aResult, void )
1150 ScTabViewObj* pImpObj = lcl_GetViewObj( *this );
1151 if ( pImpObj )
1152 pImpObj->RangeSelDone( aResult );
1155 IMPL_LINK( ScTabViewShell, SimpleRefAborted, const OUString&, rResult, void )
1157 ScTabViewObj* pImpObj = lcl_GetViewObj( *this );
1158 if ( pImpObj )
1159 pImpObj->RangeSelAborted( rResult );
1162 IMPL_LINK( ScTabViewShell, SimpleRefChange, const OUString&, rResult, void )
1164 ScTabViewObj* pImpObj = lcl_GetViewObj( *this );
1165 if ( pImpObj )
1166 pImpObj->RangeSelChanged( rResult );
1169 void ScTabViewShell::StartSimpleRefDialog(
1170 const OUString& rTitle, const OUString& rInitVal,
1171 bool bCloseOnButtonUp, bool bSingleCell, bool bMultiSelection )
1173 SfxViewFrame& rViewFrm = GetViewFrame();
1175 if ( GetActiveViewShell() != this )
1177 // #i18833# / #i34499# The API method can be called for a view that's not active.
1178 // Then the view has to be activated first, the same way as in Execute for SID_CURRENTDOC.
1179 // Can't use GrabFocus here, because it needs to take effect immediately.
1181 rViewFrm.GetFrame().Appear();
1184 sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId();
1186 ScModule::get()->SetRefDialog(nId, true, &rViewFrm);
1188 ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(rViewFrm.GetChildWindow( nId ));
1189 if (!pWnd)
1190 return;
1192 pWnd->SetCloseHdl( LINK( this, ScTabViewShell, SimpleRefClose ) );
1193 pWnd->SetUnoLinks( LINK( this, ScTabViewShell, SimpleRefDone ),
1194 LINK( this, ScTabViewShell, SimpleRefAborted ),
1195 LINK( this, ScTabViewShell, SimpleRefChange ) );
1196 pWnd->SetRefString( rInitVal );
1197 pWnd->SetFlags( bCloseOnButtonUp, bSingleCell, bMultiSelection );
1198 ScSimpleRefDlgWrapper::SetAutoReOpen( false );
1199 if (auto xWin = pWnd->GetController())
1200 xWin->set_title(rTitle);
1201 pWnd->StartRefInput();
1204 void ScTabViewShell::StopSimpleRefDialog()
1206 SfxViewFrame& rViewFrm = GetViewFrame();
1207 sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId();
1209 ScSimpleRefDlgWrapper* pWnd = static_cast<ScSimpleRefDlgWrapper*>(rViewFrm.GetChildWindow( nId ));
1210 if (pWnd)
1212 if (auto pWin = pWnd->GetController())
1213 pWin->response(RET_CLOSE);
1217 bool ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt)
1219 ScModule* pScMod = ScModule::get();
1221 SfxViewFrame& rThisFrame = GetViewFrame();
1222 if ( rThisFrame.GetChildWindow( SID_OPENDLG_FUNCTION ) )
1223 return false;
1225 vcl::KeyCode aCode = rKEvt.GetKeyCode();
1226 bool bShift = aCode.IsShift();
1227 bool bControl = aCode.IsMod1();
1228 bool bAlt = aCode.IsMod2();
1229 sal_uInt16 nCode = aCode.GetCode();
1230 bool bUsed = false;
1231 bool bInPlace = pScMod->IsEditMode(); // Editengine gets all
1232 bool bAnyEdit = pScMod->IsInputMode(); // only characters & backspace
1233 bool bDraw = IsDrawTextEdit();
1235 HideNoteMarker(); // note marker
1237 // don't do extra HideCursor/ShowCursor calls if EnterHandler will switch to a different sheet
1238 bool bOnRefSheet = ( GetViewData().GetRefTabNo() == GetViewData().GetTabNo() );
1239 bool bHideCursor = ( ( nCode == KEY_RETURN && bInPlace ) || nCode == KEY_TAB ) && bOnRefSheet;
1241 if (bHideCursor)
1242 HideAllCursors();
1244 ScDocument& rDoc = GetViewData().GetDocument();
1245 rDoc.KeyInput(); // TimerDelays etc.
1247 if( bInPlace )
1249 bUsed = pScMod->InputKeyEvent( rKEvt ); // input
1250 if( !bUsed )
1251 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators
1253 else if( bAnyEdit )
1255 bool bIsType = false;
1256 sal_uInt16 nModi = aCode.GetModifier();
1257 sal_uInt16 nGroup = aCode.GetGroup();
1259 if ( nGroup == KEYGROUP_NUM || nGroup == KEYGROUP_ALPHA || nGroup == 0 )
1260 if ( !bControl && !bAlt )
1261 bIsType = true;
1263 if ( nGroup == KEYGROUP_MISC )
1264 switch ( nCode )
1266 case KEY_RETURN:
1267 bIsType = bControl && !bAlt; // Control, Shift-Control-Return
1268 if ( !bIsType && nModi == 0 )
1270 // Does the Input Handler also want a simple Return?
1272 ScInputHandler* pHdl = pScMod->GetInputHdl(this);
1273 bIsType = pHdl && pHdl->TakesReturn();
1275 break;
1276 case KEY_SPACE:
1277 bIsType = !bControl && !bAlt; // without modifier or Shift-Space
1278 break;
1279 case KEY_ESCAPE:
1280 bIsType = (nModi == 0); // only without modifier
1281 break;
1282 default:
1283 bIsType = true;
1285 else if (nCode == KEY_RIGHT && !bControl && !bShift && !bAlt)
1287 ScInputHandler* pHdl = pScMod->GetInputHdl(this);
1288 bIsType = pHdl && pHdl->HasPartialComplete();
1291 if( bIsType )
1292 bUsed = pScMod->InputKeyEvent( rKEvt ); // input
1294 if( !bUsed )
1295 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators
1297 if ( !bUsed && !bIsType && nCode != KEY_RETURN ) // input once again afterwards
1298 bUsed = pScMod->InputKeyEvent( rKEvt );
1300 else
1302 // special case: copy/cut for multiselect -> error message
1303 // (Slot is disabled, so SfxViewShell::KeyInput would be swallowed without a comment)
1304 KeyFuncType eFunc = aCode.GetFunction();
1305 if ( eFunc == KeyFuncType::CUT )
1307 ScRange aDummy;
1308 ScMarkType eMarkType = GetViewData().GetSimpleArea( aDummy );
1309 if (eMarkType != SC_MARK_SIMPLE)
1311 ErrorMessage(STR_NOMULTISELECT);
1312 bUsed = true;
1315 if (!bUsed)
1316 bUsed = SfxViewShell::KeyInput( rKEvt ); // accelerators
1318 // during inplace editing, some slots are handled by the
1319 // container app and are executed during Window::KeyInput.
1320 // -> don't pass keys to input handler that would be used there
1321 // but should call slots instead.
1322 bool bParent = ( GetViewFrame().GetFrame().IsInPlace() && eFunc != KeyFuncType::DONTKNOW );
1324 if( !bUsed && !bDraw && nCode != KEY_RETURN && !bParent )
1325 bUsed = pScMod->InputKeyEvent( rKEvt, true ); // input
1328 if (!bInPlace && !bUsed && !bDraw)
1330 switch (nCode)
1332 case KEY_RETURN:
1334 bool bNormal = !bControl && !bAlt;
1335 if ( !bAnyEdit && bNormal )
1337 // Depending on options, Enter switches to edit mode.
1338 const ScInputOptions& rOpt = pScMod->GetInputOptions();
1339 if ( rOpt.GetEnterEdit() )
1341 pScMod->SetInputMode( SC_INPUT_TABLE );
1342 bUsed = true;
1346 bool bEditReturn = bControl && !bShift; // pass on to edit engine
1347 if ( !bUsed && !bEditReturn )
1349 if ( bOnRefSheet )
1350 HideAllCursors();
1352 ScEnterMode nMode = ScEnterMode::NORMAL;
1353 if ( bShift && bControl )
1354 nMode = ScEnterMode::MATRIX;
1355 else if ( bAlt )
1356 nMode = ScEnterMode::BLOCK;
1357 pScMod->InputEnterHandler(nMode);
1359 if (nMode == ScEnterMode::NORMAL)
1361 if( bShift )
1362 GetViewData().GetDispatcher().Execute( SID_CURSORENTERUP,
1363 SfxCallMode::SLOT | SfxCallMode::RECORD );
1364 else
1365 GetViewData().GetDispatcher().Execute( SID_CURSORENTERDOWN,
1366 SfxCallMode::SLOT | SfxCallMode::RECORD );
1368 else
1369 UpdateInputHandler(true);
1371 if ( bOnRefSheet )
1372 ShowAllCursors();
1374 // here no UpdateInputHandler, since during reference input on another
1375 // document this ViewShell is not the one that is used for input.
1377 bUsed = true;
1380 break;
1384 // hard-code Alt-Cursor key, since Alt is not configurable
1386 if ( !bUsed && bAlt && !bControl )
1388 sal_uInt16 nSlotId = 0;
1389 switch (nCode)
1391 case KEY_UP:
1392 ModifyCellSize( DIR_TOP, bShift );
1393 bUsed = true;
1394 break;
1395 case KEY_DOWN:
1396 ModifyCellSize( DIR_BOTTOM, bShift );
1397 bUsed = true;
1398 break;
1399 case KEY_LEFT:
1400 ModifyCellSize( DIR_LEFT, bShift );
1401 bUsed = true;
1402 break;
1403 case KEY_RIGHT:
1404 ModifyCellSize( DIR_RIGHT, bShift );
1405 bUsed = true;
1406 break;
1407 case KEY_PAGEUP:
1408 nSlotId = bShift ? SID_CURSORPAGELEFT_SEL : SID_CURSORPAGELEFT_;
1409 break;
1410 case KEY_PAGEDOWN:
1411 nSlotId = bShift ? SID_CURSORPAGERIGHT_SEL : SID_CURSORPAGERIGHT_;
1412 break;
1413 case KEY_EQUAL:
1415 // #tdf39302: Use "Alt + =" for autosum
1416 if ( !bAnyEdit ) // Ignore shortcut if currently editing a cell
1418 ScInputHandler* pHdl = pScMod->GetInputHdl(this);
1419 if ( pHdl )
1421 ScInputWindow* pWin = pHdl->GetInputWindow();
1422 if ( pWin )
1424 bool bRangeFinder = false;
1425 bool bSubTotal = false;
1426 pWin->AutoSum( bRangeFinder, bSubTotal, ocSum );
1430 bUsed = true;
1431 break;
1435 if ( nSlotId )
1437 GetViewData().GetDispatcher().Execute( nSlotId, SfxCallMode::SLOT | SfxCallMode::RECORD );
1438 bUsed = true;
1442 // use Ctrl+Alt+Shift+arrow keys to move the cursor in cells
1443 // while keeping the last selection
1444 if ( !bUsed && bAlt && bControl && bShift)
1446 sal_uInt16 nSlotId = 0;
1447 switch (nCode)
1449 case KEY_UP:
1450 nSlotId = SID_CURSORUP;
1451 break;
1452 case KEY_DOWN:
1453 nSlotId = SID_CURSORDOWN;
1454 break;
1455 case KEY_LEFT:
1456 nSlotId = SID_CURSORLEFT;
1457 break;
1458 case KEY_RIGHT:
1459 nSlotId = SID_CURSORRIGHT;
1460 break;
1461 case KEY_PAGEUP:
1462 nSlotId = SID_CURSORPAGEUP;
1463 break;
1464 case KEY_PAGEDOWN:
1465 nSlotId = SID_CURSORPAGEDOWN;
1466 break;
1467 case KEY_HOME:
1468 nSlotId = SID_CURSORHOME;
1469 break;
1470 case KEY_END:
1471 nSlotId = SID_CURSOREND;
1472 break;
1473 default:
1474 nSlotId = 0;
1475 break;
1477 if ( nSlotId )
1479 sal_uInt16 nMode = GetLockedModifiers();
1480 LockModifiers(KEY_MOD1);
1481 GetViewData().GetDispatcher().Execute( nSlotId, SfxCallMode::SLOT | SfxCallMode::RECORD );
1482 LockModifiers(nMode);
1483 bUsed = true;
1486 if (bHideCursor)
1487 ShowAllCursors();
1489 return bUsed;
1492 bool ScTabViewShell::SfxKeyInput(const KeyEvent& rKeyEvent)
1494 return SfxViewShell::KeyInput( rKeyEvent );
1497 bool ScTabViewShell::KeyInput( const KeyEvent &rKeyEvent )
1499 return TabKeyInput( rKeyEvent );
1502 void ScTabViewShell::Construct( TriState nForceDesignMode )
1504 SfxApplication* pSfxApp = SfxGetpApp();
1505 ScDocShell* pDocSh = GetViewData().GetDocShell();
1506 ScDocument& rDoc = pDocSh->GetDocument();
1507 bReadOnly = pDocSh->IsReadOnly();
1508 bIsActive = false;
1510 EnableAutoSpell(ScModule::GetAutoSpellProperty());
1512 SetName(u"View"_ustr); // for SBX
1513 Color aColBlack( COL_BLACK );
1514 ScModule* mod = ScModule::get();
1515 SetPool(&mod->GetPool());
1516 SetWindow( GetActiveWin() );
1518 pCurFrameLine.reset( new ::editeng::SvxBorderLine(&aColBlack, 20, SvxBorderLineStyle::SOLID) );
1519 StartListening(*GetViewData().GetDocShell(), DuplicateHandling::Prevent);
1520 StartListening(GetViewFrame(), DuplicateHandling::Prevent);
1521 StartListening(*pSfxApp, DuplicateHandling::Prevent); // #i62045# #i62046# application is needed for Calc's own hints
1523 SfxViewFrame* pFirst = SfxViewFrame::GetFirst(pDocSh);
1524 bool bFirstView = !pFirst
1525 || (pFirst == &GetViewFrame() && !SfxViewFrame::GetNext(*pFirst,pDocSh));
1527 if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1529 //TODO/LATER: is there a difference between the two GetVisArea methods?
1530 tools::Rectangle aVisArea = static_cast<const SfxObjectShell*>(pDocSh)->GetVisArea();
1532 SCTAB nVisTab = rDoc.GetVisibleTab();
1533 if (!rDoc.HasTable(nVisTab))
1535 nVisTab = 0;
1536 rDoc.SetVisibleTab(nVisTab);
1538 SetTabNo( nVisTab );
1539 bool bNegativePage = rDoc.IsNegativePage( nVisTab );
1540 // show the right cells
1541 GetViewData().SetScreenPos( bNegativePage ? aVisArea.TopRight() : aVisArea.TopLeft() );
1543 if ( GetViewFrame().GetFrame().IsInPlace() ) // inplace
1545 pDocSh->SetInplace( true ); // already initiated like this
1546 if (rDoc.IsEmbedded())
1547 rDoc.ResetEmbedded(); // no blue mark
1549 else if ( bFirstView )
1551 pDocSh->SetInplace( false );
1552 GetViewData().RefreshZoom(); // recalculate PPT
1553 if (!rDoc.IsEmbedded())
1554 rDoc.SetEmbedded( rDoc.GetVisibleTab(), aVisArea ); // mark VisArea
1558 // ViewInputHandler
1559 // Each task now has its own InputWindow,
1560 // therefore either should each task get its own InputHandler,
1561 // or the InputWindow should create its own InputHandler
1562 // (then always search via InputWindow and only if not found
1563 // use the InputHandler of the App).
1564 // As an intermediate solution each View gets its own InputHandler,
1565 // which only yields problems if two Views are in one task window.
1566 mpInputHandler.reset(new ScInputHandler);
1568 // old version:
1569 // if ( !GetViewFrame().ISA(SfxTopViewFrame) ) // OLE or Plug-In
1570 // pInputHandler = new ScInputHandler;
1572 // create FormShell before MakeDrawView, so that DrawView can be registered at the
1573 // FormShell in every case
1574 // the FormShell is pushed in the first activate
1575 pFormShell.reset( new FmFormShell(this) );
1576 pFormShell->SetControlActivationHandler( LINK( this, ScTabViewShell, FormControlActivated ) );
1578 // DrawView must not be created in TabView - ctor,
1579 // if the ViewShell is not yet constructed...
1580 if (rDoc.GetDrawLayer())
1581 MakeDrawView( nForceDesignMode );
1582 ViewOptionsHasChanged(false, false); // possibly also creates DrawView
1584 SfxUndoManager* pMgr = pDocSh->GetUndoManager();
1585 SetUndoManager( pMgr );
1586 pFormShell->SetUndoManager( pMgr );
1587 if ( !rDoc.IsUndoEnabled() )
1589 pMgr->SetMaxUndoActionCount( 0 );
1591 SetRepeatTarget( &aTarget );
1592 pFormShell->SetRepeatTarget( &aTarget );
1594 if ( bFirstView ) // first view?
1596 rDoc.SetDocVisible( true ); // used when creating new sheets
1597 if ( pDocSh->IsEmpty() )
1599 // set first sheet's RTL flag (following will already be initialized because of SetDocVisible)
1600 rDoc.SetLayoutRTL( 0, ScGlobal::IsSystemRTL() );
1602 // append additional sheets (not for OLE object)
1603 if ( pDocSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
1605 // Get the customized initial tab count
1606 const ScDefaultsOptions& rOpt = mod->GetDefaultsOptions();
1607 SCTAB nInitTabCount = rOpt.GetInitTabCount();
1609 for (SCTAB i=1; i<nInitTabCount; i++)
1610 rDoc.MakeTable(i,false);
1613 pDocSh->SetEmpty( false ); // #i6232# make sure this is done only once
1616 // ReadExtOptions is now in Activate
1618 // link update no nesting
1619 if ( pDocSh->GetCreateMode() != SfxObjectCreateMode::INTERNAL &&
1620 pDocSh->IsUpdateEnabled() ) // #105575#; update only in the first creation of the ViewShell
1622 // Check if there are any external data.
1623 bool bLink = rDoc.GetExternalRefManager()->hasExternalData();
1624 if (!bLink)
1626 // #i100042# sheet links can still exist independently from external formula references
1627 SCTAB nTabCount = rDoc.GetTableCount();
1628 for (SCTAB i=0; i<nTabCount && !bLink; i++)
1629 if (rDoc.IsLinked(i))
1630 bLink = true;
1632 if (!bLink)
1634 const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager();
1635 if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasDdeOrOleOrWebServiceLinks())
1636 bLink = true;
1638 if (bLink)
1640 if ( !pFirst )
1641 pFirst = &GetViewFrame();
1643 if(mod->GetCurRefDlgId()==0)
1645 pFirst->GetDispatcher()->Execute( SID_UPDATETABLINKS,
1646 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
1649 else
1651 // No links yet, but loading an existing document may have
1652 // disabled link update but there's no "Allow updating" infobar
1653 // that could enable it again. So in order to enable the user
1654 // to add formulas with external references allow link updates
1655 // again.
1656 pDocSh->AllowLinkUpdate();
1659 bool bReImport = false; // update imported data
1660 ScDBCollection* pDBColl = rDoc.GetDBCollection();
1661 if ( pDBColl )
1663 const ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs();
1664 bReImport = std::any_of(rDBs.begin(), rDBs.end(),
1665 [](const std::unique_ptr<ScDBData>& rxDB) { return rxDB->IsStripData() && rxDB->HasImportParam() && !rxDB->HasImportSelection(); });
1667 if (bReImport)
1669 if ( !pFirst )
1670 pFirst = &GetViewFrame();
1671 if(mod->GetCurRefDlgId()==0)
1673 pFirst->GetDispatcher()->Execute( SID_REIMPORT_AFTER_LOAD,
1674 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
1680 UpdateAutoFillMark();
1682 // ScDispatchProviderInterceptor registers itself in ctor
1683 xDisProvInterceptor = new ScDispatchProviderInterceptor( this );
1685 bFirstActivate = true; // delay NavigatorUpdate until Activate()
1687 // #105575#; update only in the first creation of the ViewShell
1688 pDocSh->SetUpdateEnabled(false);
1690 if ( GetViewFrame().GetFrame().IsInPlace() )
1691 UpdateHeaderWidth(); // The inplace activation requires headers to be calculated
1693 SvBorder aBorder;
1694 GetBorderSize( aBorder, Size() );
1695 SetBorderPixel( aBorder );
1698 class ScViewOptiChangesListener : public cppu::WeakImplHelper<util::XChangesListener>
1700 public:
1701 ScViewOptiChangesListener(ScTabViewShell&);
1702 void stopListening();
1704 virtual void SAL_CALL changesOccurred(const util::ChangesEvent& Event) override;
1705 virtual void SAL_CALL disposing(const lang::EventObject& rEvent) override;
1707 private:
1708 ScTabViewShell& mrViewShell;
1709 uno::Reference<util::XChangesNotifier> m_xViewChangesNotifier;
1710 uno::Reference<util::XChangesNotifier> m_xColorSchemeChangesNotifier;
1713 void ScViewOptiChangesListener::stopListening()
1715 if (m_xViewChangesNotifier)
1716 m_xViewChangesNotifier->removeChangesListener(this);
1717 if (m_xColorSchemeChangesNotifier)
1718 m_xColorSchemeChangesNotifier->removeChangesListener(this);
1721 // virtual
1722 void SAL_CALL ScViewOptiChangesListener::changesOccurred(const util::ChangesEvent& rEvent)
1724 for (const auto& change : rEvent.Changes)
1726 if (OUString sChangedEntry;
1727 (change.Accessor >>= sChangedEntry) && sChangedEntry == "ColumnRowHighlighting")
1729 mrViewShell.HighlightOverlay();
1730 break;
1733 if (OUString sChangedEntry; (change.Accessor >>= sChangedEntry) && sChangedEntry ==
1734 "ColorSchemes/org.openoffice.Office.UI:ColorScheme['COLOR_SCHEME_LIBREOFFICE_AUTOMATIC']/CalcCellFocus/Color")
1736 mrViewShell.GetActiveWin()->UpdateCursorOverlay();
1737 mrViewShell.GetActiveWin()->UpdateAutoFillOverlay();
1738 mrViewShell.GetActiveWin()->UpdateHighlightOverlay();
1739 break;
1744 // virtual
1745 void SAL_CALL ScViewOptiChangesListener::disposing(const lang::EventObject& /* rEvent */)
1747 m_xViewChangesNotifier.clear();
1748 m_xColorSchemeChangesNotifier.clear();
1751 ScViewOptiChangesListener::ScViewOptiChangesListener(ScTabViewShell& rViewShell)
1752 : mrViewShell(rViewShell)
1754 // add a listener for configuration changes (ColumnRowHighlighting Checkbox)
1755 uno::Reference<lang::XMultiServiceFactory> xConfigurationProvider(
1756 configuration::theDefaultProvider::get(comphelper::getProcessComponentContext()));
1758 beans::NamedValue aViewProperty{ u"nodepath"_ustr,
1759 uno::Any(u"/org.openoffice.Office.Calc/Content/Display"_ustr) };
1761 beans::NamedValue aColorSchemeProperty{ u"nodepath"_ustr,
1762 uno::Any(u"/org.openoffice.Office.UI/ColorScheme"_ustr) };
1764 uno::Reference<uno::XInterface> xViewConfigurationAccess
1765 = xConfigurationProvider->createInstanceWithArguments(
1766 u"com.sun.star.configuration.ConfigurationAccess"_ustr, { uno::Any(aViewProperty) });
1768 uno::Reference<uno::XInterface> xColorSchemeConfigurationAccess
1769 = xConfigurationProvider->createInstanceWithArguments(
1770 u"com.sun.star.configuration.ConfigurationAccess"_ustr, { uno::Any(aColorSchemeProperty) });
1772 m_xViewChangesNotifier.set(xViewConfigurationAccess, uno::UNO_QUERY);
1773 m_xColorSchemeChangesNotifier.set(xColorSchemeConfigurationAccess, uno::UNO_QUERY);
1775 if (m_xViewChangesNotifier)
1776 m_xViewChangesNotifier->addChangesListener(this);
1778 if (m_xColorSchemeChangesNotifier)
1779 m_xColorSchemeChangesNotifier->addChangesListener(this);
1782 static void lcl_RemoveCells(uno::Reference<sheet::XSpreadsheet>& rSheet, sal_uInt16 nSheet,
1783 sal_uInt32 nStartColumn, sal_uInt32 nStartRow, sal_uInt32 nEndColumn,
1784 sal_uInt32 nEndRow, bool bRows)
1786 table::CellRangeAddress aCellRange(nSheet, nStartColumn, nStartRow, nEndColumn, nEndRow);
1787 uno::Reference<sheet::XCellRangeMovement> xCRM(rSheet, uno::UNO_QUERY);
1789 if (xCRM.is())
1791 if (bRows)
1792 xCRM->removeRange(aCellRange, sheet::CellDeleteMode_UP);
1793 else
1794 xCRM->removeRange(aCellRange, sheet::CellDeleteMode_LEFT);
1798 /* For rows (bool bRows), I am passing reference to already existing sequence, and comparing the required
1799 * columns, whereas for columns, I am creating a sequence for each, with only the checked entries
1800 * in the dialog.
1802 static bool lcl_CheckInArray(std::vector<uno::Sequence<uno::Any>>& nUniqueRecords,
1803 const uno::Sequence<uno::Any>& nCurrentRecord,
1804 const std::vector<int>& rSelectedEntries, bool bRows)
1806 for (size_t m = 0; m < nUniqueRecords.size(); ++m)
1808 bool bIsDuplicate = true;
1809 for (size_t n = 0; n < rSelectedEntries.size(); ++n)
1811 // when the first different element is found
1812 int nColumn = (bRows ? rSelectedEntries[n] : n);
1813 if (nUniqueRecords[m][nColumn] != (bRows ? nCurrentRecord[rSelectedEntries[n]] : nCurrentRecord[n]))
1815 bIsDuplicate = false;
1816 break;
1820 if (bIsDuplicate)
1821 return true;
1823 return false;
1826 uno::Reference<css::sheet::XSpreadsheet> ScTabViewShell::GetRangeWithSheet(css::table::CellRangeAddress& rRangeData, bool& bHasData, bool bHasUnoArguments)
1828 // get spreadsheet document model & controller
1829 uno::Reference<frame::XModel> xModel(GetViewData().GetDocShell()->GetModel());
1830 uno::Reference<frame::XController> xController(xModel->getCurrentController());
1832 // spreadsheet's extension of com.sun.star.frame.Controller service
1833 uno::Reference<sheet::XSpreadsheetView> SpreadsheetDocument(xController, uno::UNO_QUERY);
1834 uno::Reference<sheet::XSpreadsheet> ActiveSheet = SpreadsheetDocument->getActiveSheet();
1836 if (!bHasUnoArguments)
1838 // get the selection supplier, extract selection in XSheetCellRange
1839 uno::Reference<view::XSelectionSupplier> xSelectionSupplier(SpreadsheetDocument, uno::UNO_QUERY);
1840 uno::Any Selection = xSelectionSupplier->getSelection();
1841 uno::Reference<sheet::XSheetCellRange> SelectedCellRange;
1842 Selection >>= SelectedCellRange;
1844 // Get the Selected Range Address.
1845 uno::Reference<sheet::XCellRangeAddressable> xAddressable( SelectedCellRange, uno::UNO_QUERY);
1846 if (xAddressable.is())
1847 rRangeData = xAddressable->getRangeAddress();
1848 else
1850 bHasData = false;
1851 return ActiveSheet;
1855 SCCOL nStartColumn = rRangeData.StartColumn;
1856 SCCOL nEndColumn = rRangeData.EndColumn;
1857 SCROW nStartRow = rRangeData.StartRow;
1858 SCROW nEndRow = rRangeData.EndRow;
1860 // shrink to intersection of data and selection. If no intersection ==> return
1861 bHasData = GetViewData().GetDocument().ShrinkToDataArea(rRangeData.Sheet, nStartColumn, nStartRow, nEndColumn, nEndRow);
1863 rRangeData.StartColumn = nStartColumn;
1864 rRangeData.StartRow = nStartRow;
1865 rRangeData.EndColumn = nEndColumn;
1866 rRangeData.EndRow = nEndRow;
1868 return ActiveSheet;
1871 void ScTabViewShell::ExtendSingleSelection(css::table::CellRangeAddress& rRangeData)
1873 SCCOL aStartCol(rRangeData.StartColumn);
1874 SCCOL aEndCol(rRangeData.EndColumn);
1875 SCROW aStartRow(rRangeData.StartRow);
1876 SCROW aEndRow(rRangeData.EndRow);
1878 GetViewData().GetDocument().GetDataArea(rRangeData.Sheet, aStartCol, aStartRow, aEndCol,
1879 aEndRow, true, false);
1880 MarkRange(ScRange(ScAddress(aStartCol, aStartRow, rRangeData.Sheet),
1881 ScAddress(aEndCol, aEndRow, rRangeData.Sheet)));
1883 rRangeData.StartRow = aStartRow;
1884 rRangeData.StartColumn = aStartCol;
1885 rRangeData.EndRow = aEndRow;
1886 rRangeData.EndColumn = aEndCol;
1889 /* bool bRemove == false ==> highlight duplicate rows */
1890 void ScTabViewShell::HandleDuplicateRecords(css::uno::Reference<css::sheet::XSpreadsheet> ActiveSheet,
1891 const css::table::CellRangeAddress& aRange, bool bRemove,
1892 bool bIncludesHeaders, bool bDuplicateRows,
1893 const std::vector<int>& rSelectedEntries)
1895 if (rSelectedEntries.size() == 0)
1897 Unmark();
1898 return;
1901 uno::Reference<frame::XModel> xModel(GetViewData().GetDocShell()->GetModel());
1902 uno::Reference<sheet::XSheetCellRange> xSheetRange(
1903 ActiveSheet->getCellRangeByPosition(aRange.StartColumn, aRange.StartRow, aRange.EndColumn, aRange.EndRow),
1904 uno::UNO_QUERY);
1907 uno::Reference<sheet::XCellRangeData> xCellRangeData(xSheetRange, uno::UNO_QUERY);
1908 uno::Sequence<uno::Sequence<uno::Any>> aDataArray = xCellRangeData->getDataArray();
1910 uno::Reference< document::XUndoManagerSupplier > xUndoManager( xModel, uno::UNO_QUERY );
1911 uno::Reference<document::XActionLockable> xLockable(xModel, uno::UNO_QUERY);
1913 uno::Reference<sheet::XCalculatable> xCalculatable(xModel, uno::UNO_QUERY);
1914 bool bAutoCalc = xCalculatable->isAutomaticCalculationEnabled();
1916 comphelper::ScopeGuard aUndoContextGuard(
1917 [&xUndoManager, &xLockable, &xModel, &xCalculatable, &bAutoCalc, &bRemove] {
1918 xUndoManager->getUndoManager()->leaveUndoContext();
1919 if (bRemove)
1920 xCalculatable->enableAutomaticCalculation(bAutoCalc);
1921 xLockable->removeActionLock();
1922 if (xModel->hasControllersLocked())
1923 xModel->unlockControllers();
1926 xModel->lockControllers();
1927 xLockable->addActionLock();
1928 if (bRemove)
1929 xCalculatable->enableAutomaticCalculation(true);
1930 xUndoManager->getUndoManager()->enterUndoContext("HandleDuplicateRecords");
1932 bool nModifier = false; // modifier key pressed?
1933 bool bNoDuplicatesForSelection = true;
1935 if (bDuplicateRows)
1937 std::vector<uno::Sequence<uno::Any>> aUnionArray;
1938 sal_uInt32 nRow = bIncludesHeaders ? 1 : 0;
1939 sal_uInt32 lRows = aDataArray.getLength();
1940 sal_uInt32 nDeleteCount = 0;
1942 while (nRow < lRows)
1944 if (lcl_CheckInArray(aUnionArray, aDataArray[nRow], rSelectedEntries, true))
1946 if (bRemove)
1948 lcl_RemoveCells(ActiveSheet, aRange.Sheet, aRange.StartColumn,
1949 aRange.StartRow + nRow - nDeleteCount, aRange.EndColumn,
1950 aRange.StartRow + nRow - nDeleteCount, true);
1951 ++nDeleteCount;
1953 else
1955 for (int nCol = aRange.StartColumn; nCol <= aRange.EndColumn; ++nCol)
1957 bNoDuplicatesForSelection = false;
1958 DoneBlockMode( nModifier );
1959 nModifier = true;
1960 InitBlockMode( nCol, aRange.StartRow + nRow, aRange.Sheet, false, false);
1964 else
1966 aUnionArray.push_back(aDataArray[nRow]);
1968 ++nRow;
1971 else
1973 std::vector<uno::Sequence<uno::Any>> aUnionArray;
1974 sal_uInt32 nDeleteCount = 0;
1975 sal_uInt32 nColumn = bIncludesHeaders ? 1 : 0;
1976 sal_uInt32 lColumns = aDataArray[0].getLength();
1978 while (nColumn < lColumns)
1980 uno::Sequence<uno::Any> aSeq;
1981 aSeq.realloc(rSelectedEntries.size());
1982 for (size_t i = 0; i < rSelectedEntries.size(); ++i)
1983 aSeq.getArray()[i] = aDataArray[rSelectedEntries[i]][nColumn];
1985 if (lcl_CheckInArray(aUnionArray, aSeq, rSelectedEntries, false))
1987 if (bRemove)
1989 lcl_RemoveCells(ActiveSheet, aRange.Sheet,
1990 aRange.StartColumn + nColumn - nDeleteCount, aRange.StartRow,
1991 aRange.StartColumn + nColumn - nDeleteCount, aRange.EndRow, false);
1992 ++nDeleteCount;
1994 else
1996 for (int nRow = aRange.StartRow; nRow <= aRange.EndRow; ++nRow)
1998 bNoDuplicatesForSelection = false;
1999 DoneBlockMode( nModifier );
2000 nModifier = true;
2001 InitBlockMode( aRange.StartColumn + nColumn, nRow, aRange.Sheet, false, false);
2005 else
2007 aUnionArray.push_back(aSeq);
2009 ++nColumn;
2014 if (bNoDuplicatesForSelection && !bRemove)
2015 Unmark();
2018 ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame,
2019 SfxViewShell* pOldSh ) :
2020 SfxViewShell(rViewFrame, SfxViewShellFlags::HAS_PRINTOPTIONS),
2021 ScDBFunc( &rViewFrame.GetWindow(), static_cast<ScDocShell&>(*rViewFrame.GetObjectShell()), this ),
2022 eCurOST(OST_NONE),
2023 nDrawSfxId(0),
2024 aTarget(this),
2025 bActiveDrawSh(false),
2026 bActiveDrawTextSh(false),
2027 bActiveDrawFormSh(false),
2028 bActiveOleObjectSh(false),
2029 bActiveChartSh(false),
2030 bActiveGraphicSh(false),
2031 bActiveMediaSh(false),
2032 bFormShellAtTop(false),
2033 bDontSwitch(false),
2034 bInFormatDialog(false),
2035 bReadOnly(false),
2036 bForceFocusOnCurCell(false),
2037 bInPrepareClose(false),
2038 bInDispose(false),
2039 bMoveKeepEdit(false),
2040 nCurRefDlgId(0),
2041 mbInSwitch(false),
2042 m_pDragData(new ScDragData),
2043 m_pScCondFormatDlgItem()
2045 const ScAppOptions& rAppOpt = ScModule::get()->GetAppOptions();
2047 // if switching back from print preview,
2048 // restore the view settings that were active when creating the preview
2049 // ReadUserData must not happen from ctor, because the view's edit window
2050 // has to be shown by the sfx. ReadUserData is deferred until the first Activate call.
2051 // old DesignMode state from form layer must be restored, too
2053 TriState nForceDesignMode = TRISTATE_INDET;
2054 if ( auto pPreviewShell = dynamic_cast<ScPreviewShell*>( pOldSh) )
2056 nForceDesignMode = pPreviewShell->GetSourceDesignMode();
2057 ScPreview* p = pPreviewShell->GetPreview();
2058 if (p)
2059 GetViewData().GetMarkData().SetSelectedTabs(p->GetSelectedTabs());
2062 Construct( nForceDesignMode );
2064 // make Controller known to SFX
2065 new ScTabViewObj( this );
2067 // Resolves: tdf#53899 if there is no controller, register the above
2068 // ScTabViewObj as the current controller for the duration of the first
2069 // round of calculations triggered here by SetZoom. That way any StarBasic
2070 // macros triggered while the document is loading have a CurrentController
2071 // available to them.
2072 bool bInstalledScTabViewObjAsTempController = false;
2073 uno::Reference<frame::XController> xCurrentController(GetViewData().GetDocShell()->GetModel()->getCurrentController());
2074 if (!xCurrentController)
2076 //GetController here returns the ScTabViewObj above
2077 GetViewData().GetDocShell()->GetModel()->setCurrentController(GetController());
2078 bInstalledScTabViewObjAsTempController = true;
2080 xCurrentController.clear();
2082 if ( GetViewData().GetDocShell()->IsPreview() )
2084 // preview for template dialog: always show whole page
2085 SetZoomType( SvxZoomType::WHOLEPAGE, true ); // zoom value is recalculated at next Resize
2087 else
2089 Fraction aFract( rAppOpt.GetZoom(), 100 );
2090 SetZoom( aFract, aFract, true );
2091 SetZoomType( rAppOpt.GetZoomType(), true );
2094 SetCurSubShell(OST_Cell);
2095 SvBorder aBorder;
2096 GetBorderSize( aBorder, Size() );
2097 SetBorderPixel( aBorder );
2099 MakeDrawLayer();
2101 //put things back as we found them
2102 if (bInstalledScTabViewObjAsTempController)
2103 GetViewData().GetDocShell()->GetModel()->setCurrentController(nullptr);
2105 mChangesListener.set(new ScViewOptiChangesListener(*this));
2107 // formula mode in online is not usable in collaborative mode,
2108 // this is a workaround for disabling formula mode in online
2109 // when there is more than a single view
2110 if (!comphelper::LibreOfficeKit::isActive())
2111 return;
2113 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
2114 // have we already one view ?
2115 if (!pViewShell)
2116 return;
2118 // this view is not yet visible at this stage, so we look for not visible views, too, for this same document
2119 SfxViewShell* pViewShell2 = pViewShell;
2122 pViewShell2 = SfxViewShell::GetNext(*pViewShell2, /*only visible shells*/ false);
2123 } while (pViewShell2 && pViewShell2->GetDocId() != pViewShell->GetDocId());
2124 // if the second view is not this one, it means that there is
2125 // already more than one active view and so the formula mode
2126 // has already been disabled
2127 if (pViewShell2 && pViewShell2 == this)
2129 ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
2130 assert(pTabViewShell);
2131 ScInputHandler* pInputHdl = pTabViewShell->GetInputHandler();
2132 if (pInputHdl && pInputHdl->IsFormulaMode())
2134 pInputHdl->SetMode(SC_INPUT_NONE);
2138 if (comphelper::LibreOfficeKit::isActive())
2140 ScModelObj* pModel = comphelper::getFromUnoTunnel<ScModelObj>(GetCurrentDocument());
2141 SfxLokHelper::notifyViewRenderState(this, pModel);
2145 ScTabViewShell::~ScTabViewShell()
2147 bInDispose = true;
2148 mChangesListener->stopListening();
2149 mChangesListener.clear();
2151 // Notify other LOK views that we are going away.
2152 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false"_ostr);
2153 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""_ostr);
2154 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"_ostr);
2155 SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", "EMPTY"_ostr);
2157 // all to NULL, in case the TabView-dtor tries to access them
2158 //! (should not really! ??!?!)
2159 if (mpInputHandler)
2161 mpInputHandler->SetDocumentDisposing(true);
2164 ScDocShell* pDocSh = GetViewData().GetDocShell();
2165 EndListening(*pDocSh);
2166 EndListening(GetViewFrame());
2167 EndListening(*SfxGetpApp()); // #i62045# #i62046# needed now - SfxViewShell no longer does it
2169 ScModule::get()->ViewShellGone(this);
2171 RemoveSubShell(); // all
2172 SetWindow(nullptr);
2174 // need kill editview or we will touch the editengine after it has been freed by the ScInputHandler
2175 KillEditView(true);
2177 pFontworkBarShell.reset();
2178 pExtrusionBarShell.reset();
2179 pCellShell.reset();
2180 pPageBreakShell.reset();
2181 pDrawShell.reset();
2182 pDrawFormShell.reset();
2183 pOleObjectShell.reset();
2184 pChartShell.reset();
2185 pGraphicShell.reset();
2186 pMediaShell.reset();
2187 pDrawTextShell.reset();
2188 pEditShell.reset();
2189 pPivotShell.reset();
2190 m_pSparklineShell.reset();
2191 pAuditingShell.reset();
2192 pCurFrameLine.reset();
2193 mpFormEditData.reset();
2194 mpInputHandler.reset();
2195 pDialogDPObject.reset();
2196 pNavSettings.reset();
2198 pFormShell.reset();
2199 pAccessibilityBroadcaster.reset();
2202 void ScTabViewShell::SetDialogDPObject( std::unique_ptr<ScDPObject> pObj )
2204 pDialogDPObject = std::move(pObj);
2207 void ScTabViewShell::FillFieldData( ScHeaderFieldData& rData )
2209 ScDocShell* pDocShell = GetViewData().GetDocShell();
2210 ScDocument& rDoc = pDocShell->GetDocument();
2211 SCTAB nTab = GetViewData().GetTabNo();
2212 OUString aTmp;
2213 rDoc.GetName(nTab, aTmp);
2214 rData.aTabName = aTmp;
2216 if( pDocShell->getDocProperties()->getTitle().getLength() != 0 )
2217 rData.aTitle = pDocShell->getDocProperties()->getTitle();
2218 else
2219 rData.aTitle = pDocShell->GetTitle();
2221 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
2222 rData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
2223 if ( !rData.aLongDocName.isEmpty() )
2224 rData.aShortDocName = rURLObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
2225 else
2226 rData.aShortDocName = rData.aLongDocName = rData.aTitle;
2227 rData.nPageNo = 1;
2228 rData.nTotalPages = 99;
2230 // eNumType is known by the dialog
2233 ScNavigatorSettings* ScTabViewShell::GetNavigatorSettings()
2235 if( !pNavSettings )
2236 pNavSettings.reset(new ScNavigatorSettings);
2237 return pNavSettings.get();
2240 tools::Rectangle ScTabViewShell::getLOKVisibleArea() const
2242 return GetViewData().getLOKVisibleArea();
2245 void ScTabViewShell::SetDragObject(ScTransferObj* pCellObj, ScDrawTransferObj* pDrawObj)
2247 ResetDragObject();
2248 m_pDragData->pCellTransfer = pCellObj;
2249 m_pDragData->pDrawTransfer = pDrawObj;
2252 void ScTabViewShell::ResetDragObject()
2254 m_pDragData->pCellTransfer = nullptr;
2255 m_pDragData->pDrawTransfer = nullptr;
2256 m_pDragData->pJumpLocalDoc = nullptr;
2257 m_pDragData->aLinkDoc.clear();
2258 m_pDragData->aLinkTable.clear();
2259 m_pDragData->aLinkArea.clear();
2260 m_pDragData->aJumpTarget.clear();
2261 m_pDragData->aJumpText.clear();
2264 void ScTabViewShell::SetDragLink(const OUString& rDoc, const OUString& rTab, const OUString& rArea)
2266 ResetDragObject();
2267 m_pDragData->aLinkDoc = rDoc;
2268 m_pDragData->aLinkTable = rTab;
2269 m_pDragData->aLinkArea = rArea;
2272 void ScTabViewShell::SetDragJump(ScDocument* pLocalDoc, const OUString& rTarget, const OUString& rText)
2274 ResetDragObject();
2275 m_pDragData->pJumpLocalDoc = pLocalDoc;
2276 m_pDragData->aJumpTarget = rTarget;
2277 m_pDragData->aJumpText = rText;
2280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */