| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "precompiled_sd.hxx" |
| |
| #include "BasicViewFactory.hxx" |
| |
| #include "framework/ViewShellWrapper.hxx" |
| #include "framework/FrameworkHelper.hxx" |
| #include <com/sun/star/drawing/framework/XControllerManager.hpp> |
| #include <com/sun/star/lang/IllegalArgumentException.hpp> |
| #include "framework/Pane.hxx" |
| #include "DrawController.hxx" |
| #include "DrawSubController.hxx" |
| #include "ViewShellBase.hxx" |
| #include "ViewShellManager.hxx" |
| #include "DrawDocShell.hxx" |
| #include "DrawViewShell.hxx" |
| #include "GraphicViewShell.hxx" |
| #include "OutlineViewShell.hxx" |
| #include "PresentationViewShell.hxx" |
| #include "SlideSorterViewShell.hxx" |
| #include "FrameView.hxx" |
| |
| #include <sfx2/viewfrm.hxx> |
| #include <vcl/wrkwin.hxx> |
| #include <toolkit/helper/vclunohelper.hxx> |
| |
| #include <boost/bind.hpp> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::drawing::framework; |
| |
| using ::rtl::OUString; |
| using ::sd::framework::FrameworkHelper; |
| |
| |
| namespace sd { namespace framework { |
| |
| |
| Reference<XInterface> SAL_CALL BasicViewFactory_createInstance ( |
| const Reference<XComponentContext>& rxContext) |
| { |
| return Reference<XInterface>(static_cast<XWeak*>(new BasicViewFactory(rxContext))); |
| } |
| |
| |
| |
| |
| ::rtl::OUString BasicViewFactory_getImplementationName (void) throw(RuntimeException) |
| { |
| return ::rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicViewFactory")); |
| } |
| |
| |
| |
| |
| Sequence<rtl::OUString> SAL_CALL BasicViewFactory_getSupportedServiceNames (void) |
| throw (RuntimeException) |
| { |
| static const ::rtl::OUString sServiceName( |
| ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicViewFactory")); |
| return Sequence<rtl::OUString>(&sServiceName, 1); |
| } |
| |
| |
| |
| |
| //===== ViewDescriptor ======================================================== |
| |
| class BasicViewFactory::ViewDescriptor |
| { |
| public: |
| Reference<XResource> mxView; |
| ::boost::shared_ptr<sd::ViewShell> mpViewShell; |
| ViewShellWrapper* mpWrapper; |
| Reference<XResourceId> mxViewId; |
| static bool CompareView (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor, |
| const Reference<XResource>& rxView) |
| { return rpDescriptor->mxView.get() == rxView.get(); } |
| }; |
| |
| |
| |
| |
| |
| //===== BasicViewFactory::ViewShellContainer ================================== |
| |
| class BasicViewFactory::ViewShellContainer |
| : public ::std::vector<boost::shared_ptr<ViewDescriptor> > |
| { |
| public: |
| ViewShellContainer (void) {}; |
| }; |
| |
| |
| class BasicViewFactory::ViewCache |
| : public ::std::vector<boost::shared_ptr<ViewDescriptor> > |
| { |
| public: |
| ViewCache (void) {}; |
| }; |
| |
| |
| |
| |
| //===== ViewFactory =========================================================== |
| |
| BasicViewFactory::BasicViewFactory ( |
| const Reference<XComponentContext>& rxContext) |
| : BasicViewFactoryInterfaceBase(MutexOwner::maMutex), |
| mxConfigurationController(), |
| mpViewShellContainer(new ViewShellContainer()), |
| mpBase(NULL), |
| mpFrameView(NULL), |
| mpWindow(new WorkWindow(NULL,WB_STDWORK)), |
| mpViewCache(new ViewCache()), |
| mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get())) |
| { |
| (void)rxContext; |
| } |
| |
| |
| |
| |
| BasicViewFactory::~BasicViewFactory (void) |
| { |
| } |
| |
| |
| |
| |
| void SAL_CALL BasicViewFactory::disposing (void) |
| { |
| // Disconnect from the frame view. |
| if (mpFrameView != NULL) |
| { |
| mpFrameView->Disconnect(); |
| mpFrameView = NULL; |
| } |
| |
| // Relase the view cache. |
| ViewShellContainer::const_iterator iView; |
| for (iView=mpViewCache->begin(); iView!=mpViewCache->end(); ++iView) |
| { |
| ReleaseView(*iView, true); |
| } |
| |
| // Release the view shell container. At this point no one other than us |
| // should hold references to the view shells (at the moment this is a |
| // trivial requirement, because no one other then us holds a shared |
| // pointer). |
| // ViewShellContainer::const_iterator iView; |
| for (iView=mpViewShellContainer->begin(); iView!=mpViewShellContainer->end(); ++iView) |
| { |
| OSL_ASSERT((*iView)->mpViewShell.unique()); |
| } |
| mpViewShellContainer.reset(); |
| } |
| |
| |
| |
| |
| Reference<XResource> SAL_CALL BasicViewFactory::createResource ( |
| const Reference<XResourceId>& rxViewId) |
| throw(RuntimeException, IllegalArgumentException, WrappedTargetException) |
| { |
| Reference<XResource> xView; |
| const bool bIsCenterPane ( |
| rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)); |
| |
| // Get the pane for the anchor URL. |
| Reference<XPane> xPane; |
| if (mxConfigurationController.is()) |
| xPane = Reference<XPane>(mxConfigurationController->getResource(rxViewId->getAnchor()), |
| UNO_QUERY); |
| |
| // For main views use the frame view of the last main view. |
| ::sd::FrameView* pFrameView = NULL; |
| if (xPane.is() && bIsCenterPane) |
| { |
| pFrameView = mpFrameView; |
| } |
| |
| // Get Window pointer for XWindow of the pane. |
| ::Window* pWindow = NULL; |
| if (xPane.is()) |
| pWindow = VCLUnoHelper::GetWindow(xPane->getWindow()); |
| |
| // Get the view frame. |
| SfxViewFrame* pFrame = NULL; |
| if (mpBase != NULL) |
| pFrame = mpBase->GetViewFrame(); |
| |
| if (pFrame != NULL && mpBase!=NULL && pWindow!=NULL) |
| { |
| // Try to get the view from the cache. |
| ::boost::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane)); |
| |
| // When the requested view is not in the cache then create a new view. |
| if (pDescriptor.get() == NULL) |
| { |
| pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane); |
| } |
| |
| if (pDescriptor.get() != NULL) |
| xView = pDescriptor->mxView; |
| |
| mpViewShellContainer->push_back(pDescriptor); |
| |
| if (bIsCenterPane) |
| ActivateCenterView(pDescriptor); |
| else |
| pWindow->Resize(); |
| } |
| |
| return xView; |
| } |
| |
| |
| |
| |
| void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView) |
| throw(RuntimeException) |
| { |
| if ( ! rxView.is()) |
| throw lang::IllegalArgumentException(); |
| |
| if (rxView.is() && mpBase!=NULL) |
| { |
| ViewShellContainer::iterator iViewShell ( |
| ::std::find_if( |
| mpViewShellContainer->begin(), |
| mpViewShellContainer->end(), |
| ::boost::bind(&ViewDescriptor::CompareView, _1, rxView))); |
| if (iViewShell != mpViewShellContainer->end()) |
| { |
| ::boost::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell); |
| |
| if ((*iViewShell)->mxViewId->isBoundToURL( |
| FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) |
| { |
| // Obtain a pointer to and connect to the frame view of the |
| // view. The next view, that is created, will be |
| // initialized with this frame view. |
| if (mpFrameView == NULL) |
| { |
| mpFrameView = pViewShell->GetFrameView(); |
| if (mpFrameView) |
| mpFrameView->Connect(); |
| } |
| |
| // With the view in the center pane the sub controller is |
| // released, too. |
| mpBase->GetDrawController().SetSubController( |
| Reference<drawing::XDrawSubController>()); |
| |
| SfxViewShell* pSfxViewShell = pViewShell->GetViewShell(); |
| if (pSfxViewShell != NULL) |
| pSfxViewShell->DisconnectAllClients(); |
| } |
| |
| ReleaseView(*iViewShell); |
| |
| mpViewShellContainer->erase(iViewShell); |
| } |
| else |
| { |
| throw lang::IllegalArgumentException(); |
| } |
| } |
| } |
| |
| |
| |
| |
| void SAL_CALL BasicViewFactory::initialize (const Sequence<Any>& aArguments) |
| throw (Exception, RuntimeException) |
| { |
| if (aArguments.getLength() > 0) |
| { |
| Reference<XConfigurationController> xCC; |
| try |
| { |
| // Get the XController from the first argument. |
| Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW); |
| |
| // Tunnel through the controller to obtain a ViewShellBase. |
| Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW); |
| ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>( |
| xTunnel->getSomething(sd::DrawController::getUnoTunnelId())); |
| if (pController != NULL) |
| mpBase = pController->GetViewShellBase(); |
| |
| // Register the factory for its supported views. |
| Reference<XControllerManager> xCM (xController,UNO_QUERY_THROW); |
| mxConfigurationController = xCM->getConfigurationController(); |
| if ( ! mxConfigurationController.is()) |
| throw RuntimeException(); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this); |
| mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this); |
| } |
| catch (RuntimeException&) |
| { |
| mpBase = NULL; |
| if (mxConfigurationController.is()) |
| mxConfigurationController->removeResourceFactoryForReference(this); |
| throw; |
| } |
| } |
| } |
| |
| |
| |
| |
| ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView ( |
| const Reference<XResourceId>& rxViewId, |
| SfxViewFrame& rFrame, |
| ::Window& rWindow, |
| const Reference<XPane>& rxPane, |
| FrameView* pFrameView, |
| const bool bIsCenterPane) |
| { |
| ::boost::shared_ptr<ViewDescriptor> pDescriptor (new ViewDescriptor()); |
| |
| pDescriptor->mpViewShell = CreateViewShell( |
| rxViewId, |
| rFrame, |
| rWindow, |
| pFrameView, |
| bIsCenterPane); |
| pDescriptor->mxViewId = rxViewId; |
| |
| if (pDescriptor->mpViewShell.get() != NULL) |
| { |
| pDescriptor->mpViewShell->Init(bIsCenterPane); |
| mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get()); |
| |
| pDescriptor->mpWrapper = new ViewShellWrapper( |
| pDescriptor->mpViewShell, |
| rxViewId, |
| rxPane->getWindow()); |
| pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( XResource::static_type() ), UNO_QUERY_THROW ); |
| } |
| |
| return pDescriptor; |
| } |
| |
| |
| |
| |
| ::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell ( |
| const Reference<XResourceId>& rxViewId, |
| SfxViewFrame& rFrame, |
| ::Window& rWindow, |
| FrameView* pFrameView, |
| const bool bIsCenterPane) |
| { |
| ::boost::shared_ptr<ViewShell> pViewShell; |
| const OUString& rsViewURL (rxViewId->getResourceURL()); |
| if (rsViewURL.equals(FrameworkHelper::msImpressViewURL)) |
| { |
| pViewShell.reset( |
| new DrawViewShell( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| PK_STANDARD, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL)) |
| { |
| pViewShell.reset( |
| new GraphicViewShell ( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL)) |
| { |
| pViewShell.reset( |
| new OutlineViewShell ( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL)) |
| { |
| pViewShell.reset( |
| new DrawViewShell( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| PK_NOTES, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL)) |
| { |
| pViewShell.reset( |
| new DrawViewShell( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| PK_HANDOUT, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL)) |
| { |
| pViewShell.reset( |
| new PresentationViewShell( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| pFrameView)); |
| } |
| else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL)) |
| { |
| pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create ( |
| &rFrame, |
| *mpBase, |
| &rWindow, |
| pFrameView, |
| bIsCenterPane); |
| } |
| |
| return pViewShell; |
| } |
| |
| |
| |
| |
| void BasicViewFactory::ReleaseView ( |
| const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor, |
| bool bDoNotCache) |
| { |
| bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor)); |
| |
| if (bIsCacheable) |
| { |
| Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY); |
| if (xResource.is()) |
| { |
| Reference<XResource> xNewAnchor (mxLocalPane, UNO_QUERY); |
| if (xNewAnchor.is()) |
| if (xResource->relocateToAnchor(xNewAnchor)) |
| mpViewCache->push_back(rpDescriptor); |
| else |
| bIsCacheable = false; |
| else |
| bIsCacheable = false; |
| } |
| else |
| { |
| bIsCacheable = false; |
| } |
| } |
| |
| if ( ! bIsCacheable) |
| { |
| // Shut down the current view shell. |
| rpDescriptor->mpViewShell->Shutdown (); |
| mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get()); |
| mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get()); |
| |
| Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY); |
| if (xComponent.is()) |
| xComponent->dispose(); |
| } |
| } |
| |
| |
| |
| |
| bool BasicViewFactory::IsCacheable (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor) |
| { |
| bool bIsCacheable (false); |
| |
| Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY); |
| if (xResource.is()) |
| { |
| static ::std::vector<Reference<XResourceId> > maCacheableResources; |
| if (maCacheableResources.empty() ) |
| { |
| ::boost::shared_ptr<FrameworkHelper> pHelper (FrameworkHelper::Instance(*mpBase)); |
| |
| // The slide sorter and the task panel are cacheable and relocatable. |
| maCacheableResources.push_back(pHelper->CreateResourceId( |
| FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL)); |
| maCacheableResources.push_back(pHelper->CreateResourceId( |
| FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL)); |
| } |
| |
| ::std::vector<Reference<XResourceId> >::const_iterator iId; |
| for (iId=maCacheableResources.begin(); iId!=maCacheableResources.end(); ++iId) |
| { |
| if ((*iId)->compareTo(rpDescriptor->mxViewId) == 0) |
| { |
| bIsCacheable = true; |
| break; |
| } |
| } |
| } |
| |
| return bIsCacheable; |
| } |
| |
| |
| |
| |
| ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache ( |
| const Reference<XResourceId>& rxViewId, |
| const Reference<XPane>& rxPane) |
| { |
| ::boost::shared_ptr<ViewDescriptor> pDescriptor; |
| |
| // Search for the requested view in the cache. |
| ViewCache::iterator iEntry; |
| for (iEntry=mpViewCache->begin(); iEntry!=mpViewCache->end(); ++iEntry) |
| { |
| if ((*iEntry)->mxViewId->compareTo(rxViewId) == 0) |
| { |
| pDescriptor = *iEntry; |
| mpViewCache->erase(iEntry); |
| break; |
| } |
| } |
| |
| // When the view has been found then relocate it to the given pane and |
| // remove it from the cache. |
| if (pDescriptor.get() != NULL) |
| { |
| bool bRelocationSuccessfull (false); |
| Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY); |
| Reference<XResource> xNewAnchor (rxPane, UNO_QUERY); |
| if (xResource.is() && xNewAnchor.is()) |
| { |
| if (xResource->relocateToAnchor(xNewAnchor)) |
| bRelocationSuccessfull = true; |
| } |
| |
| if ( ! bRelocationSuccessfull) |
| { |
| ReleaseView(pDescriptor, true); |
| pDescriptor.reset(); |
| } |
| } |
| |
| return pDescriptor; |
| } |
| |
| |
| |
| |
| void BasicViewFactory::ActivateCenterView ( |
| const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor) |
| { |
| mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get()); |
| |
| // During the creation of the new sub-shell, resize requests were not |
| // forwarded to it because it was not yet registered. Therefore, we |
| // have to request a resize now. |
| rpDescriptor->mpViewShell->UIFeatureChanged(); |
| if (mpBase->GetDocShell()->IsInPlaceActive()) |
| mpBase->GetViewFrame()->Resize(sal_True); |
| |
| mpBase->GetDrawController().SetSubController( |
| rpDescriptor->mpViewShell->CreateSubController()); |
| } |
| |
| } } // end of namespace sd::framework |