xref: /aoo41x/main/sfx2/source/control/statcach.cxx (revision d119d52d)
1*d119d52dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*d119d52dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*d119d52dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*d119d52dSAndrew Rist  * distributed with this work for additional information
6*d119d52dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*d119d52dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*d119d52dSAndrew Rist  * "License"); you may not use this file except in compliance
9*d119d52dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*d119d52dSAndrew Rist  *
11*d119d52dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*d119d52dSAndrew Rist  *
13*d119d52dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*d119d52dSAndrew Rist  * software distributed under the License is distributed on an
15*d119d52dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*d119d52dSAndrew Rist  * KIND, either express or implied.  See the License for the
17*d119d52dSAndrew Rist  * specific language governing permissions and limitations
18*d119d52dSAndrew Rist  * under the License.
19*d119d52dSAndrew Rist  *
20*d119d52dSAndrew Rist  *************************************************************/
21*d119d52dSAndrew Rist 
22*d119d52dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sfx2.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #ifdef SOLARIS
28cdf0e10cSrcweir // HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8
29cdf0e10cSrcweir #include <ctime>
30cdf0e10cSrcweir #endif
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <string> // HACK: prevent conflict between STLPORT and Workshop headers
33cdf0e10cSrcweir #include <com/sun/star/util/XURLTransformer.hpp>
34cdf0e10cSrcweir #include <com/sun/star/frame/XController.hpp>
35cdf0e10cSrcweir #include <com/sun/star/frame/XFrameActionListener.hpp>
36cdf0e10cSrcweir #include <com/sun/star/frame/XComponentLoader.hpp>
37cdf0e10cSrcweir #include <com/sun/star/frame/XFrame.hpp>
38cdf0e10cSrcweir #include <com/sun/star/frame/FrameActionEvent.hpp>
39cdf0e10cSrcweir #include <com/sun/star/frame/FrameAction.hpp>
40cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp>
41cdf0e10cSrcweir #include <cppuhelper/weak.hxx>
42cdf0e10cSrcweir #include <svl/eitem.hxx>
43cdf0e10cSrcweir #include <svl/intitem.hxx>
44cdf0e10cSrcweir #include <svl/stritem.hxx>
45cdf0e10cSrcweir #include <svl/visitem.hxx>
46cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #ifndef GCC
49cdf0e10cSrcweir #endif
50cdf0e10cSrcweir 
51cdf0e10cSrcweir #include <sfx2/app.hxx>
52cdf0e10cSrcweir #include <sfx2/appuno.hxx>
53cdf0e10cSrcweir #include "statcach.hxx"
54cdf0e10cSrcweir #include <sfx2/msg.hxx>
55cdf0e10cSrcweir #include <sfx2/ctrlitem.hxx>
56cdf0e10cSrcweir #include <sfx2/dispatch.hxx>
57cdf0e10cSrcweir #include "sfxtypes.hxx"
58cdf0e10cSrcweir #include <sfx2/sfxuno.hxx>
59cdf0e10cSrcweir #include <sfx2/unoctitm.hxx>
60cdf0e10cSrcweir #include <sfx2/msgpool.hxx>
61cdf0e10cSrcweir #include <sfx2/viewfrm.hxx>
62cdf0e10cSrcweir 
63cdf0e10cSrcweir using namespace ::com::sun::star;
64cdf0e10cSrcweir using namespace ::com::sun::star::uno;
65cdf0e10cSrcweir using namespace ::com::sun::star::util;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir //====================================================================
68cdf0e10cSrcweir 
69cdf0e10cSrcweir DBG_NAME(SfxStateCache)
DBG_NAME(SfxStateCacheSetState)70cdf0e10cSrcweir DBG_NAME(SfxStateCacheSetState)
71cdf0e10cSrcweir 
72cdf0e10cSrcweir SFX_IMPL_XINTERFACE_2( BindDispatch_Impl, OWeakObject, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
73cdf0e10cSrcweir SFX_IMPL_XTYPEPROVIDER_2( BindDispatch_Impl, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
74cdf0e10cSrcweir 
75cdf0e10cSrcweir //-----------------------------------------------------------------------------
76cdf0e10cSrcweir BindDispatch_Impl::BindDispatch_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > & rDisp, const ::com::sun::star::util::URL& rURL, SfxStateCache *pStateCache, const SfxSlot* pS )
77cdf0e10cSrcweir 	: xDisp( rDisp )
78cdf0e10cSrcweir 	, aURL( rURL )
79cdf0e10cSrcweir 	, pCache( pStateCache )
80cdf0e10cSrcweir     , pSlot( pS )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir     DBG_ASSERT( pCache && pSlot, "Invalid BindDispatch!");
83cdf0e10cSrcweir     aStatus.IsEnabled = sal_True;
84cdf0e10cSrcweir }
85cdf0e10cSrcweir 
disposing(const::com::sun::star::lang::EventObject &)86cdf0e10cSrcweir void SAL_CALL BindDispatch_Impl::disposing( const ::com::sun::star::lang::EventObject& ) throw( ::com::sun::star::uno::RuntimeException )
87cdf0e10cSrcweir {
88cdf0e10cSrcweir 	if ( xDisp.is() )
89cdf0e10cSrcweir 	{
90cdf0e10cSrcweir         xDisp->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, aURL );
91cdf0e10cSrcweir 		xDisp = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
92cdf0e10cSrcweir 	}
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
statusChanged(const::com::sun::star::frame::FeatureStateEvent & rEvent)95cdf0e10cSrcweir void SAL_CALL  BindDispatch_Impl::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& rEvent ) throw( ::com::sun::star::uno::RuntimeException )
96cdf0e10cSrcweir {
97cdf0e10cSrcweir 	aStatus = rEvent;
98cdf0e10cSrcweir     if ( !pCache )
99cdf0e10cSrcweir 		return;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 	::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >  xRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
102cdf0e10cSrcweir 	if ( aStatus.Requery )
103cdf0e10cSrcweir 		pCache->Invalidate( sal_True );
104cdf0e10cSrcweir 	else
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir         SfxPoolItem *pItem=NULL;
107cdf0e10cSrcweir         sal_uInt16 nId = pCache->GetId();
108cdf0e10cSrcweir         SfxItemState eState = SFX_ITEM_DISABLED;
109cdf0e10cSrcweir         // pCache->Invalidate( sal_False );
110cdf0e10cSrcweir         if ( !aStatus.IsEnabled )
111cdf0e10cSrcweir         {
112cdf0e10cSrcweir             // default
113cdf0e10cSrcweir         }
114cdf0e10cSrcweir         else if (aStatus.State.hasValue())
115cdf0e10cSrcweir 		{
116cdf0e10cSrcweir             eState = SFX_ITEM_AVAILABLE;
117cdf0e10cSrcweir 			::com::sun::star::uno::Any aAny = aStatus.State;
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 			::com::sun::star::uno::Type pType =	aAny.getValueType();
120cdf0e10cSrcweir 			if ( pType == ::getBooleanCppuType() )
121cdf0e10cSrcweir 			{
122cdf0e10cSrcweir 				sal_Bool bTemp = false;
123cdf0e10cSrcweir 				aAny >>= bTemp ;
124cdf0e10cSrcweir 				pItem = new SfxBoolItem( nId, bTemp );
125cdf0e10cSrcweir 			}
126cdf0e10cSrcweir 			else if ( pType == ::getCppuType((const sal_uInt16*)0) )
127cdf0e10cSrcweir 			{
128cdf0e10cSrcweir 				sal_uInt16 nTemp = 0;
129cdf0e10cSrcweir 				aAny >>= nTemp ;
130cdf0e10cSrcweir 				pItem = new SfxUInt16Item( nId, nTemp );
131cdf0e10cSrcweir 			}
132cdf0e10cSrcweir 			else if ( pType == ::getCppuType((const sal_uInt32*)0) )
133cdf0e10cSrcweir 			{
134cdf0e10cSrcweir 				sal_uInt32 nTemp = 0;
135cdf0e10cSrcweir 				aAny >>= nTemp ;
136cdf0e10cSrcweir 				pItem = new SfxUInt32Item( nId, nTemp );
137cdf0e10cSrcweir 			}
138cdf0e10cSrcweir 			else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
139cdf0e10cSrcweir 			{
140cdf0e10cSrcweir 				::rtl::OUString sTemp ;
141cdf0e10cSrcweir 				aAny >>= sTemp ;
142cdf0e10cSrcweir 				pItem = new SfxStringItem( nId, sTemp );
143cdf0e10cSrcweir 			}
144cdf0e10cSrcweir 			else
145cdf0e10cSrcweir             {
146cdf0e10cSrcweir                 if ( pSlot )
147cdf0e10cSrcweir                     pItem = pSlot->GetType()->CreateItem();
148cdf0e10cSrcweir                 if ( pItem )
149cdf0e10cSrcweir                 {
150cdf0e10cSrcweir                     pItem->SetWhich( nId );
151cdf0e10cSrcweir                     pItem->PutValue( aAny );
152cdf0e10cSrcweir                 }
153cdf0e10cSrcweir                 else
154cdf0e10cSrcweir                     pItem = new SfxVoidItem( nId );
155cdf0e10cSrcweir             }
156cdf0e10cSrcweir 		}
157cdf0e10cSrcweir 		else
158cdf0e10cSrcweir 		{
159cdf0e10cSrcweir 			// DONTCARE status
160cdf0e10cSrcweir             pItem = new SfxVoidItem(0);
161cdf0e10cSrcweir             eState = SFX_ITEM_UNKNOWN;
162cdf0e10cSrcweir 		}
163cdf0e10cSrcweir 
164cdf0e10cSrcweir         for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
165cdf0e10cSrcweir             pCtrl;
166cdf0e10cSrcweir             pCtrl = pCtrl->GetItemLink() )
167cdf0e10cSrcweir             pCtrl->StateChanged( nId, eState, pItem );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir        delete pItem;
170cdf0e10cSrcweir 	}
171cdf0e10cSrcweir }
172cdf0e10cSrcweir 
Release()173cdf0e10cSrcweir void BindDispatch_Impl::Release()
174cdf0e10cSrcweir {
175cdf0e10cSrcweir 	if ( xDisp.is() )
176cdf0e10cSrcweir 	{
177cdf0e10cSrcweir         xDisp->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, aURL );
178cdf0e10cSrcweir 		xDisp = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
179cdf0e10cSrcweir 	}
180cdf0e10cSrcweir 
181cdf0e10cSrcweir 	pCache = NULL;
182cdf0e10cSrcweir 	release();
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
GetStatus() const185cdf0e10cSrcweir const ::com::sun::star::frame::FeatureStateEvent& BindDispatch_Impl::GetStatus() const
186cdf0e10cSrcweir {
187cdf0e10cSrcweir 	return aStatus;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir 
Dispatch(uno::Sequence<beans::PropertyValue> aProps,sal_Bool bForceSynchron)190cdf0e10cSrcweir void BindDispatch_Impl::Dispatch( uno::Sequence < beans::PropertyValue > aProps, sal_Bool bForceSynchron )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir     if ( xDisp.is() && aStatus.IsEnabled )
193cdf0e10cSrcweir     {
194cdf0e10cSrcweir 		sal_Int32 nLength = aProps.getLength();
195cdf0e10cSrcweir         aProps.realloc(nLength+1);
196cdf0e10cSrcweir         aProps[nLength].Name = DEFINE_CONST_UNICODE("SynchronMode");
197cdf0e10cSrcweir         aProps[nLength].Value <<= bForceSynchron ;
198cdf0e10cSrcweir         xDisp->dispatch( aURL, aProps );
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir //--------------------------------------------------------------------
203cdf0e10cSrcweir 
204cdf0e10cSrcweir /*	Dieser Konstruktor fuer einen ungueltigen Cache, der sich also
205cdf0e10cSrcweir 	bei der ersten Anfrage zun"achst updated.
206cdf0e10cSrcweir  */
207cdf0e10cSrcweir 
SfxStateCache(sal_uInt16 nFuncId)208cdf0e10cSrcweir SfxStateCache::SfxStateCache( sal_uInt16 nFuncId ):
209cdf0e10cSrcweir     pDispatch( 0 ),
210cdf0e10cSrcweir     nId(nFuncId),
211cdf0e10cSrcweir     pInternalController(0),
212cdf0e10cSrcweir     pController(0),
213cdf0e10cSrcweir     pLastItem( 0 ),
214cdf0e10cSrcweir     eLastState( 0 ),
215cdf0e10cSrcweir     bItemVisible( sal_True )
216cdf0e10cSrcweir {
217cdf0e10cSrcweir 	DBG_MEMTEST();
218cdf0e10cSrcweir 	DBG_CTOR(SfxStateCache,	0);
219cdf0e10cSrcweir 	bCtrlDirty = sal_True;
220cdf0e10cSrcweir 	bSlotDirty = sal_True;
221cdf0e10cSrcweir 	bItemDirty = sal_True;
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir //--------------------------------------------------------------------
225cdf0e10cSrcweir 
226cdf0e10cSrcweir /*	Der Destruktor pr"uft per Assertion, ob noch Controller angemeldet
227cdf0e10cSrcweir 	sind.
228cdf0e10cSrcweir  */
229cdf0e10cSrcweir 
~SfxStateCache()230cdf0e10cSrcweir SfxStateCache::~SfxStateCache()
231cdf0e10cSrcweir {
232cdf0e10cSrcweir 	DBG_MEMTEST();
233cdf0e10cSrcweir 	DBG_DTOR(SfxStateCache,	0);
234cdf0e10cSrcweir     DBG_ASSERT( pController == 0 && pInternalController == 0, "es sind noch Controller angemeldet" );
235cdf0e10cSrcweir 	if ( !IsInvalidItem(pLastItem) )
236cdf0e10cSrcweir 		delete pLastItem;
237cdf0e10cSrcweir 	if ( pDispatch )
238cdf0e10cSrcweir 	{
239cdf0e10cSrcweir 		pDispatch->Release();
240cdf0e10cSrcweir 		pDispatch = NULL;
241cdf0e10cSrcweir 	}
242cdf0e10cSrcweir }
243cdf0e10cSrcweir 
244cdf0e10cSrcweir //--------------------------------------------------------------------
245cdf0e10cSrcweir // invalidates the cache (next request will force update)
Invalidate(sal_Bool bWithMsg)246cdf0e10cSrcweir void SfxStateCache::Invalidate( sal_Bool bWithMsg )
247cdf0e10cSrcweir {
248cdf0e10cSrcweir 	bCtrlDirty = sal_True;
249cdf0e10cSrcweir 	if ( bWithMsg )
250cdf0e10cSrcweir 	{
251cdf0e10cSrcweir 		bSlotDirty = sal_True;
252cdf0e10cSrcweir 		aSlotServ.SetSlot( 0 );
253cdf0e10cSrcweir 		if ( pDispatch )
254cdf0e10cSrcweir 		{
255cdf0e10cSrcweir 			pDispatch->Release();
256cdf0e10cSrcweir 			pDispatch = NULL;
257cdf0e10cSrcweir 		}
258cdf0e10cSrcweir 	}
259cdf0e10cSrcweir }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir //--------------------------------------------------------------------
262cdf0e10cSrcweir 
263cdf0e10cSrcweir // gets the corresponding function from the dispatcher or the cache
264cdf0e10cSrcweir 
GetSlotServer(SfxDispatcher & rDispat,const::com::sun::star::uno::Reference<::com::sun::star::frame::XDispatchProvider> & xProv)265cdf0e10cSrcweir const SfxSlotServer* SfxStateCache::GetSlotServer( SfxDispatcher &rDispat , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & xProv )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir 	DBG_MEMTEST();
268cdf0e10cSrcweir 	DBG_CHKTHIS(SfxStateCache, 0);
269cdf0e10cSrcweir 
270cdf0e10cSrcweir 	if ( bSlotDirty )
271cdf0e10cSrcweir 	{
272cdf0e10cSrcweir         // get the SlotServer; we need it for internal controllers anyway, but also in most cases
273cdf0e10cSrcweir         rDispat._FindServer( nId, aSlotServ, sal_False );
274cdf0e10cSrcweir 
275cdf0e10cSrcweir         DBG_ASSERT( !pDispatch, "Old Dispatch not removed!" );
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         // we don't need to check the dispatch provider if we only have an internal controller
278cdf0e10cSrcweir         if ( xProv.is() )
279cdf0e10cSrcweir         {
280cdf0e10cSrcweir             const SfxSlot* pSlot = aSlotServ.GetSlot();
281cdf0e10cSrcweir             if ( !pSlot )
282cdf0e10cSrcweir                 // get the slot - even if it is disabled on the dispatcher
283cdf0e10cSrcweir                 pSlot = SfxSlotPool::GetSlotPool( rDispat.GetFrame() ).GetSlot( nId );
284cdf0e10cSrcweir 
285cdf0e10cSrcweir             if ( !pSlot || !pSlot->pUnoName )
286cdf0e10cSrcweir             {
287cdf0e10cSrcweir                 bSlotDirty = sal_False;
288cdf0e10cSrcweir                 bCtrlDirty = sal_True;
289cdf0e10cSrcweir                 return aSlotServ.GetSlot()? &aSlotServ: 0;
290cdf0e10cSrcweir             }
291cdf0e10cSrcweir 
292cdf0e10cSrcweir             // create the dispatch URL from the slot data
293cdf0e10cSrcweir             ::com::sun::star::util::URL aURL;
294cdf0e10cSrcweir             ::rtl::OUString aCmd = DEFINE_CONST_UNICODE(".uno:");
295cdf0e10cSrcweir             aURL.Protocol = aCmd;
296cdf0e10cSrcweir             aURL.Path = ::rtl::OUString::createFromAscii( pSlot->GetUnoName() );
297cdf0e10cSrcweir             aCmd += aURL.Path;
298cdf0e10cSrcweir             aURL.Complete = aCmd;
299cdf0e10cSrcweir             aURL.Main = aCmd;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir             // try to get a dispatch object for this command
302cdf0e10cSrcweir             ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
303cdf0e10cSrcweir             if ( xDisp.is() )
304cdf0e10cSrcweir             {
305cdf0e10cSrcweir                 // test the dispatch object if it is just a wrapper for a SfxDispatcher
306cdf0e10cSrcweir 				::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
307cdf0e10cSrcweir                 SfxOfficeDispatch* pDisp = NULL;
308cdf0e10cSrcweir                 if ( xTunnel.is() )
309cdf0e10cSrcweir                 {
310cdf0e10cSrcweir                     sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
311cdf0e10cSrcweir                     pDisp = reinterpret_cast< SfxOfficeDispatch* >(sal::static_int_cast< sal_IntPtr >( nImplementation ));
312cdf0e10cSrcweir                 }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir                 if ( pDisp )
315cdf0e10cSrcweir                 {
316cdf0e10cSrcweir                     // The intercepting object is an SFX component
317cdf0e10cSrcweir                     // If this dispatch object does not use the wanted dispatcher or the AppDispatcher, it's treated like any other UNO component
318cdf0e10cSrcweir                     // (intercepting by internal dispatches)
319cdf0e10cSrcweir                     SfxDispatcher *pDispatcher = pDisp->GetDispatcher_Impl();
320cdf0e10cSrcweir 					if ( pDispatcher == &rDispat || pDispatcher == SFX_APP()->GetAppDispatcher_Impl() )
321cdf0e10cSrcweir 					{
322cdf0e10cSrcweir                         // so we can use it directly
323cdf0e10cSrcweir                         bSlotDirty = sal_False;
324cdf0e10cSrcweir                         bCtrlDirty = sal_True;
325cdf0e10cSrcweir                         return aSlotServ.GetSlot()? &aSlotServ: 0;
326cdf0e10cSrcweir                     }
327cdf0e10cSrcweir                 }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir                 // so the dispatch object isn't a SfxDispatcher wrapper or it is one, but it uses another dispatcher, but not rDispat
330cdf0e10cSrcweir                 pDispatch = new BindDispatch_Impl( xDisp, aURL, this, pSlot );
331cdf0e10cSrcweir                 pDispatch->acquire();
332cdf0e10cSrcweir 
333cdf0e10cSrcweir                 // flags must be set before adding StatusListener because the dispatch object will set the state
334cdf0e10cSrcweir                 bSlotDirty = sal_False;
335cdf0e10cSrcweir                 bCtrlDirty = sal_True;
336cdf0e10cSrcweir                 xDisp->addStatusListener( pDispatch, aURL );
337cdf0e10cSrcweir             }
338cdf0e10cSrcweir             else if ( rDispat.GetFrame() )
339cdf0e10cSrcweir             {
340cdf0e10cSrcweir                 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xFrameProv(
341cdf0e10cSrcweir                         rDispat.GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY );
342cdf0e10cSrcweir                 if ( xFrameProv != xProv )
343cdf0e10cSrcweir                     return GetSlotServer( rDispat, xFrameProv );
344cdf0e10cSrcweir             }
345cdf0e10cSrcweir         }
346cdf0e10cSrcweir 
347cdf0e10cSrcweir 		bSlotDirty = sal_False;
348cdf0e10cSrcweir 		bCtrlDirty = sal_True;
349cdf0e10cSrcweir 	}
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     // we *always* return a SlotServer (if there is one); but in case of an external dispatch we might not use it
352cdf0e10cSrcweir     // for the "real" (non internal) controllers
353cdf0e10cSrcweir     return aSlotServ.GetSlot()? &aSlotServ: 0;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir 
357cdf0e10cSrcweir //--------------------------------------------------------------------
358cdf0e10cSrcweir 
359cdf0e10cSrcweir // Status setzen in allen Controllern
360cdf0e10cSrcweir 
SetState(SfxItemState eState,const SfxPoolItem * pState,sal_Bool bMaybeDirty)361cdf0e10cSrcweir void SfxStateCache::SetState
362cdf0e10cSrcweir (
363cdf0e10cSrcweir 	SfxItemState		eState, 	// <SfxItemState> von 'pState'
364cdf0e10cSrcweir 	const SfxPoolItem*	pState,		// Status des Slots, ggf. 0 oder -1
365cdf0e10cSrcweir 	sal_Bool bMaybeDirty
366cdf0e10cSrcweir )
367cdf0e10cSrcweir 
368cdf0e10cSrcweir /*	[Beschreibung]
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 	Diese Methode verteilt die Status auf alle an dieser SID gebundenen
371cdf0e10cSrcweir 	<SfxControllerItem>s. Ist der Wert derselbe wie zuvor und wurde in-
372cdf0e10cSrcweir 	zwischen weder ein Controller angemeldet, noch ein Controller invalidiert,
373cdf0e10cSrcweir 	dann wird kein Wert weitergeleitet. Dadurch wird z.B. Flackern in
374cdf0e10cSrcweir 	ListBoxen vermieden.
375cdf0e10cSrcweir */
376cdf0e10cSrcweir 
377cdf0e10cSrcweir {
378cdf0e10cSrcweir //    if ( pDispatch )
379cdf0e10cSrcweir //        return;
380cdf0e10cSrcweir 	SetState_Impl( eState, pState, bMaybeDirty );
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir //--------------------------------------------------------------------
384cdf0e10cSrcweir 
SetVisibleState(sal_Bool bShow)385cdf0e10cSrcweir void SfxStateCache::SetVisibleState( sal_Bool bShow )
386cdf0e10cSrcweir {
387cdf0e10cSrcweir 	SfxItemState		eState( SFX_ITEM_AVAILABLE );
388cdf0e10cSrcweir 	const SfxPoolItem*	pState( NULL );
389cdf0e10cSrcweir 	sal_Bool            bNotify( sal_False );
390cdf0e10cSrcweir     sal_Bool            bDeleteItem( sal_False );
391cdf0e10cSrcweir 
392cdf0e10cSrcweir     if ( bShow != bItemVisible )
393cdf0e10cSrcweir     {
394cdf0e10cSrcweir         bItemVisible = bShow;
395cdf0e10cSrcweir         if ( bShow )
396cdf0e10cSrcweir         {
397cdf0e10cSrcweir             if ( IsInvalidItem(pLastItem) || ( pLastItem == NULL ))
398cdf0e10cSrcweir             {
399cdf0e10cSrcweir                 pState = new SfxVoidItem( nId );
400cdf0e10cSrcweir                 bDeleteItem = sal_True;
401cdf0e10cSrcweir             }
402cdf0e10cSrcweir             else
403cdf0e10cSrcweir                 pState = pLastItem;
404cdf0e10cSrcweir 
405cdf0e10cSrcweir             eState = eLastState;
406cdf0e10cSrcweir             bNotify = ( pState != 0 );
407cdf0e10cSrcweir         }
408cdf0e10cSrcweir         else
409cdf0e10cSrcweir         {
410cdf0e10cSrcweir             pState = new SfxVisibilityItem( nId, sal_False );
411cdf0e10cSrcweir             bDeleteItem = sal_True;
412cdf0e10cSrcweir         }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir         // Controller updaten
415cdf0e10cSrcweir         if ( !pDispatch && pController )
416cdf0e10cSrcweir         {
417cdf0e10cSrcweir             for ( SfxControllerItem *pCtrl = pController;
418cdf0e10cSrcweir                     pCtrl;
419cdf0e10cSrcweir                     pCtrl = pCtrl->GetItemLink() )
420cdf0e10cSrcweir                 pCtrl->StateChanged( nId, eState, pState );
421cdf0e10cSrcweir         }
422cdf0e10cSrcweir 
423cdf0e10cSrcweir         if ( pInternalController )
424cdf0e10cSrcweir             pInternalController->StateChanged( nId, eState, pState );
425cdf0e10cSrcweir 
426cdf0e10cSrcweir         if ( !bDeleteItem )
427cdf0e10cSrcweir             delete pState;
428cdf0e10cSrcweir     }
429cdf0e10cSrcweir }
430cdf0e10cSrcweir 
431cdf0e10cSrcweir //--------------------------------------------------------------------
432cdf0e10cSrcweir 
SetState_Impl(SfxItemState eState,const SfxPoolItem * pState,sal_Bool bMaybeDirty)433cdf0e10cSrcweir void SfxStateCache::SetState_Impl
434cdf0e10cSrcweir (
435cdf0e10cSrcweir 	SfxItemState		eState, 	// <SfxItemState> von 'pState'
436cdf0e10cSrcweir 	const SfxPoolItem*	pState,		// Status des Slots, ggf. 0 oder -1
437cdf0e10cSrcweir 	sal_Bool bMaybeDirty
438cdf0e10cSrcweir )
439cdf0e10cSrcweir {
440cdf0e10cSrcweir     (void)bMaybeDirty; //unused
441cdf0e10cSrcweir 	DBG_MEMTEST();
442cdf0e10cSrcweir 	DBG_CHKTHIS(SfxStateCache, 0);
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 	// wenn zwischen Enter- und LeaveRegistrations ein hartes Update kommt
445cdf0e10cSrcweir 	// k"onnen zwischenzeitlich auch Cached ohne Controller exisitieren
446cdf0e10cSrcweir     if ( !pController && !pInternalController )
447cdf0e10cSrcweir 		return;
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 	DBG_ASSERT( bMaybeDirty || !bSlotDirty, "setting state of dirty message" );
450cdf0e10cSrcweir //	DBG_ASSERT( bCtrlDirty || ( aSlotServ.GetSlot() && aSlotServ.GetSlot()->IsMode(SFX_SLOT_VOLATILE) ), ! Discussed with MBA
451cdf0e10cSrcweir //				"setting state of non dirty controller" );
452cdf0e10cSrcweir     DBG_ASSERT( SfxControllerItem::GetItemState(pState) == eState, "invalid SfxItemState" );
453cdf0e10cSrcweir 	DBG_PROFSTART(SfxStateCacheSetState);
454cdf0e10cSrcweir 
455cdf0e10cSrcweir 	// m"ussen die Controller "uberhaupt benachrichtigt werden?
456cdf0e10cSrcweir 	bool bNotify = bItemDirty;
457cdf0e10cSrcweir 	if ( !bItemDirty )
458cdf0e10cSrcweir 	{
459cdf0e10cSrcweir 		bool bBothAvailable = pLastItem && pState &&
460cdf0e10cSrcweir 					!IsInvalidItem(pState) && !IsInvalidItem(pLastItem);
461cdf0e10cSrcweir 		DBG_ASSERT( !bBothAvailable || pState != pLastItem, "setting state with own item" );
462cdf0e10cSrcweir 		if ( bBothAvailable )
463cdf0e10cSrcweir 			bNotify = pState->Type() != pLastItem->Type() ||
464cdf0e10cSrcweir 					  *pState != *pLastItem;
465cdf0e10cSrcweir 		else
466cdf0e10cSrcweir 			bNotify = ( pState != pLastItem ) || ( eState != eLastState );
467cdf0e10cSrcweir 	}
468cdf0e10cSrcweir 
469cdf0e10cSrcweir 	if ( bNotify )
470cdf0e10cSrcweir 	{
471cdf0e10cSrcweir 		// Controller updaten
472cdf0e10cSrcweir         if ( !pDispatch && pController )
473cdf0e10cSrcweir         {
474cdf0e10cSrcweir             for ( SfxControllerItem *pCtrl = pController;
475cdf0e10cSrcweir                 pCtrl;
476cdf0e10cSrcweir                 pCtrl = pCtrl->GetItemLink() )
477cdf0e10cSrcweir                 pCtrl->StateChanged( nId, eState, pState );
478cdf0e10cSrcweir         }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir         if ( pInternalController )
481cdf0e10cSrcweir             ((SfxDispatchController_Impl *)pInternalController)->StateChanged( nId, eState, pState, &aSlotServ );
482cdf0e10cSrcweir 
483cdf0e10cSrcweir 		// neuen Wert merken
484cdf0e10cSrcweir 		if ( !IsInvalidItem(pLastItem) )
485cdf0e10cSrcweir 			DELETEZ(pLastItem);
486cdf0e10cSrcweir 		if ( pState && !IsInvalidItem(pState) )
487cdf0e10cSrcweir 			pLastItem = pState->Clone();
488cdf0e10cSrcweir 		else
489cdf0e10cSrcweir 			pLastItem = 0;
490cdf0e10cSrcweir 		eLastState = eState;
491cdf0e10cSrcweir 		bItemDirty = sal_False;
492cdf0e10cSrcweir 	}
493cdf0e10cSrcweir 
494cdf0e10cSrcweir 	bCtrlDirty = sal_False;
495cdf0e10cSrcweir 	DBG_PROFSTOP(SfxStateCacheSetState);
496cdf0e10cSrcweir }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir 
499cdf0e10cSrcweir //--------------------------------------------------------------------
500cdf0e10cSrcweir 
501cdf0e10cSrcweir // alten Status in allen Controllern nochmal setzen
502cdf0e10cSrcweir 
SetCachedState(sal_Bool bAlways)503cdf0e10cSrcweir void SfxStateCache::SetCachedState( sal_Bool bAlways )
504cdf0e10cSrcweir {
505cdf0e10cSrcweir 	DBG_MEMTEST();
506cdf0e10cSrcweir 	DBG_CHKTHIS(SfxStateCache, 0);
507cdf0e10cSrcweir 	DBG_ASSERT(pController==NULL||pController->GetId()==nId, "Cache mit falschem ControllerItem" );
508cdf0e10cSrcweir 	DBG_PROFSTART(SfxStateCacheSetState);
509cdf0e10cSrcweir 
510cdf0e10cSrcweir 	// nur updaten wenn cached item vorhanden und auch verarbeitbar
511cdf0e10cSrcweir 	// (Wenn der State gesendet wird, mu\s sichergestellt sein, da\s ein
512cdf0e10cSrcweir 	// Slotserver vorhanden ist, s. SfxControllerItem::GetCoreMetric() )
513cdf0e10cSrcweir 	if ( bAlways || ( !bItemDirty && !bSlotDirty ) )
514cdf0e10cSrcweir 	{
515cdf0e10cSrcweir 		// Controller updaten
516cdf0e10cSrcweir         if ( !pDispatch && pController )
517cdf0e10cSrcweir         {
518cdf0e10cSrcweir             for ( SfxControllerItem *pCtrl = pController;
519cdf0e10cSrcweir                 pCtrl;
520cdf0e10cSrcweir                 pCtrl = pCtrl->GetItemLink() )
521cdf0e10cSrcweir                 pCtrl->StateChanged( nId, eLastState, pLastItem );
522cdf0e10cSrcweir         }
523cdf0e10cSrcweir 
524cdf0e10cSrcweir         if ( pInternalController )
525cdf0e10cSrcweir             ((SfxDispatchController_Impl *)pInternalController)->StateChanged( nId, eLastState, pLastItem, &aSlotServ );
526cdf0e10cSrcweir 
527cdf0e10cSrcweir 		// Controller sind jetzt ok
528cdf0e10cSrcweir 		bCtrlDirty = sal_True;
529cdf0e10cSrcweir 	}
530cdf0e10cSrcweir 
531cdf0e10cSrcweir 	DBG_PROFSTOP(SfxStateCacheSetState);
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 
535cdf0e10cSrcweir //--------------------------------------------------------------------
536cdf0e10cSrcweir 
537cdf0e10cSrcweir // FloatingWindows in allen Controls mit dieser Id zerstoeren
538cdf0e10cSrcweir 
DeleteFloatingWindows()539cdf0e10cSrcweir void SfxStateCache::DeleteFloatingWindows()
540cdf0e10cSrcweir {
541cdf0e10cSrcweir 	DBG_MEMTEST();
542cdf0e10cSrcweir 	DBG_CHKTHIS(SfxStateCache, 0);
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 	SfxControllerItem *pNextCtrl=0;
545cdf0e10cSrcweir 	for ( SfxControllerItem *pCtrl=pController; pCtrl; pCtrl=pNextCtrl )
546cdf0e10cSrcweir 	{
547cdf0e10cSrcweir 		DBG_TRACE((ByteString("pCtrl: ").Append(ByteString::CreateFromInt64((sal_uIntPtr)pCtrl))).GetBuffer());
548cdf0e10cSrcweir 		pNextCtrl = pCtrl->GetItemLink();
549cdf0e10cSrcweir 		pCtrl->DeleteFloatingWindow();
550cdf0e10cSrcweir 	}
551cdf0e10cSrcweir }
552cdf0e10cSrcweir 
GetDispatch() const553cdf0e10cSrcweir ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  SfxStateCache::GetDispatch() const
554cdf0e10cSrcweir {
555cdf0e10cSrcweir 	if ( pDispatch )
556cdf0e10cSrcweir 		return pDispatch->xDisp;
557cdf0e10cSrcweir 	return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
558cdf0e10cSrcweir }
559cdf0e10cSrcweir 
Dispatch(const SfxItemSet * pSet,sal_Bool bForceSynchron)560cdf0e10cSrcweir void SfxStateCache::Dispatch( const SfxItemSet* pSet, sal_Bool bForceSynchron )
561cdf0e10cSrcweir {
562cdf0e10cSrcweir 	// protect pDispatch against destruction in the call
563cdf0e10cSrcweir 	::com::sun::star::uno::Reference < ::com::sun::star::frame::XStatusListener > xKeepAlive( pDispatch );
564cdf0e10cSrcweir 	if ( pDispatch )
565cdf0e10cSrcweir 	{
566cdf0e10cSrcweir 		uno::Sequence < beans::PropertyValue > aArgs;
567cdf0e10cSrcweir 		if (pSet)
568cdf0e10cSrcweir 			TransformItems( nId, *pSet, aArgs );
569cdf0e10cSrcweir         pDispatch->Dispatch( aArgs, bForceSynchron );
570cdf0e10cSrcweir 	}
571cdf0e10cSrcweir }
572cdf0e10cSrcweir 
573cdf0e10cSrcweir 
574