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 "ConfigurationControllerBroadcaster.hxx" 31 #include <com/sun/star/lang/IllegalArgumentException.hpp> 32 #include <com/sun/star/lang/DisposedException.hpp> 33 #include <tools/debug.hxx> 34 #include <tools/diagnose_ex.h> 35 36 using namespace ::com::sun::star; 37 using namespace ::com::sun::star::uno; 38 using namespace ::com::sun::star::drawing::framework; 39 using rtl::OUString; 40 41 namespace sd { namespace framework { 42 43 ConfigurationControllerBroadcaster::ConfigurationControllerBroadcaster ( 44 const Reference<XConfigurationController>& rxController) 45 : mxConfigurationController(rxController), 46 maListenerMap() 47 { 48 } 49 50 51 52 53 void ConfigurationControllerBroadcaster::AddListener( 54 const Reference<XConfigurationChangeListener>& rxListener, 55 const ::rtl::OUString& rsEventType, 56 const Any& rUserData) 57 { 58 if ( ! rxListener.is()) 59 throw lang::IllegalArgumentException( 60 OUString::createFromAscii("invalid listener"), 61 mxConfigurationController, 62 0); 63 64 if (maListenerMap.find(rsEventType) == maListenerMap.end()) 65 maListenerMap[rsEventType] = ListenerList(); 66 ListenerDescriptor aDescriptor; 67 aDescriptor.mxListener = rxListener; 68 aDescriptor.maUserData = rUserData; 69 maListenerMap[rsEventType].push_back(aDescriptor); 70 } 71 72 73 74 75 void ConfigurationControllerBroadcaster::RemoveListener( 76 const Reference<XConfigurationChangeListener>& rxListener) 77 { 78 if ( ! rxListener.is()) 79 throw lang::IllegalArgumentException( 80 OUString::createFromAscii("invalid listener"), 81 mxConfigurationController, 82 0); 83 84 ListenerMap::iterator iMap; 85 ListenerList::iterator iList; 86 for (iMap=maListenerMap.begin(); iMap!=maListenerMap.end(); ++iMap) 87 { 88 for (iList=iMap->second.begin(); iList!=iMap->second.end(); ++iList) 89 { 90 if (iList->mxListener == rxListener) 91 { 92 iMap->second.erase(iList); 93 break; 94 } 95 } 96 } 97 } 98 99 100 101 102 void ConfigurationControllerBroadcaster::NotifyListeners ( 103 const ListenerList& rList, 104 const ConfigurationChangeEvent& rEvent) 105 { 106 // Create a local copy of the event in which the user data is modified 107 // for every listener. 108 ConfigurationChangeEvent aEvent (rEvent); 109 110 ListenerList::const_iterator iListener; 111 for (iListener=rList.begin(); iListener!=rList.end(); ++iListener) 112 { 113 try 114 { 115 aEvent.UserData = iListener->maUserData; 116 iListener->mxListener->notifyConfigurationChange(aEvent); 117 } 118 catch (lang::DisposedException& rException) 119 { 120 // When the exception comes from the listener itself then 121 // unregister it. 122 if (rException.Context == iListener->mxListener) 123 RemoveListener(iListener->mxListener); 124 } 125 catch(RuntimeException&) 126 { 127 DBG_UNHANDLED_EXCEPTION(); 128 } 129 } 130 } 131 132 133 134 135 void ConfigurationControllerBroadcaster::NotifyListeners (const ConfigurationChangeEvent& rEvent) 136 { 137 // Notify the specialized listeners. 138 ListenerMap::const_iterator iMap (maListenerMap.find(rEvent.Type)); 139 if (iMap != maListenerMap.end()) 140 { 141 // Create a local list of the listeners to avoid problems with 142 // concurrent changes and to be able to remove disposed listeners. 143 ListenerList aList (iMap->second.begin(), iMap->second.end()); 144 NotifyListeners(aList,rEvent); 145 } 146 147 // Notify the universal listeners. 148 iMap = maListenerMap.find(OUString()); 149 if (iMap != maListenerMap.end()) 150 { 151 // Create a local list of the listeners to avoid problems with 152 // concurrent changes and to be able to remove disposed listeners. 153 ListenerList aList (iMap->second.begin(), iMap->second.end()); 154 NotifyListeners(aList,rEvent); 155 } 156 } 157 158 159 160 161 void ConfigurationControllerBroadcaster::NotifyListeners ( 162 const OUString& rsEventType, 163 const Reference<XResourceId>& rxResourceId, 164 const Reference<XResource>& rxResourceObject) 165 { 166 ConfigurationChangeEvent aEvent; 167 aEvent.Type = rsEventType; 168 aEvent.ResourceId = rxResourceId; 169 aEvent.ResourceObject = rxResourceObject; 170 try 171 { 172 NotifyListeners(aEvent); 173 } 174 catch (lang::DisposedException) 175 { 176 } 177 } 178 179 180 181 182 183 void ConfigurationControllerBroadcaster::DisposeAndClear (void) 184 { 185 lang::EventObject aEvent; 186 aEvent.Source = mxConfigurationController; 187 while (!maListenerMap.empty()) 188 { 189 ListenerMap::iterator iMap (maListenerMap.begin()); 190 if (iMap == maListenerMap.end()) 191 break; 192 193 // When the first vector is empty then remove it from the map. 194 if (iMap->second.empty()) 195 { 196 maListenerMap.erase(iMap); 197 continue; 198 } 199 else 200 { 201 Reference<lang::XEventListener> xListener ( 202 iMap->second.front().mxListener, UNO_QUERY); 203 if (xListener.is()) 204 { 205 // Tell the listener that the configuration controller is 206 // being disposed and remove the listener (for all event 207 // types). 208 try 209 { 210 RemoveListener(iMap->second.front().mxListener); 211 xListener->disposing(aEvent); 212 } 213 catch (RuntimeException&) 214 { 215 DBG_UNHANDLED_EXCEPTION(); 216 } 217 } 218 else 219 { 220 // Remove just this reference to the listener. 221 iMap->second.erase(iMap->second.begin()); 222 } 223 } 224 } 225 } 226 227 228 229 230 } } // end of namespace sd::framework 231 232