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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 #include <sfx2/sfxstatuslistener.hxx>
31 #include <svl/poolitem.hxx>
32 #include <svl/eitem.hxx>
33 #include <svl/stritem.hxx>
34 #include <svl/intitem.hxx>
35 #include <svl/itemset.hxx>
36 #include <svtools/itemdel.hxx>
37 #include <svl/visitem.hxx>
38 #include <cppuhelper/weak.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <vos/mutex.hxx>
41 #include <vcl/svapp.hxx>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/lang/XUnoTunnel.hpp>
44 #include <com/sun/star/frame/status/ItemStatus.hpp>
45 #include <com/sun/star/frame/status/ItemState.hpp>
46 #include <com/sun/star/frame/status/Visibility.hpp>
47 
48 #include <sfx2/viewfrm.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/unoctitm.hxx>
51 #include <sfx2/msgpool.hxx>
52 
53 using ::rtl::OUString;
54 using namespace ::cppu;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::frame;
57 using namespace ::com::sun::star::frame::status;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::util;
60 
61 SFX_IMPL_XINTERFACE_3( SfxStatusListener, OWeakObject, ::com::sun::star::lang::XComponent, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
62 SFX_IMPL_XTYPEPROVIDER_3( SfxStatusListener, ::com::sun::star::lang::XComponent, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
63 
64 SfxStatusListener::SfxStatusListener( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const OUString& rCommand ) :
65     cppu::OWeakObject(),
66     m_nSlotID( nSlotId ),
67     m_xDispatchProvider( rDispatchProvider )
68 {
69     m_aCommand.Complete = rCommand;
70     Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance(
71                                             rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
72     xTrans->parseStrict( m_aCommand );
73     if ( rDispatchProvider.is() )
74         m_xDispatch = rDispatchProvider->queryDispatch( m_aCommand, rtl::OUString(), 0 );
75 }
76 
77 SfxStatusListener::~SfxStatusListener()
78 {
79 }
80 
81 // old sfx controller item C++ API
82 void SfxStatusListener::StateChanged( sal_uInt16, SfxItemState, const SfxPoolItem* )
83 {
84     // must be implemented by sub class
85 }
86 
87 void SfxStatusListener::Bind()
88 {
89     if ( !m_xDispatch.is() && m_xDispatchProvider.is() )
90     {
91         m_xDispatch = m_xDispatchProvider->queryDispatch( m_aCommand, rtl::OUString(), 0 );
92         try
93         {
94             Reference< XStatusListener > aStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
95             m_xDispatch->addStatusListener( aStatusListener, m_aCommand );
96         }
97         catch( Exception& )
98         {
99         }
100     }
101 }
102 
103 void SfxStatusListener::Bind( sal_uInt16 nSlotId, const rtl::OUString& rNewCommand )
104 {
105     // first remove old listener, if we have a dispatch object
106     Reference< XStatusListener > aStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
107     if ( m_xDispatch.is() )
108         m_xDispatch->removeStatusListener( aStatusListener, m_aCommand );
109     if ( m_xDispatchProvider.is() )
110     {
111         // Store new command data and query for new dispatch
112         m_nSlotID = nSlotId;
113         m_aCommand.Complete = rNewCommand;
114         Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance(
115                                                 rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
116         xTrans->parseStrict( m_aCommand );
117 
118         m_xDispatch = m_xDispatchProvider->queryDispatch( m_aCommand, rtl::OUString(), 0 );
119 
120         try
121         {
122             m_xDispatch->addStatusListener( aStatusListener, m_aCommand );
123         }
124         catch( Exception& )
125         {
126         }
127     }
128 }
129 
130 void SfxStatusListener::UnBind()
131 {
132     if ( m_xDispatch.is() )
133     {
134         Reference< XStatusListener > aStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
135         m_xDispatch->removeStatusListener( aStatusListener, m_aCommand );
136         m_xDispatch.clear();
137     }
138 }
139 
140 void SfxStatusListener::ReBind()
141 {
142     Reference< XStatusListener > aStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
143     if ( m_xDispatch.is() )
144         m_xDispatch->removeStatusListener( aStatusListener, m_aCommand );
145     if ( m_xDispatchProvider.is() )
146     {
147         try
148         {
149             m_xDispatch = m_xDispatchProvider->queryDispatch( m_aCommand, rtl::OUString(), 0 );
150             if ( m_xDispatch.is() )
151                 m_xDispatch->addStatusListener( aStatusListener, m_aCommand );
152         }
153         catch( Exception& )
154         {
155         }
156     }
157 }
158 
159 // new UNO API
160 void SAL_CALL SfxStatusListener::dispose() throw( ::com::sun::star::uno::RuntimeException )
161 {
162     if ( m_xDispatch.is() && m_aCommand.Complete.getLength() > 0 )
163     {
164         try
165         {
166             Reference< XStatusListener > aStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY );
167             m_xDispatch->removeStatusListener( aStatusListener, m_aCommand );
168         }
169         catch ( Exception& )
170         {
171         }
172     }
173 
174     m_xDispatch.clear();
175     m_xDispatchProvider.clear();
176 }
177 
178 void SAL_CALL SfxStatusListener::addEventListener( const Reference< XEventListener >& )
179 throw ( RuntimeException )
180 {
181     // do nothing - this is a wrapper class which does not support listeners
182 }
183 
184 void SAL_CALL SfxStatusListener::removeEventListener( const Reference< XEventListener >& )
185 throw ( RuntimeException )
186 {
187     // do nothing - this is a wrapper class which does not support listeners
188 }
189 
190 void SAL_CALL SfxStatusListener::disposing( const EventObject& Source )
191 throw( RuntimeException )
192 {
193     ::vos::OGuard aGuard( Application::GetSolarMutex() );
194 
195     if ( Source.Source == Reference< XInterface >( m_xDispatch, UNO_QUERY ))
196         m_xDispatch.clear();
197     else if ( Source.Source == Reference< XInterface >( m_xDispatchProvider, UNO_QUERY ))
198         m_xDispatchProvider.clear();
199 }
200 
201 void SAL_CALL SfxStatusListener::statusChanged( const FeatureStateEvent& rEvent)
202 throw( RuntimeException )
203 {
204     ::vos::OGuard aGuard( Application::GetSolarMutex() );
205 
206     SfxViewFrame* pViewFrame = NULL;
207     if ( m_xDispatch.is() )
208     {
209         Reference< XUnoTunnel > xTunnel( m_xDispatch, UNO_QUERY );
210         SfxOfficeDispatch* pDisp = NULL;
211         if ( xTunnel.is() )
212         {
213             sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
214             pDisp = reinterpret_cast< SfxOfficeDispatch* >(sal::static_int_cast< sal_IntPtr >( nImplementation ));
215         }
216 
217         if ( pDisp )
218             pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
219     }
220 
221     SfxSlotPool& rPool = SfxSlotPool::GetSlotPool( pViewFrame );
222     const SfxSlot* pSlot = rPool.GetSlot( m_nSlotID );
223 
224     SfxItemState eState = SFX_ITEM_DISABLED;
225 	SfxPoolItem* pItem = NULL;
226     if ( rEvent.IsEnabled )
227 	{
228 		eState = SFX_ITEM_AVAILABLE;
229 		::com::sun::star::uno::Type pType =	rEvent.State.getValueType();
230 
231         if ( pType == ::getVoidCppuType() )
232         {
233             pItem = new SfxVoidItem( m_nSlotID );
234             eState = SFX_ITEM_UNKNOWN;
235         }
236 		else if ( pType == ::getBooleanCppuType() )
237 		{
238 			sal_Bool bTemp = false;
239 			rEvent.State >>= bTemp ;
240 			pItem = new SfxBoolItem( m_nSlotID, bTemp );
241 		}
242 		else if ( pType == ::getCppuType((const sal_uInt16*)0) )
243 		{
244 			sal_uInt16 nTemp = 0;
245 			rEvent.State >>= nTemp ;
246 			pItem = new SfxUInt16Item( m_nSlotID, nTemp );
247 		}
248 		else if ( pType == ::getCppuType((const sal_uInt32*)0) )
249 		{
250 			sal_uInt32 nTemp = 0;
251 			rEvent.State >>= nTemp ;
252 			pItem = new SfxUInt32Item( m_nSlotID, nTemp );
253 		}
254 		else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
255 		{
256 			::rtl::OUString sTemp ;
257 			rEvent.State >>= sTemp ;
258 			pItem = new SfxStringItem( m_nSlotID, sTemp );
259 		}
260         else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::ItemStatus*)0) )
261         {
262             ItemStatus aItemStatus;
263             rEvent.State >>= aItemStatus;
264             eState = aItemStatus.State;
265             pItem = new SfxVoidItem( m_nSlotID );
266         }
267         else if ( pType == ::getCppuType((const ::com::sun::star::frame::status::Visibility*)0) )
268         {
269             Visibility aVisibilityStatus;
270             rEvent.State >>= aVisibilityStatus;
271             pItem = new SfxVisibilityItem( m_nSlotID, aVisibilityStatus.bVisible );
272         }
273         else
274         {
275             if ( pSlot )
276                 pItem = pSlot->GetType()->CreateItem();
277             if ( pItem )
278             {
279                 pItem->SetWhich( m_nSlotID );
280                 pItem->PutValue( rEvent.State );
281             }
282             else
283                 pItem = new SfxVoidItem( m_nSlotID );
284         }
285 	}
286 
287     StateChanged( m_nSlotID, eState, pItem );
288     delete pItem;
289 }
290 
291