diff options
-rw-r--r-- | extensions/inc/bitmaps.hlst | 2 | ||||
-rw-r--r-- | extensions/source/update/ui/updatecheckui.cxx | 390 | ||||
-rw-r--r-- | include/vcl/bubblewindow.hxx | 58 | ||||
-rw-r--r-- | vcl/inc/bitmaps.hlst | 3 | ||||
-rw-r--r-- | vcl/source/window/bubblewindow.cxx | 347 |
5 files changed, 423 insertions, 377 deletions
diff --git a/extensions/inc/bitmaps.hlst b/extensions/inc/bitmaps.hlst index 60a388e0c7b4..c07bc6ec16d1 100644 --- a/extensions/inc/bitmaps.hlst +++ b/extensions/inc/bitmaps.hlst @@ -38,8 +38,6 @@ #define RID_EXTBMP_SCROLLBAR "res/sx10768.png" #define RID_EXTBMP_SPINBUTTON "res/sx10769.png" #define RID_EXTBMP_NAVIGATIONBAR "res/sx10607.png" -#define RID_UPDATE_AVAILABLE_16 "extensions/res/update/ui/onlineupdate_16.png" -#define RID_UPDATE_AVAILABLE_26 "extensions/res/update/ui/onlineupdate_26.png" #define RID_SCANNER_HANDLE "extensions/res/scanner/handle.png" #define BMP_TABLE "res/sx03188.png" #define BMP_QUERY "res/sx03202.png" diff --git a/extensions/source/update/ui/updatecheckui.cxx b/extensions/source/update/ui/updatecheckui.cxx index c73db90d4a4f..b9582b465410 100644 --- a/extensions/source/update/ui/updatecheckui.cxx +++ b/extensions/source/update/ui/updatecheckui.cxx @@ -31,12 +31,8 @@ #include <comphelper/processfactory.hxx> #include <unotools/resmgr.hxx> #include <vcl/image.hxx> -#include <vcl/window.hxx> #include <vcl/bubblewindow.hxx> #include <vcl/timer.hxx> -#include <vcl/idle.hxx> -#include <vcl/lineinfo.hxx> -#include <vcl/menu.hxx> #include <vcl/outdev.hxx> #include <vcl/weld.hxx> #include <vcl/settings.hxx> @@ -59,62 +55,22 @@ using namespace ::com::sun::star; namespace { -Image GetMenuBarIcon( MenuBar const * pMBar ) -{ - OUString sResID; - vcl::Window *pMBarWin = pMBar->GetWindow(); - sal_uInt32 nMBarHeight = 20; - - if ( pMBarWin ) - nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight(); - - if (nMBarHeight >= 35) - sResID = RID_UPDATE_AVAILABLE_26; - else - sResID = RID_UPDATE_AVAILABLE_16; - - return Image(StockImage::Yes, sResID); -} - class UpdateCheckUI : public ::cppu::WeakImplHelper < lang::XServiceInfo, document::XDocumentEventListener, beans::XPropertySet > { uno::Reference< uno::XComponentContext > m_xContext; uno::Reference< task::XJob > mrJob; - OUString maBubbleTitle; - OUString maBubbleText; OUString maBubbleImageURL; - Image maBubbleImage; - VclPtr<BubbleWindow> mpBubbleWin; - VclPtr<SystemWindow> mpIconSysWin; - VclPtr<MenuBar> mpIconMBar; + MenuBarUpdateIconManager maBubbleManager; std::locale maSfxLocale; - Idle maWaitIdle; - Timer maTimeoutTimer; - Link<VclWindowEvent&,void> maWindowEventHdl; - Link<VclSimpleEvent&,void> maApplicationEventHdl; - bool mbShowBubble; - bool mbShowMenuIcon; - bool mbBubbleChanged; - sal_uInt16 mnIconID; private: - DECL_LINK(ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool); - DECL_LINK(HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, bool); - DECL_LINK(WaitTimeOutHdl, Timer *, void); - DECL_LINK(TimeOutHdl, Timer *, void); - DECL_LINK(UserEventHdl, void *, void); - DECL_LINK(WindowEventHdl, VclWindowEvent&, void); - DECL_LINK(ApplicationEventHdl, VclSimpleEvent&, void); - - VclPtr<BubbleWindow> GetBubbleWindow(); - void RemoveBubbleWindow( bool bRemoveIcon ); - void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl ); + DECL_LINK(ClickHdl, LinkParamNone*, void); + Image GetBubbleImage( OUString const &rURL ); public: explicit UpdateCheckUI(const uno::Reference<uno::XComponentContext>&); - virtual ~UpdateCheckUI() override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; @@ -139,36 +95,18 @@ public: const uno::Reference< beans::XVetoableChangeListener > & aListener) override; }; -UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) : - m_xContext(xContext) - , mpIconMBar( nullptr ) - , mbShowBubble( false ) - , mbShowMenuIcon( false ) - , mbBubbleChanged( false ) - , mnIconID( 0 ) +UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) + : m_xContext(xContext) { maSfxLocale = Translate::Create("sfx"); - maBubbleImage = GetBubbleImage( maBubbleImageURL ); - - maWaitIdle.SetPriority( TaskPriority::LOWEST ); - maWaitIdle.SetInvokeHandler( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) ); - - maTimeoutTimer.SetTimeout( 10000 ); - maTimeoutTimer.SetInvokeHandler( LINK( this, UpdateCheckUI, TimeOutHdl ) ); - uno::Reference< document::XDocumentEventBroadcaster > xBroadcaster( frame::theGlobalEventBroadcaster::get(m_xContext) ); xBroadcaster->addDocumentEventListener( this ); - maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl ); - maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl ); - Application::AddEventListener( maApplicationEventHdl ); -} + SolarMutexGuard aGuard; -UpdateCheckUI::~UpdateCheckUI() -{ - Application::RemoveEventListener( maApplicationEventHdl ); - RemoveBubbleWindow( true ); + maBubbleManager.SetBubbleImage(GetBubbleImage(maBubbleImageURL)); + maBubbleManager.SetClickHdl(LINK(this, UpdateCheckUI, ClickHdl)); } OUString SAL_CALL @@ -225,83 +163,25 @@ Image UpdateCheckUI::GetBubbleImage( OUString const &rURL ) return aImage; } - -void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl ) -{ - if ( ! mbShowMenuIcon ) - return; - - SolarMutexGuard aGuard; - - MenuBar *pActiveMBar = pSysWin->GetMenuBar(); - if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) ) - { - if ( bAddEventHdl && mpIconSysWin ) - mpIconSysWin->RemoveEventListener( maWindowEventHdl ); - - RemoveBubbleWindow( true ); - - if ( pActiveMBar ) - { - OUStringBuffer aBuf; - if( !maBubbleTitle.isEmpty() ) - aBuf.append( maBubbleTitle ); - if( !maBubbleText.isEmpty() ) - { - if( !maBubbleTitle.isEmpty() ) - aBuf.append( "\n\n" ); - aBuf.append( maBubbleText ); - } - - Image aImage = GetMenuBarIcon( pActiveMBar ); - mnIconID = pActiveMBar->AddMenuBarButton( aImage, - LINK( this, UpdateCheckUI, ClickHdl ), - aBuf.makeStringAndClear() - ); - pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID, - LINK( this, UpdateCheckUI, HighlightHdl ) ); - } - mpIconMBar = pActiveMBar; - mpIconSysWin = pSysWin; - if ( bAddEventHdl && mpIconSysWin ) - mpIconSysWin->AddEventListener( maWindowEventHdl ); - } - - if ( mbShowBubble && pActiveMBar ) - { - mpBubbleWin = GetBubbleWindow(); - if ( mpBubbleWin ) - { - mpBubbleWin->Show(); - maTimeoutTimer.Start(); - } - mbShowBubble = false; - } -} - - void SAL_CALL UpdateCheckUI::documentEventOccured(const document::DocumentEvent& rEvent) { SolarMutexGuard aGuard; if( rEvent.EventName == "OnPrepareViewClosing" ) { - RemoveBubbleWindow( true ); + maBubbleManager.RemoveBubbleWindow(true); } } - void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&) { } - uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo() { return nullptr; } - void UpdateCheckUI::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue) { @@ -311,32 +191,23 @@ void UpdateCheckUI::setPropertyValue(const OUString& rPropertyName, if( rPropertyName == PROPERTY_TITLE ) { rValue >>= aString; - if ( aString != maBubbleTitle ) { - maBubbleTitle = aString; - mbBubbleChanged = true; - } + maBubbleManager.SetBubbleTitle(aString); } else if( rPropertyName == PROPERTY_TEXT ) { rValue >>= aString; - if ( aString != maBubbleText ) { - maBubbleText = aString; - mbBubbleChanged = true; - } + maBubbleManager.SetBubbleText(aString); } else if( rPropertyName == PROPERTY_IMAGE ) { rValue >>= aString; if ( aString != maBubbleImageURL ) { maBubbleImageURL = aString; - maBubbleImage = GetBubbleImage( maBubbleImageURL ); - mbBubbleChanged = true; + maBubbleManager.SetBubbleImage(GetBubbleImage(maBubbleImageURL)); } } else if( rPropertyName == PROPERTY_SHOW_BUBBLE ) { - rValue >>= mbShowBubble; - if ( mbShowBubble ) - Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) ); - else if ( mpBubbleWin ) - mpBubbleWin->Show( false ); + bool bShowBubble= false; + rValue >>= bShowBubble; + maBubbleManager.SetShowBubble(bShowBubble); } else if( rPropertyName == PROPERTY_CLICK_HDL ) { uno::Reference< task::XJob > aJob; @@ -348,23 +219,12 @@ void UpdateCheckUI::setPropertyValue(const OUString& rPropertyName, else if (rPropertyName == PROPERTY_SHOW_MENUICON ) { bool bShowMenuIcon = false; rValue >>= bShowMenuIcon; - if ( bShowMenuIcon != mbShowMenuIcon ) - { - mbShowMenuIcon = bShowMenuIcon; - if ( bShowMenuIcon ) - Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) ); - else - RemoveBubbleWindow( true ); - } + maBubbleManager.SetShowMenuIcon(bShowMenuIcon); } else throw beans::UnknownPropertyException(rPropertyName); - - if ( mbBubbleChanged && mpBubbleWin ) - mpBubbleWin->Show( false ); } - uno::Any UpdateCheckUI::getPropertyValue(const OUString& rPropertyName) { SolarMutexGuard aGuard; @@ -372,17 +232,17 @@ uno::Any UpdateCheckUI::getPropertyValue(const OUString& rPropertyName) uno::Any aRet; if( rPropertyName == PROPERTY_TITLE ) - aRet <<= maBubbleTitle; + aRet <<= maBubbleManager.GetBubbleTitle(); else if( rPropertyName == PROPERTY_TEXT ) - aRet <<= maBubbleText; + aRet <<= maBubbleManager.GetBubbleText(); else if( rPropertyName == PROPERTY_SHOW_BUBBLE ) - aRet <<= mbShowBubble; + aRet <<= maBubbleManager.GetShowBubble(); else if( rPropertyName == PROPERTY_IMAGE ) aRet <<= maBubbleImageURL; else if( rPropertyName == PROPERTY_CLICK_HDL ) aRet <<= mrJob; else if( rPropertyName == PROPERTY_SHOW_MENUICON ) - aRet <<= mbShowMenuIcon; + aRet <<= maBubbleManager.GetShowMenuIcon(); else throw beans::UnknownPropertyException(rPropertyName); @@ -403,91 +263,22 @@ void UpdateCheckUI::removePropertyChangeListener( const OUString& /*aPropertyNam //no bound properties } - void UpdateCheckUI::addVetoableChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) { //no vetoable properties } - void UpdateCheckUI::removeVetoableChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) { //no vetoable properties } - -VclPtr<BubbleWindow> UpdateCheckUI::GetBubbleWindow() -{ - if ( !mpIconSysWin ) - return nullptr; - - tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID ); - if( aIconRect.IsEmpty() ) - return nullptr; - - auto pBubbleWin = mpBubbleWin; - - if ( !pBubbleWin ) { - pBubbleWin = VclPtr<BubbleWindow>::Create( mpIconSysWin, maBubbleTitle, - maBubbleText, maBubbleImage ); - mbBubbleChanged = false; - } - else if ( mbBubbleChanged ) { - pBubbleWin->SetTitleAndText( maBubbleTitle, maBubbleText, - maBubbleImage ); - mbBubbleChanged = false; - } - - Point aWinPos = aIconRect.BottomCenter(); - - pBubbleWin->SetTipPosPixel( aWinPos ); - - return pBubbleWin; -} - - -void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon ) +IMPL_LINK_NOARG(UpdateCheckUI, ClickHdl, LinkParamNone*, void) { SolarMutexGuard aGuard; - maWaitIdle.Stop(); - maTimeoutTimer.Stop(); - - if ( mpBubbleWin ) - { - mpBubbleWin.disposeAndClear(); - } - - if ( bRemoveIcon ) - { - try { - if ( mpIconMBar && ( mnIconID != 0 ) ) - { - mpIconMBar->RemoveMenuBarButton( mnIconID ); - mpIconMBar = nullptr; - mnIconID = 0; - } - } - catch ( ... ) { - mpIconMBar = nullptr; - mnIconID = 0; - } - - mpIconSysWin = nullptr; - } -} - - -IMPL_LINK_NOARG(UpdateCheckUI, ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool) -{ - SolarMutexGuard aGuard; - - maWaitIdle.Stop(); - if ( mpBubbleWin ) - mpBubbleWin->Show( false ); - if ( mrJob.is() ) { try { @@ -501,145 +292,6 @@ IMPL_LINK_NOARG(UpdateCheckUI, ClickHdl, MenuBar::MenuBarButtonCallbackArg&, boo xErrorBox->run(); } } - - return false; -} - - -IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, rData, bool ) -{ - if ( rData.bHighlight ) - maWaitIdle.Start(); - else - RemoveBubbleWindow( false ); - - return false; -} - - -IMPL_LINK_NOARG(UpdateCheckUI, WaitTimeOutHdl, Timer *, void) -{ - SolarMutexGuard aGuard; - - mpBubbleWin = GetBubbleWindow(); - - if ( mpBubbleWin ) - { - mpBubbleWin->Show(); - } -} - - -IMPL_LINK_NOARG(UpdateCheckUI, TimeOutHdl, Timer *, void) -{ - RemoveBubbleWindow( false ); -} - - -IMPL_LINK_NOARG(UpdateCheckUI, UserEventHdl, void*, void) -{ - SolarMutexGuard aGuard; - - vcl::Window *pTopWin = Application::GetFirstTopLevelWindow(); - vcl::Window *pActiveWin = Application::GetActiveTopWindow(); - SystemWindow *pActiveSysWin = nullptr; - - vcl::Window *pBubbleWin = nullptr; - if ( mpBubbleWin ) - pBubbleWin = mpBubbleWin; - - if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() ) - pActiveSysWin = pActiveWin->GetSystemWindow(); - - if ( pActiveWin == pBubbleWin ) - pActiveSysWin = nullptr; - - while ( !pActiveSysWin && pTopWin ) - { - if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() ) - pActiveSysWin = pTopWin->GetSystemWindow(); - if ( !pActiveSysWin ) - pTopWin = Application::GetNextTopLevelWindow( pTopWin ); - } - - if ( pActiveSysWin ) - AddMenuBarIcon( pActiveSysWin, true ); -} - - -IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent&, rEvent, void ) -{ - VclEventId nEventID = rEvent.GetId(); - - if ( VclEventId::ObjectDying == nEventID ) - { - SolarMutexGuard aGuard; - if ( mpIconSysWin == rEvent.GetWindow() ) - { - mpIconSysWin->RemoveEventListener( maWindowEventHdl ); - RemoveBubbleWindow( true ); - } - } - else if ( VclEventId::WindowMenubarAdded == nEventID ) - { - SolarMutexGuard aGuard; - vcl::Window *pWindow = rEvent.GetWindow(); - if ( pWindow ) - { - SystemWindow *pSysWin = pWindow->GetSystemWindow(); - if ( pSysWin ) - { - AddMenuBarIcon( pSysWin, false ); - } - } - } - else if ( VclEventId::WindowMenubarRemoved == nEventID ) - { - SolarMutexGuard aGuard; - MenuBar *pMBar = static_cast<MenuBar*>(rEvent.GetData()); - if ( pMBar && ( pMBar == mpIconMBar ) ) - RemoveBubbleWindow( true ); - } - else if ( ( nEventID == VclEventId::WindowMove ) || - ( nEventID == VclEventId::WindowResize ) ) - { - SolarMutexGuard aGuard; - if ( ( mpIconSysWin == rEvent.GetWindow() ) && - mpBubbleWin && ( mpIconMBar != nullptr ) ) - { - tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID ); - Point aWinPos = aIconRect.BottomCenter(); - mpBubbleWin->SetTipPosPixel( aWinPos ); - if ( mpBubbleWin->IsVisible() ) - mpBubbleWin->Show(); // This will recalc the screen position of the bubble - } - } -} - - -IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent&, rEvent, void) -{ - switch (rEvent.GetId()) - { - case VclEventId::WindowShow: - case VclEventId::WindowActivate: - case VclEventId::WindowGetFocus: { - SolarMutexGuard aGuard; - - vcl::Window *pWindow = static_cast< VclWindowEvent * >(&rEvent)->GetWindow(); - if ( pWindow && pWindow->IsTopWindow() ) - { - SystemWindow *pSysWin = pWindow->GetSystemWindow(); - MenuBar *pMBar = pSysWin ? pSysWin->GetMenuBar() : nullptr; - if (pMBar) - { - AddMenuBarIcon( pSysWin, true ); - } - } - break; - } - default: break; - } } } // anonymous namespace diff --git a/include/vcl/bubblewindow.hxx b/include/vcl/bubblewindow.hxx index 0d9d873437e2..ae15c051ecc1 100644 --- a/include/vcl/bubblewindow.hxx +++ b/include/vcl/bubblewindow.hxx @@ -21,6 +21,7 @@ #include <vcl/floatwin.hxx> #include <vcl/image.hxx> +#include <vcl/menu.hxx> class VCL_DLLPUBLIC BubbleWindow final : public FloatingWindow { @@ -52,4 +53,61 @@ public: const Image& rImage ); }; +class VCL_DLLPUBLIC MenuBarUpdateIconManager +{ +private: + OUString maBubbleTitle; + OUString maBubbleText; + OUString maBubbleImageURL; + Image maBubbleImage; + VclPtr<BubbleWindow> mpBubbleWin; + VclPtr<SystemWindow> mpIconSysWin; + VclPtr<MenuBar> mpIconMBar; + + Link<VclWindowEvent&,void> maWindowEventHdl; + Link<VclSimpleEvent&,void> maApplicationEventHdl; + Link<LinkParamNone*,void> maClickHdl; + + Timer maTimeoutTimer; + Idle maWaitIdle; + + sal_uInt16 mnIconID; + + bool mbShowMenuIcon; + bool mbShowBubble; + bool mbBubbleChanged; + + DECL_LINK(UserEventHdl, void *, void); + DECL_LINK(TimeOutHdl, Timer *, void); + DECL_LINK(WindowEventHdl, VclWindowEvent&, void); + DECL_LINK(ApplicationEventHdl, VclSimpleEvent&, void); + DECL_LINK(WaitTimeOutHdl, Timer *, void); + DECL_LINK(ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool); + DECL_LINK(HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, bool); + + VclPtr<BubbleWindow> GetBubbleWindow(); + void SetBubbleChanged(); + +public: + MenuBarUpdateIconManager(); + ~MenuBarUpdateIconManager(); + + void SetShowMenuIcon(bool bShowMenuIcon); + void SetShowBubble(bool bShowBubble); + void SetBubbleImage(const Image& rImage); + void SetBubbleTitle(const OUString& rTitle); + void SetBubbleText(const OUString& rText); + + void SetClickHdl(const Link<LinkParamNone*,void>& rHdl) { maClickHdl = rHdl; } + + bool GetShowMenuIcon() const { return mbShowMenuIcon; } + bool GetShowBubble() const { return mbShowBubble; } + OUString GetBubbleTitle() const { return maBubbleTitle; } + OUString GetBubbleText() const { return maBubbleText; } + + void RemoveBubbleWindow(bool bRemoveIcon); + + void AddMenuBarIcon(SystemWindow *pSysWin, bool bAddEventHdl); +}; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/bitmaps.hlst b/vcl/inc/bitmaps.hlst index 73e05c724ca2..02e3dea0f540 100644 --- a/vcl/inc/bitmaps.hlst +++ b/vcl/inc/bitmaps.hlst @@ -221,6 +221,9 @@ #define CHEVRON "sfx2/res/chevron.png" +#define RID_UPDATE_AVAILABLE_16 "extensions/res/update/ui/onlineupdate_16.png" +#define RID_UPDATE_AVAILABLE_26 "extensions/res/update/ui/onlineupdate_26.png" + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/window/bubblewindow.cxx b/vcl/source/window/bubblewindow.cxx index 65e96753d08e..736b66612b0f 100644 --- a/vcl/source/window/bubblewindow.cxx +++ b/vcl/source/window/bubblewindow.cxx @@ -17,10 +17,13 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <rtl/ustrbuf.hxx> #include <vcl/bubblewindow.hxx> #include <vcl/lineinfo.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> +#include <unotools/resmgr.hxx> +#include <bitmaps.hlst> #define TIP_HEIGHT 15 #define TIP_WIDTH 7 @@ -46,8 +49,6 @@ BubbleWindow::BubbleWindow( vcl::Window* pParent, const OUString& rTitle, void BubbleWindow::Resize() { - SolarMutexGuard aGuard; - FloatingWindow::Resize(); Size aSize = GetSizePixel(); @@ -87,8 +88,6 @@ void BubbleWindow::SetTitleAndText( const OUString& rTitle, void BubbleWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& /*rRect*/) { - SolarMutexGuard aGuard; - LineInfo aThickLine( LineStyle::Solid, 2 ); DrawPolyLine( maRectPoly, aThickLine ); @@ -130,8 +129,6 @@ void BubbleWindow::MouseButtonDown( const MouseEvent& ) void BubbleWindow::Show( bool bVisible ) { - SolarMutexGuard aGuard; - if ( !bVisible ) { FloatingWindow::Show( bVisible ); @@ -216,4 +213,342 @@ void BubbleWindow::RecalcTextRects() maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetFontHeight() * 3 / 4 ); } +MenuBarUpdateIconManager::MenuBarUpdateIconManager() + : mnIconID (0) + , mbShowMenuIcon(false) + , mbShowBubble(false) + , mbBubbleChanged( false ) +{ + maTimeoutTimer.SetTimeout( 10000 ); + maTimeoutTimer.SetInvokeHandler(LINK(this, MenuBarUpdateIconManager, TimeOutHdl)); + + maWaitIdle.SetPriority( TaskPriority::LOWEST ); + maWaitIdle.SetInvokeHandler(LINK(this, MenuBarUpdateIconManager, WaitTimeOutHdl)); + + maApplicationEventHdl = LINK(this, MenuBarUpdateIconManager, ApplicationEventHdl); + Application::AddEventListener( maApplicationEventHdl ); + + maWindowEventHdl = LINK(this, MenuBarUpdateIconManager, WindowEventHdl); +} + +VclPtr<BubbleWindow> MenuBarUpdateIconManager::GetBubbleWindow() +{ + if ( !mpIconSysWin ) + return nullptr; + + tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID ); + if( aIconRect.IsEmpty() ) + return nullptr; + + auto pBubbleWin = mpBubbleWin; + + if ( !pBubbleWin ) { + pBubbleWin = VclPtr<BubbleWindow>::Create( mpIconSysWin, maBubbleTitle, + maBubbleText, maBubbleImage ); + mbBubbleChanged = false; + } + else if ( mbBubbleChanged ) { + pBubbleWin->SetTitleAndText( maBubbleTitle, maBubbleText, + maBubbleImage ); + mbBubbleChanged = false; + } + + Point aWinPos = aIconRect.BottomCenter(); + + pBubbleWin->SetTipPosPixel( aWinPos ); + + return pBubbleWin; +} + +IMPL_LINK_NOARG(MenuBarUpdateIconManager, TimeOutHdl, Timer *, void) +{ + RemoveBubbleWindow( false ); +} + +IMPL_LINK(MenuBarUpdateIconManager, WindowEventHdl, VclWindowEvent&, rEvent, void) +{ + VclEventId nEventID = rEvent.GetId(); + + if ( VclEventId::ObjectDying == nEventID ) + { + if ( mpIconSysWin == rEvent.GetWindow() ) + { + mpIconSysWin->RemoveEventListener( maWindowEventHdl ); + RemoveBubbleWindow( true ); + } + } + else if ( VclEventId::WindowMenubarAdded == nEventID ) + { + vcl::Window *pWindow = rEvent.GetWindow(); + if ( pWindow ) + { + SystemWindow *pSysWin = pWindow->GetSystemWindow(); + if ( pSysWin ) + { + AddMenuBarIcon( pSysWin, false ); + } + } + } + else if ( VclEventId::WindowMenubarRemoved == nEventID ) + { + MenuBar *pMBar = static_cast<MenuBar*>(rEvent.GetData()); + if ( pMBar && ( pMBar == mpIconMBar ) ) + RemoveBubbleWindow( true ); + } + else if ( ( nEventID == VclEventId::WindowMove ) || + ( nEventID == VclEventId::WindowResize ) ) + { + if ( ( mpIconSysWin == rEvent.GetWindow() ) && + mpBubbleWin && ( mpIconMBar != nullptr ) ) + { + tools::Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID ); + Point aWinPos = aIconRect.BottomCenter(); + mpBubbleWin->SetTipPosPixel( aWinPos ); + if ( mpBubbleWin->IsVisible() ) + mpBubbleWin->Show(); // This will recalc the screen position of the bubble + } + } +} + +IMPL_LINK(MenuBarUpdateIconManager, ApplicationEventHdl, VclSimpleEvent&, rEvent, void) +{ + switch (rEvent.GetId()) + { + case VclEventId::WindowShow: + case VclEventId::WindowActivate: + case VclEventId::WindowGetFocus: { + + vcl::Window *pWindow = static_cast< VclWindowEvent * >(&rEvent)->GetWindow(); + if ( pWindow && pWindow->IsTopWindow() ) + { + SystemWindow *pSysWin = pWindow->GetSystemWindow(); + MenuBar *pMBar = pSysWin ? pSysWin->GetMenuBar() : nullptr; + if (pMBar) + { + AddMenuBarIcon( pSysWin, true ); + } + } + break; + } + default: break; + } +} + +IMPL_LINK_NOARG(MenuBarUpdateIconManager, UserEventHdl, void*, void) +{ + vcl::Window *pTopWin = Application::GetFirstTopLevelWindow(); + vcl::Window *pActiveWin = Application::GetActiveTopWindow(); + SystemWindow *pActiveSysWin = nullptr; + + vcl::Window *pBubbleWin = nullptr; + if ( mpBubbleWin ) + pBubbleWin = mpBubbleWin; + + if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() ) + pActiveSysWin = pActiveWin->GetSystemWindow(); + + if ( pActiveWin == pBubbleWin ) + pActiveSysWin = nullptr; + + while ( !pActiveSysWin && pTopWin ) + { + if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() ) + pActiveSysWin = pTopWin->GetSystemWindow(); + if ( !pActiveSysWin ) + pTopWin = Application::GetNextTopLevelWindow( pTopWin ); + } + + if ( pActiveSysWin ) + AddMenuBarIcon( pActiveSysWin, true ); +} + +IMPL_LINK_NOARG(MenuBarUpdateIconManager, ClickHdl, MenuBar::MenuBarButtonCallbackArg&, bool) +{ + maWaitIdle.Stop(); + if ( mpBubbleWin ) + mpBubbleWin->Show( false ); + + maClickHdl.Call(nullptr); + + return false; +} + +IMPL_LINK(MenuBarUpdateIconManager, HighlightHdl, MenuBar::MenuBarButtonCallbackArg&, rData, bool) +{ + if ( rData.bHighlight ) + maWaitIdle.Start(); + else + RemoveBubbleWindow(false); + + return false; +} + +IMPL_LINK_NOARG(MenuBarUpdateIconManager, WaitTimeOutHdl, Timer *, void) +{ + mpBubbleWin = GetBubbleWindow(); + + if ( mpBubbleWin ) + { + mpBubbleWin->Show(); + } +} + +MenuBarUpdateIconManager::~MenuBarUpdateIconManager() +{ + Application::RemoveEventListener( maApplicationEventHdl ); + + RemoveBubbleWindow(true); +} + +void MenuBarUpdateIconManager::SetShowMenuIcon(bool bShowMenuIcon) +{ + if ( bShowMenuIcon != mbShowMenuIcon ) + { + mbShowMenuIcon = bShowMenuIcon; + if ( bShowMenuIcon ) + Application::PostUserEvent(LINK(this, MenuBarUpdateIconManager, UserEventHdl)); + else + RemoveBubbleWindow( true ); + } +} + +void MenuBarUpdateIconManager::SetShowBubble(bool bShowBubble) +{ + mbShowBubble = bShowBubble; + if ( mbShowBubble ) + Application::PostUserEvent(LINK(this, MenuBarUpdateIconManager, UserEventHdl)); + else if ( mpBubbleWin ) + mpBubbleWin->Show( false ); +} + +void MenuBarUpdateIconManager::SetBubbleChanged() +{ + mbBubbleChanged = true; + if (mbBubbleChanged && mpBubbleWin) + mpBubbleWin->Show( false ); +} + +void MenuBarUpdateIconManager::SetBubbleImage(const Image& rImage) +{ + maBubbleImage = rImage; + SetBubbleChanged(); +} + +void MenuBarUpdateIconManager::SetBubbleTitle(const OUString& rTitle) +{ + if (rTitle != maBubbleTitle) + { + maBubbleTitle = rTitle; + SetBubbleChanged(); + } +} + +void MenuBarUpdateIconManager::SetBubbleText(const OUString& rText) +{ + if (rText != maBubbleText) + { + maBubbleText = rText; + SetBubbleChanged(); + } +} + +namespace { +Image GetMenuBarIcon( MenuBar const * pMBar ) +{ + OUString sResID; + vcl::Window *pMBarWin = pMBar->GetWindow(); + sal_uInt32 nMBarHeight = 20; + + if ( pMBarWin ) + nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight(); + + if (nMBarHeight >= 35) + sResID = RID_UPDATE_AVAILABLE_26; + else + sResID = RID_UPDATE_AVAILABLE_16; + + return Image(StockImage::Yes, sResID); +} +} + +void MenuBarUpdateIconManager::AddMenuBarIcon(SystemWindow *pSysWin, bool bAddEventHdl) +{ + if ( ! mbShowMenuIcon ) + return; + + MenuBar *pActiveMBar = pSysWin->GetMenuBar(); + if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) ) + { + if ( bAddEventHdl && mpIconSysWin ) + mpIconSysWin->RemoveEventListener( maWindowEventHdl ); + + RemoveBubbleWindow( true ); + + if ( pActiveMBar ) + { + OUStringBuffer aBuf; + if( !maBubbleTitle.isEmpty() ) + aBuf.append( maBubbleTitle ); + if( !maBubbleText.isEmpty() ) + { + if( !maBubbleTitle.isEmpty() ) + aBuf.append( "\n\n" ); + aBuf.append( maBubbleText ); + } + + Image aImage = GetMenuBarIcon( pActiveMBar ); + mnIconID = pActiveMBar->AddMenuBarButton( aImage, + LINK( this, MenuBarUpdateIconManager, ClickHdl ), + aBuf.makeStringAndClear() + ); + pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID, + LINK( this, MenuBarUpdateIconManager, HighlightHdl ) ); + } + mpIconMBar = pActiveMBar; + mpIconSysWin = pSysWin; + if ( bAddEventHdl && mpIconSysWin ) + mpIconSysWin->AddEventListener( maWindowEventHdl ); + } + + if ( mbShowBubble && pActiveMBar ) + { + mpBubbleWin = GetBubbleWindow(); + if ( mpBubbleWin ) + { + mpBubbleWin->Show(); + maTimeoutTimer.Start(); + } + mbShowBubble = false; + } +} + +void MenuBarUpdateIconManager::RemoveBubbleWindow( bool bRemoveIcon ) +{ + maWaitIdle.Stop(); + maTimeoutTimer.Stop(); + + if ( mpBubbleWin ) + { + mpBubbleWin.disposeAndClear(); + } + + if ( bRemoveIcon ) + { + try { + if ( mpIconMBar && ( mnIconID != 0 ) ) + { + mpIconMBar->RemoveMenuBarButton( mnIconID ); + mpIconMBar = nullptr; + mnIconID = 0; + } + } + catch ( ... ) { + mpIconMBar = nullptr; + mnIconID = 0; + } + + mpIconSysWin = nullptr; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |