bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / update / ui / updatecheckui.cxx
blobaf32a628b45416b4850ffc940230ce9f100d70af
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <list>
23 #include <cppuhelper/implbase.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>
35 #include <comphelper/processfactory.hxx>
36 #include <unotools/resmgr.hxx>
37 #include <vcl/window.hxx>
38 #include <vcl/floatwin.hxx>
39 #include <vcl/timer.hxx>
40 #include <vcl/idle.hxx>
41 #include <vcl/menu.hxx>
42 #include <vcl/outdev.hxx>
43 #include <vcl/weld.hxx>
44 #include <vcl/lineinfo.hxx>
45 #include <vcl/button.hxx>
46 #include <vcl/settings.hxx>
47 #include <vcl/svapp.hxx>
48 #include <sfx2/strings.hrc>
49 #include <rtl/ustrbuf.hxx>
51 #include <bitmaps.hlst>
53 #define PROPERTY_TITLE "BubbleHeading"
54 #define PROPERTY_TEXT "BubbleText"
55 #define PROPERTY_IMAGE "BubbleImageURL"
56 #define PROPERTY_SHOW_BUBBLE "BubbleVisible"
57 #define PROPERTY_CLICK_HDL "MenuClickHDL"
58 #define PROPERTY_SHOW_MENUICON "MenuIconVisible"
60 using namespace ::com::sun::star;
63 static uno::Sequence< OUString > getServiceNames()
65 uno::Sequence< OUString > aServiceList { "com.sun.star.setup.UpdateCheckUI" };
66 return aServiceList;
70 static OUString getImplementationName()
72 return OUString("vnd.sun.UpdateCheckUI");
76 namespace
79 Image GetMenuBarIcon( MenuBar const * pMBar )
81 OUString sResID;
82 vcl::Window *pMBarWin = pMBar->GetWindow();
83 sal_uInt32 nMBarHeight = 20;
85 if ( pMBarWin )
86 nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight();
88 if (nMBarHeight >= 35)
89 sResID = RID_UPDATE_AVAILABLE_26;
90 else
91 sResID = RID_UPDATE_AVAILABLE_16;
93 return Image(StockImage::Yes, sResID);
96 class BubbleWindow : public FloatingWindow
98 Point maTipPos;
99 vcl::Region maBounds;
100 tools::Polygon maRectPoly;
101 tools::Polygon maTriPoly;
102 OUString maBubbleTitle;
103 OUString maBubbleText;
104 Image maBubbleImage;
105 Size maMaxTextSize;
106 tools::Rectangle maTitleRect;
107 tools::Rectangle maTextRect;
108 long mnTipOffset;
110 private:
111 void RecalcTextRects();
113 public:
114 BubbleWindow( vcl::Window* pParent, const OUString& rTitle,
115 const OUString& rText, const Image& rImage );
117 virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
118 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
119 void Resize() override;
120 void Show( bool bVisible = true, ShowFlags nFlags = ShowFlags::NoActivate );
121 void SetTipPosPixel( const Point& rTipPos ) { maTipPos = rTipPos; }
122 void SetTitleAndText( const OUString& rTitle, const OUString& rText,
123 const Image& rImage );
127 class UpdateCheckUI : public ::cppu::WeakImplHelper
128 < lang::XServiceInfo, document::XDocumentEventListener, beans::XPropertySet >
130 uno::Reference< uno::XComponentContext > m_xContext;
131 uno::Reference< task::XJob > mrJob;
132 OUString maBubbleTitle;
133 OUString maBubbleText;
134 OUString maBubbleImageURL;
135 Image maBubbleImage;
136 VclPtr<BubbleWindow> mpBubbleWin;
137 VclPtr<SystemWindow> mpIconSysWin;
138 VclPtr<MenuBar> mpIconMBar;
139 std::locale maSfxLocale;
140 Idle maWaitIdle;
141 Timer maTimeoutTimer;
142 Link<VclWindowEvent&,void> maWindowEventHdl;
143 Link<VclSimpleEvent&,void> maApplicationEventHdl;
144 bool mbShowBubble;
145 bool mbShowMenuIcon;
146 bool mbBubbleChanged;
147 sal_uInt16 mnIconID;
149 private:
150 DECL_LINK(ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool);
151 DECL_LINK(HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, bool);
152 DECL_LINK(WaitTimeOutHdl, Timer *, void);
153 DECL_LINK(TimeOutHdl, Timer *, void);
154 DECL_LINK(UserEventHdl, void *, void);
155 DECL_LINK(WindowEventHdl, VclWindowEvent&, void);
156 DECL_LINK(ApplicationEventHdl, VclSimpleEvent&, void);
158 VclPtr<BubbleWindow> GetBubbleWindow();
159 void RemoveBubbleWindow( bool bRemoveIcon );
160 void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl );
161 Image GetBubbleImage( OUString const &rURL );
163 public:
164 explicit UpdateCheckUI(const uno::Reference<uno::XComponentContext>&);
165 virtual ~UpdateCheckUI() override;
167 // XServiceInfo
168 virtual OUString SAL_CALL getImplementationName() override;
169 virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName) override;
170 virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
172 // XDocumentEventListener
173 virtual void SAL_CALL documentEventOccured(const document::DocumentEvent& Event) override;
174 virtual void SAL_CALL disposing(const lang::EventObject& Event) override;
176 //XPropertySet
177 virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
178 virtual void SAL_CALL setPropertyValue(const OUString& PropertyName, const uno::Any& aValue) override;
179 virtual uno::Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
180 virtual void SAL_CALL addPropertyChangeListener(const OUString& PropertyName,
181 const uno::Reference< beans::XPropertyChangeListener > & aListener) override;
182 virtual void SAL_CALL removePropertyChangeListener(const OUString& PropertyName,
183 const uno::Reference< beans::XPropertyChangeListener > & aListener) override;
184 virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName,
185 const uno::Reference< beans::XVetoableChangeListener > & aListener) override;
186 virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName,
187 const uno::Reference< beans::XVetoableChangeListener > & aListener) override;
190 UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) :
191 m_xContext(xContext)
192 , mpIconMBar( nullptr )
193 , mbShowBubble( false )
194 , mbShowMenuIcon( false )
195 , mbBubbleChanged( false )
196 , mnIconID( 0 )
198 maSfxLocale = Translate::Create("sfx");
200 maBubbleImage = GetBubbleImage( maBubbleImageURL );
202 maWaitIdle.SetPriority( TaskPriority::LOWEST );
203 maWaitIdle.SetInvokeHandler( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) );
205 maTimeoutTimer.SetTimeout( 10000 );
206 maTimeoutTimer.SetInvokeHandler( LINK( this, UpdateCheckUI, TimeOutHdl ) );
208 uno::Reference< document::XDocumentEventBroadcaster > xBroadcaster( frame::theGlobalEventBroadcaster::get(m_xContext) );
209 xBroadcaster->addDocumentEventListener( this );
211 maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl );
212 maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl );
213 Application::AddEventListener( maApplicationEventHdl );
216 UpdateCheckUI::~UpdateCheckUI()
218 Application::RemoveEventListener( maApplicationEventHdl );
219 RemoveBubbleWindow( true );
222 OUString SAL_CALL
223 UpdateCheckUI::getImplementationName()
225 return ::getImplementationName();
228 uno::Sequence< OUString > SAL_CALL
229 UpdateCheckUI::getSupportedServiceNames()
231 return ::getServiceNames();
234 sal_Bool SAL_CALL
235 UpdateCheckUI::supportsService( OUString const & serviceName )
237 return cppu::supportsService(this, serviceName);
240 Image UpdateCheckUI::GetBubbleImage( OUString const &rURL )
242 Image aImage;
244 if ( !maBubbleImageURL.isEmpty() )
246 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
248 if( !xContext.is() )
249 throw uno::RuntimeException(
250 "UpdateCheckUI: unable to obtain service manager from component context" );
254 uno::Reference< graphic::XGraphicProvider > xGraphProvider(graphic::GraphicProvider::create(xContext));
255 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
256 aMediaProps[0].Name = "URL";
257 aMediaProps[0].Value <<= rURL;
259 uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
260 if ( xGraphic.is() )
262 aImage = Image( xGraphic );
265 catch( const uno::Exception& )
270 if ( aImage.GetSizePixel().Width() == 0 )
271 aImage = Image(StockImage::Yes, SV_RESID_BITMAP_INFOBOX);
273 return aImage;
277 void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl )
279 if ( ! mbShowMenuIcon )
280 return;
282 SolarMutexGuard aGuard;
284 MenuBar *pActiveMBar = pSysWin->GetMenuBar();
285 if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) )
287 if ( bAddEventHdl && mpIconSysWin )
288 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
290 RemoveBubbleWindow( true );
292 if ( pActiveMBar )
294 OUStringBuffer aBuf;
295 if( !maBubbleTitle.isEmpty() )
296 aBuf.append( maBubbleTitle );
297 if( !maBubbleText.isEmpty() )
299 if( !maBubbleTitle.isEmpty() )
300 aBuf.append( "\n\n" );
301 aBuf.append( maBubbleText );
304 Image aImage = GetMenuBarIcon( pActiveMBar );
305 mnIconID = pActiveMBar->AddMenuBarButton( aImage,
306 LINK( this, UpdateCheckUI, ClickHdl ),
307 aBuf.makeStringAndClear()
309 pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID,
310 LINK( this, UpdateCheckUI, HighlightHdl ) );
312 mpIconMBar = pActiveMBar;
313 mpIconSysWin = pSysWin;
314 if ( bAddEventHdl && mpIconSysWin )
315 mpIconSysWin->AddEventListener( maWindowEventHdl );
318 if ( mbShowBubble && pActiveMBar )
320 mpBubbleWin = GetBubbleWindow();
321 if ( mpBubbleWin )
323 mpBubbleWin->Show();
324 maTimeoutTimer.Start();
326 mbShowBubble = false;
331 void SAL_CALL UpdateCheckUI::documentEventOccured(const document::DocumentEvent& rEvent)
333 SolarMutexGuard aGuard;
335 if( rEvent.EventName == "OnPrepareViewClosing" )
337 RemoveBubbleWindow( true );
342 void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&)
347 uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo()
349 return nullptr;
353 void UpdateCheckUI::setPropertyValue(const OUString& rPropertyName,
354 const uno::Any& rValue)
356 SolarMutexGuard aGuard;
358 OUString aString;
360 if( rPropertyName == PROPERTY_TITLE ) {
361 rValue >>= aString;
362 if ( aString != maBubbleTitle ) {
363 maBubbleTitle = aString;
364 mbBubbleChanged = true;
367 else if( rPropertyName == PROPERTY_TEXT ) {
368 rValue >>= aString;
369 if ( aString != maBubbleText ) {
370 maBubbleText = aString;
371 mbBubbleChanged = true;
374 else if( rPropertyName == PROPERTY_IMAGE ) {
375 rValue >>= aString;
376 if ( aString != maBubbleImageURL ) {
377 maBubbleImageURL = aString;
378 maBubbleImage = GetBubbleImage( maBubbleImageURL );
379 mbBubbleChanged = true;
382 else if( rPropertyName == PROPERTY_SHOW_BUBBLE ) {
383 rValue >>= mbShowBubble;
384 if ( mbShowBubble )
385 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
386 else if ( mpBubbleWin )
387 mpBubbleWin->Show( false );
389 else if( rPropertyName == PROPERTY_CLICK_HDL ) {
390 uno::Reference< task::XJob > aJob;
391 rValue >>= aJob;
392 if ( !aJob.is() )
393 throw lang::IllegalArgumentException();
394 mrJob = aJob;
396 else if (rPropertyName == PROPERTY_SHOW_MENUICON ) {
397 bool bShowMenuIcon = false;
398 rValue >>= bShowMenuIcon;
399 if ( bShowMenuIcon != mbShowMenuIcon )
401 mbShowMenuIcon = bShowMenuIcon;
402 if ( bShowMenuIcon )
403 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
404 else
405 RemoveBubbleWindow( true );
408 else
409 throw beans::UnknownPropertyException();
411 if ( mbBubbleChanged && mpBubbleWin )
412 mpBubbleWin->Show( false );
416 uno::Any UpdateCheckUI::getPropertyValue(const OUString& rPropertyName)
418 SolarMutexGuard aGuard;
420 uno::Any aRet;
422 if( rPropertyName == PROPERTY_TITLE )
423 aRet <<= maBubbleTitle;
424 else if( rPropertyName == PROPERTY_TEXT )
425 aRet <<= maBubbleText;
426 else if( rPropertyName == PROPERTY_SHOW_BUBBLE )
427 aRet <<= mbShowBubble;
428 else if( rPropertyName == PROPERTY_IMAGE )
429 aRet <<= maBubbleImageURL;
430 else if( rPropertyName == PROPERTY_CLICK_HDL )
431 aRet <<= mrJob;
432 else if( rPropertyName == PROPERTY_SHOW_MENUICON )
433 aRet <<= mbShowMenuIcon;
434 else
435 throw beans::UnknownPropertyException();
437 return aRet;
441 void UpdateCheckUI::addPropertyChangeListener( const OUString& /*aPropertyName*/,
442 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
444 //no bound properties
448 void UpdateCheckUI::removePropertyChangeListener( const OUString& /*aPropertyName*/,
449 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
451 //no bound properties
455 void UpdateCheckUI::addVetoableChangeListener( const OUString& /*aPropertyName*/,
456 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
458 //no vetoable properties
462 void UpdateCheckUI::removeVetoableChangeListener( const OUString& /*aPropertyName*/,
463 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
465 //no vetoable properties
469 VclPtr<BubbleWindow> UpdateCheckUI::GetBubbleWindow()
471 if ( !mpIconSysWin )
472 return nullptr;
474 tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
475 if( aIconRect.IsEmpty() )
476 return nullptr;
478 auto pBubbleWin = mpBubbleWin;
480 if ( !pBubbleWin ) {
481 pBubbleWin = VclPtr<BubbleWindow>::Create( mpIconSysWin, maBubbleTitle,
482 maBubbleText, maBubbleImage );
483 mbBubbleChanged = false;
485 else if ( mbBubbleChanged ) {
486 pBubbleWin->SetTitleAndText( maBubbleTitle, maBubbleText,
487 maBubbleImage );
488 mbBubbleChanged = false;
491 Point aWinPos = aIconRect.BottomCenter();
493 pBubbleWin->SetTipPosPixel( aWinPos );
495 return pBubbleWin;
499 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon )
501 SolarMutexGuard aGuard;
503 maWaitIdle.Stop();
504 maTimeoutTimer.Stop();
506 if ( mpBubbleWin )
508 mpBubbleWin.disposeAndClear();
511 if ( bRemoveIcon )
513 try {
514 if ( mpIconMBar && ( mnIconID != 0 ) )
516 mpIconMBar->RemoveMenuBarButton( mnIconID );
517 mpIconMBar = nullptr;
518 mnIconID = 0;
521 catch ( ... ) {
522 mpIconMBar = nullptr;
523 mnIconID = 0;
526 mpIconSysWin = nullptr;
531 IMPL_LINK_NOARG(UpdateCheckUI, ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool)
533 SolarMutexGuard aGuard;
535 maWaitIdle.Stop();
536 if ( mpBubbleWin )
537 mpBubbleWin->Show( false );
539 if ( mrJob.is() )
541 try {
542 uno::Sequence<beans::NamedValue> aEmpty;
543 mrJob->execute( aEmpty );
545 catch(const uno::Exception&) {
546 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
547 VclMessageType::Warning, VclButtonsType::Ok,
548 Translate::get(STR_NO_WEBBROWSER_FOUND, maSfxLocale)));
549 xErrorBox->run();
553 return false;
557 IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, rData, bool )
559 if ( rData.bHighlight )
560 maWaitIdle.Start();
561 else
562 RemoveBubbleWindow( false );
564 return false;
568 IMPL_LINK_NOARG(UpdateCheckUI, WaitTimeOutHdl, Timer *, void)
570 SolarMutexGuard aGuard;
572 mpBubbleWin = GetBubbleWindow();
574 if ( mpBubbleWin )
576 mpBubbleWin->Show();
581 IMPL_LINK_NOARG(UpdateCheckUI, TimeOutHdl, Timer *, void)
583 RemoveBubbleWindow( false );
587 IMPL_LINK_NOARG(UpdateCheckUI, UserEventHdl, void*, void)
589 SolarMutexGuard aGuard;
591 vcl::Window *pTopWin = Application::GetFirstTopLevelWindow();
592 vcl::Window *pActiveWin = Application::GetActiveTopWindow();
593 SystemWindow *pActiveSysWin = nullptr;
595 vcl::Window *pBubbleWin = nullptr;
596 if ( mpBubbleWin )
597 pBubbleWin = mpBubbleWin;
599 if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() )
600 pActiveSysWin = pActiveWin->GetSystemWindow();
602 if ( pActiveWin == pBubbleWin )
603 pActiveSysWin = nullptr;
605 while ( !pActiveSysWin && pTopWin )
607 if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() )
608 pActiveSysWin = pTopWin->GetSystemWindow();
609 if ( !pActiveSysWin )
610 pTopWin = Application::GetNextTopLevelWindow( pTopWin );
613 if ( pActiveSysWin )
614 AddMenuBarIcon( pActiveSysWin, true );
618 IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent&, rEvent, void )
620 VclEventId nEventID = rEvent.GetId();
622 if ( VclEventId::ObjectDying == nEventID )
624 SolarMutexGuard aGuard;
625 if ( mpIconSysWin == rEvent.GetWindow() )
627 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
628 RemoveBubbleWindow( true );
631 else if ( VclEventId::WindowMenubarAdded == nEventID )
633 SolarMutexGuard aGuard;
634 vcl::Window *pWindow = rEvent.GetWindow();
635 if ( pWindow )
637 SystemWindow *pSysWin = pWindow->GetSystemWindow();
638 if ( pSysWin )
640 AddMenuBarIcon( pSysWin, false );
644 else if ( VclEventId::WindowMenubarRemoved == nEventID )
646 SolarMutexGuard aGuard;
647 MenuBar *pMBar = static_cast<MenuBar*>(rEvent.GetData());
648 if ( pMBar && ( pMBar == mpIconMBar ) )
649 RemoveBubbleWindow( true );
651 else if ( ( nEventID == VclEventId::WindowMove ) ||
652 ( nEventID == VclEventId::WindowResize ) )
654 SolarMutexGuard aGuard;
655 if ( ( mpIconSysWin == rEvent.GetWindow() ) &&
656 mpBubbleWin && ( mpIconMBar != nullptr ) )
658 tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
659 Point aWinPos = aIconRect.BottomCenter();
660 mpBubbleWin->SetTipPosPixel( aWinPos );
661 if ( mpBubbleWin->IsVisible() )
662 mpBubbleWin->Show(); // This will recalc the screen position of the bubble
668 IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent&, rEvent, void)
670 switch (rEvent.GetId())
672 case VclEventId::WindowShow:
673 case VclEventId::WindowActivate:
674 case VclEventId::WindowGetFocus: {
675 SolarMutexGuard aGuard;
677 vcl::Window *pWindow = static_cast< VclWindowEvent * >(&rEvent)->GetWindow();
678 if ( pWindow && pWindow->IsTopWindow() )
680 SystemWindow *pSysWin = pWindow->GetSystemWindow();
681 MenuBar *pMBar = pSysWin ? pSysWin->GetMenuBar() : nullptr;
682 if (pMBar)
684 AddMenuBarIcon( pSysWin, true );
687 break;
689 default: break;
694 #define TIP_HEIGHT 15
695 #define TIP_WIDTH 7
696 #define TIP_RIGHT_OFFSET 18
697 #define BUBBLE_BORDER 10
698 #define TEXT_MAX_WIDTH 300
699 #define TEXT_MAX_HEIGHT 200
702 BubbleWindow::BubbleWindow( vcl::Window* pParent, const OUString& rTitle,
703 const OUString& rText, const Image& rImage )
704 : FloatingWindow( pParent, WB_SYSTEMWINDOW
705 | WB_OWNERDRAWDECORATION
706 | WB_NOBORDER
708 , maBubbleTitle( rTitle )
709 , maBubbleText( rText )
710 , maBubbleImage( rImage )
711 , maMaxTextSize( TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT )
712 , mnTipOffset( 0 )
714 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
717 void BubbleWindow::Resize()
719 SolarMutexGuard aGuard;
721 FloatingWindow::Resize();
723 Size aSize = GetSizePixel();
725 if ( ( aSize.Height() < 20 ) || ( aSize.Width() < 60 ) )
726 return;
728 tools::Rectangle aRect( 0, TIP_HEIGHT, aSize.Width(), aSize.Height() - TIP_HEIGHT );
729 maRectPoly = tools::Polygon( aRect, 6, 6 );
730 vcl::Region aRegion( maRectPoly );
731 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
733 Point aPointArr[4];
734 aPointArr[0] = Point( nTipOffset, TIP_HEIGHT );
735 aPointArr[1] = Point( nTipOffset, 0 );
736 aPointArr[2] = Point( nTipOffset + TIP_WIDTH , TIP_HEIGHT );
737 aPointArr[3] = Point( nTipOffset, TIP_HEIGHT );
738 maTriPoly = tools::Polygon( 4, aPointArr );
739 vcl::Region aTriRegion( maTriPoly );
741 aRegion.Union( aTriRegion);
742 maBounds = aRegion;
744 SetWindowRegionPixel( maBounds );
748 void BubbleWindow::SetTitleAndText( const OUString& rTitle,
749 const OUString& rText,
750 const Image& rImage )
752 maBubbleTitle = rTitle;
753 maBubbleText = rText;
754 maBubbleImage = rImage;
756 Resize();
760 void BubbleWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& /*rRect*/)
762 SolarMutexGuard aGuard;
764 LineInfo aThickLine( LineStyle::Solid, 2 );
766 DrawPolyLine( maRectPoly, aThickLine );
767 DrawPolyLine( maTriPoly );
769 Color aOldLine = GetLineColor();
770 Size aSize = GetSizePixel();
771 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
773 SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
774 DrawLine( Point( nTipOffset+2, TIP_HEIGHT ),
775 Point( nTipOffset + TIP_WIDTH -1 , TIP_HEIGHT ),
776 aThickLine );
777 SetLineColor( aOldLine );
779 Size aImgSize = maBubbleImage.GetSizePixel();
781 DrawImage( Point( BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT ), maBubbleImage );
783 vcl::Font aOldFont = GetFont();
784 vcl::Font aBoldFont = aOldFont;
785 aBoldFont.SetWeight( WEIGHT_BOLD );
787 SetFont( aBoldFont );
788 tools::Rectangle aTitleRect = maTitleRect;
789 aTitleRect.Move( aImgSize.Width(), 0 );
790 DrawText( aTitleRect, maBubbleTitle, DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
792 SetFont( aOldFont );
793 tools::Rectangle aTextRect = maTextRect;
794 aTextRect.Move( aImgSize.Width(), 0 );
795 DrawText( aTextRect, maBubbleText, DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
799 void BubbleWindow::MouseButtonDown( const MouseEvent& )
801 Show( false );
805 void BubbleWindow::Show( bool bVisible, ShowFlags nFlags )
807 SolarMutexGuard aGuard;
809 if ( !bVisible )
811 FloatingWindow::Show( bVisible );
812 return;
815 // don't show bubbles without a text
816 if ( ( maBubbleTitle.isEmpty() ) && ( maBubbleText.isEmpty() ) )
817 return;
819 Size aWindowSize = GetSizePixel();
821 Size aImgSize = maBubbleImage.GetSizePixel();
823 RecalcTextRects();
825 aWindowSize.setHeight( maTitleRect.GetHeight() * 7 / 4+ maTextRect.GetHeight() +
826 3 * BUBBLE_BORDER + TIP_HEIGHT );
828 if ( maTitleRect.GetWidth() > maTextRect.GetWidth() )
829 aWindowSize.setWidth( maTitleRect.GetWidth() );
830 else
831 aWindowSize.setWidth( maTextRect.GetWidth() );
833 aWindowSize.setWidth( aWindowSize.Width() + 3 * BUBBLE_BORDER + aImgSize.Width() );
835 if ( aWindowSize.Height() < aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER )
836 aWindowSize.setHeight( aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER );
838 Point aPos;
839 aPos.setX( maTipPos.X() - aWindowSize.Width() + TIP_RIGHT_OFFSET );
840 aPos.setY( maTipPos.Y() );
841 Point aScreenPos = GetParent()->OutputToAbsoluteScreenPixel( aPos );
842 if ( aScreenPos.X() < 0 )
844 mnTipOffset = aScreenPos.X();
845 aPos.AdjustX( -mnTipOffset );
847 SetPosSizePixel( aPos, aWindowSize );
849 FloatingWindow::Show( bVisible, nFlags );
853 void BubbleWindow::RecalcTextRects()
855 Size aTotalSize;
856 bool bFinished = false;
857 vcl::Font aOldFont = GetFont();
858 vcl::Font aBoldFont = aOldFont;
860 aBoldFont.SetWeight( WEIGHT_BOLD );
862 while ( !bFinished )
864 SetFont( aBoldFont );
866 maTitleRect = GetTextRect( tools::Rectangle( Point( 0, 0 ), maMaxTextSize ),
867 maBubbleTitle,
868 DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
870 SetFont( aOldFont );
871 maTextRect = GetTextRect( tools::Rectangle( Point( 0, 0 ), maMaxTextSize ),
872 maBubbleText,
873 DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
875 if ( maTextRect.GetHeight() < 10 )
876 maTextRect.setHeight( 10 );
878 aTotalSize.setHeight( maTitleRect.GetHeight() +
879 aBoldFont.GetFontHeight() * 3 / 4 +
880 maTextRect.GetHeight() +
881 3 * BUBBLE_BORDER + TIP_HEIGHT );
882 if ( aTotalSize.Height() > maMaxTextSize.Height() )
884 maMaxTextSize.setWidth( maMaxTextSize.Width() * 3 / 2 );
885 maMaxTextSize.setHeight( maMaxTextSize.Height() * 3 / 2 );
887 else
888 bFinished = true;
890 maTitleRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT );
891 maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetFontHeight() * 3 / 4 );
895 } // anonymous namespace
898 static uno::Reference<uno::XInterface>
899 createInstance(const uno::Reference<uno::XComponentContext>& xContext)
901 SolarMutexGuard aGuard;
902 return *new UpdateCheckUI(xContext);
906 static const cppu::ImplementationEntry kImplementations_entries[] =
909 createInstance,
910 getImplementationName,
911 getServiceNames,
912 cppu::createSingleComponentFactory,
913 nullptr,
916 { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
920 extern "C" SAL_DLLPUBLIC_EXPORT void * updchkui_component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
922 return cppu::component_getFactoryHelper(
923 pszImplementationName,
924 pServiceManager,
925 pRegistryKey,
926 kImplementations_entries) ;
929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */