blob: eb979464453cd9fc70b049da4fb78705d948684c [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sdext.hxx"
#include "PresenterProtocolHandler.hxx"
#include "PresenterConfigurationAccess.hxx"
#include "PresenterController.hxx"
#include "PresenterHelper.hxx"
#include "PresenterNotesView.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterViewFactory.hxx"
#include "PresenterWindowManager.hxx"
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/drawing/SlideSorter.hpp>
#include <com/sun/star/drawing/framework/Configuration.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
#include <com/sun/star/presentation/XSlideShow.hpp>
#include <com/sun/star/presentation/XSlideShowView.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
#include <cppuhelper/compbase2.hxx>
#include <boost/bind.hpp>
#include <tools/debug.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;
#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
namespace sdext { namespace presenter {
namespace {
const static OUString gsProtocol (A2S("vnd.com.sun.star.presentation.PresenterScreen:"));
class Command
{
public:
virtual void Execute (void) = 0;
virtual bool IsEnabled (void) const = 0;
virtual Any GetState (void) const = 0;
};
class GotoPreviousSlideCommand : public Command
{
public:
GotoPreviousSlideCommand (
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~GotoPreviousSlideCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
rtl::Reference<PresenterController> mpPresenterController;
};
class GotoNextSlideCommand : public Command
{
public:
GotoNextSlideCommand (
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~GotoNextSlideCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
rtl::Reference<PresenterController> mpPresenterController;
};
class GotoNextEffectCommand : public Command
{
public:
GotoNextEffectCommand (
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~GotoNextEffectCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
rtl::Reference<PresenterController> mpPresenterController;
};
class SetNotesViewCommand : public Command
{
public:
SetNotesViewCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~SetNotesViewCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
bool mbOn;
rtl::Reference<PresenterController> mpPresenterController;
bool IsActive (const ::rtl::Reference<PresenterWindowManager>& rpWindowManager) const;
};
class SetSlideSorterCommand : public Command
{
public:
SetSlideSorterCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~SetSlideSorterCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
bool mbOn;
rtl::Reference<PresenterController> mpPresenterController;
};
class SetHelpViewCommand : public Command
{
public:
SetHelpViewCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController);
virtual ~SetHelpViewCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
private:
bool mbOn;
rtl::Reference<PresenterController> mpPresenterController;
};
class NotesFontSizeCommand : public Command
{
public:
NotesFontSizeCommand(
const rtl::Reference<PresenterController>& rpPresenterController,
const sal_Int32 nSizeChange);
virtual ~NotesFontSizeCommand (void) {}
virtual void Execute (void);
virtual bool IsEnabled (void) const;
virtual Any GetState (void) const;
protected:
::rtl::Reference<PresenterNotesView> GetNotesView (void) const;
private:
rtl::Reference<PresenterController> mpPresenterController;
const sal_Int32 mnSizeChange;
};
} // end of anonymous namespace
namespace {
typedef ::cppu::WeakComponentImplHelper2 <
css::frame::XDispatch,
css::document::XEventListener
> PresenterDispatchInterfaceBase;
}
class PresenterProtocolHandler::Dispatch
: protected ::cppu::BaseMutex,
public PresenterDispatchInterfaceBase
{
public:
typedef void (PresenterProtocolHandler::Dispatch::* Action)(void);
/** Create a new Dispatch object. When the given command name
(rsURLPath) is not known then an empty reference is returned.
*/
static Reference<frame::XDispatch> Create (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController);
void SAL_CALL disposing (void);
static Command* CreateCommand (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController);
// XDispatch
virtual void SAL_CALL dispatch(
const css::util::URL& aURL,
const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
throw(css::uno::RuntimeException);
virtual void SAL_CALL addStatusListener(
const css::uno::Reference<css::frame::XStatusListener>& rxListener,
const css::util::URL& rURL)
throw(css::uno::RuntimeException);
virtual void SAL_CALL removeStatusListener (
const css::uno::Reference<css::frame::XStatusListener>& rxListener,
const css::util::URL& rURL)
throw(css::uno::RuntimeException);
// document::XEventListener
virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent)
throw(css::uno::RuntimeException);
// lang::XEventListener
virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException);
private:
OUString msURLPath;
::boost::scoped_ptr<Command> mpCommand;
::rtl::Reference<PresenterController> mpPresenterController;
typedef ::std::vector<Reference<frame::XStatusListener> > StatusListenerContainer;
StatusListenerContainer maStatusListenerContainer;
bool mbIsListeningToWindowManager;
Dispatch (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController);
virtual ~Dispatch (void);
void ThrowIfDisposed (void) const throw (css::lang::DisposedException);
};
//----- Service ---------------------------------------------------------------
OUString PresenterProtocolHandler::getImplementationName_static (void)
{
return A2S("com.sun.star.comp.presentation.PresenterProtocolHandler");
}
Sequence<OUString> PresenterProtocolHandler::getSupportedServiceNames_static (void)
{
static const ::rtl::OUString sServiceName(A2S("com.sun.star.frame.ProtocolHandler"));
return Sequence<rtl::OUString>(&sServiceName, 1);
}
Reference<XInterface> PresenterProtocolHandler::Create (
const Reference<uno::XComponentContext>& rxContext)
SAL_THROW((Exception))
{
return Reference<XInterface>(static_cast<XWeak*>(new PresenterProtocolHandler(rxContext)));
}
//===== PresenterProtocolHandler =========================================================
PresenterProtocolHandler::PresenterProtocolHandler (const Reference<XComponentContext>& rxContext)
: PresenterProtocolHandlerInterfaceBase(m_aMutex)
{
(void)rxContext;
}
PresenterProtocolHandler::~PresenterProtocolHandler (void)
{
}
void SAL_CALL PresenterProtocolHandler::disposing (void)
{
}
//----- XInitialize -----------------------------------------------------------
void SAL_CALL PresenterProtocolHandler::initialize (const Sequence<Any>& aArguments)
throw (Exception, RuntimeException)
{
ThrowIfDisposed();
if (aArguments.getLength() > 0)
{
try
{
Reference<frame::XFrame> xFrame;
if (aArguments[0] >>= xFrame)
{
mpPresenterController = PresenterController::Instance(xFrame);
}
}
catch (RuntimeException&)
{
OSL_ASSERT(false);
}
}
}
//----- XDispatchProvider -----------------------------------------------------
Reference<frame::XDispatch> SAL_CALL PresenterProtocolHandler::queryDispatch (
const css::util::URL& rURL,
const rtl::OUString& rsTargetFrameName,
sal_Int32 nSearchFlags)
throw(RuntimeException)
{
(void)rsTargetFrameName;
(void)nSearchFlags;
ThrowIfDisposed();
Reference<frame::XDispatch> xDispatch;
if (rURL.Protocol == gsProtocol)
{
xDispatch.set(Dispatch::Create(rURL.Path, mpPresenterController));
}
return xDispatch;
}
Sequence<Reference<frame::XDispatch> > SAL_CALL PresenterProtocolHandler::queryDispatches(
const Sequence<frame::DispatchDescriptor>& rDescriptors)
throw(RuntimeException)
{
(void)rDescriptors;
ThrowIfDisposed();
return Sequence<Reference<frame::XDispatch> >();
}
//-----------------------------------------------------------------------------
void PresenterProtocolHandler::ThrowIfDisposed (void) const
throw (::com::sun::star::lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM(
"PresenterProtocolHandler object has already been disposed")),
const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
}
}
//===== PresenterProtocolHandler::Dispatch ====================================
Reference<frame::XDispatch> PresenterProtocolHandler::Dispatch::Create (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController)
{
::rtl::Reference<Dispatch> pDispatch (new Dispatch (rsURLPath, rpPresenterController));
if (pDispatch->mpCommand.get() != NULL)
return Reference<frame::XDispatch>(pDispatch.get());
else
return NULL;
}
PresenterProtocolHandler::Dispatch::Dispatch (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController)
: PresenterDispatchInterfaceBase(m_aMutex),
msURLPath(rsURLPath),
mpCommand(CreateCommand(rsURLPath, rpPresenterController)),
mpPresenterController(rpPresenterController),
maStatusListenerContainer(),
mbIsListeningToWindowManager(false)
{
if (mpCommand.get() != NULL)
{
mpPresenterController->GetWindowManager()->AddLayoutListener(this);
mbIsListeningToWindowManager = true;
}
}
Command* PresenterProtocolHandler::Dispatch::CreateCommand (
const OUString& rsURLPath,
const ::rtl::Reference<PresenterController>& rpPresenterController)
{
if (rsURLPath.getLength() <= 5)
return NULL;
switch (rsURLPath[0])
{
case sal_Char('C') :
switch (rsURLPath[5])
{
case sal_Char('N'):
if (rsURLPath == A2S("CloseNotes"))
return new SetNotesViewCommand(false, rpPresenterController);
break;
case sal_Char('S'):
if (rsURLPath == A2S("CloseSlideSorter"))
return new SetSlideSorterCommand(false, rpPresenterController);
break;
case sal_Char('H'):
if (rsURLPath == A2S("CloseHelp"))
return new SetHelpViewCommand(false, rpPresenterController);
break;
}
break;
case sal_Char('G') :
if (rsURLPath == A2S("GrowNotesFont"))
return new NotesFontSizeCommand(rpPresenterController, +1);
break;
case sal_Char('N') :
switch (rsURLPath[4])
{
case sal_Char('E'):
if (rsURLPath == A2S("NextEffect"))
return new GotoNextEffectCommand(rpPresenterController);
case sal_Char('S'):
if (rsURLPath == A2S("NextSlide"))
return new GotoNextSlideCommand(rpPresenterController);
break;
}
break;
case sal_Char('P') :
if (rsURLPath == A2S("PrevSlide"))
return new GotoPreviousSlideCommand(rpPresenterController);
break;
case sal_Char('S') :
switch (rsURLPath[4])
{
case sal_Char('N'):
if (rsURLPath == A2S("ShowNotes"))
return new SetNotesViewCommand(true, rpPresenterController);
break;
case sal_Char('S'):
if (rsURLPath == A2S("ShowSlideSorter"))
return new SetSlideSorterCommand(true, rpPresenterController);
break;
case sal_Char('H'):
if (rsURLPath == A2S("ShowHelp"))
return new SetHelpViewCommand(true, rpPresenterController);
break;
case sal_Char('n'):
if (rsURLPath == A2S("ShrinkNotesFont"))
return new NotesFontSizeCommand(rpPresenterController, -1);
break;
}
break;
default:
break;
}
return NULL;
}
PresenterProtocolHandler::Dispatch::~Dispatch (void)
{
}
void PresenterProtocolHandler::Dispatch::disposing (void)
{
if (mbIsListeningToWindowManager)
{
if (mpPresenterController.get() != NULL)
mpPresenterController->GetWindowManager()->RemoveLayoutListener(this);
mbIsListeningToWindowManager = false;
}
msURLPath = OUString();
mpCommand.reset();
}
//----- XDispatch -------------------------------------------------------------
void SAL_CALL PresenterProtocolHandler::Dispatch::dispatch(
const css::util::URL& rURL,
const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
throw(css::uno::RuntimeException)
{
(void)rArguments;
ThrowIfDisposed();
if (rURL.Protocol == gsProtocol
&& rURL.Path == msURLPath)
{
if (mpCommand.get() != NULL)
mpCommand->Execute();
}
else
{
// We can not throw an IllegalArgumentException
throw RuntimeException();
}
}
void SAL_CALL PresenterProtocolHandler::Dispatch::addStatusListener(
const css::uno::Reference<css::frame::XStatusListener>& rxListener,
const css::util::URL& rURL)
throw(css::uno::RuntimeException)
{
if (rURL.Path == msURLPath)
{
maStatusListenerContainer.push_back(rxListener);
frame::FeatureStateEvent aEvent;
aEvent.FeatureURL = rURL;
aEvent.IsEnabled = mpCommand->IsEnabled();
aEvent.Requery = sal_False;
aEvent.State = mpCommand->GetState();
rxListener->statusChanged(aEvent);
}
else
throw RuntimeException();
}
void SAL_CALL PresenterProtocolHandler::Dispatch::removeStatusListener (
const css::uno::Reference<css::frame::XStatusListener>& rxListener,
const css::util::URL& rURL)
throw(css::uno::RuntimeException)
{
if (rURL.Path == msURLPath)
{
StatusListenerContainer::iterator iListener (
::std::find(
maStatusListenerContainer.begin(),
maStatusListenerContainer.end(),
rxListener));
if (iListener != maStatusListenerContainer.end())
maStatusListenerContainer.erase(iListener);
}
else
throw RuntimeException();
}
//-----------------------------------------------------------------------------
void PresenterProtocolHandler::Dispatch::ThrowIfDisposed (void) const
throw (::com::sun::star::lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM(
"PresenterProtocolHandler::Dispatch object has already been disposed")),
const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
}
}
//----- document::XEventListener ----------------------------------------------
void SAL_CALL PresenterProtocolHandler::Dispatch::notifyEvent (
const css::document::EventObject& rEvent)
throw(css::uno::RuntimeException)
{
(void)rEvent;
mpCommand->GetState();
}
//----- lang::XEventListener --------------------------------------------------
void SAL_CALL PresenterProtocolHandler::Dispatch::disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException)
{
(void)rEvent;
mbIsListeningToWindowManager = false;
}
//===== GotoPreviousSlideCommand ==============================================
GotoPreviousSlideCommand::GotoPreviousSlideCommand (
const rtl::Reference<PresenterController>& rpPresenterController)
: mpPresenterController(rpPresenterController)
{
}
void GotoPreviousSlideCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
if ( ! mpPresenterController->GetSlideShowController().is())
return;
mpPresenterController->GetSlideShowController()->gotoPreviousSlide();
}
bool GotoPreviousSlideCommand::IsEnabled (void) const
{
if ( ! mpPresenterController.is())
return false;
if ( ! mpPresenterController->GetSlideShowController().is())
return false;
return mpPresenterController->GetSlideShowController()->getCurrentSlideIndex()>0;
}
Any GotoPreviousSlideCommand::GetState (void) const
{
return Any(sal_False);
}
//===== GotoNextEffect ========================================================
GotoNextEffectCommand::GotoNextEffectCommand (
const rtl::Reference<PresenterController>& rpPresenterController)
: mpPresenterController(rpPresenterController)
{
}
void GotoNextEffectCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
if ( ! mpPresenterController->GetSlideShowController().is())
return;
mpPresenterController->GetSlideShowController()->gotoNextEffect();
}
bool GotoNextEffectCommand::IsEnabled (void) const
{
// The next slide command is always enabled, even when the current slide
// is the last slide: from the last slide it goes to the pause slide,
// and from there it ends the slide show.
return true;
}
Any GotoNextEffectCommand::GetState (void) const
{
return Any(sal_False);
}
//===== GotoNextSlide =========================================================
GotoNextSlideCommand::GotoNextSlideCommand (
const rtl::Reference<PresenterController>& rpPresenterController)
: mpPresenterController(rpPresenterController)
{
}
void GotoNextSlideCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
if ( ! mpPresenterController->GetSlideShowController().is())
return;
mpPresenterController->GetSlideShowController()->gotoNextSlide();
}
bool GotoNextSlideCommand::IsEnabled (void) const
{
// The next slide command is always enabled, even when the current slide
// is the last slide: from the last slide it goes to the pause slide,
// and from there it ends the slide show.
return true;
}
Any GotoNextSlideCommand::GetState (void) const
{
return Any(sal_False);
}
//===== SetNotesViewCommand ===================================================
SetNotesViewCommand::SetNotesViewCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController)
: mbOn(bOn),
mpPresenterController(rpPresenterController)
{
}
void SetNotesViewCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return;
if (mbOn)
pWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
else
pWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
}
bool SetNotesViewCommand::IsEnabled (void) const
{
return true;
}
Any SetNotesViewCommand::GetState (void) const
{
if ( ! mpPresenterController.is())
return Any(false);
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return Any(false);
return Any(IsActive(pWindowManager));
}
bool SetNotesViewCommand::IsActive (
const ::rtl::Reference<PresenterWindowManager>& rpWindowManager) const
{
return rpWindowManager->GetViewMode() == PresenterWindowManager::VM_Notes;
}
//===== SetSlideSorterCommand =================================================
SetSlideSorterCommand::SetSlideSorterCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController)
: mbOn(bOn),
mpPresenterController(rpPresenterController)
{
}
void SetSlideSorterCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return;
pWindowManager->SetSlideSorterState(mbOn);
}
bool SetSlideSorterCommand::IsEnabled (void) const
{
return true;
}
Any SetSlideSorterCommand::GetState (void) const
{
if ( ! mpPresenterController.is())
return Any(false);
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return Any(false);
return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_SlideOverview);
}
//===== SetHelpViewCommand ===================================================
SetHelpViewCommand::SetHelpViewCommand (
const bool bOn,
const rtl::Reference<PresenterController>& rpPresenterController)
: mbOn(bOn),
mpPresenterController(rpPresenterController)
{
}
void SetHelpViewCommand::Execute (void)
{
if ( ! mpPresenterController.is())
return;
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return;
pWindowManager->SetHelpViewState(mbOn);
}
bool SetHelpViewCommand::IsEnabled (void) const
{
return true;
}
Any SetHelpViewCommand::GetState (void) const
{
if ( ! mpPresenterController.is())
return Any(false);
::rtl::Reference<PresenterWindowManager> pWindowManager (
mpPresenterController->GetWindowManager());
if ( ! pWindowManager.is())
return Any(false);
return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_Help);
}
//===== NotesFontSizeCommand ==================================================
NotesFontSizeCommand::NotesFontSizeCommand(
const rtl::Reference<PresenterController>& rpPresenterController,
const sal_Int32 nSizeChange)
: mpPresenterController(rpPresenterController),
mnSizeChange(nSizeChange)
{
}
::rtl::Reference<PresenterNotesView> NotesFontSizeCommand::GetNotesView (void) const
{
if (mpPresenterController.get() == NULL)
return NULL;
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPresenterController->GetPaneContainer()->FindViewURL(
PresenterViewFactory::msNotesViewURL));
if (pDescriptor.get() == NULL)
return NULL;
return dynamic_cast<PresenterNotesView*>(pDescriptor->mxView.get());
}
void NotesFontSizeCommand::Execute (void)
{
::rtl::Reference<PresenterNotesView> pView (GetNotesView());
if (pView.is())
pView->ChangeFontSize(mnSizeChange);
}
bool NotesFontSizeCommand::IsEnabled (void) const
{
return true;
}
Any NotesFontSizeCommand::GetState (void) const
{
return Any();
}
} } // end of namespace ::sdext::presenter