summaryrefslogtreecommitdiff
path: root/framework/source/dispatch/menudispatcher.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/dispatch/menudispatcher.cxx')
-rw-r--r--framework/source/dispatch/menudispatcher.cxx488
1 files changed, 488 insertions, 0 deletions
diff --git a/framework/source/dispatch/menudispatcher.cxx b/framework/source/dispatch/menudispatcher.cxx
new file mode 100644
index 000000000000..248df065e38d
--- /dev/null
+++ b/framework/source/dispatch/menudispatcher.cxx
@@ -0,0 +1,488 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <dispatch/menudispatcher.hxx>
+#include <general.h>
+#include <xml/menuconfiguration.hxx>
+#include <classes/addonmenu.hxx>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <vcl/window.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/resmgr.hxx>
+#include <tools/rcid.h>
+#include <osl/mutex.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <rtl/logfile.hxx>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <ucbhelper/content.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+using namespace ::com::sun::star ;
+using namespace ::com::sun::star::awt ;
+using namespace ::com::sun::star::beans ;
+using namespace ::com::sun::star::container ;
+using namespace ::com::sun::star::frame ;
+using namespace ::com::sun::star::lang ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::util ;
+using namespace ::cppu ;
+ using ::rtl::OUString;
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+const USHORT SLOTID_MDIWINDOWLIST = 5610;
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+MenuDispatcher::MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory ,
+ const uno::Reference< XFrame >& xOwner )
+ // Init baseclasses first
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xOwnerWeak ( xOwner )
+ , m_xFactory ( xFactory )
+ , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
+ , m_bAlreadyDisposed ( sal_False )
+ , m_bActivateListener ( sal_False )
+ , m_pMenuManager ( NULL )
+{
+ // Safe impossible cases
+ // We need valid informations about ouer ownerfor work.
+ LOG_ASSERT( impldbg_checkParameter_MenuDispatcher( xFactory, xOwner ), "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!\n" )
+
+ m_bActivateListener = sal_True;
+ xOwner->addFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+MenuDispatcher::~MenuDispatcher()
+{
+ // Warn programmer if he forgot to dispose this instance.
+ // We must release all our references ...
+ // and a dtor isn't the best place to do that!
+}
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_4 ( MenuDispatcher ,
+ OWeakObject ,
+ DIRECT_INTERFACE( XTypeProvider ),
+ DIRECT_INTERFACE( XDispatch ),
+ DIRECT_INTERFACE( XEventListener ),
+ DERIVED_INTERFACE( XFrameActionListener, XEventListener )
+ )
+
+DEFINE_XTYPEPROVIDER_4 ( MenuDispatcher ,
+ XTypeProvider ,
+ XDispatch ,
+ XEventListener ,
+ XFrameActionListener
+ )
+
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void SAL_CALL MenuDispatcher::dispatch( const URL& /*aURL*/ ,
+ const Sequence< PropertyValue >& /*seqProperties*/ ) throw( RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void SAL_CALL MenuDispatcher::addStatusListener( const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL ) throw( RuntimeException )
+{
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+ // Safe impossible cases
+ // Method not defined for all incoming parameter
+ LOG_ASSERT( impldbg_checkParameter_addStatusListener( xControl, aURL ), "MenuDispatcher::addStatusListener()\nInvalid parameter detected.\n" )
+ // Add listener to container.
+ m_aListenerContainer.addInterface( aURL.Complete, xControl );
+}
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void SAL_CALL MenuDispatcher::removeStatusListener( const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL ) throw( RuntimeException )
+{
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+ // Safe impossible cases
+ // Method not defined for all incoming parameter
+ LOG_ASSERT( impldbg_checkParameter_removeStatusListener( xControl, aURL ), "MenuDispatcher::removeStatusListener()\nInvalid parameter detected.\n" )
+ // Add listener to container.
+ m_aListenerContainer.removeInterface( aURL.Complete, xControl );
+}
+
+//*****************************************************************************************************************
+// XFrameActionListener
+//*****************************************************************************************************************
+
+void SAL_CALL MenuDispatcher::frameAction( const FrameActionEvent& aEvent ) throw ( RuntimeException )
+{
+ ResetableGuard aGuard( m_aLock );
+
+ if ( m_pMenuManager && aEvent.Action == FrameAction_FRAME_UI_ACTIVATED )
+ {
+ MenuBar* pMenuBar = (MenuBar *)m_pMenuManager->GetMenu();
+ uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
+ aGuard.unlock();
+
+ if ( xFrame.is() && pMenuBar )
+ {
+ uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
+
+ SolarMutexGuard aSolarGuard;
+ {
+ Window* pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+ while ( pWindow && !pWindow->IsSystemWindow() )
+ pWindow = pWindow->GetParent();
+
+ if ( pWindow )
+ {
+ SystemWindow* pSysWindow = (SystemWindow *)pWindow;
+ pSysWindow->SetMenuBar( pMenuBar );
+ }
+ }
+ }
+ }
+ else if ( m_pMenuManager && aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
+ {
+ if ( m_pMenuManager )
+ impl_setMenuBar( NULL );
+ }
+}
+
+//*****************************************************************************************************************
+// XEventListener
+//*****************************************************************************************************************
+void SAL_CALL MenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
+{
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+ // Safe impossible cases
+ LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
+
+ if( m_bAlreadyDisposed == sal_False )
+ {
+ m_bAlreadyDisposed = sal_True;
+
+ if ( m_bActivateListener )
+ {
+ uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
+ if ( xFrame.is() )
+ {
+ xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
+ m_bActivateListener = sal_False;
+ if ( m_pMenuManager )
+ {
+ EventObject aEventObj;
+ aEventObj.Source = xFrame;
+ m_pMenuManager->disposing( aEventObj );
+ }
+ }
+ }
+
+ // Forget our factory.
+ m_xFactory = uno::Reference< XMultiServiceFactory >();
+
+ // Remove our menu from system window if it is still there!
+ if ( m_pMenuManager )
+ impl_setMenuBar( NULL );
+ }
+}
+
+//*****************************************************************************************************************
+// private method
+//
+//
+//*****************************************************************************************************************
+void MenuDispatcher::impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel )
+{
+ for ( USHORT nPos = 0; nPos < pMenu->GetItemCount(); ++nPos )
+ {
+ USHORT nId = pMenu->GetItemId(nPos);
+ PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
+ if ( pPopup )
+ impl_setAccelerators( (Menu *)pPopup, aAccel );
+ else if ( nId && !pMenu->GetPopupMenu(nId))
+ {
+ KeyCode aCode = aAccel.GetKeyCode( nId );
+ if ( aCode.GetCode() )
+ pMenu->SetAccelKey( nId, aCode );
+ }
+ }
+}
+
+//*****************************************************************************************************************
+// private method
+//
+//
+//*****************************************************************************************************************
+sal_Bool MenuDispatcher::impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource )
+{
+ uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
+ if ( xFrame.is() )
+ {
+ uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
+ Window* pWindow = NULL;
+
+ // Use SolarMutex for threadsafe code too!
+ SolarMutexGuard aSolarGuard;
+ {
+ pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
+ while ( pWindow && !pWindow->IsSystemWindow() )
+ pWindow = pWindow->GetParent();
+ }
+
+ if ( pWindow )
+ {
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+
+ SystemWindow* pSysWindow = (SystemWindow *)pWindow;
+
+ if ( m_pMenuManager )
+ {
+ // remove old menu from our system window if it was set before
+ if ( m_pMenuManager->GetMenu() == (Menu *)pSysWindow->GetMenuBar() )
+ pSysWindow->SetMenuBar( NULL );
+
+ // remove listener before we destruct ourself, so we cannot be called back afterwards
+ m_pMenuManager->RemoveListener();
+
+ SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)m_pMenuManager )->release();
+
+ m_pMenuManager = 0;
+ }
+
+ if ( pMenuBar != NULL )
+ {
+ USHORT nPos = pMenuBar->GetItemPos( SLOTID_MDIWINDOWLIST );
+ if ( nPos != MENU_ITEM_NOTFOUND )
+ {
+ OUString aNoContext;
+
+ uno::Reference< XModel > xModel;
+ uno::Reference< XController > xController( xFrame->getController(), UNO_QUERY );
+
+ if ( xController.is() )
+ xModel = uno::Reference< XModel >( xController->getModel(), UNO_QUERY );
+
+ // retrieve addon popup menus and add them to our menu bar
+ AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, pMenuBar );
+
+ // retrieve addon help menu items and add them to our help menu
+ AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar );
+ }
+
+ // set new menu on our system window and create new menu manager
+ if ( bMenuFromResource )
+ {
+ // #110897#
+ // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_False );
+ m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_False );
+ }
+ else
+ {
+ // #110897#
+ // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_True );
+ m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_True );
+ }
+
+ pSysWindow->SetMenuBar( pMenuBar );
+ }
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+IMPL_LINK( MenuDispatcher, Close_Impl, void*, EMPTYARG )
+{
+ css::uno::Reference < css::frame::XFrame > xFrame( m_xOwnerWeak.get(), css::uno::UNO_QUERY );
+ if ( !xFrame.is() )
+ return 0;
+
+ css::util::URL aURL;
+ aURL.Complete = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
+ css::uno::Reference< css::util::XURLTransformer > xTrans ( m_xFactory->createInstance(
+ SERVICENAME_URLTRANSFORMER ), css::uno::UNO_QUERY );
+ if( xTrans.is() )
+ {
+ // Datei laden
+ xTrans->parseStrict( aURL );
+ uno::Reference< XDispatchProvider > xProv( xFrame, UNO_QUERY );
+ if ( xProv.is() )
+ {
+ css::uno::Reference < css::frame::XDispatch > aDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
+ if ( aDisp.is() )
+ aDisp->dispatch( aURL, css::uno::Sequence < css::beans::PropertyValue>() );
+ }
+ }
+
+ return 0;
+}
+
+
+//_________________________________________________________________________________________________________________
+// debug methods
+//_________________________________________________________________________________________________________________
+
+/*-----------------------------------------------------------------------------------------------------------------
+ The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
+ we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
+
+ ATTENTION
+
+ If you miss a test for one of this parameters, contact the autor or add it himself !(?)
+ But ... look for right testing! See using of this methods!
+-----------------------------------------------------------------------------------------------------------------*/
+
+#ifdef ENABLE_ASSERTIONS
+
+//*****************************************************************************************************************
+sal_Bool MenuDispatcher::impldbg_checkParameter_MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory ,
+ const uno::Reference< XFrame >& xOwner )
+{
+ // Set default return value.
+ sal_Bool bOK = sal_True;
+ // Check parameter.
+ if (
+ ( &xFactory == NULL ) ||
+ ( &xOwner == NULL ) ||
+ ( xFactory.is() == sal_False ) ||
+ ( xOwner.is() == sal_False )
+ )
+ {
+ bOK = sal_False ;
+ }
+ // Return result of check.
+ return bOK ;
+}
+
+//*****************************************************************************************************************
+// We need a valid URL. What is meaning with "register for nothing"?!
+// xControl must correct to - nobody can advised otherwise!
+sal_Bool MenuDispatcher::impldbg_checkParameter_addStatusListener( const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL )
+{
+ // Set default return value.
+ sal_Bool bOK = sal_True;
+ // Check parameter.
+ if (
+ ( &xControl == NULL ) ||
+ ( &aURL == NULL ) ||
+ ( aURL.Complete.getLength() < 1 )
+ )
+ {
+ bOK = sal_False ;
+ }
+ // Return result of check.
+ return bOK ;
+}
+
+//*****************************************************************************************************************
+// The same goes for these case! We have added valid listener for correct URL only.
+// We can't remove invalid listener for nothing!
+sal_Bool MenuDispatcher::impldbg_checkParameter_removeStatusListener( const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL )
+{
+ // Set default return value.
+ sal_Bool bOK = sal_True;
+ // Check parameter.
+ if (
+ ( &xControl == NULL ) ||
+ ( &aURL == NULL ) ||
+ ( aURL.Complete.getLength() < 1 )
+ )
+ {
+ bOK = sal_False ;
+ }
+ // Return result of check.
+ return bOK ;
+}
+
+#endif // #ifdef ENABLE_ASSERTIONS
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */