/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: PresenterScreen.cxx,v $
 *
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "PresenterScreen.hxx"
#include "PresenterConfigurationAccess.hxx"
#include "PresenterController.hxx"
#include "PresenterFrameworkObserver.hxx"
#include "PresenterHelper.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterViewFactory.hxx"
#include "PresenterWindowManager.hxx"
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/drawing/framework/Configuration.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
#include <com/sun/star/presentation/XSlideShow.hpp>
#include <com/sun/star/presentation/XPresentation2.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <boost/bind.hpp>
#include <tools/debug.hxx>

#include <com/sun/star/view/XSelectionSupplier.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::presentation;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;

#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)))

namespace sdext { namespace presenter {

namespace {
    typedef ::cppu::WeakComponentImplHelper1 <
		css::document::XEventListener
        > PresenterScreenListenerInterfaceBase;

    /** One instance of a PresenterScreenListener is registered per Impress
        document and waits for the full screen slide show to start and to
        end.
    */
    class PresenterScreenListener
        : private ::boost::noncopyable,
          private ::cppu::BaseMutex,
          public PresenterScreenListenerInterfaceBase
    {
    public:
        PresenterScreenListener (
            const css::uno::Reference<css::uno::XComponentContext>& rxContext,
            const css::uno::Reference<css::frame::XModel2>& rxModel);
        virtual ~PresenterScreenListener (void);

        void Initialize (void);
        virtual void SAL_CALL disposing (void);

        // document::XEventListener
        
        virtual void SAL_CALL notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException);

        // XEventListener
    
        virtual void SAL_CALL disposing ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException);

    private:
        css::uno::Reference<css::frame::XModel2 > mxModel;
        css::uno::Reference<css::uno::XComponentContext> mxComponentContext;
        rtl::Reference<PresenterScreen> mpPresenterScreen;

        void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException);
    };
}


//----- Service ---------------------------------------------------------------

OUString PresenterScreenJob::getImplementationName_static (void)
{
    return A2S("com.sun.star.comp.Draw.framework.PresenterScreenJob");
}




Sequence<OUString> PresenterScreenJob::getSupportedServiceNames_static (void)
{
	static const ::rtl::OUString sServiceName(
        A2S("com.sun.star.drawing.framework.PresenterScreenJob"));
	return Sequence<rtl::OUString>(&sServiceName, 1);
}




Reference<XInterface> PresenterScreenJob::Create (const Reference<uno::XComponentContext>& rxContext)
    SAL_THROW((css::uno::Exception))
{
    return Reference<XInterface>(static_cast<XWeak*>(new PresenterScreenJob(rxContext)));
}




//===== PresenterScreenJob ====================================================

PresenterScreenJob::PresenterScreenJob (const Reference<XComponentContext>& rxContext)
    : PresenterScreenJobInterfaceBase(m_aMutex),
      mxComponentContext(rxContext)
{
}




PresenterScreenJob::~PresenterScreenJob (void)
{
}




void SAL_CALL PresenterScreenJob::disposing (void)
{
    mxComponentContext = NULL;
}




//----- XJob -----------------------------------------------------------

Any SAL_CALL PresenterScreenJob::execute(
    const Sequence< beans::NamedValue >& Arguments )
    throw (lang::IllegalArgumentException, Exception, RuntimeException)
{
	Sequence< beans::NamedValue > lEnv;

    sal_Int32               i = 0;
    sal_Int32               c = Arguments.getLength();
    const beans::NamedValue* p = Arguments.getConstArray();
    for (i=0; i<c; ++i)
	{
        if (p[i].Name.equalsAscii("Environment"))
        {
            p[i].Value >>= lEnv;
            break;
        }
	}

    Reference<frame::XModel2> xModel;
    c = lEnv.getLength();
    p = lEnv.getConstArray();
    for (i=0; i<c; ++i)
    {
        if (p[i].Name.equalsAscii("Model"))
        {
            p[i].Value >>= xModel;
            break;
        }
    }

	Reference< XServiceInfo > xInfo( xModel, UNO_QUERY );
	if( xInfo.is() && xInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) ) )
	{
        // Create a new listener that waits for the full screen presentation
        // to start and to end.  It takes care of its own lifetime.
        ::rtl::Reference<PresenterScreenListener> pListener (
            new PresenterScreenListener(mxComponentContext, xModel));
        pListener->Initialize();
	}

    return Any();
}




//===== PresenterScreenListener ===============================================

namespace {

PresenterScreenListener::PresenterScreenListener (
    const css::uno::Reference<css::uno::XComponentContext>& rxContext,
    const css::uno::Reference<css::frame::XModel2>& rxModel)
    : PresenterScreenListenerInterfaceBase(m_aMutex),
      mxModel(rxModel),
      mxComponentContext(rxContext),
      mpPresenterScreen()
{
}




void PresenterScreenListener::Initialize (void)
{
    Reference< document::XEventListener > xDocListener(
        static_cast< document::XEventListener* >(this), UNO_QUERY);
    Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
    if( xDocBroadcaster.is() )
        xDocBroadcaster->addEventListener(xDocListener);
}




PresenterScreenListener::~PresenterScreenListener (void)
{
}




void SAL_CALL PresenterScreenListener::disposing (void)
{
    Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY );
    if( xDocBroadcaster.is() )
        xDocBroadcaster->removeEventListener(
            Reference<document::XEventListener>(
                static_cast<document::XEventListener*>(this), UNO_QUERY));
    
    if (mpPresenterScreen.is())
    {
        mpPresenterScreen->RequestShutdownPresenterScreen();
        mpPresenterScreen = NULL;
    }
}




// document::XEventListener
        
void SAL_CALL PresenterScreenListener::notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException)
{
    ThrowIfDisposed();

	if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnStartPresentation" ) ) )
	{
		mpPresenterScreen = new PresenterScreen(mxComponentContext, mxModel);
        mpPresenterScreen->InitializePresenterScreen();
	}
	else if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnEndPresentation" ) ) )
	{
        if (mpPresenterScreen.is())
        {
            mpPresenterScreen->RequestShutdownPresenterScreen();
            mpPresenterScreen = NULL;
        }
	}
}




// XEventListener
    
void SAL_CALL PresenterScreenListener::disposing (const css::lang::EventObject& rEvent)
    throw (css::uno::RuntimeException)
{
    (void)rEvent;
    
    if (mpPresenterScreen.is())
    {
        mpPresenterScreen->RequestShutdownPresenterScreen();
        mpPresenterScreen = NULL;
    }
}




void PresenterScreenListener::ThrowIfDisposed (void) const throw (
    ::com::sun::star::lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM(
                "PresenterScreenListener object has already been disposed")),
            const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}

} // end of anonymous namespace




//===== PresenterScreen =======================================================

PresenterScreen::PresenterScreen (
    const Reference<XComponentContext>& rxContext,
    const css::uno::Reference<css::frame::XModel2>& rxModel)
    : PresenterScreenInterfaceBase(m_aMutex),
	  mxModel(rxModel),
      mxController(),
      mxConfigurationControllerWeak(),
      mxContextWeak(rxContext),
      mxSlideShowControllerWeak(),
      mpPresenterController(),
      mxSlideShowViewId(),
      mxSavedConfiguration(),
      mpPaneContainer(),
      mnComponentIndex(0),
      mxPaneFactory(),
      mxViewFactory(),
      maViewDescriptors()
{
}




PresenterScreen::~PresenterScreen (void)
{
}




void SAL_CALL PresenterScreen::disposing (void)
{
    Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
    if (xCC.is() && mxSavedConfiguration.is())
    {
        xCC->restoreConfiguration(mxSavedConfiguration);
    }
    mxConfigurationControllerWeak = Reference<XConfigurationController>(NULL);

    Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
    if (xViewFactoryComponent.is())
       xViewFactoryComponent->dispose();
    Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
    if (xPaneFactoryComponent.is())
        xPaneFactoryComponent->dispose();

    mxModel = NULL;
}




//----- XEventListener --------------------------------------------------------

void SAL_CALL PresenterScreen::disposing (const lang::EventObject& /*rEvent*/)
    throw (RuntimeException)
{
	mxSlideShowControllerWeak = WeakReference<presentation::XSlideShowController>();
	RequestShutdownPresenterScreen();
}




//-----------------------------------------------------------------------------

void PresenterScreen::InitializePresenterScreen (void)
{
	try
	{
		Reference<XComponentContext> xContext (mxContextWeak);
        mpPaneContainer =
            new PresenterPaneContainer(Reference<XComponentContext>(xContext));

        Reference<XPresentationSupplier> xPS ( mxModel, UNO_QUERY_THROW);
		Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW);
		Reference<presentation::XSlideShowController> xSlideShowController( xPresentation->getController() );
        mxSlideShowControllerWeak = xSlideShowController;

		if( !xSlideShowController.is() || !xSlideShowController->isFullScreen() )
			return;

		// find first controller that is not the current controller (the one with the slideshow
		mxController = mxModel->getCurrentController();
		Reference< container::XEnumeration > xEnum( mxModel->getControllers() );
		if( xEnum.is() )
		{
			while( xEnum->hasMoreElements() )
			{
				Reference< frame::XController > xC( xEnum->nextElement(), UNO_QUERY );
				if( xC.is() && (xC != mxController) )
				{
					mxController = xC;
					break;
				}
			}
		}
		// Get the XController from the first argument.
		Reference<XControllerManager> xCM(mxController, UNO_QUERY_THROW);

		Reference<XConfigurationController> xCC( xCM->getConfigurationController());
		mxConfigurationControllerWeak = xCC;

		if (xCC.is() && xContext.is())
		{
			// Store the current configuration so that we can restore it when
			// the presenter view is deactivated.
			mxSavedConfiguration = xCC->getRequestedConfiguration();
			xCC->lock();

			try
			{
                Reference<drawing::framework::XResourceId> xMainPaneId(
                    GetMainPaneId(xPresentation));
                // An empty reference means that the presenter screen can
                // not or must not be displayed.
                if ( ! xMainPaneId.is())
                    return;
                
                // At the moment the presenter controller is displayed in its
                // own full screen window that is controlled by the same
                // configuration controller as the Impress document from
                // which the presentation was started.  Therefore the main
                // pane is actived additionally to the already existing
                // panes and does not replace them.
				xCC->requestResourceActivation(
					xMainPaneId,
					ResourceActivationMode_ADD);
				SetupConfiguration(xContext, xMainPaneId);

				mpPresenterController = new PresenterController(
					xContext,
					mxController,
					xSlideShowController,
					mpPaneContainer,
					xMainPaneId);

				// Create pane and view factories and integrate them into the
				// drawing framework.
				SetupPaneFactory(xContext);
				SetupViewFactory(xContext);

                mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
                mpPresenterController->GetWindowManager()->SetLayoutMode(
                    PresenterWindowManager::Standard);
			}
			catch (RuntimeException&)
			{
				xCC->restoreConfiguration(mxSavedConfiguration);
			}
			xCC->unlock();
		}
	}
	catch (Exception&)
	{
	}
}




sal_Int32 PresenterScreen::GetScreenNumber (
    const Reference<presentation::XPresentation2>& rxPresentation) const
{
    // Determine the screen on which the full screen presentation is being
    // displayed.
    sal_Int32 nScreenNumber (0);
    sal_Int32 nScreenCount (1);
    try
    {
        Reference<beans::XPropertySet> xProperties (rxPresentation, UNO_QUERY);
        if ( ! xProperties.is())
            return -1;

        sal_Int32 nDisplayNumber (-1);
        if ( ! (xProperties->getPropertyValue(A2S("Display")) >>= nDisplayNumber))
            return -1;

        Reference<XComponentContext> xContext (mxContextWeak);
        if ( ! xContext.is())
            return -1;
        Reference<lang::XMultiComponentFactory> xFactory (
            xContext->getServiceManager(), UNO_QUERY);
        if ( ! xFactory.is())
            return -1;
        Reference<beans::XPropertySet> xDisplayProperties (
            xFactory->createInstanceWithContext(A2S("com.sun.star.awt.DisplayAccess"),xContext),
            UNO_QUERY);
        if  ( ! xDisplayProperties.is())
            return -1;
        
        if (nDisplayNumber > 0)
        {
            nScreenNumber = nDisplayNumber - 1;
        }
        else if (nDisplayNumber == 0)
        {
            // A display number value of 0 indicates the primary screen.
            // Instantiate the DisplayAccess service to find out which
            // screen number that is.
            if (nDisplayNumber <= 0 && xDisplayProperties.is())
                xDisplayProperties->getPropertyValue(A2S("DefaultDisplay")) >>= nScreenNumber;
        }
        
        // We still have to determine the number of screens to decide
        // whether the presenter screen may be shown at all.
        Reference<container::XIndexAccess> xIndexAccess (xDisplayProperties, UNO_QUERY);
        if ( ! xIndexAccess.is())
            return -1;
        nScreenCount = xIndexAccess->getCount();

        if (nScreenCount < 2 || nDisplayNumber > nScreenCount)
        {
            // There is either only one screen or the full screen
            // presentation spans all available screens.  The presenter
            // screen is shown only when a special flag in the configuration
            // is set.
            PresenterConfigurationAccess aConfiguration (
                xContext,
                OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
                PresenterConfigurationAccess::READ_ONLY);
            bool bStartAlways (false);
            if (aConfiguration.GetConfigurationNode(
                OUString::createFromAscii("Presenter/StartAlways")) >>= bStartAlways)
            {
                if (bStartAlways)
                    return nScreenNumber;
            }
            return -1;
        }
    }
    catch (beans::UnknownPropertyException&)
    {
        OSL_ASSERT(false);
        // For some reason we can not access the screen number.  Use
        // the default instead.
    }

    return nScreenNumber;
}




Reference<drawing::framework::XResourceId> PresenterScreen::GetMainPaneId (
    const Reference<presentation::XPresentation2>& rxPresentation) const
{
    // A negative value means that the presentation spans all available
    // displays.  That leaves no room for the presenter.
    const sal_Int32 nScreenNumber(GetScreenNumber(rxPresentation));
    if (nScreenNumber < 0)
        return NULL;
    
    // Setup the resource id of the full screen background pane so that
    // it is displayed on another screen than the presentation.
    sal_Int32 nPresenterScreenNumber (1);
    switch (nScreenNumber)
    {
        case 0:
            nPresenterScreenNumber = 1;
            break;

        case 1:
            nPresenterScreenNumber = 0;
            break;
            
        default:
            // When the full screen presentation is displayed on a screen
            // other than 0 or 1 then place the presenter on the first
            // available screen.
            nPresenterScreenNumber = 0;
            break;
    }
    
    return ResourceId::create(
        Reference<XComponentContext>(mxContextWeak),
        PresenterHelper::msFullScreenPaneURL
            +A2S("?FullScreen=true&ScreenNumber=")
                + OUString::valueOf(nPresenterScreenNumber));
}




void PresenterScreen::DeactivatePanes (const Reference<XConfigurationController>& rxCC)
{
    OSL_ASSERT(rxCC.is());

    Reference<XComponentContext> xContext (mxContextWeak);
    if ( ! xContext.is())
        return;
    Reference<XResourceId> xCenterPaneId(ResourceId::create(
          xContext,
          PresenterHelper::msCenterPaneURL));
    if ( ! xCenterPaneId.is())
        return;

    Reference<XConfiguration> xCurrentConfiguration (rxCC->getCurrentConfiguration());
    if (xCurrentConfiguration.is())
    {
        // First explicitly deactivate the view in the center pane.  This
        // view is used as marker by some other modules and it is important
        // that its deactivation is requested first.
        const Sequence<Reference<XResourceId> > aViews (xCurrentConfiguration->getResources(
            xCenterPaneId,
            PresenterHelper::msViewURLPrefix,
            AnchorBindingMode_DIRECT));
        for (sal_Int32 nIndex=0; nIndex<aViews.getLength(); ++nIndex)
            rxCC->requestResourceDeactivation(aViews[nIndex]);

        // Now deactivate all top level panes and and all resources anchored
        // to them.
        const Sequence<Reference<XResourceId> > aPanes (xCurrentConfiguration->getResources(
            xCenterPaneId,
            PresenterHelper::msPaneURLPrefix,
            AnchorBindingMode_DIRECT));
        for (sal_Int32 nIndex=0; nIndex<aPanes.getLength(); ++nIndex)
            rxCC->requestResourceDeactivation(aPanes[nIndex]);
    }
}




void PresenterScreen::RequestShutdownPresenterScreen (void)
{
    // Restore the configuration that was active before the presenter screen
    // has been activated.  Now, that the presenter screen is displayed in
    // its own top level window this probably not necessary, but one never knows.
    Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
    if (xCC.is() && mxSavedConfiguration.is())
    {
        xCC->restoreConfiguration(mxSavedConfiguration);
        mxSavedConfiguration = NULL;
    }

    if (xCC.is())
    {
        // The actual restoration of the configuration takes place
        // asynchronously.  The view and pane factories can only by disposed
        // after that.  Therefore, set up a listener and wait for the
        // restoration.
        rtl::Reference<PresenterScreen> pSelf (this);
        PresenterFrameworkObserver::RunOnUpdateEnd(
            xCC,
            ::boost::bind(&PresenterScreen::ShutdownPresenterScreen, pSelf));
        xCC->update();
    }
}




void PresenterScreen::ShutdownPresenterScreen (void)
{
    Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY);
    if (xViewFactoryComponent.is())
        xViewFactoryComponent->dispose();
    mxViewFactory = NULL;
    
    Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY);
    if (xPaneFactoryComponent.is())
        xPaneFactoryComponent->dispose();
    mxPaneFactory = NULL;

    if (mpPresenterController.get() != NULL)
    {
        mpPresenterController->dispose();
        mpPresenterController = rtl::Reference<PresenterController>();
    }
    mpPaneContainer = new PresenterPaneContainer(Reference<XComponentContext>(mxContextWeak));
}




void PresenterScreen::SetupPaneFactory (const Reference<XComponentContext>& rxContext)
{
    try
    {
        if ( ! mxPaneFactory.is())
            mxPaneFactory = PresenterPaneFactory::Create(
                rxContext,
                mxController,
                mpPresenterController);
    }
    catch (RuntimeException&)
    {
        OSL_ASSERT(false);
    }
}




void PresenterScreen::SetupViewFactory (const Reference<XComponentContext>& rxContext)
{
    try
    {
        if ( ! mxViewFactory.is())
            mxViewFactory = PresenterViewFactory::Create(
                rxContext,
                mxController,
                mpPresenterController);
    }
    catch (RuntimeException&)
    {
        OSL_ASSERT(false);
    }
}




void PresenterScreen::SetupConfiguration (
    const Reference<XComponentContext>& rxContext,
    const Reference<XResourceId>& rxAnchorId)
{
    try
    {
        PresenterConfigurationAccess aConfiguration (
            rxContext,
            OUString::createFromAscii("org.openoffice.Office.extension.PresenterScreen"),
            PresenterConfigurationAccess::READ_ONLY);
        maViewDescriptors.clear();
        ProcessViewDescriptions(aConfiguration);
        OUString sLayoutName (OUString::createFromAscii("DefaultLayout"));
        aConfiguration.GetConfigurationNode(
            OUString::createFromAscii("Presenter/CurrentLayout")) >>= sLayoutName;
        ProcessLayout(aConfiguration, sLayoutName, rxContext, rxAnchorId);
    }
    catch (RuntimeException&)
    {
    }    
}




void PresenterScreen::ProcessLayout (
    PresenterConfigurationAccess& rConfiguration,
    const OUString& rsLayoutName,
    const Reference<XComponentContext>& rxContext,
    const Reference<XResourceId>& rxAnchorId)
{
    try
    {
        Reference<container::XHierarchicalNameAccess> xLayoutNode (
            rConfiguration.GetConfigurationNode(
                OUString::createFromAscii("Presenter/Layouts/")+rsLayoutName),
            UNO_QUERY_THROW);

        // Read the parent layout first, if one is referenced.
        OUString sParentLayout;
        rConfiguration.GetConfigurationNode(
            xLayoutNode,
            OUString::createFromAscii("ParentLayout")) >>= sParentLayout;
        if (sParentLayout.getLength() > 0)
        {
            // Prevent infinite recursion.
            if (rsLayoutName != sParentLayout)
                ProcessLayout(rConfiguration, sParentLayout, rxContext, rxAnchorId);
        }

        // Process the actual layout list.
        Reference<container::XNameAccess> xList (
            rConfiguration.GetConfigurationNode(
                xLayoutNode,
                OUString::createFromAscii("Layout")),
            UNO_QUERY_THROW);

        ::std::vector<rtl::OUString> aProperties (6);
        aProperties[0] = OUString::createFromAscii("PaneURL");
        aProperties[1] = OUString::createFromAscii("ViewURL");
        aProperties[2] = OUString::createFromAscii("RelativeX");
        aProperties[3] = OUString::createFromAscii("RelativeY");
        aProperties[4] = OUString::createFromAscii("RelativeWidth");
        aProperties[5] = OUString::createFromAscii("RelativeHeight");
        mnComponentIndex = 1;
        PresenterConfigurationAccess::ForAll(
            xList,
            aProperties,
            ::boost::bind(&PresenterScreen::ProcessComponent, this,
                _1,
                _2,
                rxContext,
                rxAnchorId));
    }
    catch (RuntimeException&)
    {
    }    
}




void PresenterScreen::ProcessViewDescriptions (
    PresenterConfigurationAccess& rConfiguration)
{
    try
    {
        Reference<container::XNameAccess> xViewDescriptionsNode (
            rConfiguration.GetConfigurationNode(A2S("Presenter/Views")),
            UNO_QUERY_THROW);

        ::std::vector<rtl::OUString> aProperties (3);
        aProperties[0] = OUString::createFromAscii("ViewURL");
        aProperties[1] = OUString::createFromAscii("Title");
        aProperties[2] = OUString::createFromAscii("IsOpaque");
        mnComponentIndex = 1;
        PresenterConfigurationAccess::ForAll(
            xViewDescriptionsNode,
            aProperties,
            ::boost::bind(&PresenterScreen::ProcessViewDescription, this, _1, _2));
    }
    catch (RuntimeException&)
    {
        OSL_ASSERT(false);
    }    
}




void PresenterScreen::ProcessComponent (
    const OUString& rsKey,
    const ::std::vector<Any>& rValues,
    const Reference<XComponentContext>& rxContext,
    const Reference<XResourceId>& rxAnchorId)
{
    (void)rsKey;

    if (rValues.size() != 6)
        return;

    try
    {
        OUString sPaneURL;
        OUString sViewURL;
        double nX = 0;
        double nY = 0;
        double nWidth = 0;
        double nHeight = 0;
        rValues[0] >>= sPaneURL;
        rValues[1] >>= sViewURL;
        rValues[2] >>= nX;
        rValues[3] >>= nY;
        rValues[4] >>= nWidth;
        rValues[5] >>= nHeight;

        if (nX>=0 && nY>=0 && nWidth>0 && nHeight>0)
        {
            SetupView(
                rxContext,
                rxAnchorId,
                sPaneURL,
                sViewURL,
                PresenterPaneContainer::ViewInitializationFunction(),
                nX,
                nY,
                nX+nWidth,
                nY+nHeight);
        }
   	}
	catch (Exception& e)
	{
        (void)e;
        OSL_ASSERT(false);
	}
}




void PresenterScreen::ProcessViewDescription (
    const OUString& rsKey,
    const ::std::vector<Any>& rValues)
{
    (void)rsKey;

    if (rValues.size() != 3)
        return;

    try
    {
        ViewDescriptor aViewDescriptor;
        OUString sViewURL;
        rValues[0] >>= sViewURL;
        rValues[1] >>= aViewDescriptor.msTitle;
        rValues[2] >>= aViewDescriptor.mbIsOpaque;
        maViewDescriptors[sViewURL] = aViewDescriptor;
   	}
	catch (Exception&)
	{
        OSL_ASSERT(false);
	}
}




void PresenterScreen::SetupView(
    const Reference<XComponentContext>& rxContext,
    const Reference<XResourceId>& rxAnchorId,
    const OUString& rsPaneURL,
    const OUString& rsViewURL,
    const PresenterPaneContainer::ViewInitializationFunction& rViewInitialization,
    const double nLeft,
    const double nTop,
    const double nRight,
    const double nBottom)
{
    Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
    if (xCC.is())
    {
        Reference<XResourceId> xPaneId (ResourceId::createWithAnchor(rxContext,rsPaneURL,rxAnchorId));
        // Look up the view descriptor.
        ViewDescriptor aViewDescriptor;
        ViewDescriptorContainer::const_iterator iDescriptor (maViewDescriptors.find(rsViewURL));
        if (iDescriptor != maViewDescriptors.end())
            aViewDescriptor = iDescriptor->second;

        // Prepare the pane.
        OSL_ASSERT(mpPaneContainer.get() != NULL);
        mpPaneContainer->PreparePane(
            xPaneId,
            rsViewURL,
            aViewDescriptor.msTitle,
            aViewDescriptor.mbIsOpaque,
            rViewInitialization,
            nLeft,
            nTop,
            nRight,
            nBottom);
    }
}




void PresenterScreen::ThrowIfDisposed (void) const
    throw (::com::sun::star::lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM(
                "PresenterScreen object has already been disposed")),
            const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}


    
} } // end of namespace ::sdext::presenter
