[Libreoffice-commits] core.git: extensions/inc extensions/source include/vcl vcl/inc vcl/source
Caolán McNamara (via logerrit)
logerrit at kemper.freedesktop.org
Wed Mar 3 09:09:16 UTC 2021
extensions/inc/bitmaps.hlst | 2
extensions/source/update/ui/updatecheckui.cxx | 390 +-------------------------
include/vcl/bubblewindow.hxx | 58 +++
vcl/inc/bitmaps.hlst | 3
vcl/source/window/bubblewindow.cxx | 347 ++++++++++++++++++++++-
5 files changed, 423 insertions(+), 377 deletions(-)
New commits:
commit d2cd1fad73b97e62443a215c84b7b5d5ee74a818
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Mon Mar 1 21:01:05 2021 +0000
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Wed Mar 3 10:08:33 2021 +0100
split and move MenuBar BubbleWindowManager to vcl
Change-Id: I1d0f4b7d56845a77e979199917c5d9c849b76c8e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111798
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
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: */
More information about the Libreoffice-commits
mailing list