xref: /trunk/main/sfx2/source/appl/helpinterceptor.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 
31 #include "helpinterceptor.hxx"
32 #include "helpdispatch.hxx"
33 #include "newhelp.hxx"
34 #include <sfx2/sfxuno.hxx>
35 #include <tools/urlobj.hxx>
36 #include <tools/debug.hxx>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
39 #include <cppuhelper/interfacecontainer.h>
40 #include <vcl/window.hxx>
41 #include <limits.h>
42 
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::frame;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::util;
47 using namespace ::com::sun::star::lang;
48 
49 extern void AppendConfigToken_Impl( String& rURL, sal_Bool bQuestionMark ); // sfxhelp.cxx
50 
51 // class HelpInterceptor_Impl --------------------------------------------
52 
53 HelpInterceptor_Impl::HelpInterceptor_Impl() :
54 
55     m_pHistory  ( NULL ),
56     m_nCurPos   ( 0 )
57 
58 {
59 }
60 
61 // -----------------------------------------------------------------------
62 
63 HelpInterceptor_Impl::~HelpInterceptor_Impl()
64 {
65     for ( sal_uInt16 i = 0; m_pHistory && i < m_pHistory->Count(); ++i )
66         delete m_pHistory->GetObject(i);
67     delete m_pHistory;
68 }
69 
70 // -----------------------------------------------------------------------
71 
72 void HelpInterceptor_Impl::addURL( const String& rURL )
73 {
74   if ( !m_pHistory )
75         m_pHistory = new HelpHistoryList_Impl;
76     sal_uIntPtr nCount = m_pHistory->Count();
77     if ( nCount && m_nCurPos < ( nCount - 1 ) )
78     {
79         for ( sal_uIntPtr i = nCount - 1; i > m_nCurPos; i-- )
80             delete m_pHistory->Remove(i);
81     }
82     Reference<XFrame> xFrame(m_xIntercepted, UNO_QUERY);
83     Reference<XController> xController;
84     if(xFrame.is())
85         xController = xFrame->getController();
86     Any aViewData;
87     if(xController.is() && m_pHistory->Count())
88     {
89         m_pHistory->GetObject(m_nCurPos)->aViewData = xController->getViewData();
90     }
91 
92     m_aCurrentURL = rURL;
93     Any aEmptyViewData;
94     m_pHistory->Insert( new HelpHistoryEntry_Impl( rURL, aEmptyViewData ), LIST_APPEND );
95     m_nCurPos = m_pHistory->Count() - 1;
96 // TODO ?
97     if ( m_xListener.is() )
98     {
99         ::com::sun::star::frame::FeatureStateEvent aEvent;
100         URL aURL;
101         aURL.Complete = rURL;
102         aEvent.FeatureURL = aURL;
103         aEvent.Source = (::com::sun::star::frame::XDispatch*)this;
104         m_xListener->statusChanged( aEvent );
105     }
106 
107     m_pWindow->UpdateToolbox();
108 }
109 
110 // -----------------------------------------------------------------------
111 
112 void HelpInterceptor_Impl::setInterception( Reference< XFrame > xFrame )
113 {
114     m_xIntercepted = Reference< XDispatchProviderInterception>( xFrame, UNO_QUERY );
115 
116     if ( m_xIntercepted.is() )
117         m_xIntercepted->registerDispatchProviderInterceptor( (XDispatchProviderInterceptor*)this );
118 }
119 
120 // -----------------------------------------------------------------------
121 
122 void HelpInterceptor_Impl::SetStartURL( const String& rURL )
123 {
124     DBG_ASSERT( !m_pHistory, "invalid history" );
125     if ( !m_pHistory )
126     {
127         m_pHistory = new HelpHistoryList_Impl;
128         Any aEmptyViewData;
129         m_pHistory->Insert( new HelpHistoryEntry_Impl( rURL, aEmptyViewData ), ((sal_uIntPtr)0x0) );
130         m_nCurPos = m_pHistory->Count() - 1;
131 
132         m_pWindow->UpdateToolbox();
133     }
134     m_aCurrentURL = rURL;
135 }
136 
137 sal_Bool HelpInterceptor_Impl::HasHistoryPred() const
138 {
139     return m_pHistory && ( m_nCurPos > 0 );
140 }
141 
142 sal_Bool HelpInterceptor_Impl::HasHistorySucc() const
143 {
144     return m_pHistory && ( m_nCurPos < ( m_pHistory->Count() - 1 ) );
145 }
146 
147 
148 // -----------------------------------------------------------------------
149 // XDispatchProvider
150 
151 Reference< XDispatch > SAL_CALL HelpInterceptor_Impl::queryDispatch(
152 
153     const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags )
154 
155     throw( RuntimeException )
156 
157 {
158     Reference< XDispatch > xResult;
159     if ( m_xSlaveDispatcher.is() )
160         xResult = m_xSlaveDispatcher->queryDispatch( aURL, aTargetFrameName, nSearchFlags );
161 
162     // INetURLObject aObj( aURL.Complete );
163     // sal_Bool bHelpURL = ( aObj.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP );
164     sal_Bool bHelpURL = aURL.Complete.toAsciiLowerCase().match(rtl::OUString::createFromAscii("vnd.sun.star.help"),0);
165 
166     if ( bHelpURL )
167     {
168         DBG_ASSERT( xResult.is(), "invalid dispatch" );
169         HelpDispatch_Impl* pHelpDispatch = new HelpDispatch_Impl( *this, xResult );
170         xResult = Reference< XDispatch >( static_cast< ::cppu::OWeakObject* >(pHelpDispatch), UNO_QUERY );
171     }
172 
173     return xResult;
174 }
175 
176 // -----------------------------------------------------------------------
177 
178 Sequence < Reference < XDispatch > > SAL_CALL HelpInterceptor_Impl::queryDispatches(
179 
180     const Sequence< DispatchDescriptor >& aDescripts )
181 
182     throw( RuntimeException )
183 
184 {
185     Sequence< Reference< XDispatch > > aReturn( aDescripts.getLength() );
186     Reference< XDispatch >* pReturn = aReturn.getArray();
187     const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
188     for ( sal_Int16 i = 0; i < aDescripts.getLength(); ++i, ++pReturn, ++pDescripts )
189     {
190         *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
191     }
192     return aReturn;
193 }
194 
195 // -----------------------------------------------------------------------
196 // XDispatchProviderInterceptor
197 
198 Reference< XDispatchProvider > SAL_CALL HelpInterceptor_Impl::getSlaveDispatchProvider()
199 
200     throw( RuntimeException )
201 
202 {
203     return m_xSlaveDispatcher;
204 }
205 
206 // -----------------------------------------------------------------------
207 
208 void SAL_CALL HelpInterceptor_Impl::setSlaveDispatchProvider( const Reference< XDispatchProvider >& xNewSlave )
209 
210     throw( RuntimeException )
211 
212 {
213     m_xSlaveDispatcher = xNewSlave;
214 }
215 
216 // -----------------------------------------------------------------------
217 
218 Reference< XDispatchProvider > SAL_CALL HelpInterceptor_Impl::getMasterDispatchProvider()
219 
220     throw( RuntimeException )
221 
222 {
223     return m_xMasterDispatcher;
224 }
225 
226 // -----------------------------------------------------------------------
227 
228 void SAL_CALL HelpInterceptor_Impl::setMasterDispatchProvider( const Reference< XDispatchProvider >& xNewMaster )
229 
230     throw( RuntimeException )
231 
232 {
233     m_xMasterDispatcher = xNewMaster;
234 }
235 
236 // -----------------------------------------------------------------------
237 // XInterceptorInfo
238 
239 Sequence< ::rtl::OUString > SAL_CALL HelpInterceptor_Impl::getInterceptedURLs()
240 
241     throw( RuntimeException )
242 
243 {
244     Sequence< ::rtl::OUString > aURLList( 1 );
245     aURLList[0] = DEFINE_CONST_UNICODE("vnd.sun.star.help://*");
246     return aURLList;;
247 }
248 
249 // -----------------------------------------------------------------------
250 // XDispatch
251 
252 void SAL_CALL HelpInterceptor_Impl::dispatch(
253     const URL& aURL, const Sequence< ::com::sun::star::beans::PropertyValue >& ) throw( RuntimeException )
254 {
255     sal_Bool bBack = ( String( DEFINE_CONST_UNICODE(".uno:Backward") ) == String( aURL.Complete ) );
256     if ( bBack || String( DEFINE_CONST_UNICODE(".uno:Forward") ) == String( aURL.Complete ) )
257     {
258         if ( m_pHistory )
259         {
260             if(m_pHistory->Count() > m_nCurPos)
261             {
262                 Reference<XFrame> xFrame(m_xIntercepted, UNO_QUERY);
263                 Reference<XController> xController;
264                 if(xFrame.is())
265                     xController = xFrame->getController();
266                 if(xController.is())
267                 {
268                     m_pHistory->GetObject(m_nCurPos)->aViewData = xController->getViewData();
269                 }
270             }
271 
272             sal_uIntPtr nPos = ( bBack && m_nCurPos > 0 ) ? --m_nCurPos
273                                                     : ( !bBack && m_nCurPos < m_pHistory->Count() - 1 )
274                                                     ? ++m_nCurPos
275                                                     : ULONG_MAX;
276 
277             if ( nPos < ULONG_MAX )
278             {
279                 HelpHistoryEntry_Impl* pEntry = m_pHistory->GetObject( nPos );
280                 if ( pEntry )
281                     m_pWindow->loadHelpContent(pEntry->aURL, sal_False); // false => dont add item to history again!
282             }
283 
284             m_pWindow->UpdateToolbox();
285         }
286     }
287 }
288 
289 // -----------------------------------------------------------------------
290 
291 void SAL_CALL HelpInterceptor_Impl::addStatusListener(
292     const Reference< XStatusListener >& xControl, const URL& ) throw( RuntimeException )
293 {
294     DBG_ASSERT( !m_xListener.is(), "listener already exists" );
295     m_xListener = xControl;
296 }
297 
298 // -----------------------------------------------------------------------
299 
300 void SAL_CALL HelpInterceptor_Impl::removeStatusListener(
301     const Reference< XStatusListener >&, const URL&) throw( RuntimeException )
302 {
303     m_xListener = 0;
304 }
305 
306 // HelpListener_Impl -----------------------------------------------------
307 
308 HelpListener_Impl::HelpListener_Impl( HelpInterceptor_Impl* pInter )
309 {
310     pInterceptor = pInter;
311     pInterceptor->addStatusListener( this, ::com::sun::star::util::URL() );
312 }
313 
314 // -----------------------------------------------------------------------
315 
316 void SAL_CALL HelpListener_Impl::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event )
317 
318     throw( ::com::sun::star::uno::RuntimeException )
319 
320 {
321     INetURLObject aObj( Event.FeatureURL.Complete );
322     aFactory = aObj.GetHost();
323     aChangeLink.Call( this );
324 }
325 
326 // -----------------------------------------------------------------------
327 
328 void SAL_CALL HelpListener_Impl::disposing( const ::com::sun::star::lang::EventObject& )
329 
330     throw( ::com::sun::star::uno::RuntimeException )
331 
332 {
333     pInterceptor->removeStatusListener( this, ::com::sun::star::util::URL() );
334     pInterceptor = NULL;
335 }
336 /*-- 05.09.2002 12:17:59---------------------------------------------------
337 
338   -----------------------------------------------------------------------*/
339 HelpStatusListener_Impl::HelpStatusListener_Impl(
340         Reference < XDispatch > aDispatch, URL& rURL)
341 {
342     aDispatch->addStatusListener(this, rURL);
343 }
344 /*-- 05.09.2002 12:17:59---------------------------------------------------
345 
346   -----------------------------------------------------------------------*/
347 HelpStatusListener_Impl::~HelpStatusListener_Impl()
348 {
349     if(xDispatch.is())
350         xDispatch->removeStatusListener(this, com::sun::star::util::URL());
351 }
352 /*-- 05.09.2002 12:17:59---------------------------------------------------
353 
354   -----------------------------------------------------------------------*/
355 void HelpStatusListener_Impl::statusChanged(
356     const FeatureStateEvent& rEvent ) throw( RuntimeException )
357 {
358     aStateEvent = rEvent;
359 }
360 /*-- 05.09.2002 12:18:00---------------------------------------------------
361 
362   -----------------------------------------------------------------------*/
363 void HelpStatusListener_Impl::disposing( const EventObject& ) throw( RuntimeException )
364 {
365     xDispatch->removeStatusListener(this, com::sun::star::util::URL());
366     xDispatch = 0;
367 }
368