merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / update / ui / updatecheckui.cxx
bloba2a8c31908fc3709e9ed734aa1693d2afff12bc9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include <list>
33 #include <cppuhelper/implbase3.hxx>
34 #include <cppuhelper/implementationentry.hxx>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <com/sun/star/document/XEventListener.hpp>
38 #include <com/sun/star/document/XEventBroadcaster.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/graphic/XGraphicProvider.hpp>
41 #include <com/sun/star/task/XJob.hpp>
43 #include <comphelper/processfactory.hxx>
45 #include <vos/mutex.hxx>
46 #include <osl/mutex.hxx>
48 #include <vcl/window.hxx>
49 #include <vcl/floatwin.hxx>
50 #include <vcl/timer.hxx>
51 #include <vcl/menu.hxx>
52 #include <vcl/outdev.hxx>
53 #include <vcl/msgbox.hxx>
54 #include <vcl/lineinfo.hxx>
55 #include <vcl/imagebtn.hxx>
56 #include <vcl/settings.hxx>
57 #include <vcl/svapp.hxx>
58 #include <sfx2/sfx.hrc>
59 #include "rtl/ustrbuf.hxx"
61 #include "updatecheckui.hrc"
63 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
65 #define MSG_ERR_NO_WEBBROWSER_FOUND (RID_SFX_APP_START + 7)
66 #define DEFAULT_MENUBAR_HEIGHT 24
68 #define PROPERTY_TITLE RTL_CONSTASCII_STRINGPARAM("BubbleHeading")
69 #define PROPERTY_TEXT RTL_CONSTASCII_STRINGPARAM("BubbleText")
70 #define PROPERTY_IMAGE RTL_CONSTASCII_STRINGPARAM("BubbleImageURL")
71 #define PROPERTY_SHOW_BUBBLE RTL_CONSTASCII_STRINGPARAM("BubbleVisible")
72 #define PROPERTY_CLICK_HDL RTL_CONSTASCII_STRINGPARAM("MenuClickHDL")
73 #define PROPERTY_SHOW_MENUICON RTL_CONSTASCII_STRINGPARAM("MenuIconVisible")
75 #define START_TIMER 1
77 using namespace ::com::sun::star;
79 //------------------------------------------------------------------------------
81 static uno::Sequence< rtl::OUString > getServiceNames()
83 uno::Sequence< rtl::OUString > aServiceList(1);
84 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckUI");
85 return aServiceList;
88 //------------------------------------------------------------------------------
90 static rtl::OUString getImplementationName()
92 return UNISTRING( "vnd.sun.UpdateCheckUI");
95 //------------------------------------------------------------------------------
97 namespace
100 //------------------------------------------------------------------------------
101 class BubbleWindow : public FloatingWindow
103 Point maTipPos;
104 Region maBounds;
105 Polygon maRectPoly;
106 Polygon maTriPoly;
107 XubString maBubbleTitle;
108 XubString maBubbleText;
109 Image maBubbleImage;
110 Size maMaxTextSize;
111 Rectangle maTitleRect;
112 Rectangle maTextRect;
113 long mnTipOffset;
115 private:
116 void RecalcTextRects();
118 public:
119 BubbleWindow( Window* pParent, const XubString& rTitle,
120 const XubString& rText, const Image& rImage );
121 ~BubbleWindow();
123 virtual void MouseButtonDown( const MouseEvent& rMEvt );
124 virtual void Paint( const Rectangle& rRect );
125 void Resize();
126 void Show( BOOL bVisible = TRUE, USHORT nFlags = SHOW_NOACTIVATE );
127 void SetTipPosPixel( const Point& rTipPos ) { maTipPos = rTipPos; }
128 void SetTitleAndText( const XubString& rTitle, const XubString& rText,
129 const Image& rImage );
132 //------------------------------------------------------------------------------
133 class UpdateCheckUI : public ::cppu::WeakImplHelper3
134 < lang::XServiceInfo, document::XEventListener, beans::XPropertySet >
136 uno::Reference< uno::XComponentContext > m_xContext;
137 uno::Reference< task::XJob > mrJob;
138 rtl::OUString maBubbleTitle;
139 rtl::OUString maBubbleText;
140 rtl::OUString maBubbleImageURL;
141 Image maBubbleImage;
142 BubbleWindow* mpBubbleWin;
143 SystemWindow* mpIconSysWin;
144 MenuBar* mpIconMBar;
145 ResMgr* mpUpdResMgr;
146 ResMgr* mpSfxResMgr;
147 Timer maWaitTimer;
148 Timer maTimeoutTimer;
149 Link maWindowEventHdl;
150 Link maApplicationEventHdl;
151 bool mbShowBubble;
152 bool mbShowMenuIcon;
153 bool mbBubbleChanged;
154 USHORT mnIconID;
156 private:
157 DECL_LINK( ClickHdl, USHORT* );
158 DECL_LINK( HighlightHdl, MenuBar::MenuBarButtonCallbackArg* );
159 DECL_LINK( WaitTimeOutHdl, Timer* );
160 DECL_LINK( TimeOutHdl, Timer* );
161 DECL_LINK( UserEventHdl, UpdateCheckUI* );
162 DECL_LINK( WindowEventHdl, VclWindowEvent* );
163 DECL_LINK( ApplicationEventHdl, VclSimpleEvent* );
165 BubbleWindow* GetBubbleWindow();
166 void RemoveBubbleWindow( bool bRemoveIcon );
167 Image GetMenuBarIcon( MenuBar* pMBar );
168 void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl );
169 Image GetBubbleImage( ::rtl::OUString &rURL );
171 uno::Reference< document::XEventBroadcaster > getGlobalEventBroadcaster() const
172 throw (uno::RuntimeException);
174 public:
175 UpdateCheckUI(const uno::Reference<uno::XComponentContext>&);
176 virtual ~UpdateCheckUI();
178 // XServiceInfo
179 virtual rtl::OUString SAL_CALL getImplementationName()
180 throw (uno::RuntimeException);
181 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
182 throw (uno::RuntimeException);
183 virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
184 throw (uno::RuntimeException);
186 // XEventListener
187 virtual void SAL_CALL notifyEvent(const document::EventObject& Event)
188 throw (uno::RuntimeException);
189 virtual void SAL_CALL disposing(const lang::EventObject& Event)
190 throw (uno::RuntimeException);
192 //XPropertySet
193 virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(void)
194 throw ( uno::RuntimeException );
195 virtual void SAL_CALL setPropertyValue(const rtl::OUString& PropertyName, const uno::Any& aValue)
196 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
197 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException );
198 virtual uno::Any SAL_CALL getPropertyValue(const rtl::OUString& PropertyName)
199 throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
200 virtual void SAL_CALL addPropertyChangeListener(const rtl::OUString& PropertyName,
201 const uno::Reference< beans::XPropertyChangeListener > & aListener)
202 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
203 virtual void SAL_CALL removePropertyChangeListener(const rtl::OUString& PropertyName,
204 const uno::Reference< beans::XPropertyChangeListener > & aListener)
205 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
206 virtual void SAL_CALL addVetoableChangeListener(const rtl::OUString& PropertyName,
207 const uno::Reference< beans::XVetoableChangeListener > & aListener)
208 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
209 virtual void SAL_CALL removeVetoableChangeListener(const rtl::OUString& PropertyName,
210 const uno::Reference< beans::XVetoableChangeListener > & aListener)
211 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
214 //------------------------------------------------------------------------------
215 UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) :
216 m_xContext(xContext)
217 , mpBubbleWin( NULL )
218 , mpIconSysWin( NULL )
219 , mpIconMBar( NULL )
220 , mbShowBubble( false )
221 , mbShowMenuIcon( false )
222 , mbBubbleChanged( false )
223 , mnIconID( 0 )
225 mpUpdResMgr = ResMgr::CreateResMgr( "updchk" );
226 mpSfxResMgr = ResMgr::CreateResMgr( "sfx" );
228 maBubbleImage = GetBubbleImage( maBubbleImageURL );
230 maWaitTimer.SetTimeout( 400 );
231 maWaitTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) );
233 maTimeoutTimer.SetTimeout( 10000 );
234 maTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, TimeOutHdl ) );
236 uno::Reference< document::XEventBroadcaster > xBroadcaster( getGlobalEventBroadcaster() );
237 xBroadcaster->addEventListener( this );
239 maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl );
240 maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl );
241 Application::AddEventListener( maApplicationEventHdl );
244 //------------------------------------------------------------------------------
245 UpdateCheckUI::~UpdateCheckUI()
247 Application::RemoveEventListener( maApplicationEventHdl );
248 RemoveBubbleWindow( true );
249 delete mpUpdResMgr;
250 delete mpSfxResMgr;
253 //------------------------------------------------------------------------------
254 uno::Reference<document::XEventBroadcaster>
255 UpdateCheckUI::getGlobalEventBroadcaster() const throw (uno::RuntimeException)
257 if( !m_xContext.is() )
258 throw uno::RuntimeException(
259 UNISTRING( "UpdateCheckUI: empty component context" ),
260 uno::Reference< uno::XInterface >() );
262 uno::Reference< lang::XMultiComponentFactory > xServiceManager(m_xContext->getServiceManager());
264 if( !xServiceManager.is() )
265 throw uno::RuntimeException(
266 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
267 uno::Reference< uno::XInterface >() );
269 return uno::Reference<document::XEventBroadcaster> (
270 xServiceManager->createInstanceWithContext(
271 UNISTRING( "com.sun.star.frame.GlobalEventBroadcaster" ),
272 m_xContext),
273 uno::UNO_QUERY_THROW);
276 //------------------------------------------------------------------------------
277 rtl::OUString SAL_CALL
278 UpdateCheckUI::getImplementationName() throw (uno::RuntimeException)
280 return ::getImplementationName();
283 //------------------------------------------------------------------------------
284 uno::Sequence< rtl::OUString > SAL_CALL
285 UpdateCheckUI::getSupportedServiceNames() throw (uno::RuntimeException)
287 return ::getServiceNames();
290 //------------------------------------------------------------------------------
291 sal_Bool SAL_CALL
292 UpdateCheckUI::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
294 uno::Sequence< rtl::OUString > aServiceNameList = ::getServiceNames();
296 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
297 if( aServiceNameList[n].equals(serviceName) )
298 return sal_True;
300 return sal_False;
303 //------------------------------------------------------------------------------
304 Image UpdateCheckUI::GetMenuBarIcon( MenuBar* pMBar )
306 sal_uInt32 nResID;
307 Window *pMBarWin = pMBar->GetWindow();
308 sal_uInt32 nMBarHeight = 20;
310 if ( pMBarWin )
311 nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight();
313 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) {
314 if ( nMBarHeight >= 35 )
315 nResID = RID_UPDATE_AVAILABLE_26_HC;
316 else
317 nResID = RID_UPDATE_AVAILABLE_16_HC;
318 } else {
319 if ( nMBarHeight >= 35 )
320 nResID = RID_UPDATE_AVAILABLE_26;
321 else
322 nResID = RID_UPDATE_AVAILABLE_16;
325 return Image( ResId( nResID, *mpUpdResMgr ) );
328 //------------------------------------------------------------------------------
329 Image UpdateCheckUI::GetBubbleImage( ::rtl::OUString &rURL )
331 Image aImage;
333 if ( maBubbleImageURL.getLength() != 0 )
335 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
337 if( !xServiceManager.is() )
338 throw uno::RuntimeException(
339 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
340 uno::Reference< uno::XInterface >() );
344 uno::Reference< graphic::XGraphicProvider > xGraphProvider(
345 xServiceManager->createInstance(
346 ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ),
347 uno::UNO_QUERY );
348 if ( xGraphProvider.is() )
350 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
351 aMediaProps[0].Name = ::rtl::OUString::createFromAscii( "URL" );
352 aMediaProps[0].Value <<= rURL;
354 uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
355 if ( xGraphic.is() )
357 aImage = Image( xGraphic );
361 catch( uno::Exception& )
366 if ( aImage.GetSizePixel().Width() == 0 )
367 aImage = InfoBox::GetStandardImage();
369 return aImage;
372 //------------------------------------------------------------------------------
373 void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl )
375 if ( ! mbShowMenuIcon )
376 return;
378 vos::OGuard aGuard( Application::GetSolarMutex() );
380 MenuBar *pActiveMBar = pSysWin->GetMenuBar();
381 if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) )
383 if ( bAddEventHdl && mpIconSysWin )
384 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
386 RemoveBubbleWindow( true );
388 if ( pActiveMBar )
390 rtl::OUStringBuffer aBuf;
391 if( maBubbleTitle.getLength() )
392 aBuf.append( maBubbleTitle );
393 if( maBubbleText.getLength() )
395 if( maBubbleTitle.getLength() )
396 aBuf.appendAscii( "\n\n" );
397 aBuf.append( maBubbleText );
400 Image aImage = GetMenuBarIcon( pActiveMBar );
401 mnIconID = pActiveMBar->AddMenuBarButton( aImage,
402 LINK( this, UpdateCheckUI, ClickHdl ),
403 aBuf.makeStringAndClear()
405 pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID,
406 LINK( this, UpdateCheckUI, HighlightHdl ) );
408 mpIconMBar = pActiveMBar;
409 mpIconSysWin = pSysWin;
410 if ( bAddEventHdl && mpIconSysWin )
411 mpIconSysWin->AddEventListener( maWindowEventHdl );
414 if ( mbShowBubble && pActiveMBar )
416 mpBubbleWin = GetBubbleWindow();
417 if ( mpBubbleWin )
419 mpBubbleWin->Show( TRUE );
420 maTimeoutTimer.Start();
422 mbShowBubble = false;
426 //------------------------------------------------------------------------------
427 void SAL_CALL UpdateCheckUI::notifyEvent(const document::EventObject& rEvent)
428 throw (uno::RuntimeException)
430 vos::OGuard aGuard( Application::GetSolarMutex() );
432 if( rEvent.EventName.compareToAscii( RTL_CONSTASCII_STRINGPARAM("OnPrepareViewClosing") ) == 0 )
434 RemoveBubbleWindow( true );
438 //------------------------------------------------------------------------------
439 void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&)
440 throw (uno::RuntimeException)
444 //------------------------------------------------------------------------------
445 uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo(void)
446 throw ( uno::RuntimeException )
448 return NULL;
451 //------------------------------------------------------------------------------
452 void UpdateCheckUI::setPropertyValue(const rtl::OUString& rPropertyName,
453 const uno::Any& rValue)
454 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
455 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
457 vos::OGuard aGuard( Application::GetSolarMutex() );
459 rtl::OUString aString;
461 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 ) {
462 rValue >>= aString;
463 if ( aString != maBubbleTitle ) {
464 maBubbleTitle = aString;
465 mbBubbleChanged = true;
468 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 ) {
469 rValue >>= aString;
470 if ( aString != maBubbleText ) {
471 maBubbleText = aString;
472 mbBubbleChanged = true;
475 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 ) {
476 rValue >>= aString;
477 if ( aString != maBubbleImageURL ) {
478 maBubbleImageURL = aString;
479 maBubbleImage = GetBubbleImage( maBubbleImageURL );
480 mbBubbleChanged = true;
483 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 ) {
484 rValue >>= mbShowBubble;
485 if ( mbShowBubble )
486 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
487 else if ( mpBubbleWin )
488 mpBubbleWin->Show( FALSE );
490 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 ) {
491 uno::Reference< task::XJob > aJob;
492 rValue >>= aJob;
493 if ( aJob.is() )
494 mrJob = aJob;
495 else
496 throw lang::IllegalArgumentException();
498 else if (rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0) {
499 bool bShowMenuIcon = sal_False;
500 rValue >>= bShowMenuIcon;
501 if ( bShowMenuIcon != mbShowMenuIcon )
503 mbShowMenuIcon = bShowMenuIcon;
504 if ( bShowMenuIcon )
505 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
506 else
507 RemoveBubbleWindow( true );
510 else
511 throw beans::UnknownPropertyException();
513 if ( mbBubbleChanged && mpBubbleWin )
514 mpBubbleWin->Show( FALSE );
517 //------------------------------------------------------------------------------
518 uno::Any UpdateCheckUI::getPropertyValue(const rtl::OUString& rPropertyName)
519 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
521 vos::OGuard aGuard( Application::GetSolarMutex() );
523 uno::Any aRet;
525 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 )
526 aRet = uno::makeAny( maBubbleTitle );
527 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 )
528 aRet = uno::makeAny( maBubbleText );
529 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 )
530 aRet = uno::makeAny( mbShowBubble );
531 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 )
532 aRet = uno::makeAny( maBubbleImageURL );
533 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 )
534 aRet = uno::makeAny( mrJob );
535 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0 )
536 aRet = uno::makeAny( mbShowMenuIcon );
537 else
538 throw beans::UnknownPropertyException();
540 return aRet;
543 //------------------------------------------------------------------------------
544 void UpdateCheckUI::addPropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
545 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
546 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
548 //no bound properties
551 //------------------------------------------------------------------------------
552 void UpdateCheckUI::removePropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
553 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
554 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
556 //no bound properties
559 //------------------------------------------------------------------------------
560 void UpdateCheckUI::addVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
561 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
562 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
564 //no vetoable properties
567 //------------------------------------------------------------------------------
568 void UpdateCheckUI::removeVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
569 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
570 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
572 //no vetoable properties
576 //------------------------------------------------------------------------------
577 //------------------------------------------------------------------------------
578 //------------------------------------------------------------------------------
579 BubbleWindow * UpdateCheckUI::GetBubbleWindow()
581 if ( !mpIconSysWin )
582 return NULL;
584 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
585 if( aIconRect.IsEmpty() )
586 return NULL;
588 BubbleWindow* pBubbleWin = mpBubbleWin;
590 if ( !pBubbleWin ) {
591 pBubbleWin = new BubbleWindow( mpIconSysWin,
592 XubString( maBubbleTitle ),
593 XubString( maBubbleText ),
594 maBubbleImage );
595 mbBubbleChanged = false;
597 else if ( mbBubbleChanged ) {
598 pBubbleWin->SetTitleAndText( XubString( maBubbleTitle ),
599 XubString( maBubbleText ),
600 maBubbleImage );
601 mbBubbleChanged = false;
604 Point aWinPos = aIconRect.BottomCenter();
606 pBubbleWin->SetTipPosPixel( aWinPos );
608 return pBubbleWin;
611 //------------------------------------------------------------------------------
612 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon )
614 vos::OGuard aGuard( Application::GetSolarMutex() );
616 maWaitTimer.Stop();
617 maTimeoutTimer.Stop();
619 if ( mpBubbleWin )
621 delete mpBubbleWin;
622 mpBubbleWin = NULL;
625 if ( bRemoveIcon )
627 try {
628 if ( mpIconMBar && ( mnIconID != 0 ) )
630 mpIconMBar->RemoveMenuBarButton( mnIconID );
631 mpIconMBar = NULL;
632 mnIconID = 0;
635 catch ( ... ) {
636 mpIconMBar = NULL;
637 mnIconID = 0;
640 mpIconSysWin = NULL;
644 // -----------------------------------------------------------------------
645 IMPL_LINK( UpdateCheckUI, ClickHdl, USHORT*, EMPTYARG )
647 vos::OGuard aGuard( Application::GetSolarMutex() );
649 maWaitTimer.Stop();
650 if ( mpBubbleWin )
651 mpBubbleWin->Show( FALSE );
653 if ( mrJob.is() )
655 try {
656 uno::Sequence<beans::NamedValue> aEmpty;
657 mrJob->execute( aEmpty );
659 catch(const uno::Exception&) {
660 ErrorBox( NULL, ResId( MSG_ERR_NO_WEBBROWSER_FOUND, *mpSfxResMgr )).Execute();
664 return 0;
667 // -----------------------------------------------------------------------
668 IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg*, pData )
670 if ( pData->bHighlight )
671 maWaitTimer.Start();
672 else
673 RemoveBubbleWindow( false );
675 return 0;
678 // -----------------------------------------------------------------------
679 IMPL_LINK( UpdateCheckUI, WaitTimeOutHdl, Timer*, EMPTYARG )
681 vos::OGuard aGuard( Application::GetSolarMutex() );
683 mpBubbleWin = GetBubbleWindow();
685 if ( mpBubbleWin )
687 mpBubbleWin->Show();
690 return 0;
693 // -----------------------------------------------------------------------
694 IMPL_LINK( UpdateCheckUI, TimeOutHdl, Timer*, EMPTYARG )
696 RemoveBubbleWindow( false );
698 return 0;
701 // -----------------------------------------------------------------------
702 IMPL_LINK( UpdateCheckUI, UserEventHdl, UpdateCheckUI*, EMPTYARG )
704 vos::OGuard aGuard( Application::GetSolarMutex() );
706 Window *pTopWin = Application::GetFirstTopLevelWindow();
707 Window *pActiveWin = Application::GetActiveTopWindow();
708 SystemWindow *pActiveSysWin = NULL;
710 Window *pBubbleWin = NULL;
711 if ( mpBubbleWin )
712 pBubbleWin = mpBubbleWin;
714 if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() )
715 pActiveSysWin = pActiveWin->GetSystemWindow();
717 if ( pActiveWin == pBubbleWin )
718 pActiveSysWin = NULL;
720 while ( !pActiveSysWin && pTopWin )
722 if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() )
723 pActiveSysWin = pTopWin->GetSystemWindow();
724 if ( !pActiveSysWin )
725 pTopWin = Application::GetNextTopLevelWindow( pTopWin );
728 if ( pActiveSysWin )
729 AddMenuBarIcon( pActiveSysWin, true );
731 return 0;
734 // -----------------------------------------------------------------------
735 IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent*, pEvent )
737 ULONG nEventID = pEvent->GetId();
739 if ( VCLEVENT_OBJECT_DYING == nEventID )
741 vos::OGuard aGuard( Application::GetSolarMutex() );
742 if ( mpIconSysWin == pEvent->GetWindow() )
744 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
745 RemoveBubbleWindow( true );
748 else if ( VCLEVENT_WINDOW_MENUBARADDED == nEventID )
750 vos::OGuard aGuard( Application::GetSolarMutex() );
751 Window *pWindow = pEvent->GetWindow();
752 if ( pWindow )
754 SystemWindow *pSysWin = pWindow->GetSystemWindow();
755 if ( pSysWin )
757 AddMenuBarIcon( pSysWin, false );
761 else if ( VCLEVENT_WINDOW_MENUBARREMOVED == nEventID )
763 vos::OGuard aGuard( Application::GetSolarMutex() );
764 MenuBar *pMBar = (MenuBar*) pEvent->GetData();
765 if ( pMBar && ( pMBar == mpIconMBar ) )
766 RemoveBubbleWindow( true );
768 else if ( ( nEventID == VCLEVENT_WINDOW_MOVE ) ||
769 ( nEventID == VCLEVENT_WINDOW_RESIZE ) )
771 vos::OGuard aGuard( Application::GetSolarMutex() );
772 if ( ( mpIconSysWin == pEvent->GetWindow() ) &&
773 ( mpBubbleWin != NULL ) && ( mpIconMBar != NULL ) )
775 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
776 Point aWinPos = aIconRect.BottomCenter();
777 mpBubbleWin->SetTipPosPixel( aWinPos );
778 if ( mpBubbleWin->IsVisible() )
779 mpBubbleWin->Show(); // This will recalc the screen positon of the bubble
783 return 0;
786 //------------------------------------------------------------------------------
787 IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent *, pEvent)
789 switch (pEvent->GetId())
791 case VCLEVENT_WINDOW_SHOW:
792 case VCLEVENT_WINDOW_ACTIVATE:
793 case VCLEVENT_WINDOW_GETFOCUS: {
794 vos::OGuard aGuard( Application::GetSolarMutex() );
796 Window *pWindow = static_cast< VclWindowEvent * >(pEvent)->GetWindow();
797 if ( pWindow && pWindow->IsTopWindow() )
799 SystemWindow *pSysWin = pWindow->GetSystemWindow();
800 MenuBar *pMBar = pSysWin->GetMenuBar();
801 if ( pSysWin && pMBar )
803 AddMenuBarIcon( pSysWin, true );
806 break;
809 return 0;
811 //------------------------------------------------------------------------------
812 //------------------------------------------------------------------------------
813 //------------------------------------------------------------------------------
815 #define TIP_HEIGHT 15
816 #define TIP_WIDTH 7
817 #define TIP_RIGHT_OFFSET 18
818 #define BUBBLE_BORDER 10
819 #define TEXT_MAX_WIDTH 300
820 #define TEXT_MAX_HEIGHT 200
821 #define INITIAL_SHOW_TIME 10000
823 //------------------------------------------------------------------------------
824 BubbleWindow::BubbleWindow( Window* pParent, const XubString& rTitle,
825 const XubString& rText, const Image& rImage )
826 : FloatingWindow( pParent, WB_SYSTEMWINDOW
827 | WB_OWNERDRAWDECORATION
828 | WB_NOBORDER
830 , maBubbleTitle( rTitle )
831 , maBubbleText( rText )
832 , maBubbleImage( rImage )
833 , maMaxTextSize( TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT )
834 , mnTipOffset( 0 )
836 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
839 //------------------------------------------------------------------------------
840 BubbleWindow::~BubbleWindow()
844 //------------------------------------------------------------------------------
845 void BubbleWindow::Resize()
847 vos::OGuard aGuard( Application::GetSolarMutex() );
849 FloatingWindow::Resize();
851 Size aSize = GetSizePixel();
853 if ( ( aSize.Height() < 20 ) || ( aSize.Width() < 60 ) )
854 return;
856 Rectangle aRect( 0, TIP_HEIGHT, aSize.Width(), aSize.Height() - TIP_HEIGHT );
857 maRectPoly = Polygon( aRect, 6, 6 );
858 Region aRegion( maRectPoly );
859 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
861 Point aPointArr[4];
862 aPointArr[0] = Point( nTipOffset, TIP_HEIGHT );
863 aPointArr[1] = Point( nTipOffset, 0 );
864 aPointArr[2] = Point( nTipOffset + TIP_WIDTH , TIP_HEIGHT );
865 aPointArr[3] = Point( nTipOffset, TIP_HEIGHT );
866 maTriPoly = Polygon( 4, aPointArr );
867 Region aTriRegion( maTriPoly );
869 aRegion.Union( aTriRegion);
870 maBounds = aRegion;
872 SetWindowRegionPixel( maBounds );
875 //------------------------------------------------------------------------------
876 void BubbleWindow::SetTitleAndText( const XubString& rTitle,
877 const XubString& rText,
878 const Image& rImage )
880 maBubbleTitle = rTitle;
881 maBubbleText = rText;
882 maBubbleImage = rImage;
884 Resize();
887 //------------------------------------------------------------------------------
888 void BubbleWindow::Paint( const Rectangle& )
890 vos::OGuard aGuard( Application::GetSolarMutex() );
892 LineInfo aThickLine( LINE_SOLID, 2 );
894 DrawPolyLine( maRectPoly, aThickLine );
895 DrawPolyLine( maTriPoly );
897 Color aOldLine = GetLineColor();
898 Size aSize = GetSizePixel();
899 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
901 SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
902 DrawLine( Point( nTipOffset+2, TIP_HEIGHT ),
903 Point( nTipOffset + TIP_WIDTH -1 , TIP_HEIGHT ),
904 aThickLine );
905 SetLineColor( aOldLine );
907 //Image aImage = InfoBox::GetStandardImage();
908 Size aImgSize = maBubbleImage.GetSizePixel();
910 DrawImage( Point( BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT ), maBubbleImage );
912 Font aOldFont = GetFont();
913 Font aBoldFont = aOldFont;
914 aBoldFont.SetWeight( WEIGHT_BOLD );
916 SetFont( aBoldFont );
917 Rectangle aTitleRect = maTitleRect;
918 aTitleRect.Move( aImgSize.Width(), 0 );
919 DrawText( aTitleRect, maBubbleTitle, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
921 SetFont( aOldFont );
922 Rectangle aTextRect = maTextRect;
923 aTextRect.Move( aImgSize.Width(), 0 );
924 DrawText( aTextRect, maBubbleText, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
927 //------------------------------------------------------------------------------
928 void BubbleWindow::MouseButtonDown( const MouseEvent& )
930 Show( FALSE );
933 //------------------------------------------------------------------------------
934 void BubbleWindow::Show( BOOL bVisible, USHORT nFlags )
936 vos::OGuard aGuard( Application::GetSolarMutex() );
938 if ( !bVisible )
940 FloatingWindow::Show( bVisible );
941 return;
944 // don't show bubbles without a text
945 if ( ( maBubbleTitle.Len() == 0 ) && ( maBubbleText.Len() == 0 ) )
946 return;
948 Size aWindowSize = GetSizePixel();
950 // Image aImage = InfoBox::GetStandardImage();
951 Size aImgSize = maBubbleImage.GetSizePixel();
953 RecalcTextRects();
955 aWindowSize.setHeight( maTitleRect.GetHeight() * 7 / 4+ maTextRect.GetHeight() +
956 3 * BUBBLE_BORDER + TIP_HEIGHT );
958 if ( maTitleRect.GetWidth() > maTextRect.GetWidth() )
959 aWindowSize.setWidth( maTitleRect.GetWidth() );
960 else
961 aWindowSize.setWidth( maTextRect.GetWidth() );
963 aWindowSize.setWidth( aWindowSize.Width() + 3 * BUBBLE_BORDER + aImgSize.Width() );
965 if ( aWindowSize.Height() < aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER )
966 aWindowSize.setHeight( aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER );
968 Point aPos;
969 aPos.X() = maTipPos.X() - aWindowSize.Width() + TIP_RIGHT_OFFSET;
970 aPos.Y() = maTipPos.Y();
971 Point aScreenPos = GetParent()->OutputToAbsoluteScreenPixel( aPos );
972 if ( aScreenPos.X() < 0 )
974 mnTipOffset = aScreenPos.X();
975 aPos.X() -= mnTipOffset;
977 SetPosSizePixel( aPos, aWindowSize );
979 FloatingWindow::Show( bVisible, nFlags );
982 //------------------------------------------------------------------------------
983 void BubbleWindow::RecalcTextRects()
985 Size aTotalSize;
986 BOOL bFinished = FALSE;
987 Font aOldFont = GetFont();
988 Font aBoldFont = aOldFont;
990 aBoldFont.SetWeight( WEIGHT_BOLD );
992 while ( !bFinished )
994 SetFont( aBoldFont );
996 maTitleRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
997 maBubbleTitle,
998 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
1000 SetFont( aOldFont );
1001 maTextRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
1002 maBubbleText,
1003 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
1005 if ( maTextRect.GetHeight() < 10 )
1006 maTextRect.setHeight( 10 );
1008 aTotalSize.setHeight( maTitleRect.GetHeight() +
1009 aBoldFont.GetHeight() * 3 / 4 +
1010 maTextRect.GetHeight() +
1011 3 * BUBBLE_BORDER + TIP_HEIGHT );
1012 if ( aTotalSize.Height() > maMaxTextSize.Height() )
1014 maMaxTextSize.Width() = maMaxTextSize.Width() * 3 / 2;
1015 maMaxTextSize.Height() = maMaxTextSize.Height() * 3 / 2;
1017 else
1018 bFinished = TRUE;
1020 maTitleRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT );
1021 maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetHeight() * 3 / 4 );
1023 //------------------------------------------------------------------------------
1024 //------------------------------------------------------------------------------
1025 //------------------------------------------------------------------------------
1027 } // anonymous namespace
1029 //------------------------------------------------------------------------------
1031 static uno::Reference<uno::XInterface> SAL_CALL
1032 createInstance(const uno::Reference<uno::XComponentContext>& xContext)
1034 return *new UpdateCheckUI(xContext);
1037 //------------------------------------------------------------------------------
1039 static const cppu::ImplementationEntry kImplementations_entries[] =
1042 createInstance,
1043 getImplementationName,
1044 getServiceNames,
1045 cppu::createSingleComponentFactory,
1046 NULL,
1049 { NULL, NULL, NULL, NULL, NULL, 0 }
1052 //------------------------------------------------------------------------------
1054 extern "C" void SAL_CALL
1055 component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
1057 *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
1060 //------------------------------------------------------------------------------
1062 extern "C" sal_Bool SAL_CALL
1063 component_writeInfo(void *pServiceManager, void *pRegistryKey)
1065 return cppu::component_writeInfoHelper(
1066 pServiceManager,
1067 pRegistryKey,
1068 kImplementations_entries
1072 //------------------------------------------------------------------------------
1074 extern "C" void *
1075 component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
1077 return cppu::component_getFactoryHelper(
1078 pszImplementationName,
1079 pServiceManager,
1080 pRegistryKey,
1081 kImplementations_entries) ;