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