cid#1607171 Data race condition
[LibreOffice.git] / sd / source / ui / view / drviews1.cxx
blobb8e5f82b9343c2a70adce1cbc94c8ed3ab56ee13
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <DrawViewShell.hxx>
21 #include <ViewShellImplementation.hxx>
23 #include <DrawController.hxx>
24 #include <com/sun/star/embed/XEmbeddedObject.hpp>
26 #include <comphelper/scopeguard.hxx>
27 #include <rtl/ref.hxx>
29 #include <svx/svxids.hrc>
30 #include <svx/svdpagv.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/bindings.hxx>
33 #include <svx/svdoole2.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/module.hxx>
36 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
37 #include <svx/svdopage.hxx>
38 #include <svx/fmshell.hxx>
39 #include <tools/debug.hxx>
40 #include <comphelper/diagnose_ex.hxx>
41 #include <vcl/graphicfilter.hxx>
43 #include <view/viewoverlaymanager.hxx>
45 #include <app.hrc>
47 #include <fupoor.hxx>
48 #include <unokywds.hxx>
49 #include <sdpage.hxx>
50 #include <FrameView.hxx>
51 #include <Window.hxx>
52 #include <drawview.hxx>
53 #include <drawdoc.hxx>
54 #include <DrawDocShell.hxx>
55 #include <Ruler.hxx>
56 #include <Client.hxx>
57 #include <slideshow.hxx>
58 #include <AnimationChildWindow.hxx>
59 #include <ToolBarManager.hxx>
60 #include <FormShellManager.hxx>
61 #include <ViewShellBase.hxx>
62 #include <LayerTabBar.hxx>
63 #include <ViewShellManager.hxx>
64 #include <ViewShellHint.hxx>
65 #include <SlideSorter.hxx>
66 #include <SlideSorterViewShell.hxx>
67 #include <controller/SlideSorterController.hxx>
68 #include <controller/SlsPageSelector.hxx>
70 #include <comphelper/lok.hxx>
71 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
72 #include <vcl/uitest/logger.hxx>
73 #include <vcl/uitest/eventdescription.hxx>
74 #include <titledockwin.hxx>
75 #include <strings.hrc>
76 #include <sdresid.hxx>
78 using namespace com::sun::star;
80 namespace sd {
82 void DrawViewShell::Activate(bool bIsMDIActivate)
84 ViewShell::Activate(bIsMDIActivate);
86 // tdf#150773: do not grab focus on loading
87 if (mbFirstTimeActivation)
88 mbFirstTimeActivation = false;
89 else
92 // When the mode is switched to normal the main view shell grabs focus.
93 // This is done for getting cut/copy/paste commands on slides in the left
94 // pane (slide sorter view shell) to work properly.
95 SfxShell* pTopViewShell = GetViewShellBase().GetViewShellManager()->GetTopViewShell();
96 if (pTopViewShell == this)
98 GetActiveWindow()->GrabFocus();
103 void DrawViewShell::UIActivating( SfxInPlaceClient* pCli )
105 ViewShell::UIActivating(pCli);
107 // Disable own controls
108 maTabControl->Disable();
109 if (GetLayerTabControl() != nullptr)
110 GetLayerTabControl()->Disable();
113 void DrawViewShell::UIDeactivated( SfxInPlaceClient* pCli )
115 // Enable own controls
116 maTabControl->Enable();
117 if (GetLayerTabControl() != nullptr)
118 GetLayerTabControl()->Enable();
120 ViewShell::UIDeactivated(pCli);
123 void DrawViewShell::Deactivate(bool bIsMDIActivate)
125 // Temporarily disable context broadcasting while the Deactivate()
126 // call is forwarded to our base class.
127 const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
129 ViewShell::Deactivate(bIsMDIActivate);
131 SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
134 namespace
136 class LockUI
138 private:
139 void Lock(bool bLock);
140 SfxViewFrame *mpFrame;
141 public:
142 explicit LockUI(SfxViewFrame *pFrame) : mpFrame(pFrame) { Lock(true); }
143 ~LockUI() { Lock(false); }
147 void LockUI::Lock(bool bLock)
149 if (!mpFrame)
150 return;
151 mpFrame->Enable( !bLock );
156 * Called, if state of selection of view is changed
159 void DrawViewShell::SelectionHasChanged()
161 Invalidate();
163 //Update3DWindow(); // 3D-Controller
164 SfxBoolItem aItem( SID_3D_STATE, true );
165 GetViewFrame()->GetDispatcher()->ExecuteList(
166 SID_3D_STATE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem });
168 SdrOle2Obj* pOleObj = nullptr;
170 const SdrMarkList& rMarkList(mpDrawView->GetMarkedObjectList());
171 if ( rMarkList.GetMarkCount() != 0 )
173 if (rMarkList.GetMarkCount() == 1)
175 SdrMark* pMark = rMarkList.GetMark(0);
176 SdrObject* pObj = pMark->GetMarkedSdrObj();
178 SdrInventor nInv = pObj->GetObjInventor();
179 SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
181 if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2)
183 pOleObj = static_cast<SdrOle2Obj*>(pObj);
184 UpdateIMapDlg( pObj );
186 else if (nSdrObjKind == SdrObjKind::Graphic)
187 UpdateIMapDlg( pObj );
191 ViewShellBase& rBase = GetViewShellBase();
192 rBase.SetVerbs( uno::Sequence< embed::VerbDescriptor >() );
196 if (pOleObj)
198 if (const auto& xObj = pOleObj->GetObjRef())
199 rBase.SetVerbs(xObj->getSupportedVerbs());
201 else if (auto* pIPClient = rBase.GetIPClient();
202 pIPClient && pIPClient->IsObjectInPlaceActive())
204 // as appropriate take ole-objects into account and deactivate
206 // this means we recently deselected an inplace active ole object so
207 // we need to deselect it now
209 //#i47279# disable frame until after object has completed unload
210 LockUI aUILock(GetViewFrame());
211 pIPClient->DeactivateObject();
212 //HMHmpDrView->ShowMarkHdl();
215 catch( css::uno::Exception& )
217 TOOLS_WARN_EXCEPTION( "sd", "sd::DrawViewShell::SelectionHasChanged()" );
220 if( HasCurrentFunction() )
222 GetCurrentFunction()->SelectionHasChanged();
224 else
226 GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*this,*mpDrawView);
229 // Invalidate for every subshell
230 GetViewShellBase().GetViewShellManager()->InvalidateAllSubShells(this);
232 mpDrawView->UpdateSelectionClipboard();
234 GetViewShellBase().GetDrawController()->FireSelectionChangeListener();
237 namespace {
239 void collectUIInformation(const OUString& aZoom)
241 EventDescription aDescription;
242 aDescription.aID = "impress_win";
243 aDescription.aParameters = {{"ZOOM", aZoom}};
244 aDescription.aAction = "SET";
245 aDescription.aKeyWord = "ImpressWindowUIObject";
246 aDescription.aParent = "MainWindow";
248 UITestLogger::getInstance().logEvent(aDescription);
254 * set zoom factor
256 void DrawViewShell::SetZoom( ::tools::Long nZoom )
258 // Make sure that the zoom factor will not be recalculated on
259 // following window resizings.
260 mbZoomOnPage = false;
261 ViewShell::SetZoom( nZoom );
262 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
263 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
264 mpViewOverlayManager->onZoomChanged();
265 collectUIInformation(OUString::number(nZoom));
269 * Set zoom rectangle for active window
272 void DrawViewShell::SetZoomRect( const ::tools::Rectangle& rZoomRect )
274 ViewShell::SetZoomRect( rZoomRect );
275 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
276 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
277 mpViewOverlayManager->onZoomChanged();
281 * PrepareClose, as appropriate end text input, so other viewshells
282 * discover a refreshed text object.
285 bool DrawViewShell::PrepareClose( bool bUI )
287 if ( !ViewShell::PrepareClose(bUI) )
288 return false;
290 if( HasCurrentFunction() )
292 sal_uInt16 nID = GetCurrentFunction()->GetSlotID();
293 if (nID == SID_TEXTEDIT || nID == SID_ATTR_CHAR)
295 mpDrawView->SdrEndTextEdit();
299 return true;
304 * Set status (enabled/disabled) of menu SfxSlots
307 void DrawViewShell::ChangeEditMode(EditMode eEMode, bool bIsLayerModeActive)
309 if (meEditMode == eEMode && mbIsLayerModeActive == bIsLayerModeActive)
310 return;
312 ViewShellManager::UpdateLock aLock (GetViewShellBase().GetViewShellManager());
314 sal_uInt16 nActualPageId = maTabControl->GetPageId(0);
316 if (mePageKind == PageKind::Handout)
318 // at handouts only allow MasterPage
319 eEMode = EditMode::MasterPage;
322 GetViewShellBase().GetDrawController()->FireChangeEditMode (eEMode == EditMode::MasterPage);
323 GetViewShellBase().GetDrawController()->FireChangeLayerMode (bIsLayerModeActive);
325 if ( mpDrawView->IsTextEdit() )
327 // This exits the text edit mode when going in and out of window focus, which is not needed
328 // Let's keep this call as comment for now as it probably just needs a better conditional.
329 // mpDrawView->SdrEndTextEdit();
332 LayerTabBar* pLayerBar = GetLayerTabControl();
333 if (pLayerBar != nullptr)
334 pLayerBar->EndEditMode();
335 maTabControl->EndEditMode();
337 GetViewShellBase().GetDrawController()->BroadcastContextChange();
339 meEditMode = eEMode;
341 if(pLayerBar)
343 // #i87182# only switch activation mode of LayerTabBar when there is one,
344 // else it will not get initialized with the current set of Layers as needed
345 mbIsLayerModeActive = bIsLayerModeActive;
348 // Determine whether to show the master view toolbar. The master
349 // page mode has to be active and the shell must not be a handout
350 // view.
351 bool bShowMasterViewToolbar (meEditMode == EditMode::MasterPage
352 && GetShellType() != ViewShell::ST_HANDOUT);
353 bool bShowPresentationToolbar (meEditMode != EditMode::MasterPage
354 && GetShellType() != ViewShell::ST_HANDOUT
355 && GetShellType() != ViewShell::ST_DRAW);
357 // If the master view toolbar is not shown we hide it before
358 // switching the edit mode.
359 if (::sd::ViewShell::mpImpl->mbIsInitialized
360 && IsMainViewShell())
362 if ( !bShowMasterViewToolbar )
363 GetViewShellBase().GetToolBarManager()->ResetToolBars(ToolBarManager::ToolBarGroup::MasterMode);
364 if ( !bShowPresentationToolbar )
365 GetViewShellBase().GetToolBarManager()->ResetToolBars(ToolBarManager::ToolBarGroup::CommonTask);
368 ConfigureAppBackgroundColor();
370 // tdf#87638 - change slide pane title according to the edit mode
371 auto setLeftPaneTitleIfPaneExists
372 = [pViewShell = GetViewFrame()](sal_uInt16 nId, TranslateId aId)
374 if (auto* pChildWindow = pViewShell->GetChildWindow(nId))
375 if (auto* pTitledDockingWindow
376 = static_cast<TitledDockingWindow*>(pChildWindow->GetWindow()))
377 pTitledDockingWindow->SetTitle(SdResId(aId));
380 if (comphelper::LibreOfficeKit::isActive())
381 GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
382 ".uno:DocumentStatus"_ostr); // pseudo-command
384 if (meEditMode == EditMode::Page)
386 /******************************************************************
387 * PAGEMODE
388 ******************************************************************/
390 maTabControl->Clear();
392 // tdf#87638 - change slide pane title according to the edit mode
393 setLeftPaneTitleIfPaneExists(SID_LEFT_PANE_DRAW, STR_LEFT_PANE_DRAW_TITLE);
394 setLeftPaneTitleIfPaneExists(SID_LEFT_PANE_IMPRESS, STR_LEFT_PANE_IMPRESS_TITLE);
396 SdPage* pPage;
397 sal_uInt16 nPageCnt = GetDoc()->GetSdPageCount(mePageKind);
399 for (sal_uInt16 i = 0; i < nPageCnt; i++)
401 pPage = GetDoc()->GetSdPage(i, mePageKind);
402 OUString aPageName = pPage->GetName();
403 maTabControl->InsertPage(pPage->getPageId(), aPageName);
405 if ( !comphelper::LibreOfficeKit::isActive() && pPage->IsSelected() )
407 nActualPageId = pPage->getPageId();
411 maTabControl->SetCurPageId(nActualPageId);
413 SwitchPage(maTabControl->GetPagePos(nActualPageId));
415 //tdf#102343 re-enable common undo on switch back from master mode
416 mpDrawView->GetModel().SetDisableTextEditUsesCommonUndoManager(false);
418 else
420 /******************************************************************
421 * MASTERPAGE
422 ******************************************************************/
423 GetViewFrame()->SetChildWindow(
424 AnimationChildWindow::GetChildWindowId(), false );
426 // tdf#87638 - change slide pane title according to the edit mode
427 setLeftPaneTitleIfPaneExists(SID_LEFT_PANE_DRAW, STR_LEFT_PANE_DRAW_TITLE_MASTER);
428 setLeftPaneTitleIfPaneExists(SID_LEFT_PANE_IMPRESS, STR_LEFT_PANE_IMPRESS_TITLE_MASTER);
430 if (!mpActualPage)
432 // as long as there is no mpActualPage, take first
433 mpActualPage = GetDoc()->GetSdPage(0, mePageKind);
436 maTabControl->Clear();
437 sal_uInt16 nActualMasterPageId = maTabControl->GetPageId(0);
438 sal_uInt16 nMasterPageCnt = GetDoc()->GetMasterSdPageCount(mePageKind);
440 for (sal_uInt16 i = 0; i < nMasterPageCnt; i++)
442 SdPage* pMaster = GetDoc()->GetMasterSdPage(i, mePageKind);
443 OUString aLayoutName = pMaster->GetLayoutName();
444 sal_Int32 nPos = aLayoutName.indexOf(SD_LT_SEPARATOR);
445 if (nPos != -1)
446 aLayoutName = aLayoutName.copy(0, nPos);
448 maTabControl->InsertPage(pMaster->getPageId(), aLayoutName);
450 if (&(mpActualPage->TRG_GetMasterPage()) == pMaster)
452 nActualMasterPageId = pMaster->getPageId();
456 maTabControl->SetCurPageId(nActualMasterPageId);
457 SwitchPage(maTabControl->GetPagePos(nActualMasterPageId));
459 //tdf#102343 changing attributes of textboxes in master typically
460 //changes the stylesheet they are linked to, so if the common
461 //undo manager is in use, those stylesheet changes are thrown
462 //away at present
463 mpDrawView->GetModel().SetDisableTextEditUsesCommonUndoManager(true);
466 // If the master view toolbar is to be shown we turn it on after the
467 // edit mode has been changed.
468 if (::sd::ViewShell::mpImpl->mbIsInitialized && !sfx2::SfxNotebookBar::IsActive()
469 && IsMainViewShell())
471 if (bShowMasterViewToolbar)
472 GetViewShellBase().GetToolBarManager()->SetToolBar(
473 ToolBarManager::ToolBarGroup::MasterMode,
474 ToolBarManager::msMasterViewToolBar);
475 if (bShowPresentationToolbar)
476 GetViewShellBase().GetToolBarManager()->SetToolBar(
477 ToolBarManager::ToolBarGroup::CommonTask,
478 ToolBarManager::msCommonTaskToolBar);
481 if ( ! mbIsLayerModeActive)
483 maTabControl->Show();
484 // Set the tab control only for draw pages. For master page
485 // this has been done already above.
486 if (meEditMode == EditMode::Page)
487 maTabControl->SetCurPageId (nActualPageId);
490 ResetActualLayer();
492 Invalidate( SID_PAGEMODE );
493 Invalidate( SID_LAYERMODE );
494 Invalidate( SID_MASTERPAGE );
495 Invalidate( SID_DELETE_MASTER_PAGE );
496 Invalidate( SID_DELETE_PAGE );
497 Invalidate( SID_SLIDE_MASTER_MODE );
498 Invalidate( SID_NOTES_MASTER_MODE );
499 Invalidate( SID_HANDOUT_MASTER_MODE );
500 InvalidateWindows();
502 if (sfx2::SfxNotebookBar::IsActive())
503 UIFeatureChanged();
505 SetContextName(GetSidebarContextName());
510 * Generate horizontal ruler
513 VclPtr<SvxRuler> DrawViewShell::CreateHRuler (::sd::Window* pWin)
515 VclPtr<Ruler> pRuler;
516 WinBits aWBits;
517 SvxRulerSupportFlags nFlags = SvxRulerSupportFlags::OBJECT;
519 aWBits = WB_HSCROLL | WB_3DLOOK | WB_BORDER | WB_EXTRAFIELD;
520 nFlags |= SvxRulerSupportFlags::SET_NULLOFFSET |
521 SvxRulerSupportFlags::TABS |
522 SvxRulerSupportFlags::PARAGRAPH_MARGINS; // new
524 pRuler = VclPtr<Ruler>::Create(*this, GetParentWindow(), pWin, nFlags,
525 GetViewFrame()->GetBindings(), aWBits);
527 // Metric ...
528 sal_uInt16 nMetric = static_cast<sal_uInt16>(GetDoc()->GetUIUnit());
530 if( nMetric == 0xffff )
531 nMetric = static_cast<sal_uInt16>(GetViewShellBase().GetViewFrame().GetDispatcher()->GetModule()->GetFieldUnit());
533 pRuler->SetUnit( FieldUnit( nMetric ) );
535 // ... and also set DefTab at the ruler
536 pRuler->SetDefTabDist( GetDoc()->GetDefaultTabulator() ); // new
538 Fraction aUIScale(pWin->GetMapMode().GetScaleX());
539 aUIScale *= GetDoc()->GetUIScale();
540 pRuler->SetZoom(aUIScale);
542 return pRuler;
546 * Generate vertical ruler
549 VclPtr<SvxRuler> DrawViewShell::CreateVRuler(::sd::Window* pWin)
551 VclPtr<SvxRuler> pRuler;
552 WinBits aWBits = WB_VSCROLL | WB_3DLOOK | WB_BORDER;
553 SvxRulerSupportFlags nFlags = SvxRulerSupportFlags::OBJECT;
555 pRuler = VclPtr<Ruler>::Create(*this, GetParentWindow(), pWin, nFlags,
556 GetViewFrame()->GetBindings(), aWBits);
558 // Metric same as HRuler, use document setting
559 sal_uInt16 nMetric = static_cast<sal_uInt16>(GetDoc()->GetUIUnit());
561 if( nMetric == 0xffff )
562 nMetric = static_cast<sal_uInt16>(GetViewShellBase().GetViewFrame().GetDispatcher()->GetModule()->GetFieldUnit());
564 pRuler->SetUnit( FieldUnit( nMetric ) );
566 Fraction aUIScale(pWin->GetMapMode().GetScaleY());
567 aUIScale *= GetDoc()->GetUIScale();
568 pRuler->SetZoom(aUIScale);
570 return pRuler;
574 * Refresh horizontal ruler
577 void DrawViewShell::UpdateHRuler()
579 Invalidate( SID_ATTR_LONG_LRSPACE );
580 Invalidate( SID_RULER_PAGE_POS );
581 Invalidate( SID_RULER_OBJECT );
582 Invalidate( SID_RULER_TEXT_RIGHT_TO_LEFT );
584 if (mpHorizontalRuler)
585 mpHorizontalRuler->ForceUpdate();
589 * Refresh vertical ruler
592 void DrawViewShell::UpdateVRuler()
594 Invalidate( SID_ATTR_LONG_LRSPACE );
595 Invalidate( SID_RULER_PAGE_POS );
596 Invalidate( SID_RULER_OBJECT );
598 if (mpVerticalRuler)
599 mpVerticalRuler->ForceUpdate();
603 * Refresh TabControl on splitter change
606 IMPL_LINK( DrawViewShell, TabSplitHdl, TabBar *, pTab, void )
608 const ::tools::Long nMax = maViewSize.Width() - maScrBarWH.Width()
609 - maTabControl->GetPosPixel().X() ;
611 Size aTabSize = maTabControl->GetSizePixel();
612 aTabSize.setWidth( std::min(pTab->GetSplitSize(), static_cast<::tools::Long>(nMax-1)) );
614 maTabControl->SetSizePixel(aTabSize);
616 if(GetLayerTabControl()) // #i87182#
618 GetLayerTabControl()->SetSizePixel(aTabSize);
621 Point aPos = maTabControl->GetPosPixel();
622 aPos.AdjustX(aTabSize.Width() );
624 Size aScrSize(nMax - aTabSize.Width(), maScrBarWH.Height());
625 mpHorizontalScrollBar->SetPosSizePixel(aPos, aScrSize);
628 /// inherited from sd::ViewShell
629 SdPage* DrawViewShell::getCurrentPage() const
631 const sal_uInt16 nPageCount = (meEditMode == EditMode::Page)?
632 GetDoc()->GetSdPageCount(mePageKind):
633 GetDoc()->GetMasterSdPageCount(mePageKind);
635 sal_uInt16 nCurrentPage = maTabControl->GetCurPagePos();
636 DBG_ASSERT((nCurrentPage<nPageCount), "sd::DrawViewShell::getCurrentPage(), illegal page index!");
637 if (nCurrentPage >= nPageCount)
638 nCurrentPage = 0; // play safe here
640 if (meEditMode == EditMode::Page)
642 return GetDoc()->GetSdPage(nCurrentPage, mePageKind);
644 else // EditMode::MasterPage
646 return GetDoc()->GetMasterSdPage(nCurrentPage, mePageKind);
651 * Select new refreshed page, in case of a page order change (eg. by undo)
654 void DrawViewShell::ResetActualPage()
656 if (!GetDoc())
657 return;
659 sal_uInt16 nCurrentPageId = maTabControl->GetCurPageId();
660 sal_uInt16 nNewPageId;
661 sal_uInt16 nCurrentPageNum = maTabControl->GetPagePos(nCurrentPageId);
662 sal_uInt16 nPageCount = (meEditMode == EditMode::Page)?GetDoc()->GetSdPageCount(mePageKind):GetDoc()->GetMasterSdPageCount(mePageKind);
664 if (nCurrentPageNum >= nPageCount)
665 nCurrentPageNum = nPageCount - 1;
667 if (meEditMode == EditMode::Page)
670 // Update for TabControl
671 maTabControl->Clear();
673 SdPage* pPage = nullptr;
675 for (sal_uInt16 i = 0; i < nPageCount; i++)
677 pPage = GetDoc()->GetSdPage(i, mePageKind);
678 OUString aPageName = pPage->GetName();
679 maTabControl->InsertPage(pPage->getPageId(), aPageName);
681 if (nCurrentPageId == pPage->getPageId())
683 nCurrentPageNum = i;
684 GetDoc()->SetSelected(pPage, true);
686 else
687 GetDoc()->SetSelected(pPage, false);
690 nNewPageId = maTabControl->GetPageId(nCurrentPageNum);
691 maTabControl->SetCurPageId(nNewPageId);
693 else // EditMode::MasterPage
695 maTabControl->Clear();
697 sal_uInt16 nMasterPageCnt = GetDoc()->GetMasterSdPageCount(mePageKind);
698 for (sal_uInt16 i = 0; i < nMasterPageCnt; i++)
700 SdPage* pMaster = GetDoc()->GetMasterSdPage(i, mePageKind);
701 OUString aLayoutName = pMaster->GetLayoutName();
702 sal_Int32 nPos = aLayoutName.indexOf(SD_LT_SEPARATOR);
703 if (nPos != -1)
704 aLayoutName = aLayoutName.copy(0, nPos);
705 maTabControl->InsertPage(pMaster->getPageId(), aLayoutName);
707 if (pMaster->getPageId() == nCurrentPageId)
708 nCurrentPageNum = i;
711 nNewPageId = maTabControl->GetPageId(nCurrentPageNum);
712 maTabControl->SetCurPageId(nNewPageId);
713 SwitchPage(nCurrentPageNum);
716 bool bAllowChangeFocus = nNewPageId != nCurrentPageId;
717 SfxBoolItem aI(SID_SWITCHPAGE, bAllowChangeFocus);
718 GetViewFrame()->GetDispatcher()->ExecuteList(SID_SWITCHPAGE,
719 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
720 { &aI });
724 * Apply "Verb" on OLE-object.
726 ErrCode DrawViewShell::DoVerb(sal_Int32 nVerb)
728 const SdrMarkList& rMarkList(mpDrawView->GetMarkedObjectList());
729 if ( rMarkList.GetMarkCount() != 0 )
731 if (rMarkList.GetMarkCount() == 1)
733 SdrMark* pMark = rMarkList.GetMark(0);
734 SdrObject* pObj = pMark->GetMarkedSdrObj();
736 SdrInventor nInv = pObj->GetObjInventor();
737 SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
739 if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2)
741 ActivateObject( static_cast<SdrOle2Obj*>(pObj), nVerb);
746 return ERRCODE_NONE;
750 * Activate OLE-object
752 bool DrawViewShell::ActivateObject(SdrOle2Obj* pObj, sal_Int32 nVerb)
754 bool bActivated = false;
756 if ( !GetDocSh()->IsUIActive() )
758 ToolBarManager::UpdateLock aLock (GetViewShellBase().GetToolBarManager());
760 bActivated = ViewShell::ActivateObject(pObj, nVerb);
763 return bActivated;
767 * Mark the desired page as selected (1), deselected (0), toggle (2).
768 * nPage refers to the page in question.
770 bool DrawViewShell::SelectPage(sal_uInt16 nPage, sal_uInt16 nSelect)
772 SdPage* pPage = GetDoc()->GetSdPage(nPage, PageKind::Standard);
774 //page selector marks pages to selected in view
775 auto &pageSelector = sd::slidesorter::SlideSorterViewShell::GetSlideSorter(GetViewShellBase())->GetSlideSorter().GetController().GetPageSelector();
777 if (pPage)
779 if (nSelect == 0)
781 GetDoc()->SetSelected(pPage, false); // Deselect.
782 pageSelector.DeselectPage(nPage);
784 else if (nSelect == 1)
786 GetDoc()->SetSelected(pPage, true); // Select.
787 pageSelector.SelectPage(nPage);
789 else
791 // Toggle.
792 if (pPage->IsSelected())
794 GetDoc()->SetSelected(pPage, false);
795 pageSelector.DeselectPage(nPage);
797 else
799 GetDoc()->SetSelected(pPage, true);
800 pageSelector.SelectPage(nPage);
803 return true;
806 return false;
809 bool DrawViewShell::IsSelected(sal_uInt16 nPage)
811 slidesorter::SlideSorterViewShell* pVShell
812 = slidesorter::SlideSorterViewShell::GetSlideSorter(GetViewShellBase());
813 if (pVShell != nullptr)
814 return pVShell->GetSlideSorter().GetController().GetPageSelector().IsPageSelected(nPage);
816 return false;
820 * Switch to desired page.
821 * nSelectPage refers to the current EditMode
822 * bAllowChangeFocus set to false when slide is inserted before current page
823 * and we need to only update the current page number,
824 * do not disturb editing in that case
826 bool DrawViewShell::SwitchPage(sal_uInt16 nSelectedPage, bool bAllowChangeFocus)
828 /** Under some circumstances there are nested calls to SwitchPage() and
829 may crash the application (activation of form controls when the
830 shell of the edit view is not on top of the shell stack, see issue
831 83888 for details.) Therefore the nested calls are ignored (they
832 would jump to the wrong page anyway.)
835 if (mbIsInSwitchPage)
836 return false;
837 mbIsInSwitchPage = true;
838 comphelper::ScopeGuard aGuard(
839 [this] () { this->mbIsInSwitchPage = false; } );
841 if (GetActiveWindow()->IsInPaint())
843 // Switching the current page while a Paint is being executed is
844 // dangerous. So, post it for later execution and return.
845 maAsynchronousSwitchPageCall.Post(
846 [this, nSelectedPage] () { this->SwitchPage(nSelectedPage); } );
847 return false;
850 bool bOK = false;
852 // With the current implementation of FuSlideShow there is a problem
853 // when it displays the show in a window: when the show is stopped it
854 // returns at one point in time SDRPAGE_NOTFOUND as current page index.
855 // Because FuSlideShow is currently being rewritten this bug is fixed
856 // here.
857 // This is not as bad a hack as it may look because making SwitchPage()
858 // more robust with respect to invalid page numbers is a good thing
859 // anyway.
860 if (nSelectedPage == SDRPAGE_NOTFOUND)
862 nSelectedPage = 0;
864 else
866 // Make sure that the given page index points to an existing page. Move
867 // the index into the valid range if necessary.
868 sal_uInt16 nPageCount = (meEditMode == EditMode::Page)
869 ? GetDoc()->GetSdPageCount(mePageKind)
870 : GetDoc()->GetMasterSdPageCount(mePageKind);
871 if (nSelectedPage >= nPageCount)
872 nSelectedPage = nPageCount-1;
875 if (IsSwitchPageAllowed())
877 ModifyGuard aGuard2( GetDoc() );
879 bOK = true;
881 if (mpActualPage)
883 SdPage* pNewPage = nullptr;
885 if (meEditMode == EditMode::MasterPage)
887 if( GetDoc()->GetMasterSdPageCount(mePageKind) > nSelectedPage )
888 pNewPage = GetDoc()->GetMasterSdPage(nSelectedPage, mePageKind);
890 if( pNewPage )
892 SdrPageView* pPV = mpDrawView->GetSdrPageView();
893 OUString sPageText(pNewPage->GetLayoutName());
894 sal_Int32 nPos = sPageText.indexOf(SD_LT_SEPARATOR);
895 if (nPos != -1)
896 sPageText = sPageText.copy(0, nPos);
897 if (pPV
898 && pNewPage == dynamic_cast< SdPage* >( pPV->GetPage() )
899 && sPageText == maTabControl->GetPageText(maTabControl->GetPageId(nSelectedPage)))
901 // this slide is already visible
902 return true;
906 else
908 OSL_ASSERT(mpFrameView!=nullptr);
909 mpFrameView->SetSelectedPage(nSelectedPage);
911 if (GetDoc()->GetSdPageCount(mePageKind) > nSelectedPage)
912 pNewPage = GetDoc()->GetSdPage(nSelectedPage, mePageKind);
914 if (mpActualPage == pNewPage)
916 SdrPageView* pPV = mpDrawView->GetSdrPageView();
918 SdPage* pCurrentPage = pPV ? dynamic_cast<SdPage*>(pPV->GetPage()) : nullptr;
919 if (pCurrentPage
920 && pNewPage == pCurrentPage
921 && maTabControl->GetPageText(maTabControl->GetPageId(nSelectedPage)) == pNewPage->GetName())
923 // this slide is already visible
924 return true;
930 if (bAllowChangeFocus)
931 mpDrawView->SdrEndTextEdit();
933 mpActualPage = nullptr;
935 if (meEditMode == EditMode::Page)
937 mpActualPage = GetDoc()->GetSdPage(nSelectedPage, mePageKind);
939 else
941 SdPage* pMaster = GetDoc()->GetMasterSdPage(nSelectedPage, mePageKind);
943 // does the selected page fit to the masterpage?
944 sal_uInt16 nPageCount = GetDoc()->GetSdPageCount(mePageKind);
945 for (sal_uInt16 i = 0; i < nPageCount; i++)
947 SdPage* pPage = GetDoc()->GetSdPage(i, mePageKind);
948 if(pPage && pPage->IsSelected() && pMaster == &(pPage->TRG_GetMasterPage()))
950 mpActualPage = pPage;
951 break;
955 if (!mpActualPage)
957 // take the first page, that fits to the masterpage
958 for (sal_uInt16 i = 0; i < nPageCount; i++)
960 SdPage* pPage = GetDoc()->GetSdPage(i, mePageKind);
961 if(pPage && pMaster == &(pPage->TRG_GetMasterPage()))
963 mpActualPage = pPage;
964 break;
970 for (sal_uInt16 i = 0; i < GetDoc()->GetSdPageCount(mePageKind); i++)
972 // deselect all pages
973 GetDoc()->SetSelected( GetDoc()->GetSdPage(i, mePageKind), false);
976 if (!mpActualPage)
978 // as far as there is no mpActualPage, take the first
979 mpActualPage = GetDoc()->GetSdPage(0, mePageKind);
982 // also select this page (mpActualPage always points at a drawing page,
983 // never at a masterpage)
984 GetDoc()->SetSelected(mpActualPage, true);
986 if (comphelper::LibreOfficeKit::isActive())
988 // notify LibreOfficeKit about changed page
989 OString aPayload = OString::number(nSelectedPage);
990 if (SfxViewShell* pViewShell = GetViewShell())
991 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_SET_PART, aPayload);
994 rtl::Reference< sd::SlideShow > xSlideshow( SlideShow::GetSlideShow( GetDoc() ) );
995 if( !xSlideshow.is() || !xSlideshow->isRunning() || ( xSlideshow->getAnimationMode() != ANIMATIONMODE_SHOW ) )
997 // tighten VisArea, to possibly deactivate objects
998 // !!! only if we are not in presentation mode (#96279) !!!
999 OSL_ASSERT (GetViewShell()!=nullptr);
1000 GetViewShell()->DisconnectAllClients();
1001 VisAreaChanged(::tools::Rectangle(Point(), Size(1, 1)));
1004 // Try to prefetch all graphics for the active page. This will be done
1005 // in threads to be more efficient than loading them on-demand one by one.
1006 std::vector<Graphic*> graphics;
1007 mpActualPage->getGraphicsForPrefetch(graphics);
1008 if(graphics.size() > 1) // threading does not help with loading just one
1009 GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded(graphics);
1011 if (meEditMode == EditMode::Page)
1013 /**********************************************************************
1014 * PAGEMODE
1015 **********************************************************************/
1016 GetDoc()->SetSelected(mpActualPage, true);
1018 SdrPageView* pPageView = mpDrawView->GetSdrPageView();
1020 if (pPageView)
1022 mpFrameView->SetVisibleLayers( pPageView->GetVisibleLayers() );
1023 mpFrameView->SetPrintableLayers( pPageView->GetPrintableLayers() );
1024 mpFrameView->SetLockedLayers( pPageView->GetLockedLayers() );
1026 if (mePageKind == PageKind::Notes)
1028 mpFrameView->SetNotesHelpLines( pPageView->GetHelpLines() );
1030 else if (mePageKind == PageKind::Handout)
1032 mpFrameView->SetHandoutHelpLines( pPageView->GetHelpLines() );
1034 else
1036 mpFrameView->SetStandardHelpLines( pPageView->GetHelpLines() );
1040 mpDrawView->HideSdrPage();
1041 maTabControl->SetCurPageId(maTabControl->GetPageId(nSelectedPage));
1042 mpDrawView->ShowSdrPage(mpActualPage);
1043 GetViewShellBase().GetDrawController()->FireSwitchCurrentPage(mpActualPage);
1045 SdrPageView* pNewPageView = mpDrawView->GetSdrPageView();
1047 if (pNewPageView)
1049 pNewPageView->SetVisibleLayers( mpFrameView->GetVisibleLayers() );
1050 pNewPageView->SetPrintableLayers( mpFrameView->GetPrintableLayers() );
1051 pNewPageView->SetLockedLayers( mpFrameView->GetLockedLayers() );
1053 if (mePageKind == PageKind::Notes)
1055 pNewPageView->SetHelpLines( mpFrameView->GetNotesHelpLines() );
1057 else if (mePageKind == PageKind::Handout)
1059 pNewPageView->SetHelpLines( mpFrameView->GetHandoutHelpLines() );
1061 else
1063 pNewPageView->SetHelpLines( mpFrameView->GetStandardHelpLines() );
1067 OUString aPageName = mpActualPage->GetName();
1069 if (maTabControl->GetPageText(maTabControl->GetPageId(nSelectedPage)) != aPageName)
1071 maTabControl->SetPageText(maTabControl->GetPageId(nSelectedPage), aPageName);
1074 else
1076 /**********************************************************************
1077 * MASTERPAGE
1078 **********************************************************************/
1079 SdrPageView* pPageView = mpDrawView->GetSdrPageView();
1081 if (pPageView)
1083 mpFrameView->SetVisibleLayers( pPageView->GetVisibleLayers() );
1084 mpFrameView->SetPrintableLayers( pPageView->GetPrintableLayers() );
1085 mpFrameView->SetLockedLayers( pPageView->GetLockedLayers() );
1087 if (mePageKind == PageKind::Notes)
1089 mpFrameView->SetNotesHelpLines( pPageView->GetHelpLines() );
1091 else if (mePageKind == PageKind::Handout)
1093 mpFrameView->SetHandoutHelpLines( pPageView->GetHelpLines() );
1095 else
1097 mpFrameView->SetStandardHelpLines( pPageView->GetHelpLines() );
1101 mpDrawView->HideSdrPage();
1102 maTabControl->SetCurPageId(maTabControl->GetPageId(nSelectedPage));
1104 SdPage* pMaster = GetDoc()->GetMasterSdPage(nSelectedPage, mePageKind);
1106 if( !pMaster ) // if this page should not exist
1107 pMaster = GetDoc()->GetMasterSdPage(0, mePageKind);
1109 sal_uInt16 nNum = pMaster->GetPageNum();
1110 mpDrawView->ShowSdrPage(mpDrawView->GetModel().GetMasterPage(nNum));
1112 GetViewShellBase().GetDrawController()->FireSwitchCurrentPage(pMaster);
1114 SdrPageView* pNewPageView = mpDrawView->GetSdrPageView();
1116 if (pNewPageView)
1118 pNewPageView->SetVisibleLayers( mpFrameView->GetVisibleLayers() );
1119 pNewPageView->SetPrintableLayers( mpFrameView->GetPrintableLayers() );
1120 pNewPageView->SetLockedLayers( mpFrameView->GetLockedLayers() );
1122 if (mePageKind == PageKind::Notes)
1124 pNewPageView->SetHelpLines( mpFrameView->GetNotesHelpLines() );
1126 else if (mePageKind == PageKind::Handout)
1128 pNewPageView->SetHelpLines( mpFrameView->GetHandoutHelpLines() );
1130 else
1132 pNewPageView->SetHelpLines( mpFrameView->GetStandardHelpLines() );
1136 OUString aLayoutName(pMaster->GetLayoutName());
1137 sal_Int32 nPos = aLayoutName.indexOf(SD_LT_SEPARATOR);
1138 if (nPos != -1)
1139 aLayoutName = aLayoutName.copy(0, nPos);
1141 if (maTabControl->GetPageText(maTabControl->GetPageId(nSelectedPage)) != aLayoutName)
1143 maTabControl->SetPageText(maTabControl->GetPageId(nSelectedPage), aLayoutName);
1146 if( mePageKind == PageKind::Handout )
1148 // set pages for all available handout presentation objects
1149 sd::ShapeList& rShapeList = pMaster->GetPresentationShapeList();
1150 SdrObject* pObj = nullptr;
1151 rShapeList.seekShape(0);
1153 while( (pObj = rShapeList.getNextShape()) )
1155 if( pMaster->GetPresObjKind(pObj) == PresObjKind::Handout )
1157 // #i105146# We want no content to be displayed for PageKind::Handout,
1158 // so just never set a page as content
1159 static_cast<SdrPageObj*>(pObj)->SetReferencedPage(nullptr);
1165 Size aVisSizePixel = GetActiveWindow()->GetOutputSizePixel();
1166 ::tools::Rectangle aVisAreaWin = GetActiveWindow()->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
1167 VisAreaChanged(aVisAreaWin);
1168 mpDrawView->VisAreaChanged(GetActiveWindow()->GetOutDev());
1170 // so navigator (and effect window) notice that
1171 SfxBindings& rBindings = GetViewFrame()->GetBindings();
1172 rBindings.Invalidate(SID_NAVIGATOR_STATE, true);
1173 rBindings.Invalidate(SID_NAVIGATOR_PAGENAME, true);
1174 rBindings.Invalidate(SID_STATUS_PAGE, true);
1175 rBindings.Invalidate(SID_DELETE_MASTER_PAGE, true);
1176 rBindings.Invalidate(SID_DELETE_PAGE, true);
1177 rBindings.Invalidate(SID_ASSIGN_LAYOUT, true);
1178 rBindings.Invalidate(SID_INSERTPAGE, true);
1179 UpdatePreview( mpActualPage );
1181 mpDrawView->AdjustMarkHdl();
1184 return bOK;
1188 * Check if page change is allowed
1191 bool DrawViewShell::IsSwitchPageAllowed() const
1193 bool bOK = true;
1195 FmFormShell* pFormShell = GetViewShellBase().GetFormShellManager()->GetFormShell();
1196 if (pFormShell != nullptr && !pFormShell->PrepareClose(false))
1197 bOK = false;
1199 return bOK;
1203 * Select new refreshed page, in case of a page order change (eg. by undo)
1206 void DrawViewShell::ResetActualLayer()
1208 LayerTabBar* pLayerBar = GetLayerTabControl();
1209 if (pLayerBar == nullptr)
1210 return;
1212 // remember old tab count and current tab id
1213 // this is needed when one layer is renamed to
1214 // restore current tab
1215 sal_uInt16 nOldLayerCnt = pLayerBar->GetPageCount(); // actually it is tab count
1216 sal_uInt16 nOldLayerPos = pLayerBar->GetCurPageId(); // actually it is a tab nId
1219 * Update for LayerTab
1221 pLayerBar->Clear();
1223 OUString aName; // a real layer name
1224 OUString aActiveLayer = mpDrawView->GetActiveLayer();
1225 sal_uInt16 nActiveLayerPos = SDRLAYERPOS_NOTFOUND;
1226 SdrLayerAdmin& rLayerAdmin = GetDoc()->GetLayerAdmin();
1227 sal_uInt16 nLayerCnt = rLayerAdmin.GetLayerCount();
1229 for ( sal_uInt16 nLayerPos = 0; nLayerPos < nLayerCnt; nLayerPos++ )
1231 aName = rLayerAdmin.GetLayer(nLayerPos)->GetName();
1233 if ( aName == aActiveLayer )
1235 nActiveLayerPos = nLayerPos;
1238 if ( aName != sUNO_LayerName_background ) // layer "background" has never a tab
1240 if (meEditMode == EditMode::MasterPage)
1242 // don't show page layer onto the masterpage
1243 if (aName != sUNO_LayerName_layout &&
1244 aName != sUNO_LayerName_controls &&
1245 aName != sUNO_LayerName_measurelines)
1247 TabBarPageBits nBits = TabBarPageBits::NONE;
1248 SdrPageView* pPV = mpDrawView->GetSdrPageView();
1249 if (pPV)
1251 if (!pPV->IsLayerVisible(aName))
1253 nBits |= TabBarPageBits::Blue;
1255 if (pPV->IsLayerLocked(aName))
1257 nBits |= TabBarPageBits::Italic;
1259 if (!pPV->IsLayerPrintable(aName))
1261 nBits |= TabBarPageBits::Underline;
1265 pLayerBar->InsertPage(nLayerPos+1, aName, nBits); // why +1? It is a nId, not a position. Position is APPEND.
1268 else
1270 // don't show masterpage layer onto the page
1271 if (aName != sUNO_LayerName_background_objects)
1273 TabBarPageBits nBits = TabBarPageBits::NONE;
1274 if (!mpDrawView->GetSdrPageView()->IsLayerVisible(aName))
1276 nBits = TabBarPageBits::Blue;
1278 if (mpDrawView->GetSdrPageView()->IsLayerLocked(aName))
1280 nBits |= TabBarPageBits::Italic;
1282 if (!mpDrawView->GetSdrPageView()->IsLayerPrintable(aName))
1284 nBits |= TabBarPageBits::Underline;
1287 pLayerBar->InsertPage(nLayerPos+1, aName, nBits);// why +1?
1293 if ( nActiveLayerPos == SDRLAYERPOS_NOTFOUND )
1295 if( nOldLayerCnt == pLayerBar->GetPageCount() )
1297 nActiveLayerPos = nOldLayerPos - 1;
1299 else
1301 nActiveLayerPos = ( meEditMode == EditMode::MasterPage ) ? 2 : 0;
1304 mpDrawView->SetActiveLayer( pLayerBar->GetLayerName(nActiveLayerPos + 1) );// why +1?
1307 pLayerBar->SetCurPageId(nActiveLayerPos + 1);
1308 GetViewFrame()->GetBindings().Invalidate( SID_TOGGLELAYERVISIBILITY );
1309 GetViewFrame()->GetBindings().Invalidate( SID_MODIFYLAYER );
1310 GetViewFrame()->GetBindings().Invalidate( SID_DELETE_LAYER );
1314 * AcceptDrop
1317 sal_Int8 DrawViewShell::AcceptDrop (
1318 const AcceptDropEvent& rEvt,
1319 DropTargetHelper& rTargetHelper,
1320 ::sd::Window* /*pTargetWindow*/,
1321 sal_uInt16 /*nPage*/,
1322 SdrLayerID nLayer )
1324 if( SlideShow::IsRunning( GetViewShellBase() ) && !SlideShow::IsInteractiveSlideshow( &GetViewShellBase() ) ) // IASS
1325 return DND_ACTION_NONE;
1327 return mpDrawView->AcceptDrop( rEvt, rTargetHelper, nLayer );
1331 * ExecuteDrop
1334 sal_Int8 DrawViewShell::ExecuteDrop (
1335 const ExecuteDropEvent& rEvt,
1336 DropTargetHelper& /*rTargetHelper*/,
1337 ::sd::Window* pTargetWindow,
1338 sal_uInt16 nPage,
1339 SdrLayerID nLayer)
1341 if( nPage != SDRPAGE_NOTFOUND )
1342 nPage = GetDoc()->GetSdPage( nPage, mePageKind )->GetPageNum();
1344 if( SlideShow::IsRunning( GetViewShellBase() ) && !SlideShow::IsInteractiveSlideshow( &GetViewShellBase() )) // IASS
1345 return DND_ACTION_NONE;
1347 Broadcast(ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START));
1348 sal_Int8 nResult (mpDrawView->ExecuteDrop( rEvt, pTargetWindow, nPage, nLayer ));
1349 Broadcast(ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END));
1351 return nResult;
1354 } // end of namespace sd
1356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */