1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include "PresenterScreen.hxx"
21 #include "PresenterConfigurationAccess.hxx"
22 #include "PresenterController.hxx"
23 #include "PresenterFrameworkObserver.hxx"
24 #include "PresenterHelper.hxx"
25 #include "PresenterPaneContainer.hxx"
26 #include "PresenterPaneFactory.hxx"
27 #include "PresenterViewFactory.hxx"
28 #include "PresenterWindowManager.hxx"
29 #include <com/sun/star/frame/XController.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
32 #include <com/sun/star/drawing/framework/ResourceId.hpp>
33 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
34 #include <com/sun/star/presentation/XPresentation2.hpp>
35 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
36 #include <com/sun/star/document/XEventBroadcaster.hpp>
37 #include <cppuhelper/compbase.hxx>
38 #include <cppuhelper/supportsservice.hxx>
39
40 #include <vcl/svapp.hxx>
41 #include <sal/log.hxx>
42
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::lang;
46 using namespace ::com::sun::star::presentation;
47 using namespace ::com::sun::star::drawing::framework;
48
49 namespace sdext::presenter {
50
51 namespace {
52 typedef ::cppu::WeakComponentImplHelper <
53 css::document::XEventListener
54 > PresenterScreenListenerInterfaceBase;
55
56 /** One instance of a PresenterScreenListener is registered per Impress
57 document and waits for the full screen slide show to start and to
58 end.
59 */
60 class PresenterScreenListener
61 : private ::cppu::BaseMutex,
62 public PresenterScreenListenerInterfaceBase
63 {
64 public:
65 PresenterScreenListener (
66 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
67 const css::uno::Reference<css::frame::XModel2>& rxModel);
68 PresenterScreenListener(const PresenterScreenListener&) = delete;
69 PresenterScreenListener& operator=(const PresenterScreenListener&) = delete;
70
71 void Initialize();
72 virtual void SAL_CALL disposing() override;
73
74 // document::XEventListener
75
76 virtual void SAL_CALL notifyEvent( const css::document::EventObject& Event ) override;
77
78 // XEventListener
79
80 virtual void SAL_CALL disposing ( const css::lang::EventObject& rEvent) override;
81
82 private:
83 css::uno::Reference<css::frame::XModel2 > mxModel;
84 css::uno::Reference<css::uno::XComponentContext> mxComponentContext;
85 rtl::Reference<PresenterScreen> mpPresenterScreen;
86 };
87 }
88
89 //----- XServiceInfo ---------------------------------------------------------------
90
getSupportedServiceNames()91 Sequence< OUString > SAL_CALL PresenterScreenJob::getSupportedServiceNames()
92 {
93 return { };
94 }
95
getImplementationName()96 OUString SAL_CALL PresenterScreenJob::getImplementationName()
97 {
98 return "org.libreoffice.comp.PresenterScreenJob";
99 }
100
supportsService(const OUString & aServiceName)101 sal_Bool SAL_CALL PresenterScreenJob::supportsService(const OUString& aServiceName)
102 {
103 return cppu::supportsService(this, aServiceName);
104 }
105
106
107 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
sdext_PresenterScreenJob_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)108 sdext_PresenterScreenJob_get_implementation(
109 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
110 {
111 return cppu::acquire(new PresenterScreenJob(context));
112 }
113
114
115 //===== PresenterScreenJob ====================================================
116
PresenterScreenJob(const Reference<XComponentContext> & rxContext)117 PresenterScreenJob::PresenterScreenJob (const Reference<XComponentContext>& rxContext)
118 : PresenterScreenJobInterfaceBase(m_aMutex),
119 mxComponentContext(rxContext)
120 {
121 }
122
~PresenterScreenJob()123 PresenterScreenJob::~PresenterScreenJob()
124 {
125 }
126
disposing()127 void SAL_CALL PresenterScreenJob::disposing()
128 {
129 mxComponentContext = nullptr;
130 }
131
132 //----- XJob -----------------------------------------------------------
133
execute(const Sequence<beans::NamedValue> & Arguments)134 Any SAL_CALL PresenterScreenJob::execute(
135 const Sequence< beans::NamedValue >& Arguments )
136 {
137 Sequence< beans::NamedValue > lEnv;
138 auto pArg = std::find_if(Arguments.begin(), Arguments.end(),
139 [](const beans::NamedValue& rArg) { return rArg.Name == "Environment"; });
140 if (pArg != Arguments.end())
141 pArg->Value >>= lEnv;
142
143 Reference<frame::XModel2> xModel;
144 auto pProp = std::find_if(lEnv.begin(), lEnv.end(),
145 [](const beans::NamedValue& rProp) { return rProp.Name == "Model"; });
146 if (pProp != lEnv.end())
147 pProp->Value >>= xModel;
148
149 Reference< XServiceInfo > xInfo( xModel, UNO_QUERY );
150 if( xInfo.is() && xInfo->supportsService("com.sun.star.presentation.PresentationDocument") )
151 {
152 // Create a new listener that waits for the full screen presentation
153 // to start and to end. It takes care of its own lifetime.
154 ::rtl::Reference<PresenterScreenListener> pListener (
155 new PresenterScreenListener(mxComponentContext, xModel));
156 pListener->Initialize();
157 }
158
159 return Any();
160 }
161
162 //===== PresenterScreenListener ===============================================
163
164 namespace {
165
PresenterScreenListener(const css::uno::Reference<css::uno::XComponentContext> & rxContext,const css::uno::Reference<css::frame::XModel2> & rxModel)166 PresenterScreenListener::PresenterScreenListener (
167 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
168 const css::uno::Reference<css::frame::XModel2>& rxModel)
169 : PresenterScreenListenerInterfaceBase(m_aMutex),
170 mxModel(rxModel),
171 mxComponentContext(rxContext),
172 mpPresenterScreen()
173 {
174 }
175
Initialize()176 void PresenterScreenListener::Initialize()
177 {
178 Reference< document::XEventListener > xDocListener(
179 static_cast< document::XEventListener* >(this), UNO_QUERY);
180 Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
181 if( xDocBroadcaster.is() )
182 xDocBroadcaster->addEventListener(xDocListener);
183 }
184
disposing()185 void SAL_CALL PresenterScreenListener::disposing()
186 {
187 Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
188 if( xDocBroadcaster.is() )
189 xDocBroadcaster->removeEventListener(
190 Reference<document::XEventListener>(
191 static_cast<document::XEventListener*>(this), UNO_QUERY));
192
193 if (mpPresenterScreen.is())
194 {
195 mpPresenterScreen->RequestShutdownPresenterScreen();
196 mpPresenterScreen = nullptr;
197 }
198 }
199
200 // document::XEventListener
201
notifyEvent(const css::document::EventObject & Event)202 void SAL_CALL PresenterScreenListener::notifyEvent( const css::document::EventObject& Event )
203 {
204 if (rBHelper.bDisposed || rBHelper.bInDispose)
205 {
206 throw lang::DisposedException (
207 "PresenterScreenListener object has already been disposed",
208 static_cast<uno::XWeak*>(this));
209 }
210
211 if ( Event.EventName == "OnStartPresentation" )
212 {
213 mpPresenterScreen = new PresenterScreen(mxComponentContext, mxModel);
214 if(PresenterScreen::isPresenterScreenEnabled(mxComponentContext))
215 mpPresenterScreen->InitializePresenterScreen();
216 }
217 else if ( Event.EventName == "OnEndPresentation" )
218 {
219 if (mpPresenterScreen.is())
220 {
221 mpPresenterScreen->RequestShutdownPresenterScreen();
222 mpPresenterScreen = nullptr;
223 }
224 }
225 }
226
227 // XEventListener
228
disposing(const css::lang::EventObject &)229 void SAL_CALL PresenterScreenListener::disposing (const css::lang::EventObject&)
230 {
231 if (mpPresenterScreen.is())
232 {
233 mpPresenterScreen->RequestShutdownPresenterScreen();
234 mpPresenterScreen = nullptr;
235 }
236 }
237
238 } // end of anonymous namespace
239
240 //===== PresenterScreen =======================================================
241
PresenterScreen(const Reference<XComponentContext> & rxContext,const css::uno::Reference<css::frame::XModel2> & rxModel)242 PresenterScreen::PresenterScreen (
243 const Reference<XComponentContext>& rxContext,
244 const css::uno::Reference<css::frame::XModel2>& rxModel)
245 : PresenterScreenInterfaceBase(m_aMutex),
246 mxModel(rxModel),
247 mxController(),
248 mxConfigurationControllerWeak(),
249 mxContextWeak(rxContext),
250 mpPresenterController(),
251 mxSavedConfiguration(),
252 mpPaneContainer(),
253 mxPaneFactory(),
254 mxViewFactory(),
255 maViewDescriptors()
256 {
257 }
258
~PresenterScreen()259 PresenterScreen::~PresenterScreen()
260 {
261 }
262
isPresenterScreenEnabled(const css::uno::Reference<css::uno::XComponentContext> & rxContext)263 bool PresenterScreen::isPresenterScreenEnabled(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
264 {
265 bool dEnablePresenterScreen=true;
266 PresenterConfigurationAccess aConfiguration (
267 rxContext,
268 "/org.openoffice.Office.Impress/",
269 PresenterConfigurationAccess::READ_ONLY);
270 aConfiguration.GetConfigurationNode("Misc/Start/EnablePresenterScreen")
271 >>= dEnablePresenterScreen;
272 return dEnablePresenterScreen;
273 }
disposing()274 void SAL_CALL PresenterScreen::disposing()
275 {
276 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
277 if (xCC.is() && mxSavedConfiguration.is())
278 {
279 xCC->restoreConfiguration(mxSavedConfiguration);
280 }
281 mxConfigurationControllerWeak = Reference<XConfigurationController>(nullptr);
282
283 Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
284 if (xViewFactoryComponent.is())
285 xViewFactoryComponent->dispose();
286 Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
287 if (xPaneFactoryComponent.is())
288 xPaneFactoryComponent->dispose();
289
290 mxModel = nullptr;
291 }
292
293 //----- XEventListener --------------------------------------------------------
294
disposing(const lang::EventObject &)295 void SAL_CALL PresenterScreen::disposing (const lang::EventObject& /*rEvent*/)
296 {
297 RequestShutdownPresenterScreen();
298 }
299
300
InitializePresenterScreen()301 void PresenterScreen::InitializePresenterScreen()
302 {
303 try
304 {
305 Reference<XComponentContext> xContext (mxContextWeak);
306 mpPaneContainer = new PresenterPaneContainer(xContext);
307
308 Reference<XPresentationSupplier> xPS ( mxModel, UNO_QUERY_THROW);
309 Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW);
310 Reference<presentation::XSlideShowController> xSlideShowController( xPresentation->getController() );
311
312 if( !xSlideShowController.is() || !xSlideShowController->isFullScreen() )
313 return;
314
315 // find first controller that is not the current controller (the one with the slideshow
316 mxController = mxModel->getCurrentController();
317 Reference< container::XEnumeration > xEnum( mxModel->getControllers() );
318 if( xEnum.is() )
319 {
320 while( xEnum->hasMoreElements() )
321 {
322 Reference< frame::XController > xC( xEnum->nextElement(), UNO_QUERY );
323 if( xC.is() && (xC != mxController) )
324 {
325 mxController = xC;
326 break;
327 }
328 }
329 }
330 // Get the XController from the first argument.
331 Reference<XControllerManager> xCM(mxController, UNO_QUERY_THROW);
332
333 Reference<XConfigurationController> xCC( xCM->getConfigurationController());
334 mxConfigurationControllerWeak = xCC;
335
336 Reference<drawing::framework::XResourceId> xMainPaneId(
337 GetMainPaneId(xPresentation));
338 // An empty reference means that the presenter screen can
339 // not or must not be displayed.
340 if ( ! xMainPaneId.is())
341 return;
342
343 if (xCC.is() && xContext.is())
344 {
345 // Store the current configuration so that we can restore it when
346 // the presenter view is deactivated.
347 mxSavedConfiguration = xCC->getRequestedConfiguration();
348 xCC->lock();
349
350 try
351 {
352 // At the moment the presenter controller is displayed in its
353 // own full screen window that is controlled by the same
354 // configuration controller as the Impress document from
355 // which the presentation was started. Therefore the main
356 // pane is activated additionally to the already existing
357 // panes and does not replace them.
358 xCC->requestResourceActivation(
359 xMainPaneId,
360 ResourceActivationMode_ADD);
361 SetupConfiguration(xContext, xMainPaneId);
362
363 mpPresenterController = new PresenterController(
364 css::uno::WeakReference<css::lang::XEventListener>(this),
365 xContext,
366 mxController,
367 xSlideShowController,
368 mpPaneContainer,
369 xMainPaneId);
370
371 // Create pane and view factories and integrate them into the
372 // drawing framework.
373 SetupPaneFactory(xContext);
374 SetupViewFactory(xContext);
375
376 mpPresenterController->GetWindowManager()->RestoreViewMode();
377 }
378 catch (const RuntimeException&)
379 {
380 xCC->restoreConfiguration(mxSavedConfiguration);
381 }
382 xCC->unlock();
383 }
384 }
385 catch (const Exception&)
386 {
387 }
388 }
389
SwitchMonitors()390 void PresenterScreen::SwitchMonitors()
391 {
392 try {
393 Reference<XPresentationSupplier> xPS ( mxModel, UNO_QUERY_THROW);
394 Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW);
395
396 // Get the existing presenter console screen, we want to switch the
397 // presentation to use that instead.
398 sal_Int32 nNewScreen = GetPresenterScreenNumber (xPresentation);
399 if (nNewScreen < 0)
400 return;
401
402 // Adapt that display number to be the 'default' setting of 0 if it matches
403 sal_Int32 nExternalDisplay = Application::GetDisplayExternalScreen();
404
405 if (nNewScreen == nExternalDisplay)
406 nNewScreen = 0; // screen zero is best == the primary display
407 else
408 nNewScreen++; // otherwise we store screens offset by one.
409
410 // Set the new presentation display
411 Reference<beans::XPropertySet> xProperties (xPresentation, UNO_QUERY_THROW);
412 xProperties->setPropertyValue("Display", Any(nNewScreen));
413 } catch (const uno::Exception &) {
414 }
415 }
416
417 /**
418 * Return the real VCL screen number to show the presenter console
419 * on or -1 to not show anything.
420 */
GetPresenterScreenNumber(const Reference<presentation::XPresentation2> & rxPresentation) const421 sal_Int32 PresenterScreen::GetPresenterScreenNumber (
422 const Reference<presentation::XPresentation2>& rxPresentation) const
423 {
424 sal_Int32 nScreenNumber (0);
425 try
426 {
427 if ( ! rxPresentation.is())
428 return -1;
429
430 // Determine the screen on which the full screen presentation is being
431 // displayed.
432 sal_Int32 nDisplayNumber (-1);
433 if ( ! (rxPresentation->getPropertyValue("Display") >>= nDisplayNumber))
434 return -1;
435 if (nDisplayNumber == -1)
436 {
437 // The special value -1 indicates that the slide show
438 // spans all available displays. That leaves no room for
439 // the presenter screen.
440 return -1;
441 }
442
443 SAL_INFO("sdext.presenter", "Display number is " << nDisplayNumber);
444
445 if (nDisplayNumber > 0)
446 {
447 nScreenNumber = nDisplayNumber - 1;
448 }
449 else if (nDisplayNumber == 0)
450 {
451 // A display number value of 0 indicates the primary screen.
452 // Find out which screen number that is.
453 nScreenNumber = Application::GetDisplayExternalScreen();
454 }
455
456 // We still have to determine the number of screens to decide
457 // whether the presenter screen may be shown at all.
458 sal_Int32 nScreenCount = Application::GetScreenCount();
459
460 if (nScreenCount < 2 || nDisplayNumber > nScreenCount)
461 {
462 // There is either only one screen or the full screen
463 // presentation spans all available screens. The presenter
464 // screen is shown only when a special flag in the configuration
465 // is set.
466 Reference<XComponentContext> xContext (mxContextWeak);
467 PresenterConfigurationAccess aConfiguration (
468 xContext,
469 "/org.openoffice.Office.PresenterScreen/",
470 PresenterConfigurationAccess::READ_ONLY);
471 bool bStartAlways (false);
472 if (aConfiguration.GetConfigurationNode(
473 "Presenter/StartAlways") >>= bStartAlways)
474 {
475 if (bStartAlways)
476 return GetPresenterScreenFromScreen(nScreenNumber);
477 }
478 return -1;
479 }
480 }
481 catch (const beans::UnknownPropertyException&)
482 {
483 OSL_ASSERT(false);
484 // For some reason we can not access the screen number. Use
485 // the default instead.
486 }
487 SAL_INFO("sdext.presenter", "Get presenter screen for screen " << nScreenNumber);
488 return GetPresenterScreenFromScreen(nScreenNumber);
489 }
490
GetPresenterScreenFromScreen(sal_Int32 nPresentationScreen)491 sal_Int32 PresenterScreen::GetPresenterScreenFromScreen( sal_Int32 nPresentationScreen )
492 {
493 // Setup the resource id of the full screen background pane so that
494 // it is displayed on another screen than the presentation.
495 sal_Int32 nPresenterScreenNumber (1);
496 switch (nPresentationScreen)
497 {
498 case 0:
499 nPresenterScreenNumber = 1;
500 break;
501
502 case 1:
503 nPresenterScreenNumber = 0;
504 break;
505
506 default:
507 SAL_INFO("sdext.presenter", "Warning unexpected, out of bound screen "
508 "mapped to 0" << nPresentationScreen);
509 // When the full screen presentation is displayed on a screen
510 // other than 0 or 1 then place the presenter on the first
511 // available screen.
512 nPresenterScreenNumber = 0;
513 break;
514 }
515 return nPresenterScreenNumber;
516 }
517
GetMainPaneId(const Reference<presentation::XPresentation2> & rxPresentation) const518 Reference<drawing::framework::XResourceId> PresenterScreen::GetMainPaneId (
519 const Reference<presentation::XPresentation2>& rxPresentation) const
520 {
521 // A negative value means that the presentation spans all available
522 // displays. That leaves no room for the presenter.
523 const sal_Int32 nScreen(GetPresenterScreenNumber(rxPresentation));
524 if (nScreen < 0)
525 return nullptr;
526
527 return ResourceId::create(
528 Reference<XComponentContext>(mxContextWeak),
529 PresenterHelper::msFullScreenPaneURL
530 + "?FullScreen=true&ScreenNumber="
531 + OUString::number(nScreen));
532 }
533
RequestShutdownPresenterScreen()534 void PresenterScreen::RequestShutdownPresenterScreen()
535 {
536 // Restore the configuration that was active before the presenter screen
537 // has been activated. Now, that the presenter screen is displayed in
538 // its own top level window this probably not necessary, but one never knows.
539 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
540 if (xCC.is() && mxSavedConfiguration.is())
541 {
542 xCC->restoreConfiguration(mxSavedConfiguration);
543 mxSavedConfiguration = nullptr;
544 }
545
546 if (xCC.is())
547 {
548 // The actual restoration of the configuration takes place
549 // asynchronously. The view and pane factories can only by disposed
550 // after that. Therefore, set up a listener and wait for the
551 // restoration.
552 rtl::Reference<PresenterScreen> pSelf (this);
553 PresenterFrameworkObserver::RunOnUpdateEnd(
554 xCC,
555 [pSelf](bool){ return pSelf->ShutdownPresenterScreen(); });
556 xCC->update();
557 }
558 }
559
ShutdownPresenterScreen()560 void PresenterScreen::ShutdownPresenterScreen()
561 {
562 Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
563 if (xViewFactoryComponent.is())
564 xViewFactoryComponent->dispose();
565 mxViewFactory = nullptr;
566
567 Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
568 if (xPaneFactoryComponent.is())
569 xPaneFactoryComponent->dispose();
570 mxPaneFactory = nullptr;
571
572 if (mpPresenterController)
573 {
574 mpPresenterController->dispose();
575 mpPresenterController.clear();
576 }
577 mpPaneContainer = new PresenterPaneContainer(Reference<XComponentContext>(mxContextWeak));
578 }
579
SetupPaneFactory(const Reference<XComponentContext> & rxContext)580 void PresenterScreen::SetupPaneFactory (const Reference<XComponentContext>& rxContext)
581 {
582 try
583 {
584 if ( ! mxPaneFactory.is())
585 mxPaneFactory = PresenterPaneFactory::Create(
586 rxContext,
587 mxController,
588 mpPresenterController);
589 }
590 catch (const RuntimeException&)
591 {
592 OSL_ASSERT(false);
593 }
594 }
595
SetupViewFactory(const Reference<XComponentContext> & rxContext)596 void PresenterScreen::SetupViewFactory (const Reference<XComponentContext>& rxContext)
597 {
598 try
599 {
600 if ( ! mxViewFactory.is())
601 mxViewFactory = PresenterViewFactory::Create(
602 rxContext,
603 mxController,
604 mpPresenterController);
605 }
606 catch (const RuntimeException&)
607 {
608 OSL_ASSERT(false);
609 }
610 }
611
SetupConfiguration(const Reference<XComponentContext> & rxContext,const Reference<XResourceId> & rxAnchorId)612 void PresenterScreen::SetupConfiguration (
613 const Reference<XComponentContext>& rxContext,
614 const Reference<XResourceId>& rxAnchorId)
615 {
616 try
617 {
618 PresenterConfigurationAccess aConfiguration (
619 rxContext,
620 "org.openoffice.Office.PresenterScreen",
621 PresenterConfigurationAccess::READ_ONLY);
622 maViewDescriptors.clear();
623 ProcessViewDescriptions(aConfiguration);
624 OUString sLayoutName ("DefaultLayout");
625 aConfiguration.GetConfigurationNode(
626 "Presenter/CurrentLayout") >>= sLayoutName;
627 ProcessLayout(aConfiguration, sLayoutName, rxContext, rxAnchorId);
628 }
629 catch (const RuntimeException&)
630 {
631 }
632 }
633
ProcessLayout(PresenterConfigurationAccess & rConfiguration,std::u16string_view rsLayoutName,const Reference<XComponentContext> & rxContext,const Reference<XResourceId> & rxAnchorId)634 void PresenterScreen::ProcessLayout (
635 PresenterConfigurationAccess& rConfiguration,
636 std::u16string_view rsLayoutName,
637 const Reference<XComponentContext>& rxContext,
638 const Reference<XResourceId>& rxAnchorId)
639 {
640 try
641 {
642 Reference<container::XHierarchicalNameAccess> xLayoutNode (
643 rConfiguration.GetConfigurationNode(
644 OUString::Concat("Presenter/Layouts/")+rsLayoutName),
645 UNO_QUERY_THROW);
646
647 // Read the parent layout first, if one is referenced.
648 OUString sParentLayout;
649 PresenterConfigurationAccess::GetConfigurationNode(
650 xLayoutNode,
651 "ParentLayout") >>= sParentLayout;
652 if (!sParentLayout.isEmpty())
653 {
654 // Prevent infinite recursion.
655 if (rsLayoutName != sParentLayout)
656 ProcessLayout(rConfiguration, sParentLayout, rxContext, rxAnchorId);
657 }
658
659 // Process the actual layout list.
660 Reference<container::XNameAccess> xList (
661 PresenterConfigurationAccess::GetConfigurationNode(
662 xLayoutNode,
663 "Layout"),
664 UNO_QUERY_THROW);
665
666 ::std::vector<OUString> aProperties
667 {
668 "PaneURL",
669 "ViewURL",
670 "RelativeX",
671 "RelativeY",
672 "RelativeWidth",
673 "RelativeHeight"
674 };
675 PresenterConfigurationAccess::ForAll(
676 xList,
677 aProperties,
678 [this, rxContext, rxAnchorId](std::vector<uno::Any> const& rArgs)
679 {
680 this->ProcessComponent(rArgs, rxContext, rxAnchorId);
681 });
682 }
683 catch (const RuntimeException&)
684 {
685 }
686 }
687
ProcessViewDescriptions(PresenterConfigurationAccess & rConfiguration)688 void PresenterScreen::ProcessViewDescriptions (
689 PresenterConfigurationAccess& rConfiguration)
690 {
691 try
692 {
693 Reference<container::XNameAccess> xViewDescriptionsNode (
694 rConfiguration.GetConfigurationNode("Presenter/Views"),
695 UNO_QUERY_THROW);
696
697 ::std::vector<OUString> aProperties
698 {
699 "ViewURL",
700 "Title",
701 "AccessibleTitle",
702 "IsOpaque"
703 };
704 PresenterConfigurationAccess::ForAll(
705 xViewDescriptionsNode,
706 aProperties,
707 [this](std::vector<uno::Any> const& rArgs)
708 {
709 return this->ProcessViewDescription(rArgs);
710 });
711 }
712 catch (const RuntimeException&)
713 {
714 OSL_ASSERT(false);
715 }
716 }
717
ProcessComponent(const::std::vector<Any> & rValues,const Reference<XComponentContext> & rxContext,const Reference<XResourceId> & rxAnchorId)718 void PresenterScreen::ProcessComponent (
719 const ::std::vector<Any>& rValues,
720 const Reference<XComponentContext>& rxContext,
721 const Reference<XResourceId>& rxAnchorId)
722 {
723 if (rValues.size() != 6)
724 return;
725
726 try
727 {
728 OUString sPaneURL;
729 OUString sViewURL;
730 double nX = 0;
731 double nY = 0;
732 double nWidth = 0;
733 double nHeight = 0;
734 rValues[0] >>= sPaneURL;
735 rValues[1] >>= sViewURL;
736 rValues[2] >>= nX;
737 rValues[3] >>= nY;
738 rValues[4] >>= nWidth;
739 rValues[5] >>= nHeight;
740
741 if (nX>=0 && nY>=0 && nWidth>0 && nHeight>0)
742 {
743 SetupView(
744 rxContext,
745 rxAnchorId,
746 sPaneURL,
747 sViewURL,
748 PresenterPaneContainer::ViewInitializationFunction());
749 }
750 }
751 catch (const Exception&)
752 {
753 OSL_ASSERT(false);
754 }
755 }
756
ProcessViewDescription(const::std::vector<Any> & rValues)757 void PresenterScreen::ProcessViewDescription (
758 const ::std::vector<Any>& rValues)
759 {
760 if (rValues.size() != 4)
761 return;
762
763 try
764 {
765 ViewDescriptor aViewDescriptor;
766 OUString sViewURL;
767 rValues[0] >>= sViewURL;
768 rValues[1] >>= aViewDescriptor.msTitle;
769 rValues[2] >>= aViewDescriptor.msAccessibleTitle;
770 rValues[3] >>= aViewDescriptor.mbIsOpaque;
771 if (aViewDescriptor.msAccessibleTitle.isEmpty())
772 aViewDescriptor.msAccessibleTitle = aViewDescriptor.msTitle;
773 maViewDescriptors[sViewURL] = aViewDescriptor;
774 }
775 catch (const Exception&)
776 {
777 OSL_ASSERT(false);
778 }
779 }
780
SetupView(const Reference<XComponentContext> & rxContext,const Reference<XResourceId> & rxAnchorId,const OUString & rsPaneURL,const OUString & rsViewURL,const PresenterPaneContainer::ViewInitializationFunction & rViewInitialization)781 void PresenterScreen::SetupView(
782 const Reference<XComponentContext>& rxContext,
783 const Reference<XResourceId>& rxAnchorId,
784 const OUString& rsPaneURL,
785 const OUString& rsViewURL,
786 const PresenterPaneContainer::ViewInitializationFunction& rViewInitialization)
787 {
788 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
789 if (!xCC.is())
790 return;
791
792 Reference<XResourceId> xPaneId (ResourceId::createWithAnchor(rxContext,rsPaneURL,rxAnchorId));
793 // Look up the view descriptor.
794 ViewDescriptor aViewDescriptor;
795 ViewDescriptorContainer::const_iterator iDescriptor (maViewDescriptors.find(rsViewURL));
796 if (iDescriptor != maViewDescriptors.end())
797 aViewDescriptor = iDescriptor->second;
798
799 // Prepare the pane.
800 OSL_ASSERT(mpPaneContainer);
801 mpPaneContainer->PreparePane(
802 xPaneId,
803 rsViewURL,
804 aViewDescriptor.msTitle,
805 aViewDescriptor.msAccessibleTitle,
806 aViewDescriptor.mbIsOpaque,
807 rViewInitialization);
808 }
809
810 } // end of namespace ::sdext::presenter
811
812 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
813