lp#1296715: refresh invalidated menus

- so we need to be a StatusListener in framework after all
- we ware updating all menus for now, instead of just one
- this would have a hugh performance hit when there is much change to the menu
- thus we just invalidate the menu and update with all changes after 100ms once

Change-Id: I48cda968cf0ae1eae0421b3424bb3e5830817e84
This commit is contained in:
Bjoern Michaelsen 2014-05-18 14:28:39 +02:00
parent b24739c98f
commit eda624641b
5 changed files with 80 additions and 1 deletions

View file

@ -67,6 +67,7 @@
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/svapp.hxx>
#include <vcl/window.hxx>
#include <vcl/menu.hxx>
#include <vcl/settings.hxx>
#include <osl/mutex.hxx>
#include <osl/file.hxx>
@ -429,6 +430,10 @@ throw ( RuntimeException, std::exception )
OUString aFeatureURL = Event.FeatureURL.Complete;
SolarMutexGuard aSolarGuard;
{
vcl::MenuInvalidator aInvalidator;
aInvalidator.Invalidated();
}
{
if ( m_bDisposed )
return;
@ -914,9 +919,9 @@ IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu )
if ( !bPopupMenu )
{
// We need only an update to reflect the current state
xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
}
}
else if ( !bPopupMenu )

View file

@ -23,6 +23,7 @@
#include <list>
#include <vcl/dllapi.h>
#include <vcl/vclevent.hxx>
#include <rtl/ustring.hxx>
@ -54,6 +55,8 @@ enum whichOfficePath { InstallationRootPath, UserPath, ConfigPath };
OUString VCL_DLLPUBLIC getOfficePath( enum whichOfficePath ePath );
} // namespace
bool VCL_DLLPUBLIC GetMenuInvalidateListeners();
#endif // INCLUDED_VCL_HELPER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -359,6 +359,17 @@ public:
};
namespace vcl
{
class VCL_DLLPUBLIC MenuInvalidator
{
public:
MenuInvalidator();
VclEventListeners2* GetMenuInvalidateListeners();
void Invalidated();
};
}
// - MenuBar -

View file

@ -6130,4 +6130,21 @@ ImplMenuDelData::~ImplMenuDelData()
const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
}
namespace vcl
{
MenuInvalidator::MenuInvalidator() {};
static VclEventListeners2* pMenuInvalidateListeners = NULL;
VclEventListeners2* MenuInvalidator::GetMenuInvalidateListeners()
{
if(!pMenuInvalidateListeners)
pMenuInvalidateListeners = new VclEventListeners2();
return pMenuInvalidateListeners;
}
void MenuInvalidator::Invalidated()
{
VclSimpleEvent aEvent(0);
GetMenuInvalidateListeners()->callListeners(&aEvent);
};
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -11,6 +11,8 @@
#ifdef ENABLE_GMENU_INTEGRATION
#include <generic/gendata.hxx>
#include <unx/saldisp.hxx>
#include <unx/gtk/glomenu.h>
#include <unx/gtk/gloactiongroup.h>
#include <vcl/menu.hxx>
@ -448,9 +450,50 @@ void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsig
pItem->mpSubMenu = pGtkSubMenu;
}
static bool bInvalidMenus = false;
static gboolean RefreshMenusUnity(gpointer)
{
SalDisplay* pSalDisplay = GetGenericData()->GetSalDisplay();
std::list< SalFrame* >::const_iterator pSalFrame = pSalDisplay->getFrames().begin();
std::list< SalFrame* >::const_iterator pEndSalFrame = pSalDisplay->getFrames().end();
for(; pSalFrame != pEndSalFrame; ++pSalFrame) {
const GtkSalFrame* pGtkSalFrame = static_cast< const GtkSalFrame* >( *pSalFrame );
GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(pGtkSalFrame);
GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*>(pFrameNonConst->GetMenu());
if(pSalMenu) {
pSalMenu->Activate();
pSalMenu->UpdateFull();
}
}
bInvalidMenus = false;
return FALSE;
}
static long RefreshMenusUnity(void*, void*)
{
if(!bInvalidMenus) {
g_timeout_add(10, &RefreshMenusUnity, NULL);
bInvalidMenus = true;
}
return 0;
}
static Link* getRefreshLinkInstance()
{
static Link* pLink = NULL;
if(!pLink) {
pLink = new Link(NULL, &RefreshMenusUnity);
}
return pLink;
}
void GtkSalMenu::SetFrame( const SalFrame* pFrame )
{
SolarMutexGuard aGuard;
{
vcl::MenuInvalidator aInvalidator;
aInvalidator.GetMenuInvalidateListeners()->addListener(*getRefreshLinkInstance());
}
assert(mbMenuBar);
SAL_INFO("vcl.unity", "GtkSalMenu set to frame");