1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26 
27 #include "PresenterScreen.hxx"
28 #include "PresenterConfigurationAccess.hxx"
29 #include "PresenterController.hxx"
30 #include "PresenterFrameworkObserver.hxx"
31 #include "PresenterHelper.hxx"
32 #include "PresenterPaneContainer.hxx"
33 #include "PresenterPaneFactory.hxx"
34 #include "PresenterViewFactory.hxx"
35 #include "PresenterWindowManager.hxx"
36 #include <com/sun/star/frame/XController.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/drawing/framework/Configuration.hpp>
39 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
40 #include <com/sun/star/drawing/framework/ResourceId.hpp>
41 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
42 #include <com/sun/star/presentation/XSlideShow.hpp>
43 #include <com/sun/star/presentation/XPresentation2.hpp>
44 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
45 #include <com/sun/star/document/XEventBroadcaster.hpp>
46 #include <boost/bind.hpp>
47 #include <tools/debug.hxx>
48 
49 #include <com/sun/star/view/XSelectionSupplier.hpp>
50 
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::presentation;
55 using namespace ::com::sun::star::drawing::framework;
56 using ::rtl::OUString;
57 
58 #define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)))
59 
60 namespace sdext { namespace presenter {
61 
62 namespace {
63     typedef ::cppu::WeakComponentImplHelper1 <
64 		css::document::XEventListener
65         > PresenterScreenListenerInterfaceBase;
66 
67     /** One instance of a PresenterScreenListener is registered per Impress
68         document and waits for the full screen slide show to start and to
69         end.
70     */
71     class PresenterScreenListener
72         : private ::boost::noncopyable,
73           private ::cppu::BaseMutex,
74           public PresenterScreenListenerInterfaceBase
75     {
76     public:
77         PresenterScreenListener (
78             const css::uno::Reference<css::uno::XComponentContext>& rxContext,
79             const css::uno::Reference<css::frame::XModel2>& rxModel);
80         virtual ~PresenterScreenListener (void);
81 
82         void Initialize (void);
83         virtual void SAL_CALL disposing (void);
84 
85         // document::XEventListener
86 
87         virtual void SAL_CALL notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException);
88 
89         // XEventListener
90 
91         virtual void SAL_CALL disposing ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException);
92 
93     private:
94         css::uno::Reference<css::frame::XModel2 > mxModel;
95         css::uno::Reference<css::uno::XComponentContext> mxComponentContext;
96         rtl::Reference<PresenterScreen> mpPresenterScreen;
97 
98         void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException);
99     };
100 }
101 
102 
103 //----- Service ---------------------------------------------------------------
104 
105 OUString PresenterScreenJob::getImplementationName_static (void)
106 {
107     return A2S("com.sun.star.comp.Draw.framework.PresenterScreenJob");
108 }
109 
110 
111 
112 
113 Sequence<OUString> PresenterScreenJob::getSupportedServiceNames_static (void)
114 {
115 	static const ::rtl::OUString sServiceName(
116         A2S("com.sun.star.drawing.framework.PresenterScreenJob"));
117 	return Sequence<rtl::OUString>(&sServiceName, 1);
118 }
119 
120 
121 
122 
123 Reference<XInterface> PresenterScreenJob::Create (const Reference<uno::XComponentContext>& rxContext)
124     SAL_THROW((css::uno::Exception))
125 {
126     return Reference<XInterface>(static_cast<XWeak*>(new PresenterScreenJob(rxContext)));
127 }
128 
129 
130 
131 
132 //===== PresenterScreenJob ====================================================
133 
134 PresenterScreenJob::PresenterScreenJob (const Reference<XComponentContext>& rxContext)
135     : PresenterScreenJobInterfaceBase(m_aMutex),
136       mxComponentContext(rxContext)
137 {
138 }
139 
140 
141 
142 
143 PresenterScreenJob::~PresenterScreenJob (void)
144 {
145 }
146 
147 
148 
149 
150 void SAL_CALL PresenterScreenJob::disposing (void)
151 {
152     mxComponentContext = NULL;
153 }
154 
155 
156 
157 
158 //----- XJob -----------------------------------------------------------
159 
160 Any SAL_CALL PresenterScreenJob::execute(
161     const Sequence< beans::NamedValue >& Arguments )
162     throw (lang::IllegalArgumentException, Exception, RuntimeException)
163 {
164 	Sequence< beans::NamedValue > lEnv;
165 
166     sal_Int32               i = 0;
167     sal_Int32               c = Arguments.getLength();
168     const beans::NamedValue* p = Arguments.getConstArray();
169     for (i=0; i<c; ++i)
170 	{
171         if (p[i].Name.equalsAscii("Environment"))
172         {
173             p[i].Value >>= lEnv;
174             break;
175         }
176 	}
177 
178     Reference<frame::XModel2> xModel;
179     c = lEnv.getLength();
180     p = lEnv.getConstArray();
181     for (i=0; i<c; ++i)
182     {
183         if (p[i].Name.equalsAscii("Model"))
184         {
185             p[i].Value >>= xModel;
186             break;
187         }
188     }
189 
190 	Reference< XServiceInfo > xInfo( xModel, UNO_QUERY );
191 	if( xInfo.is() && xInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) ) )
192 	{
193         // Create a new listener that waits for the full screen presentation
194         // to start and to end.  It takes care of its own lifetime.
195         ::rtl::Reference<PresenterScreenListener> pListener (
196             new PresenterScreenListener(mxComponentContext, xModel));
197         pListener->Initialize();
198 	}
199 
200     return Any();
201 }
202 
203 
204 
205 
206 //===== PresenterScreenListener ===============================================
207 
208 namespace {
209 
210 PresenterScreenListener::PresenterScreenListener (
211     const css::uno::Reference<css::uno::XComponentContext>& rxContext,
212     const css::uno::Reference<css::frame::XModel2>& rxModel)
213     : PresenterScreenListenerInterfaceBase(m_aMutex),
214       mxModel(rxModel),
215       mxComponentContext(rxContext),
216       mpPresenterScreen()
217 {
218 }
219 
220 
221 
222 
223 void PresenterScreenListener::Initialize (void)
224 {
225     Reference< document::XEventListener > xDocListener(
226         static_cast< document::XEventListener* >(this), UNO_QUERY);
227     Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
228     if( xDocBroadcaster.is() )
229         xDocBroadcaster->addEventListener(xDocListener);
230 }
231 
232 
233 
234 
235 PresenterScreenListener::~PresenterScreenListener (void)
236 {
237 }
238 
239 
240 
241 
242 void SAL_CALL PresenterScreenListener::disposing (void)
243 {
244     Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
245     if( xDocBroadcaster.is() )
246         xDocBroadcaster->removeEventListener(
247             Reference<document::XEventListener>(
248                 static_cast<document::XEventListener*>(this), UNO_QUERY));
249 
250     if (mpPresenterScreen.is())
251     {
252         mpPresenterScreen->RequestShutdownPresenterScreen();
253         mpPresenterScreen = NULL;
254     }
255 }
256 
257 
258 
259 
260 // document::XEventListener
261 
262 void SAL_CALL PresenterScreenListener::notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException)
263 {
264     ThrowIfDisposed();
265 
266 	if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnStartPresentation" ) ) )
267 	{
268 		mpPresenterScreen = new PresenterScreen(mxComponentContext, mxModel);
269         mpPresenterScreen->InitializePresenterScreen();
270 	}
271 	else if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnEndPresentation" ) ) )
272 	{
273         if (mpPresenterScreen.is())
274         {
275             mpPresenterScreen->RequestShutdownPresenterScreen();
276             mpPresenterScreen = NULL;
277         }
278 	}
279 }
280 
281 
282 
283 
284 // XEventListener
285 
286 void SAL_CALL PresenterScreenListener::disposing (const css::lang::EventObject& rEvent)
287     throw (css::uno::RuntimeException)
288 {
289     (void)rEvent;
290 
291     if (mpPresenterScreen.is())
292     {
293         mpPresenterScreen->RequestShutdownPresenterScreen();
294         mpPresenterScreen = NULL;
295     }
296 }
297 
298 
299 
300 
301 void PresenterScreenListener::ThrowIfDisposed (void) const throw (
302     ::com::sun::star::lang::DisposedException)
303 {
304 	if (rBHelper.bDisposed || rBHelper.bInDispose)
305 	{
306         throw lang::DisposedException (
307             OUString(RTL_CONSTASCII_USTRINGPARAM(
308                 "PresenterScreenListener object has already been disposed")),
309             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
310     }
311 }
312 
313 } // end of anonymous namespace
314 
315 
316 
317 
318 //===== PresenterScreen =======================================================
319 
320 PresenterScreen::PresenterScreen (
321     const Reference<XComponentContext>& rxContext,
322     const css::uno::Reference<css::frame::XModel2>& rxModel)
323     : PresenterScreenInterfaceBase(m_aMutex),
324 	  mxModel(rxModel),
325       mxController(),
326       mxConfigurationControllerWeak(),
327       mxContextWeak(rxContext),
328       mxSlideShowControllerWeak(),
329       mpPresenterController(),
330       mxSlideShowViewId(),
331       mxSavedConfiguration(),
332       mpPaneContainer(),
333       mnComponentIndex(0),
334       mxPaneFactory(),
335       mxViewFactory(),
336       maViewDescriptors()
337 {
338 }
339 
340 
341 
342 
343 PresenterScreen::~PresenterScreen (void)
344 {
345 }
346 
347 
348 
349 
350 void SAL_CALL PresenterScreen::disposing (void)
351 {
352     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
353     if (xCC.is() && mxSavedConfiguration.is())
354     {
355         xCC->restoreConfiguration(mxSavedConfiguration);
356     }
357     mxConfigurationControllerWeak = Reference<XConfigurationController>(NULL);
358 
359     Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
360     if (xViewFactoryComponent.is())
361        xViewFactoryComponent->dispose();
362     Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
363     if (xPaneFactoryComponent.is())
364         xPaneFactoryComponent->dispose();
365 
366     mxModel = NULL;
367 }
368 
369 
370 
371 
372 //----- XEventListener --------------------------------------------------------
373 
374 void SAL_CALL PresenterScreen::disposing (const lang::EventObject& /*rEvent*/)
375     throw (RuntimeException)
376 {
377 	mxSlideShowControllerWeak = WeakReference<presentation::XSlideShowController>();
378 	RequestShutdownPresenterScreen();
379 }
380 
381 
382 
383 
384 //-----------------------------------------------------------------------------
385 
386 void PresenterScreen::InitializePresenterScreen (void)
387 {
388 	try
389 	{
390 		Reference<XComponentContext> xContext (mxContextWeak);
391         mpPaneContainer =
392             new PresenterPaneContainer(Reference<XComponentContext>(xContext));
393 
394         Reference<XPresentationSupplier> xPS ( mxModel, UNO_QUERY_THROW);
395 		Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW);
396 		Reference<presentation::XSlideShowController> xSlideShowController( xPresentation->getController() );
397         mxSlideShowControllerWeak = xSlideShowController;
398 
399 		if( !xSlideShowController.is() || !xSlideShowController->isFullScreen() )
400 			return;
401 
402 		// find first controller that is not the current controller (the one with the slideshow
403 		mxController = mxModel->getCurrentController();
404 		Reference< container::XEnumeration > xEnum( mxModel->getControllers() );
405 		if( xEnum.is() )
406 		{
407 			while( xEnum->hasMoreElements() )
408 			{
409 				Reference< frame::XController > xC( xEnum->nextElement(), UNO_QUERY );
410 				if( xC.is() && (xC != mxController) )
411 				{
412 					mxController = xC;
413 					break;
414 				}
415 			}
416 		}
417 		// Get the XController from the first argument.
418 		Reference<XControllerManager> xCM(mxController, UNO_QUERY_THROW);
419 
420 		Reference<XConfigurationController> xCC( xCM->getConfigurationController());
421 		mxConfigurationControllerWeak = xCC;
422 
423         Reference<drawing::framework::XResourceId> xMainPaneId(
424             GetMainPaneId(xPresentation));
425         // An empty reference means that the presenter screen can
426         // not or must not be displayed.
427         if ( ! xMainPaneId.is())
428             return;
429 
430 		if (xCC.is() && xContext.is())
431 		{
432 			// Store the current configuration so that we can restore it when
433 			// the presenter view is deactivated.
434 			mxSavedConfiguration = xCC->getRequestedConfiguration();
435 			xCC->lock();
436 
437 			try
438 			{
439                 // At the moment the presenter controller is displayed in its
440                 // own full screen window that is controlled by the same
441                 // configuration controller as the Impress document from
442                 // which the presentation was started.  Therefore the main
443                 // pane is actived additionally to the already existing
444                 // panes and does not replace them.
445 				xCC->requestResourceActivation(
446 					xMainPaneId,
447 					ResourceActivationMode_ADD);
448 				SetupConfiguration(xContext, xMainPaneId);
449 
450 				mpPresenterController = new PresenterController(
451 					xContext,
452 					mxController,
453 					xSlideShowController,
454 					mpPaneContainer,
455 					xMainPaneId);
456 
457 				// Create pane and view factories and integrate them into the
458 				// drawing framework.
459 				SetupPaneFactory(xContext);
460 				SetupViewFactory(xContext);
461 
462                 mpPresenterController->GetWindowManager()->RestoreViewMode();
463 			}
464 			catch (RuntimeException&)
465 			{
466 				xCC->restoreConfiguration(mxSavedConfiguration);
467 			}
468 			xCC->unlock();
469 		}
470 	}
471 	catch (Exception&)
472 	{
473 	}
474 }
475 
476 
477 
478 
479 sal_Int32 PresenterScreen::GetScreenNumber (
480     const Reference<presentation::XPresentation2>& rxPresentation) const
481 {
482     // Determine the screen on which the full screen presentation is being
483     // displayed.
484     sal_Int32 nScreenNumber (0);
485     sal_Int32 nScreenCount (1);
486     try
487     {
488         Reference<beans::XPropertySet> xProperties (rxPresentation, UNO_QUERY);
489         if ( ! xProperties.is())
490             return -1;
491 
492         sal_Int32 nDisplayNumber (-1);
493         if ( ! (xProperties->getPropertyValue(A2S("Display")) >>= nDisplayNumber))
494             return -1;
495         if (nDisplayNumber == -1)
496         {
497             // The special value -1 indicates that the slide show
498             // spans all available displays.  That leaves no room for
499             // the presenter screen.
500             return -1;
501         }
502 
503         Reference<XComponentContext> xContext (mxContextWeak);
504         if ( ! xContext.is())
505             return -1;
506         Reference<lang::XMultiComponentFactory> xFactory (
507             xContext->getServiceManager(), UNO_QUERY);
508         if ( ! xFactory.is())
509             return -1;
510         Reference<beans::XPropertySet> xDisplayProperties (
511             xFactory->createInstanceWithContext(A2S("com.sun.star.awt.DisplayAccess"),xContext),
512             UNO_QUERY);
513         if  ( ! xDisplayProperties.is())
514             return -1;
515 
516         if (nDisplayNumber > 0)
517         {
518             nScreenNumber = nDisplayNumber - 1;
519         }
520         else if (nDisplayNumber == 0)
521         {
522             // A display number value of 0 indicates the primary screen.
523             // Instantiate the DisplayAccess service to find out which
524             // screen number that is.
525             if (nDisplayNumber <= 0 && xDisplayProperties.is())
526                 xDisplayProperties->getPropertyValue(A2S("DefaultDisplay")) >>= nScreenNumber;
527         }
528 
529         // We still have to determine the number of screens to decide
530         // whether the presenter screen may be shown at all.
531         Reference<container::XIndexAccess> xIndexAccess (xDisplayProperties, UNO_QUERY);
532         if ( ! xIndexAccess.is())
533             return -1;
534         nScreenCount = xIndexAccess->getCount();
535 
536         if (nScreenCount < 2 || nDisplayNumber > nScreenCount)
537         {
538             // There is either only one screen or the full screen
539             // presentation spans all available screens.  The presenter
540             // screen is shown only when a special flag in the configuration
541             // is set.
542             PresenterConfigurationAccess aConfiguration (
543                 xContext,
544                 OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
545                 PresenterConfigurationAccess::READ_ONLY);
546             bool bStartAlways (false);
547             if (aConfiguration.GetConfigurationNode(
548                 OUString::createFromAscii("Presenter/StartAlways")) >>= bStartAlways)
549             {
550                 if (bStartAlways)
551                     return nScreenNumber;
552             }
553             return -1;
554         }
555     }
556     catch (beans::UnknownPropertyException&)
557     {
558         OSL_ASSERT(false);
559         // For some reason we can not access the screen number.  Use
560         // the default instead.
561     }
562 
563     return nScreenNumber;
564 }
565 
566 
567 
568 
569 Reference<drawing::framework::XResourceId> PresenterScreen::GetMainPaneId (
570     const Reference<presentation::XPresentation2>& rxPresentation) const
571 {
572     // A negative value means that the presentation spans all available
573     // displays.  That leaves no room for the presenter.
574     const sal_Int32 nScreenNumber(GetScreenNumber(rxPresentation));
575     if (nScreenNumber < 0)
576         return NULL;
577 
578     // Setup the resource id of the full screen background pane so that
579     // it is displayed on another screen than the presentation.
580     sal_Int32 nPresenterScreenNumber (1);
581     switch (nScreenNumber)
582     {
583         case 0:
584             nPresenterScreenNumber = 1;
585             break;
586 
587         case 1:
588             nPresenterScreenNumber = 0;
589             break;
590 
591         default:
592             // When the full screen presentation is displayed on a screen
593             // other than 0 or 1 then place the presenter on the first
594             // available screen.
595             nPresenterScreenNumber = 0;
596             break;
597     }
598 
599     return ResourceId::create(
600         Reference<XComponentContext>(mxContextWeak),
601         PresenterHelper::msFullScreenPaneURL
602             +A2S("?FullScreen=true&ScreenNumber=")
603                 + OUString::valueOf(nPresenterScreenNumber));
604 }
605 
606 
607 
608 
609 void PresenterScreen::RequestShutdownPresenterScreen (void)
610 {
611     // Restore the configuration that was active before the presenter screen
612     // has been activated.  Now, that the presenter screen is displayed in
613     // its own top level window this probably not necessary, but one never knows.
614     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
615     if (xCC.is() && mxSavedConfiguration.is())
616     {
617         xCC->restoreConfiguration(mxSavedConfiguration);
618         mxSavedConfiguration = NULL;
619     }
620 
621     if (xCC.is())
622     {
623         // The actual restoration of the configuration takes place
624         // asynchronously.  The view and pane factories can only by disposed
625         // after that.  Therefore, set up a listener and wait for the
626         // restoration.
627         rtl::Reference<PresenterScreen> pSelf (this);
628         PresenterFrameworkObserver::RunOnUpdateEnd(
629             xCC,
630             ::boost::bind(&PresenterScreen::ShutdownPresenterScreen, pSelf));
631         xCC->update();
632     }
633 }
634 
635 
636 
637 
638 void PresenterScreen::ShutdownPresenterScreen (void)
639 {
640     Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
641     if (xViewFactoryComponent.is())
642         xViewFactoryComponent->dispose();
643     mxViewFactory = NULL;
644 
645     Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
646     if (xPaneFactoryComponent.is())
647         xPaneFactoryComponent->dispose();
648     mxPaneFactory = NULL;
649 
650     if (mpPresenterController.get() != NULL)
651     {
652         mpPresenterController->dispose();
653         mpPresenterController = rtl::Reference<PresenterController>();
654     }
655     mpPaneContainer = new PresenterPaneContainer(Reference<XComponentContext>(mxContextWeak));
656 }
657 
658 
659 
660 
661 void PresenterScreen::SetupPaneFactory (const Reference<XComponentContext>& rxContext)
662 {
663     try
664     {
665         if ( ! mxPaneFactory.is())
666             mxPaneFactory = PresenterPaneFactory::Create(
667                 rxContext,
668                 mxController,
669                 mpPresenterController);
670     }
671     catch (RuntimeException&)
672     {
673         OSL_ASSERT(false);
674     }
675 }
676 
677 
678 
679 
680 void PresenterScreen::SetupViewFactory (const Reference<XComponentContext>& rxContext)
681 {
682     try
683     {
684         if ( ! mxViewFactory.is())
685             mxViewFactory = PresenterViewFactory::Create(
686                 rxContext,
687                 mxController,
688                 mpPresenterController);
689     }
690     catch (RuntimeException&)
691     {
692         OSL_ASSERT(false);
693     }
694 }
695 
696 
697 
698 
699 void PresenterScreen::SetupConfiguration (
700     const Reference<XComponentContext>& rxContext,
701     const Reference<XResourceId>& rxAnchorId)
702 {
703     try
704     {
705         PresenterConfigurationAccess aConfiguration (
706             rxContext,
707             OUString::createFromAscii("org.openoffice.Office.PresenterScreen"),
708             PresenterConfigurationAccess::READ_ONLY);
709         maViewDescriptors.clear();
710         ProcessViewDescriptions(aConfiguration);
711         OUString sLayoutName (OUString::createFromAscii("DefaultLayout"));
712         aConfiguration.GetConfigurationNode(
713             OUString::createFromAscii("Presenter/CurrentLayout")) >>= sLayoutName;
714         ProcessLayout(aConfiguration, sLayoutName, rxContext, rxAnchorId);
715     }
716     catch (RuntimeException&)
717     {
718     }
719 }
720 
721 
722 
723 
724 void PresenterScreen::ProcessLayout (
725     PresenterConfigurationAccess& rConfiguration,
726     const OUString& rsLayoutName,
727     const Reference<XComponentContext>& rxContext,
728     const Reference<XResourceId>& rxAnchorId)
729 {
730     try
731     {
732         Reference<container::XHierarchicalNameAccess> xLayoutNode (
733             rConfiguration.GetConfigurationNode(
734                 OUString::createFromAscii("Presenter/Layouts/")+rsLayoutName),
735             UNO_QUERY_THROW);
736 
737         // Read the parent layout first, if one is referenced.
738         OUString sParentLayout;
739         rConfiguration.GetConfigurationNode(
740             xLayoutNode,
741             OUString::createFromAscii("ParentLayout")) >>= sParentLayout;
742         if (sParentLayout.getLength() > 0)
743         {
744             // Prevent infinite recursion.
745             if (rsLayoutName != sParentLayout)
746                 ProcessLayout(rConfiguration, sParentLayout, rxContext, rxAnchorId);
747         }
748 
749         // Process the actual layout list.
750         Reference<container::XNameAccess> xList (
751             rConfiguration.GetConfigurationNode(
752                 xLayoutNode,
753                 OUString::createFromAscii("Layout")),
754             UNO_QUERY_THROW);
755 
756         ::std::vector<rtl::OUString> aProperties (6);
757         aProperties[0] = OUString::createFromAscii("PaneURL");
758         aProperties[1] = OUString::createFromAscii("ViewURL");
759         aProperties[2] = OUString::createFromAscii("RelativeX");
760         aProperties[3] = OUString::createFromAscii("RelativeY");
761         aProperties[4] = OUString::createFromAscii("RelativeWidth");
762         aProperties[5] = OUString::createFromAscii("RelativeHeight");
763         mnComponentIndex = 1;
764         PresenterConfigurationAccess::ForAll(
765             xList,
766             aProperties,
767             ::boost::bind(&PresenterScreen::ProcessComponent, this,
768                 _1,
769                 _2,
770                 rxContext,
771                 rxAnchorId));
772     }
773     catch (RuntimeException&)
774     {
775     }
776 }
777 
778 
779 
780 
781 void PresenterScreen::ProcessViewDescriptions (
782     PresenterConfigurationAccess& rConfiguration)
783 {
784     try
785     {
786         Reference<container::XNameAccess> xViewDescriptionsNode (
787             rConfiguration.GetConfigurationNode(A2S("Presenter/Views")),
788             UNO_QUERY_THROW);
789 
790         ::std::vector<rtl::OUString> aProperties (4);
791         aProperties[0] = OUString::createFromAscii("ViewURL");
792         aProperties[1] = OUString::createFromAscii("Title");
793         aProperties[2] = OUString::createFromAscii("AccessibleTitle");
794         aProperties[3] = OUString::createFromAscii("IsOpaque");
795         mnComponentIndex = 1;
796         PresenterConfigurationAccess::ForAll(
797             xViewDescriptionsNode,
798             aProperties,
799             ::boost::bind(&PresenterScreen::ProcessViewDescription, this, _1, _2));
800     }
801     catch (RuntimeException&)
802     {
803         OSL_ASSERT(false);
804     }
805 }
806 
807 
808 
809 
810 void PresenterScreen::ProcessComponent (
811     const OUString& rsKey,
812     const ::std::vector<Any>& rValues,
813     const Reference<XComponentContext>& rxContext,
814     const Reference<XResourceId>& rxAnchorId)
815 {
816     (void)rsKey;
817 
818     if (rValues.size() != 6)
819         return;
820 
821     try
822     {
823         OUString sPaneURL;
824         OUString sViewURL;
825         double nX = 0;
826         double nY = 0;
827         double nWidth = 0;
828         double nHeight = 0;
829         rValues[0] >>= sPaneURL;
830         rValues[1] >>= sViewURL;
831         rValues[2] >>= nX;
832         rValues[3] >>= nY;
833         rValues[4] >>= nWidth;
834         rValues[5] >>= nHeight;
835 
836         if (nX>=0 && nY>=0 && nWidth>0 && nHeight>0)
837         {
838             SetupView(
839                 rxContext,
840                 rxAnchorId,
841                 sPaneURL,
842                 sViewURL,
843                 PresenterPaneContainer::ViewInitializationFunction(),
844                 nX,
845                 nY,
846                 nX+nWidth,
847                 nY+nHeight);
848         }
849    	}
850 	catch (Exception& e)
851 	{
852         (void)e;
853         OSL_ASSERT(false);
854 	}
855 }
856 
857 
858 
859 
860 void PresenterScreen::ProcessViewDescription (
861     const OUString& rsKey,
862     const ::std::vector<Any>& rValues)
863 {
864     (void)rsKey;
865 
866     if (rValues.size() != 4)
867         return;
868 
869     try
870     {
871         ViewDescriptor aViewDescriptor;
872         OUString sViewURL;
873         rValues[0] >>= sViewURL;
874         rValues[1] >>= aViewDescriptor.msTitle;
875         rValues[2] >>= aViewDescriptor.msAccessibleTitle;
876         rValues[3] >>= aViewDescriptor.mbIsOpaque;
877         if (aViewDescriptor.msAccessibleTitle.getLength()==0)
878             aViewDescriptor.msAccessibleTitle = aViewDescriptor.msTitle;
879         maViewDescriptors[sViewURL] = aViewDescriptor;
880    	}
881 	catch (Exception&)
882 	{
883         OSL_ASSERT(false);
884 	}
885 }
886 
887 
888 
889 
890 void PresenterScreen::SetupView(
891     const Reference<XComponentContext>& rxContext,
892     const Reference<XResourceId>& rxAnchorId,
893     const OUString& rsPaneURL,
894     const OUString& rsViewURL,
895     const PresenterPaneContainer::ViewInitializationFunction& rViewInitialization,
896     const double nLeft,
897     const double nTop,
898     const double nRight,
899     const double nBottom)
900 {
901     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
902     if (xCC.is())
903     {
904         Reference<XResourceId> xPaneId (ResourceId::createWithAnchor(rxContext,rsPaneURL,rxAnchorId));
905         // Look up the view descriptor.
906         ViewDescriptor aViewDescriptor;
907         ViewDescriptorContainer::const_iterator iDescriptor (maViewDescriptors.find(rsViewURL));
908         if (iDescriptor != maViewDescriptors.end())
909             aViewDescriptor = iDescriptor->second;
910 
911         // Prepare the pane.
912         OSL_ASSERT(mpPaneContainer.get() != NULL);
913         mpPaneContainer->PreparePane(
914             xPaneId,
915             rsViewURL,
916             aViewDescriptor.msTitle,
917             aViewDescriptor.msAccessibleTitle,
918             aViewDescriptor.mbIsOpaque,
919             rViewInitialization,
920             nLeft,
921             nTop,
922             nRight,
923             nBottom);
924     }
925 }
926 
927 
928 
929 
930 } } // end of namespace ::sdext::presenter
931