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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 
27 #include "ModifyListenerHelper.hxx"
28 #include "WeakListenerAdapter.hxx"
29 #include "macros.hxx"
30 
31 #include <cppuhelper/interfacecontainer.hxx>
32 
33 #include <com/sun/star/frame/XModel.hpp>
34 
35 using namespace ::com::sun::star;
36 
37 using ::com::sun::star::uno::Reference;
38 using ::com::sun::star::uno::Sequence;
39 using ::rtl::OUString;
40 
41 namespace
42 {
43 
lcl_fireModifyEvent(::cppu::OBroadcastHelper & rBroadcastHelper,const Reference<uno::XWeak> & xEventSource,const lang::EventObject * pEvent)44 void lcl_fireModifyEvent(
45     ::cppu::OBroadcastHelper & rBroadcastHelper,
46     const Reference< uno::XWeak > & xEventSource,
47     const lang::EventObject * pEvent )
48 {
49     ::cppu::OInterfaceContainerHelper * pCntHlp = rBroadcastHelper.getContainer(
50         ::getCppuType( reinterpret_cast< Reference< util::XModifyListener > * >(0)));
51 	if( pCntHlp )
52     {
53         lang::EventObject aEventToSend;
54         if( pEvent )
55             aEventToSend = *pEvent;
56         else
57             aEventToSend.Source.set( xEventSource );
58         OSL_ENSURE( aEventToSend.Source.is(), "Sending event without source" );
59 
60         ::cppu::OInterfaceIteratorHelper aIt( *pCntHlp );
61 
62         while( aIt.hasMoreElements())
63         {
64             Reference< util::XModifyListener > xModListener( aIt.next(), uno::UNO_QUERY );
65             if( xModListener.is())
66                 xModListener->modified( aEventToSend );
67         }
68     }
69 }
70 
71 struct lcl_weakReferenceToSame : public ::std::unary_function<
72         ::std::pair<
73             ::com::sun::star::uno::WeakReference< ::com::sun::star::util::XModifyListener >,
74             ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener > >,
75         bool >
76 {
lcl_weakReferenceToSame__anon05c6fd980111::lcl_weakReferenceToSame77     lcl_weakReferenceToSame( const Reference< util::XModifyListener > & xModListener ) :
78             m_xHardRef( xModListener )
79     {}
80 
operator ()__anon05c6fd980111::lcl_weakReferenceToSame81     bool operator() ( const argument_type & xElem )
82     {
83         Reference< util::XModifyListener > xWeakAsHard( xElem.first );
84         if( xWeakAsHard.is())
85             return (xWeakAsHard == m_xHardRef);
86         return false;
87     }
88 
89 private:
90     Reference< util::XModifyListener > m_xHardRef;
91 };
92 
93 } //  anonymous namespace
94 
95 // ================================================================================
96 
97 namespace chart
98 {
99 namespace ModifyListenerHelper
100 {
101 
createModifyEventForwarder()102 uno::Reference< util::XModifyListener > createModifyEventForwarder()
103 {
104     return new ModifyEventForwarder();
105 }
106 
ModifyEventForwarder()107 ModifyEventForwarder::ModifyEventForwarder() :
108         ::cppu::WeakComponentImplHelper2<
109         ::com::sun::star::util::XModifyBroadcaster,
110         ::com::sun::star::util::XModifyListener >( m_aMutex ),
111         m_aModifyListeners( m_aMutex )
112 {
113 }
114 
FireEvent(const lang::EventObject & rEvent)115 void ModifyEventForwarder::FireEvent( const lang::EventObject & rEvent )
116 {
117     lcl_fireModifyEvent( m_aModifyListeners, Reference< uno::XWeak >(), & rEvent );
118 }
119 
AddListener(const Reference<util::XModifyListener> & aListener)120 void ModifyEventForwarder::AddListener( const Reference< util::XModifyListener >& aListener )
121 {
122     try
123     {
124         Reference< util::XModifyListener > xListenerToAdd( aListener );
125 
126         Reference< uno::XWeak > xWeak( aListener, uno::UNO_QUERY );
127         if( xWeak.is())
128         {
129             // remember the helper class for later remove
130             uno::WeakReference< util::XModifyListener > xWeakRef( aListener );
131             xListenerToAdd.set( new WeakModifyListenerAdapter( xWeakRef ));
132             m_aListenerMap.push_back( tListenerMap::value_type( xWeakRef, xListenerToAdd ));
133         }
134 
135         m_aModifyListeners.addListener( ::getCppuType( &xListenerToAdd ), xListenerToAdd );
136     }
137     catch( const uno::Exception & ex )
138     {
139         ASSERT_EXCEPTION( ex );
140     }
141 }
142 
RemoveListener(const Reference<util::XModifyListener> & aListener)143 void ModifyEventForwarder::RemoveListener( const Reference< util::XModifyListener >& aListener )
144 {
145     try
146     {
147         // look up fitting helper class that has been added
148         Reference< util::XModifyListener > xListenerToRemove( aListener );
149         tListenerMap::iterator aIt(
150             ::std::find_if( m_aListenerMap.begin(), m_aListenerMap.end(), lcl_weakReferenceToSame( aListener )));
151         if( aIt != m_aListenerMap.end())
152         {
153             xListenerToRemove.set( (*aIt).second );
154             // map entry is no longer needed
155             m_aListenerMap.erase( aIt );
156         }
157 
158         m_aModifyListeners.removeListener( ::getCppuType( &aListener ), xListenerToRemove );
159     }
160     catch( const uno::Exception & ex )
161     {
162         ASSERT_EXCEPTION( ex );
163     }
164 }
165 
DisposeAndClear(const Reference<uno::XWeak> & xSource)166 void ModifyEventForwarder::DisposeAndClear( const Reference< uno::XWeak > & xSource )
167 {
168     ::cppu::OInterfaceContainerHelper * pCntHlp = m_aModifyListeners.getContainer(
169         ::getCppuType( reinterpret_cast< Reference< util::XModifyListener > * >(0)));
170     if( pCntHlp )
171         pCntHlp->disposeAndClear( lang::EventObject( xSource ) );
172 }
173 
174 // ____ XModifyBroadcaster ____
addModifyListener(const Reference<util::XModifyListener> & aListener)175 void SAL_CALL ModifyEventForwarder::addModifyListener( const Reference< util::XModifyListener >& aListener )
176     throw (uno::RuntimeException)
177 {
178     AddListener( aListener );
179 }
180 
removeModifyListener(const Reference<util::XModifyListener> & aListener)181 void SAL_CALL ModifyEventForwarder::removeModifyListener( const Reference< util::XModifyListener >& aListener )
182     throw (uno::RuntimeException)
183 {
184     RemoveListener( aListener );
185 }
186 
187 // ____ XModifyListener ____
modified(const lang::EventObject & aEvent)188 void SAL_CALL ModifyEventForwarder::modified( const lang::EventObject& aEvent )
189     throw (uno::RuntimeException)
190 {
191     FireEvent( aEvent );
192 }
193 
194 // ____ XEventListener (base of XModifyListener) ____
disposing(const lang::EventObject &)195 void SAL_CALL ModifyEventForwarder::disposing( const lang::EventObject& /* Source */ )
196     throw (uno::RuntimeException)
197 {
198     // nothing
199 }
200 
201 // ____ WeakComponentImplHelperBase ____
disposing()202 void SAL_CALL ModifyEventForwarder::disposing()
203 {
204     // dispose was called at this
205     DisposeAndClear( this );
206 }
207 
208 } //  namespace ModifyListenerHelper
209 } //  namespace chart
210