Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sdext / source / presenter / PresenterProtocolHandler.cxx
blobb7ca0c08a4b2008266771eb54610c534d60b49db
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include "PresenterProtocolHandler.hxx"
22 #include "PresenterConfigurationAccess.hxx"
23 #include "PresenterController.hxx"
24 #include "PresenterHelper.hxx"
25 #include "PresenterNotesView.hxx"
26 #include "PresenterPaneContainer.hxx"
27 #include "PresenterPaneFactory.hxx"
28 #include "PresenterViewFactory.hxx"
29 #include "PresenterWindowManager.hxx"
30 #include <com/sun/star/drawing/SlideSorter.hpp>
31 #include <com/sun/star/drawing/framework/Configuration.hpp>
32 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
33 #include <com/sun/star/drawing/framework/ResourceId.hpp>
34 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
35 #include <cppuhelper/compbase.hxx>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <algorithm>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::drawing::framework;
43 namespace sdext { namespace presenter {
45 namespace {
46 class Command
48 public:
49 virtual ~Command() {}
50 virtual void Execute() = 0;
51 virtual bool IsEnabled() const { return true; }
52 virtual Any GetState() const { return Any(false); }
55 class GotoPreviousSlideCommand : public Command
57 public:
58 explicit GotoPreviousSlideCommand (
59 const rtl::Reference<PresenterController>& rpPresenterController);
60 virtual void Execute() override;
61 virtual bool IsEnabled() const override;
62 private:
63 rtl::Reference<PresenterController> mpPresenterController;
66 class GotoNextSlideCommand : public Command
68 public:
69 explicit GotoNextSlideCommand (
70 const rtl::Reference<PresenterController>& rpPresenterController);
71 virtual void Execute() override;
72 // The next slide command is always enabled, even when the current slide
73 // is the last slide: from the last slide it goes to the pause slide,
74 // and from there it ends the slide show.
75 virtual bool IsEnabled() const override { return true; }
76 private:
77 rtl::Reference<PresenterController> mpPresenterController;
80 class GotoNextEffectCommand : public Command
82 public:
83 explicit GotoNextEffectCommand (
84 const rtl::Reference<PresenterController>& rpPresenterController);
85 virtual void Execute() override;
86 private:
87 rtl::Reference<PresenterController> mpPresenterController;
90 class SwitchMonitorCommand : public Command
92 public:
93 explicit SwitchMonitorCommand (
94 const rtl::Reference<PresenterController>& rpPresenterController);
95 virtual void Execute() override;
96 private:
97 rtl::Reference<PresenterController> mpPresenterController;
100 /// This command restarts the presentation timer.
101 class RestartTimerCommand : public Command
103 public:
104 explicit RestartTimerCommand(const rtl::Reference<PresenterController>& rpPresenterController);
105 virtual void Execute() override;
106 private:
107 rtl::Reference<PresenterController> mpPresenterController;
110 class SetNotesViewCommand : public Command
112 public:
113 SetNotesViewCommand (
114 const bool bOn,
115 const rtl::Reference<PresenterController>& rpPresenterController);
116 virtual void Execute() override;
117 virtual Any GetState() const override;
118 private:
119 bool mbOn;
120 rtl::Reference<PresenterController> mpPresenterController;
123 class SetSlideSorterCommand : public Command
125 public:
126 SetSlideSorterCommand (
127 const bool bOn,
128 const rtl::Reference<PresenterController>& rpPresenterController);
129 virtual void Execute() override;
130 virtual Any GetState() const override;
131 private:
132 bool mbOn;
133 rtl::Reference<PresenterController> mpPresenterController;
136 class SetHelpViewCommand : public Command
138 public:
139 SetHelpViewCommand (
140 const bool bOn,
141 const rtl::Reference<PresenterController>& rpPresenterController);
142 virtual void Execute() override;
143 virtual Any GetState() const override;
144 private:
145 bool mbOn;
146 rtl::Reference<PresenterController> mpPresenterController;
149 class NotesFontSizeCommand : public Command
151 public:
152 NotesFontSizeCommand(
153 const rtl::Reference<PresenterController>& rpPresenterController,
154 const sal_Int32 nSizeChange);
155 virtual void Execute() override;
156 virtual Any GetState() const override;
157 protected:
158 ::rtl::Reference<PresenterNotesView> GetNotesView() const;
159 private:
160 rtl::Reference<PresenterController> mpPresenterController;
161 const sal_Int32 mnSizeChange;
164 } // end of anonymous namespace
166 namespace {
167 typedef ::cppu::WeakComponentImplHelper <
168 css::frame::XDispatch,
169 css::document::XEventListener
170 > PresenterDispatchInterfaceBase;
173 class PresenterProtocolHandler::Dispatch
174 : protected ::cppu::BaseMutex,
175 public PresenterDispatchInterfaceBase
177 public:
178 typedef void (PresenterProtocolHandler::Dispatch::* Action)(void);
180 /** Create a new Dispatch object. When the given command name
181 (rsURLPath) is not known then an empty reference is returned.
183 static Reference<frame::XDispatch> Create (
184 const OUString& rsURLPath,
185 const ::rtl::Reference<PresenterController>& rpPresenterController);
187 void SAL_CALL disposing() override;
188 static Command* CreateCommand (
189 const OUString& rsURLPath,
190 const ::rtl::Reference<PresenterController>& rpPresenterController);
192 // XDispatch
193 virtual void SAL_CALL dispatch(
194 const css::util::URL& aURL,
195 const css::uno::Sequence<css::beans::PropertyValue>& rArguments) override;
197 virtual void SAL_CALL addStatusListener(
198 const css::uno::Reference<css::frame::XStatusListener>& rxListener,
199 const css::util::URL& rURL) override;
201 virtual void SAL_CALL removeStatusListener (
202 const css::uno::Reference<css::frame::XStatusListener>& rxListener,
203 const css::util::URL& rURL) override;
205 // document::XEventListener
207 virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) override;
209 // lang::XEventListener
211 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
213 private:
214 OUString msURLPath;
215 std::unique_ptr<Command> mpCommand;
216 ::rtl::Reference<PresenterController> mpPresenterController;
217 typedef ::std::vector<Reference<frame::XStatusListener> > StatusListenerContainer;
218 StatusListenerContainer maStatusListenerContainer;
219 bool mbIsListeningToWindowManager;
221 Dispatch (
222 const OUString& rsURLPath,
223 const ::rtl::Reference<PresenterController>& rpPresenterController);
224 virtual ~Dispatch() override;
227 //----- Service ---------------------------------------------------------------
229 OUString PresenterProtocolHandler::getImplementationName_static()
231 return OUString("org.libreoffice.comp.PresenterScreenProtocolHandler");
234 Sequence<OUString> PresenterProtocolHandler::getSupportedServiceNames_static()
236 static const OUString sServiceName("com.sun.star.frame.ProtocolHandler");
237 return Sequence<OUString>(&sServiceName, 1);
240 Reference<XInterface> PresenterProtocolHandler::Create (
241 SAL_UNUSED_PARAMETER const Reference<uno::XComponentContext>&)
243 return Reference<XInterface>(static_cast<XWeak*>(new PresenterProtocolHandler));
246 //===== PresenterProtocolHandler =========================================================
248 PresenterProtocolHandler::PresenterProtocolHandler ()
249 : PresenterProtocolHandlerInterfaceBase(m_aMutex)
253 PresenterProtocolHandler::~PresenterProtocolHandler()
257 void SAL_CALL PresenterProtocolHandler::disposing()
261 //----- XInitialize -----------------------------------------------------------
263 void SAL_CALL PresenterProtocolHandler::initialize (const Sequence<Any>& aArguments)
265 ThrowIfDisposed();
266 if (aArguments.getLength() > 0)
270 Reference<frame::XFrame> xFrame;
271 if (aArguments[0] >>= xFrame)
273 mpPresenterController = PresenterController::Instance(xFrame);
276 catch (RuntimeException&)
278 OSL_ASSERT(false);
283 OUString PresenterProtocolHandler::getImplementationName()
285 return getImplementationName_static();
288 sal_Bool PresenterProtocolHandler::supportsService(OUString const & ServiceName)
290 return cppu::supportsService(this, ServiceName);
293 css::uno::Sequence<OUString>
294 PresenterProtocolHandler::getSupportedServiceNames()
296 return getSupportedServiceNames_static();
299 //----- XDispatchProvider -----------------------------------------------------
301 Reference<frame::XDispatch> SAL_CALL PresenterProtocolHandler::queryDispatch (
302 const css::util::URL& rURL,
303 const OUString&,
304 sal_Int32)
306 ThrowIfDisposed();
308 Reference<frame::XDispatch> xDispatch;
310 if (rURL.Protocol == "vnd.org.libreoffice.presenterscreen:")
312 xDispatch.set(Dispatch::Create(rURL.Path, mpPresenterController));
315 return xDispatch;
318 Sequence<Reference<frame::XDispatch> > SAL_CALL PresenterProtocolHandler::queryDispatches(
319 const Sequence<frame::DispatchDescriptor>&)
321 ThrowIfDisposed();
322 return Sequence<Reference<frame::XDispatch> >();
326 void PresenterProtocolHandler::ThrowIfDisposed() const
328 if (rBHelper.bDisposed || rBHelper.bInDispose)
330 throw lang::DisposedException (
331 "PresenterProtocolHandler object has already been disposed",
332 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
336 //===== PresenterProtocolHandler::Dispatch ====================================
338 Reference<frame::XDispatch> PresenterProtocolHandler::Dispatch::Create (
339 const OUString& rsURLPath,
340 const ::rtl::Reference<PresenterController>& rpPresenterController)
342 ::rtl::Reference<Dispatch> pDispatch (new Dispatch (rsURLPath, rpPresenterController));
343 if (pDispatch->mpCommand.get() != nullptr)
344 return Reference<frame::XDispatch>(pDispatch.get());
345 else
346 return nullptr;
349 PresenterProtocolHandler::Dispatch::Dispatch (
350 const OUString& rsURLPath,
351 const ::rtl::Reference<PresenterController>& rpPresenterController)
352 : PresenterDispatchInterfaceBase(m_aMutex),
353 msURLPath(rsURLPath),
354 mpCommand(CreateCommand(rsURLPath, rpPresenterController)),
355 mpPresenterController(rpPresenterController),
356 maStatusListenerContainer(),
357 mbIsListeningToWindowManager(false)
359 if (mpCommand.get() != nullptr)
361 mpPresenterController->GetWindowManager()->AddLayoutListener(this);
362 mbIsListeningToWindowManager = true;
366 Command* PresenterProtocolHandler::Dispatch::CreateCommand (
367 const OUString& rsURLPath,
368 const ::rtl::Reference<PresenterController>& rpPresenterController)
370 if (rsURLPath.getLength() <= 5)
371 return nullptr;
373 if (rsURLPath == "CloseNotes")
374 return new SetNotesViewCommand(false, rpPresenterController);
375 if (rsURLPath == "CloseSlideSorter")
376 return new SetSlideSorterCommand(false, rpPresenterController);
377 if (rsURLPath == "CloseHelp")
378 return new SetHelpViewCommand(false, rpPresenterController);
379 if (rsURLPath == "GrowNotesFont")
380 return new NotesFontSizeCommand(rpPresenterController, +1);
381 if (rsURLPath == "NextEffect")
382 return new GotoNextEffectCommand(rpPresenterController);
383 if (rsURLPath == "NextSlide")
384 return new GotoNextSlideCommand(rpPresenterController);
385 if (rsURLPath == "PrevSlide")
386 return new GotoPreviousSlideCommand(rpPresenterController);
387 if (rsURLPath == "SwitchMonitor")
388 return new SwitchMonitorCommand(rpPresenterController);
389 if (rsURLPath == "RestartTimer")
390 return new RestartTimerCommand(rpPresenterController);
391 if (rsURLPath == "ShowNotes")
392 return new SetNotesViewCommand(true, rpPresenterController);
393 if (rsURLPath == "ShowSlideSorter")
394 return new SetSlideSorterCommand(true, rpPresenterController);
395 if (rsURLPath == "ShowHelp")
396 return new SetHelpViewCommand(true, rpPresenterController);
397 if (rsURLPath == "ShrinkNotesFont")
398 return new NotesFontSizeCommand(rpPresenterController, -1);
400 return nullptr;
403 PresenterProtocolHandler::Dispatch::~Dispatch()
407 void PresenterProtocolHandler::Dispatch::disposing()
409 if (mbIsListeningToWindowManager)
411 if (mpPresenterController.get() != nullptr)
412 mpPresenterController->GetWindowManager()->RemoveLayoutListener(this);
413 mbIsListeningToWindowManager = false;
416 msURLPath.clear();
417 mpCommand.reset();
420 //----- XDispatch -------------------------------------------------------------
422 void SAL_CALL PresenterProtocolHandler::Dispatch::dispatch(
423 const css::util::URL& rURL,
424 const css::uno::Sequence<css::beans::PropertyValue>& /*rArguments*/)
426 if (rBHelper.bDisposed || rBHelper.bInDispose)
428 throw lang::DisposedException (
429 "PresenterProtocolHandler::Dispatch object has already been disposed",
430 static_cast<uno::XWeak*>(this));
433 if (rURL.Protocol != "vnd.org.libreoffice.presenterscreen:"
434 || rURL.Path != msURLPath)
436 // We can not throw an IllegalArgumentException
437 throw RuntimeException();
440 if (mpCommand.get() != nullptr)
441 mpCommand->Execute();
444 void SAL_CALL PresenterProtocolHandler::Dispatch::addStatusListener(
445 const css::uno::Reference<css::frame::XStatusListener>& rxListener,
446 const css::util::URL& rURL)
448 if (rURL.Path != msURLPath)
449 throw RuntimeException();
451 maStatusListenerContainer.push_back(rxListener);
453 frame::FeatureStateEvent aEvent;
454 aEvent.FeatureURL = rURL;
455 aEvent.IsEnabled = mpCommand->IsEnabled();
456 aEvent.Requery = false;
457 aEvent.State = mpCommand->GetState();
458 rxListener->statusChanged(aEvent);
461 void SAL_CALL PresenterProtocolHandler::Dispatch::removeStatusListener (
462 const css::uno::Reference<css::frame::XStatusListener>& rxListener,
463 const css::util::URL& rURL)
465 if (rURL.Path != msURLPath)
466 throw RuntimeException();
468 StatusListenerContainer::iterator iListener (
469 ::std::find(
470 maStatusListenerContainer.begin(),
471 maStatusListenerContainer.end(),
472 rxListener));
473 if (iListener != maStatusListenerContainer.end())
474 maStatusListenerContainer.erase(iListener);
477 //----- document::XEventListener ----------------------------------------------
479 void SAL_CALL PresenterProtocolHandler::Dispatch::notifyEvent (
480 const css::document::EventObject&)
482 mpCommand->GetState();
485 //----- lang::XEventListener --------------------------------------------------
487 void SAL_CALL PresenterProtocolHandler::Dispatch::disposing (const css::lang::EventObject&)
489 mbIsListeningToWindowManager = false;
492 //===== GotoPreviousSlideCommand ==============================================
494 GotoPreviousSlideCommand::GotoPreviousSlideCommand (
495 const rtl::Reference<PresenterController>& rpPresenterController)
496 : mpPresenterController(rpPresenterController)
500 void GotoPreviousSlideCommand::Execute()
502 if ( ! mpPresenterController.is())
503 return;
505 if ( ! mpPresenterController->GetSlideShowController().is())
506 return;
508 mpPresenterController->GetSlideShowController()->gotoPreviousSlide();
511 bool GotoPreviousSlideCommand::IsEnabled() const
513 if ( ! mpPresenterController.is())
514 return false;
516 if ( ! mpPresenterController->GetSlideShowController().is())
517 return false;
519 return mpPresenterController->GetSlideShowController()->getCurrentSlideIndex()>0;
522 //===== GotoNextEffect ========================================================
524 GotoNextEffectCommand::GotoNextEffectCommand (
525 const rtl::Reference<PresenterController>& rpPresenterController)
526 : mpPresenterController(rpPresenterController)
530 void GotoNextEffectCommand::Execute()
532 if ( ! mpPresenterController.is())
533 return;
535 if ( ! mpPresenterController->GetSlideShowController().is())
536 return;
538 mpPresenterController->GetSlideShowController()->gotoNextEffect();
541 //===== GotoNextSlide =========================================================
543 GotoNextSlideCommand::GotoNextSlideCommand (
544 const rtl::Reference<PresenterController>& rpPresenterController)
545 : mpPresenterController(rpPresenterController)
549 void GotoNextSlideCommand::Execute()
551 if ( ! mpPresenterController.is())
552 return;
554 if ( ! mpPresenterController->GetSlideShowController().is())
555 return;
557 mpPresenterController->GetSlideShowController()->gotoNextSlide();
560 //===== SwitchMonitorCommand ==============================================
562 SwitchMonitorCommand::SwitchMonitorCommand (
563 const rtl::Reference<PresenterController>& rpPresenterController)
564 : mpPresenterController(rpPresenterController)
568 void SwitchMonitorCommand::Execute()
570 mpPresenterController->SwitchMonitors();
573 RestartTimerCommand::RestartTimerCommand (const rtl::Reference<PresenterController>& rpPresenterController)
574 : mpPresenterController(rpPresenterController)
578 void RestartTimerCommand::Execute()
580 if (IPresentationTime* pPresentationTime = mpPresenterController->GetPresentationTime())
581 pPresentationTime->restart();
584 //===== SetNotesViewCommand ===================================================
586 SetNotesViewCommand::SetNotesViewCommand (
587 const bool bOn,
588 const rtl::Reference<PresenterController>& rpPresenterController)
589 : mbOn(bOn),
590 mpPresenterController(rpPresenterController)
594 void SetNotesViewCommand::Execute()
596 if ( ! mpPresenterController.is())
597 return;
599 ::rtl::Reference<PresenterWindowManager> pWindowManager (
600 mpPresenterController->GetWindowManager());
601 if ( ! pWindowManager.is())
602 return;
604 if (mbOn)
605 pWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
606 else
607 pWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
610 Any SetNotesViewCommand::GetState() const
612 if ( ! mpPresenterController.is())
613 return Any(false);
615 ::rtl::Reference<PresenterWindowManager> pWindowManager (
616 mpPresenterController->GetWindowManager());
617 if ( ! pWindowManager.is())
618 return Any(false);
620 return Any(pWindowManager->GetViewMode() == PresenterWindowManager::VM_Notes);
623 //===== SetSlideSorterCommand =================================================
625 SetSlideSorterCommand::SetSlideSorterCommand (
626 const bool bOn,
627 const rtl::Reference<PresenterController>& rpPresenterController)
628 : mbOn(bOn),
629 mpPresenterController(rpPresenterController)
633 void SetSlideSorterCommand::Execute()
635 if ( ! mpPresenterController.is())
636 return;
638 ::rtl::Reference<PresenterWindowManager> pWindowManager (
639 mpPresenterController->GetWindowManager());
640 if ( ! pWindowManager.is())
641 return;
643 pWindowManager->SetSlideSorterState(mbOn);
646 Any SetSlideSorterCommand::GetState() const
648 if ( ! mpPresenterController.is())
649 return Any(false);
651 ::rtl::Reference<PresenterWindowManager> pWindowManager (
652 mpPresenterController->GetWindowManager());
653 if ( ! pWindowManager.is())
654 return Any(false);
656 return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_SlideOverview);
659 //===== SetHelpViewCommand ===================================================
661 SetHelpViewCommand::SetHelpViewCommand (
662 const bool bOn,
663 const rtl::Reference<PresenterController>& rpPresenterController)
664 : mbOn(bOn),
665 mpPresenterController(rpPresenterController)
669 void SetHelpViewCommand::Execute()
671 if ( ! mpPresenterController.is())
672 return;
674 ::rtl::Reference<PresenterWindowManager> pWindowManager (
675 mpPresenterController->GetWindowManager());
676 if ( ! pWindowManager.is())
677 return;
679 pWindowManager->SetHelpViewState(mbOn);
682 Any SetHelpViewCommand::GetState() const
684 if ( ! mpPresenterController.is())
685 return Any(false);
687 ::rtl::Reference<PresenterWindowManager> pWindowManager (
688 mpPresenterController->GetWindowManager());
689 if ( ! pWindowManager.is())
690 return Any(false);
692 return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_Help);
695 //===== NotesFontSizeCommand ==================================================
697 NotesFontSizeCommand::NotesFontSizeCommand(
698 const rtl::Reference<PresenterController>& rpPresenterController,
699 const sal_Int32 nSizeChange)
700 : mpPresenterController(rpPresenterController),
701 mnSizeChange(nSizeChange)
705 ::rtl::Reference<PresenterNotesView> NotesFontSizeCommand::GetNotesView() const
707 if (mpPresenterController.get() == nullptr)
708 return nullptr;
710 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
711 mpPresenterController->GetPaneContainer()->FindViewURL(
712 PresenterViewFactory::msNotesViewURL));
713 if (pDescriptor.get() == nullptr)
714 return nullptr;
716 return dynamic_cast<PresenterNotesView*>(pDescriptor->mxView.get());
719 void NotesFontSizeCommand::Execute()
721 ::rtl::Reference<PresenterNotesView> pView (GetNotesView());
722 if (pView.is())
723 pView->ChangeFontSize(mnSizeChange);
726 Any NotesFontSizeCommand::GetState() const
728 return Any();
731 } } // end of namespace ::sdext::presenter
733 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */