summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorMaxim Monastirsky <momonasmon@gmail.com>2017-02-12 22:14:48 +0200
committerMaxim Monastirsky <momonasmon@gmail.com>2017-02-12 21:56:29 +0000
commit81d4fbc0daa54889ccb09e6a3fadff9c70d99448 (patch)
treee76c9281a295dda0e1b25316efc77640ad3dc3bf /framework
parente5aa7a5b5753c57969fc2e17fb334781bb2a0481 (diff)
tdf#42029 Use a floating toolbar to show clipped items
Change-Id: I6b366f115258ef8497807163179d3e08ab3d5e6f Reviewed-on: https://gerrit.libreoffice.org/34180 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
Diffstat (limited to 'framework')
-rw-r--r--framework/inc/uielement/toolbarmanager.hxx11
-rw-r--r--framework/source/uielement/addonstoolbarmanager.cxx1
-rw-r--r--framework/source/uielement/popuptoolbarcontroller.cxx10
-rw-r--r--framework/source/uielement/subtoolbarcontroller.cxx1
-rw-r--r--framework/source/uielement/toolbarmanager.cxx217
5 files changed, 132 insertions, 108 deletions
diff --git a/framework/inc/uielement/toolbarmanager.hxx b/framework/inc/uielement/toolbarmanager.hxx
index 739d22f5647a..9876d6b61ef8 100644
--- a/framework/inc/uielement/toolbarmanager.hxx
+++ b/framework/inc/uielement/toolbarmanager.hxx
@@ -94,6 +94,7 @@ class ToolBarManager : public ToolbarManager_Base
void CheckAndUpdateImages();
virtual void RefreshImages();
void FillToolbar( const css::uno::Reference< css::container::XIndexAccess >& rToolBarData );
+ void FillOverflowToolbar( ToolBox* pParent );
void notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand );
void Destroy();
@@ -113,8 +114,6 @@ class ToolBarManager : public ToolbarManager_Base
};
protected:
- DECL_LINK( Command, CommandEvent const *, void );
- PopupMenu * GetToolBarCustomMenu(ToolBox* pToolBar);
DECL_LINK(Click, ToolBox *, void);
DECL_LINK(DropdownClick, ToolBox *, void);
DECL_LINK(DoubleClick, ToolBox *, void);
@@ -124,13 +123,16 @@ class ToolBarManager : public ToolbarManager_Base
DECL_LINK( MiscOptionsChanged, LinkParamNone*, void );
DECL_LINK( MenuButton, ToolBox *, void );
+ DECL_LINK( MenuPreExecute, ToolBox *, void );
DECL_LINK( MenuSelect, Menu *, bool );
- void MenuDeactivated();
DECL_LINK(AsyncUpdateControllersHdl, Timer *, void);
+ DECL_LINK( OverflowEventListener, VclWindowEvent&, void );
DECL_STATIC_LINK( ToolBarManager, ExecuteHdl_Impl, void*, void );
virtual bool MenuItemAllowed( sal_uInt16 ) const;
+ void AddCustomizeMenuItems(ToolBox* pToolBar);
+ void InitImageManager();
void RemoveControllers();
void CreateControllers();
void UpdateControllers();
@@ -138,7 +140,6 @@ class ToolBarManager : public ToolbarManager_Base
void UpdateController( const css::uno::Reference< css::frame::XToolbarController >& xController);
//end
void AddFrameActionListener();
- void ImplClearPopupMenu( ToolBox *pToolBar );
void RequestImages();
ToolBoxItemBits ConvertStyleToToolboxItemBits( sal_Int32 nStyle );
css::uno::Reference< css::frame::XModel > GetModelFromFrame() const;
@@ -178,6 +179,8 @@ class ToolBarManager : public ToolbarManager_Base
SubToolBarToSubToolBarControllerMap m_aSubToolBarControllerMap;
Timer m_aAsyncUpdateControllersTimer;
OUString m_sIconTheme;
+
+ rtl::Reference< ToolBarManager > m_aOverflowManager;
};
}
diff --git a/framework/source/uielement/addonstoolbarmanager.cxx b/framework/source/uielement/addonstoolbarmanager.cxx
index 9458d2f6e45f..4f8a4f6a7b7d 100644
--- a/framework/source/uielement/addonstoolbarmanager.cxx
+++ b/framework/source/uielement/addonstoolbarmanager.cxx
@@ -82,7 +82,6 @@ AddonsToolBarManager::AddonsToolBarManager( const Reference< XComponentContext >
m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) );
m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) );
m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) );
- m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) );
m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) );
m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) );
}
diff --git a/framework/source/uielement/popuptoolbarcontroller.cxx b/framework/source/uielement/popuptoolbarcontroller.cxx
index b04c831e7a12..34b3a39cf528 100644
--- a/framework/source/uielement/popuptoolbarcontroller.cxx
+++ b/framework/source/uielement/popuptoolbarcontroller.cxx
@@ -200,7 +200,13 @@ PopupMenuToolbarController::createPopupWindow()
pToolBox->SetItemDown( m_nToolBoxId, true );
WindowAlign eAlign( pToolBox->GetAlign() );
- sal_uInt16 nId = m_xPopupMenu->execute(
+
+ // If the parent ToolBox is in popup mode (e.g. sub toolbar, overflow popup),
+ // its ToolBarManager can be disposed along with our controller, destroying
+ // m_xPopupMenu, while the latter still in execute. This should be fixed at a
+ // different level, for now just hold it here so it won't crash.
+ css::uno::Reference< css::awt::XPopupMenu > xPopupMenu ( m_xPopupMenu );
+ sal_uInt16 nId = xPopupMenu->execute(
css::uno::Reference< css::awt::XWindowPeer >( getParent(), css::uno::UNO_QUERY ),
VCLUnoHelper::ConvertToAWTRect( pToolBox->GetItemRect( m_nToolBoxId ) ),
( eAlign == WindowAlign::Top || eAlign == WindowAlign::Bottom ) ?
@@ -209,7 +215,7 @@ PopupMenuToolbarController::createPopupWindow()
pToolBox->SetItemDown( m_nToolBoxId, false );
if ( nId )
- functionExecuted( m_xPopupMenu->getCommand( nId ) );
+ functionExecuted( xPopupMenu->getCommand( nId ) );
return xRet;
}
diff --git a/framework/source/uielement/subtoolbarcontroller.cxx b/framework/source/uielement/subtoolbarcontroller.cxx
index de8dffd16875..aa5450fe9436 100644
--- a/framework/source/uielement/subtoolbarcontroller.cxx
+++ b/framework/source/uielement/subtoolbarcontroller.cxx
@@ -245,6 +245,7 @@ css::uno::Reference< css::awt::XWindow > SubToolBarController::createPopupWindow
// calc and set size for popup mode
Size aSize = pToolBar->CalcPopupWindowSizePixel();
pToolBar->SetSizePixel( aSize );
+ pToolBar->SetMenuType( ToolBoxMenuType::NONE );
// open subtoolbox in popup mode
vcl::Window::GetDockingManager()->StartPopupMode( pToolBox, pToolBar );
}
diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx
index 7331d246018b..c7af7cf5869e 100644
--- a/framework/source/uielement/toolbarmanager.cxx
+++ b/framework/source/uielement/toolbarmanager.cxx
@@ -180,9 +180,10 @@ ToolBarManager::ToolBarManager( const Reference< XComponentContext >& rxContext,
if ( !aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "CreateDialog"))
nMenuType |= ToolBoxMenuType::Customize;
- m_pToolBar->SetCommandHdl( LINK( this, ToolBarManager, Command ) );
m_pToolBar->SetMenuType( nMenuType );
m_pToolBar->SetMenuButtonHdl( LINK( this, ToolBarManager, MenuButton ) );
+ m_pToolBar->SetMenuExecuteHdl( LINK( this, ToolBarManager, MenuPreExecute ) );
+ m_pToolBar->GetMenu()->SetSelectHdl( LINK( this, ToolBarManager, MenuSelect ) );
// set name for testtool, the useful part is after the last '/'
sal_Int32 idx = rResourceName.lastIndexOf('/');
@@ -243,7 +244,6 @@ void ToolBarManager::Destroy()
m_pToolBar->SetDoubleClickHdl( Link<ToolBox *, void>() );
m_pToolBar->SetStateChangedHdl( Link<StateChangedType const *, void>() );
m_pToolBar->SetDataChangedHdl( Link<DataChangedEvent const *, void>() );
- m_pToolBar->SetCommandHdl( Link<CommandEvent const *, void>() );
m_pToolBar.clear();
@@ -493,7 +493,11 @@ void SAL_CALL ToolBarManager::dispose()
}
m_xModuleImageManager.clear();
- ImplClearPopupMenu( m_pToolBar );
+ if ( m_aOverflowManager.is() )
+ {
+ m_aOverflowManager->dispose();
+ m_aOverflowManager.clear();
+ }
// We have to destroy our toolbar instance now.
Destroy();
@@ -919,18 +923,8 @@ ToolBoxItemBits ToolBarManager::ConvertStyleToToolboxItemBits( sal_Int32 nStyle
return nItemBits;
}
-void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer )
+void ToolBarManager::InitImageManager()
{
- OString aTbxName = OUStringToOString( m_aResourceName, RTL_TEXTENCODING_ASCII_US );
- SAL_INFO( "fwk.uielement", "framework (cd100003) ::ToolBarManager::FillToolbar " << aTbxName.getStr() );
-
- SolarMutexGuard g;
-
- if ( m_bDisposed )
- return;
-
- sal_uInt16 nId( 1 );
-
Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
if ( !m_xDocImageManager.is() )
{
@@ -966,6 +960,19 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine
m_xModuleImageManager->addConfigurationListener( Reference< XUIConfigurationListener >(
static_cast< OWeakObject* >( this ), UNO_QUERY ));
}
+}
+
+void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContainer )
+{
+ OString aTbxName = OUStringToOString( m_aResourceName, RTL_TEXTENCODING_ASCII_US );
+ SAL_INFO( "fwk.uielement", "framework (cd100003) ::ToolBarManager::FillToolbar " << aTbxName.getStr() );
+
+ SolarMutexGuard g;
+
+ if ( m_bDisposed )
+ return;
+
+ InitImageManager();
RemoveControllers();
@@ -974,6 +981,7 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine
m_aControllerMap.clear();
m_aCommandMap.clear();
+ sal_uInt16 nId( 1 );
CommandInfo aCmdInfo;
for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
{
@@ -1165,6 +1173,65 @@ void ToolBarManager::FillToolbar( const Reference< XIndexAccess >& rItemContaine
}
}
+void ToolBarManager::FillOverflowToolbar( ToolBox* pParent )
+{
+ CommandInfo aCmdInfo;
+ bool bInsertSeparator = false;
+ for ( sal_uInt16 i = 0; i < pParent->GetItemCount(); ++i )
+ {
+ sal_uInt16 nId = pParent->GetItemId( i );
+ if ( pParent->IsItemClipped( nId ) )
+ {
+ if ( bInsertSeparator )
+ {
+ m_pToolBar->InsertSeparator();
+ bInsertSeparator = false;
+ }
+
+ const OUString aCommandURL( pParent->GetItemCommand( nId ) );
+ m_pToolBar->InsertItem( nId, pParent->GetItemText( nId ) );
+ m_pToolBar->SetItemCommand( nId, aCommandURL );
+ m_pToolBar->SetQuickHelpText( nId, pParent->GetQuickHelpText( nId ) );
+
+ // Fill command map. It stores all our commands and from what
+ // image manager we got our image. So we can decide if we have to use an
+ // image from a notification message.
+ CommandToInfoMap::iterator pIter = m_aCommandMap.find( aCommandURL );
+ if ( pIter == m_aCommandMap.end())
+ {
+ aCmdInfo.nId = nId;
+ const CommandToInfoMap::value_type aValue( aCommandURL, aCmdInfo );
+ m_aCommandMap.insert( aValue );
+ }
+ else
+ {
+ pIter->second.aIds.push_back( nId );
+ }
+ }
+ else
+ {
+ ToolBoxItemType eType = pParent->GetItemType( i );
+ if ( m_pToolBar->GetItemCount() &&
+ ( eType == ToolBoxItemType::SEPARATOR || eType == ToolBoxItemType::BREAK ) )
+ bInsertSeparator = true;
+ }
+ }
+
+ InitImageManager();
+
+ // Request images for all toolbar items. Must be done before CreateControllers as
+ // some controllers need access to the image.
+ RequestImages();
+
+ // Create controllers after we set the images. There are controllers which needs
+ // an image at the toolbar at creation time!
+ CreateControllers();
+
+ // Notify controllers that they are now correctly initialized and can start listening
+ // toolbars that will open in popup mode will be updated immediately to avoid flickering
+ UpdateControllers();
+}
+
void ToolBarManager::RequestImages()
{
@@ -1297,39 +1364,6 @@ IMPL_LINK_NOARG(ToolBarManager, DoubleClick, ToolBox *, void)
HandleClick(&XToolbarController::doubleClick);
}
-void ToolBarManager::ImplClearPopupMenu( ToolBox *pToolBar )
-{
- if ( m_bDisposed )
- return;
-
- ::PopupMenu *pMenu = pToolBar->GetMenu();
- if (pMenu == nullptr) {
- return;
- }
-
- // remove config entries from menu, so we have a clean menu to start with
- // remove submenu first
- pMenu->SetPopupMenu( 1, nullptr );
-
- // remove all items that were not added by the toolbar itself
- sal_uInt16 i;
- for( i=0; i<pMenu->GetItemCount(); )
- {
- if( pMenu->GetItemId( i ) < TOOLBOX_MENUITEM_START
- && pMenu->GetItemId( i ) != 0 ) // Don't remove separators (Id == 0)
- pMenu->RemoveItem( i );
- else
- i++;
- }
-}
-
-void ToolBarManager::MenuDeactivated()
-{
- if (m_bDisposed)
- return;
- ImplClearPopupMenu(m_pToolBar);
-}
-
Reference< XModel > ToolBarManager::GetModelFromFrame() const
{
Reference< XController > xController = m_xFrame->getController();
@@ -1363,14 +1397,10 @@ bool ToolBarManager::MenuItemAllowed( sal_uInt16 ) const
return true;
}
-::PopupMenu * ToolBarManager::GetToolBarCustomMenu(ToolBox* pToolBar)
+void ToolBarManager::AddCustomizeMenuItems(ToolBox* pToolBar)
{
- // update the list of hidden tool items first
- pToolBar->UpdateCustomMenu();
-
::PopupMenu *pMenu = pToolBar->GetMenu();
- // remove all entries before inserting new ones
- ImplClearPopupMenu( pToolBar );
+
// No config menu entries if command ".uno:ConfigureDialog" is not enabled
Reference< XDispatch > xDisp;
css::util::URL aURL;
@@ -1383,7 +1413,7 @@ bool ToolBarManager::MenuItemAllowed( sal_uInt16 ) const
xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
if ( !xDisp.is() || IsPluginMode() )
- return nullptr;
+ return;
}
// popup menu for quick customization
@@ -1485,60 +1515,57 @@ bool ToolBarManager::MenuItemAllowed( sal_uInt16 ) const
if ( bHideDisabledEntries )
pMenu->RemoveDisabledEntries();
-
- return pMenu;
}
-IMPL_LINK( ToolBarManager, Command, CommandEvent const *, pCmdEvt, void )
+IMPL_LINK( ToolBarManager, MenuButton, ToolBox*, pToolBar, void )
{
SolarMutexGuard g;
if ( m_bDisposed )
return;
- if ( pCmdEvt->GetCommand() != CommandEventId::ContextMenu )
+
+ assert( !m_aOverflowManager.is() );
+
+ VclPtrInstance<ToolBox> pOverflowToolBar( pToolBar, WB_LINESPACING | WB_BORDER | WB_SCROLL );
+ pOverflowToolBar->SetOutStyle( pToolBar->GetOutStyle() );
+ m_aOverflowManager.set( new ToolBarManager( m_xContext, m_xFrame, OUString(), pOverflowToolBar ) );
+ m_aOverflowManager->FillOverflowToolbar( pToolBar );
+ pOverflowToolBar->SetMenuType( ToolBoxMenuType::NONE );
+
+ ::Size aActSize( pOverflowToolBar->GetSizePixel() );
+ ::Size aSize( pOverflowToolBar->CalcWindowSizePixel() );
+ aSize.Width() = aActSize.Width();
+ pOverflowToolBar->SetOutputSizePixel( aSize );
+
+ aSize = pOverflowToolBar->CalcPopupWindowSizePixel();
+ pOverflowToolBar->SetSizePixel( aSize );
+
+ pOverflowToolBar->EnableDocking();
+ pOverflowToolBar->AddEventListener( LINK( this, ToolBarManager, OverflowEventListener ) );
+ vcl::Window::GetDockingManager()->StartPopupMode( pToolBar, pOverflowToolBar, FloatWinPopupFlags::AllMouseButtonClose );
+}
+
+IMPL_LINK( ToolBarManager, OverflowEventListener, VclWindowEvent&, rWindowEvent, void )
+{
+ if ( rWindowEvent.GetId() != VclEventId::WindowEndPopupMode )
return;
- ::PopupMenu * pMenu = GetToolBarCustomMenu(m_pToolBar);
- if (pMenu)
+ if ( m_aOverflowManager.is() )
{
- // We only want to handle events for the context menu, but not events
- // on the toolbars overflow menu, hence we should only receive events
- // from the toolbox menu when we are actually showing it as our context
- // menu (the same menu retrieved with GetMenu() is reused for both the
- // overflow and context menus). If we set these Hdls permanently rather
- // than just when the context menu is showing, then events are duplicated
- // when the menu is being used as an overflow menu.
- Menu *pManagerMenu = m_pToolBar->GetMenu();
- pManagerMenu->SetSelectHdl( LINK( this, ToolBarManager, MenuSelect ) );
-
- // make sure all disabled entries will be shown
- pMenu->SetMenuFlags( pMenu->GetMenuFlags() | MenuFlags::AlwaysShowDisabledEntries );
- ::Point aPoint( pCmdEvt->GetMousePosPixel() );
- pMenu->Execute( m_pToolBar, aPoint );
-
- //fdo#86820 We may have been disposed and so have a NULL m_pToolBar by
- //executing a menu entry, e.g. inserting a chart replaces the toolbars
- pManagerMenu = m_bDisposed ? nullptr : m_pToolBar->GetMenu();
- if (pManagerMenu)
- {
- // Unlink our listeners again -- see above for why.
- pManagerMenu->SetSelectHdl( Link<Menu*, bool>() );
- MenuDeactivated();
- }
+ m_aOverflowManager->dispose();
+ m_aOverflowManager.clear();
}
}
-IMPL_LINK( ToolBarManager, MenuButton, ToolBox*, pToolBar, void )
+IMPL_LINK( ToolBarManager, MenuPreExecute, ToolBox*, pToolBar, void )
{
SolarMutexGuard g;
if ( m_bDisposed )
return;
- pToolBar->UpdateCustomMenu();
- // remove all entries that do not come from the toolbar itself (fdo#38276)
- ImplClearPopupMenu( pToolBar );
- }
+ AddCustomizeMenuItems( pToolBar );
+}
IMPL_LINK( ToolBarManager, MenuSelect, Menu*, pMenu, bool )
{
@@ -1700,21 +1727,9 @@ IMPL_LINK( ToolBarManager, MenuSelect, Menu*, pMenu, bool )
}
}
}
- else
- // The list of "hidden items", i.e. items which are disabled on
- // the toolbar hence shown in the context menu for easier access,
- // which are managed by the owning toolbar.
- {
- m_pToolBar->TriggerItem( pMenu->GetCurItemId()
- - TOOLBOX_MENUITEM_START );
- }
break;
}
}
-
- // remove all entries - deactivate is not reliable
- // The method checks if we are already disposed and in that case does nothing!
- ImplClearPopupMenu( m_pToolBar );
}
return true;