1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_sd.hxx" 29 30 #include "ReadOnlyModeObserver.hxx" 31 32 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 33 #include <com/sun/star/lang/DisposedException.hpp> 34 #include <com/sun/star/util/XURLTransformer.hpp> 35 #include <comphelper/processfactory.hxx> 36 #include <cppuhelper/interfacecontainer.hxx> 37 38 #include "tools/SlotStateListener.hxx" 39 #include "framework/FrameworkHelper.hxx" 40 41 using namespace ::com::sun::star::uno; 42 using namespace ::com::sun::star; 43 using namespace ::com::sun::star::drawing::framework; 44 using ::rtl::OUString; 45 46 namespace sd { namespace framework { 47 48 class ReadOnlyModeObserver::ModifyBroadcaster 49 : public ::cppu::OBroadcastHelper 50 { 51 public: 52 explicit ModifyBroadcaster (::osl::Mutex& rOslMutex) : ::cppu::OBroadcastHelper(rOslMutex) {} 53 }; 54 55 56 57 58 ReadOnlyModeObserver::ReadOnlyModeObserver ( 59 const Reference<frame::XController>& rxController) 60 : ReadOnlyModeObserverInterfaceBase(maMutex), 61 maSlotNameURL(), 62 mxController(rxController), 63 mxConfigurationController(NULL), 64 mxDispatch(NULL), 65 mpBroadcaster(new ModifyBroadcaster(maMutex)) 66 { 67 // Create a URL object for the slot name. 68 maSlotNameURL.Complete = OUString::createFromAscii(".uno:EditDoc"); 69 uno::Reference<lang::XMultiServiceFactory> xServiceManager ( 70 ::comphelper::getProcessServiceFactory()); 71 if (xServiceManager.is()) 72 { 73 Reference<util::XURLTransformer> xTransformer(xServiceManager->createInstance( 74 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), 75 UNO_QUERY); 76 if (xTransformer.is()) 77 xTransformer->parseStrict(maSlotNameURL); 78 } 79 80 if ( ! ConnectToDispatch()) 81 { 82 // The controller is not yet connected to a frame. This means that 83 // the dispatcher is not yet set up. We wait for this to happen by 84 // waiting for configuration updates and try again. 85 Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY); 86 if (xControllerManager.is()) 87 { 88 mxConfigurationController = xControllerManager->getConfigurationController(); 89 if (mxConfigurationController.is()) 90 { 91 mxConfigurationController->addConfigurationChangeListener( 92 this, 93 FrameworkHelper::msConfigurationUpdateStartEvent, 94 Any()); 95 } 96 } 97 } 98 } 99 100 101 102 103 ReadOnlyModeObserver::~ReadOnlyModeObserver (void) 104 { 105 } 106 107 108 109 110 void SAL_CALL ReadOnlyModeObserver::disposing (void) 111 { 112 if (mxController.is()) 113 { 114 mxController = NULL; 115 } 116 if (mxConfigurationController.is()) 117 { 118 mxConfigurationController->removeConfigurationChangeListener(this); 119 mxConfigurationController = NULL; 120 } 121 if (mxDispatch.is()) 122 { 123 mxDispatch->removeStatusListener(this, maSlotNameURL); 124 mxDispatch = NULL; 125 } 126 127 lang::EventObject aEvent; 128 aEvent.Source = static_cast<XWeak*>(this); 129 ::cppu::OInterfaceContainerHelper* pIterator 130 = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL)); 131 pIterator->disposeAndClear(aEvent); 132 } 133 134 135 136 137 void ReadOnlyModeObserver::AddStatusListener ( 138 const Reference<frame::XStatusListener>& rxListener) 139 { 140 mpBroadcaster->addListener( 141 getCppuType((Reference<frame::XStatusListener>*)NULL), 142 rxListener); 143 } 144 145 146 147 148 bool ReadOnlyModeObserver::ConnectToDispatch (void) 149 { 150 if ( ! mxDispatch.is()) 151 { 152 // Get the dispatch object. 153 Reference<frame::XDispatchProvider> xProvider (mxController->getFrame(), UNO_QUERY); 154 if (xProvider.is()) 155 { 156 mxDispatch = xProvider->queryDispatch(maSlotNameURL, OUString(), 0); 157 if (mxDispatch.is()) 158 { 159 mxDispatch->addStatusListener(this, maSlotNameURL); 160 } 161 } 162 } 163 164 return mxDispatch.is(); 165 } 166 167 168 169 170 void ReadOnlyModeObserver::statusChanged (const frame::FeatureStateEvent& rEvent) 171 throw (RuntimeException) 172 { 173 ::cppu::OInterfaceContainerHelper* pIterator 174 = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL)); 175 if (pIterator != NULL) 176 { 177 pIterator->notifyEach(&frame::XStatusListener::statusChanged, rEvent); 178 } 179 } 180 181 182 183 184 //----- XEventListener -------------------------------------------------------- 185 186 void SAL_CALL ReadOnlyModeObserver::disposing ( 187 const lang::EventObject& rEvent) 188 throw (RuntimeException) 189 { 190 if (rEvent.Source == mxConfigurationController) 191 mxConfigurationController = NULL; 192 else if (rEvent.Source == mxDispatch) 193 mxDispatch = NULL; 194 195 dispose(); 196 } 197 198 199 200 201 void SAL_CALL ReadOnlyModeObserver::notifyConfigurationChange ( 202 const ConfigurationChangeEvent& rEvent) 203 throw (RuntimeException) 204 { 205 if (rEvent.Type.equals(FrameworkHelper::msConfigurationUpdateStartEvent)) 206 { 207 if (mxController.is() && mxController->getFrame().is()) 208 { 209 if (ConnectToDispatch()) 210 { 211 // We have connected successfully to the dispatcher and 212 // therefore can disconnect from the configuration controller. 213 mxConfigurationController->removeConfigurationChangeListener(this); 214 mxConfigurationController = NULL; 215 } 216 } 217 } 218 } 219 220 } } // end of namespace sd::framework 221