| /************************************************************** |
| * |
| * 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 "BasicPaneFactory.hxx" |
| |
| #include "ChildWindowPane.hxx" |
| #include "FrameWindowPane.hxx" |
| #include "FullScreenPane.hxx" |
| |
| #include "framework/FrameworkHelper.hxx" |
| #include "ViewShellBase.hxx" |
| #include "PaneChildWindows.hxx" |
| #include "DrawController.hxx" |
| #include "DrawDocShell.hxx" |
| #include <com/sun/star/drawing/framework/XControllerManager.hpp> |
| #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 { |
| enum PaneId { |
| CenterPaneId, |
| FullScreenPaneId, |
| LeftImpressPaneId, |
| LeftDrawPaneId |
| }; |
| |
| static const sal_Int32 gnConfigurationUpdateStartEvent(0); |
| static const sal_Int32 gnConfigurationUpdateEndEvent(1); |
| } |
| |
| namespace sd { namespace framework { |
| |
| |
| /** Store URL, XPane reference and (local) PaneId for every pane factory |
| that is registered at the PaneController. |
| */ |
| class BasicPaneFactory::PaneDescriptor |
| { |
| public: |
| OUString msPaneURL; |
| Reference<XResource> mxPane; |
| PaneId mePaneId; |
| /** The mbReleased flag is set when the pane has been released. Some |
| panes are just hidden and destroyed. When the pane is reused this |
| flag is reset. |
| */ |
| bool mbIsReleased; |
| bool mbIsChildWindow; |
| |
| bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); } |
| bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; } |
| }; |
| |
| |
| class BasicPaneFactory::PaneContainer |
| : public ::std::vector<PaneDescriptor> |
| { |
| public: |
| PaneContainer (void) {} |
| }; |
| |
| |
| |
| Reference<XInterface> SAL_CALL BasicPaneFactory_createInstance ( |
| const Reference<XComponentContext>& rxContext) |
| { |
| return Reference<XInterface>(static_cast<XWeak*>(new BasicPaneFactory(rxContext))); |
| } |
| |
| |
| |
| |
| ::rtl::OUString BasicPaneFactory_getImplementationName (void) throw(RuntimeException) |
| { |
| return ::rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicPaneFactory")); |
| } |
| |
| |
| |
| |
| Sequence<rtl::OUString> SAL_CALL BasicPaneFactory_getSupportedServiceNames (void) |
| throw (RuntimeException) |
| { |
| static const ::rtl::OUString sServiceName( |
| ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicPaneFactory")); |
| return Sequence<rtl::OUString>(&sServiceName, 1); |
| } |
| |
| |
| |
| |
| //===== PaneFactory =========================================================== |
| |
| BasicPaneFactory::BasicPaneFactory ( |
| const Reference<XComponentContext>& rxContext) |
| : BasicPaneFactoryInterfaceBase(m_aMutex), |
| mxComponentContext(rxContext), |
| mxConfigurationControllerWeak(), |
| mpViewShellBase(NULL), |
| mpPaneContainer(new PaneContainer), |
| mbFirstUpdateSeen(false), |
| mpUpdateLockManager() |
| { |
| } |
| |
| |
| |
| |
| |
| BasicPaneFactory::~BasicPaneFactory (void) |
| { |
| } |
| |
| |
| |
| |
| void SAL_CALL BasicPaneFactory::disposing (void) |
| { |
| Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); |
| if (xCC.is()) |
| { |
| xCC->removeResourceFactoryForReference(this); |
| xCC->removeConfigurationChangeListener(this); |
| mxConfigurationControllerWeak = Reference<XConfigurationController>(); |
| } |
| |
| for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin(); |
| iDescriptor != mpPaneContainer->end(); |
| ++iDescriptor) |
| { |
| if (iDescriptor->mbIsReleased) |
| { |
| Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY); |
| if (xComponent.is()) |
| { |
| xComponent->removeEventListener(this); |
| xComponent->dispose(); |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments) |
| throw (Exception, RuntimeException) |
| { |
| if (aArguments.getLength() > 0) |
| { |
| try |
| { |
| // Get the XController from the first argument. |
| Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW); |
| mxControllerWeak = xController; |
| |
| // Tunnel through the controller to obtain access to the ViewShellBase. |
| try |
| { |
| Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW); |
| DrawController* pController |
| = reinterpret_cast<DrawController*>( |
| (sal::static_int_cast<sal_uIntPtr>( |
| xTunnel->getSomething(DrawController::getUnoTunnelId())))); |
| mpViewShellBase = pController->GetViewShellBase(); |
| mpUpdateLockManager = mpViewShellBase->GetUpdateLockManager(); |
| } |
| catch(RuntimeException&) |
| {} |
| |
| Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW); |
| Reference<XConfigurationController> xCC (xCM->getConfigurationController()); |
| mxConfigurationControllerWeak = xCC; |
| |
| // Add pane factories for the two left panes (one for Impress and one for |
| // Draw) and the center pane. |
| if (xController.is() && xCC.is()) |
| { |
| PaneDescriptor aDescriptor; |
| aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL; |
| aDescriptor.mePaneId = CenterPaneId; |
| aDescriptor.mbIsReleased = false; |
| aDescriptor.mbIsChildWindow = false; |
| mpPaneContainer->push_back(aDescriptor); |
| xCC->addResourceFactory(aDescriptor.msPaneURL, this); |
| |
| aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL; |
| aDescriptor.mePaneId = FullScreenPaneId; |
| mpPaneContainer->push_back(aDescriptor); |
| xCC->addResourceFactory(aDescriptor.msPaneURL, this); |
| |
| aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL; |
| aDescriptor.mePaneId = LeftImpressPaneId; |
| aDescriptor.mbIsChildWindow = true; |
| mpPaneContainer->push_back(aDescriptor); |
| xCC->addResourceFactory(aDescriptor.msPaneURL, this); |
| |
| aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL; |
| aDescriptor.mePaneId = LeftDrawPaneId; |
| mpPaneContainer->push_back(aDescriptor); |
| xCC->addResourceFactory(aDescriptor.msPaneURL, this); |
| } |
| |
| // Register as configuration change listener. |
| if (xCC.is()) |
| { |
| xCC->addConfigurationChangeListener( |
| this, |
| FrameworkHelper::msConfigurationUpdateStartEvent, |
| makeAny(gnConfigurationUpdateStartEvent)); |
| xCC->addConfigurationChangeListener( |
| this, |
| FrameworkHelper::msConfigurationUpdateEndEvent, |
| makeAny(gnConfigurationUpdateEndEvent)); |
| } |
| } |
| catch (RuntimeException&) |
| { |
| Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); |
| if (xCC.is()) |
| xCC->removeResourceFactoryForReference(this); |
| } |
| } |
| } |
| |
| |
| |
| |
| //===== XPaneFactory ========================================================== |
| |
| Reference<XResource> SAL_CALL BasicPaneFactory::createResource ( |
| const Reference<XResourceId>& rxPaneId) |
| throw (RuntimeException, IllegalArgumentException, WrappedTargetException) |
| { |
| ThrowIfDisposed(); |
| |
| Reference<XResource> xPane; |
| |
| // Based on the ResourceURL of the given ResourceId look up the |
| // corresponding factory descriptor. |
| PaneContainer::iterator iDescriptor ( |
| ::std::find_if ( |
| mpPaneContainer->begin(), |
| mpPaneContainer->end(), |
| ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL()))); |
| |
| if (iDescriptor != mpPaneContainer->end()) |
| { |
| if (iDescriptor->mxPane.is()) |
| { |
| // The pane has already been created and is still active (has |
| // not yet been released). This should not happen. |
| xPane = iDescriptor->mxPane; |
| } |
| else |
| { |
| // Create a new pane. |
| switch (iDescriptor->mePaneId) |
| { |
| case CenterPaneId: |
| xPane = CreateFrameWindowPane(rxPaneId); |
| break; |
| |
| case FullScreenPaneId: |
| xPane = CreateFullScreenPane(mxComponentContext, rxPaneId); |
| break; |
| |
| case LeftImpressPaneId: |
| case LeftDrawPaneId: |
| xPane = CreateChildWindowPane( |
| rxPaneId, |
| *iDescriptor); |
| break; |
| } |
| iDescriptor->mxPane = xPane; |
| |
| // Listen for the pane being disposed. |
| Reference<lang::XComponent> xComponent (xPane, UNO_QUERY); |
| if (xComponent.is()) |
| xComponent->addEventListener(this); |
| } |
| iDescriptor->mbIsReleased = false; |
| } |
| else |
| { |
| // The requested pane can not be created by any of the factories |
| // managed by the called BasicPaneFactory object. |
| throw lang::IllegalArgumentException( |
| ::rtl::OUString::createFromAscii( |
| "BasicPaneFactory::createPane() called for unknown resource id"), |
| NULL, |
| 0); |
| } |
| |
| return xPane; |
| } |
| |
| |
| |
| |
| |
| void SAL_CALL BasicPaneFactory::releaseResource ( |
| const Reference<XResource>& rxPane) |
| throw (RuntimeException) |
| { |
| ThrowIfDisposed(); |
| |
| // Based on the given XPane reference look up the corresponding factory |
| // descriptor. |
| PaneContainer::iterator iDescriptor ( |
| ::std::find_if( |
| mpPaneContainer->begin(), |
| mpPaneContainer->end(), |
| ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane))); |
| |
| if (iDescriptor != mpPaneContainer->end()) |
| { |
| // The given pane was created by one of the factories. Child |
| // windows are just hidden and will be reused when requested later. |
| // Other windows are disposed and their reference is reset so that |
| // on the next createPane() call for the same pane type the pane is |
| // created anew. |
| ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get()); |
| if (pChildWindowPane != NULL) |
| { |
| iDescriptor->mbIsReleased = true; |
| pChildWindowPane->Hide(); |
| } |
| else |
| { |
| iDescriptor->mxPane = NULL; |
| Reference<XComponent> xComponent (rxPane, UNO_QUERY); |
| if (xComponent.is()) |
| { |
| // We are disposing the pane and do not have to be informed of |
| // that. |
| xComponent->removeEventListener(this); |
| xComponent->dispose(); |
| } |
| } |
| } |
| else |
| { |
| // The given XPane reference is either empty or the pane was not |
| // created by any of the factories managed by the called |
| // BasicPaneFactory object. |
| throw lang::IllegalArgumentException( |
| ::rtl::OUString::createFromAscii( |
| "BasicPaneFactory::releasePane() called for pane that that was not created by same factory."), |
| NULL, |
| 0); |
| } |
| } |
| |
| |
| |
| |
| //===== XConfigurationChangeListener ========================================== |
| |
| void SAL_CALL BasicPaneFactory::notifyConfigurationChange ( |
| const ConfigurationChangeEvent& rEvent) |
| throw (RuntimeException) |
| { |
| sal_Int32 nEventType = 0; |
| rEvent.UserData >>= nEventType; |
| switch (nEventType) |
| { |
| case gnConfigurationUpdateStartEvent: |
| // Lock UI updates while we are switching the views except for |
| // the first time after creation. Outherwise this leads to |
| // problems after reload (missing resizes for the side panes). |
| if (mbFirstUpdateSeen) |
| { |
| if (mpUpdateLockManager.get()!=NULL) |
| { |
| // ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex()); |
| // mpUpdateLockManager->Lock(); |
| } |
| } |
| else |
| mbFirstUpdateSeen = true; |
| break; |
| |
| case gnConfigurationUpdateEndEvent: |
| // Unlock the update lock here when only the visibility of |
| // windows but not the view shells displayed in them have |
| // changed. Otherwise the UpdateLockManager takes care of |
| // unlocking at the right time. |
| if (mpUpdateLockManager.get() != NULL) |
| { |
| ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex()); |
| // if (mpUpdateLockManager->IsLocked()) |
| // mpUpdateLockManager->Unlock(); |
| } |
| break; |
| } |
| } |
| |
| |
| |
| |
| //===== lang::XEventListener ================================================== |
| |
| void SAL_CALL BasicPaneFactory::disposing ( |
| const lang::EventObject& rEventObject) |
| throw (RuntimeException) |
| { |
| if (mxConfigurationControllerWeak == rEventObject.Source) |
| { |
| mxConfigurationControllerWeak = Reference<XConfigurationController>(); |
| } |
| else |
| { |
| // Has one of the panes been disposed? If so, then release the |
| // reference to that pane, but not the pane descriptor. |
| Reference<XResource> xPane (rEventObject.Source, UNO_QUERY); |
| PaneContainer::iterator iDescriptor ( |
| ::std::find_if ( |
| mpPaneContainer->begin(), |
| mpPaneContainer->end(), |
| ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane))); |
| if (iDescriptor != mpPaneContainer->end()) |
| { |
| iDescriptor->mxPane = NULL; |
| } |
| } |
| } |
| |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| Reference<XResource> BasicPaneFactory::CreateFrameWindowPane ( |
| const Reference<XResourceId>& rxPaneId) |
| { |
| Reference<XResource> xPane; |
| |
| if (mpViewShellBase != NULL) |
| { |
| xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow()); |
| } |
| |
| return xPane; |
| } |
| |
| |
| |
| |
| Reference<XResource> BasicPaneFactory::CreateFullScreenPane ( |
| const Reference<XComponentContext>& rxComponentContext, |
| const Reference<XResourceId>& rxPaneId) |
| { |
| Reference<XResource> xPane ( |
| new FullScreenPane( |
| rxComponentContext, |
| rxPaneId, |
| mpViewShellBase->GetViewWindow())); |
| |
| return xPane; |
| } |
| |
| |
| |
| |
| Reference<XResource> BasicPaneFactory::CreateChildWindowPane ( |
| const Reference<XResourceId>& rxPaneId, |
| const PaneDescriptor& rDescriptor) |
| { |
| Reference<XResource> xPane; |
| |
| if (mpViewShellBase != NULL) |
| { |
| // Create the corresponding shell and determine the id of the child window. |
| sal_uInt16 nChildWindowId = 0; |
| ::std::auto_ptr<SfxShell> pShell; |
| switch (rDescriptor.mePaneId) |
| { |
| case LeftImpressPaneId: |
| pShell.reset(new LeftImpressPaneShell()); |
| nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId(); |
| break; |
| |
| case LeftDrawPaneId: |
| pShell.reset(new LeftDrawPaneShell()); |
| nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId(); |
| break; |
| |
| default: |
| break; |
| } |
| |
| // With shell and child window id create the ChildWindowPane |
| // wrapper. |
| if (pShell.get() != NULL) |
| { |
| xPane = new ChildWindowPane( |
| rxPaneId, |
| nChildWindowId, |
| *mpViewShellBase, |
| pShell); |
| } |
| } |
| |
| return xPane; |
| } |
| |
| void BasicPaneFactory::ThrowIfDisposed (void) const |
| throw (lang::DisposedException) |
| { |
| if (rBHelper.bDisposed || rBHelper.bInDispose) |
| { |
| throw lang::DisposedException ( |
| ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( |
| "BasicPaneFactory object has already been disposed")), |
| const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); |
| } |
| } |
| |
| |
| } } // end of namespace sd::framework |