/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "PresenterViewFactory.hxx" #include "PresenterPaneContainer.hxx" #include "PresenterHelper.hxx" #include "PresenterHelpView.hxx" #include "PresenterNotesView.hxx" #include "PresenterSlideShowView.hxx" #include "PresenterSlidePreview.hxx" #include "PresenterSlideSorter.hxx" #include "PresenterToolBar.hxx" #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 sdext { namespace presenter { const OUString PresenterViewFactory::msCurrentSlidePreviewViewURL( "private:resource/view/Presenter/CurrentSlidePreview"); const OUString PresenterViewFactory::msNextSlidePreviewViewURL( "private:resource/view/Presenter/NextSlidePreview"); const OUString PresenterViewFactory::msNotesViewURL( "private:resource/view/Presenter/Notes"); const OUString PresenterViewFactory::msToolBarViewURL( "private:resource/view/Presenter/ToolBar"); const OUString PresenterViewFactory::msSlideSorterURL( "private:resource/view/Presenter/SlideSorter"); const OUString PresenterViewFactory::msHelpViewURL( "private:resource/view/Presenter/Help"); namespace { /** By default the PresenterSlidePreview shows the preview of the current slide. This adapter class makes it display the preview of the next slide. */ class NextSlidePreview : public PresenterSlidePreview { public: NextSlidePreview ( const css::uno::Reference& rxContext, const css::uno::Reference& rxViewId, const css::uno::Reference& rxAnchorPane, const ::rtl::Reference& rpPresenterController) : PresenterSlidePreview(rxContext, rxViewId, rxAnchorPane, rpPresenterController) { } virtual void SAL_CALL setCurrentPage ( const css::uno::Reference& rxSlide) override { Reference xSlideShowController ( mpPresenterController->GetSlideShowController()); Reference xSlide; if (xSlideShowController.is()) { const sal_Int32 nCount (xSlideShowController->getSlideCount()); sal_Int32 nNextSlideIndex (-1); if (xSlideShowController->getCurrentSlide() == rxSlide) { nNextSlideIndex = xSlideShowController->getNextSlideIndex(); } else { for (sal_Int32 nIndex=0; nIndex( xSlideShowController->getSlideByIndex(nIndex), UNO_QUERY)) { nNextSlideIndex = nIndex + 1; } } } if (nNextSlideIndex >= 0) { if (nNextSlideIndex < nCount) { xSlide.set( xSlideShowController->getSlideByIndex(nNextSlideIndex), UNO_QUERY); } } } PresenterSlidePreview::setCurrentPage(xSlide); } }; } // end of anonymous namespace //===== PresenterViewFactory ============================================== PresenterViewFactory::PresenterViewFactory ( const Reference& rxContext, const Reference& rxController, const ::rtl::Reference& rpPresenterController) : PresenterViewFactoryInterfaceBase(m_aMutex), mxComponentContext(rxContext), mxConfigurationController(), mxControllerWeak(rxController), mpPresenterController(rpPresenterController), mpResourceCache() { } Reference PresenterViewFactory::Create ( const Reference& rxContext, const Reference& rxController, const ::rtl::Reference& rpPresenterController) { rtl::Reference pFactory ( new PresenterViewFactory(rxContext,rxController,rpPresenterController)); pFactory->Register(rxController); return Reference( static_cast(pFactory.get()), UNO_QUERY); } void PresenterViewFactory::Register (const Reference& rxController) { try { // Get the configuration controller. Reference xCM (rxController, UNO_QUERY_THROW); mxConfigurationController = xCM->getConfigurationController(); if ( ! mxConfigurationController.is()) { throw RuntimeException(); } mxConfigurationController->addResourceFactory(msCurrentSlidePreviewViewURL, this); mxConfigurationController->addResourceFactory(msNextSlidePreviewViewURL, this); mxConfigurationController->addResourceFactory(msNotesViewURL, this); mxConfigurationController->addResourceFactory(msToolBarViewURL, this); mxConfigurationController->addResourceFactory(msSlideSorterURL, this); mxConfigurationController->addResourceFactory(msHelpViewURL, this); } catch (RuntimeException&) { OSL_ASSERT(false); if (mxConfigurationController.is()) mxConfigurationController->removeResourceFactoryForReference(this); mxConfigurationController = nullptr; throw; } } PresenterViewFactory::~PresenterViewFactory() { } void SAL_CALL PresenterViewFactory::disposing() { if (mxConfigurationController.is()) mxConfigurationController->removeResourceFactoryForReference(this); mxConfigurationController = nullptr; if (mpResourceCache == nullptr) return; // Dispose all views in the cache. for (const auto& rView : *mpResourceCache) { try { Reference xComponent (rView.second.first, UNO_QUERY); if (xComponent.is()) xComponent->dispose(); } catch (lang::DisposedException&) { } } mpResourceCache.reset(); } //----- XViewFactory ---------------------------------------------------------- Reference SAL_CALL PresenterViewFactory::createResource ( const Reference& rxViewId) { ThrowIfDisposed(); Reference xView; if (rxViewId.is()) { Reference xAnchorPane ( mxConfigurationController->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); xView = GetViewFromCache(rxViewId, xAnchorPane); if (xView == nullptr) xView = CreateView(rxViewId, xAnchorPane); // Activate the view. PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( mpPresenterController->GetPaneContainer()->FindPaneId(rxViewId->getAnchor())); if (pDescriptor.get() != nullptr) pDescriptor->SetActivationState(true); } return xView; } void SAL_CALL PresenterViewFactory::releaseResource (const Reference& rxView) { ThrowIfDisposed(); if ( ! rxView.is()) return; // Deactivate the view. PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( mpPresenterController->GetPaneContainer()->FindPaneId( rxView->getResourceId()->getAnchor())); if (pDescriptor.get() != nullptr) pDescriptor->SetActivationState(false); // Dispose only views that we can not put into the cache. CachablePresenterView* pView = dynamic_cast(rxView.get()); if (pView == nullptr || mpResourceCache == nullptr) { try { if (pView != nullptr) pView->ReleaseView(); Reference xComponent (rxView, UNO_QUERY); if (xComponent.is()) xComponent->dispose(); } catch (lang::DisposedException&) { // Do not let disposed exceptions get out. It might be interpreted // as coming from the factory, which would then be removed from the // drawing framework. } } else { // Put cachable views in the cache. Reference xViewId (rxView->getResourceId()); if (xViewId.is()) { Reference xAnchorPane ( mxConfigurationController->getResource(xViewId->getAnchor()), UNO_QUERY_THROW); (*mpResourceCache)[xViewId->getResourceURL()] = ViewResourceDescriptor(Reference(rxView, UNO_QUERY), xAnchorPane); pView->DeactivatePresenterView(); } } } Reference PresenterViewFactory::GetViewFromCache( const Reference& rxViewId, const Reference& rxAnchorPane) const { if (mpResourceCache == nullptr) return nullptr; try { const OUString sResourceURL (rxViewId->getResourceURL()); // Can we use a view from the cache? ResourceContainer::const_iterator iView (mpResourceCache->find(sResourceURL)); if (iView != mpResourceCache->end()) { // The view is in the container but it can only be used if // the anchor pane is the same now as it was at creation of // the view. if (iView->second.second == rxAnchorPane) { CachablePresenterView* pView = dynamic_cast(iView->second.first.get()); if (pView != nullptr) pView->ActivatePresenterView(); return Reference(iView->second.first, UNO_QUERY); } // Right view, wrong pane. Create a new view. } } catch (RuntimeException&) { } return nullptr; } Reference PresenterViewFactory::CreateView( const Reference& rxViewId, const Reference& rxAnchorPane) { Reference xView; try { const OUString sResourceURL (rxViewId->getResourceURL()); if (sResourceURL == msCurrentSlidePreviewViewURL) { xView = CreateSlideShowView(rxViewId); } else if (sResourceURL == msNotesViewURL) { xView = CreateNotesView(rxViewId); } else if (sResourceURL == msNextSlidePreviewViewURL) { xView = CreateSlidePreviewView(rxViewId, rxAnchorPane); } else if (sResourceURL == msToolBarViewURL) { xView = CreateToolBarView(rxViewId); } else if (sResourceURL == msSlideSorterURL) { xView = CreateSlideSorterView(rxViewId); } else if (sResourceURL == msHelpViewURL) { xView = CreateHelpView(rxViewId); } // Activate it. CachablePresenterView* pView = dynamic_cast(xView.get()); if (pView != nullptr) pView->ActivatePresenterView(); } catch (RuntimeException&) { xView = nullptr; } return xView; } Reference PresenterViewFactory::CreateSlideShowView( const Reference& rxViewId) const { Reference xView; if ( ! mxConfigurationController.is()) return xView; if ( ! mxComponentContext.is()) return xView; try { rtl::Reference pShowView ( new PresenterSlideShowView( mxComponentContext, rxViewId, Reference(mxControllerWeak), mpPresenterController)); pShowView->LateInit(); xView.set(pShowView.get()); } catch (RuntimeException&) { xView = nullptr; } return xView; } Reference PresenterViewFactory::CreateSlidePreviewView( const Reference& rxViewId, const Reference& rxAnchorPane) const { Reference xView; if ( ! mxConfigurationController.is()) return xView; if ( ! mxComponentContext.is()) return xView; try { xView.set( static_cast(new NextSlidePreview( mxComponentContext, rxViewId, rxAnchorPane, mpPresenterController)), UNO_QUERY_THROW); } catch (RuntimeException&) { xView = nullptr; } return xView; } Reference PresenterViewFactory::CreateToolBarView( const Reference& rxViewId) const { return new PresenterToolBarView( mxComponentContext, rxViewId, Reference(mxControllerWeak), mpPresenterController); } Reference PresenterViewFactory::CreateNotesView( const Reference& rxViewId) const { Reference xView; if ( ! mxConfigurationController.is()) return xView; if ( ! mxComponentContext.is()) return xView; try { xView.set(static_cast( new PresenterNotesView( mxComponentContext, rxViewId, Reference(mxControllerWeak), mpPresenterController)), UNO_QUERY_THROW); } catch (RuntimeException&) { xView = nullptr; } return xView; } Reference PresenterViewFactory::CreateSlideSorterView( const Reference& rxViewId) const { Reference xView; if ( ! mxConfigurationController.is()) return xView; if ( ! mxComponentContext.is()) return xView; try { rtl::Reference pView ( new PresenterSlideSorter( mxComponentContext, rxViewId, Reference(mxControllerWeak), mpPresenterController)); xView = pView.get(); } catch (RuntimeException&) { xView = nullptr; } return xView; } Reference PresenterViewFactory::CreateHelpView( const Reference& rxViewId) const { return Reference(new PresenterHelpView( mxComponentContext, rxViewId, Reference(mxControllerWeak), mpPresenterController)); } void PresenterViewFactory::ThrowIfDisposed() const { if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ( "PresenterViewFactory object has already been disposed", const_cast(static_cast(this))); } } //===== CachablePresenterView ================================================= CachablePresenterView::CachablePresenterView() : mbIsPresenterViewActive(true) { } void CachablePresenterView::ActivatePresenterView() { mbIsPresenterViewActive = true; } void CachablePresenterView::DeactivatePresenterView() { mbIsPresenterViewActive = false; } void CachablePresenterView::ReleaseView() { } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */