1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/svapp.hxx>
22 #include <sfx2/viewfrm.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <svx/dataaccessdescriptor.hxx>
25 #include <comphelper/servicehelper.hxx>
26 #include <unodispatch.hxx>
27 #include <unobaseclass.hxx>
34 using namespace ::com::sun::star
;
37 static const char* cURLFormLetter
= ".uno:DataSourceBrowser/FormLetter";
38 static const char* cURLInsertContent
= ".uno:DataSourceBrowser/InsertContent";//data into fields
39 static const char* cURLInsertColumns
= ".uno:DataSourceBrowser/InsertColumns";//data into text
40 static const char* cURLDocumentDataSource
= ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document
41 static const sal_Char
* cInternalDBChangeNotification
= ".uno::Writer/DataSourceChanged";
43 SwXDispatchProviderInterceptor::SwXDispatchProviderInterceptor(SwView
& rVw
) :
46 uno::Reference
< frame::XFrame
> xUnoFrame
= m_pView
->GetViewFrame()->GetFrame().GetFrameInterface();
47 m_xIntercepted
= uno::Reference
< frame::XDispatchProviderInterception
>(xUnoFrame
, uno::UNO_QUERY
);
48 if(m_xIntercepted
.is())
51 m_xIntercepted
->registerDispatchProviderInterceptor((frame::XDispatchProviderInterceptor
*)this);
52 // this should make us the top-level dispatch-provider for the component, via a call to our
53 // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
54 uno::Reference
< lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
55 if (xInterceptedComponent
.is())
56 xInterceptedComponent
->addEventListener((lang::XEventListener
*)this);
61 SwXDispatchProviderInterceptor::~SwXDispatchProviderInterceptor()
65 uno::Reference
< frame::XDispatch
> SwXDispatchProviderInterceptor::queryDispatch(
66 const util::URL
& aURL
, const OUString
& aTargetFrameName
, sal_Int32 nSearchFlags
)
67 throw(uno::RuntimeException
)
69 DispatchMutexLock_Impl
aLock(*this);
70 uno::Reference
< frame::XDispatch
> xResult
;
71 // create some dispatch ...
72 if(m_pView
&& aURL
.Complete
.startsWith(".uno:DataSourceBrowser/"))
74 if(!aURL
.Complete
.compareToAscii(cURLFormLetter
) ||
75 !aURL
.Complete
.compareToAscii(cURLInsertContent
) ||
76 !aURL
.Complete
.compareToAscii(cURLInsertColumns
)||
77 !aURL
.Complete
.compareToAscii(cURLDocumentDataSource
))
80 m_xDispatch
= new SwXDispatch(*m_pView
);
81 xResult
= m_xDispatch
;
85 // ask our slave provider
86 if (!xResult
.is() && m_xSlaveDispatcher
.is())
87 xResult
= m_xSlaveDispatcher
->queryDispatch(aURL
, aTargetFrameName
, nSearchFlags
);
92 uno::Sequence
< uno::Reference
< frame::XDispatch
> > SwXDispatchProviderInterceptor::queryDispatches(
93 const uno::Sequence
< frame::DispatchDescriptor
>& aDescripts
) throw(uno::RuntimeException
)
95 DispatchMutexLock_Impl
aLock(*this);
96 uno::Sequence
< uno::Reference
< frame::XDispatch
> > aReturn(aDescripts
.getLength());
97 uno::Reference
< frame::XDispatch
>* pReturn
= aReturn
.getArray();
98 const frame::DispatchDescriptor
* pDescripts
= aDescripts
.getConstArray();
99 for (sal_Int16 i
=0; i
<aDescripts
.getLength(); ++i
, ++pReturn
, ++pDescripts
)
101 *pReturn
= queryDispatch(pDescripts
->FeatureURL
,
102 pDescripts
->FrameName
, pDescripts
->SearchFlags
);
107 uno::Reference
< frame::XDispatchProvider
> SwXDispatchProviderInterceptor::getSlaveDispatchProvider( )
108 throw(uno::RuntimeException
)
110 DispatchMutexLock_Impl
aLock(*this);
111 return m_xSlaveDispatcher
;
114 void SwXDispatchProviderInterceptor::setSlaveDispatchProvider(
115 const uno::Reference
< frame::XDispatchProvider
>& xNewDispatchProvider
) throw(uno::RuntimeException
)
117 DispatchMutexLock_Impl
aLock(*this);
118 m_xSlaveDispatcher
= xNewDispatchProvider
;
121 uno::Reference
< frame::XDispatchProvider
> SwXDispatchProviderInterceptor::getMasterDispatchProvider( )
122 throw(uno::RuntimeException
)
124 DispatchMutexLock_Impl
aLock(*this);
125 return m_xMasterDispatcher
;
128 void SwXDispatchProviderInterceptor::setMasterDispatchProvider(
129 const uno::Reference
< frame::XDispatchProvider
>& xNewSupplier
) throw(uno::RuntimeException
)
131 DispatchMutexLock_Impl
aLock(*this);
132 m_xMasterDispatcher
= xNewSupplier
;
135 void SwXDispatchProviderInterceptor::disposing( const lang::EventObject
& )
136 throw(uno::RuntimeException
)
138 DispatchMutexLock_Impl
aLock(*this);
139 if (m_xIntercepted
.is())
141 m_xIntercepted
->releaseDispatchProviderInterceptor((frame::XDispatchProviderInterceptor
*)this);
142 uno::Reference
< lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
143 if (xInterceptedComponent
.is())
144 xInterceptedComponent
->removeEventListener((lang::XEventListener
*)this);
147 m_xIntercepted
= NULL
;
152 class theSwXDispatchProviderInterceptorUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theSwXDispatchProviderInterceptorUnoTunnelId
> {};
155 const uno::Sequence
< sal_Int8
> & SwXDispatchProviderInterceptor::getUnoTunnelId()
157 return theSwXDispatchProviderInterceptorUnoTunnelId::get().getSeq();
160 sal_Int64
SwXDispatchProviderInterceptor::getSomething(
161 const uno::Sequence
< sal_Int8
>& aIdentifier
)
162 throw(uno::RuntimeException
)
164 if( aIdentifier
.getLength() == 16
165 && 0 == memcmp( getUnoTunnelId().getConstArray(),
166 aIdentifier
.getConstArray(), 16 ) )
168 return sal::static_int_cast
< sal_Int64
>( reinterpret_cast< sal_IntPtr
>( this ));
173 void SwXDispatchProviderInterceptor::Invalidate()
175 DispatchMutexLock_Impl
aLock(*this);
176 if (m_xIntercepted
.is())
178 m_xIntercepted
->releaseDispatchProviderInterceptor((frame::XDispatchProviderInterceptor
*)this);
179 uno::Reference
< lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
180 if (xInterceptedComponent
.is())
181 xInterceptedComponent
->removeEventListener((lang::XEventListener
*)this);
184 m_xIntercepted
= NULL
;
188 SwXDispatch::SwXDispatch(SwView
& rVw
) :
190 m_bOldEnable(sal_False
),
191 m_bListenerAdded(sal_False
)
195 SwXDispatch::~SwXDispatch()
197 if(m_bListenerAdded
&& m_pView
)
199 uno::Reference
<view::XSelectionSupplier
> xSupplier
= m_pView
->GetUNOObject();
200 uno::Reference
<view::XSelectionChangeListener
> xThis
= this;
201 xSupplier
->removeSelectionChangeListener(xThis
);
205 void SwXDispatch::dispatch(
206 const util::URL
& aURL
, const uno::Sequence
< beans::PropertyValue
>& aArgs
) throw(uno::RuntimeException
)
209 throw uno::RuntimeException();
210 SwWrtShell
& rSh
= m_pView
->GetWrtShell();
211 SwNewDBMgr
* pNewDBMgr
= rSh
.GetNewDBMgr();
212 if(!aURL
.Complete
.compareToAscii(cURLInsertContent
))
214 ::svx::ODataAccessDescriptor
aDescriptor(aArgs
);
215 SwMergeDescriptor
aMergeDesc( DBMGR_MERGE
, rSh
, aDescriptor
);
216 pNewDBMgr
->MergeNew(aMergeDesc
);
218 else if(!aURL
.Complete
.compareToAscii(cURLInsertColumns
))
220 pNewDBMgr
->InsertText(rSh
, aArgs
);
222 else if(!aURL
.Complete
.compareToAscii(cURLFormLetter
))
224 SfxUsrAnyItem
aDBProperties(FN_PARAM_DATABASE_PROPERTIES
, uno::makeAny(aArgs
));
225 m_pView
->GetViewFrame()->GetDispatcher()->Execute(
227 SFX_CALLMODE_ASYNCHRON
,
230 else if(!aURL
.Complete
.compareToAscii(cURLDocumentDataSource
))
232 OSL_FAIL("SwXDispatch::dispatch: this URL is not to be dispatched!");
234 else if(!aURL
.Complete
.compareToAscii(cInternalDBChangeNotification
))
236 frame::FeatureStateEvent aEvent
;
237 aEvent
.IsEnabled
= sal_True
;
238 aEvent
.Source
= *(cppu::OWeakObject
*)this;
240 const SwDBData
& rData
= m_pView
->GetWrtShell().GetDBDesc();
241 ::svx::ODataAccessDescriptor aDescriptor
;
242 aDescriptor
.setDataSource(rData
.sDataSource
);
243 aDescriptor
[::svx::daCommand
] <<= rData
.sCommand
;
244 aDescriptor
[::svx::daCommandType
] <<= rData
.nCommandType
;
246 aEvent
.State
<<= aDescriptor
.createPropertyValueSequence();
247 aEvent
.IsEnabled
= !rData
.sDataSource
.isEmpty();
249 StatusListenerList::iterator aListIter
= m_aListenerList
.begin();
250 for(aListIter
= m_aListenerList
.begin(); aListIter
!= m_aListenerList
.end(); ++aListIter
)
252 StatusStruct_Impl aStatus
= *aListIter
;
253 if(!aStatus
.aURL
.Complete
.compareToAscii(cURLDocumentDataSource
))
255 aEvent
.FeatureURL
= aStatus
.aURL
;
256 aStatus
.xListener
->statusChanged( aEvent
);
261 throw uno::RuntimeException();
265 void SwXDispatch::addStatusListener(
266 const uno::Reference
< frame::XStatusListener
>& xControl
, const util::URL
& aURL
) throw(uno::RuntimeException
)
269 throw uno::RuntimeException();
270 ShellModes eMode
= m_pView
->GetShellMode();
271 sal_Bool bEnable
= SHELL_MODE_TEXT
== eMode
||
272 SHELL_MODE_LIST_TEXT
== eMode
||
273 SHELL_MODE_TABLE_TEXT
== eMode
||
274 SHELL_MODE_TABLE_LIST_TEXT
== eMode
;
276 m_bOldEnable
= bEnable
;
277 frame::FeatureStateEvent aEvent
;
278 aEvent
.IsEnabled
= bEnable
;
279 aEvent
.Source
= *(cppu::OWeakObject
*)this;
280 aEvent
.FeatureURL
= aURL
;
282 // one of the URLs requires a special state ....
283 if (!aURL
.Complete
.compareToAscii(cURLDocumentDataSource
))
285 const SwDBData
& rData
= m_pView
->GetWrtShell().GetDBDesc();
287 ::svx::ODataAccessDescriptor aDescriptor
;
288 aDescriptor
.setDataSource(rData
.sDataSource
);
289 aDescriptor
[::svx::daCommand
] <<= rData
.sCommand
;
290 aDescriptor
[::svx::daCommandType
] <<= rData
.nCommandType
;
292 aEvent
.State
<<= aDescriptor
.createPropertyValueSequence();
293 aEvent
.IsEnabled
= !rData
.sDataSource
.isEmpty();
297 xControl
->statusChanged( aEvent
);
299 StatusListenerList::iterator aListIter
= m_aListenerList
.begin();
300 StatusStruct_Impl aStatus
;
301 aStatus
.xListener
= xControl
;
303 m_aListenerList
.insert(aListIter
, aStatus
);
305 if(!m_bListenerAdded
)
307 uno::Reference
<view::XSelectionSupplier
> xSupplier
= m_pView
->GetUNOObject();
308 uno::Reference
<view::XSelectionChangeListener
> xThis
= this;
309 xSupplier
->addSelectionChangeListener(xThis
);
310 m_bListenerAdded
= sal_True
;
314 void SwXDispatch::removeStatusListener(
315 const uno::Reference
< frame::XStatusListener
>& xControl
, const util::URL
& ) throw(uno::RuntimeException
)
317 StatusListenerList::iterator aListIter
= m_aListenerList
.begin();
318 for(aListIter
= m_aListenerList
.begin(); aListIter
!= m_aListenerList
.end(); ++aListIter
)
320 StatusStruct_Impl aStatus
= *aListIter
;
321 if(aStatus
.xListener
.get() == xControl
.get())
323 m_aListenerList
.erase(aListIter
);
327 if(m_aListenerList
.empty() && m_pView
)
329 uno::Reference
<view::XSelectionSupplier
> xSupplier
= m_pView
->GetUNOObject();
330 uno::Reference
<view::XSelectionChangeListener
> xThis
= this;
331 xSupplier
->removeSelectionChangeListener(xThis
);
332 m_bListenerAdded
= sal_False
;
336 void SwXDispatch::selectionChanged( const lang::EventObject
& ) throw(uno::RuntimeException
)
338 ShellModes eMode
= m_pView
->GetShellMode();
339 sal_Bool bEnable
= SHELL_MODE_TEXT
== eMode
||
340 SHELL_MODE_LIST_TEXT
== eMode
||
341 SHELL_MODE_TABLE_TEXT
== eMode
||
342 SHELL_MODE_TABLE_LIST_TEXT
== eMode
;
343 if(bEnable
!= m_bOldEnable
)
345 m_bOldEnable
= bEnable
;
346 frame::FeatureStateEvent aEvent
;
347 aEvent
.IsEnabled
= bEnable
;
348 aEvent
.Source
= *(cppu::OWeakObject
*)this;
350 StatusListenerList::iterator aListIter
= m_aListenerList
.begin();
351 for(aListIter
= m_aListenerList
.begin(); aListIter
!= m_aListenerList
.end(); ++aListIter
)
353 StatusStruct_Impl aStatus
= *aListIter
;
354 aEvent
.FeatureURL
= aStatus
.aURL
;
355 if (0 != aStatus
.aURL
.Complete
.compareToAscii(cURLDocumentDataSource
))
356 // the document's data source does not depend on the selection, so it's state does not change here
357 aStatus
.xListener
->statusChanged( aEvent
);
362 void SwXDispatch::disposing( const lang::EventObject
& rSource
) throw(uno::RuntimeException
)
364 uno::Reference
<view::XSelectionSupplier
> xSupplier(rSource
.Source
, uno::UNO_QUERY
);
365 uno::Reference
<view::XSelectionChangeListener
> xThis
= this;
366 xSupplier
->removeSelectionChangeListener(xThis
);
367 m_bListenerAdded
= sal_False
;
369 lang::EventObject aObject
;
370 aObject
.Source
= (cppu::OWeakObject
*)this;
371 StatusListenerList::iterator aListIter
= m_aListenerList
.begin();
372 for(; aListIter
!= m_aListenerList
.end(); ++aListIter
)
374 StatusStruct_Impl aStatus
= *aListIter
;
375 aStatus
.xListener
->disposing(aObject
);
380 const sal_Char
* SwXDispatch::GetDBChangeURL()
382 return cInternalDBChangeNotification
;
385 SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::DispatchMutexLock_Impl(
386 SwXDispatchProviderInterceptor
& ) :
387 aGuard(Application::GetSolarMutex())
391 SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::~DispatchMutexLock_Impl()
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */