1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helpagentdispatcher.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 #include <dispatch/helpagentdispatcher.hxx>
34 #include <threadhelp/readguard.hxx>
35 #include <threadhelp/writeguard.hxx>
36 #include <com/sun/star/awt/XWindow2.hpp>
37 #include <com/sun/star/awt/PosSize.hpp>
38 #include <com/sun/star/awt/Size.hpp>
39 #include <com/sun/star/awt/Rectangle.hpp>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <svtools/helpopt.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/help.hxx>
45 namespace css
= ::com::sun::star
;
47 //........................................................................
51 //-----------------------------------------------
52 DEFINE_XINTERFACE_4(HelpAgentDispatcher
,
54 DIRECT_INTERFACE (css::lang::XTypeProvider
),
55 DIRECT_INTERFACE (css::frame::XDispatch
),
56 DIRECT_INTERFACE (css::awt::XWindowListener
),
57 DIRECT_INTERFACE (css::lang::XEventListener
))
59 //-----------------------------------------------
60 DEFINE_XTYPEPROVIDER_2(HelpAgentDispatcher
,
61 css::lang::XTypeProvider
,
62 css::frame::XDispatch
)
64 //--------------------------------------------------------------------
65 HelpAgentDispatcher::HelpAgentDispatcher( const css::uno::Reference
< css::frame::XFrame
>& xParentFrame
)
66 : ThreadHelpBase (&Application::GetSolarMutex())
68 , m_xContainerWindow( )
73 // It's required that this class has to be contructed with a valid frame.
74 // And "valid" means: the frame must already bound to a valid container window.
75 m_xContainerWindow
= xParentFrame
->getContainerWindow();
78 //--------------------------------------------------------------------
79 HelpAgentDispatcher::~HelpAgentDispatcher()
82 implts_ignoreCurrentURL();
84 // Needed ... because it was create as "new VCLWindow()" ! Such windows must be disposed explicitly.
85 css::uno::Reference
< css::lang::XComponent
> xAgentWindow(m_xAgentWindow
, css::uno::UNO_QUERY
);
86 if (xAgentWindow
.is())
87 xAgentWindow
->dispose();
90 //--------------------------------------------------------------------
91 void SAL_CALL
HelpAgentDispatcher::dispatch(const css::util::URL
& aURL
,
92 const css::uno::Sequence
< css::beans::PropertyValue
>&)
93 throw(css::uno::RuntimeException
)
95 // silently drop the request if the new URL was marked to be ignored next time.
96 sal_Int32 nAllowedToIgnore
= SvtHelpOptions().getAgentIgnoreURLCounter(aURL
.Complete
);
97 if (nAllowedToIgnore
< 1)
100 // stop the expiration timer for the old URL
101 // The timer will add the old URL to the list of ignorable URLs.
102 // So m_sCurrentURL must be set AFTER the timer was stopped !!!
106 WriteGuard
aWriteLock(m_aLock
);
107 m_sCurrentURL
= aURL
.Complete
;
111 // start the expiration timer for the new URL
114 // make sure the agent window is shown
115 implts_showAgentWindow();
118 //--------------------------------------------------------------------
119 void SAL_CALL
HelpAgentDispatcher::addStatusListener(const css::uno::Reference
< css::frame::XStatusListener
>&,
120 const css::util::URL
&)
121 throw(css::uno::RuntimeException
)
123 // no status available
126 //--------------------------------------------------------------------
127 void SAL_CALL
HelpAgentDispatcher::removeStatusListener(const css::uno::Reference
< css::frame::XStatusListener
>&,
128 const css::util::URL
&)
129 throw(css::uno::RuntimeException
)
131 // no status available
134 //--------------------------------------------------------------------
135 void SAL_CALL
HelpAgentDispatcher::windowResized(const css::awt::WindowEvent
&)
136 throw(css::uno::RuntimeException
)
138 implts_positionAgentWindow();
141 //--------------------------------------------------------------------
142 void SAL_CALL
HelpAgentDispatcher::windowMoved(const css::awt::WindowEvent
&)
143 throw(css::uno::RuntimeException
)
145 implts_positionAgentWindow();
148 //--------------------------------------------------------------------
149 void SAL_CALL
HelpAgentDispatcher::windowShown(const css::lang::EventObject
&)
150 throw(css::uno::RuntimeException
)
152 implts_showAgentWindow();
155 //--------------------------------------------------------------------
156 void SAL_CALL
HelpAgentDispatcher::windowHidden(const css::lang::EventObject
&)
157 throw(css::uno::RuntimeException
)
159 implts_hideAgentWindow();
162 //--------------------------------------------------------------------
163 void SAL_CALL
HelpAgentDispatcher::disposing(const css::lang::EventObject
& aEvent
)
164 throw(css::uno::RuntimeException
)
167 WriteGuard
aWriteLock(m_aLock
);
169 // Already disposed ?!
170 if (! m_xContainerWindow
.is())
172 // Wrong broadcaster ?!
173 if (aEvent
.Source
!= m_xContainerWindow
)
176 css::uno::Reference
< css::uno::XInterface
> xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch
* >(this), css::uno::UNO_QUERY_THROW
);
183 implts_hideAgentWindow();
184 implts_ignoreCurrentURL();
188 m_xContainerWindow
.clear();
189 css::uno::Reference
< css::lang::XComponent
> xAgentWindow(m_xAgentWindow
, css::uno::UNO_QUERY
);
190 m_xAgentWindow
.clear();
194 // Needed ... because it was create as "new VCLWindow()" ! Such windows must be disposed explicitly.
195 if (xAgentWindow
.is())
196 xAgentWindow
->dispose();
199 //--------------------------------------------------------------------
200 void HelpAgentDispatcher::helpRequested()
203 implts_hideAgentWindow();
204 implts_acceptCurrentURL();
207 //-----------------------------------------------
208 void HelpAgentDispatcher::closeAgent()
211 implts_hideAgentWindow();
212 implts_ignoreCurrentURL();
215 //--------------------------------------------------------------------
216 void HelpAgentDispatcher::implts_acceptCurrentURL()
219 WriteGuard
aWriteLock(m_aLock
);
221 ::rtl::OUString sAcceptedURL
= m_sCurrentURL
;
222 m_sCurrentURL
= ::rtl::OUString();
227 // We must make sure that this URL isnt marked as ignored by the user.
228 // Otherwhise the user wont see the corresponding help content in the future.
229 SvtHelpOptions().resetAgentIgnoreURLCounter(sAcceptedURL
);
231 // show the right help content
234 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
235 Help
* pHelp
= Application::GetHelp();
237 pHelp
->Start(sAcceptedURL
, NULL
);
242 //--------------------------------------------------------------------
243 void HelpAgentDispatcher::implts_ignoreCurrentURL()
246 WriteGuard
aWriteLock(m_aLock
);
248 ::rtl::OUString sIgnoredURL
= m_sCurrentURL
;
249 m_sCurrentURL
= ::rtl::OUString();
254 if (sIgnoredURL
.getLength())
255 SvtHelpOptions().decAgentIgnoreURLCounter(sIgnoredURL
);
258 //--------------------------------------------------------------------
259 void HelpAgentDispatcher::implts_stopTimer()
262 WriteGuard
aWriteLock(m_aLock
);
268 // Timer access needs no "own lock" ! It lives if we live ...
269 // But it requires locking of the solar mutex ... because it's a vcl based timer.
271 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
272 if (! m_aTimer
.IsActive())
279 //--------------------------------------------------------------------
280 void HelpAgentDispatcher::implts_startTimer()
283 // Timer access needs no "own lock" ! It lives if we live ...
284 // But it requires locking of the solar mutex ... because it's a vcl based timer.
286 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
287 if (m_aTimer
.IsActive())
293 // Timer uses pointer to this help agent dispatcher ...
294 // But normaly we are ref counted. So we must make sure that this
295 // dispatcher isnt killed during the timer runs .-)
296 WriteGuard
aWriteLock(m_aLock
);
297 m_xSelfHold
= css::uno::Reference
< css::uno::XInterface
>(static_cast< css::frame::XDispatch
* >(this), css::uno::UNO_QUERY_THROW
);
301 sal_Int32 nTime
= SvtHelpOptions().GetHelpAgentTimeoutPeriod();
304 // Timer access needs no "own lock" ! It lives if we live ...
305 // But it requires locking of the solar mutex ... because it's a vcl based timer.
307 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
308 m_aTimer
.SetTimeout(nTime
*1000); // sec => ms !
313 //-----------------------------------------------
314 IMPL_LINK(HelpAgentDispatcher
, implts_timerExpired
, void*,)
316 // This method is called by using a pointer to us.
317 // But we must be aware that we can be destroyed hardly
318 // if our uno reference will be gone!
319 // => Hold this object alive till this method finish its work.
321 WriteGuard
aWriteLock(m_aLock
);
322 css::uno::Reference
< css::uno::XInterface
> xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch
* >(this), css::uno::UNO_QUERY_THROW
);
327 implts_hideAgentWindow();
328 implts_ignoreCurrentURL();
333 //--------------------------------------------------------------------
334 void HelpAgentDispatcher::implts_showAgentWindow()
337 ReadGuard
aReadLock(m_aLock
);
338 css::uno::Reference
< css::awt::XWindow2
> xContainerWindow(m_xContainerWindow
, css::uno::UNO_QUERY_THROW
);
342 css::uno::Reference
< css::awt::XWindow
> xAgentWindow
= implts_ensureAgentWindow();
345 (xContainerWindow
.is() ) &&
346 (xAgentWindow
.is() ) &&
347 (xContainerWindow
->isVisible())
350 // make sure that agent window resists at the right place .-)
351 implts_positionAgentWindow();
352 xAgentWindow
->setVisible(sal_True
);
356 //--------------------------------------------------------------------
357 void HelpAgentDispatcher::implts_hideAgentWindow()
359 css::uno::Reference
< css::awt::XWindow
> xAgentWindow
= implts_ensureAgentWindow();
360 if (xAgentWindow
.is())
361 xAgentWindow
->setVisible(sal_False
);
364 //--------------------------------------------------------------------
365 void HelpAgentDispatcher::implts_positionAgentWindow()
368 ReadGuard
aReadLock(m_aLock
);
369 css::uno::Reference
< css::awt::XWindow
> xContainerWindow
= m_xContainerWindow
;
373 css::uno::Reference
< css::awt::XWindow
> xAgentWindow
= implts_ensureAgentWindow();
375 (! xContainerWindow
.is()) ||
376 (! xAgentWindow
.is() )
380 ::svt::HelpAgentWindow
* pAgentWindow
= (::svt::HelpAgentWindow
*)VCLUnoHelper::GetWindow(xAgentWindow
);
381 const css::awt::Rectangle aContainerSize
= xContainerWindow
->getPosSize();
382 const Size aAgentSize
= pAgentWindow
->getPreferredSizePixel();
384 sal_Int32 nW
= aAgentSize
.Width() ;
385 sal_Int32 nH
= aAgentSize
.Height();
392 sal_Int32 nX
= aContainerSize
.Width
- nW
;
393 sal_Int32 nY
= aContainerSize
.Height
- nH
;
395 // TODO: use a surrogate if the container window is too small to contain the full-sized agent window
396 xAgentWindow
->setPosSize(nX
, nY
, nW
, nH
, css::awt::PosSize::POSSIZE
);
399 //--------------------------------------------------------------------
400 css::uno::Reference
< css::awt::XWindow
> HelpAgentDispatcher::implts_ensureAgentWindow()
403 ReadGuard
aReadLock(m_aLock
);
404 if (m_xAgentWindow
.is())
405 return m_xAgentWindow
;
406 css::uno::Reference
< css::awt::XWindow
> xContainerWindow
= m_xContainerWindow
;
410 if (!xContainerWindow
.is())
411 return css::uno::Reference
< css::awt::XWindow
>();
413 ::svt::HelpAgentWindow
* pAgentWindow
= 0;
416 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
417 // create the agent window
418 Window
* pContainerWindow
= VCLUnoHelper::GetWindow(xContainerWindow
);
419 pAgentWindow
= new ::svt::HelpAgentWindow(pContainerWindow
);
420 pAgentWindow
->setCallback(this);
425 WriteGuard
aWriteLock(m_aLock
);
426 m_xAgentWindow
= VCLUnoHelper::GetInterface(pAgentWindow
);
427 css::uno::Reference
< css::awt::XWindow
> xAgentWindow
= m_xAgentWindow
;
431 // add as window listener to the container window so we can maintain the property position of the agent window
432 xContainerWindow
->addWindowListener(this);
436 ::vos::OGuard
aSolarLock(Application::GetSolarMutex());
437 // establish callback for our internal used timer.
438 // Note: Its only active, if the timer will be started ...
439 m_aTimer
.SetTimeoutHdl(LINK(this, HelpAgentDispatcher
, implts_timerExpired
));
446 } // namespace framework