xref: /AOO41X/main/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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