summaryrefslogtreecommitdiff
path: root/framework/source/dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/dispatch')
-rw-r--r--framework/source/dispatch/closedispatcher.cxx656
-rw-r--r--framework/source/dispatch/dispatchinformationprovider.cxx193
-rw-r--r--framework/source/dispatch/dispatchprovider.cxx798
-rw-r--r--framework/source/dispatch/helpagentdispatcher.cxx446
-rw-r--r--framework/source/dispatch/interaction.cxx212
-rw-r--r--framework/source/dispatch/interceptionhelper.cxx343
-rw-r--r--framework/source/dispatch/loaddispatcher.cxx201
-rw-r--r--framework/source/dispatch/mailtodispatcher.cxx333
-rw-r--r--framework/source/dispatch/makefile.mk63
-rw-r--r--framework/source/dispatch/menudispatcher.cxx488
-rw-r--r--framework/source/dispatch/oxt_handler.cxx283
-rw-r--r--framework/source/dispatch/popupmenudispatcher.cxx422
-rw-r--r--framework/source/dispatch/servicehandler.cxx354
-rw-r--r--framework/source/dispatch/startmoduledispatcher.cxx244
-rw-r--r--framework/source/dispatch/systemexec.cxx237
-rw-r--r--framework/source/dispatch/windowcommanddispatch.cxx194
16 files changed, 5467 insertions, 0 deletions
diff --git a/framework/source/dispatch/closedispatcher.cxx b/framework/source/dispatch/closedispatcher.cxx
new file mode 100644
index 000000000000..15b44aad0430
--- /dev/null
+++ b/framework/source/dispatch/closedispatcher.cxx
@@ -0,0 +1,656 @@
+/* -*- 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/closedispatcher.hxx>
+#include <pattern/frame.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <classes/framelistanalyzer.hxx>
+#include <services.h>
+#include <general.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/CommandGroup.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/document/XActionLockable.hpp>
+#include "com/sun/star/beans/XFastPropertySet.hpp"
+#include <toolkit/helper/vclunohelper.hxx>
+
+//_______________________________________________
+// includes of other projects
+
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <unotools/moduleoptions.hxx>
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+#ifdef fpf
+ #error "Who uses \"fpf\" as define. It will overwrite my namespace alias ..."
+#endif
+namespace fpf = ::framework::pattern::frame;
+
+//_______________________________________________
+// non exported const
+
+static ::rtl::OUString URL_CLOSEDOC = DECLARE_ASCII(".uno:CloseDoc" );
+static ::rtl::OUString URL_CLOSEWIN = DECLARE_ASCII(".uno:CloseWin" );
+static ::rtl::OUString URL_CLOSEFRAME = DECLARE_ASCII(".uno:CloseFrame");
+
+//_______________________________________________
+// declarations
+
+DEFINE_XINTERFACE_4(CloseDispatcher ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::frame::XNotifyingDispatch ),
+ DIRECT_INTERFACE(css::frame::XDispatch ),
+ DIRECT_INTERFACE(css::frame::XDispatchInformationProvider))
+
+// Note: XStatusListener is an implementation detail. Hide it for scripting!
+DEFINE_XTYPEPROVIDER_4(CloseDispatcher ,
+ css::lang::XTypeProvider ,
+ css::frame::XDispatchInformationProvider,
+ css::frame::XNotifyingDispatch ,
+ css::frame::XDispatch )
+
+//-----------------------------------------------
+CloseDispatcher::CloseDispatcher(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame ,
+ const ::rtl::OUString& sTarget)
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+ , ::cppu::OWeakObject( )
+ , m_xSMGR (xSMGR )
+ , m_aAsyncCallback (LINK( this, CloseDispatcher, impl_asyncCallback))
+ , m_lStatusListener (m_aLock.getShareableOslMutex() )
+{
+ m_xCloseFrame = CloseDispatcher::static_impl_searchRightTargetFrame(xFrame, sTarget);
+}
+
+//-----------------------------------------------
+CloseDispatcher::~CloseDispatcher()
+{
+}
+
+//-----------------------------------------------
+void SAL_CALL CloseDispatcher::dispatch(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
+ throw(css::uno::RuntimeException)
+{
+ dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
+}
+
+//-----------------------------------------------
+css::uno::Sequence< sal_Int16 > SAL_CALL CloseDispatcher::getSupportedCommandGroups()
+ throw(css::uno::RuntimeException)
+{
+ css::uno::Sequence< sal_Int16 > lGroups(2);
+ lGroups[0] = css::frame::CommandGroup::VIEW;
+ lGroups[1] = css::frame::CommandGroup::DOCUMENT;
+ return lGroups;
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL CloseDispatcher::getConfigurableDispatchInformation(sal_Int16 nCommandGroup)
+ throw(css::uno::RuntimeException)
+{
+ if (nCommandGroup == css::frame::CommandGroup::VIEW)
+ {
+ /* Attention: Dont add .uno:CloseFrame here. Because its not realy
+ a configurable feature ... and further it does not have
+ a valid UIName entry inside the GenericCommands.xcu ... */
+ css::uno::Sequence< css::frame::DispatchInformation > lViewInfos(1);
+ lViewInfos[0].Command = URL_CLOSEWIN;
+ lViewInfos[0].GroupId = css::frame::CommandGroup::VIEW;
+ return lViewInfos;
+ }
+ else
+ if (nCommandGroup == css::frame::CommandGroup::DOCUMENT)
+ {
+ css::uno::Sequence< css::frame::DispatchInformation > lDocInfos(1);
+ lDocInfos[0].Command = URL_CLOSEDOC;
+ lDocInfos[0].GroupId = css::frame::CommandGroup::DOCUMENT;
+ return lDocInfos;
+ }
+
+ return css::uno::Sequence< css::frame::DispatchInformation >();
+}
+
+//-----------------------------------------------
+void SAL_CALL CloseDispatcher::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+void SAL_CALL CloseDispatcher::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+void SAL_CALL CloseDispatcher::dispatchWithNotification(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
+ throw(css::uno::RuntimeException)
+{
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // This reference indicates, that we was already called before and
+ // our asynchronous process was not finished yet.
+ // We have to reject double calls. Otherwhise we risk,
+ // that we try to close an already closed resource ...
+ // And its no problem to do nothing then. The UI user will try it again, if
+ // non of these jobs was successfully.
+ if (m_xSelfHold.is())
+ {
+ aWriteLock.unlock();
+ // <- SAFE ------------------------------
+
+ implts_notifyResultListener(
+ xListener,
+ css::frame::DispatchResultState::DONTKNOW,
+ css::uno::Any());
+ return;
+ }
+
+ // First we have to check, if this dispatcher is used right. Means if valid URLs are used.
+ // If not - we have to break this operation. But an optional listener must be informed.
+ // BTW: We save the information about the requested operation. Because
+ // we need it later.
+ if (aURL.Complete.equals(URL_CLOSEDOC))
+ m_eOperation = E_CLOSE_DOC;
+ else
+ if (aURL.Complete.equals(URL_CLOSEWIN))
+ m_eOperation = E_CLOSE_WIN;
+ else
+ if (aURL.Complete.equals(URL_CLOSEFRAME))
+ m_eOperation = E_CLOSE_FRAME;
+ else
+ {
+ aWriteLock.unlock();
+ // <- SAFE ------------------------------
+
+ implts_notifyResultListener(
+ xListener,
+ css::frame::DispatchResultState::FAILURE,
+ css::uno::Any());
+ return;
+ }
+
+ // OK - URLs are the right ones.
+ // But we cant execute synchronously :-)
+ // May we are called from a generic key-input handler,
+ // which isnt aware that this call kill its own environment ...
+ // Do it asynchronous everytimes!
+
+ // But dont forget to hold usself alive.
+ // We are called back from an environment, which doesnt know an uno reference.
+ // They call us back by using our c++ interface.
+
+ m_xResultListener = xListener;
+ m_xSelfHold = css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ sal_Bool bIsSynchron = sal_False;
+ for (sal_Int32 nArgs=0; nArgs<lArguments.getLength(); nArgs++ )
+ {
+ if ( lArguments[nArgs].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SynchronMode")) )
+ {
+ lArguments[nArgs].Value >>= bIsSynchron;
+ break;
+ }
+ }
+
+ if ( bIsSynchron )
+ impl_asyncCallback(0);
+ else
+ m_aAsyncCallback.Post(0);
+}
+
+//-----------------------------------------------
+/**
+ @short asynchronous callback
+ @descr We start all actions inside this object asnychronoue.
+ (see comments there).
+ Now we do the following:
+ - close all views to the same document, if needed and possible
+ - make the current frame empty
+ ! This step is neccessary to handle errors during closing the
+ document inside the frame. May the document shows a dialog and
+ the user ignore it. Then the state of the office can be changed
+ during we try to close frame and document.
+ - check the environment (menas count open frames - exlcuding our
+ current one)
+ - decide then, if we must close this frame only, establish the backing mode
+ or shutdown the whole application.
+*/
+IMPL_LINK( CloseDispatcher, impl_asyncCallback, void*, EMPTYARG )
+{
+ try
+ {
+
+ // Allow calling of XController->suspend() everytimes.
+ // Dispatch is an UI functionality. We implement such dispatch object here.
+ // And further XController->suspend() was designed to bring an UI ...
+ sal_Bool bAllowSuspend = sal_True;
+ sal_Bool bControllerSuspended = sal_False;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ // Closing of all views, related to the same document, is allowed
+ // only if the dispatched URL was ".uno:CloseDoc"!
+ sal_Bool bCloseAllViewsToo = (m_eOperation == E_CLOSE_DOC);
+
+ // BTW: Make some copies, which are needed later ...
+ EOperation eOperation = m_eOperation;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::frame::XFrame > xCloseFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchResultListener > xListener = m_xResultListener;
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // frame already dead ?!
+ // Nothing to do !
+ if (! xCloseFrame.is())
+ return 0;
+
+ sal_Bool bCloseFrame = sal_False;
+ sal_Bool bEstablishBackingMode = sal_False;
+ sal_Bool bTerminateApp = sal_False;
+
+ // Analyze the environment a first time.
+ // If we found some special cases, we can
+ // make some decisions erliar!
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
+ FrameListAnalyzer aCheck1(xDesktop, xCloseFrame, FrameListAnalyzer::E_HELP | FrameListAnalyzer::E_BACKINGCOMPONENT);
+
+ // a) If the curent frame (where the close dispatch was requested for) does not have
+ // any parent frame ... it will close this frame only. Such frame isnt part of the
+ // global desktop tree ... and such frames are used as "implementation details" only.
+ // E.g. the live previews of our wizards doing such things. And then the owner of the frame
+ // is responsible for closing the application or accepting closing of the application
+ // by others.
+ if ( ! xCloseFrame->getCreator().is())
+ bCloseFrame = sal_True;
+ else
+
+ // b) The help window cant disagree with any request.
+ // Because it doesnt implement a controller - it uses a window only.
+ // Further t cant be the last open frame - if we do all other things
+ // right inside this CloseDispatcher implementation.
+ // => close it!
+ if (aCheck1.m_bReferenceIsHelp)
+ bCloseFrame = sal_True;
+ else
+
+ // c) If we are already in "backing mode", we have to terminate
+ // the application, if this special frame is closed.
+ // It doesnt matter, how many other frames (can be the help or hidden frames only)
+ // are open then.
+ // => terminate the application!
+ if (aCheck1.m_bReferenceIsBacking)
+ bTerminateApp = sal_True;
+ else
+
+ // d) Otherwhise we have to: close all views to the same document, close the
+ // document inside our own frame and decide then again, what has to be done!
+ {
+ if (implts_prepareFrameForClosing(m_xCloseFrame, bAllowSuspend, bCloseAllViewsToo, bControllerSuspended))
+ {
+ // OK; this frame is empty now.
+ // Check the environment again to decide, what is the next step.
+ FrameListAnalyzer aCheck2(xDesktop, xCloseFrame, FrameListAnalyzer::E_ALL);
+
+ // c1) there is as minimum 1 frame open, which is visible and contains a document
+ // different from our one. And its not the help!
+ // => close our frame only - nothing else.
+ if (aCheck2.m_lOtherVisibleFrames.getLength()>0)
+ bCloseFrame = sal_True;
+ else
+
+ // c2) if we close the current view ... but not all other views
+ // to the same document, we must close the current frame only!
+ // Because implts_closeView() suspended this view only - does not
+ // close the frame.
+ if (
+ (!bCloseAllViewsToo ) &&
+ (aCheck2.m_lModelFrames.getLength() > 0)
+ )
+ bCloseFrame = sal_True;
+
+ else
+ // c3) there is no other (visible) frame open ...
+ // The help module will be ignored everytimes!
+ // But we have to decide if we must terminate the
+ // application or establish the backing mode now.
+ // And that depends from the dispatched URL ...
+ {
+ if (eOperation == E_CLOSE_FRAME)
+ bTerminateApp = sal_True;
+ else if( SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE) )
+ bEstablishBackingMode = sal_True;
+ else
+ bTerminateApp = sal_True;
+ }
+ }
+ }
+
+ // Do it now ...
+ sal_Bool bSuccess = sal_False;
+ if (bCloseFrame)
+ bSuccess = implts_closeFrame();
+ else
+ if (bEstablishBackingMode)
+ #if defined QUARTZ
+ {
+ // on mac close down, quickstarter keeps the process alive
+ // however if someone has shut down the quickstarter
+ // behave as any other platform
+
+ bool bQuickstarterRunning = false;
+ // get quickstart service
+ try
+ {
+ css::uno::Reference< css::beans::XFastPropertySet > xSet( xSMGR->createInstance(IMPLEMENTATIONNAME_QUICKLAUNCHER), css::uno::UNO_QUERY_THROW );
+ if( xSet.is() )
+ {
+ css::uno::Any aVal( xSet->getFastPropertyValue( 0 ) );
+ sal_Bool bState = sal_False;
+ if( aVal >>= bState )
+ bQuickstarterRunning = bState;
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+ bSuccess = bQuickstarterRunning ? implts_terminateApplication() : implts_establishBackingMode();
+ }
+ #else
+ bSuccess = implts_establishBackingMode();
+ #endif
+ else
+ if (bTerminateApp)
+ bSuccess = implts_terminateApplication();
+
+ if (
+ ( ! bSuccess ) &&
+ ( bControllerSuspended )
+ )
+ {
+ css::uno::Reference< css::frame::XController > xController = xCloseFrame->getController();
+ if (xController.is())
+ xController->suspend(sal_False);
+ }
+
+ // inform listener
+ sal_Int16 nState = css::frame::DispatchResultState::FAILURE;
+ if (bSuccess)
+ nState = css::frame::DispatchResultState::SUCCESS;
+ implts_notifyResultListener(xListener, nState, css::uno::Any());
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+
+ // This method was called asynchronous from our main thread by using a pointer.
+ // We reached this method only, by using a reference to ourself :-)
+ // Further this member is used to detect still running and not yet finished
+ // ansynchronous operations. So its time now to release this reference.
+ // But hold it temp alive. Otherwhise we die before we can finish this method realy :-))
+ css::uno::Reference< css::uno::XInterface > xTempHold = m_xSelfHold;
+ m_xSelfHold.clear();
+ m_xResultListener.clear();
+
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ }
+ catch(const css::lang::DisposedException&)
+ {
+ LOG_ERROR("CloseDispatcher::impl_asyncCallback", "Congratulation! You found the reason for bug #120310#. Please contact the right developer and show him a scenario, which trigger this bug. THX.")
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------
+sal_Bool CloseDispatcher::implts_prepareFrameForClosing(const css::uno::Reference< css::frame::XFrame >& xFrame ,
+ sal_Bool bAllowSuspend ,
+ sal_Bool bCloseAllOtherViewsToo,
+ sal_Bool& bControllerSuspended )
+{
+ // Frame already dead ... so this view is closed ... is closed ... is ... .-)
+ if (! xFrame.is())
+ return sal_True;
+
+ // Close all views to the same document ... if forced to do so.
+ // But dont touch our own frame here!
+ // We must do so ... because the may be following controller->suspend()
+ // will show the "save/discard/cancel" dialog for the last view only!
+ if (bCloseAllOtherViewsToo)
+ {
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
+ FrameListAnalyzer aCheck(xDesktop, xFrame, FrameListAnalyzer::E_ALL);
+
+ sal_Int32 c = aCheck.m_lModelFrames.getLength();
+ sal_Int32 i = 0;
+ for (i=0; i<c; ++i)
+ {
+ if (!fpf::closeIt(aCheck.m_lModelFrames[i], sal_False))
+ return sal_False;
+ }
+ }
+
+ // If allowed - inform user about modified documents or
+ // still running jobs (e.g. printing).
+ if (bAllowSuspend)
+ {
+ css::uno::Reference< css::frame::XController > xController = xFrame->getController();
+ if (xController.is()) // some views dont uses a controller .-( (e.g. the help window)
+ {
+ bControllerSuspended = xController->suspend(sal_True);
+ if (! bControllerSuspended)
+ return sal_False;
+ }
+ }
+
+ // dont remove the component realy by e.g. calling setComponent(null, null).
+ // It's enough to suspend the controller.
+ // If we close the frame later this controller doesnt show the same dialog again.
+ return sal_True;
+}
+
+//-----------------------------------------------
+sal_Bool CloseDispatcher::implts_closeFrame()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XFrame > xFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ // frame already dead ? => so it's closed ... it's closed ...
+ if ( ! xFrame.is() )
+ return sal_True;
+
+ // dont deliver owner ship; our "UI user" will try it again if it failed.
+ // OK - he will get an empty frame then. But normaly an empty frame
+ // should be closeable always :-)
+ if (!fpf::closeIt(xFrame, sal_False))
+ return sal_False;
+
+ // SAFE -> ----------------------------------
+ WriteGuard aWriteLock(m_aLock);
+ m_xCloseFrame = css::uno::WeakReference< css::frame::XFrame >();
+ aWriteLock.unlock();
+ // <- SAFE ----------------------------------
+
+ return sal_True;
+}
+
+//-----------------------------------------------
+sal_Bool CloseDispatcher::implts_establishBackingMode()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::frame::XFrame > xFrame (m_xCloseFrame.get(), css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (!xFrame.is())
+ return sal_False;
+
+ css::uno::Reference < css::document::XActionLockable > xLock( xFrame, css::uno::UNO_QUERY );
+ if ( xLock.is() && xLock->isActionLocked() )
+ return sal_False;
+
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
+ css::uno::Sequence< css::uno::Any > lArgs(1);
+ lArgs[0] <<= xContainerWindow;
+
+ css::uno::Reference< css::frame::XController > xBackingComp(
+ xSMGR->createInstanceWithArguments(SERVICENAME_STARTMODULE, lArgs),
+ css::uno::UNO_QUERY_THROW);
+
+ // Attention: You MUST(!) call setComponent() before you call attachFrame().
+ css::uno::Reference< css::awt::XWindow > xBackingWin(xBackingComp, css::uno::UNO_QUERY);
+ xFrame->setComponent(xBackingWin, xBackingComp);
+ xBackingComp->attachFrame(xFrame);
+ xContainerWindow->setVisible(sal_True);
+
+ return sal_True;
+}
+
+//-----------------------------------------------
+sal_Bool CloseDispatcher::implts_terminateApplication()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XDesktop > xDesktop(
+ xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
+
+ return xDesktop->terminate();
+}
+
+//-----------------------------------------------
+void CloseDispatcher::implts_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
+ sal_Int16 nState ,
+ const css::uno::Any& aResult )
+{
+ if (!xListener.is())
+ return;
+
+ css::frame::DispatchResultEvent aEvent(
+ css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY),
+ nState,
+ aResult);
+
+ xListener->dispatchFinished(aEvent);
+}
+
+//-----------------------------------------------
+css::uno::Reference< css::frame::XFrame > CloseDispatcher::static_impl_searchRightTargetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame ,
+ const ::rtl::OUString& sTarget)
+{
+ if (sTarget.equalsIgnoreAsciiCaseAscii("_self"))
+ return xFrame;
+
+ OSL_ENSURE((sTarget.getLength() < 1), "CloseDispatch used for unexpected target. Magic things will happen now .-)");
+
+ css::uno::Reference< css::frame::XFrame > xTarget = xFrame;
+ while(sal_True)
+ {
+ // a) top frames wil be closed
+ if (xTarget->isTop())
+ return xTarget;
+
+ // b) even child frame containing top level windows (e.g. query designer of database) will be closed
+ css::uno::Reference< css::awt::XWindow > xWindow = xTarget->getContainerWindow();
+ css::uno::Reference< css::awt::XTopWindow > xTopWindowCheck(xWindow, css::uno::UNO_QUERY);
+ if (xTopWindowCheck.is())
+ {
+ // b1) Note: Toolkit interface XTopWindow sometimes is used by real VCL-child-windows also .-)
+ // Be sure that these window is realy a "top system window".
+ // Attention ! Checking Window->GetParent() isnt the right approach here.
+ // Because sometimes VCL create "implicit border windows" as parents even we created
+ // a simple XWindow using the toolkit only .-(
+ SolarMutexGuard aSolarLock;
+ Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if (
+ (pWindow ) &&
+ (pWindow->IsSystemWindow())
+ )
+ return xTarget;
+ }
+
+ // c) try to find better results on parent frame
+ // If no parent frame exists (because this frame is used outside the desktop tree)
+ // the given frame must be used directly.
+ css::uno::Reference< css::frame::XFrame > xParent(xTarget->getCreator(), css::uno::UNO_QUERY);
+ if ( ! xParent.is())
+ return xTarget;
+
+ // c1) check parent frame inside next loop ...
+ xTarget = xParent;
+ }
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/dispatchinformationprovider.cxx b/framework/source/dispatch/dispatchinformationprovider.cxx
new file mode 100644
index 000000000000..bef585ed6ab5
--- /dev/null
+++ b/framework/source/dispatch/dispatchinformationprovider.cxx
@@ -0,0 +1,193 @@
+/* -*- 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/dispatchinformationprovider.hxx>
+#include <dispatch/closedispatcher.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <stdtypes.h>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/frame/CommandGroup.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <comphelper/sequenceasvector.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+namespace css = ::com::sun::star;
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+DEFINE_XINTERFACE_1(DispatchInformationProvider ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::frame::XDispatchInformationProvider))
+
+//_________________________________________________________________________________________________________________
+DispatchInformationProvider::DispatchInformationProvider(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame)
+ : ThreadHelpBase(&Application::GetSolarMutex())
+ , m_xSMGR (xSMGR )
+ , m_xFrame (xFrame )
+{
+}
+
+//_________________________________________________________________________________________________________________
+DispatchInformationProvider::~DispatchInformationProvider()
+{
+}
+
+//_________________________________________________________________________________________________________________
+css::uno::Sequence< sal_Int16 > SAL_CALL DispatchInformationProvider::getSupportedCommandGroups()
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatchInformationProvider > > lProvider = implts_getAllSubProvider();
+ sal_Int32 c1 = lProvider.getLength();
+ sal_Int32 i1 = 0;
+
+ ::comphelper::SequenceAsVector< sal_Int16 > lGroups;
+
+ for (i1=0; i1<c1; ++i1)
+ {
+ // ignore controller, which doesnt implement the right interface
+ css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider = lProvider[i1];
+ if (!xProvider.is())
+ continue;
+
+ const css::uno::Sequence< sal_Int16 > lProviderGroups = xProvider->getSupportedCommandGroups();
+ sal_Int32 c2 = lProviderGroups.getLength();
+ sal_Int32 i2 = 0;
+ for (i2=0; i2<c2; ++i2)
+ {
+ const sal_Int16& rGroup = lProviderGroups[i2];
+ ::comphelper::SequenceAsVector< sal_Int16 >::const_iterator pGroup = ::std::find(lGroups.begin(), lGroups.end(), rGroup);
+ if (pGroup == lGroups.end())
+ lGroups.push_back(rGroup);
+ }
+ }
+
+ return lGroups.getAsConstList();
+}
+
+//_________________________________________________________________________________________________________________
+css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL DispatchInformationProvider::getConfigurableDispatchInformation(sal_Int16 nCommandGroup)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatchInformationProvider > > lProvider = implts_getAllSubProvider();
+ sal_Int32 c1 = lProvider.getLength();
+ sal_Int32 i1 = 0;
+
+ BaseHash< css::frame::DispatchInformation > lInfos;
+
+ for (i1=0; i1<c1; ++i1)
+ {
+ try
+ {
+ // ignore controller, which doesnt implement the right interface
+ css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider = lProvider[i1];
+ if (!xProvider.is())
+ continue;
+
+ const css::uno::Sequence< css::frame::DispatchInformation > lProviderInfos = xProvider->getConfigurableDispatchInformation(nCommandGroup);
+ sal_Int32 c2 = lProviderInfos.getLength();
+ sal_Int32 i2 = 0;
+ for (i2=0; i2<c2; ++i2)
+ {
+ const css::frame::DispatchInformation& rInfo = lProviderInfos[i2];
+ BaseHash< css::frame::DispatchInformation >::const_iterator pInfo = lInfos.find(rInfo.Command);
+ if (pInfo == lInfos.end())
+ lInfos[rInfo.Command] = rInfo;
+ }
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { continue; }
+ }
+
+ c1 = (sal_Int32)lInfos.size();
+ i1 = 0;
+
+ css::uno::Sequence< css::frame::DispatchInformation > lReturn(c1);
+ BaseHash< css::frame::DispatchInformation >::const_iterator pStepp ;
+ for ( pStepp = lInfos.begin() ;
+ pStepp != lInfos.end () && i1<c1 ;
+ ++pStepp, ++i1 )
+ {
+ lReturn[i1] = pStepp->second;
+ }
+ return lReturn;
+}
+
+//_________________________________________________________________________________________________________________
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatchInformationProvider > > DispatchInformationProvider::implts_getAllSubProvider()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY);
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ if (!xFrame.is())
+ return css::uno::Sequence< css::uno::Reference< css::frame::XDispatchInformationProvider > >();
+
+ CloseDispatcher* pCloser = new CloseDispatcher(xSMGR, xFrame, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_self"))); // explicit "_self" ... not "" ... see implementation of close dispatcher itself!
+ css::uno::Reference< css::uno::XInterface > xCloser(static_cast< css::frame::XDispatch* >(pCloser), css::uno::UNO_QUERY);
+
+ css::uno::Reference< css::frame::XDispatchInformationProvider > xCloseDispatch(xCloser , css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchInformationProvider > xController (xFrame->getController() , css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchInformationProvider > xAppDispatcher(xSMGR->createInstance(IMPLEMENTATIONNAME_APPDISPATCHPROVIDER), css::uno::UNO_QUERY);
+
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatchInformationProvider > > lProvider(3);
+ lProvider[0] = xController ;
+ lProvider[1] = xCloseDispatch;
+ lProvider[2] = xAppDispatcher;
+
+ return lProvider;
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/dispatchprovider.cxx b/framework/source/dispatch/dispatchprovider.cxx
new file mode 100644
index 000000000000..1b1bfc263335
--- /dev/null
+++ b/framework/source/dispatch/dispatchprovider.cxx
@@ -0,0 +1,798 @@
+/* -*- 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 <stdio.h>
+#include <dispatch/dispatchprovider.hxx>
+#include <loadenv/loadenv.hxx>
+#include <dispatch/loaddispatcher.hxx>
+#include <dispatch/closedispatcher.hxx>
+#include <dispatch/menudispatcher.hxx>
+#include <dispatch/helpagentdispatcher.hxx>
+#include <dispatch/startmoduledispatcher.hxx>
+
+#include <pattern/window.hxx>
+#include <threadhelp/transactionguard.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <dispatchcommands.h>
+#include <protocols.h>
+#include <services.h>
+#include <targets.h>
+#include <general.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/ucb/XContentProviderManager.hpp>
+#include <com/sun/star/document/XTypeDetection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+#include <osl/diagnose.h>
+#include <rtl/string.h>
+#include <rtl/ustring.hxx>
+#include <vcl/svapp.hxx>
+#include <rtl/ustrbuf.hxx>
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_2( DispatchProvider ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::frame::XDispatchProvider)
+ )
+
+DEFINE_XTYPEPROVIDER_2( DispatchProvider ,
+ css::lang::XTypeProvider ,
+ css::frame::XDispatchProvider
+ )
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short standard ctor/dtor
+ @descr These initialize a new instance of tihs class with needed informations for work.
+ We hold a weakreference to our owner frame which start dispatches at us.
+ We can't use a normal reference because he hold a reference of us too ...
+ nobody can die so ...!
+
+ @seealso using at owner
+
+ @param xFactory
+ reference to servicemanager to create new services.
+ @param xFrame
+ reference to our owner frame.
+
+ @modified 17.05.2002 10:07, as96863
+*/
+DispatchProvider::DispatchProvider( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame )
+ // Init baseclasses first
+ : ThreadHelpBase( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+ , m_xFrame ( xFrame )
+{
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short protected(!) dtor for deinitializing
+ @descr We made it protected to prevent using of us as base class instead as a member.
+
+ @modified 17.05.2002 10:05, as96863
+ */
+DispatchProvider::~DispatchProvider()
+{
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @interface XDispatchProvider
+ @short search a dispatcher for given URL
+ @descr If no interceptor is set on owner, we search for right frame and dispatch URL to it.
+ If no frame was found, we do nothing.
+ But we doesn't do it directly here. We detect the type of our owner frame and calls
+ specialized queryDispatch() helper dependen from that. Because a Desktop handle some
+ requests in another way then a normal frame.
+
+ @param aURL
+ URL to dispatch.
+ @param sTargetFrameName
+ name of searched frame.
+ @param nSearchFlags
+ flags for searching.
+ @return A reference to a dispatch object for this URL (if someone was found!).
+
+ @threadsafe yes
+ @modified 17.05.2002 10:59, as96863
+*/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL DispatchProvider::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
+ aReadLock.unlock();
+ /* } SAFE */
+
+ css::uno::Reference< css::frame::XDesktop > xDesktopCheck( xOwner, css::uno::UNO_QUERY );
+
+ if (xDesktopCheck.is())
+ xDispatcher = implts_queryDesktopDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
+ else
+ xDispatcher = implts_queryFrameDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
+
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @interface XDispatchProvider
+ @short do the same like queryDispatch() ... but handle multiple dispatches at the same time
+ @descr It's an optimism. User give us a list of queries ... and we return a list of dispatcher.
+ If one of given queries couldn't be solved to a real existing dispatcher ...
+ we return a list with empty references in it! Order of both lists will be retained!
+
+ @seealso method queryDispatch()
+
+ @param lDescriptions
+ a list of all dispatch parameters for multiple requests
+ @return A reference a list of dispatch objects for these URLs - may with some <NULL/> values inside.
+
+ @threadsafe yes
+ @modified 17.05.2002 09:55, as96863
+*/
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL DispatchProvider::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions ) throw( css::uno::RuntimeException )
+{
+ // Create return list - which must have same size then the given descriptor
+ // It's not allowed to pack it!
+ sal_Int32 nCount = lDescriptions.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
+
+ // Step over all descriptors and try to get any dispatcher for it.
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ lDispatcher[i] = queryDispatch( lDescriptions[i].FeatureURL ,
+ lDescriptions[i].FrameName ,
+ lDescriptions[i].SearchFlags );
+ }
+
+ return lDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+::sal_Bool lcl_isStartModuleDispatch (const css::util::URL& aURL)
+{
+ return (aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(CMD_UNO_SHOWSTARTMODULE)));
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short helper for queryDispatch()
+ @descr Every member of the frame tree (frame, desktop) must handle such request
+ in another way. So we implement different specialized metods for every one.
+
+ @threadsafe yes
+ @modified 20.08.2003 08:32, as96863
+ */
+css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryDesktopDispatch( const css::uno::Reference< css::frame::XFrame > xDesktop ,
+ const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+
+ // ignore wrong requests which are not supported
+ if (
+ (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for frame dispatches - not for desktop
+ (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for frame dispatches - not for desktop
+ (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition
+ (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only -
+ // and they exist more then ones. We have no idea which our sub tasks is the right one
+ )
+ {
+ return NULL;
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I) handle special cases which not right for using findFrame() first
+ //-----------------------------------------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.I) "_blank"
+ // It's not the right place to create a new task here - because we are queried for a dispatch object
+ // only, which can handle such request. Such dispatcher should create the required task on demand.
+ // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
+ // here. Thats why we must "intercept" here.
+ //-----------------------------------------------------------------------------------------------------
+ if (sTargetFrameName==SPECIALTARGET_BLANK)
+ {
+ if (implts_isLoadableContent(aURL))
+ xDispatcher = implts_getOrCreateDispatchHelper( E_BLANKDISPATCHER, xDesktop );
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.II) "_default"
+ // This is a combination of search an empty task for recycling - or create a new one.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetFrameName==SPECIALTARGET_DEFAULT)
+ {
+ if (implts_isLoadableContent(aURL))
+ xDispatcher = implts_getOrCreateDispatchHelper( E_DEFAULTDISPATCHER, xDesktop );
+
+ if (lcl_isStartModuleDispatch(aURL))
+ xDispatcher = implts_getOrCreateDispatchHelper( E_STARTMODULEDISPATCHER, xDesktop );
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.III) "_self", "", "_top"
+ // The desktop can't load any document - but he can handle some special protocols like "uno", "slot" ...
+ // Why is "top" here handled too? Because the desktop is the topest frame. Normaly it's superflous
+ // to use this target - but we can handle it in the same manner then "_self".
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (
+ (sTargetFrameName==SPECIALTARGET_SELF) ||
+ (sTargetFrameName==SPECIALTARGET_TOP ) ||
+ (sTargetFrameName.getLength()<1 )
+ )
+ {
+ xDispatcher = implts_searchProtocolHandler(aURL);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.IV) no further special targets exist
+ // Now we have to search for the right target frame by calling findFrame() - but should provide our code
+ // against creation of a new task if no frame could be found.
+ // I said it b efore - it's allowed for dispatch() only.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ {
+ sal_Int32 nRightFlags = nSearchFlags;
+ nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
+
+ // try to find any existing target and ask him for his dispatcher
+ css::uno::Reference< css::frame::XFrame > xFoundFrame = xDesktop->findFrame(sTargetFrameName, nRightFlags);
+ if (xFoundFrame.is())
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
+ xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
+ }
+ else
+ // if it couldn't be found - but creation was allowed
+ // use special dispatcher for creatio or froward it to the browser
+ if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
+ xDispatcher = implts_getOrCreateDispatchHelper( E_CREATEDISPATCHER, xDesktop, sTargetFrameName, nSearchFlags );
+ }
+
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryFrameDispatch( const css::uno::Reference< css::frame::XFrame > xFrame ,
+ const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName ,
+ sal_Int32 nSearchFlags )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+
+ //-----------------------------------------------------------------------------------------------------
+ // 0) Some URLs are dispatched in a generic way (e.g. by the menu) using the default target "".
+ // But they are specified to use her own fix target. Detect such URLs here and use the correct target.
+ //-----------------------------------------------------------------------------------------------------
+
+ ::rtl::OUString sTargetName = sTargetFrameName;
+
+ //-----------------------------------------------------------------------------------------------------
+ // I) handle special cases which not right for using findFrame() first
+ //-----------------------------------------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.I) "_blank", "_default"
+ // It's not the right place to create a new task here. Only the desktop can do that.
+ // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
+ // here. Thats why we must "intercept" here.
+ //-----------------------------------------------------------------------------------------------------
+ if (
+ (sTargetName==SPECIALTARGET_BLANK ) ||
+ (sTargetName==SPECIALTARGET_DEFAULT)
+ )
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
+ if (xParent.is())
+ xDispatcher = xParent->queryDispatch(aURL, sTargetName, 0); // its a special target - ignore search flags
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.II) "_menubar"
+ // Special mode on frame or task to receive the local menu. Not supported by findFrame()
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetName==SPECIALTARGET_MENUBAR)
+ {
+ xDispatcher = implts_getOrCreateDispatchHelper( E_MENUDISPATCHER, xFrame );
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.III) "_helpagent"
+ // Special mode on frame or task to start the help agent.
+ // It's defined for top level frames only.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetName==SPECIALTARGET_HELPAGENT)
+ {
+ if (WindowHelper::isTopWindow(xFrame->getContainerWindow()))
+ xDispatcher = implts_getOrCreateDispatchHelper( E_HELPAGENTDISPATCHER, xFrame );
+ else
+ {
+ // Don''t use findFrame() here - because it's not possible to find
+ // a top lebel frame without knowing his name. And a frame with name
+ // "" can't be realy searched! That's why forward query to any parent
+ // explicitly.
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFrame->getCreator(), css::uno::UNO_QUERY );
+ if (xProvider.is())
+ xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_HELPAGENT,0);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.IV) "_helpagent"
+ // Special sub frame of a top frame only. Search or create it. ... OK it's currently a little bit HACKI.
+ // Only the sfx (means the controller) can create it it.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetName==SPECIALTARGET_BEAMER)
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xBeamer( xFrame->findFrame( SPECIALTARGET_BEAMER, css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::SELF ), css::uno::UNO_QUERY );
+ if (xBeamer.is())
+ {
+ xDispatcher = xBeamer->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
+ }
+ else
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
+ if (xController.is())
+ // force using of special target - but use original search flags
+ // May the caller used the CREATE flag or not!
+ xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_BEAMER, nSearchFlags);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.V) "_parent"
+ // Our parent frame (if it exist) should handle this URL.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetName==SPECIALTARGET_PARENT)
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
+ if (xParent.is())
+ // SELF => we must adress the parent directly... and not his parent or any other parent!
+ xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.VI) "_top"
+ // This request must be forwarded to any parent frame, till we reach a top frame.
+ // If no parent exist, we can handle itself.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (sTargetName==SPECIALTARGET_TOP)
+ {
+ if (xFrame->isTop())
+ {
+ // If we are this top frame itself (means our owner frame)
+ // we should call ourself recursiv with a better target "_self".
+ // So we can share the same code! (see reaction for "_self" inside this method too.)
+ xDispatcher = this->queryDispatch(aURL,SPECIALTARGET_SELF,0);
+ }
+ else
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
+ // Normaly if isTop() returned FALSE ... the parent frame MUST(!) exist ...
+ // But it seams to be better to check that here to prevent us against an access violation.
+ if (xParent.is())
+ xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_TOP, 0);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.VII) "_self", ""
+ // Our owner frame should handle this URL. But we can't do it for all of them.
+ // So we ask the internal setted controller first. If he disagree we try to find a registered
+ // protocol handler. If this failed too - we check for a loadable content and in case of true
+ // we load it into the frame by returning specilized dispatch object.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ if (
+ (sTargetName==SPECIALTARGET_SELF) ||
+ (sTargetName.getLength()<1 )
+ )
+ {
+ // There exist a hard coded interception for special URLs.
+ if (
+ (aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".uno:CloseDoc"))) ||
+ (aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".uno:CloseWin")))
+ )
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
+ // In case the frame is not a top one, is not based on system window and has a parent,
+ // the parent frame should to be queried for the correct dispatcher.
+ // See i93473
+ if (
+ !WindowHelper::isTopWindow(xFrame->getContainerWindow()) &&
+ !VCLUnoHelper::GetWindow(xFrame->getContainerWindow())->IsSystemWindow() &&
+ xParent.is()
+ )
+ xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
+ else
+ xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
+ }
+ else if (aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".uno:CloseFrame")))
+ xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
+
+ if ( ! xDispatcher.is())
+ {
+ // Ask our controller for his agreement for these dispatched URL ...
+ // because some URLs are internal and can be handled faster by SFX - which most is the current controller!
+ // But in case of e.g. the bibliography not all queries will be handled successfully here.
+ css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
+ if (xController.is())
+ xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
+ }
+
+ // If controller has no fun to dispatch these URL - we must search another right dispatcher.
+ // Search for any registered protocol handler first.
+ if (!xDispatcher.is())
+ xDispatcher = implts_searchProtocolHandler(aURL);
+
+ // Not for controller - not for protocol handler
+ // It should be a loadable content - may be a file. Check it ...
+ // This check is neccessary to found out, that
+ // support for some protocols isn't installed by user. May be
+ // "ftp" isn't available. So we suppress creation of our self dispatcher.
+ // The result will be clear. He can't handle it - but he would try it.
+ if (
+ ( ! xDispatcher.is() ) &&
+ ( implts_isLoadableContent(aURL) )
+ )
+ {
+ xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------
+ // I.VI) no further special handlings exist
+ // Now we have to search for the right target frame by calling findFrame() - but should provide our code
+ // against creation of a new task if no frame could be found.
+ // I said it before - it's allowed for dispatch() only.
+ //-----------------------------------------------------------------------------------------------------
+ else
+ {
+ sal_Int32 nRightFlags = nSearchFlags;
+ nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
+
+ // try to find any existing target and ask him for his dispatcher
+ css::uno::Reference< css::frame::XFrame > xFoundFrame = xFrame->findFrame(sTargetName, nRightFlags);
+ if (xFoundFrame.is())
+ {
+ // Attention: Found target is our own owner frame!
+ // Don't ask him for his dispatcher. We know it already - it's our self dispatch helper.
+ // Otherwhise we can start a never ending recursiv call. Why?
+ // Somewere called our owner frame - he called some interceptor objects - and may by this dispatch provider
+ // is called. If wa use queryDispatch() on our owner frame again - we start this call stack again ... and again.
+ if (xFoundFrame==xFrame)
+ xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
+ else
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
+ xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
+ }
+ }
+ else
+ // if it couldn't be found - but creation was allowed
+ // forward request to the desktop.
+ // Note: The given target name must be used to set the name on new created task!
+ // Don't forward request by changing it to a special one e.g _blank.
+ // Use the CREATE flag only to prevent call against further searches.
+ // We already know it - the target must be created new.
+ if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
+ if (xParent.is())
+ xDispatcher = xParent->queryDispatch(aURL, sTargetName, css::frame::FrameSearchFlag::CREATE);
+ }
+ }
+
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short search for a registered protocol handler and ask him for a dispatch object
+ @descr Wes earch a suitable handler inside our cfg package org.openoffice.Office.ProtocolHandler.
+ If we found anyone, we create and initialize it. Initialize means: we set our owner frame on it
+ as context information. He can use it or leave it. Of course - we are aware of handler implementations,
+ which doesn't support initialization. It's an optional feature.
+
+ @param aURL
+ the dispatch URL for which may a handler is registered
+
+ @return A dispatch object if a handler was found and agree with the given URL or <NULL/> otherwhise.
+
+ @threadsafe yes
+ @modified 05.09.2002 13:43, as96863
+*/
+css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_searchProtocolHandler( const css::util::URL& aURL )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+ ProtocolHandler aHandler ;
+
+ // This member is threadsafe by himself and lives if we live - we doesn't need any mutex here.
+ if (m_aProtocolHandlerCache.search(aURL,&aHandler))
+ {
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+
+ // create it
+ css::uno::Reference< css::frame::XDispatchProvider > xHandler;
+ try
+ {
+ xHandler = css::uno::Reference< css::frame::XDispatchProvider >(
+ m_xFactory->createInstance(aHandler.m_sUNOName),
+ css::uno::UNO_QUERY);
+ }
+ catch(css::uno::Exception&) {}
+
+ // look if initialization is neccessary
+ css::uno::Reference< css::lang::XInitialization > xInit( xHandler, css::uno::UNO_QUERY );
+ if (xInit.is())
+ {
+ css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
+ LOG_ASSERT(xOwner.is(), "DispatchProvider::implts_searchProtocolHandler()\nCouldn't get reference to my owner frame. So I can't set may needed context information for this protocol handler.")
+ if (xOwner.is())
+ {
+ try
+ {
+ // but do it only, if all context informations are OK
+ css::uno::Sequence< css::uno::Any > lContext(1);
+ lContext[0] <<= xOwner;
+ xInit->initialize(lContext);
+ }
+ catch(css::uno::Exception&) {}
+ }
+ }
+
+ aReadLock.unlock();
+ /* } SAFE */
+
+ // ask for his (sub)dispatcher for the given URL
+ if (xHandler.is())
+ xDispatcher = xHandler->queryDispatch(aURL,SPECIALTARGET_SELF,0);
+ }
+
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short get or create new dispatch helper
+ @descr Sometimes we need some helper implementations to support dispatching of special URLs or commands.
+ But it's not a good idea to hold these services for the whole life time of this provider instance.
+ We should create it on demand ...
+ Thats why we implement this method. It return an already existing helper or create a new one otherwise.
+
+ @attention The parameter sTarget and nSearchFlags are defaulted to "" and 0!
+ Please use it only, if you can be shure, that the realy given by the outside calli!
+ Mostly it depends from the parameter eHelper is they are required or not.
+
+ @param eHelper
+ specify the requested dispatch helper
+ @param xOwner
+ the target of possible dispatch() call on created dispatch helper
+ @param sTarget
+ the target parameter of the original queryDispatch() request
+ @param nSearchFlags
+ the flags parameter of the original queryDispatch() request
+ @return A reference to a dispatch helper.
+
+ @threadsafe yes
+ @modified 20.08.2003 10:22, as96863
+*/
+css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_getOrCreateDispatchHelper( EDispatchHelper eHelper ,
+ const css::uno::Reference< css::frame::XFrame >& xOwner ,
+ const ::rtl::OUString& sTarget ,
+ sal_Int32 nSearchFlags)
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatchHelper;
+
+ /* SAFE { */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ /* } SAFE */
+
+ switch (eHelper)
+ {
+ case E_MENUDISPATCHER :
+ {
+ // Attention: Such menue dispatcher must be a singleton for this frame - means our owner frame.
+ // Otherwhise he can make some trouble.
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ if ( ! m_xMenuDispatcher.is() )
+ {
+ MenuDispatcher* pDispatcher = new MenuDispatcher( xFactory, xOwner );
+ m_xMenuDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ xDispatchHelper = m_xMenuDispatcher;
+ aWriteLock.unlock();
+ /* } SAFE */
+ }
+ break;
+
+ case E_HELPAGENTDISPATCHER :
+ {
+ // Attention: It's not a good idea to create this help agent twice for the same frame (window)
+ // May it will be shown twice too - and user activate the first one. Then he get the corresponding
+ // help window ... but there exist another help agent window on bottom side of the frame window.
+ // It's superflous. Create it on demand - but hold it alive till this provider dies.
+ /* SAFE { */
+ WriteGuard aWriteLock( m_aLock );
+ if ( ! m_xHelpAgentDispatcher.is() )
+ {
+ HelpAgentDispatcher* pDispatcher = new HelpAgentDispatcher( xOwner );
+ m_xHelpAgentDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ xDispatchHelper = m_xHelpAgentDispatcher;
+ aWriteLock.unlock();
+ /* } SAFE */
+ }
+ break;
+
+ case E_CREATEDISPATCHER :
+ {
+ LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, sTarget, nSearchFlags);
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ break;
+
+ case E_BLANKDISPATCHER :
+ {
+ css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
+ if (xDesktop.is())
+ {
+ LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_BLANK, 0);
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ }
+ break;
+
+ case E_DEFAULTDISPATCHER :
+ {
+ css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
+ if (xDesktop.is())
+ {
+ LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_DEFAULT, 0);
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ }
+ break;
+
+ case E_SELFDISPATCHER :
+ {
+ LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_SELF, 0);
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ break;
+
+ case E_CLOSEDISPATCHER :
+ {
+ CloseDispatcher* pDispatcher = new CloseDispatcher( xFactory, xOwner, sTarget );
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ break;
+
+ case E_STARTMODULEDISPATCHER :
+ {
+ StartModuleDispatcher* pDispatcher = new StartModuleDispatcher( xFactory, xOwner, sTarget );
+ xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
+ }
+ break;
+ }
+
+ return xDispatchHelper;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short check URL for support by our used loader or handler
+ @descr If we must return our own dispatch helper implementations (self, blank, create dispatcher!)
+ we should be shure, that URL describe any loadable content. Otherwise slot/uno URLs
+ will be detected ... but there exist nothing for ral loading into a target frame!
+
+ @param aURL
+ URL which should be "detected"
+ @return <TRUE/> if somewhere could handle that - <FALSE/> otherwise.
+
+ @threadsafe yes
+ @modified 17.05.2002 09:47, as96863
+*/
+sal_Bool DispatchProvider::implts_isLoadableContent( const css::util::URL& aURL )
+{
+ LoadEnv::EContentType eType = LoadEnv::classifyContent(aURL.Complete, css::uno::Sequence< css::beans::PropertyValue >());
+ return ( eType == LoadEnv::E_CAN_BE_LOADED );
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/helpagentdispatcher.cxx b/framework/source/dispatch/helpagentdispatcher.cxx
new file mode 100644
index 000000000000..4ae8ac15ee6f
--- /dev/null
+++ b/framework/source/dispatch/helpagentdispatcher.cxx
@@ -0,0 +1,446 @@
+/* -*- 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"
+#include <dispatch/helpagentdispatcher.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <svtools/helpopt.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+
+namespace css = ::com::sun::star;
+
+//........................................................................
+namespace framework
+{
+
+//-----------------------------------------------
+DEFINE_XINTERFACE_4(HelpAgentDispatcher ,
+ OWeakObject ,
+ DIRECT_INTERFACE (css::lang::XTypeProvider ),
+ DIRECT_INTERFACE (css::frame::XDispatch ),
+ DIRECT_INTERFACE (css::awt::XWindowListener),
+ DIRECT_INTERFACE (css::lang::XEventListener))
+
+//-----------------------------------------------
+DEFINE_XTYPEPROVIDER_2(HelpAgentDispatcher ,
+ css::lang::XTypeProvider,
+ css::frame::XDispatch )
+
+//--------------------------------------------------------------------
+HelpAgentDispatcher::HelpAgentDispatcher( const css::uno::Reference< css::frame::XFrame >& xParentFrame)
+ : ThreadHelpBase (&Application::GetSolarMutex())
+ , m_sCurrentURL ( )
+ , m_xContainerWindow( )
+ , m_xAgentWindow ( )
+ , m_aTimer ( )
+ , m_xSelfHold ( )
+{
+ // It's required that this class has to be contructed with a valid frame.
+ // And "valid" means: the frame must already bound to a valid container window.
+ m_xContainerWindow = xParentFrame->getContainerWindow();
+}
+
+//--------------------------------------------------------------------
+HelpAgentDispatcher::~HelpAgentDispatcher()
+{
+ implts_stopTimer();
+ implts_ignoreCurrentURL();
+
+ // Needed ... because it was create as "new VCLWindow()" ! Such windows must be disposed explicitly.
+ css::uno::Reference< css::lang::XComponent > xAgentWindow(m_xAgentWindow, css::uno::UNO_QUERY);
+ if (xAgentWindow.is())
+ xAgentWindow->dispose();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::dispatch(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >&)
+ throw(css::uno::RuntimeException)
+{
+ // silently drop the request if the new URL was marked to be ignored next time.
+ sal_Int32 nAllowedToIgnore = SvtHelpOptions().getAgentIgnoreURLCounter(aURL.Complete);
+ if (nAllowedToIgnore < 1)
+ return;
+
+ // stop the expiration timer for the old URL
+ // The timer will add the old URL to the list of ignorable URLs.
+ // So m_sCurrentURL must be set AFTER the timer was stopped !!!
+ implts_stopTimer();
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_sCurrentURL = aURL.Complete;
+ aWriteLock.unlock();
+ // <- SAFE
+
+ // start the expiration timer for the new URL
+ implts_startTimer();
+
+ // make sure the agent window is shown
+ implts_showAgentWindow();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >&,
+ const css::util::URL&)
+ throw(css::uno::RuntimeException)
+{
+ // no status available
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >&,
+ const css::util::URL&)
+ throw(css::uno::RuntimeException)
+{
+ // no status available
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::windowResized(const css::awt::WindowEvent&)
+ throw(css::uno::RuntimeException)
+{
+ implts_positionAgentWindow();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::windowMoved(const css::awt::WindowEvent&)
+ throw(css::uno::RuntimeException)
+{
+ implts_positionAgentWindow();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::windowShown(const css::lang::EventObject&)
+ throw(css::uno::RuntimeException)
+{
+ implts_showAgentWindow();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::windowHidden(const css::lang::EventObject&)
+ throw(css::uno::RuntimeException)
+{
+ implts_hideAgentWindow();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL HelpAgentDispatcher::disposing(const css::lang::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ // Already disposed ?!
+ if (! m_xContainerWindow.is())
+ return;
+ // Wrong broadcaster ?!
+ if (aEvent.Source != m_xContainerWindow)
+ return;
+
+ css::uno::Reference< css::uno::XInterface > xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY_THROW);
+ m_xSelfHold.clear();
+
+ aWriteLock.unlock();
+ // <- SAFE
+
+ implts_stopTimer();
+ implts_hideAgentWindow();
+ implts_ignoreCurrentURL();
+
+ // SAFE ->
+ aWriteLock.lock();
+ m_xContainerWindow.clear();
+ css::uno::Reference< css::lang::XComponent > xAgentWindow(m_xAgentWindow, css::uno::UNO_QUERY);
+ m_xAgentWindow.clear();
+ aWriteLock.unlock();
+ // <- SAFE
+
+ // Needed ... because it was create as "new VCLWindow()" ! Such windows must be disposed explicitly.
+ if (xAgentWindow.is())
+ xAgentWindow->dispose();
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::helpRequested()
+{
+ implts_stopTimer();
+ implts_hideAgentWindow();
+ implts_acceptCurrentURL();
+}
+
+//-----------------------------------------------
+void HelpAgentDispatcher::closeAgent()
+{
+ implts_stopTimer();
+ implts_hideAgentWindow();
+ implts_ignoreCurrentURL();
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_acceptCurrentURL()
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ ::rtl::OUString sAcceptedURL = m_sCurrentURL;
+ m_sCurrentURL = ::rtl::OUString();
+
+ aWriteLock.unlock();
+ // <- SAFE
+
+ // We must make sure that this URL isnt marked as ignored by the user.
+ // Otherwhise the user wont see the corresponding help content in the future.
+ SvtHelpOptions().resetAgentIgnoreURLCounter(sAcceptedURL);
+
+ // show the right help content
+ // SOLAR SAFE ->
+ {
+ SolarMutexGuard aSolarLock;
+ Help* pHelp = Application::GetHelp();
+ if (pHelp)
+ pHelp->Start(sAcceptedURL, NULL);
+ }
+ // <- SOLAR SAFE
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_ignoreCurrentURL()
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+
+ ::rtl::OUString sIgnoredURL = m_sCurrentURL;
+ m_sCurrentURL = ::rtl::OUString();
+
+ aWriteLock.unlock();
+ // <- SAFE
+
+ if (sIgnoredURL.getLength())
+ SvtHelpOptions().decAgentIgnoreURLCounter(sIgnoredURL);
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_stopTimer()
+{
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xSelfHold.clear();
+ aWriteLock.unlock();
+ // <- SAFE
+
+ // SOLAR SAFE ->
+ // Timer access needs no "own lock" ! It lives if we live ...
+ // But it requires locking of the solar mutex ... because it's a vcl based timer.
+ {
+ SolarMutexGuard aSolarLock;
+ if (! m_aTimer.IsActive())
+ return;
+ m_aTimer.Stop();
+ }
+ // <- SOLAR SAFE
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_startTimer()
+{
+ // SOLAR SAFE ->
+ // Timer access needs no "own lock" ! It lives if we live ...
+ // But it requires locking of the solar mutex ... because it's a vcl based timer.
+ {
+ SolarMutexGuard aSolarLock;
+ if (m_aTimer.IsActive())
+ return;
+ }
+ // <- SOLAR SAFE
+
+ // SAFE ->
+ // Timer uses pointer to this help agent dispatcher ...
+ // But normaly we are ref counted. So we must make sure that this
+ // dispatcher isnt killed during the timer runs .-)
+ WriteGuard aWriteLock(m_aLock);
+ m_xSelfHold = css::uno::Reference< css::uno::XInterface >(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY_THROW);
+ aWriteLock.unlock();
+ // <- SAFE
+
+ sal_Int32 nTime = SvtHelpOptions().GetHelpAgentTimeoutPeriod();
+
+ // SOLAR SAFE ->
+ // Timer access needs no "own lock" ! It lives if we live ...
+ // But it requires locking of the solar mutex ... because it's a vcl based timer.
+ {
+ SolarMutexGuard aSolarLock;
+ m_aTimer.SetTimeout(nTime*1000); // sec => ms !
+ m_aTimer.Start();
+ }
+}
+
+//-----------------------------------------------
+IMPL_LINK(HelpAgentDispatcher, implts_timerExpired, void*,)
+{
+ // This method is called by using a pointer to us.
+ // But we must be aware that we can be destroyed hardly
+ // if our uno reference will be gone!
+ // => Hold this object alive till this method finish its work.
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ css::uno::Reference< css::uno::XInterface > xSelfHoldUntilMethodEnds(static_cast< css::frame::XDispatch* >(this), css::uno::UNO_QUERY_THROW);
+ m_xSelfHold.clear();
+ aWriteLock.unlock();
+ // <- SAFE
+
+ implts_hideAgentWindow();
+ implts_ignoreCurrentURL();
+
+ return 0;
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_showAgentWindow()
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::awt::XWindow2 > xContainerWindow(m_xContainerWindow, css::uno::UNO_QUERY_THROW);
+ aReadLock.unlock();
+ // <- SAFE
+
+ css::uno::Reference< css::awt::XWindow > xAgentWindow = implts_ensureAgentWindow();
+
+ if (
+ (xContainerWindow.is() ) &&
+ (xAgentWindow.is() ) &&
+ (xContainerWindow->isVisible())
+ )
+ {
+ // make sure that agent window resists at the right place .-)
+ implts_positionAgentWindow();
+ xAgentWindow->setVisible(sal_True);
+ }
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_hideAgentWindow()
+{
+ css::uno::Reference< css::awt::XWindow > xAgentWindow = implts_ensureAgentWindow();
+ if (xAgentWindow.is())
+ xAgentWindow->setVisible(sal_False);
+}
+
+//--------------------------------------------------------------------
+void HelpAgentDispatcher::implts_positionAgentWindow()
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
+ aReadLock.unlock();
+ // <- SAFE
+
+ css::uno::Reference< css::awt::XWindow > xAgentWindow = implts_ensureAgentWindow();
+ if (
+ (! xContainerWindow.is()) ||
+ (! xAgentWindow.is() )
+ )
+ return;
+
+ ::svt::HelpAgentWindow* pAgentWindow = (::svt::HelpAgentWindow*)VCLUnoHelper::GetWindow(xAgentWindow);
+ const css::awt::Rectangle aContainerSize = xContainerWindow->getPosSize();
+ const Size aAgentSize = pAgentWindow->getPreferredSizePixel();
+
+ sal_Int32 nW = aAgentSize.Width() ;
+ sal_Int32 nH = aAgentSize.Height();
+
+ if (nW < 1)
+ nW = 100;
+ if (nH < 1)
+ nH = 100;
+
+ sal_Int32 nX = aContainerSize.Width - nW;
+ sal_Int32 nY = aContainerSize.Height - nH;
+
+ // TODO: use a surrogate if the container window is too small to contain the full-sized agent window
+ xAgentWindow->setPosSize(nX, nY, nW, nH, css::awt::PosSize::POSSIZE);
+}
+
+//--------------------------------------------------------------------
+css::uno::Reference< css::awt::XWindow > HelpAgentDispatcher::implts_ensureAgentWindow()
+{
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ if (m_xAgentWindow.is())
+ return m_xAgentWindow;
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
+ aReadLock.unlock();
+ // <- SAFE
+
+ if (!xContainerWindow.is())
+ return css::uno::Reference< css::awt::XWindow >();
+
+ ::svt::HelpAgentWindow* pAgentWindow = 0;
+ // SOLAR SAFE ->
+ {
+ SolarMutexGuard aSolarLock;
+ // create the agent window
+ Window* pContainerWindow = VCLUnoHelper::GetWindow(xContainerWindow);
+ pAgentWindow = new ::svt::HelpAgentWindow(pContainerWindow);
+ pAgentWindow->setCallback(this);
+ }
+ // <- SOLAR SAFE
+
+ // SAFE ->
+ WriteGuard aWriteLock(m_aLock);
+ m_xAgentWindow = VCLUnoHelper::GetInterface(pAgentWindow);
+ css::uno::Reference< css::awt::XWindow > xAgentWindow = m_xAgentWindow;
+ aWriteLock.unlock();
+ // <- SAFE
+
+ // add as window listener to the container window so we can maintain the property position of the agent window
+ xContainerWindow->addWindowListener(this);
+
+ // SOLAR SAFE ->
+ {
+ SolarMutexGuard aSolarLock;
+ // establish callback for our internal used timer.
+ // Note: Its only active, if the timer will be started ...
+ m_aTimer.SetTimeoutHdl(LINK(this, HelpAgentDispatcher, implts_timerExpired));
+ }
+ // <- SOLAR SAFE
+
+ return xAgentWindow;
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/interaction.cxx b/framework/source/dispatch/interaction.cxx
new file mode 100644
index 000000000000..5c37ce12d317
--- /dev/null
+++ b/framework/source/dispatch/interaction.cxx
@@ -0,0 +1,212 @@
+/* -*- 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/interaction.hxx>
+#include <general.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//---------------------------------------------------------------------------------------------------------
+// initialize continuation with right start values
+//---------------------------------------------------------------------------------------------------------
+ContinuationFilterSelect::ContinuationFilterSelect()
+ : m_sFilter( ::rtl::OUString() )
+{
+}
+
+//---------------------------------------------------------------------------------------------------------
+// handler should use it after selection to set user specified filter for transport
+//---------------------------------------------------------------------------------------------------------
+void SAL_CALL ContinuationFilterSelect::setFilter( const ::rtl::OUString& sFilter ) throw( css::uno::RuntimeException )
+{
+ m_sFilter = sFilter;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// read access to transported filter
+//---------------------------------------------------------------------------------------------------------
+::rtl::OUString SAL_CALL ContinuationFilterSelect::getFilter() throw( css::uno::RuntimeException )
+{
+ return m_sFilter;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// initialize instance with all neccessary informations
+// We use it without any further checks on our member then ...!
+//---------------------------------------------------------------------------------------------------------
+RequestFilterSelect::RequestFilterSelect( const ::rtl::OUString& sURL )
+{
+ ::rtl::OUString temp;
+ css::uno::Reference< css::uno::XInterface > temp2;
+ css::document::NoSuchFilterRequest aFilterRequest( temp ,
+ temp2 ,
+ sURL );
+ m_aRequest <<= aFilterRequest;
+
+ m_pAbort = new ContinuationAbort ;
+ m_pFilter = new ContinuationFilterSelect;
+
+ m_lContinuations.realloc( 2 );
+ m_lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >( m_pAbort );
+ m_lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >( m_pFilter );
+}
+
+//---------------------------------------------------------------------------------------------------------
+// return abort state of interaction
+// If it is true, return value of method "getFilter()" will be unspecified then!
+//---------------------------------------------------------------------------------------------------------
+sal_Bool RequestFilterSelect::isAbort() const
+{
+ return m_pAbort->isSelected();
+}
+
+//---------------------------------------------------------------------------------------------------------
+// return user selected filter
+// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony!
+//---------------------------------------------------------------------------------------------------------
+::rtl::OUString RequestFilterSelect::getFilter() const
+{
+ return m_pFilter->getFilter();
+}
+
+//---------------------------------------------------------------------------------------------------------
+// handler call it to get type of request
+// Is hard coded to "please select filter" here. see ctor for further informations.
+//---------------------------------------------------------------------------------------------------------
+css::uno::Any SAL_CALL RequestFilterSelect::getRequest() throw( css::uno::RuntimeException )
+{
+ return m_aRequest;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// handler call it to get possible continuations
+// We support "abort/select_filter" only here.
+// After interaction we support read access on these continuations on our c++ interface to
+// return user decision.
+//---------------------------------------------------------------------------------------------------------
+css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > SAL_CALL RequestFilterSelect::getContinuations() throw( css::uno::RuntimeException )
+{
+ return m_lContinuations;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// initialize instance with all neccessary informations
+// We use it without any further checks on our member then ...!
+//---------------------------------------------------------------------------------------------------------
+RequestAmbigousFilter::RequestAmbigousFilter( const ::rtl::OUString& sURL ,
+ const ::rtl::OUString& sSelectedFilter ,
+ const ::rtl::OUString& sDetectedFilter )
+{
+ ::rtl::OUString temp;
+ css::uno::Reference< css::uno::XInterface > temp2;
+ css::document::AmbigousFilterRequest aFilterRequest( temp ,
+ temp2 ,
+ sURL ,
+ sSelectedFilter ,
+ sDetectedFilter );
+ m_aRequest <<= aFilterRequest;
+
+ m_pAbort = new ContinuationAbort ;
+ m_pFilter = new ContinuationFilterSelect;
+
+ m_lContinuations.realloc( 2 );
+ m_lContinuations[0] = css::uno::Reference< css::task::XInteractionContinuation >( m_pAbort );
+ m_lContinuations[1] = css::uno::Reference< css::task::XInteractionContinuation >( m_pFilter );
+}
+
+//---------------------------------------------------------------------------------------------------------
+// return abort state of interaction
+// If it is true, return value of method "getFilter()" will be unspecified then!
+//---------------------------------------------------------------------------------------------------------
+sal_Bool RequestAmbigousFilter::isAbort() const
+{
+ return m_pAbort->isSelected();
+}
+
+//---------------------------------------------------------------------------------------------------------
+// return user selected filter
+// Return value valid for non aborted interaction only. Please check "isAbort()" before you call these ony!
+//---------------------------------------------------------------------------------------------------------
+::rtl::OUString RequestAmbigousFilter::getFilter() const
+{
+ return m_pFilter->getFilter();
+}
+
+//---------------------------------------------------------------------------------------------------------
+// handler call it to get type of request
+// Is hard coded to "please select filter" here. see ctor for further informations.
+//---------------------------------------------------------------------------------------------------------
+css::uno::Any SAL_CALL RequestAmbigousFilter::getRequest() throw( css::uno::RuntimeException )
+{
+ return m_aRequest;
+}
+
+//---------------------------------------------------------------------------------------------------------
+// handler call it to get possible continuations
+// We support "abort/select_filter" only here.
+// After interaction we support read access on these continuations on our c++ interface to
+// return user decision.
+//---------------------------------------------------------------------------------------------------------
+css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > SAL_CALL RequestAmbigousFilter::getContinuations() throw( css::uno::RuntimeException )
+{
+ return m_lContinuations;
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/interceptionhelper.cxx b/framework/source/dispatch/interceptionhelper.cxx
new file mode 100644
index 000000000000..8dc54239ad0e
--- /dev/null
+++ b/framework/source/dispatch/interceptionhelper.cxx
@@ -0,0 +1,343 @@
+/* -*- 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/interceptionhelper.hxx>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/XInterceptorInfo.hpp>
+
+//_______________________________________________
+// includes of other projects
+#include <vcl/svapp.hxx>
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+//_______________________________________________
+// non exported const
+
+sal_Bool InterceptionHelper::m_bPreferrFirstInterceptor = sal_True;
+
+//_______________________________________________
+// non exported definitions
+
+//_______________________________________________
+// declarations
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 09:02
+-----------------------------------------------------------------------------*/
+DEFINE_XINTERFACE_3(InterceptionHelper ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE(css::frame::XDispatchProviderInterception),
+ DIRECT_INTERFACE(css::lang::XEventListener ))
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 09:02
+-----------------------------------------------------------------------------*/
+InterceptionHelper::InterceptionHelper(const css::uno::Reference< css::frame::XFrame >& xOwner,
+ const css::uno::Reference< css::frame::XDispatchProvider >& xSlave)
+ // Init baseclasses first
+ : ThreadHelpBase(&Application::GetSolarMutex())
+ , OWeakObject ( )
+ // Init member
+ , m_xOwnerWeak (xOwner )
+ , m_xSlave (xSlave )
+{
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 09:02
+-----------------------------------------------------------------------------*/
+InterceptionHelper::~InterceptionHelper()
+{
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 09:09
+-----------------------------------------------------------------------------*/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryDispatch(const css::util::URL& aURL ,
+ const ::rtl::OUString& sTargetFrameName,
+ sal_Int32 nSearchFlags )
+ throw(css::uno::RuntimeException)
+{
+ // SAFE {
+ ReadGuard aReadLock(m_aLock);
+
+ // a) first search an interceptor, which match to this URL by it's URL pattern registration
+ // Note: if it return NULL - it does not mean an empty interceptor list automaticly!
+ css::uno::Reference< css::frame::XDispatchProvider > xInterceptor;
+ InterceptorList::const_iterator pIt = m_lInterceptionRegs.findByPattern(aURL.Complete);
+ if (pIt != m_lInterceptionRegs.end())
+ xInterceptor = pIt->xInterceptor;
+
+ // b) No match by registration - but a valid interceptor list.
+ // Use first interceptor everytimes.
+ // Note: it doesn't matter, which direction this helper implementation use to ask interceptor objects.
+ // Using of member m_aInterceptorList will starts at the beginning everytimes.
+ // It depends from the filling operation, in which direction it works realy!
+ if (!xInterceptor.is() && m_lInterceptionRegs.size()>0)
+ {
+ pIt = m_lInterceptionRegs.begin();
+ xInterceptor = pIt->xInterceptor;
+ }
+
+ // c) No registered interceptor => use our direct slave.
+ // This helper exist by design and must be valid everytimes ...
+ // But to be more feature proof - we should check that .-)
+ if (!xInterceptor.is() && m_xSlave.is())
+ xInterceptor = m_xSlave;
+
+ aReadLock.unlock();
+ // } SAFE
+
+ css::uno::Reference< css::frame::XDispatch > xReturn;
+ if (xInterceptor.is())
+ xReturn = xInterceptor->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
+ return xReturn;
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 07:58
+-----------------------------------------------------------------------------*/
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL InterceptionHelper::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
+ throw(css::uno::RuntimeException)
+{
+ sal_Int32 c = lDescriptor.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches (c);
+ css::uno::Reference< css::frame::XDispatch >* pDispatches = lDispatches.getArray();
+ const css::frame::DispatchDescriptor* pDescriptor = lDescriptor.getConstArray();
+
+ for (sal_Int32 i=0; i<c; ++i)
+ pDispatches[i] = queryDispatch(pDescriptor[i].FeatureURL, pDescriptor[i].FrameName, pDescriptor[i].SearchFlags);
+
+ return lDispatches;
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 10:20
+-----------------------------------------------------------------------------*/
+void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw(css::uno::RuntimeException)
+{
+ // reject wrong calling of this interface method
+ css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ if (!xInterceptor.is())
+ throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
+
+ // Fill a new info structure for new interceptor.
+ // Save his reference and try to get an additional URL/pattern list from him.
+ // If no list exist register these interceptor for all dispatch events with "*"!
+ InterceptorInfo aInfo;
+
+ aInfo.xInterceptor = css::uno::Reference< css::frame::XDispatchProvider >(xInterceptor, css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XInterceptorInfo > xInfo(xInterceptor, css::uno::UNO_QUERY);
+ if (xInfo.is())
+ aInfo.lURLPattern = xInfo->getInterceptedURLs();
+ else
+ {
+ aInfo.lURLPattern.realloc(1);
+ aInfo.lURLPattern[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*"));
+ }
+
+ // SAFE {
+ WriteGuard aWriteLock(m_aLock);
+
+ // a) no interceptor at all - set this instance as master for given interceptor
+ // and set our slave as it's slave - and put this interceptor to the list.
+ // It's place there doesn matter. Because this list is currently empty.
+ if (m_lInterceptionRegs.empty())
+ {
+ xInterceptor->setMasterDispatchProvider(xThis );
+ xInterceptor->setSlaveDispatchProvider (m_xSlave);
+ m_lInterceptionRegs.push_back(aInfo);
+ }
+
+ // b) OK - there is at least one interceptor already registered.
+ // It's slave and it's master must be valid references ...
+ // because we created it. But we have to look for the static bool which
+ // regulate direction of using of interceptor objects!
+
+ // b1) If "m_bPreferrFirstInterceptor" is set to true, we have to
+ // insert it behind any other existing interceptor - means at the end of our list.
+ else if (m_bPreferrFirstInterceptor)
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xMasterD = m_lInterceptionRegs.rbegin()->xInterceptor;
+ css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD, css::uno::UNO_QUERY);
+
+ xInterceptor->setMasterDispatchProvider(xMasterD );
+ xInterceptor->setSlaveDispatchProvider (m_xSlave );
+ xMasterI->setSlaveDispatchProvider (aInfo.xInterceptor);
+
+ m_lInterceptionRegs.push_back(aInfo);
+ }
+
+ // b2) If "m_bPreferrFirstInterceptor" is set to false, we have to
+ // insert it before any other existing interceptor - means at the beginning of our list.
+ else
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xSlaveD = m_lInterceptionRegs.begin()->xInterceptor;
+ css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
+
+ xInterceptor->setMasterDispatchProvider(xThis );
+ xInterceptor->setSlaveDispatchProvider (xSlaveD );
+ xSlaveI->setMasterDispatchProvider (aInfo.xInterceptor);
+
+ m_lInterceptionRegs.push_front(aInfo);
+ }
+
+ css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
+
+ aWriteLock.unlock();
+ // } SAFE
+
+ // Don't forget to send a frame action event "context changed".
+ // Any cached dispatch objects must be validated now!
+ if (xOwner.is())
+ xOwner->contextChanged();
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 10:27
+-----------------------------------------------------------------------------*/
+void SAL_CALL InterceptionHelper::releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
+ throw(css::uno::RuntimeException)
+{
+ // reject wrong calling of this interface method
+ css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ if (!xInterceptor.is())
+ throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
+
+ // SAFE {
+ WriteGuard aWriteLock(m_aLock);
+
+ // search this interceptor ...
+ // If it could be located inside cache -
+ // use it's slave/master relations to update the interception list;
+ // set empty references for it as new master and slave;
+ // and relase it from out cache.
+ InterceptorList::iterator pIt = m_lInterceptionRegs.findByReference(xInterceptor);
+ if (pIt != m_lInterceptionRegs.end())
+ {
+ css::uno::Reference< css::frame::XDispatchProvider > xSlaveD (xInterceptor->getSlaveDispatchProvider() , css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchProvider > xMasterD (xInterceptor->getMasterDispatchProvider(), css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD , css::uno::UNO_QUERY);
+
+ if (xMasterI.is())
+ xMasterI->setSlaveDispatchProvider(xSlaveD);
+
+ if (xSlaveI.is())
+ xSlaveI->setMasterDispatchProvider(xMasterD);
+
+ xInterceptor->setSlaveDispatchProvider (css::uno::Reference< css::frame::XDispatchProvider >());
+ xInterceptor->setMasterDispatchProvider(css::uno::Reference< css::frame::XDispatchProvider >());
+
+ m_lInterceptionRegs.erase(pIt);
+ }
+
+ css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
+
+ aWriteLock.unlock();
+ // } SAFE
+
+ // Don't forget to send a frame action event "context changed".
+ // Any cached dispatch objects must be validated now!
+ if (xOwner.is())
+ xOwner->contextChanged();
+}
+
+/*-----------------------------------------------------------------------------
+ 31.03.2003 10:31
+-----------------------------------------------------------------------------*/
+#define FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
+void SAL_CALL InterceptionHelper::disposing(const css::lang::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ #ifdef FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+
+ // check calli ... we accept such disposing call's only from our onwer frame.
+ css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
+ if (aEvent.Source != xOwner)
+ return;
+
+ // Because every interceptor hold at least one reference to us ... and we destruct this list
+ // of interception objects ... we should hold ourself alive .-)
+ css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW);
+
+ // We need a full copy of all currently registered interceptor objects.
+ // Otherwhise we cant iterate over this vector without the risk, that our iterator will be invalid.
+ // Because this vetor will be influenced by every deregistered interceptor.
+ InterceptionHelper::InterceptorList aCopy = m_lInterceptionRegs;
+
+ aReadLock.unlock();
+ // <- SAFE
+
+ InterceptionHelper::InterceptorList::iterator pIt;
+ for ( pIt = aCopy.begin();
+ pIt != aCopy.end() ;
+ ++pIt )
+ {
+ InterceptionHelper::InterceptorInfo& rInfo = *pIt;
+ if (rInfo.xInterceptor.is())
+ {
+ css::uno::Reference< css::frame::XDispatchProviderInterceptor > xInterceptor(rInfo.xInterceptor, css::uno::UNO_QUERY_THROW);
+ releaseDispatchProviderInterceptor(xInterceptor);
+ rInfo.xInterceptor.clear();
+ }
+ }
+
+ aCopy.clear();
+
+ #if OSL_DEBUG_LEVEL > 0
+ // SAFE ->
+ aReadLock.lock();
+ if (!m_lInterceptionRegs.empty() )
+ OSL_ENSURE(sal_False, "There are some pending interceptor objects, which seams to be registered during (!) the destruction of a frame.");
+ aReadLock.unlock();
+ // <- SAFE
+ #endif // ODL_DEBUG_LEVEL>0
+
+ #endif // FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/loaddispatcher.cxx b/framework/source/dispatch/loaddispatcher.cxx
new file mode 100644
index 000000000000..31accd649aa7
--- /dev/null
+++ b/framework/source/dispatch/loaddispatcher.cxx
@@ -0,0 +1,201 @@
+/* -*- 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/loaddispatcher.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/DispatchResultState.hpp>
+
+//_______________________________________________
+// includes of other projects
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+namespace css = ::com::sun::star;
+
+//_______________________________________________
+// declarations
+
+/*-----------------------------------------------
+ 20.08.2003 09:52
+-----------------------------------------------*/
+LoadDispatcher::LoadDispatcher(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xOwnerFrame ,
+ const ::rtl::OUString sTargetName ,
+ sal_Int32 nSearchFlags)
+ : ThreadHelpBase( )
+ , m_xSMGR (xSMGR )
+ , m_xOwnerFrame (xOwnerFrame )
+ , m_sTarget (sTargetName )
+ , m_nSearchFlags(nSearchFlags)
+ , m_aLoader (xSMGR )
+{
+}
+
+/*-----------------------------------------------
+ 20.08.2003 09:12
+-----------------------------------------------*/
+LoadDispatcher::~LoadDispatcher()
+{
+ m_xSMGR.clear();
+}
+
+/*-----------------------------------------------
+ 20.08.2003 09:58
+-----------------------------------------------*/
+void SAL_CALL LoadDispatcher::dispatchWithNotification(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
+ throw(css::uno::RuntimeException)
+{
+ impl_dispatch( aURL, lArguments, xListener );
+}
+
+/*-----------------------------------------------
+ 20.08.2003 09:16
+-----------------------------------------------*/
+void SAL_CALL LoadDispatcher::dispatch(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
+ throw(css::uno::RuntimeException)
+{
+ impl_dispatch( aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >() );
+}
+
+/*-----------------------------------------------
+ 14.04.2008
+-----------------------------------------------*/
+css::uno::Any SAL_CALL LoadDispatcher::dispatchWithReturnValue( const css::util::URL& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
+ throw( css::uno::RuntimeException )
+{
+ return impl_dispatch( rURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
+}
+
+/*-----------------------------------------------
+ 20.08.2003 10:48
+-----------------------------------------------*/
+void SAL_CALL LoadDispatcher::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+/*-----------------------------------------------
+ 20.08.2003 10:49
+-----------------------------------------------*/
+void SAL_CALL LoadDispatcher::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+/*-----------------------------------------------
+ 20.08.2003 09:58
+-----------------------------------------------*/
+css::uno::Any LoadDispatcher::impl_dispatch( const css::util::URL& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
+{
+ // Attention: May be nobody outside hold such temp. dispatch object alive (because
+ // the container in which we resists isnt implemented threadsafe but updated by a timer
+ // and clear our reference ...) we should hold us self alive!
+ css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::frame::XNotifyingDispatch* >(this), css::uno::UNO_QUERY);
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+
+ // We are the only client of this load env object ... but
+ // may a dispatch request before is still in progress (?!).
+ // Then we should wait a little bit and block this new request.
+ // In case we run into the timeout, we should reject this new request
+ // and return "FAILED" as result. Otherwhise we can start this new operation.
+ if (!m_aLoader.waitWhileLoading(2000)) // => 2 sec.
+ {
+ if (xListener.is())
+ xListener->dispatchFinished(
+ css::frame::DispatchResultEvent(xThis, css::frame::DispatchResultState::DONTKNOW, css::uno::Any())); // DONTKNOW? ... not realy started ... not realy failed :-)
+ }
+
+ css::uno::Reference< css::frame::XFrame > xBaseFrame(m_xOwnerFrame.get(), css::uno::UNO_QUERY);
+ if (!xBaseFrame.is())
+ {
+ if (xListener.is())
+ xListener->dispatchFinished(
+ css::frame::DispatchResultEvent(xThis, css::frame::DispatchResultState::FAILURE, css::uno::Any()));
+ }
+
+ // OK ... now the internal loader seems to be useable for new requests
+ // and our owner frame seems to be valid for such operations.
+ // Initialize it with all new but needed properties and start the loading.
+ css::uno::Reference< css::lang::XComponent > xComponent;
+ try
+ {
+ m_aLoader.initializeLoading( rURL.Complete, lArguments, xBaseFrame, m_sTarget, m_nSearchFlags, (LoadEnv::EFeature)(LoadEnv::E_ALLOW_CONTENTHANDLER | LoadEnv::E_WORK_WITH_UI));
+ m_aLoader.startLoading();
+ m_aLoader.waitWhileLoading(); // wait for ever!
+ xComponent = m_aLoader.getTargetComponent();
+
+ // TODO thinking about asynchronous operations and listener support
+ }
+ catch(const LoadEnvException&)
+ { xComponent.clear(); }
+
+ if (xListener.is())
+ {
+ if (xComponent.is())
+ xListener->dispatchFinished(
+ css::frame::DispatchResultEvent(xThis, css::frame::DispatchResultState::SUCCESS, css::uno::Any()));
+ else
+ xListener->dispatchFinished(
+ css::frame::DispatchResultEvent(xThis, css::frame::DispatchResultState::FAILURE, css::uno::Any()));
+ }
+
+ // return the model - like loadComponentFromURL()
+ css::uno::Any aRet;
+ if ( xComponent.is () )
+ aRet = css::uno::makeAny( xComponent );
+
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+ return aRet;
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/mailtodispatcher.cxx b/framework/source/dispatch/mailtodispatcher.cxx
new file mode 100644
index 000000000000..3c505540ae33
--- /dev/null
+++ b/framework/source/dispatch/mailtodispatcher.cxx
@@ -0,0 +1,333 @@
+/* -*- 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/mailtodispatcher.hxx>
+#include <threadhelp/readguard.hxx>
+#include <general.h>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/system/XSystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <vcl/svapp.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+#define PROTOCOL_VALUE "mailto:"
+#define PROTOCOL_LENGTH 7
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XINTERFACE_5(MailToDispatcher ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
+ DIRECT_INTERFACE(css::frame::XDispatch ))
+
+DEFINE_XTYPEPROVIDER_5(MailToDispatcher ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDispatchProvider ,
+ css::frame::XNotifyingDispatch,
+ css::frame::XDispatch )
+
+DEFINE_XSERVICEINFO_MULTISERVICE(MailToDispatcher ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_PROTOCOLHANDLER ,
+ IMPLEMENTATIONNAME_MAILTODISPATCHER)
+
+DEFINE_INIT_SERVICE(MailToDispatcher,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ }
+ )
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short standard ctor
+ @descr These initialize a new instance of ths class with needed informations for work.
+
+ @param xFactory
+ reference to uno servicemanager for creation of new services
+
+ @modified 30.04.2002 14:10, as96863
+*/
+MailToDispatcher::MailToDispatcher( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ : ThreadHelpBase( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+{
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short standard dtor
+ @descr -
+
+ @modified 30.04.2002 14:10, as96863
+*/
+MailToDispatcher::~MailToDispatcher()
+{
+ m_xFactory = NULL;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short decide if this dispatch implementation can be used for requested URL or not
+ @descr A protocol handler is registerd for an URL pattern inside configuration and will
+ be asked by the generic dispatch mechanism inside framework, if he can handle this
+ special URL wich match his registration. He can agree by returning of a valid dispatch
+ instance or disagree by returning <NULL/>.
+ We don't create new dispatch instances here realy - we return THIS as result to handle it
+ at the same implementation.
+
+ @modified 02.05.2002 15:25, as96863
+*/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL MailToDispatcher::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& /*sTarget*/ ,
+ sal_Int32 /*nFlags*/ ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+ if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
+ xDispatcher = this;
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short do the same like dispatch() but for multiple requests at the same time
+ @descr -
+
+ @modified 02.05.2002 15:27, as96863
+*/
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL MailToDispatcher::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
+{
+ sal_Int32 nCount = lDescriptor.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ lDispatcher[i] = this->queryDispatch(
+ lDescriptor[i].FeatureURL,
+ lDescriptor[i].FrameName,
+ lDescriptor[i].SearchFlags);
+ }
+ return lDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short dispatch URL with arguments
+ @descr We use threadsafe internal method to do so. It returns a state value - but we ignore it.
+ Because we doesn't support status listener notifications here. Status events are not guaranteed -
+ and we call another service internaly which doesn't return any notifications too.
+
+ @param aURL
+ mail URL which should be executed
+ @param lArguments
+ list of optional arguments for this mail request
+
+ @modified 30.04.2002 14:15, as96863
+*/
+void SAL_CALL MailToDispatcher::dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
+{
+ // dispatch() is an [oneway] call ... and may our user release his reference to us immediatly.
+ // So we should hold us self alive till this call ends.
+ css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ implts_dispatch(aURL,lArguments);
+ // No notification for status listener!
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short dispatch with guaranteed notifications about success
+ @descr We use threadsafe internal method to do so. Return state of this function will be used
+ for notification if an optional listener is given.
+
+ @param aURL
+ mail URL which should be executed
+ @param lArguments
+ list of optional arguments for this mail request
+ @param xListener
+ reference to a valid listener for state events
+
+ @modified 30.04.2002 14:49, as96863
+*/
+void SAL_CALL MailToDispatcher::dispatchWithNotification( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ // This class was designed to die by reference. And if user release his reference to us immediatly after calling this method
+ // we can run into some problems. So we hold us self alive till this method ends.
+ // Another reason: We can use this reference as source of sending event at the end too.
+ css::uno::Reference< css::frame::XNotifyingDispatch > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+
+ sal_Bool bState = implts_dispatch(aURL,lArguments);
+ if (xListener.is())
+ {
+ css::frame::DispatchResultEvent aEvent;
+ if (bState)
+ aEvent.State = css::frame::DispatchResultState::SUCCESS;
+ else
+ aEvent.State = css::frame::DispatchResultState::FAILURE;
+ aEvent.Source = xThis;
+
+ xListener->dispatchFinished( aEvent );
+ }
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short threadsafe helper for dispatch calls
+ @descr We support two interfaces for the same process - dispatch URLs. That the reason for this internal
+ function. It implements the real dispatch operation and returns a state value which inform caller
+ about success. He can notify listener then by using this return value.
+
+ @param aURL
+ mail URL which should be executed
+ @param lArguments
+ list of optional arguments for this mail request
+
+ @return <TRUE/> if dispatch could be started successfully
+ Note: Our internal used shell executor doesn't return any state value - so we must
+ belive that call was successfully.
+ <FALSE/> if neccessary ressource couldn't be created or an exception was thrown.
+
+ @modified 30.04.2002 14:49, as96863
+*/
+sal_Bool MailToDispatcher::implts_dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ ) throw( css::uno::RuntimeException )
+{
+ sal_Bool bSuccess = sal_False;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory;
+ /* SAFE */{
+ ReadGuard aReadLock( m_aLock );
+ xFactory = m_xFactory;
+ /* SAFE */}
+
+ css::uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute( xFactory->createInstance(SERVICENAME_SYSTEMSHELLEXECUTE), css::uno::UNO_QUERY );
+ if (xSystemShellExecute.is())
+ {
+ try
+ {
+ // start mail client
+ // Because there is no notofocation about success - we use case of
+ // no detected exception as SUCCESS - FAILED otherwhise.
+ xSystemShellExecute->execute( aURL.Complete, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS );
+ bSuccess = sal_True;
+ }
+ catch (css::lang::IllegalArgumentException&)
+ {
+ }
+ catch (css::system::SystemShellExecuteException&)
+ {
+ }
+ }
+
+ return bSuccess;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short add/remove listener for state events
+ @descr Because we use an external process to forward such mail URLs, and this process doesn't
+ return any notifications about success or failed state - we doesn't support such status
+ listener. We have no status to send.
+
+ @param xListener
+ reference to a valid listener for state events
+ @param aURL
+ URL about listener will be informed, if something occurred
+
+ @modified 30.04.2002 14:49, as96863
+*/
+void SAL_CALL MailToDispatcher::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
+ const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL MailToDispatcher::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
+ const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/makefile.mk b/framework/source/dispatch/makefile.mk
new file mode 100644
index 000000000000..b969d71ea9fc
--- /dev/null
+++ b/framework/source/dispatch/makefile.mk
@@ -0,0 +1,63 @@
+#*************************************************************************
+#
+# 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.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME= framework
+TARGET= fwk_dispatch
+USE_DEFFILE= TRUE
+ENABLE_EXCEPTIONS= TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- defines ------------------------------------------------------
+
+CDEFS+=-DCOMPMOD_NAMESPACE=framework
+
+# --- Generate -----------------------------------------------------
+
+SLOFILES=\
+ $(SLO)$/closedispatcher.obj \
+ $(SLO)$/dispatchinformationprovider.obj \
+ $(SLO)$/dispatchprovider.obj \
+ $(SLO)$/helpagentdispatcher.obj \
+ $(SLO)$/interaction.obj \
+ $(SLO)$/interceptionhelper.obj \
+ $(SLO)$/loaddispatcher.obj \
+ $(SLO)$/mailtodispatcher.obj \
+ $(SLO)$/menudispatcher.obj \
+ $(SLO)$/oxt_handler.obj \
+ $(SLO)$/popupmenudispatcher.obj \
+ $(SLO)$/servicehandler.obj \
+ $(SLO)$/systemexec.obj \
+ $(SLO)$/windowcommanddispatch.obj \
+ $(SLO)$/startmoduledispatcher.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
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: */
diff --git a/framework/source/dispatch/oxt_handler.cxx b/framework/source/dispatch/oxt_handler.cxx
new file mode 100644
index 000000000000..695fea4b3d81
--- /dev/null
+++ b/framework/source/dispatch/oxt_handler.cxx
@@ -0,0 +1,283 @@
+/* -*- 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/oxt_handler.hxx>
+
+#include <threadhelp/transactionguard.hxx>
+
+#include <threadhelp/writeguard.hxx>
+
+#include <threadhelp/readguard.hxx>
+
+#include <macros/debug.hxx>
+
+#include <services.h>
+
+#include <comphelper/mediadescriptor.hxx>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// XInterface, XTypeProvider, XServiceInfo
+//*****************************************************************************************************************
+DEFINE_XINTERFACE_5 ( Oxt_Handler ,
+ OWeakObject ,
+ DIRECT_INTERFACE( css::lang::XTypeProvider ),
+ DIRECT_INTERFACE( css::lang::XServiceInfo ),
+ DIRECT_INTERFACE( css::frame::XNotifyingDispatch ),
+ DIRECT_INTERFACE( css::frame::XDispatch ),
+ DIRECT_INTERFACE( css::document::XExtendedFilterDetection )
+ )
+
+DEFINE_XTYPEPROVIDER_5 ( Oxt_Handler ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XNotifyingDispatch ,
+ css::frame::XDispatch ,
+ css::document::XExtendedFilterDetection
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE ( Oxt_Handler ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_CONTENTHANDLER ,
+ IMPLEMENTATIONNAME_OXT_HANDLER
+ )
+
+DEFINE_INIT_SERVICE ( Oxt_Handler,
+ {
+ }
+ )
+
+/*-************************************************************************************************************//**
+ @short standard ctor
+ @descr These initialize a new instance of this class with needed informations for work.
+
+ @seealso using at owner
+
+ @param "xFactory", reference to service manager for creation of new services
+ @return -
+
+ @onerror Show an assertion and do nothing else.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+Oxt_Handler::Oxt_Handler( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ : ThreadHelpBase ( )
+ , ::cppu::OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+{
+}
+
+/*-************************************************************************************************************//**
+ @short standard dtor
+ @descr -
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+ @threadsafe -
+*//*-*************************************************************************************************************/
+Oxt_Handler::~Oxt_Handler()
+{
+ if ( m_xListener.is() )
+ {
+ css::frame::DispatchResultEvent aEvent;
+ aEvent.State = css::frame::DispatchResultState::FAILURE;
+ m_xListener->dispatchFinished( aEvent );
+ m_xListener = css::uno::Reference< css::frame::XDispatchResultListener >();
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface ::com::sun::star::frame::XDispatch
+
+ @short try to load audio file
+ @descr This method try to load given audio file by URL and play it. We use vcl/Sound class to do that.
+ Playing of sound is asynchron everytime.
+
+ @attention We must hold us alive by ourself ... because we use async. vcl sound player ... but playing is started
+ in async interface call "dispatch()" too. And caller forget us imediatly. But then our uno ref count
+ will decreased to 0 and will die. The only solution is to use own reference to our implementation.
+ But we do it for realy started jobs only and release it during call back of vcl.
+
+ @seealso class vcl/Sound
+ @seealso method implts_PlayerNotify()
+
+ @param "aURL" , URL to dispatch.
+ @param "lArguments", list of optional arguments.
+ @return -
+
+ @onerror We do nothing.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+void SAL_CALL Oxt_Handler::dispatchWithNotification( const css::util::URL& aURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
+ throw( css::uno::RuntimeException )
+{
+ // SAFE {
+ ResetableGuard aLock( m_aLock );
+
+ rtl::OUString sServiceName = UNISTRING( "com.sun.star.deployment.ui.PackageManagerDialog" );
+ css::uno::Sequence< css::uno::Any > lParams(1);
+ lParams[0] <<= aURL.Main;
+
+ css::uno::Reference< css::uno::XInterface > xService;
+
+ xService = m_xFactory->createInstanceWithArguments( sServiceName, lParams );
+ css::uno::Reference< css::task::XJobExecutor > xExecuteable( xService, css::uno::UNO_QUERY );
+ if ( xExecuteable.is() )
+ xExecuteable->trigger( rtl::OUString() );
+
+ if ( xListener.is() )
+ {
+ css::frame::DispatchResultEvent aEvent;
+ aEvent.State = css::frame::DispatchResultState::SUCCESS;
+ xListener->dispatchFinished( aEvent );
+ }
+
+/*
+ // Try to initialize player.
+ m_xListener = xListener;
+ if (m_aPlayer.SetSoundName(aURL.Complete))
+ {
+ // OK- we can start async playing ...
+ // Count this request and initialize self-holder against dieing by uno ref count ...
+ m_xSelfHold = css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ m_aPlayer.Play();
+ }
+*/
+ // } SAFE
+ aLock.unlock();
+}
+
+void SAL_CALL Oxt_Handler::dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
+ throw( css::uno::RuntimeException )
+{
+ dispatchWithNotification( aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >() );
+}
+
+/*-************************************************************************************************************//**
+ @interface ::com::sun::star::document::XExtendedFilterDetection
+
+ @short try to detect file (given as argument included in "lDescriptor")
+ @descr We try to detect, if given file could be handled by this class and is a well known one.
+ If it is - we return right internal type name - otherwise we return nothing!
+ So call can search for another detect service and ask him too.
+
+ @attention a) We don't need any mutex here ... because we don't use any member!
+ b) Dont' use internal player instance "m_pPlayer" to detect given sound file!
+ It's not neccessary to do that ... and we can use temp. variable to do the same.
+ This way is easy - we don't must synchronize it with currently played sounds!
+ Another reason to do so ... We are a listener on our internal ma_Player object.
+ If you would call "IsSoundFile()" on this instance, he would call us back and
+ we make some uneccssary things ...
+
+ @seealso -
+
+ @param "lDescriptor", description of file to detect
+ @return Internal type name which match this file ... or nothing if it is unknown.
+
+ @onerror We return nothing.
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+::rtl::OUString SAL_CALL Oxt_Handler::detect( css::uno::Sequence< css::beans::PropertyValue >& lDescriptor )
+ throw( css::uno::RuntimeException )
+{
+ // Our default is "nothing". So we can return it, if detection failed or fily type is realy unknown.
+ ::rtl::OUString sTypeName;
+
+ // Analyze given descriptor to find filename or input stream or ...
+ ::comphelper::MediaDescriptor aDescriptor( lDescriptor );
+ ::rtl::OUString sURL = aDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString() );
+
+ long nLength = sURL.getLength();
+ if ( ( nLength > 4 ) && sURL.matchIgnoreAsciiCase( UNISTRING(".oxt"), nLength-4 ) )
+ {
+ // "IsSoundFile" idffer between different "wav" and "au" file versions ...
+ // couldn't return this information ... because: He use the OS to detect it!
+ // I think we can the following ones:
+ // a) look for given extension of url to map our type decision HARD CODED!!!
+ // b) return preferred type every time... it's easy :-)
+ sTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("oxt_OpenOffice_Extension"));
+ aDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sTypeName;
+ aDescriptor >> lDescriptor;
+ }
+
+ // Return our decision.
+ return sTypeName;
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/popupmenudispatcher.cxx b/framework/source/dispatch/popupmenudispatcher.cxx
new file mode 100644
index 000000000000..96c57d78c3fe
--- /dev/null
+++ b/framework/source/dispatch/popupmenudispatcher.cxx
@@ -0,0 +1,422 @@
+/* -*- 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
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+
+#include <dispatch/popupmenudispatcher.hxx>
+#include <general.h>
+#include <xml/menuconfiguration.hxx>
+#include <classes/addonmenu.hxx>
+#include <services.h>
+#include <properties.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>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <ucbhelper/content.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.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 namespace ::osl ;
+using namespace ::rtl ;
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+const char* PROTOCOL_VALUE = "vnd.sun.star.popup:";
+const sal_Int32 PROTOCOL_LENGTH = 19;
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//*****************************************************************************************************************
+// constructor
+//*****************************************************************************************************************
+PopupMenuDispatcher::PopupMenuDispatcher(
+ const uno::Reference< XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ : ThreadHelpBase ( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+ , m_aListenerContainer ( m_aLock.getShareableOslMutex() )
+ , m_bAlreadyDisposed ( sal_False )
+ , m_bActivateListener ( sal_False )
+{
+}
+
+//*****************************************************************************************************************
+// destructor
+//*****************************************************************************************************************
+PopupMenuDispatcher::~PopupMenuDispatcher()
+{
+ // 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_7 ( PopupMenuDispatcher ,
+ ::cppu::OWeakObject ,
+ DIRECT_INTERFACE( XTypeProvider ),
+ DIRECT_INTERFACE( XServiceInfo ),
+ DIRECT_INTERFACE( XDispatchProvider ),
+ DIRECT_INTERFACE( XDispatch ),
+ DIRECT_INTERFACE( XEventListener ),
+ DIRECT_INTERFACE( XInitialization ),
+ DERIVED_INTERFACE( XFrameActionListener, XEventListener )
+ )
+
+DEFINE_XTYPEPROVIDER_7 ( PopupMenuDispatcher ,
+ XTypeProvider ,
+ XServiceInfo ,
+ XDispatchProvider ,
+ XDispatch ,
+ XEventListener ,
+ XInitialization ,
+ XFrameActionListener
+ )
+
+DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_PROTOCOLHANDLER ,
+ IMPLEMENTATIONNAME_POPUPMENUDISPATCHER )
+
+DEFINE_INIT_SERVICE(PopupMenuDispatcher,
+{
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+}
+)
+
+//*****************************************************************************************************************
+// XInitialization
+//*****************************************************************************************************************
+void SAL_CALL PopupMenuDispatcher::initialize(
+ const css::uno::Sequence< css::uno::Any >& lArguments )
+throw( css::uno::Exception, css::uno::RuntimeException)
+{
+ css::uno::Reference< css::frame::XFrame > xFrame;
+
+ /* SAFE { */
+ WriteGuard aWriteLock(m_aLock);
+
+ for (int a=0; a<lArguments.getLength(); ++a)
+ {
+ if (a==0)
+ {
+ lArguments[a] >>= xFrame;
+ m_xWeakFrame = xFrame;
+
+ m_bActivateListener = sal_True;
+ uno::Reference< css::frame::XFrameActionListener > xFrameActionListener(
+ (OWeakObject *)this, css::uno::UNO_QUERY );
+ xFrame->addFrameActionListener( xFrameActionListener );
+ }
+ }
+
+ aWriteLock.unlock();
+ /* } SAFE */
+}
+
+//*****************************************************************************************************************
+// XDispatchProvider
+//*****************************************************************************************************************
+css::uno::Reference< css::frame::XDispatch >
+SAL_CALL PopupMenuDispatcher::queryDispatch(
+ const css::util::URL& rURL ,
+ const ::rtl::OUString& sTarget ,
+ sal_Int32 nFlags )
+throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatch;
+
+ if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 )
+ {
+ // --- SAFE ---
+ ResetableGuard aGuard( m_aLock );
+ impl_RetrievePopupControllerQuery();
+ impl_CreateUriRefFactory();
+
+ css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
+ css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory );
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( xPopupCtrlQuery.is() )
+ {
+ try
+ {
+ // Just use the main part of the URL for popup menu controllers
+ sal_Int32 nQueryPart( 0 );
+ sal_Int32 nSchemePart( 0 );
+ rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
+ rtl::OUString aURL( rURL.Complete );
+
+ nSchemePart = aURL.indexOf( ':' );
+ if (( nSchemePart > 0 ) &&
+ ( aURL.getLength() > ( nSchemePart+1 )))
+ {
+ nQueryPart = aURL.indexOf( '?', nSchemePart );
+ if ( nQueryPart > 0 )
+ aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) );
+ else if ( nQueryPart == -1 )
+ aBaseURL += aURL.copy( nSchemePart+1 );
+ }
+
+ css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;
+
+ // Find popup menu controller using the base URL
+ xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider;
+ aGuard.unlock();
+
+ // Ask popup menu dispatch provider for dispatch object
+ if ( xDispatchProvider.is() )
+ xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
+ }
+ catch ( RuntimeException& )
+ {
+ throw;
+ }
+ catch ( Exception& )
+ {
+ }
+ }
+ }
+ return xDispatch;
+}
+
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
+PopupMenuDispatcher::queryDispatches(
+ const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
+throw( css::uno::RuntimeException )
+{
+ sal_Int32 nCount = lDescriptor.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ lDispatcher[i] = this->queryDispatch(
+ lDescriptor[i].FeatureURL,
+ lDescriptor[i].FrameName,
+ lDescriptor[i].SearchFlags);
+ }
+ return lDispatcher;
+}
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void
+SAL_CALL PopupMenuDispatcher::dispatch(
+ const URL& /*aURL*/ ,
+ const Sequence< PropertyValue >& /*seqProperties*/ )
+throw( RuntimeException )
+{
+}
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void
+SAL_CALL PopupMenuDispatcher::addStatusListener(
+ const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL )
+throw( RuntimeException )
+{
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+ // Safe impossible cases
+ // Add listener to container.
+ m_aListenerContainer.addInterface( aURL.Complete, xControl );
+}
+
+//*****************************************************************************************************************
+// XDispatch
+//*****************************************************************************************************************
+void
+SAL_CALL PopupMenuDispatcher::removeStatusListener(
+ const uno::Reference< XStatusListener >& xControl,
+ const URL& aURL )
+throw( RuntimeException )
+{
+ // Ready for multithreading
+ ResetableGuard aGuard( m_aLock );
+ // Safe impossible cases
+ // Add listener to container.
+ m_aListenerContainer.removeInterface( aURL.Complete, xControl );
+}
+
+//*****************************************************************************************************************
+// XFrameActionListener
+//*****************************************************************************************************************
+
+void
+SAL_CALL PopupMenuDispatcher::frameAction(
+ const FrameActionEvent& aEvent )
+throw ( RuntimeException )
+{
+ ResetableGuard aGuard( m_aLock );
+
+ if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
+ ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ))
+ {
+ // Reset query reference to requery it again next time
+ m_xPopupCtrlQuery.clear();
+ }
+}
+
+//*****************************************************************************************************************
+// XEventListener
+//*****************************************************************************************************************
+void
+SAL_CALL PopupMenuDispatcher::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_xWeakFrame.get(), UNO_QUERY );
+ if ( xFrame.is() )
+ {
+ xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
+ m_bActivateListener = sal_False;
+ }
+ }
+
+ // Forget our factory.
+ m_xFactory = uno::Reference< XMultiServiceFactory >();
+ }
+}
+
+void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
+{
+ if ( !m_xPopupCtrlQuery.is() )
+ {
+ css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );
+
+ if ( xFrame.is() )
+ {
+ css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ try
+ {
+ xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager;
+
+ if ( xLayoutManager.is() )
+ {
+ css::uno::Reference< css::ui::XUIElement > xMenuBar;
+ rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
+ xMenuBar = xLayoutManager->getElement( aMenuBar );
+
+ m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >(
+ xMenuBar, css::uno::UNO_QUERY );
+ }
+ }
+ catch ( css::uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch ( css::uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+}
+
+void PopupMenuDispatcher::impl_CreateUriRefFactory()
+{
+ if ( !m_xUriRefFactory.is() )
+ {
+ rtl::OUString aUriRefFactoryService(
+ RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));
+
+ m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >(
+ m_xFactory->createInstance( aUriRefFactoryService ),
+ css::uno::UNO_QUERY);
+
+ }
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/servicehandler.cxx b/framework/source/dispatch/servicehandler.cxx
new file mode 100644
index 000000000000..6f019f247775
--- /dev/null
+++ b/framework/source/dispatch/servicehandler.cxx
@@ -0,0 +1,354 @@
+/* -*- 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/servicehandler.hxx>
+#include <threadhelp/readguard.hxx>
+#include <general.h>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <vcl/svapp.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+#define PROTOCOL_VALUE "service:"
+#define PROTOCOL_LENGTH 8
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XINTERFACE_5(ServiceHandler ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
+ DIRECT_INTERFACE(css::frame::XDispatch ))
+
+DEFINE_XTYPEPROVIDER_5(ServiceHandler ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDispatchProvider ,
+ css::frame::XNotifyingDispatch,
+ css::frame::XDispatch )
+
+DEFINE_XSERVICEINFO_MULTISERVICE(ServiceHandler ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_PROTOCOLHANDLER ,
+ IMPLEMENTATIONNAME_SERVICEHANDLER)
+
+DEFINE_INIT_SERVICE(ServiceHandler,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ }
+ )
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short standard ctor
+ @descr These initialize a new instance of ths class with needed informations for work.
+
+ @param xFactory
+ reference to uno servicemanager for creation of new services
+
+ @modified 02.05.2002 08:16, as96863
+*/
+ServiceHandler::ServiceHandler( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ : ThreadHelpBase( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+{
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short standard dtor
+ @descr -
+
+ @modified 02.05.2002 08:16, as96863
+*/
+ServiceHandler::~ServiceHandler()
+{
+ m_xFactory = NULL;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short decide if this dispatch implementation can be used for requested URL or not
+ @descr A protocol handler is registerd for an URL pattern inside configuration and will
+ be asked by the generic dispatch mechanism inside framework, if he can handle this
+ special URL wich match his registration. He can agree by returning of a valid dispatch
+ instance or disagree by returning <NULL/>.
+ We don't create new dispatch instances here realy - we return THIS as result to handle it
+ at the same implementation.
+
+ @modified 02.05.2002 15:25, as96863
+*/
+css::uno::Reference< css::frame::XDispatch > SAL_CALL ServiceHandler::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString& /*sTarget*/ ,
+ sal_Int32 /*nFlags*/ ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+ if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
+ xDispatcher = this;
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short do the same like dispatch() but for multiple requests at the same time
+ @descr -
+
+ @modified 02.05.2002 15:27, as96863
+*/
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL ServiceHandler::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
+{
+ sal_Int32 nCount = lDescriptor.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ lDispatcher[i] = this->queryDispatch(
+ lDescriptor[i].FeatureURL,
+ lDescriptor[i].FrameName,
+ lDescriptor[i].SearchFlags);
+ }
+ return lDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short dispatch URL with arguments
+ @descr We use threadsafe internal method to do so. It returns a state value - but we ignore it.
+ Because we doesn't support status listener notifications here.
+
+ @param aURL
+ uno URL which should be executed
+ @param lArguments
+ list of optional arguments for this request
+
+ @modified 02.05.2002 08:19, as96863
+*/
+void SAL_CALL ServiceHandler::dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
+{
+ // dispatch() is an [oneway] call ... and may our user release his reference to us immediatly.
+ // So we should hold us self alive till this call ends.
+ css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ implts_dispatch(aURL,lArguments);
+ // No notification for status listener!
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short dispatch with guaranteed notifications about success
+ @descr We use threadsafe internal method to do so. Return state of this function will be used
+ for notification if an optional listener is given.
+
+ @param aURL
+ uno URL which should be executed
+ @param lArguments
+ list of optional arguments for this request
+ @param xListener
+ optional listener for state events
+
+ @modified 30.04.2002 14:49, as96863
+*/
+void SAL_CALL ServiceHandler::dispatchWithNotification( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ // This class was designed to die by reference. And if user release his reference to us immediatly after calling this method
+ // we can run into some problems. So we hold us self alive till this method ends.
+ // Another reason: We can use this reference as source of sending event at the end too.
+ css::uno::Reference< css::frame::XNotifyingDispatch > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+
+ css::uno::Reference< css::uno::XInterface > xService = implts_dispatch(aURL,lArguments);
+ if (xListener.is())
+ {
+ css::frame::DispatchResultEvent aEvent;
+ if (xService.is())
+ aEvent.State = css::frame::DispatchResultState::SUCCESS;
+ else
+ aEvent.State = css::frame::DispatchResultState::FAILURE;
+ aEvent.Result <<= xService; // may NULL for state=FAILED!
+ aEvent.Source = xThis;
+
+ xListener->dispatchFinished( aEvent );
+ }
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short threadsafe helper for dispatch calls
+ @descr We support two interfaces for the same process - dispatch URLs. That the reason for this internal
+ function. It implements the real dispatch operation and returns a state value which inform caller
+ about success. He can notify listener then by using this return value.
+
+ @param aURL
+ uno URL which should be executed
+ @param lArguments
+ list of optional arguments for this request
+
+ @return <NULL/> if requested service couldn't be created successullfy;
+ a valid reference otherwise. This return value can be used to indicate,
+ if dispatch was successfully or not.
+
+ @modified 02.05.2002 10:51, as96863
+*/
+css::uno::Reference< css::uno::XInterface > ServiceHandler::implts_dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ ) throw( css::uno::RuntimeException )
+{
+ /* SAFE */
+ ReadGuard aReadLock( m_aLock );
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ /* SAFE */
+
+ if (!xFactory.is())
+ return css::uno::Reference< css::uno::XInterface >();
+
+ // extract service name and may optional given parameters from given URL
+ // and use it to create and start the component
+ ::rtl::OUString sServiceAndArguments = aURL.Complete.copy(PROTOCOL_LENGTH);
+ ::rtl::OUString sServiceName;
+ ::rtl::OUString sArguments ;
+
+ sal_Int32 nArgStart = sServiceAndArguments.indexOf('?',0);
+ if (nArgStart!=-1)
+ {
+ sServiceName = sServiceAndArguments.copy(0,nArgStart);
+ ++nArgStart; // ignore '?'!
+ sArguments = sServiceAndArguments.copy(nArgStart);
+ }
+ else
+ {
+ sServiceName = sServiceAndArguments;
+ }
+
+ if (!sServiceName.getLength())
+ return css::uno::Reference< css::uno::XInterface >();
+
+ // If a service doesnt support an optional job executor interface - he can't get
+ // any given parameters!
+ // Because we can't know if we must call createInstanceWithArguments() or XJobExecutor::trigger() ...
+
+ css::uno::Reference< css::uno::XInterface > xService;
+ try
+ {
+ // => a) a service starts running inside his own ctor and we create it only
+ xService = xFactory->createInstance(sServiceName);
+ // or b) he implements the right interface and starts there (may with optional parameters)
+ css::uno::Reference< css::task::XJobExecutor > xExecuteable(xService, css::uno::UNO_QUERY);
+ if (xExecuteable.is())
+ xExecuteable->trigger(sArguments);
+ }
+ // ignore all errors - inclusive runtime errors!
+ // E.g. a script based service (written in phyton) could not be executed
+ // because it contains syntax errors, which was detected at runtime ...
+ catch(const css::uno::Exception&)
+ { xService.clear(); }
+
+ return xService;
+}
+
+//_________________________________________________________________________________________________________________
+
+/**
+ @short add/remove listener for state events
+ @descr We use an internal container to hold such registered listener. This container lives if we live.
+ And if call pas registration as non breakable transaction - we can accept the request without
+ any explicit lock. Because we share our mutex with this container.
+
+ @param xListener
+ reference to a valid listener for state events
+ @param aURL
+ URL about listener will be informed, if something occurred
+
+ @modified 30.04.2002 14:49, as96863
+*/
+void SAL_CALL ServiceHandler::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
+ const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL ServiceHandler::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
+ const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/startmoduledispatcher.cxx b/framework/source/dispatch/startmoduledispatcher.cxx
new file mode 100644
index 000000000000..755935a3a5bd
--- /dev/null
+++ b/framework/source/dispatch/startmoduledispatcher.cxx
@@ -0,0 +1,244 @@
+/* -*- 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"
+
+#include <dispatch/startmoduledispatcher.hxx>
+
+//_______________________________________________
+// my own includes
+
+#include <pattern/frame.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <classes/framelistanalyzer.hxx>
+#include <dispatchcommands.h>
+#include <targets.h>
+#include <services.h>
+#include <general.h>
+
+//_______________________________________________
+// interface includes
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/CommandGroup.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include "com/sun/star/beans/XFastPropertySet.hpp"
+#include <com/sun/star/frame/XModuleManager.hpp>
+
+//_______________________________________________
+// includes of other projects
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <unotools/moduleoptions.hxx>
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+#ifdef fpf
+ #error "Who uses \"fpf\" as define. It will overwrite my namespace alias ..."
+#endif
+namespace fpf = ::framework::pattern::frame;
+
+//_______________________________________________
+// declarations
+
+DEFINE_XINTERFACE_4(StartModuleDispatcher ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::frame::XNotifyingDispatch ),
+ DIRECT_INTERFACE(css::frame::XDispatch ),
+ DIRECT_INTERFACE(css::frame::XDispatchInformationProvider))
+
+// Note: XStatusListener is an implementation detail. Hide it for scripting!
+DEFINE_XTYPEPROVIDER_4(StartModuleDispatcher ,
+ css::lang::XTypeProvider ,
+ css::frame::XDispatchInformationProvider,
+ css::frame::XNotifyingDispatch ,
+ css::frame::XDispatch )
+
+//-----------------------------------------------
+StartModuleDispatcher::StartModuleDispatcher(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame ,
+ const ::rtl::OUString& sTarget)
+ : ThreadHelpBase (&Application::GetSolarMutex() )
+ , ::cppu::OWeakObject( )
+ , m_xSMGR (xSMGR )
+ , m_xOwner (xFrame )
+ , m_sDispatchTarget (sTarget )
+ , m_lStatusListener (m_aLock.getShareableOslMutex())
+{
+}
+
+//-----------------------------------------------
+StartModuleDispatcher::~StartModuleDispatcher()
+{
+}
+
+//-----------------------------------------------
+void SAL_CALL StartModuleDispatcher::dispatch(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
+ throw(css::uno::RuntimeException)
+{
+ dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
+}
+
+//-----------------------------------------------
+void SAL_CALL StartModuleDispatcher::dispatchWithNotification(const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
+ throw(css::uno::RuntimeException)
+{
+ ::sal_Int16 nResult = css::frame::DispatchResultState::DONTKNOW;
+ if (aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(CMD_UNO_SHOWSTARTMODULE)))
+ {
+ nResult = css::frame::DispatchResultState::FAILURE;
+ if (implts_isBackingModePossible ())
+ {
+ if (implts_establishBackingMode ())
+ nResult = css::frame::DispatchResultState::SUCCESS;
+ }
+ }
+
+ implts_notifyResultListener(xListener, nResult, css::uno::Any());
+}
+
+//-----------------------------------------------
+css::uno::Sequence< ::sal_Int16 > SAL_CALL StartModuleDispatcher::getSupportedCommandGroups()
+ throw(css::uno::RuntimeException)
+{
+ return css::uno::Sequence< ::sal_Int16 >();
+}
+
+//-----------------------------------------------
+css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL StartModuleDispatcher::getConfigurableDispatchInformation(::sal_Int16 /*nCommandGroup*/)
+ throw(css::uno::RuntimeException)
+{
+ return css::uno::Sequence< css::frame::DispatchInformation >();
+}
+
+//-----------------------------------------------
+void SAL_CALL StartModuleDispatcher::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+void SAL_CALL StartModuleDispatcher::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/,
+ const css::util::URL& /*aURL*/ )
+ throw(css::uno::RuntimeException)
+{
+}
+
+//-----------------------------------------------
+::sal_Bool StartModuleDispatcher::implts_isBackingModePossible ()
+{
+ if ( ! SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE))
+ return sal_False;
+
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
+ xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
+
+ FrameListAnalyzer aCheck(
+ xDesktop,
+ css::uno::Reference< css::frame::XFrame >(),
+ FrameListAnalyzer::E_HELP | FrameListAnalyzer::E_BACKINGCOMPONENT);
+
+ ::sal_Bool bIsPossible = sal_False;
+ ::sal_Int32 nVisibleFrames = aCheck.m_lOtherVisibleFrames.getLength ();
+
+ if (
+ ( ! aCheck.m_xBackingComponent.is ()) &&
+ ( nVisibleFrames < 1 )
+ )
+ {
+ bIsPossible = sal_True;
+ }
+
+ return bIsPossible;
+}
+
+//-----------------------------------------------
+::sal_Bool StartModuleDispatcher::implts_establishBackingMode()
+{
+ // SAFE -> ----------------------------------
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SAFE ----------------------------------
+
+ css::uno::Reference< css::frame::XFrame > xDesktop (xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
+ css::uno::Reference< css::frame::XFrame > xFrame = xDesktop->findFrame (SPECIALTARGET_BLANK, 0);
+ css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow ();
+
+ css::uno::Sequence< css::uno::Any > lArgs(1);
+ lArgs[0] <<= xContainerWindow;
+
+ css::uno::Reference< css::frame::XController > xStartModule(
+ xSMGR->createInstanceWithArguments(SERVICENAME_STARTMODULE, lArgs),
+ css::uno::UNO_QUERY_THROW);
+
+ css::uno::Reference< css::awt::XWindow > xComponentWindow(xStartModule, css::uno::UNO_QUERY);
+ xFrame->setComponent(xComponentWindow, xStartModule);
+ xStartModule->attachFrame(xFrame);
+ xContainerWindow->setVisible(sal_True);
+
+ return sal_True;
+}
+
+//-----------------------------------------------
+void StartModuleDispatcher::implts_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
+ ::sal_Int16 nState ,
+ const css::uno::Any& aResult )
+{
+ if ( ! xListener.is())
+ return;
+
+ css::frame::DispatchResultEvent aEvent(
+ css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY),
+ nState,
+ aResult);
+
+ xListener->dispatchFinished(aEvent);
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/systemexec.cxx b/framework/source/dispatch/systemexec.cxx
new file mode 100644
index 000000000000..8f20919ecdb0
--- /dev/null
+++ b/framework/source/dispatch/systemexec.cxx
@@ -0,0 +1,237 @@
+/* -*- 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/systemexec.hxx>
+#include <threadhelp/readguard.hxx>
+#include <general.h>
+#include <services.h>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+#include <com/sun/star/system/XSystemShellExecute.hpp>
+#include <com/sun/star/util/XStringSubstitution.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+
+//_________________________________________________________________________________________________________________
+// includes of other projects
+//_________________________________________________________________________________________________________________
+
+#include <vcl/svapp.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// non exported const
+//_________________________________________________________________________________________________________________
+
+#define PROTOCOL_VALUE "systemexecute:"
+#define PROTOCOL_LENGTH 14
+
+//_________________________________________________________________________________________________________________
+// non exported definitions
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// XInterface, XTypeProvider, XServiceInfo
+
+DEFINE_XINTERFACE_5(SystemExec ,
+ OWeakObject ,
+ DIRECT_INTERFACE(css::lang::XTypeProvider ),
+ DIRECT_INTERFACE(css::lang::XServiceInfo ),
+ DIRECT_INTERFACE(css::frame::XDispatchProvider ),
+ DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
+ DIRECT_INTERFACE(css::frame::XDispatch ))
+
+DEFINE_XTYPEPROVIDER_5(SystemExec ,
+ css::lang::XTypeProvider ,
+ css::lang::XServiceInfo ,
+ css::frame::XDispatchProvider ,
+ css::frame::XNotifyingDispatch,
+ css::frame::XDispatch )
+
+DEFINE_XSERVICEINFO_MULTISERVICE(SystemExec ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_PROTOCOLHANDLER ,
+ IMPLEMENTATIONNAME_SYSTEMEXEC)
+
+DEFINE_INIT_SERVICE(SystemExec,
+ {
+ /*Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ }
+ )
+
+//_________________________________________________________________________________________________________________
+
+SystemExec::SystemExec( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
+ // Init baseclasses first
+ : ThreadHelpBase( &Application::GetSolarMutex() )
+ , OWeakObject ( )
+ // Init member
+ , m_xFactory ( xFactory )
+{
+}
+
+//_________________________________________________________________________________________________________________
+
+SystemExec::~SystemExec()
+{
+ m_xFactory = NULL;
+}
+
+//_________________________________________________________________________________________________________________
+
+css::uno::Reference< css::frame::XDispatch > SAL_CALL SystemExec::queryDispatch( const css::util::URL& aURL ,
+ const ::rtl::OUString&,
+ sal_Int32 ) throw( css::uno::RuntimeException )
+{
+ css::uno::Reference< css::frame::XDispatch > xDispatcher;
+ if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
+ xDispatcher = this;
+ return xDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL SystemExec::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
+{
+ sal_Int32 nCount = lDescriptor.getLength();
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
+ for( sal_Int32 i=0; i<nCount; ++i )
+ {
+ lDispatcher[i] = this->queryDispatch(
+ lDescriptor[i].FeatureURL,
+ lDescriptor[i].FrameName,
+ lDescriptor[i].SearchFlags);
+ }
+ return lDispatcher;
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL SystemExec::dispatch( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
+{
+ dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL SystemExec::dispatchWithNotification( const css::util::URL& aURL ,
+ const css::uno::Sequence< css::beans::PropertyValue >&,
+ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
+{
+ // convert "systemexec:file:///c:/temp/test.html" => "file:///c:/temp/test.html"
+ sal_Int32 c = aURL.Complete.getLength()-PROTOCOL_LENGTH;
+ if (c<1) // we dont check for valid URLs here! The system will show an error message ...
+ {
+ impl_notifyResultListener(xListener, css::frame::DispatchResultState::FAILURE);
+ return;
+ }
+ ::rtl::OUString sSystemURLWithVariables = aURL.Complete.copy(PROTOCOL_LENGTH, c);
+
+ // SAFE ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
+ aReadLock.unlock();
+ // <- SAFE
+
+ // TODO check security settings ...
+
+ try
+ {
+ css::uno::Reference< css::util::XStringSubstitution > xPathSubst(
+ xFactory->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES),
+ css::uno::UNO_QUERY_THROW);
+
+ ::rtl::OUString sSystemURL = xPathSubst->substituteVariables(sSystemURLWithVariables, sal_True); // sal_True force an exception if unknown variables exists !
+
+ css::uno::Reference< css::system::XSystemShellExecute > xShell(
+ xFactory->createInstance(SERVICENAME_SYSTEMSHELLEXECUTE),
+ css::uno::UNO_QUERY_THROW);
+
+ xShell->execute(sSystemURL, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS);
+ impl_notifyResultListener(xListener, css::frame::DispatchResultState::SUCCESS);
+ }
+ catch(const css::uno::Exception&)
+ {
+ impl_notifyResultListener(xListener, css::frame::DispatchResultState::FAILURE);
+ }
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL SystemExec::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >&,
+ const css::util::URL& ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+//_________________________________________________________________________________________________________________
+
+void SAL_CALL SystemExec::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >&,
+ const css::util::URL& ) throw( css::uno::RuntimeException )
+{
+ // not suported yet
+}
+
+//_________________________________________________________________________________________________________________
+
+void SystemExec::impl_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
+ const sal_Int16 nState )
+{
+ if (xListener.is())
+ {
+ css::frame::DispatchResultEvent aEvent;
+ aEvent.State = nState;
+ xListener->dispatchFinished(aEvent);
+ }
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/dispatch/windowcommanddispatch.cxx b/framework/source/dispatch/windowcommanddispatch.cxx
new file mode 100644
index 000000000000..09efdb3e8ae6
--- /dev/null
+++ b/framework/source/dispatch/windowcommanddispatch.cxx
@@ -0,0 +1,194 @@
+/* -*- 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/windowcommanddispatch.hxx>
+#include <threadhelp/readguard.hxx>
+#include <threadhelp/writeguard.hxx>
+#include <targets.h>
+#include <services.h>
+
+//_______________________________________________
+// interface includes
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+//_______________________________________________
+// includes of other projects
+
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/cmdevt.hxx>
+#include <osl/mutex.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <rtl/logfile.hxx>
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+namespace css = ::com::sun::star;
+
+//_______________________________________________
+// declarations
+
+const ::rtl::OUString WindowCommandDispatch::COMMAND_PREFERENCES(RTL_CONSTASCII_USTRINGPARAM(".uno:OptionsTreeDialog"));
+const ::rtl::OUString WindowCommandDispatch::COMMAND_ABOUTBOX(RTL_CONSTASCII_USTRINGPARAM(".uno:About"));
+
+//-----------------------------------------------
+WindowCommandDispatch::WindowCommandDispatch(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
+ const css::uno::Reference< css::frame::XFrame >& xFrame)
+ : ThreadHelpBase( )
+ , m_xSMGR (xSMGR )
+ , m_xFrame (xFrame )
+ , m_xWindow (xFrame->getContainerWindow())
+{
+ impl_startListening();
+}
+
+//-----------------------------------------------
+WindowCommandDispatch::~WindowCommandDispatch()
+{
+ m_xSMGR.clear();
+}
+
+//-----------------------------------------------
+void SAL_CALL WindowCommandDispatch::disposing(const css::lang::EventObject& /*aSource*/)
+ throw (css::uno::RuntimeException)
+{
+ // We hold our window weak ... so there is no need to clear it's reference here.
+ // The window and we will die by ref count automatically.
+}
+
+//-----------------------------------------------
+void WindowCommandDispatch::impl_startListening()
+{
+ // SYNCHRONIZED ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::awt::XWindow > xWindow( m_xWindow.get(), css::uno::UNO_QUERY );
+ aReadLock.unlock();
+ // <- SYNCHRONIZED
+
+ if ( ! xWindow.is())
+ return;
+
+ // SYNCHRONIZED ->
+ {
+ SolarMutexGuard aSolarLock;
+
+ Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
+ if ( ! pWindow)
+ return;
+
+ pWindow->AddEventListener( LINK(this, WindowCommandDispatch, impl_notifyCommand) );
+ }
+ // <- SYNCHRONIZED
+}
+
+//-----------------------------------------------
+IMPL_LINK(WindowCommandDispatch, impl_notifyCommand, void*, pParam)
+{
+ if ( ! pParam)
+ return 0L;
+
+ const VclWindowEvent* pEvent = (VclWindowEvent*)pParam;
+ if (pEvent->GetId() != VCLEVENT_WINDOW_COMMAND)
+ return 0L;
+
+ const CommandEvent* pCommand = (CommandEvent*)pEvent->GetData();
+ if (pCommand->GetCommand() != COMMAND_SHOWDIALOG)
+ return 0L;
+
+ const CommandDialogData* pData = pCommand->GetDialogData();
+ if ( ! pData)
+ return 0L;
+
+ const int nCommand = pData->GetDialogId();
+ ::rtl::OUString sCommand;
+
+ switch (nCommand)
+ {
+ case SHOWDIALOG_ID_PREFERENCES :
+ sCommand = WindowCommandDispatch::COMMAND_PREFERENCES;
+ break;
+
+ case SHOWDIALOG_ID_ABOUT :
+ sCommand = WindowCommandDispatch::COMMAND_ABOUTBOX;
+ break;
+
+ default :
+ return 0L;
+ }
+
+ impl_dispatchCommand(sCommand);
+
+ return 0L;
+}
+
+//-----------------------------------------------
+void WindowCommandDispatch::impl_dispatchCommand(const ::rtl::OUString& sCommand)
+{
+ // ignore all errors here. It's clicking a menu entry only ...
+ // The user will try it again, in case nothing happens .-)
+ try
+ {
+ // SYNCHRONIZED ->
+ ReadGuard aReadLock(m_aLock);
+ css::uno::Reference< css::frame::XDispatchProvider > xProvider(m_xFrame.get(), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
+ aReadLock.unlock();
+ // <- SYNCHRONIZED
+
+ // check provider ... we know it's weak reference only
+ if ( ! xProvider.is())
+ return;
+
+ css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
+ css::util::URL aCommand;
+ aCommand.Complete = sCommand;
+ xParser->parseStrict(aCommand);
+
+ css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aCommand, SPECIALTARGET_SELF, 0);
+ if (xDispatch.is())
+ xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
+ }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */