122de8995SAndre Fischer /**************************************************************
222de8995SAndre Fischer  *
322de8995SAndre Fischer  * Licensed to the Apache Software Foundation (ASF) under one
422de8995SAndre Fischer  * or more contributor license agreements.  See the NOTICE file
522de8995SAndre Fischer  * distributed with this work for additional information
622de8995SAndre Fischer  * regarding copyright ownership.  The ASF licenses this file
722de8995SAndre Fischer  * to you under the Apache License, Version 2.0 (the
822de8995SAndre Fischer  * "License"); you may not use this file except in compliance
922de8995SAndre Fischer  * with the License.  You may obtain a copy of the License at
1022de8995SAndre Fischer  *
1122de8995SAndre Fischer  *   http://www.apache.org/licenses/LICENSE-2.0
1222de8995SAndre Fischer  *
1322de8995SAndre Fischer  * Unless required by applicable law or agreed to in writing,
1422de8995SAndre Fischer  * software distributed under the License is distributed on an
1522de8995SAndre Fischer  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1622de8995SAndre Fischer  * KIND, either express or implied.  See the License for the
1722de8995SAndre Fischer  * specific language governing permissions and limitations
1822de8995SAndre Fischer  * under the License.
1922de8995SAndre Fischer  *
2022de8995SAndre Fischer  *************************************************************/
2122de8995SAndre Fischer 
2222de8995SAndre Fischer #include "precompiled_framework.hxx"
2322de8995SAndre Fischer 
2422de8995SAndre Fischer #include "services/ContextChangeEventMultiplexer.hxx"
2522de8995SAndre Fischer #include "services.h"
2622de8995SAndre Fischer 
2722de8995SAndre Fischer using ::rtl::OUString;
2822de8995SAndre Fischer 
2922de8995SAndre Fischer #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
3022de8995SAndre Fischer 
3122de8995SAndre Fischer namespace framework {
3222de8995SAndre Fischer 
3322de8995SAndre Fischer #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer"
3422de8995SAndre Fischer #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer"
3522de8995SAndre Fischer #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton"
3622de8995SAndre Fischer 
3722de8995SAndre Fischer 
3822de8995SAndre Fischer ContextChangeEventMultiplexer::ContextChangeEventMultiplexer (
39b9e67834SAndre Fischer     const cssu::Reference<cssu::XComponentContext>& rxContext)
4022de8995SAndre Fischer     : ContextChangeEventMultiplexerInterfaceBase(m_aMutex),
4122de8995SAndre Fischer       maListeners()
4222de8995SAndre Fischer {
4322de8995SAndre Fischer     (void)rxContext;
4422de8995SAndre Fischer }
4522de8995SAndre Fischer 
4622de8995SAndre Fischer 
4722de8995SAndre Fischer 
4822de8995SAndre Fischer 
4922de8995SAndre Fischer ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void)
5022de8995SAndre Fischer {
51b9e67834SAndre Fischer }
52b9e67834SAndre Fischer 
53b9e67834SAndre Fischer 
54b9e67834SAndre Fischer 
55b9e67834SAndre Fischer 
56b9e67834SAndre Fischer void SAL_CALL ContextChangeEventMultiplexer::disposing (void)
57b9e67834SAndre Fischer {
58b9e67834SAndre Fischer     ListenerMap aListeners;
59b9e67834SAndre Fischer     aListeners.swap(maListeners);
60b9e67834SAndre Fischer 
61*95a18594SAndre Fischer     cssu::Reference<cssu::XInterface> xThis (static_cast<XWeak*>(this));
62*95a18594SAndre Fischer     css::lang::EventObject aEvent (xThis);
63b9e67834SAndre Fischer     for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end());
64b9e67834SAndre Fischer          iContainer!=iEnd;
65b9e67834SAndre Fischer          ++iContainer)
66b9e67834SAndre Fischer     {
67b9e67834SAndre Fischer         for (ListenerContainer::const_iterator
68*95a18594SAndre Fischer                  iListener(iContainer->second.maListeners.begin()),
69*95a18594SAndre Fischer                  iContainerEnd(iContainer->second.maListeners.end());
70b9e67834SAndre Fischer              iListener!=iContainerEnd;
71b9e67834SAndre Fischer              ++iListener)
72b9e67834SAndre Fischer         {
73b9e67834SAndre Fischer             (*iListener)->disposing(aEvent);
74b9e67834SAndre Fischer         }
75b9e67834SAndre Fischer     }
7622de8995SAndre Fischer }
7722de8995SAndre Fischer 
7822de8995SAndre Fischer 
7922de8995SAndre Fischer 
8022de8995SAndre Fischer 
8122de8995SAndre Fischer // XContextChangeEventMultiplexer
8222de8995SAndre Fischer 
8322de8995SAndre Fischer void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
8422de8995SAndre Fischer     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
8522de8995SAndre Fischer     const cssu::Reference<cssu::XInterface>& rxEventFocus)
8622de8995SAndre Fischer     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
8722de8995SAndre Fischer {
8822de8995SAndre Fischer     if ( ! rxListener.is())
8922de8995SAndre Fischer         throw css::lang::IllegalArgumentException(
9022de8995SAndre Fischer             A2S("can not add an empty reference"),
9122de8995SAndre Fischer             static_cast<XWeak*>(this),
9222de8995SAndre Fischer             0);
9322de8995SAndre Fischer 
94*95a18594SAndre Fischer     ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
95*95a18594SAndre Fischer     if (iDescriptor == maListeners.end())
9622de8995SAndre Fischer     {
9722de8995SAndre Fischer         // Create a new listener container for the event focus.
98*95a18594SAndre Fischer         iDescriptor = maListeners.insert(
9922de8995SAndre Fischer             ListenerMap::value_type(
10022de8995SAndre Fischer                 rxEventFocus,
101*95a18594SAndre Fischer                 FocusDescriptor())).first;
10222de8995SAndre Fischer     }
103*95a18594SAndre Fischer     if (iDescriptor != maListeners.end())
10422de8995SAndre Fischer     {
105*95a18594SAndre Fischer         ListenerContainer& rContainer (iDescriptor->second.maListeners);
10622de8995SAndre Fischer         if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end())
10722de8995SAndre Fischer             rContainer.push_back(rxListener);
10822de8995SAndre Fischer         else
10922de8995SAndre Fischer         {
11022de8995SAndre Fischer             // The listener was added for the same event focus
11122de8995SAndre Fischer             // previously.  That is an error.
11222de8995SAndre Fischer             throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0);
11322de8995SAndre Fischer         }
11422de8995SAndre Fischer     }
115*95a18594SAndre Fischer 
116*95a18594SAndre Fischer     // Send out an initial event that informs the new listener about
117*95a18594SAndre Fischer     // the current context.
118*95a18594SAndre Fischer     if (rxEventFocus.is() && iDescriptor != maListeners.end())
119*95a18594SAndre Fischer     {
120*95a18594SAndre Fischer         css::ui::ContextChangeEventObject aEvent (
121*95a18594SAndre Fischer             NULL,
122*95a18594SAndre Fischer             iDescriptor->second.msCurrentApplicationName,
123*95a18594SAndre Fischer             iDescriptor->second.msCurrentContextName);
124*95a18594SAndre Fischer         rxListener->notifyContextChangeEvent(aEvent);
125*95a18594SAndre Fischer     }
12622de8995SAndre Fischer }
12722de8995SAndre Fischer 
12822de8995SAndre Fischer 
12922de8995SAndre Fischer 
13022de8995SAndre Fischer 
13122de8995SAndre Fischer void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
13222de8995SAndre Fischer     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
13322de8995SAndre Fischer     const cssu::Reference<cssu::XInterface>& rxEventFocus)
13422de8995SAndre Fischer     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
13522de8995SAndre Fischer {
13622de8995SAndre Fischer     if ( ! rxListener.is())
137*95a18594SAndre Fischer         throw cssl::IllegalArgumentException(
138*95a18594SAndre Fischer             A2S("can not remove an empty reference"),
139*95a18594SAndre Fischer             static_cast<XWeak*>(this), 0);
14022de8995SAndre Fischer 
141*95a18594SAndre Fischer     ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
142*95a18594SAndre Fischer     if (iDescriptor != maListeners.end())
14322de8995SAndre Fischer     {
144*95a18594SAndre Fischer         ListenerContainer& rContainer (iDescriptor->second.maListeners);
145*95a18594SAndre Fischer         const ListenerContainer::iterator iListener (
146*95a18594SAndre Fischer             ::std::find(rContainer.begin(), rContainer.end(), rxListener));
14722de8995SAndre Fischer         if (iListener != rContainer.end())
148b9e67834SAndre Fischer         {
14922de8995SAndre Fischer             rContainer.erase(iListener);
150b9e67834SAndre Fischer 
151b9e67834SAndre Fischer             // Remove the listener container as well when its last
152b9e67834SAndre Fischer             // listener was just removed.  This prevents us from
153b9e67834SAndre Fischer             // holding the focus alive.
154b9e67834SAndre Fischer             if (rContainer.empty())
155*95a18594SAndre Fischer                 maListeners.erase(iDescriptor);
156b9e67834SAndre Fischer         }
15722de8995SAndre Fischer     }
15822de8995SAndre Fischer 
15922de8995SAndre Fischer }
16022de8995SAndre Fischer 
16122de8995SAndre Fischer 
16222de8995SAndre Fischer 
16322de8995SAndre Fischer 
16422de8995SAndre Fischer void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
16522de8995SAndre Fischer     const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener)
16622de8995SAndre Fischer     throw(cssu::RuntimeException,cssl::IllegalArgumentException)
16722de8995SAndre Fischer {
16822de8995SAndre Fischer     if ( ! rxListener.is())
169*95a18594SAndre Fischer         throw cssl::IllegalArgumentException(
170*95a18594SAndre Fischer             A2S("can not remove an empty reference"),
171*95a18594SAndre Fischer             static_cast<XWeak*>(this), 0);
17222de8995SAndre Fischer 
173b9e67834SAndre Fischer     ::std::vector<cssu::Reference<cssu::XInterface> > aContainersToRemove;
17422de8995SAndre Fischer     for (ListenerMap::iterator
17522de8995SAndre Fischer              iContainer(maListeners.begin()),
17622de8995SAndre Fischer              iEnd(maListeners.end());
17722de8995SAndre Fischer          iContainer!=iEnd;
17822de8995SAndre Fischer          ++iContainer)
17922de8995SAndre Fischer     {
180*95a18594SAndre Fischer         const ListenerContainer::iterator iListener (
181*95a18594SAndre Fischer             ::std::find(iContainer->second.maListeners.begin(), iContainer->second.maListeners.end(), rxListener));
182*95a18594SAndre Fischer         if (iListener != iContainer->second.maListeners.end())
183b9e67834SAndre Fischer         {
184*95a18594SAndre Fischer             iContainer->second.maListeners.erase(iListener);
185b9e67834SAndre Fischer 
186b9e67834SAndre Fischer             // When we just removed the last listener then mark the
187b9e67834SAndre Fischer             // container as to be removed.
188*95a18594SAndre Fischer             if (iContainer->second.maListeners.empty())
189b9e67834SAndre Fischer                 aContainersToRemove.push_back(iContainer->first);
190b9e67834SAndre Fischer         }
191b9e67834SAndre Fischer     }
192b9e67834SAndre Fischer 
193b9e67834SAndre Fischer     for (::std::vector<cssu::Reference<cssu::XInterface> >::iterator
194b9e67834SAndre Fischer              iFocus(aContainersToRemove.begin()),
195b9e67834SAndre Fischer              iEnd(aContainersToRemove.end());
196b9e67834SAndre Fischer          iFocus!=iEnd;
197b9e67834SAndre Fischer          ++iFocus)
198b9e67834SAndre Fischer     {
199b9e67834SAndre Fischer         maListeners.erase(*iFocus);
20022de8995SAndre Fischer     }
20122de8995SAndre Fischer }
20222de8995SAndre Fischer 
20322de8995SAndre Fischer 
20422de8995SAndre Fischer 
20522de8995SAndre Fischer 
20622de8995SAndre Fischer void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
20722de8995SAndre Fischer     const css::ui::ContextChangeEventObject& rEventObject,
20822de8995SAndre Fischer     const cssu::Reference<cssu::XInterface>& rxEventFocus)
20922de8995SAndre Fischer     throw(cssu::RuntimeException)
21022de8995SAndre Fischer {
211*95a18594SAndre Fischer     // Remember the current context.
212*95a18594SAndre Fischer     if (rxEventFocus.is())
213*95a18594SAndre Fischer     {
214*95a18594SAndre Fischer         ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
215*95a18594SAndre Fischer         if (iDescriptor != maListeners.end())
216*95a18594SAndre Fischer         {
217*95a18594SAndre Fischer             iDescriptor->second.msCurrentApplicationName = rEventObject.ApplicationName;
218*95a18594SAndre Fischer             iDescriptor->second.msCurrentContextName = rEventObject.ContextName;
219*95a18594SAndre Fischer         }
220*95a18594SAndre Fischer     }
221*95a18594SAndre Fischer 
22222de8995SAndre Fischer     BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
22322de8995SAndre Fischer     if (rxEventFocus.is())
22422de8995SAndre Fischer         BroadcastEventToSingleContainer(rEventObject, NULL);
22522de8995SAndre Fischer }
22622de8995SAndre Fischer 
22722de8995SAndre Fischer 
22822de8995SAndre Fischer 
22922de8995SAndre Fischer 
23022de8995SAndre Fischer void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
23122de8995SAndre Fischer     const css::ui::ContextChangeEventObject& rEventObject,
23222de8995SAndre Fischer     const cssu::Reference<cssu::XInterface>& rxEventFocus)
23322de8995SAndre Fischer {
234*95a18594SAndre Fischer     ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
235*95a18594SAndre Fischer     if (iDescriptor != maListeners.end())
23622de8995SAndre Fischer     {
23722de8995SAndre Fischer         // Create a copy of the listener container to avoid problems
23822de8995SAndre Fischer         // when one of the called listeners calls add... or remove...
239*95a18594SAndre Fischer         ListenerContainer aContainer (iDescriptor->second.maListeners);
24022de8995SAndre Fischer         for (ListenerContainer::const_iterator
24122de8995SAndre Fischer                  iListener(aContainer.begin()),
24222de8995SAndre Fischer                  iEnd(aContainer.end());
24322de8995SAndre Fischer              iListener!=iEnd;
24422de8995SAndre Fischer              ++iListener)
24522de8995SAndre Fischer         {
24622de8995SAndre Fischer             (*iListener)->notifyContextChangeEvent(rEventObject);
24722de8995SAndre Fischer         }
24822de8995SAndre Fischer     }
24922de8995SAndre Fischer }
25022de8995SAndre Fischer 
25122de8995SAndre Fischer 
25222de8995SAndre Fischer 
25322de8995SAndre Fischer 
25422de8995SAndre Fischer // XSingleComponentFactory
25522de8995SAndre Fischer 
25622de8995SAndre Fischer cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext (
25722de8995SAndre Fischer     const cssu::Reference<cssu::XComponentContext>& rxContext)
25822de8995SAndre Fischer     throw (cssu::Exception, cssu::RuntimeException)
25922de8995SAndre Fischer {
26022de8995SAndre Fischer     (void)rxContext;
26122de8995SAndre Fischer     return cssu::Reference<cssu::XInterface>();
26222de8995SAndre Fischer }
26322de8995SAndre Fischer 
26422de8995SAndre Fischer 
26522de8995SAndre Fischer 
26622de8995SAndre Fischer 
26722de8995SAndre Fischer cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext (
26822de8995SAndre Fischer     const cssu::Sequence<cssu::Any>& rArguments,
26922de8995SAndre Fischer     const cssu::Reference<cssu::XComponentContext>& rxContext)
27022de8995SAndre Fischer     throw (cssu::Exception, cssu::RuntimeException)
27122de8995SAndre Fischer {
27222de8995SAndre Fischer     (void)rArguments;
27322de8995SAndre Fischer     (void)rxContext;
27422de8995SAndre Fischer     return cssu::Reference<cssu::XInterface>();
27522de8995SAndre Fischer }
27622de8995SAndre Fischer 
27722de8995SAndre Fischer 
27822de8995SAndre Fischer 
27922de8995SAndre Fischer 
28022de8995SAndre Fischer // XServiceInfo
28122de8995SAndre Fischer 
28222de8995SAndre Fischer ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void)
28322de8995SAndre Fischer     throw(cssu::RuntimeException)
28422de8995SAndre Fischer {
28522de8995SAndre Fischer     return impl_getStaticImplementationName();
28622de8995SAndre Fischer }
28722de8995SAndre Fischer 
28822de8995SAndre Fischer 
28922de8995SAndre Fischer 
29022de8995SAndre Fischer 
29122de8995SAndre Fischer 
29222de8995SAndre Fischer sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
29322de8995SAndre Fischer     const ::rtl::OUString& rsServiceName)
29422de8995SAndre Fischer     throw (cssu::RuntimeException)
29522de8995SAndre Fischer {
29622de8995SAndre Fischer     return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0;
29722de8995SAndre Fischer }
29822de8995SAndre Fischer 
29922de8995SAndre Fischer 
30022de8995SAndre Fischer 
30122de8995SAndre Fischer 
30222de8995SAndre Fischer cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void)
30322de8995SAndre Fischer     throw (cssu::RuntimeException)
30422de8995SAndre Fischer {
30522de8995SAndre Fischer     return static_GetSupportedServiceNames();
30622de8995SAndre Fischer }
30722de8995SAndre Fischer 
30822de8995SAndre Fischer 
30922de8995SAndre Fischer 
31022de8995SAndre Fischer 
31122de8995SAndre Fischer // Local and static methods.
31222de8995SAndre Fischer 
31322de8995SAndre Fischer OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void)
31422de8995SAndre Fischer {
31522de8995SAndre Fischer     return A2S(IMPLEMENTATION_NAME);
31622de8995SAndre Fischer }
31722de8995SAndre Fischer 
31822de8995SAndre Fischer 
31922de8995SAndre Fischer 
32022de8995SAndre Fischer 
32122de8995SAndre Fischer cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void)
32222de8995SAndre Fischer {
32322de8995SAndre Fischer     cssu::Sequence<OUString> aServiceNames (2);
32422de8995SAndre Fischer     aServiceNames[0] = A2S(SERVICE_NAME);
32522de8995SAndre Fischer     aServiceNames[1] = A2S(SINGLETON_NAME);
32622de8995SAndre Fischer     return aServiceNames;
32722de8995SAndre Fischer }
32822de8995SAndre Fischer 
32922de8995SAndre Fischer 
33022de8995SAndre Fischer 
33122de8995SAndre Fischer 
33222de8995SAndre Fischer cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory (
33322de8995SAndre Fischer     const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager)
33422de8995SAndre Fischer {
33522de8995SAndre Fischer     (void)rxServiceManager;
33622de8995SAndre Fischer     return cppu::createSingleComponentFactory(
33722de8995SAndre Fischer         ContextChangeEventMultiplexer::static_CreateInstance,
33822de8995SAndre Fischer         ContextChangeEventMultiplexer::impl_getStaticImplementationName(),
33922de8995SAndre Fischer         ContextChangeEventMultiplexer::static_GetSupportedServiceNames()
34022de8995SAndre Fischer         );
34122de8995SAndre Fischer }
34222de8995SAndre Fischer 
34322de8995SAndre Fischer 
34422de8995SAndre Fischer 
34522de8995SAndre Fischer 
34622de8995SAndre Fischer cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance (
34722de8995SAndre Fischer     const cssu::Reference<cssu::XComponentContext>& rxComponentContext)
34822de8995SAndre Fischer     throw (cssu::Exception)
34922de8995SAndre Fischer {
35022de8995SAndre Fischer     ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext);
35122de8995SAndre Fischer     cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY);
35222de8995SAndre Fischer     return xService;
35322de8995SAndre Fischer }
35422de8995SAndre Fischer 
35522de8995SAndre Fischer }  // end of namespace framework
356