update dev300-m58
[ooovba.git] / framework / source / dispatch / helpagentdispatcher.cxx
blob707219b90802d4250e2fd951e1c4b3f857d1a898
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helpagentdispatcher.cxx,v $
10 * $Revision: 1.11 $
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 //........................................................................
48 namespace framework
51 //-----------------------------------------------
52 DEFINE_XINTERFACE_4(HelpAgentDispatcher ,
53 OWeakObject ,
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())
67 , m_sCurrentURL ( )
68 , m_xContainerWindow( )
69 , m_xAgentWindow ( )
70 , m_aTimer ( )
71 , m_xSelfHold ( )
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()
81 implts_stopTimer();
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)
98 return;
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 !!!
103 implts_stopTimer();
105 // SAFE ->
106 WriteGuard aWriteLock(m_aLock);
107 m_sCurrentURL = aURL.Complete;
108 aWriteLock.unlock();
109 // <- SAFE
111 // start the expiration timer for the new URL
112 implts_startTimer();
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)
166 // SAFE ->
167 WriteGuard aWriteLock(m_aLock);
169 // Already disposed ?!
170 if (! m_xContainerWindow.is())
171 return;
172 // Wrong broadcaster ?!
173 if (aEvent.Source != m_xContainerWindow)
174 return;
176 css::uno::Reference< css::uno::XInterface > xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY_THROW);
177 m_xSelfHold.clear();
179 aWriteLock.unlock();
180 // <- SAFE
182 implts_stopTimer();
183 implts_hideAgentWindow();
184 implts_ignoreCurrentURL();
186 // SAFE ->
187 aWriteLock.lock();
188 m_xContainerWindow.clear();
189 css::uno::Reference< css::lang::XComponent > xAgentWindow(m_xAgentWindow, css::uno::UNO_QUERY);
190 m_xAgentWindow.clear();
191 aWriteLock.unlock();
192 // <- SAFE
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()
202 implts_stopTimer();
203 implts_hideAgentWindow();
204 implts_acceptCurrentURL();
207 //-----------------------------------------------
208 void HelpAgentDispatcher::closeAgent()
210 implts_stopTimer();
211 implts_hideAgentWindow();
212 implts_ignoreCurrentURL();
215 //--------------------------------------------------------------------
216 void HelpAgentDispatcher::implts_acceptCurrentURL()
218 // SAFE ->
219 WriteGuard aWriteLock(m_aLock);
221 ::rtl::OUString sAcceptedURL = m_sCurrentURL;
222 m_sCurrentURL = ::rtl::OUString();
224 aWriteLock.unlock();
225 // <- SAFE
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
232 // SOLAR SAFE ->
234 ::vos::OGuard aSolarLock(Application::GetSolarMutex());
235 Help* pHelp = Application::GetHelp();
236 if (pHelp)
237 pHelp->Start(sAcceptedURL, NULL);
239 // <- SOLAR SAFE
242 //--------------------------------------------------------------------
243 void HelpAgentDispatcher::implts_ignoreCurrentURL()
245 // SAFE ->
246 WriteGuard aWriteLock(m_aLock);
248 ::rtl::OUString sIgnoredURL = m_sCurrentURL;
249 m_sCurrentURL = ::rtl::OUString();
251 aWriteLock.unlock();
252 // <- SAFE
254 if (sIgnoredURL.getLength())
255 SvtHelpOptions().decAgentIgnoreURLCounter(sIgnoredURL);
258 //--------------------------------------------------------------------
259 void HelpAgentDispatcher::implts_stopTimer()
261 // SAFE ->
262 WriteGuard aWriteLock(m_aLock);
263 m_xSelfHold.clear();
264 aWriteLock.unlock();
265 // <- SAFE
267 // SOLAR SAFE ->
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())
273 return;
274 m_aTimer.Stop();
276 // <- SOLAR SAFE
279 //--------------------------------------------------------------------
280 void HelpAgentDispatcher::implts_startTimer()
282 // SOLAR SAFE ->
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())
288 return;
290 // <- SOLAR SAFE
292 // SAFE ->
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);
298 aWriteLock.unlock();
299 // <- SAFE
301 sal_Int32 nTime = SvtHelpOptions().GetHelpAgentTimeoutPeriod();
303 // SOLAR SAFE ->
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 !
309 m_aTimer.Start();
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.
320 // SAFE ->
321 WriteGuard aWriteLock(m_aLock);
322 css::uno::Reference< css::uno::XInterface > xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY_THROW);
323 m_xSelfHold.clear();
324 aWriteLock.unlock();
325 // <- SAFE
327 implts_hideAgentWindow();
328 implts_ignoreCurrentURL();
330 return 0;
333 //--------------------------------------------------------------------
334 void HelpAgentDispatcher::implts_showAgentWindow()
336 // SAFE ->
337 ReadGuard aReadLock(m_aLock);
338 css::uno::Reference< css::awt::XWindow2 > xContainerWindow(m_xContainerWindow, css::uno::UNO_QUERY_THROW);
339 aReadLock.unlock();
340 // <- SAFE
342 css::uno::Reference< css::awt::XWindow > xAgentWindow = implts_ensureAgentWindow();
344 if (
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()
367 // SAFE ->
368 ReadGuard aReadLock(m_aLock);
369 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
370 aReadLock.unlock();
371 // <- SAFE
373 css::uno::Reference< css::awt::XWindow > xAgentWindow = implts_ensureAgentWindow();
374 if (
375 (! xContainerWindow.is()) ||
376 (! xAgentWindow.is() )
378 return;
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();
387 if (nW < 1)
388 nW = 100;
389 if (nH < 1)
390 nH = 100;
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()
402 // SAFE ->
403 ReadGuard aReadLock(m_aLock);
404 if (m_xAgentWindow.is())
405 return m_xAgentWindow;
406 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
407 aReadLock.unlock();
408 // <- SAFE
410 if (!xContainerWindow.is())
411 return css::uno::Reference< css::awt::XWindow >();
413 ::svt::HelpAgentWindow* pAgentWindow = 0;
414 // SOLAR SAFE ->
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);
422 // <- SOLAR SAFE
424 // SAFE ->
425 WriteGuard aWriteLock(m_aLock);
426 m_xAgentWindow = VCLUnoHelper::GetInterface(pAgentWindow);
427 css::uno::Reference< css::awt::XWindow > xAgentWindow = m_xAgentWindow;
428 aWriteLock.unlock();
429 // <- SAFE
431 // add as window listener to the container window so we can maintain the property position of the agent window
432 xContainerWindow->addWindowListener(this);
434 // SOLAR SAFE ->
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));
441 // <- SOLAR SAFE
443 return xAgentWindow;
446 } // namespace framework