1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 #include "precompiled_framework.hxx" 23 24 #include "services/ContextChangeEventMultiplexer.hxx" 25 #include "services.h" 26 27 using ::rtl::OUString; 28 29 #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 30 31 namespace framework { 32 33 #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer" 34 #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer" 35 #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton" 36 37 38 ContextChangeEventMultiplexer::ContextChangeEventMultiplexer ( 39 const cssu::Reference<cssu::XComponentContext>& rxContext) 40 : ContextChangeEventMultiplexerInterfaceBase(m_aMutex), 41 maListeners() 42 { 43 (void)rxContext; 44 } 45 46 47 48 49 ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void) 50 { 51 } 52 53 54 55 56 void SAL_CALL ContextChangeEventMultiplexer::disposing (void) 57 { 58 ListenerMap aListeners; 59 aListeners.swap(maListeners); 60 61 css::lang::EventObject aEvent (cssu::Reference<cssu::XInterface>(static_cast<XWeak*>(this))); 62 for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end()); 63 iContainer!=iEnd; 64 ++iContainer) 65 { 66 for (ListenerContainer::const_iterator 67 iListener(iContainer->second.begin()), 68 iContainerEnd(iContainer->second.end()); 69 iListener!=iContainerEnd; 70 ++iListener) 71 { 72 (*iListener)->disposing(aEvent); 73 } 74 } 75 } 76 77 78 79 80 // XContextChangeEventMultiplexer 81 82 void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener ( 83 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener, 84 const cssu::Reference<cssu::XInterface>& rxEventFocus) 85 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 86 { 87 if ( ! rxListener.is()) 88 throw css::lang::IllegalArgumentException( 89 A2S("can not add an empty reference"), 90 static_cast<XWeak*>(this), 91 0); 92 93 ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus)); 94 if (iListenerContainer == maListeners.end()) 95 { 96 // Create a new listener container for the event focus. 97 iListenerContainer = maListeners.insert( 98 ListenerMap::value_type( 99 rxEventFocus, 100 ListenerContainer())).first; 101 } 102 if (iListenerContainer != maListeners.end()) 103 { 104 ListenerContainer& rContainer (iListenerContainer->second); 105 if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end()) 106 rContainer.push_back(rxListener); 107 else 108 { 109 // The listener was added for the same event focus 110 // previously. That is an error. 111 throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0); 112 } 113 } 114 } 115 116 117 118 119 void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener ( 120 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener, 121 const cssu::Reference<cssu::XInterface>& rxEventFocus) 122 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 123 { 124 if ( ! rxListener.is()) 125 throw cssl::IllegalArgumentException(A2S("can not remove an empty reference"), static_cast<XWeak*>(this), 0); 126 127 ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus)); 128 if (iListenerContainer != maListeners.end()) 129 { 130 ListenerContainer& rContainer (iListenerContainer->second); 131 const ListenerContainer::iterator iListener (::std::find(rContainer.begin(), rContainer.end(), rxListener)); 132 if (iListener != rContainer.end()) 133 { 134 rContainer.erase(iListener); 135 136 // Remove the listener container as well when its last 137 // listener was just removed. This prevents us from 138 // holding the focus alive. 139 if (rContainer.empty()) 140 maListeners.erase(iListenerContainer); 141 } 142 } 143 144 } 145 146 147 148 149 void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners ( 150 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener) 151 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 152 { 153 if ( ! rxListener.is()) 154 throw cssl::IllegalArgumentException(A2S("can not remove an empty reference"), static_cast<XWeak*>(this), 0); 155 156 ::std::vector<cssu::Reference<cssu::XInterface> > aContainersToRemove; 157 for (ListenerMap::iterator 158 iContainer(maListeners.begin()), 159 iEnd(maListeners.end()); 160 iContainer!=iEnd; 161 ++iContainer) 162 { 163 const ListenerContainer::iterator iListener (::std::find(iContainer->second.begin(), iContainer->second.end(), rxListener)); 164 if (iListener != iContainer->second.end()) 165 { 166 iContainer->second.erase(iListener); 167 168 // When we just removed the last listener then mark the 169 // container as to be removed. 170 if (iContainer->second.empty()) 171 aContainersToRemove.push_back(iContainer->first); 172 } 173 } 174 175 for (::std::vector<cssu::Reference<cssu::XInterface> >::iterator 176 iFocus(aContainersToRemove.begin()), 177 iEnd(aContainersToRemove.end()); 178 iFocus!=iEnd; 179 ++iFocus) 180 { 181 maListeners.erase(*iFocus); 182 } 183 } 184 185 186 187 188 189 void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent ( 190 const css::ui::ContextChangeEventObject& rEventObject, 191 const cssu::Reference<cssu::XInterface>& rxEventFocus) 192 throw(cssu::RuntimeException) 193 { 194 BroadcastEventToSingleContainer(rEventObject, rxEventFocus); 195 if (rxEventFocus.is()) 196 BroadcastEventToSingleContainer(rEventObject, NULL); 197 } 198 199 200 201 202 void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer ( 203 const css::ui::ContextChangeEventObject& rEventObject, 204 const cssu::Reference<cssu::XInterface>& rxEventFocus) 205 { 206 ListenerMap::iterator iListenerContainer (maListeners.find(rxEventFocus)); 207 if (iListenerContainer != maListeners.end()) 208 { 209 // Create a copy of the listener container to avoid problems 210 // when one of the called listeners calls add... or remove... 211 ListenerContainer aContainer (iListenerContainer->second); 212 for (ListenerContainer::const_iterator 213 iListener(aContainer.begin()), 214 iEnd(aContainer.end()); 215 iListener!=iEnd; 216 ++iListener) 217 { 218 (*iListener)->notifyContextChangeEvent(rEventObject); 219 } 220 } 221 } 222 223 224 225 226 // XSingleComponentFactory 227 228 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext ( 229 const cssu::Reference<cssu::XComponentContext>& rxContext) 230 throw (cssu::Exception, cssu::RuntimeException) 231 { 232 (void)rxContext; 233 return cssu::Reference<cssu::XInterface>(); 234 } 235 236 237 238 239 cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext ( 240 const cssu::Sequence<cssu::Any>& rArguments, 241 const cssu::Reference<cssu::XComponentContext>& rxContext) 242 throw (cssu::Exception, cssu::RuntimeException) 243 { 244 (void)rArguments; 245 (void)rxContext; 246 return cssu::Reference<cssu::XInterface>(); 247 } 248 249 250 251 252 // XServiceInfo 253 254 ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void) 255 throw(cssu::RuntimeException) 256 { 257 return impl_getStaticImplementationName(); 258 } 259 260 261 262 263 264 sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService ( 265 const ::rtl::OUString& rsServiceName) 266 throw (cssu::RuntimeException) 267 { 268 return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0; 269 } 270 271 272 273 274 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void) 275 throw (cssu::RuntimeException) 276 { 277 return static_GetSupportedServiceNames(); 278 } 279 280 281 282 283 // Local and static methods. 284 285 OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void) 286 { 287 return A2S(IMPLEMENTATION_NAME); 288 } 289 290 291 292 293 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void) 294 { 295 cssu::Sequence<OUString> aServiceNames (2); 296 aServiceNames[0] = A2S(SERVICE_NAME); 297 aServiceNames[1] = A2S(SINGLETON_NAME); 298 return aServiceNames; 299 } 300 301 302 303 304 cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory ( 305 const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager) 306 { 307 (void)rxServiceManager; 308 return cppu::createSingleComponentFactory( 309 ContextChangeEventMultiplexer::static_CreateInstance, 310 ContextChangeEventMultiplexer::impl_getStaticImplementationName(), 311 ContextChangeEventMultiplexer::static_GetSupportedServiceNames() 312 ); 313 } 314 315 316 317 318 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance ( 319 const cssu::Reference<cssu::XComponentContext>& rxComponentContext) 320 throw (cssu::Exception) 321 { 322 ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext); 323 cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY); 324 return xService; 325 } 326 327 } // end of namespace framework 328