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 cssu::Reference<cssu::XInterface> xThis (static_cast<XWeak*>(this)); 62 css::lang::EventObject aEvent (xThis); 63 for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end()); 64 iContainer!=iEnd; 65 ++iContainer) 66 { 67 for (ListenerContainer::const_iterator 68 iListener(iContainer->second.maListeners.begin()), 69 iContainerEnd(iContainer->second.maListeners.end()); 70 iListener!=iContainerEnd; 71 ++iListener) 72 { 73 (*iListener)->disposing(aEvent); 74 } 75 } 76 } 77 78 79 80 81 // XContextChangeEventMultiplexer 82 83 void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener ( 84 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener, 85 const cssu::Reference<cssu::XInterface>& rxEventFocus) 86 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 87 { 88 if ( ! rxListener.is()) 89 throw css::lang::IllegalArgumentException( 90 A2S("can not add an empty reference"), 91 static_cast<XWeak*>(this), 92 0); 93 94 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus)); 95 if (iDescriptor == maListeners.end()) 96 { 97 // Create a new listener container for the event focus. 98 iDescriptor = maListeners.insert( 99 ListenerMap::value_type( 100 rxEventFocus, 101 FocusDescriptor())).first; 102 } 103 if (iDescriptor != maListeners.end()) 104 { 105 ListenerContainer& rContainer (iDescriptor->second.maListeners); 106 if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end()) 107 rContainer.push_back(rxListener); 108 else 109 { 110 // The listener was added for the same event focus 111 // previously. That is an error. 112 throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0); 113 } 114 } 115 116 // Send out an initial event that informs the new listener about 117 // the current context. 118 if (rxEventFocus.is() && iDescriptor != maListeners.end()) 119 { 120 css::ui::ContextChangeEventObject aEvent ( 121 NULL, 122 iDescriptor->second.msCurrentApplicationName, 123 iDescriptor->second.msCurrentContextName); 124 rxListener->notifyContextChangeEvent(aEvent); 125 } 126 } 127 128 129 130 131 void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener ( 132 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener, 133 const cssu::Reference<cssu::XInterface>& rxEventFocus) 134 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 135 { 136 if ( ! rxListener.is()) 137 throw cssl::IllegalArgumentException( 138 A2S("can not remove an empty reference"), 139 static_cast<XWeak*>(this), 0); 140 141 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus)); 142 if (iDescriptor != maListeners.end()) 143 { 144 ListenerContainer& rContainer (iDescriptor->second.maListeners); 145 const ListenerContainer::iterator iListener ( 146 ::std::find(rContainer.begin(), rContainer.end(), rxListener)); 147 if (iListener != rContainer.end()) 148 { 149 rContainer.erase(iListener); 150 151 // Remove the listener container as well when its last 152 // listener was just removed. This prevents us from 153 // holding the focus alive. 154 if (rContainer.empty()) 155 maListeners.erase(iDescriptor); 156 } 157 } 158 159 } 160 161 162 163 164 void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners ( 165 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener) 166 throw(cssu::RuntimeException,cssl::IllegalArgumentException) 167 { 168 if ( ! rxListener.is()) 169 throw cssl::IllegalArgumentException( 170 A2S("can not remove an empty reference"), 171 static_cast<XWeak*>(this), 0); 172 173 ::std::vector<cssu::Reference<cssu::XInterface> > aContainersToRemove; 174 for (ListenerMap::iterator 175 iContainer(maListeners.begin()), 176 iEnd(maListeners.end()); 177 iContainer!=iEnd; 178 ++iContainer) 179 { 180 const ListenerContainer::iterator iListener ( 181 ::std::find(iContainer->second.maListeners.begin(), iContainer->second.maListeners.end(), rxListener)); 182 if (iListener != iContainer->second.maListeners.end()) 183 { 184 iContainer->second.maListeners.erase(iListener); 185 186 // When we just removed the last listener then mark the 187 // container as to be removed. 188 if (iContainer->second.maListeners.empty()) 189 aContainersToRemove.push_back(iContainer->first); 190 } 191 } 192 193 for (::std::vector<cssu::Reference<cssu::XInterface> >::iterator 194 iFocus(aContainersToRemove.begin()), 195 iEnd(aContainersToRemove.end()); 196 iFocus!=iEnd; 197 ++iFocus) 198 { 199 maListeners.erase(*iFocus); 200 } 201 } 202 203 204 205 206 void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent ( 207 const css::ui::ContextChangeEventObject& rEventObject, 208 const cssu::Reference<cssu::XInterface>& rxEventFocus) 209 throw(cssu::RuntimeException) 210 { 211 // Remember the current context. 212 if (rxEventFocus.is()) 213 { 214 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus)); 215 if (iDescriptor != maListeners.end()) 216 { 217 iDescriptor->second.msCurrentApplicationName = rEventObject.ApplicationName; 218 iDescriptor->second.msCurrentContextName = rEventObject.ContextName; 219 } 220 } 221 222 BroadcastEventToSingleContainer(rEventObject, rxEventFocus); 223 if (rxEventFocus.is()) 224 BroadcastEventToSingleContainer(rEventObject, NULL); 225 } 226 227 228 229 230 void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer ( 231 const css::ui::ContextChangeEventObject& rEventObject, 232 const cssu::Reference<cssu::XInterface>& rxEventFocus) 233 { 234 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus)); 235 if (iDescriptor != maListeners.end()) 236 { 237 // Create a copy of the listener container to avoid problems 238 // when one of the called listeners calls add... or remove... 239 ListenerContainer aContainer (iDescriptor->second.maListeners); 240 for (ListenerContainer::const_iterator 241 iListener(aContainer.begin()), 242 iEnd(aContainer.end()); 243 iListener!=iEnd; 244 ++iListener) 245 { 246 (*iListener)->notifyContextChangeEvent(rEventObject); 247 } 248 } 249 } 250 251 252 253 254 // XSingleComponentFactory 255 256 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext ( 257 const cssu::Reference<cssu::XComponentContext>& rxContext) 258 throw (cssu::Exception, cssu::RuntimeException) 259 { 260 (void)rxContext; 261 return cssu::Reference<cssu::XInterface>(); 262 } 263 264 265 266 267 cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext ( 268 const cssu::Sequence<cssu::Any>& rArguments, 269 const cssu::Reference<cssu::XComponentContext>& rxContext) 270 throw (cssu::Exception, cssu::RuntimeException) 271 { 272 (void)rArguments; 273 (void)rxContext; 274 return cssu::Reference<cssu::XInterface>(); 275 } 276 277 278 279 280 // XServiceInfo 281 282 ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void) 283 throw(cssu::RuntimeException) 284 { 285 return impl_getStaticImplementationName(); 286 } 287 288 289 290 291 292 sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService ( 293 const ::rtl::OUString& rsServiceName) 294 throw (cssu::RuntimeException) 295 { 296 return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0; 297 } 298 299 300 301 302 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void) 303 throw (cssu::RuntimeException) 304 { 305 return static_GetSupportedServiceNames(); 306 } 307 308 309 310 311 // Local and static methods. 312 313 OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void) 314 { 315 return A2S(IMPLEMENTATION_NAME); 316 } 317 318 319 320 321 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void) 322 { 323 cssu::Sequence<OUString> aServiceNames (2); 324 aServiceNames[0] = A2S(SERVICE_NAME); 325 aServiceNames[1] = A2S(SINGLETON_NAME); 326 return aServiceNames; 327 } 328 329 330 331 332 cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory ( 333 const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager) 334 { 335 (void)rxServiceManager; 336 return cppu::createSingleComponentFactory( 337 ContextChangeEventMultiplexer::static_CreateInstance, 338 ContextChangeEventMultiplexer::impl_getStaticImplementationName(), 339 ContextChangeEventMultiplexer::static_GetSupportedServiceNames() 340 ); 341 } 342 343 344 345 346 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance ( 347 const cssu::Reference<cssu::XComponentContext>& rxComponentContext) 348 throw (cssu::Exception) 349 { 350 ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext); 351 cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY); 352 return xService; 353 } 354 355 } // end of namespace framework 356