1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <cppuhelper/implbase3.hxx>
24 #include <cppuhelper/implementationentry.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <com/sun/star/lang/XServiceInfo.hpp>
27 #include <com/sun/star/lang/XComponent.hpp>
28 #include <com/sun/star/document/XDocumentEventListener.hpp>
29 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
32 #include <com/sun/star/graphic/GraphicProvider.hpp>
33 #include <com/sun/star/graphic/XGraphicProvider.hpp>
34 #include <com/sun/star/task/XJob.hpp>
36 #include <comphelper/processfactory.hxx>
38 #include <osl/mutex.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/floatwin.hxx>
42 #include <vcl/timer.hxx>
43 #include <vcl/idle.hxx>
44 #include <vcl/menu.hxx>
45 #include <vcl/outdev.hxx>
46 #include <vcl/layout.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <vcl/lineinfo.hxx>
49 #include <vcl/button.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/svapp.hxx>
52 #include <sfx2/sfx.hrc>
53 #include "rtl/ustrbuf.hxx"
55 #include "updatecheckui.hrc"
57 #define STR_NO_WEBBROWSER_FOUND (RID_SFX_APP_START + 7)
59 #define PROPERTY_TITLE "BubbleHeading"
60 #define PROPERTY_TEXT "BubbleText"
61 #define PROPERTY_IMAGE "BubbleImageURL"
62 #define PROPERTY_SHOW_BUBBLE "BubbleVisible"
63 #define PROPERTY_CLICK_HDL "MenuClickHDL"
64 #define PROPERTY_SHOW_MENUICON "MenuIconVisible"
66 using namespace ::com::sun::star
;
70 static uno::Sequence
< OUString
> getServiceNames()
72 uno::Sequence
< OUString
> aServiceList(1);
73 aServiceList
[0] = "com.sun.star.setup.UpdateCheckUI";
79 static OUString
getImplementationName()
81 return OUString("vnd.sun.UpdateCheckUI");
90 class BubbleWindow
: public FloatingWindow
96 OUString maBubbleTitle
;
97 OUString maBubbleText
;
100 Rectangle maTitleRect
;
101 Rectangle maTextRect
;
105 void RecalcTextRects();
108 BubbleWindow( vcl::Window
* pParent
, const OUString
& rTitle
,
109 const OUString
& rText
, const Image
& rImage
);
110 virtual ~BubbleWindow();
112 virtual void MouseButtonDown( const MouseEvent
& rMEvt
) SAL_OVERRIDE
;
113 virtual void Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
) SAL_OVERRIDE
;
114 void Resize() SAL_OVERRIDE
;
115 void Show( bool bVisible
= true, sal_uInt16 nFlags
= SHOW_NOACTIVATE
);
116 void SetTipPosPixel( const Point
& rTipPos
) { maTipPos
= rTipPos
; }
117 void SetTitleAndText( const OUString
& rTitle
, const OUString
& rText
,
118 const Image
& rImage
);
122 class UpdateCheckUI
: public ::cppu::WeakImplHelper3
123 < lang::XServiceInfo
, document::XDocumentEventListener
, beans::XPropertySet
>
125 uno::Reference
< uno::XComponentContext
> m_xContext
;
126 uno::Reference
< task::XJob
> mrJob
;
127 OUString maBubbleTitle
;
128 OUString maBubbleText
;
129 OUString maBubbleImageURL
;
131 VclPtr
<BubbleWindow
> mpBubbleWin
;
132 VclPtr
<SystemWindow
> mpIconSysWin
;
137 Timer maTimeoutTimer
;
138 Link
<> maWindowEventHdl
;
139 Link
<> maApplicationEventHdl
;
142 bool mbBubbleChanged
;
146 DECL_LINK(ClickHdl
, void *);
147 DECL_LINK( HighlightHdl
, MenuBar::MenuBarButtonCallbackArg
* );
148 DECL_LINK_TYPED(WaitTimeOutHdl
, Idle
*, void);
149 DECL_LINK_TYPED(TimeOutHdl
, Timer
*, void);
150 DECL_LINK(UserEventHdl
, void *);
151 DECL_LINK( WindowEventHdl
, VclWindowEvent
* );
152 DECL_LINK( ApplicationEventHdl
, VclSimpleEvent
* );
154 BubbleWindow
* GetBubbleWindow();
155 void RemoveBubbleWindow( bool bRemoveIcon
);
156 Image
GetMenuBarIcon( MenuBar
* pMBar
);
157 void AddMenuBarIcon( SystemWindow
* pSysWin
, bool bAddEventHdl
);
158 Image
GetBubbleImage( OUString
&rURL
);
161 UpdateCheckUI(const uno::Reference
<uno::XComponentContext
>&);
162 virtual ~UpdateCheckUI();
165 virtual OUString SAL_CALL
getImplementationName()
166 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
167 virtual sal_Bool SAL_CALL
supportsService(OUString
const & serviceName
)
168 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
169 virtual uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
170 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
172 // XDocumentEventListener
173 virtual void SAL_CALL
documentEventOccured(const document::DocumentEvent
& Event
)
174 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
175 virtual void SAL_CALL
disposing(const lang::EventObject
& Event
)
176 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
179 virtual uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
getPropertySetInfo()
180 throw ( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
181 virtual void SAL_CALL
setPropertyValue(const OUString
& PropertyName
, const uno::Any
& aValue
)
182 throw( beans::UnknownPropertyException
, beans::PropertyVetoException
,
183 lang::IllegalArgumentException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
184 virtual uno::Any SAL_CALL
getPropertyValue(const OUString
& PropertyName
)
185 throw ( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
186 virtual void SAL_CALL
addPropertyChangeListener(const OUString
& PropertyName
,
187 const uno::Reference
< beans::XPropertyChangeListener
> & aListener
)
188 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
189 virtual void SAL_CALL
removePropertyChangeListener(const OUString
& PropertyName
,
190 const uno::Reference
< beans::XPropertyChangeListener
> & aListener
)
191 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
192 virtual void SAL_CALL
addVetoableChangeListener(const OUString
& PropertyName
,
193 const uno::Reference
< beans::XVetoableChangeListener
> & aListener
)
194 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
195 virtual void SAL_CALL
removeVetoableChangeListener(const OUString
& PropertyName
,
196 const uno::Reference
< beans::XVetoableChangeListener
> & aListener
)
197 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
201 UpdateCheckUI::UpdateCheckUI(const uno::Reference
<uno::XComponentContext
>& xContext
) :
204 , mbShowBubble( false )
205 , mbShowMenuIcon( false )
206 , mbBubbleChanged( false )
209 mpUpdResMgr
= ResMgr::CreateResMgr( "updchk" );
210 mpSfxResMgr
= ResMgr::CreateResMgr( "sfx" );
212 maBubbleImage
= GetBubbleImage( maBubbleImageURL
);
214 maWaitIdle
.SetPriority( SchedulerPriority::LOWEST
);
215 maWaitIdle
.SetIdleHdl( LINK( this, UpdateCheckUI
, WaitTimeOutHdl
) );
217 maTimeoutTimer
.SetTimeout( 10000 );
218 maTimeoutTimer
.SetTimeoutHdl( LINK( this, UpdateCheckUI
, TimeOutHdl
) );
220 uno::Reference
< document::XDocumentEventBroadcaster
> xBroadcaster( frame::theGlobalEventBroadcaster::get(m_xContext
) );
221 xBroadcaster
->addDocumentEventListener( this );
223 maWindowEventHdl
= LINK( this, UpdateCheckUI
, WindowEventHdl
);
224 maApplicationEventHdl
= LINK( this, UpdateCheckUI
, ApplicationEventHdl
);
225 Application::AddEventListener( maApplicationEventHdl
);
229 UpdateCheckUI::~UpdateCheckUI()
231 Application::RemoveEventListener( maApplicationEventHdl
);
232 RemoveBubbleWindow( true );
239 UpdateCheckUI::getImplementationName() throw (uno::RuntimeException
, std::exception
)
241 return ::getImplementationName();
245 uno::Sequence
< OUString
> SAL_CALL
246 UpdateCheckUI::getSupportedServiceNames() throw (uno::RuntimeException
, std::exception
)
248 return ::getServiceNames();
252 UpdateCheckUI::supportsService( OUString
const & serviceName
) throw (uno::RuntimeException
, std::exception
)
254 return cppu::supportsService(this, serviceName
);
258 Image
UpdateCheckUI::GetMenuBarIcon( MenuBar
* pMBar
)
261 vcl::Window
*pMBarWin
= pMBar
->GetWindow();
262 sal_uInt32 nMBarHeight
= 20;
265 nMBarHeight
= pMBarWin
->GetOutputSizePixel().getHeight();
267 if ( nMBarHeight
>= 35 )
268 nResID
= RID_UPDATE_AVAILABLE_26
;
270 nResID
= RID_UPDATE_AVAILABLE_16
;
272 return Image( ResId( nResID
, *mpUpdResMgr
) );
276 Image
UpdateCheckUI::GetBubbleImage( OUString
&rURL
)
280 if ( !maBubbleImageURL
.isEmpty() )
282 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
285 throw uno::RuntimeException(
286 "UpdateCheckUI: unable to obtain service manager from component context" );
290 uno::Reference
< graphic::XGraphicProvider
> xGraphProvider(graphic::GraphicProvider::create(xContext
));
291 uno::Sequence
< beans::PropertyValue
> aMediaProps( 1 );
292 aMediaProps
[0].Name
= "URL";
293 aMediaProps
[0].Value
<<= rURL
;
295 uno::Reference
< graphic::XGraphic
> xGraphic
= xGraphProvider
->queryGraphic( aMediaProps
);
298 aImage
= Image( xGraphic
);
301 catch( const uno::Exception
& )
306 if ( aImage
.GetSizePixel().Width() == 0 )
307 aImage
= InfoBox::GetStandardImage();
313 void UpdateCheckUI::AddMenuBarIcon( SystemWindow
*pSysWin
, bool bAddEventHdl
)
315 if ( ! mbShowMenuIcon
)
318 SolarMutexGuard aGuard
;
320 MenuBar
*pActiveMBar
= pSysWin
->GetMenuBar();
321 if ( ( pSysWin
!= mpIconSysWin
) || ( pActiveMBar
!= mpIconMBar
) )
323 if ( bAddEventHdl
&& mpIconSysWin
)
324 mpIconSysWin
->RemoveEventListener( maWindowEventHdl
);
326 RemoveBubbleWindow( true );
331 if( !maBubbleTitle
.isEmpty() )
332 aBuf
.append( maBubbleTitle
);
333 if( !maBubbleText
.isEmpty() )
335 if( !maBubbleTitle
.isEmpty() )
336 aBuf
.appendAscii( "\n\n" );
337 aBuf
.append( maBubbleText
);
340 Image aImage
= GetMenuBarIcon( pActiveMBar
);
341 mnIconID
= pActiveMBar
->AddMenuBarButton( aImage
,
342 LINK( this, UpdateCheckUI
, ClickHdl
),
343 aBuf
.makeStringAndClear()
345 pActiveMBar
->SetMenuBarButtonHighlightHdl( mnIconID
,
346 LINK( this, UpdateCheckUI
, HighlightHdl
) );
348 mpIconMBar
= pActiveMBar
;
349 mpIconSysWin
= pSysWin
;
350 if ( bAddEventHdl
&& mpIconSysWin
)
351 mpIconSysWin
->AddEventListener( maWindowEventHdl
);
354 if ( mbShowBubble
&& pActiveMBar
)
356 mpBubbleWin
= GetBubbleWindow();
359 mpBubbleWin
->Show( true );
360 maTimeoutTimer
.Start();
362 mbShowBubble
= false;
367 void SAL_CALL
UpdateCheckUI::documentEventOccured(const document::DocumentEvent
& rEvent
)
368 throw (uno::RuntimeException
, std::exception
)
370 SolarMutexGuard aGuard
;
372 if( rEvent
.EventName
== "OnPrepareViewClosing" )
374 RemoveBubbleWindow( true );
379 void SAL_CALL
UpdateCheckUI::disposing(const lang::EventObject
&)
380 throw (uno::RuntimeException
, std::exception
)
385 uno::Reference
< beans::XPropertySetInfo
> UpdateCheckUI::getPropertySetInfo()
386 throw ( uno::RuntimeException
, std::exception
)
392 void UpdateCheckUI::setPropertyValue(const OUString
& rPropertyName
,
393 const uno::Any
& rValue
)
394 throw( beans::UnknownPropertyException
, beans::PropertyVetoException
,
395 lang::IllegalArgumentException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
397 SolarMutexGuard aGuard
;
401 if( rPropertyName
== PROPERTY_TITLE
) {
403 if ( aString
!= maBubbleTitle
) {
404 maBubbleTitle
= aString
;
405 mbBubbleChanged
= true;
408 else if( rPropertyName
== PROPERTY_TEXT
) {
410 if ( aString
!= maBubbleText
) {
411 maBubbleText
= aString
;
412 mbBubbleChanged
= true;
415 else if( rPropertyName
== PROPERTY_IMAGE
) {
417 if ( aString
!= maBubbleImageURL
) {
418 maBubbleImageURL
= aString
;
419 maBubbleImage
= GetBubbleImage( maBubbleImageURL
);
420 mbBubbleChanged
= true;
423 else if( rPropertyName
== PROPERTY_SHOW_BUBBLE
) {
424 rValue
>>= mbShowBubble
;
426 Application::PostUserEvent( LINK( this, UpdateCheckUI
, UserEventHdl
) );
427 else if ( mpBubbleWin
)
428 mpBubbleWin
->Show( false );
430 else if( rPropertyName
== PROPERTY_CLICK_HDL
) {
431 uno::Reference
< task::XJob
> aJob
;
436 throw lang::IllegalArgumentException();
438 else if (rPropertyName
== PROPERTY_SHOW_MENUICON
) {
439 bool bShowMenuIcon
= false;
440 rValue
>>= bShowMenuIcon
;
441 if ( bShowMenuIcon
!= mbShowMenuIcon
)
443 mbShowMenuIcon
= bShowMenuIcon
;
445 Application::PostUserEvent( LINK( this, UpdateCheckUI
, UserEventHdl
) );
447 RemoveBubbleWindow( true );
451 throw beans::UnknownPropertyException();
453 if ( mbBubbleChanged
&& mpBubbleWin
)
454 mpBubbleWin
->Show( false );
458 uno::Any
UpdateCheckUI::getPropertyValue(const OUString
& rPropertyName
)
459 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
461 SolarMutexGuard aGuard
;
465 if( rPropertyName
== PROPERTY_TITLE
)
466 aRet
= uno::makeAny( maBubbleTitle
);
467 else if( rPropertyName
== PROPERTY_TEXT
)
468 aRet
= uno::makeAny( maBubbleText
);
469 else if( rPropertyName
== PROPERTY_SHOW_BUBBLE
)
470 aRet
= uno::makeAny( mbShowBubble
);
471 else if( rPropertyName
== PROPERTY_IMAGE
)
472 aRet
= uno::makeAny( maBubbleImageURL
);
473 else if( rPropertyName
== PROPERTY_CLICK_HDL
)
474 aRet
= uno::makeAny( mrJob
);
475 else if( rPropertyName
== PROPERTY_SHOW_MENUICON
)
476 aRet
= uno::makeAny( mbShowMenuIcon
);
478 throw beans::UnknownPropertyException();
484 void UpdateCheckUI::addPropertyChangeListener( const OUString
& /*aPropertyName*/,
485 const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
486 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
488 //no bound properties
492 void UpdateCheckUI::removePropertyChangeListener( const OUString
& /*aPropertyName*/,
493 const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
494 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
496 //no bound properties
500 void UpdateCheckUI::addVetoableChangeListener( const OUString
& /*aPropertyName*/,
501 const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
502 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
504 //no vetoable properties
508 void UpdateCheckUI::removeVetoableChangeListener( const OUString
& /*aPropertyName*/,
509 const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
510 throw( beans::UnknownPropertyException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
)
512 //no vetoable properties
519 BubbleWindow
* UpdateCheckUI::GetBubbleWindow()
524 Rectangle aIconRect
= mpIconMBar
->GetMenuBarButtonRectPixel( mnIconID
);
525 if( aIconRect
.IsEmpty() )
528 BubbleWindow
* pBubbleWin
= mpBubbleWin
;
531 pBubbleWin
= new BubbleWindow( mpIconSysWin
, maBubbleTitle
,
532 maBubbleText
, maBubbleImage
);
533 mbBubbleChanged
= false;
535 else if ( mbBubbleChanged
) {
536 pBubbleWin
->SetTitleAndText( maBubbleTitle
, maBubbleText
,
538 mbBubbleChanged
= false;
541 Point aWinPos
= aIconRect
.BottomCenter();
543 pBubbleWin
->SetTipPosPixel( aWinPos
);
549 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon
)
551 SolarMutexGuard aGuard
;
554 maTimeoutTimer
.Stop();
558 mpBubbleWin
.disposeAndClear();
564 if ( mpIconMBar
&& ( mnIconID
!= 0 ) )
566 mpIconMBar
->RemoveMenuBarButton( mnIconID
);
581 IMPL_LINK_NOARG(UpdateCheckUI
, ClickHdl
)
583 SolarMutexGuard aGuard
;
587 mpBubbleWin
->Show( false );
592 uno::Sequence
<beans::NamedValue
> aEmpty
;
593 mrJob
->execute( aEmpty
);
595 catch(const uno::Exception
&) {
596 ScopedVclPtrInstance
<MessageDialog
>::Create( nullptr, ResId( STR_NO_WEBBROWSER_FOUND
, *mpSfxResMgr
))->Execute();
604 IMPL_LINK( UpdateCheckUI
, HighlightHdl
, MenuBar::MenuBarButtonCallbackArg
*, pData
)
606 if ( pData
->bHighlight
)
609 RemoveBubbleWindow( false );
615 IMPL_LINK_NOARG_TYPED(UpdateCheckUI
, WaitTimeOutHdl
, Idle
*, void)
617 SolarMutexGuard aGuard
;
619 mpBubbleWin
= GetBubbleWindow();
628 IMPL_LINK_NOARG_TYPED(UpdateCheckUI
, TimeOutHdl
, Timer
*, void)
630 RemoveBubbleWindow( false );
634 IMPL_LINK_NOARG(UpdateCheckUI
, UserEventHdl
)
636 SolarMutexGuard aGuard
;
638 vcl::Window
*pTopWin
= Application::GetFirstTopLevelWindow();
639 vcl::Window
*pActiveWin
= Application::GetActiveTopWindow();
640 SystemWindow
*pActiveSysWin
= NULL
;
642 vcl::Window
*pBubbleWin
= NULL
;
644 pBubbleWin
= mpBubbleWin
;
646 if ( pActiveWin
&& ( pActiveWin
!= pBubbleWin
) && pActiveWin
->IsTopWindow() )
647 pActiveSysWin
= pActiveWin
->GetSystemWindow();
649 if ( pActiveWin
== pBubbleWin
)
650 pActiveSysWin
= NULL
;
652 while ( !pActiveSysWin
&& pTopWin
)
654 if ( ( pTopWin
!= pBubbleWin
) && pTopWin
->IsTopWindow() )
655 pActiveSysWin
= pTopWin
->GetSystemWindow();
656 if ( !pActiveSysWin
)
657 pTopWin
= Application::GetNextTopLevelWindow( pTopWin
);
661 AddMenuBarIcon( pActiveSysWin
, true );
667 IMPL_LINK( UpdateCheckUI
, WindowEventHdl
, VclWindowEvent
*, pEvent
)
669 sal_uLong nEventID
= pEvent
->GetId();
671 if ( VCLEVENT_OBJECT_DYING
== nEventID
)
673 SolarMutexGuard aGuard
;
674 if ( mpIconSysWin
== pEvent
->GetWindow() )
676 mpIconSysWin
->RemoveEventListener( maWindowEventHdl
);
677 RemoveBubbleWindow( true );
680 else if ( VCLEVENT_WINDOW_MENUBARADDED
== nEventID
)
682 SolarMutexGuard aGuard
;
683 vcl::Window
*pWindow
= pEvent
->GetWindow();
686 SystemWindow
*pSysWin
= pWindow
->GetSystemWindow();
689 AddMenuBarIcon( pSysWin
, false );
693 else if ( VCLEVENT_WINDOW_MENUBARREMOVED
== nEventID
)
695 SolarMutexGuard aGuard
;
696 MenuBar
*pMBar
= static_cast<MenuBar
*>(pEvent
->GetData());
697 if ( pMBar
&& ( pMBar
== mpIconMBar
) )
698 RemoveBubbleWindow( true );
700 else if ( ( nEventID
== VCLEVENT_WINDOW_MOVE
) ||
701 ( nEventID
== VCLEVENT_WINDOW_RESIZE
) )
703 SolarMutexGuard aGuard
;
704 if ( ( mpIconSysWin
== pEvent
->GetWindow() ) &&
705 mpBubbleWin
&& ( mpIconMBar
!= NULL
) )
707 Rectangle aIconRect
= mpIconMBar
->GetMenuBarButtonRectPixel( mnIconID
);
708 Point aWinPos
= aIconRect
.BottomCenter();
709 mpBubbleWin
->SetTipPosPixel( aWinPos
);
710 if ( mpBubbleWin
->IsVisible() )
711 mpBubbleWin
->Show(); // This will recalc the screen position of the bubble
719 IMPL_LINK( UpdateCheckUI
, ApplicationEventHdl
, VclSimpleEvent
*, pEvent
)
721 switch (pEvent
->GetId())
723 case VCLEVENT_WINDOW_SHOW
:
724 case VCLEVENT_WINDOW_ACTIVATE
:
725 case VCLEVENT_WINDOW_GETFOCUS
: {
726 SolarMutexGuard aGuard
;
728 vcl::Window
*pWindow
= static_cast< VclWindowEvent
* >(pEvent
)->GetWindow();
729 if ( pWindow
&& pWindow
->IsTopWindow() )
731 SystemWindow
*pSysWin
= pWindow
->GetSystemWindow();
732 MenuBar
*pMBar
= pSysWin
? pSysWin
->GetMenuBar() : NULL
;
735 AddMenuBarIcon( pSysWin
, true );
747 #define TIP_HEIGHT 15
749 #define TIP_RIGHT_OFFSET 18
750 #define BUBBLE_BORDER 10
751 #define TEXT_MAX_WIDTH 300
752 #define TEXT_MAX_HEIGHT 200
755 BubbleWindow::BubbleWindow( vcl::Window
* pParent
, const OUString
& rTitle
,
756 const OUString
& rText
, const Image
& rImage
)
757 : FloatingWindow( pParent
, WB_SYSTEMWINDOW
758 | WB_OWNERDRAWDECORATION
761 , maBubbleTitle( rTitle
)
762 , maBubbleText( rText
)
763 , maBubbleImage( rImage
)
764 , maMaxTextSize( TEXT_MAX_WIDTH
, TEXT_MAX_HEIGHT
)
767 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
771 BubbleWindow::~BubbleWindow()
776 void BubbleWindow::Resize()
778 SolarMutexGuard aGuard
;
780 FloatingWindow::Resize();
782 Size aSize
= GetSizePixel();
784 if ( ( aSize
.Height() < 20 ) || ( aSize
.Width() < 60 ) )
787 Rectangle
aRect( 0, TIP_HEIGHT
, aSize
.Width(), aSize
.Height() - TIP_HEIGHT
);
788 maRectPoly
= Polygon( aRect
, 6, 6 );
789 vcl::Region
aRegion( maRectPoly
);
790 long nTipOffset
= aSize
.Width() - TIP_RIGHT_OFFSET
+ mnTipOffset
;
793 aPointArr
[0] = Point( nTipOffset
, TIP_HEIGHT
);
794 aPointArr
[1] = Point( nTipOffset
, 0 );
795 aPointArr
[2] = Point( nTipOffset
+ TIP_WIDTH
, TIP_HEIGHT
);
796 aPointArr
[3] = Point( nTipOffset
, TIP_HEIGHT
);
797 maTriPoly
= Polygon( 4, aPointArr
);
798 vcl::Region
aTriRegion( maTriPoly
);
800 aRegion
.Union( aTriRegion
);
803 SetWindowRegionPixel( maBounds
);
807 void BubbleWindow::SetTitleAndText( const OUString
& rTitle
,
808 const OUString
& rText
,
809 const Image
& rImage
)
811 maBubbleTitle
= rTitle
;
812 maBubbleText
= rText
;
813 maBubbleImage
= rImage
;
819 void BubbleWindow::Paint(vcl::RenderContext
& /*rRenderContext*/, const Rectangle
& /*rRect*/)
821 SolarMutexGuard aGuard
;
823 LineInfo
aThickLine( LINE_SOLID
, 2 );
825 DrawPolyLine( maRectPoly
, aThickLine
);
826 DrawPolyLine( maTriPoly
);
828 Color aOldLine
= GetLineColor();
829 Size aSize
= GetSizePixel();
830 long nTipOffset
= aSize
.Width() - TIP_RIGHT_OFFSET
+ mnTipOffset
;
832 SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
833 DrawLine( Point( nTipOffset
+2, TIP_HEIGHT
),
834 Point( nTipOffset
+ TIP_WIDTH
-1 , TIP_HEIGHT
),
836 SetLineColor( aOldLine
);
838 //Image aImage = InfoBox::GetStandardImage();
839 Size aImgSize
= maBubbleImage
.GetSizePixel();
841 DrawImage( Point( BUBBLE_BORDER
, BUBBLE_BORDER
+ TIP_HEIGHT
), maBubbleImage
);
843 vcl::Font aOldFont
= GetFont();
844 vcl::Font aBoldFont
= aOldFont
;
845 aBoldFont
.SetWeight( WEIGHT_BOLD
);
847 SetFont( aBoldFont
);
848 Rectangle aTitleRect
= maTitleRect
;
849 aTitleRect
.Move( aImgSize
.Width(), 0 );
850 DrawText( aTitleRect
, maBubbleTitle
, DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
);
853 Rectangle aTextRect
= maTextRect
;
854 aTextRect
.Move( aImgSize
.Width(), 0 );
855 DrawText( aTextRect
, maBubbleText
, DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
);
859 void BubbleWindow::MouseButtonDown( const MouseEvent
& )
865 void BubbleWindow::Show( bool bVisible
, sal_uInt16 nFlags
)
867 SolarMutexGuard aGuard
;
871 FloatingWindow::Show( bVisible
);
875 // don't show bubbles without a text
876 if ( ( maBubbleTitle
.isEmpty() ) && ( maBubbleText
.isEmpty() ) )
879 Size aWindowSize
= GetSizePixel();
881 // Image aImage = InfoBox::GetStandardImage();
882 Size aImgSize
= maBubbleImage
.GetSizePixel();
886 aWindowSize
.setHeight( maTitleRect
.GetHeight() * 7 / 4+ maTextRect
.GetHeight() +
887 3 * BUBBLE_BORDER
+ TIP_HEIGHT
);
889 if ( maTitleRect
.GetWidth() > maTextRect
.GetWidth() )
890 aWindowSize
.setWidth( maTitleRect
.GetWidth() );
892 aWindowSize
.setWidth( maTextRect
.GetWidth() );
894 aWindowSize
.setWidth( aWindowSize
.Width() + 3 * BUBBLE_BORDER
+ aImgSize
.Width() );
896 if ( aWindowSize
.Height() < aImgSize
.Height() + TIP_HEIGHT
+ 2 * BUBBLE_BORDER
)
897 aWindowSize
.setHeight( aImgSize
.Height() + TIP_HEIGHT
+ 2 * BUBBLE_BORDER
);
900 aPos
.X() = maTipPos
.X() - aWindowSize
.Width() + TIP_RIGHT_OFFSET
;
901 aPos
.Y() = maTipPos
.Y();
902 Point aScreenPos
= GetParent()->OutputToAbsoluteScreenPixel( aPos
);
903 if ( aScreenPos
.X() < 0 )
905 mnTipOffset
= aScreenPos
.X();
906 aPos
.X() -= mnTipOffset
;
908 SetPosSizePixel( aPos
, aWindowSize
);
910 FloatingWindow::Show( bVisible
, nFlags
);
914 void BubbleWindow::RecalcTextRects()
917 bool bFinished
= false;
918 vcl::Font aOldFont
= GetFont();
919 vcl::Font aBoldFont
= aOldFont
;
921 aBoldFont
.SetWeight( WEIGHT_BOLD
);
925 SetFont( aBoldFont
);
927 maTitleRect
= GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize
),
929 DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
);
932 maTextRect
= GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize
),
934 DrawTextFlags::MultiLine
| DrawTextFlags::WordBreak
);
936 if ( maTextRect
.GetHeight() < 10 )
937 maTextRect
.setHeight( 10 );
939 aTotalSize
.setHeight( maTitleRect
.GetHeight() +
940 aBoldFont
.GetHeight() * 3 / 4 +
941 maTextRect
.GetHeight() +
942 3 * BUBBLE_BORDER
+ TIP_HEIGHT
);
943 if ( aTotalSize
.Height() > maMaxTextSize
.Height() )
945 maMaxTextSize
.Width() = maMaxTextSize
.Width() * 3 / 2;
946 maMaxTextSize
.Height() = maMaxTextSize
.Height() * 3 / 2;
951 maTitleRect
.Move( 2*BUBBLE_BORDER
, BUBBLE_BORDER
+ TIP_HEIGHT
);
952 maTextRect
.Move( 2*BUBBLE_BORDER
, BUBBLE_BORDER
+ TIP_HEIGHT
+ maTitleRect
.GetHeight() + aBoldFont
.GetHeight() * 3 / 4 );
958 } // anonymous namespace
962 static uno::Reference
<uno::XInterface
> SAL_CALL
963 createInstance(const uno::Reference
<uno::XComponentContext
>& xContext
)
965 return *new UpdateCheckUI(xContext
);
970 static const cppu::ImplementationEntry kImplementations_entries
[] =
974 getImplementationName
,
976 cppu::createSingleComponentFactory
,
980 { NULL
, NULL
, NULL
, NULL
, NULL
, 0 }
985 extern "C" SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
updchkui_component_getFactory(const sal_Char
*pszImplementationName
, void *pServiceManager
, void *pRegistryKey
)
987 return cppu::component_getFactoryHelper(
988 pszImplementationName
,
991 kImplementations_entries
) ;
994 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */