/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "NotesPaneModule.hxx" #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::drawing::framework; namespace { const sal_Int32 ResourceActivationRequestEvent = 0; const sal_Int32 ResourceDeactivationRequestEvent = 1; } namespace sd::framework { NotesPaneModule::NotesPaneModule(const rtl::Reference<::sd::DrawController>& rxController) : mxBottomImpressPaneId(FrameworkHelper::CreateResourceId( FrameworkHelper::msNotesPanelViewURL, FrameworkHelper::msBottomImpressPaneURL)) , mxMainViewAnchorId(FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL)) { if (!rxController.is()) return; mpViewShellBase = rxController->GetViewShellBase(); mxConfigurationController = rxController->getConfigurationController(); if (!mxConfigurationController.is()) return; mxConfigurationController->addConfigurationChangeListener( this, FrameworkHelper::msResourceActivationRequestEvent, Any(ResourceActivationRequestEvent)); mxConfigurationController->addConfigurationChangeListener( this, FrameworkHelper::msResourceDeactivationRequestEvent, Any(ResourceDeactivationRequestEvent)); if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::ImpressView::get().value_or( false)) AddActiveMainView(FrameworkHelper::msImpressViewURL); if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::OutlineView::get().value_or( false)) AddActiveMainView(FrameworkHelper::msOutlineViewURL); if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::NotesView::get().value_or( false)) AddActiveMainView(FrameworkHelper::msNotesViewURL); } NotesPaneModule::~NotesPaneModule() { if (mpViewShellBase && mbListeningEventMultiplexer) mpViewShellBase->GetEventMultiplexer()->RemoveEventListener( LINK(this, NotesPaneModule, EventMultiplexerListener)); } void NotesPaneModule::AddActiveMainView(const OUString& rsMainViewURL) { maActiveMainViewContainer.insert(rsMainViewURL); } bool NotesPaneModule::IsResourceActive(const OUString& rsMainViewURL) { return maActiveMainViewContainer.contains(rsMainViewURL); } void NotesPaneModule::SaveResourceState() { auto xChanges = comphelper::ConfigurationChanges::create(); officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::ImpressView::set( IsResourceActive(FrameworkHelper::msImpressViewURL), xChanges); officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::OutlineView::set( IsResourceActive(FrameworkHelper::msOutlineViewURL), xChanges); officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::NotesView::set( IsResourceActive(FrameworkHelper::msNotesViewURL), xChanges); xChanges->commit(); } void NotesPaneModule::disposing(std::unique_lock&) { if (mxConfigurationController.is()) { mxConfigurationController->removeConfigurationChangeListener(this); mxConfigurationController = nullptr; } } IMPL_LINK(NotesPaneModule, EventMultiplexerListener, sd::tools::EventMultiplexerEvent&, rEvent, void) { if (!mxConfigurationController.is()) return; switch (rEvent.meEventId) { case EventMultiplexerEventId::EditModeNormal: mbInMasterEditMode = false; if (IsResourceActive(msCurrentMainViewURL)) { mxConfigurationController->requestResourceActivation( mxBottomImpressPaneId->getAnchor(), ResourceActivationMode_ADD); mxConfigurationController->requestResourceActivation( mxBottomImpressPaneId, ResourceActivationMode_REPLACE); } else { mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); } break; case EventMultiplexerEventId::EditModeMaster: mbInMasterEditMode = true; mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); break; default: break; } } void SAL_CALL NotesPaneModule::notifyConfigurationChange(const ConfigurationChangeEvent& rEvent) { if (!mxConfigurationController.is()) return; // the late init is hacked here since there's EventMultiplexer isn't available when the // NotesPaneModule is constructed if (!mbListeningEventMultiplexer) { mpViewShellBase->GetEventMultiplexer()->AddEventListener( LINK(this, NotesPaneModule, EventMultiplexerListener)); mbListeningEventMultiplexer = true; } sal_Int32 nEventType = 0; rEvent.UserData >>= nEventType; switch (nEventType) { case ResourceActivationRequestEvent: if (rEvent.ResourceId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) { if (rEvent.ResourceId->getResourceTypePrefix() == FrameworkHelper::msViewURLPrefix) { onMainViewSwitch(rEvent.ResourceId->getResourceURL(), true); } } else if (rEvent.ResourceId->compareTo(mxBottomImpressPaneId) == 0) { onResourceRequest(true, rEvent.Configuration); } break; case ResourceDeactivationRequestEvent: if (rEvent.ResourceId->compareTo(mxMainViewAnchorId) == 0) { onMainViewSwitch(OUString(), false); } else if (rEvent.ResourceId->compareTo(mxBottomImpressPaneId) == 0) { onResourceRequest(false, rEvent.Configuration); } break; default: break; } } void SAL_CALL NotesPaneModule::disposing(const lang::EventObject& rEvent) { if (mxConfigurationController.is() && rEvent.Source == mxConfigurationController) { SaveResourceState(); // Without the configuration controller this class can do nothing. mxConfigurationController = nullptr; dispose(); } } void NotesPaneModule::onMainViewSwitch(const OUString& rsViewURL, const bool bIsActivated) { if (bIsActivated) msCurrentMainViewURL = rsViewURL; else msCurrentMainViewURL.clear(); if (!mxConfigurationController.is()) return; sd::framework::ConfigurationController::Lock aLock(mxConfigurationController); if (IsResourceActive(msCurrentMainViewURL) && !mbInMasterEditMode) { mxConfigurationController->requestResourceActivation(mxBottomImpressPaneId->getAnchor(), ResourceActivationMode_ADD); mxConfigurationController->requestResourceActivation(mxBottomImpressPaneId, ResourceActivationMode_REPLACE); } else { mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); } } bool NotesPaneModule::IsMasterView(const Reference& xView) { if (mpViewShellBase != nullptr) { auto pViewShellWrapper = dynamic_cast(xView.get()); if (pViewShellWrapper) { std::shared_ptr pViewShell = pViewShellWrapper->GetViewShell(); auto pDrawViewShell = std::dynamic_pointer_cast(pViewShell); if (pDrawViewShell && pDrawViewShell->GetEditMode() == EditMode::MasterPage) return true; } } return false; } void NotesPaneModule::onResourceRequest( bool bActivation, const css::uno::Reference& rxConfiguration) { Sequence> aCenterViews = rxConfiguration->getResources( FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL), FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT); if (aCenterViews.getLength() != 1) return; // do not record the state of bottom pane when in master edit modes if (!IsMasterView({ mxConfigurationController->getResource(aCenterViews[0]), UNO_QUERY })) { if (bActivation) { maActiveMainViewContainer.insert(aCenterViews[0]->getResourceURL()); } else { maActiveMainViewContainer.erase(aCenterViews[0]->getResourceURL()); } } } } // end of namespace sd::framework /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */