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