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"
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")
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");
88 //------------------------------------------------------------------------------
90 static rtl::OUString
getImplementationName()
92 return UNISTRING( "vnd.sun.UpdateCheckUI");
95 //------------------------------------------------------------------------------
100 //------------------------------------------------------------------------------
101 class BubbleWindow
: public FloatingWindow
107 XubString maBubbleTitle
;
108 XubString maBubbleText
;
111 Rectangle maTitleRect
;
112 Rectangle maTextRect
;
116 void RecalcTextRects();
119 BubbleWindow( Window
* pParent
, const XubString
& rTitle
,
120 const XubString
& rText
, const Image
& rImage
);
123 virtual void MouseButtonDown( const MouseEvent
& rMEvt
);
124 virtual void Paint( const Rectangle
& rRect
);
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
;
142 BubbleWindow
* mpBubbleWin
;
143 SystemWindow
* mpIconSysWin
;
148 Timer maTimeoutTimer
;
149 Link maWindowEventHdl
;
150 Link maApplicationEventHdl
;
153 bool mbBubbleChanged
;
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
);
175 UpdateCheckUI(const uno::Reference
<uno::XComponentContext
>&);
176 virtual ~UpdateCheckUI();
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
);
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
);
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
) :
217 , mpBubbleWin( NULL
)
218 , mpIconSysWin( NULL
)
220 , mbShowBubble( false )
221 , mbShowMenuIcon( false )
222 , mbBubbleChanged( false )
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 );
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" ),
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 //------------------------------------------------------------------------------
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
) )
303 //------------------------------------------------------------------------------
304 Image
UpdateCheckUI::GetMenuBarIcon( MenuBar
* pMBar
)
307 Window
*pMBarWin
= pMBar
->GetWindow();
308 sal_uInt32 nMBarHeight
= 20;
311 nMBarHeight
= pMBarWin
->GetOutputSizePixel().getHeight();
313 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) {
314 if ( nMBarHeight
>= 35 )
315 nResID
= RID_UPDATE_AVAILABLE_26_HC
;
317 nResID
= RID_UPDATE_AVAILABLE_16_HC
;
319 if ( nMBarHeight
>= 35 )
320 nResID
= RID_UPDATE_AVAILABLE_26
;
322 nResID
= RID_UPDATE_AVAILABLE_16
;
325 return Image( ResId( nResID
, *mpUpdResMgr
) );
328 //------------------------------------------------------------------------------
329 Image
UpdateCheckUI::GetBubbleImage( ::rtl::OUString
&rURL
)
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" ) ),
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
);
357 aImage
= Image( xGraphic
);
361 catch( uno::Exception
& )
366 if ( aImage
.GetSizePixel().Width() == 0 )
367 aImage
= InfoBox::GetStandardImage();
372 //------------------------------------------------------------------------------
373 void UpdateCheckUI::AddMenuBarIcon( SystemWindow
*pSysWin
, bool bAddEventHdl
)
375 if ( ! mbShowMenuIcon
)
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 );
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();
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
)
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 ) {
463 if ( aString
!= maBubbleTitle
) {
464 maBubbleTitle
= aString
;
465 mbBubbleChanged
= true;
468 else if( rPropertyName
.compareToAscii( PROPERTY_TEXT
) == 0 ) {
470 if ( aString
!= maBubbleText
) {
471 maBubbleText
= aString
;
472 mbBubbleChanged
= true;
475 else if( rPropertyName
.compareToAscii( PROPERTY_IMAGE
) == 0 ) {
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
;
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
;
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
;
505 Application::PostUserEvent( LINK( this, UpdateCheckUI
, UserEventHdl
) );
507 RemoveBubbleWindow( true );
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() );
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
);
538 throw beans::UnknownPropertyException();
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()
584 Rectangle aIconRect
= mpIconMBar
->GetMenuBarButtonRectPixel( mnIconID
);
585 if( aIconRect
.IsEmpty() )
588 BubbleWindow
* pBubbleWin
= mpBubbleWin
;
591 pBubbleWin
= new BubbleWindow( mpIconSysWin
,
592 XubString( maBubbleTitle
),
593 XubString( maBubbleText
),
595 mbBubbleChanged
= false;
597 else if ( mbBubbleChanged
) {
598 pBubbleWin
->SetTitleAndText( XubString( maBubbleTitle
),
599 XubString( maBubbleText
),
601 mbBubbleChanged
= false;
604 Point aWinPos
= aIconRect
.BottomCenter();
606 pBubbleWin
->SetTipPosPixel( aWinPos
);
611 //------------------------------------------------------------------------------
612 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon
)
614 vos::OGuard
aGuard( Application::GetSolarMutex() );
617 maTimeoutTimer
.Stop();
628 if ( mpIconMBar
&& ( mnIconID
!= 0 ) )
630 mpIconMBar
->RemoveMenuBarButton( mnIconID
);
644 // -----------------------------------------------------------------------
645 IMPL_LINK( UpdateCheckUI
, ClickHdl
, USHORT
*, EMPTYARG
)
647 vos::OGuard
aGuard( Application::GetSolarMutex() );
651 mpBubbleWin
->Show( FALSE
);
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();
667 // -----------------------------------------------------------------------
668 IMPL_LINK( UpdateCheckUI
, HighlightHdl
, MenuBar::MenuBarButtonCallbackArg
*, pData
)
670 if ( pData
->bHighlight
)
673 RemoveBubbleWindow( false );
678 // -----------------------------------------------------------------------
679 IMPL_LINK( UpdateCheckUI
, WaitTimeOutHdl
, Timer
*, EMPTYARG
)
681 vos::OGuard
aGuard( Application::GetSolarMutex() );
683 mpBubbleWin
= GetBubbleWindow();
693 // -----------------------------------------------------------------------
694 IMPL_LINK( UpdateCheckUI
, TimeOutHdl
, Timer
*, EMPTYARG
)
696 RemoveBubbleWindow( false );
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
;
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
);
729 AddMenuBarIcon( pActiveSysWin
, true );
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();
754 SystemWindow
*pSysWin
= pWindow
->GetSystemWindow();
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
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 );
811 //------------------------------------------------------------------------------
812 //------------------------------------------------------------------------------
813 //------------------------------------------------------------------------------
815 #define TIP_HEIGHT 15
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
830 , maBubbleTitle( rTitle
)
831 , maBubbleText( rText
)
832 , maBubbleImage( rImage
)
833 , maMaxTextSize( TEXT_MAX_WIDTH
, TEXT_MAX_HEIGHT
)
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 ) )
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
;
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
);
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
;
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
),
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
);
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
& )
933 //------------------------------------------------------------------------------
934 void BubbleWindow::Show( BOOL bVisible
, USHORT nFlags
)
936 vos::OGuard
aGuard( Application::GetSolarMutex() );
940 FloatingWindow::Show( bVisible
);
944 // don't show bubbles without a text
945 if ( ( maBubbleTitle
.Len() == 0 ) && ( maBubbleText
.Len() == 0 ) )
948 Size aWindowSize
= GetSizePixel();
950 // Image aImage = InfoBox::GetStandardImage();
951 Size aImgSize
= maBubbleImage
.GetSizePixel();
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() );
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
);
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()
986 BOOL bFinished
= FALSE
;
987 Font aOldFont
= GetFont();
988 Font aBoldFont
= aOldFont
;
990 aBoldFont
.SetWeight( WEIGHT_BOLD
);
994 SetFont( aBoldFont
);
996 maTitleRect
= GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize
),
998 TEXT_DRAW_MULTILINE
| TEXT_DRAW_WORDBREAK
);
1000 SetFont( aOldFont
);
1001 maTextRect
= GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize
),
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;
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
[] =
1043 getImplementationName
,
1045 cppu::createSingleComponentFactory
,
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(
1068 kImplementations_entries
1072 //------------------------------------------------------------------------------
1075 component_getFactory(const sal_Char
*pszImplementationName
, void *pServiceManager
, void *pRegistryKey
)
1077 return cppu::component_getFactoryHelper(
1078 pszImplementationName
,
1081 kImplementations_entries
) ;