/* -*- 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 "DrawController.hxx" #include "DrawDocShell.hxx" #include "DrawSubController.hxx" #include "sdpage.hxx" #include "ViewShellBase.hxx" #include "ViewShellManager.hxx" #include "FormShellManager.hxx" #include "Window.hxx" #include #include #include #include #include #include #include #include #include #include #include #include "slideshow.hxx" #include #include #include #include #include #include using namespace ::std; using namespace ::cppu; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::drawing::framework; using ::sfx2::sidebar::EnumContext; namespace sd { DrawController::DrawController (ViewShellBase& rBase) throw() : DrawControllerInterfaceBase(&rBase), BroadcastHelperOwner(SfxBaseController::m_aMutex), OPropertySetHelper( static_cast& >( BroadcastHelperOwner::maBroadcastHelper)), m_aSelectionTypeIdentifier( ::getCppuType( (Reference *)0 )), mpBase(&rBase), maLastVisArea(), mpCurrentPage(NULL), mbMasterPageMode(false), mbLayerMode(false), mbDisposing(false), mpPropertyArrayHelper(NULL), mxSubController(), mxConfigurationController(), mxModuleController() { ProvideFrameworkControllers(); } DrawController::~DrawController (void) throw() { } void DrawController::SetSubController ( const Reference& rxSubController) { // Update the internal state. mxSubController = rxSubController; mpPropertyArrayHelper.reset(); maLastVisArea = Rectangle(); // Inform listeners about the changed state. FireSelectionChangeListener(); } // XInterface IMPLEMENT_FORWARD_XINTERFACE2( DrawController, DrawControllerInterfaceBase, OPropertySetHelper); // XTypeProvider Sequence SAL_CALL DrawController::getTypes (void) throw (::com::sun::star::uno::RuntimeException) { ThrowIfDisposed(); // OPropertySetHelper does not provide getTypes, so we have to // implement this method manually and list its three interfaces. OTypeCollection aTypeCollection ( ::getCppuType (( const Reference*)NULL), ::getCppuType (( const Reference*)NULL), ::getCppuType (( const Reference*)NULL)); return ::comphelper::concatSequences( SfxBaseController::getTypes(), aTypeCollection.getTypes(), DrawControllerInterfaceBase::getTypes()); } IMPLEMENT_GET_IMPLEMENTATION_ID(DrawController); // XComponent void SAL_CALL DrawController::dispose (void) throw( RuntimeException ) { if( !mbDisposing ) { SolarMutexGuard aGuard; if( !mbDisposing ) { mbDisposing = true; boost::shared_ptr pViewShell; if (mpBase) pViewShell = mpBase->GetMainViewShell(); if ( pViewShell ) { pViewShell->DeactivateCurrentFunction(); DrawDocShell* pDocShell = pViewShell->GetDocSh(); if ( pDocShell != NULL ) pDocShell->SetDocShellFunction(0); } pViewShell.reset(); // When the controller has not been detached from its view // shell, i.e. mpViewShell is not NULL, then tell PaneManager // and ViewShellManager to clear the shell stack. if (mxSubController.is() && mpBase!=NULL) { mpBase->DisconnectAllClients(); mpBase->GetViewShellManager()->Shutdown(); } OPropertySetHelper::disposing(); DisposeFrameworkControllers(); SfxBaseController::dispose(); } } } void SAL_CALL DrawController::addEventListener( const Reference& xListener) throw (RuntimeException) { ThrowIfDisposed(); SfxBaseController::addEventListener( xListener ); } void SAL_CALL DrawController::removeEventListener ( const Reference& aListener) throw (RuntimeException) { if(!rBHelper.bDisposed && !rBHelper.bInDispose && !mbDisposing) SfxBaseController::removeEventListener( aListener ); } // XController ::sal_Bool SAL_CALL DrawController::suspend( ::sal_Bool Suspend ) throw (::com::sun::star::uno::RuntimeException) { if( Suspend ) { ViewShellBase* pViewShellBase = GetViewShellBase(); if( pViewShellBase ) { // do not allow suspend if a slideshow needs this controller! rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( *pViewShellBase ) ); if( xSlideShow.is() && xSlideShow->dependsOn(pViewShellBase) ) return sal_False; } } return SfxBaseController::suspend( Suspend ); } // XServiceInfo OUString SAL_CALL DrawController::getImplementationName( ) throw(RuntimeException) { // Do not throw an excepetion at the moment. This leads to a crash // under Solaris on relead. See issue i70929 for details. // ThrowIfDisposed(); return OUString("DrawController") ; } static OUString ssServiceName( "com.sun.star.drawing.DrawingDocumentDrawView"); sal_Bool SAL_CALL DrawController::supportsService ( const OUString& rsServiceName) throw(RuntimeException) { // Do not throw an exception at the moment. This leads to a crash // under Solaris on relead. See issue i70929 for details. // ThrowIfDisposed(); return rsServiceName.equals(ssServiceName); } Sequence SAL_CALL DrawController::getSupportedServiceNames (void) throw(RuntimeException) { ThrowIfDisposed(); Sequence aSupportedServices (1); OUString* pServices = aSupportedServices.getArray(); pServices[0] = ssServiceName; return aSupportedServices; } //------ XSelectionSupplier -------------------------------------------- sal_Bool SAL_CALL DrawController::select (const Any& aSelection) throw(lang::IllegalArgumentException, RuntimeException) { ThrowIfDisposed(); SolarMutexGuard aGuard; if (mxSubController.is()) return mxSubController->select(aSelection); else return false; } Any SAL_CALL DrawController::getSelection() throw(RuntimeException) { ThrowIfDisposed(); SolarMutexGuard aGuard; if (mxSubController.is()) return mxSubController->getSelection(); else return Any(); } void SAL_CALL DrawController::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener) throw(RuntimeException) { if( mbDisposing ) throw lang::DisposedException(); BroadcastHelperOwner::maBroadcastHelper.addListener (m_aSelectionTypeIdentifier, xListener); } void SAL_CALL DrawController::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener ) throw(RuntimeException) { if (rBHelper.bDisposed) throw lang::DisposedException(); BroadcastHelperOwner::maBroadcastHelper.removeListener (m_aSelectionTypeIdentifier, xListener); } //===== lang::XEventListener ================================================ void SAL_CALL DrawController::disposing (const lang::EventObject& ) throw (uno::RuntimeException) { } //===== view::XSelectionChangeListener ====================================== void SAL_CALL DrawController::selectionChanged (const lang::EventObject& rEvent) throw (uno::RuntimeException) { ThrowIfDisposed(); // Have to forward the event to our selection change listeners. OInterfaceContainerHelper* pListeners = BroadcastHelperOwner::maBroadcastHelper.getContainer( ::getCppuType((Reference*)0)); if (pListeners) { // Re-send the event to all of our listeners. OInterfaceIteratorHelper aIterator (*pListeners); while (aIterator.hasMoreElements()) { try { view::XSelectionChangeListener* pListener = static_cast( aIterator.next()); if (pListener != NULL) pListener->selectionChanged (rEvent); } catch (const RuntimeException&) { } } } } // XDrawView void SAL_CALL DrawController::setCurrentPage( const Reference< drawing::XDrawPage >& xPage ) throw(RuntimeException) { ThrowIfDisposed(); SolarMutexGuard aGuard; if (mxSubController.is()) mxSubController->setCurrentPage(xPage); } Reference< drawing::XDrawPage > SAL_CALL DrawController::getCurrentPage (void) throw(RuntimeException) { ThrowIfDisposed(); SolarMutexGuard aGuard; Reference xPage; // Get current page from sub controller. if (mxSubController.is()) xPage = mxSubController->getCurrentPage(); // When there is not yet a sub controller (during initialization) then fall back // to the current page in mpCurrentPage. if ( ! xPage.is() && mpCurrentPage.is()) xPage = Reference(mpCurrentPage->getUnoPage(), UNO_QUERY); return xPage; } void DrawController::FireVisAreaChanged (const Rectangle& rVisArea) throw() { if( maLastVisArea != rVisArea ) { Any aNewValue; aNewValue <<= awt::Rectangle( rVisArea.Left(), rVisArea.Top(), rVisArea.GetWidth(), rVisArea.GetHeight() ); Any aOldValue; aOldValue <<= awt::Rectangle( maLastVisArea.Left(), maLastVisArea.Top(), maLastVisArea.GetWidth(), maLastVisArea.GetHeight() ); FirePropertyChange (PROPERTY_WORKAREA, aNewValue, aOldValue); maLastVisArea = rVisArea; } } void DrawController::FireSelectionChangeListener() throw() { OInterfaceContainerHelper * pLC = BroadcastHelperOwner::maBroadcastHelper.getContainer( m_aSelectionTypeIdentifier); if( pLC ) { Reference< XInterface > xSource( (XWeak*)this ); const lang::EventObject aEvent( xSource ); // iterate over all listeners and send events OInterfaceIteratorHelper aIt( *pLC); while( aIt.hasMoreElements() ) { try { view::XSelectionChangeListener * pL = static_cast(aIt.next()); if (pL != NULL) pL->selectionChanged( aEvent ); } catch (const RuntimeException&) { } } } } void DrawController::FireChangeEditMode (bool bMasterPageMode) throw() { if (bMasterPageMode != mbMasterPageMode ) { FirePropertyChange( PROPERTY_MASTERPAGEMODE, makeAny(bMasterPageMode), makeAny(mbMasterPageMode)); mbMasterPageMode = bMasterPageMode; } } void DrawController::FireChangeLayerMode (bool bLayerMode) throw() { if (bLayerMode != mbLayerMode) { FirePropertyChange( PROPERTY_LAYERMODE, makeAny(bLayerMode), makeAny(mbLayerMode)); mbLayerMode = bLayerMode; } } void DrawController::FireSwitchCurrentPage (SdPage* pNewCurrentPage) throw() { SdrPage* pCurrentPage = mpCurrentPage.get(); if (pNewCurrentPage != pCurrentPage) { try { Any aNewValue ( makeAny(Reference(pNewCurrentPage->getUnoPage(), UNO_QUERY))); Any aOldValue; if (pCurrentPage != NULL) { Reference xOldPage (pCurrentPage->getUnoPage(), UNO_QUERY); aOldValue <<= xOldPage; } FirePropertyChange(PROPERTY_CURRENTPAGE, aNewValue, aOldValue); mpCurrentPage.reset(pNewCurrentPage); } catch (const uno::Exception&) { OSL_FAIL( OString("sd::SdUnoDrawView::FireSwitchCurrentPage(), exception caught: " + OUStringToOString( comphelper::anyToString( cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 )).getStr() ); } } } void DrawController::FirePropertyChange ( sal_Int32 nHandle, const Any& rNewValue, const Any& rOldValue) { try { fire (&nHandle, &rNewValue, &rOldValue, 1, sal_False); } catch (const RuntimeException&) { // Ignore this exception. Exceptions should be handled in the // fire() function so that all listeners are called. This is // not the case at the moment, so we simply ignore the // exception. } } void DrawController::BroadcastContextChange (void) const { ::boost::shared_ptr pViewShell (mpBase->GetMainViewShell()); if ( ! pViewShell) return; EnumContext::Context eContext (EnumContext::Context_Unknown); switch (pViewShell->GetShellType()) { case ViewShell::ST_IMPRESS: case ViewShell::ST_DRAW: if (mbMasterPageMode) eContext = EnumContext::Context_MasterPage; else eContext = EnumContext::Context_DrawPage; break; case ViewShell::ST_NOTES: eContext = EnumContext::Context_NotesPage; break; case ViewShell::ST_HANDOUT: eContext = EnumContext::Context_HandoutPage; break; case ViewShell::ST_OUTLINE: eContext = EnumContext::Context_OutlineText; break; case ViewShell::ST_SLIDE_SORTER: eContext = EnumContext::Context_SlidesorterPage; break; case ViewShell::ST_PRESENTATION: case ViewShell::ST_NONE: default: eContext = EnumContext::Context_Empty; break; } ContextChangeEventMultiplexer::NotifyContextChange(mpBase, eContext); } ViewShellBase* DrawController::GetViewShellBase (void) { return mpBase; } void DrawController::ReleaseViewShellBase (void) { DisposeFrameworkControllers(); mpBase = NULL; } //===== XControllerManager ============================================================== Reference SAL_CALL DrawController::getConfigurationController (void) throw (RuntimeException) { ThrowIfDisposed(); return mxConfigurationController; } Reference SAL_CALL DrawController::getModuleController (void) throw (RuntimeException) { ThrowIfDisposed(); return mxModuleController; } //===== XUnoTunnel ============================================================ namespace { class theDrawControllerUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theDrawControllerUnoTunnelId> {}; } const Sequence& DrawController::getUnoTunnelId (void) { return theDrawControllerUnoTunnelId::get().getSeq(); } sal_Int64 SAL_CALL DrawController::getSomething (const Sequence& rId) throw (RuntimeException) { sal_Int64 nResult = 0; if (rId.getLength() == 16 && memcmp(getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0) { nResult = sal::static_int_cast(reinterpret_cast(this)); } return nResult; } //===== Properties ============================================================ void DrawController::FillPropertyTable ( ::std::vector& rProperties) { rProperties.push_back( beans::Property("VisibleArea", PROPERTY_WORKAREA, ::getCppuType((const ::com::sun::star::awt::Rectangle*)0), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY)); rProperties.push_back( beans::Property( "SubController", PROPERTY_SUB_CONTROLLER, ::getCppuType((const Reference*)0), beans::PropertyAttribute::BOUND)); rProperties.push_back( beans::Property( "CurrentPage", PROPERTY_CURRENTPAGE, ::getCppuType((const Reference< drawing::XDrawPage > *)0), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("IsLayerMode", PROPERTY_LAYERMODE, ::getCppuBooleanType(), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("IsMasterPageMode", PROPERTY_MASTERPAGEMODE, ::getCppuBooleanType(), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("ActiveLayer", PROPERTY_ACTIVE_LAYER, ::getCppuBooleanType(), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("ZoomValue", PROPERTY_ZOOMVALUE, ::getCppuType((const sal_Int16*)0), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("ZoomType", PROPERTY_ZOOMTYPE, ::getCppuType((const sal_Int16*)0), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("ViewOffset", PROPERTY_VIEWOFFSET, ::getCppuType((const ::com::sun::star::awt::Point*)0), beans::PropertyAttribute::BOUND )); rProperties.push_back( beans::Property("DrawViewMode", PROPERTY_DRAWVIEWMODE, ::getCppuType((const ::com::sun::star::awt::Point*)0), beans::PropertyAttribute::BOUND|beans::PropertyAttribute::READONLY|beans::PropertyAttribute::MAYBEVOID )); } IPropertyArrayHelper & DrawController::getInfoHelper() { SolarMutexGuard aGuard; if (mpPropertyArrayHelper.get() == NULL) { ::std::vector aProperties; FillPropertyTable (aProperties); Sequence aPropertySequence (aProperties.size()); for (unsigned int i=0; i DrawController::getPropertySetInfo() throw ( ::com::sun::star::uno::RuntimeException) { SolarMutexGuard aGuard; static Reference < beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); return xInfo; } uno::Reference< form::runtime::XFormController > SAL_CALL DrawController::getFormController( const uno::Reference< form::XForm >& Form ) throw (uno::RuntimeException) { SolarMutexGuard aGuard; FmFormShell* pFormShell = mpBase->GetFormShellManager()->GetFormShell(); SdrView* pSdrView = mpBase->GetDrawView(); ::boost::shared_ptr pViewShell = mpBase->GetMainViewShell(); ::sd::Window* pWindow = pViewShell ? pViewShell->GetActiveWindow() : NULL; uno::Reference< form::runtime::XFormController > xController( NULL ); if ( pFormShell && pSdrView && pWindow ) xController = pFormShell->GetFormController( Form, *pSdrView, *pWindow ); return xController; } ::sal_Bool SAL_CALL DrawController::isFormDesignMode( ) throw (uno::RuntimeException) { SolarMutexGuard aGuard; sal_Bool bIsDesignMode = sal_True; FmFormShell* pFormShell = mpBase->GetFormShellManager()->GetFormShell(); if ( pFormShell ) bIsDesignMode = pFormShell->IsDesignMode(); return bIsDesignMode; } void SAL_CALL DrawController::setFormDesignMode( ::sal_Bool _DesignMode ) throw (uno::RuntimeException) { SolarMutexGuard aGuard; FmFormShell* pFormShell = mpBase->GetFormShellManager()->GetFormShell(); if ( pFormShell ) pFormShell->SetDesignMode( _DesignMode ); } uno::Reference< awt::XControl > SAL_CALL DrawController::getControl( const uno::Reference< awt::XControlModel >& xModel ) throw (container::NoSuchElementException, uno::RuntimeException) { SolarMutexGuard aGuard; FmFormShell* pFormShell = mpBase->GetFormShellManager()->GetFormShell(); SdrView* pSdrView = mpBase->GetDrawView(); ::boost::shared_ptr pViewShell = mpBase->GetMainViewShell(); ::sd::Window* pWindow = pViewShell ? pViewShell->GetActiveWindow() : NULL; uno::Reference< awt::XControl > xControl( NULL ); if ( pFormShell && pSdrView && pWindow ) pFormShell->GetFormControl( xModel, *pSdrView, *pWindow, xControl ); return xControl; } sal_Bool DrawController::convertFastPropertyValue ( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue) throw ( com::sun::star::lang::IllegalArgumentException) { sal_Bool bResult = sal_False; if (nHandle == PROPERTY_SUB_CONTROLLER) { rOldValue <<= mxSubController; rConvertedValue <<= Reference(rValue, UNO_QUERY); bResult = (rOldValue != rConvertedValue); } else if (mxSubController.is()) { rConvertedValue = rValue; try { rOldValue = mxSubController->getFastPropertyValue(nHandle); bResult = (rOldValue != rConvertedValue); } catch (const beans::UnknownPropertyException&) { // The property is unknown and thus an illegal argument to this method. throw com::sun::star::lang::IllegalArgumentException(); } } return bResult; } void DrawController::setFastPropertyValue_NoBroadcast ( sal_Int32 nHandle, const Any& rValue) throw ( com::sun::star::uno::Exception) { SolarMutexGuard aGuard; if (nHandle == PROPERTY_SUB_CONTROLLER) SetSubController(Reference(rValue, UNO_QUERY)); else if (mxSubController.is()) mxSubController->setFastPropertyValue(nHandle, rValue); } void DrawController::getFastPropertyValue ( Any & rRet, sal_Int32 nHandle ) const { SolarMutexGuard aGuard; switch( nHandle ) { case PROPERTY_WORKAREA: rRet <<= awt::Rectangle( maLastVisArea.Left(), maLastVisArea.Top(), maLastVisArea.GetWidth(), maLastVisArea.GetHeight()); break; case PROPERTY_SUB_CONTROLLER: rRet <<= mxSubController; break; default: if (mxSubController.is()) rRet = mxSubController->getFastPropertyValue(nHandle); break; } } //----------------------------------------------------------------------------- void DrawController::ProvideFrameworkControllers (void) { SolarMutexGuard aGuard; try { Reference xController (this); const Reference xContext ( ::comphelper::getProcessComponentContext() ); mxConfigurationController = ConfigurationController::create( xContext, xController); mxModuleController = ModuleController::create( xContext, xController); } catch (const RuntimeException&) { mxConfigurationController = NULL; mxModuleController = NULL; } } void DrawController::DisposeFrameworkControllers (void) { Reference xComponent (mxModuleController, UNO_QUERY); if (xComponent.is()) xComponent->dispose(); xComponent = Reference(mxConfigurationController, UNO_QUERY); if (xComponent.is()) xComponent->dispose(); } void DrawController::ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose || mbDisposing) { OSL_TRACE ("Calling disposed DrawController object. Throwing exception:"); throw lang::DisposedException ( "DrawController object has already been disposed", const_cast(static_cast(this))); } } } // end of namespace sd /* vim:set shiftwidth=4 softtabstop=4 expandtab: */