Update ooo320-m1
[ooovba.git] / extensions / source / update / ui / updatecheckui.cxx
blob8c673ccbc9aa8d889a9ac2989ca68a42826801d3
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: updatecheckui.cxx,v $
10 * $Revision: 1.19.18.2 $
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_extensions.hxx"
34 #include <list>
36 #include <cppuhelper/implbase3.hxx>
37 #include <cppuhelper/implementationentry.hxx>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/lang/XComponent.hpp>
40 #include <com/sun/star/document/XEventListener.hpp>
41 #include <com/sun/star/document/XEventBroadcaster.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/graphic/XGraphicProvider.hpp>
44 #include <com/sun/star/task/XJob.hpp>
46 #include <comphelper/processfactory.hxx>
48 #include <vos/mutex.hxx>
49 #include <osl/mutex.hxx>
51 #include <vcl/window.hxx>
52 #include <vcl/floatwin.hxx>
53 #include <vcl/timer.hxx>
54 #include <vcl/menu.hxx>
55 #include <vcl/outdev.hxx>
56 #include <vcl/msgbox.hxx>
57 #include <vcl/lineinfo.hxx>
58 #include <vcl/imagebtn.hxx>
59 #include <vcl/settings.hxx>
60 #include <vcl/svapp.hxx>
61 #include <sfx2/sfx.hrc>
62 #include "rtl/ustrbuf.hxx"
64 #include "updatecheckui.hrc"
66 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
68 #define MSG_ERR_NO_WEBBROWSER_FOUND (RID_SFX_APP_START + 7)
69 #define DEFAULT_MENUBAR_HEIGHT 24
71 #define PROPERTY_TITLE RTL_CONSTASCII_STRINGPARAM("BubbleHeading")
72 #define PROPERTY_TEXT RTL_CONSTASCII_STRINGPARAM("BubbleText")
73 #define PROPERTY_IMAGE RTL_CONSTASCII_STRINGPARAM("BubbleImageURL")
74 #define PROPERTY_SHOW_BUBBLE RTL_CONSTASCII_STRINGPARAM("BubbleVisible")
75 #define PROPERTY_CLICK_HDL RTL_CONSTASCII_STRINGPARAM("MenuClickHDL")
76 #define PROPERTY_SHOW_MENUICON RTL_CONSTASCII_STRINGPARAM("MenuIconVisible")
78 #define START_TIMER 1
80 using namespace ::com::sun::star;
82 //------------------------------------------------------------------------------
84 static uno::Sequence< rtl::OUString > getServiceNames()
86 uno::Sequence< rtl::OUString > aServiceList(1);
87 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckUI");
88 return aServiceList;
91 //------------------------------------------------------------------------------
93 static rtl::OUString getImplementationName()
95 return UNISTRING( "vnd.sun.UpdateCheckUI");
98 //------------------------------------------------------------------------------
100 namespace
103 //------------------------------------------------------------------------------
104 class BubbleWindow : public FloatingWindow
106 Point maTipPos;
107 Region maBounds;
108 Polygon maRectPoly;
109 Polygon maTriPoly;
110 XubString maBubbleTitle;
111 XubString maBubbleText;
112 Image maBubbleImage;
113 Size maMaxTextSize;
114 Rectangle maTitleRect;
115 Rectangle maTextRect;
116 long mnTipOffset;
118 private:
119 void RecalcTextRects();
121 public:
122 BubbleWindow( Window* pParent, const XubString& rTitle,
123 const XubString& rText, const Image& rImage );
124 ~BubbleWindow();
126 virtual void MouseButtonDown( const MouseEvent& rMEvt );
127 virtual void Paint( const Rectangle& rRect );
128 void Resize();
129 void Show( BOOL bVisible = TRUE, USHORT nFlags = SHOW_NOACTIVATE );
130 void SetTipPosPixel( const Point& rTipPos ) { maTipPos = rTipPos; }
131 void SetTitleAndText( const XubString& rTitle, const XubString& rText,
132 const Image& rImage );
135 //------------------------------------------------------------------------------
136 class UpdateCheckUI : public ::cppu::WeakImplHelper3
137 < lang::XServiceInfo, document::XEventListener, beans::XPropertySet >
139 uno::Reference< uno::XComponentContext > m_xContext;
140 uno::Reference< task::XJob > mrJob;
141 rtl::OUString maBubbleTitle;
142 rtl::OUString maBubbleText;
143 rtl::OUString maBubbleImageURL;
144 Image maBubbleImage;
145 BubbleWindow* mpBubbleWin;
146 SystemWindow* mpIconSysWin;
147 MenuBar* mpIconMBar;
148 ResMgr* mpUpdResMgr;
149 ResMgr* mpSfxResMgr;
150 Timer maWaitTimer;
151 Timer maTimeoutTimer;
152 Link maWindowEventHdl;
153 Link maApplicationEventHdl;
154 bool mbShowBubble;
155 bool mbShowMenuIcon;
156 bool mbBubbleChanged;
157 USHORT mnIconID;
159 private:
160 DECL_LINK( ClickHdl, USHORT* );
161 DECL_LINK( HighlightHdl, MenuBar::MenuBarButtonCallbackArg* );
162 DECL_LINK( WaitTimeOutHdl, Timer* );
163 DECL_LINK( TimeOutHdl, Timer* );
164 DECL_LINK( UserEventHdl, UpdateCheckUI* );
165 DECL_LINK( WindowEventHdl, VclWindowEvent* );
166 DECL_LINK( ApplicationEventHdl, VclSimpleEvent* );
168 BubbleWindow* GetBubbleWindow();
169 void RemoveBubbleWindow( bool bRemoveIcon );
170 Image GetMenuBarIcon( MenuBar* pMBar );
171 void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl );
172 Image GetBubbleImage( ::rtl::OUString &rURL );
174 uno::Reference< document::XEventBroadcaster > getGlobalEventBroadcaster() const
175 throw (uno::RuntimeException);
177 public:
178 UpdateCheckUI(const uno::Reference<uno::XComponentContext>&);
179 virtual ~UpdateCheckUI();
181 // XServiceInfo
182 virtual rtl::OUString SAL_CALL getImplementationName()
183 throw (uno::RuntimeException);
184 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
185 throw (uno::RuntimeException);
186 virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
187 throw (uno::RuntimeException);
189 // XEventListener
190 virtual void SAL_CALL notifyEvent(const document::EventObject& Event)
191 throw (uno::RuntimeException);
192 virtual void SAL_CALL disposing(const lang::EventObject& Event)
193 throw (uno::RuntimeException);
195 //XPropertySet
196 virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(void)
197 throw ( uno::RuntimeException );
198 virtual void SAL_CALL setPropertyValue(const rtl::OUString& PropertyName, const uno::Any& aValue)
199 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
200 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException );
201 virtual uno::Any SAL_CALL getPropertyValue(const rtl::OUString& PropertyName)
202 throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
203 virtual void SAL_CALL addPropertyChangeListener(const rtl::OUString& PropertyName,
204 const uno::Reference< beans::XPropertyChangeListener > & aListener)
205 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
206 virtual void SAL_CALL removePropertyChangeListener(const rtl::OUString& PropertyName,
207 const uno::Reference< beans::XPropertyChangeListener > & aListener)
208 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
209 virtual void SAL_CALL addVetoableChangeListener(const rtl::OUString& PropertyName,
210 const uno::Reference< beans::XVetoableChangeListener > & aListener)
211 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
212 virtual void SAL_CALL removeVetoableChangeListener(const rtl::OUString& PropertyName,
213 const uno::Reference< beans::XVetoableChangeListener > & aListener)
214 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
217 //------------------------------------------------------------------------------
218 UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) :
219 m_xContext(xContext)
220 , mpBubbleWin( NULL )
221 , mpIconSysWin( NULL )
222 , mpIconMBar( NULL )
223 , mbShowBubble( false )
224 , mbShowMenuIcon( false )
225 , mbBubbleChanged( false )
226 , mnIconID( 0 )
228 mpUpdResMgr = ResMgr::CreateResMgr( "updchk" );
229 mpSfxResMgr = ResMgr::CreateResMgr( "sfx" );
231 maBubbleImage = GetBubbleImage( maBubbleImageURL );
233 maWaitTimer.SetTimeout( 400 );
234 maWaitTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) );
236 maTimeoutTimer.SetTimeout( 10000 );
237 maTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, TimeOutHdl ) );
239 uno::Reference< document::XEventBroadcaster > xBroadcaster( getGlobalEventBroadcaster() );
240 xBroadcaster->addEventListener( this );
242 maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl );
243 maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl );
244 Application::AddEventListener( maApplicationEventHdl );
247 //------------------------------------------------------------------------------
248 UpdateCheckUI::~UpdateCheckUI()
250 Application::RemoveEventListener( maApplicationEventHdl );
251 RemoveBubbleWindow( true );
252 delete mpUpdResMgr;
253 delete mpSfxResMgr;
256 //------------------------------------------------------------------------------
257 uno::Reference<document::XEventBroadcaster>
258 UpdateCheckUI::getGlobalEventBroadcaster() const throw (uno::RuntimeException)
260 if( !m_xContext.is() )
261 throw uno::RuntimeException(
262 UNISTRING( "UpdateCheckUI: empty component context" ),
263 uno::Reference< uno::XInterface >() );
265 uno::Reference< lang::XMultiComponentFactory > xServiceManager(m_xContext->getServiceManager());
267 if( !xServiceManager.is() )
268 throw uno::RuntimeException(
269 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
270 uno::Reference< uno::XInterface >() );
272 return uno::Reference<document::XEventBroadcaster> (
273 xServiceManager->createInstanceWithContext(
274 UNISTRING( "com.sun.star.frame.GlobalEventBroadcaster" ),
275 m_xContext),
276 uno::UNO_QUERY_THROW);
279 //------------------------------------------------------------------------------
280 rtl::OUString SAL_CALL
281 UpdateCheckUI::getImplementationName() throw (uno::RuntimeException)
283 return ::getImplementationName();
286 //------------------------------------------------------------------------------
287 uno::Sequence< rtl::OUString > SAL_CALL
288 UpdateCheckUI::getSupportedServiceNames() throw (uno::RuntimeException)
290 return ::getServiceNames();
293 //------------------------------------------------------------------------------
294 sal_Bool SAL_CALL
295 UpdateCheckUI::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
297 uno::Sequence< rtl::OUString > aServiceNameList = ::getServiceNames();
299 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
300 if( aServiceNameList[n].equals(serviceName) )
301 return sal_True;
303 return sal_False;
306 //------------------------------------------------------------------------------
307 Image UpdateCheckUI::GetMenuBarIcon( MenuBar* pMBar )
309 sal_uInt32 nResID;
310 Window *pMBarWin = pMBar->GetWindow();
311 sal_uInt32 nMBarHeight = 20;
313 if ( pMBarWin )
314 nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight();
316 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) {
317 if ( nMBarHeight >= 35 )
318 nResID = RID_UPDATE_AVAILABLE_26_HC;
319 else
320 nResID = RID_UPDATE_AVAILABLE_16_HC;
321 } else {
322 if ( nMBarHeight >= 35 )
323 nResID = RID_UPDATE_AVAILABLE_26;
324 else
325 nResID = RID_UPDATE_AVAILABLE_16;
328 return Image( ResId( nResID, *mpUpdResMgr ) );
331 //------------------------------------------------------------------------------
332 Image UpdateCheckUI::GetBubbleImage( ::rtl::OUString &rURL )
334 Image aImage;
336 if ( maBubbleImageURL.getLength() != 0 )
338 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
340 if( !xServiceManager.is() )
341 throw uno::RuntimeException(
342 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
343 uno::Reference< uno::XInterface >() );
347 uno::Reference< graphic::XGraphicProvider > xGraphProvider(
348 xServiceManager->createInstance(
349 ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ),
350 uno::UNO_QUERY );
351 if ( xGraphProvider.is() )
353 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
354 aMediaProps[0].Name = ::rtl::OUString::createFromAscii( "URL" );
355 aMediaProps[0].Value <<= rURL;
357 uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
358 if ( xGraphic.is() )
360 aImage = Image( xGraphic );
364 catch( uno::Exception& )
369 if ( aImage.GetSizePixel().Width() == 0 )
370 aImage = InfoBox::GetStandardImage();
372 return aImage;
375 //------------------------------------------------------------------------------
376 void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl )
378 if ( ! mbShowMenuIcon )
379 return;
381 vos::OGuard aGuard( Application::GetSolarMutex() );
383 MenuBar *pActiveMBar = pSysWin->GetMenuBar();
384 if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) )
386 if ( bAddEventHdl && mpIconSysWin )
387 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
389 RemoveBubbleWindow( true );
391 if ( pActiveMBar )
393 rtl::OUStringBuffer aBuf;
394 if( maBubbleTitle.getLength() )
395 aBuf.append( maBubbleTitle );
396 if( maBubbleText.getLength() )
398 if( maBubbleTitle.getLength() )
399 aBuf.appendAscii( "\n\n" );
400 aBuf.append( maBubbleText );
403 Image aImage = GetMenuBarIcon( pActiveMBar );
404 mnIconID = pActiveMBar->AddMenuBarButton( aImage,
405 LINK( this, UpdateCheckUI, ClickHdl ),
406 aBuf.makeStringAndClear()
408 pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID,
409 LINK( this, UpdateCheckUI, HighlightHdl ) );
411 mpIconMBar = pActiveMBar;
412 mpIconSysWin = pSysWin;
413 if ( bAddEventHdl && mpIconSysWin )
414 mpIconSysWin->AddEventListener( maWindowEventHdl );
417 if ( mbShowBubble && pActiveMBar )
419 mpBubbleWin = GetBubbleWindow();
420 if ( mpBubbleWin )
422 mpBubbleWin->Show( TRUE );
423 maTimeoutTimer.Start();
425 mbShowBubble = false;
429 //------------------------------------------------------------------------------
430 void SAL_CALL UpdateCheckUI::notifyEvent(const document::EventObject& rEvent)
431 throw (uno::RuntimeException)
433 vos::OGuard aGuard( Application::GetSolarMutex() );
435 if( rEvent.EventName.compareToAscii( RTL_CONSTASCII_STRINGPARAM("OnPrepareViewClosing") ) == 0 )
437 RemoveBubbleWindow( true );
441 //------------------------------------------------------------------------------
442 void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&)
443 throw (uno::RuntimeException)
447 //------------------------------------------------------------------------------
448 uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo(void)
449 throw ( uno::RuntimeException )
451 return NULL;
454 //------------------------------------------------------------------------------
455 void UpdateCheckUI::setPropertyValue(const rtl::OUString& rPropertyName,
456 const uno::Any& rValue)
457 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
458 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
460 vos::OGuard aGuard( Application::GetSolarMutex() );
462 rtl::OUString aString;
464 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 ) {
465 rValue >>= aString;
466 if ( aString != maBubbleTitle ) {
467 maBubbleTitle = aString;
468 mbBubbleChanged = true;
471 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 ) {
472 rValue >>= aString;
473 if ( aString != maBubbleText ) {
474 maBubbleText = aString;
475 mbBubbleChanged = true;
478 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 ) {
479 rValue >>= aString;
480 if ( aString != maBubbleImageURL ) {
481 maBubbleImageURL = aString;
482 maBubbleImage = GetBubbleImage( maBubbleImageURL );
483 mbBubbleChanged = true;
486 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 ) {
487 rValue >>= mbShowBubble;
488 if ( mbShowBubble )
489 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
490 else if ( mpBubbleWin )
491 mpBubbleWin->Show( FALSE );
493 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 ) {
494 uno::Reference< task::XJob > aJob;
495 rValue >>= aJob;
496 if ( aJob.is() )
497 mrJob = aJob;
498 else
499 throw lang::IllegalArgumentException();
501 else if (rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0) {
502 bool bShowMenuIcon = sal_False;
503 rValue >>= bShowMenuIcon;
504 if ( bShowMenuIcon != mbShowMenuIcon )
506 mbShowMenuIcon = bShowMenuIcon;
507 if ( bShowMenuIcon )
508 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
509 else
510 RemoveBubbleWindow( true );
513 else
514 throw beans::UnknownPropertyException();
516 if ( mbBubbleChanged && mpBubbleWin )
517 mpBubbleWin->Show( FALSE );
520 //------------------------------------------------------------------------------
521 uno::Any UpdateCheckUI::getPropertyValue(const rtl::OUString& rPropertyName)
522 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
524 vos::OGuard aGuard( Application::GetSolarMutex() );
526 uno::Any aRet;
528 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 )
529 aRet = uno::makeAny( maBubbleTitle );
530 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 )
531 aRet = uno::makeAny( maBubbleText );
532 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 )
533 aRet = uno::makeAny( mbShowBubble );
534 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 )
535 aRet = uno::makeAny( maBubbleImageURL );
536 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 )
537 aRet = uno::makeAny( mrJob );
538 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0 )
539 aRet = uno::makeAny( mbShowMenuIcon );
540 else
541 throw beans::UnknownPropertyException();
543 return aRet;
546 //------------------------------------------------------------------------------
547 void UpdateCheckUI::addPropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
548 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
549 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
551 //no bound properties
554 //------------------------------------------------------------------------------
555 void UpdateCheckUI::removePropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
556 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
557 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
559 //no bound properties
562 //------------------------------------------------------------------------------
563 void UpdateCheckUI::addVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
564 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
565 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
567 //no vetoable properties
570 //------------------------------------------------------------------------------
571 void UpdateCheckUI::removeVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
572 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
573 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
575 //no vetoable properties
579 //------------------------------------------------------------------------------
580 //------------------------------------------------------------------------------
581 //------------------------------------------------------------------------------
582 BubbleWindow * UpdateCheckUI::GetBubbleWindow()
584 if ( !mpIconSysWin )
585 return NULL;
587 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
588 if( aIconRect.IsEmpty() )
589 return NULL;
591 BubbleWindow* pBubbleWin = mpBubbleWin;
593 if ( !pBubbleWin ) {
594 pBubbleWin = new BubbleWindow( mpIconSysWin,
595 XubString( maBubbleTitle ),
596 XubString( maBubbleText ),
597 maBubbleImage );
598 mbBubbleChanged = false;
600 else if ( mbBubbleChanged ) {
601 pBubbleWin->SetTitleAndText( XubString( maBubbleTitle ),
602 XubString( maBubbleText ),
603 maBubbleImage );
604 mbBubbleChanged = false;
607 Point aWinPos = aIconRect.BottomCenter();
609 pBubbleWin->SetTipPosPixel( aWinPos );
611 return pBubbleWin;
614 //------------------------------------------------------------------------------
615 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon )
617 vos::OGuard aGuard( Application::GetSolarMutex() );
619 maWaitTimer.Stop();
620 maTimeoutTimer.Stop();
622 if ( mpBubbleWin )
624 delete mpBubbleWin;
625 mpBubbleWin = NULL;
628 if ( bRemoveIcon )
630 try {
631 if ( mpIconMBar && ( mnIconID != 0 ) )
633 mpIconMBar->RemoveMenuBarButton( mnIconID );
634 mpIconMBar = NULL;
635 mnIconID = 0;
638 catch ( ... ) {
639 mpIconMBar = NULL;
640 mnIconID = 0;
643 mpIconSysWin = NULL;
647 // -----------------------------------------------------------------------
648 IMPL_LINK( UpdateCheckUI, ClickHdl, USHORT*, EMPTYARG )
650 vos::OGuard aGuard( Application::GetSolarMutex() );
652 maWaitTimer.Stop();
653 if ( mpBubbleWin )
654 mpBubbleWin->Show( FALSE );
656 if ( mrJob.is() )
658 try {
659 uno::Sequence<beans::NamedValue> aEmpty;
660 mrJob->execute( aEmpty );
662 catch(const uno::Exception&) {
663 ErrorBox( NULL, ResId( MSG_ERR_NO_WEBBROWSER_FOUND, *mpSfxResMgr )).Execute();
667 return 0;
670 // -----------------------------------------------------------------------
671 IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg*, pData )
673 if ( pData->bHighlight )
674 maWaitTimer.Start();
675 else
676 RemoveBubbleWindow( false );
678 return 0;
681 // -----------------------------------------------------------------------
682 IMPL_LINK( UpdateCheckUI, WaitTimeOutHdl, Timer*, EMPTYARG )
684 vos::OGuard aGuard( Application::GetSolarMutex() );
686 mpBubbleWin = GetBubbleWindow();
688 if ( mpBubbleWin )
690 mpBubbleWin->Show();
693 return 0;
696 // -----------------------------------------------------------------------
697 IMPL_LINK( UpdateCheckUI, TimeOutHdl, Timer*, EMPTYARG )
699 RemoveBubbleWindow( false );
701 return 0;
704 // -----------------------------------------------------------------------
705 IMPL_LINK( UpdateCheckUI, UserEventHdl, UpdateCheckUI*, EMPTYARG )
707 vos::OGuard aGuard( Application::GetSolarMutex() );
709 Window *pTopWin = Application::GetFirstTopLevelWindow();
710 Window *pActiveWin = Application::GetActiveTopWindow();
711 SystemWindow *pActiveSysWin = NULL;
713 Window *pBubbleWin = NULL;
714 if ( mpBubbleWin )
715 pBubbleWin = mpBubbleWin;
717 if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() )
718 pActiveSysWin = pActiveWin->GetSystemWindow();
720 if ( pActiveWin == pBubbleWin )
721 pActiveSysWin = NULL;
723 while ( !pActiveSysWin && pTopWin )
725 if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() )
726 pActiveSysWin = pTopWin->GetSystemWindow();
727 if ( !pActiveSysWin )
728 pTopWin = Application::GetNextTopLevelWindow( pTopWin );
731 if ( pActiveSysWin )
732 AddMenuBarIcon( pActiveSysWin, true );
734 return 0;
737 // -----------------------------------------------------------------------
738 IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent*, pEvent )
740 ULONG nEventID = pEvent->GetId();
742 if ( VCLEVENT_OBJECT_DYING == nEventID )
744 vos::OGuard aGuard( Application::GetSolarMutex() );
745 if ( mpIconSysWin == pEvent->GetWindow() )
747 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
748 RemoveBubbleWindow( true );
751 else if ( VCLEVENT_WINDOW_MENUBARADDED == nEventID )
753 vos::OGuard aGuard( Application::GetSolarMutex() );
754 Window *pWindow = pEvent->GetWindow();
755 if ( pWindow )
757 SystemWindow *pSysWin = pWindow->GetSystemWindow();
758 if ( pSysWin )
760 AddMenuBarIcon( pSysWin, false );
764 else if ( VCLEVENT_WINDOW_MENUBARREMOVED == nEventID )
766 vos::OGuard aGuard( Application::GetSolarMutex() );
767 MenuBar *pMBar = (MenuBar*) pEvent->GetData();
768 if ( pMBar && ( pMBar == mpIconMBar ) )
769 RemoveBubbleWindow( true );
771 else if ( ( nEventID == VCLEVENT_WINDOW_MOVE ) ||
772 ( nEventID == VCLEVENT_WINDOW_RESIZE ) )
774 vos::OGuard aGuard( Application::GetSolarMutex() );
775 if ( ( mpIconSysWin == pEvent->GetWindow() ) &&
776 ( mpBubbleWin != NULL ) && ( mpIconMBar != NULL ) )
778 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
779 Point aWinPos = aIconRect.BottomCenter();
780 mpBubbleWin->SetTipPosPixel( aWinPos );
781 if ( mpBubbleWin->IsVisible() )
782 mpBubbleWin->Show(); // This will recalc the screen positon of the bubble
786 return 0;
789 //------------------------------------------------------------------------------
790 IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent *, pEvent)
792 switch (pEvent->GetId())
794 case VCLEVENT_WINDOW_SHOW:
795 case VCLEVENT_WINDOW_ACTIVATE:
796 case VCLEVENT_WINDOW_GETFOCUS: {
797 vos::OGuard aGuard( Application::GetSolarMutex() );
799 Window *pWindow = static_cast< VclWindowEvent * >(pEvent)->GetWindow();
800 if ( pWindow && pWindow->IsTopWindow() )
802 SystemWindow *pSysWin = pWindow->GetSystemWindow();
803 MenuBar *pMBar = pSysWin->GetMenuBar();
804 if ( pSysWin && pMBar )
806 AddMenuBarIcon( pSysWin, true );
809 break;
812 return 0;
814 //------------------------------------------------------------------------------
815 //------------------------------------------------------------------------------
816 //------------------------------------------------------------------------------
818 #define TIP_HEIGHT 15
819 #define TIP_WIDTH 7
820 #define TIP_RIGHT_OFFSET 18
821 #define BUBBLE_BORDER 10
822 #define TEXT_MAX_WIDTH 300
823 #define TEXT_MAX_HEIGHT 200
824 #define INITIAL_SHOW_TIME 10000
826 //------------------------------------------------------------------------------
827 BubbleWindow::BubbleWindow( Window* pParent, const XubString& rTitle,
828 const XubString& rText, const Image& rImage )
829 : FloatingWindow( pParent, WB_SYSTEMWINDOW
830 | WB_OWNERDRAWDECORATION
831 | WB_NOBORDER
833 , maBubbleTitle( rTitle )
834 , maBubbleText( rText )
835 , maBubbleImage( rImage )
836 , maMaxTextSize( TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT )
837 , mnTipOffset( 0 )
839 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
842 //------------------------------------------------------------------------------
843 BubbleWindow::~BubbleWindow()
847 //------------------------------------------------------------------------------
848 void BubbleWindow::Resize()
850 vos::OGuard aGuard( Application::GetSolarMutex() );
852 FloatingWindow::Resize();
854 Size aSize = GetSizePixel();
856 if ( ( aSize.Height() < 20 ) || ( aSize.Width() < 60 ) )
857 return;
859 Rectangle aRect( 0, TIP_HEIGHT, aSize.Width(), aSize.Height() - TIP_HEIGHT );
860 maRectPoly = Polygon( aRect, 6, 6 );
861 Region aRegion( maRectPoly );
862 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
864 Point aPointArr[4];
865 aPointArr[0] = Point( nTipOffset, TIP_HEIGHT );
866 aPointArr[1] = Point( nTipOffset, 0 );
867 aPointArr[2] = Point( nTipOffset + TIP_WIDTH , TIP_HEIGHT );
868 aPointArr[3] = Point( nTipOffset, TIP_HEIGHT );
869 maTriPoly = Polygon( 4, aPointArr );
870 Region aTriRegion( maTriPoly );
872 aRegion.Union( aTriRegion);
873 maBounds = aRegion;
875 SetWindowRegionPixel( maBounds );
878 //------------------------------------------------------------------------------
879 void BubbleWindow::SetTitleAndText( const XubString& rTitle,
880 const XubString& rText,
881 const Image& rImage )
883 maBubbleTitle = rTitle;
884 maBubbleText = rText;
885 maBubbleImage = rImage;
887 Resize();
890 //------------------------------------------------------------------------------
891 void BubbleWindow::Paint( const Rectangle& )
893 vos::OGuard aGuard( Application::GetSolarMutex() );
895 LineInfo aThickLine( LINE_SOLID, 2 );
897 DrawPolyLine( maRectPoly, aThickLine );
898 DrawPolyLine( maTriPoly );
900 Color aOldLine = GetLineColor();
901 Size aSize = GetSizePixel();
902 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
904 SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
905 DrawLine( Point( nTipOffset+2, TIP_HEIGHT ),
906 Point( nTipOffset + TIP_WIDTH -1 , TIP_HEIGHT ),
907 aThickLine );
908 SetLineColor( aOldLine );
910 //Image aImage = InfoBox::GetStandardImage();
911 Size aImgSize = maBubbleImage.GetSizePixel();
913 DrawImage( Point( BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT ), maBubbleImage );
915 Font aOldFont = GetFont();
916 Font aBoldFont = aOldFont;
917 aBoldFont.SetWeight( WEIGHT_BOLD );
919 SetFont( aBoldFont );
920 Rectangle aTitleRect = maTitleRect;
921 aTitleRect.Move( aImgSize.Width(), 0 );
922 DrawText( aTitleRect, maBubbleTitle, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
924 SetFont( aOldFont );
925 Rectangle aTextRect = maTextRect;
926 aTextRect.Move( aImgSize.Width(), 0 );
927 DrawText( aTextRect, maBubbleText, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
930 //------------------------------------------------------------------------------
931 void BubbleWindow::MouseButtonDown( const MouseEvent& )
933 Show( FALSE );
936 //------------------------------------------------------------------------------
937 void BubbleWindow::Show( BOOL bVisible, USHORT nFlags )
939 vos::OGuard aGuard( Application::GetSolarMutex() );
941 if ( !bVisible )
943 FloatingWindow::Show( bVisible );
944 return;
947 // don't show bubbles without a text
948 if ( ( maBubbleTitle.Len() == 0 ) && ( maBubbleText.Len() == 0 ) )
949 return;
951 Size aWindowSize = GetSizePixel();
953 // Image aImage = InfoBox::GetStandardImage();
954 Size aImgSize = maBubbleImage.GetSizePixel();
956 RecalcTextRects();
958 aWindowSize.setHeight( maTitleRect.GetHeight() * 7 / 4+ maTextRect.GetHeight() +
959 3 * BUBBLE_BORDER + TIP_HEIGHT );
961 if ( maTitleRect.GetWidth() > maTextRect.GetWidth() )
962 aWindowSize.setWidth( maTitleRect.GetWidth() );
963 else
964 aWindowSize.setWidth( maTextRect.GetWidth() );
966 aWindowSize.setWidth( aWindowSize.Width() + 3 * BUBBLE_BORDER + aImgSize.Width() );
968 if ( aWindowSize.Height() < aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER )
969 aWindowSize.setHeight( aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER );
971 Point aPos;
972 aPos.X() = maTipPos.X() - aWindowSize.Width() + TIP_RIGHT_OFFSET;
973 aPos.Y() = maTipPos.Y();
974 Point aScreenPos = GetParent()->OutputToAbsoluteScreenPixel( aPos );
975 if ( aScreenPos.X() < 0 )
977 mnTipOffset = aScreenPos.X();
978 aPos.X() -= mnTipOffset;
980 SetPosSizePixel( aPos, aWindowSize );
982 FloatingWindow::Show( bVisible, nFlags );
985 //------------------------------------------------------------------------------
986 void BubbleWindow::RecalcTextRects()
988 Size aTotalSize;
989 BOOL bFinished = FALSE;
990 Font aOldFont = GetFont();
991 Font aBoldFont = aOldFont;
993 aBoldFont.SetWeight( WEIGHT_BOLD );
995 while ( !bFinished )
997 SetFont( aBoldFont );
999 maTitleRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
1000 maBubbleTitle,
1001 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
1003 SetFont( aOldFont );
1004 maTextRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
1005 maBubbleText,
1006 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
1008 if ( maTextRect.GetHeight() < 10 )
1009 maTextRect.setHeight( 10 );
1011 aTotalSize.setHeight( maTitleRect.GetHeight() +
1012 aBoldFont.GetHeight() * 3 / 4 +
1013 maTextRect.GetHeight() +
1014 3 * BUBBLE_BORDER + TIP_HEIGHT );
1015 if ( aTotalSize.Height() > maMaxTextSize.Height() )
1017 maMaxTextSize.Width() = maMaxTextSize.Width() * 3 / 2;
1018 maMaxTextSize.Height() = maMaxTextSize.Height() * 3 / 2;
1020 else
1021 bFinished = TRUE;
1023 maTitleRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT );
1024 maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetHeight() * 3 / 4 );
1026 //------------------------------------------------------------------------------
1027 //------------------------------------------------------------------------------
1028 //------------------------------------------------------------------------------
1030 } // anonymous namespace
1032 //------------------------------------------------------------------------------
1034 static uno::Reference<uno::XInterface> SAL_CALL
1035 createInstance(const uno::Reference<uno::XComponentContext>& xContext)
1037 return *new UpdateCheckUI(xContext);
1040 //------------------------------------------------------------------------------
1042 static const cppu::ImplementationEntry kImplementations_entries[] =
1045 createInstance,
1046 getImplementationName,
1047 getServiceNames,
1048 cppu::createSingleComponentFactory,
1049 NULL,
1052 { NULL, NULL, NULL, NULL, NULL, 0 }
1055 //------------------------------------------------------------------------------
1057 extern "C" void SAL_CALL
1058 component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
1060 *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
1063 //------------------------------------------------------------------------------
1065 extern "C" sal_Bool SAL_CALL
1066 component_writeInfo(void *pServiceManager, void *pRegistryKey)
1068 return cppu::component_writeInfoHelper(
1069 pServiceManager,
1070 pRegistryKey,
1071 kImplementations_entries
1075 //------------------------------------------------------------------------------
1077 extern "C" void *
1078 component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
1080 return cppu::component_getFactoryHelper(
1081 pszImplementationName,
1082 pServiceManager,
1083 pRegistryKey,
1084 kImplementations_entries) ;