/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



#include "precompiled_sdext.hxx"

#include "PresenterAccessibility.hxx"
#include "PresenterTextView.hxx"
#include "PresenterConfigurationAccess.hxx"
#include "PresenterNotesView.hxx"
#include "PresenterPaneBase.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterViewFactory.hxx"

#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
#include <com/sun/star/accessibility/XAccessibleContext.hpp>
#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <com/sun/star/drawing/framework/XPane.hpp>
#include <com/sun/star/drawing/framework/XView.hpp>
#include <cppuhelper/compbase1.hxx>
#include <cppuhelper/compbase5.hxx>
#include <cppuhelper/implbase1.hxx>
#include <boost/bind.hpp>

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

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

#define VERBOSE

//===== PresenterAccessibleObject =============================================

namespace sdext { namespace presenter {

namespace {
	typedef ::cppu::WeakComponentImplHelper5 <
		cssa::XAccessible,
		cssa::XAccessibleContext,
		cssa::XAccessibleComponent,
		cssa::XAccessibleEventBroadcaster,
		css::awt::XWindowListener
	> PresenterAccessibleObjectInterfaceBase;
}

class PresenterAccessible::AccessibleObject
	: public ::cppu::BaseMutex,
	  public PresenterAccessibleObjectInterfaceBase
{
public:
	AccessibleObject (
		const css::lang::Locale aLocale,
		const sal_Int16 nRole,
		const ::rtl::OUString& rsName);
	void LateInitialization (void);

	virtual ~AccessibleObject (void);

	virtual void SetWindow (
		const cssu::Reference<css::awt::XWindow>& rxContentWindow,
		const cssu::Reference<css::awt::XWindow>& rxBorderWindow);
	void SetAccessibleParent (const cssu::Reference<cssa::XAccessible>& rxAccessibleParent);

	virtual void SAL_CALL disposing (void);

	void NotifyCurrentSlideChange (const sal_Int32 nCurrentSlideIndex);

	void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild);
	void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild);

	void SetIsFocused (const bool bIsFocused);
	void SetAccessibleName (const ::rtl::OUString& rsName);

	void FireAccessibleEvent (
		const sal_Int16 nEventId,
		const cssu::Any& rOldValue,
		const cssu::Any& rNewValue);

	void UpdateStateSet (void);


	//----- XAccessible -------------------------------------------------------

	virtual cssu::Reference<cssa::XAccessibleContext> SAL_CALL
		getAccessibleContext (void)
		throw (cssu::RuntimeException);


	//----- XAccessibleContext ------------------------------------------------

	virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
		throw (cssu::RuntimeException);

	virtual cssu::Reference< cssa::XAccessible> SAL_CALL
		getAccessibleChild (sal_Int32 nIndex)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual cssu::Reference< cssa::XAccessible> SAL_CALL getAccessibleParent (void)
		throw (cssu::RuntimeException);

	virtual	sal_Int32 SAL_CALL getAccessibleIndexInParent (void)
		throw (cssu::RuntimeException);

	virtual sal_Int16 SAL_CALL getAccessibleRole (void)
		throw (cssu::RuntimeException);

	virtual ::rtl::OUString SAL_CALL getAccessibleDescription (void)
		throw (cssu::RuntimeException);

	virtual ::rtl::OUString SAL_CALL getAccessibleName (void)
		throw (cssu::RuntimeException);

	virtual cssu::Reference<cssa::XAccessibleRelationSet> SAL_CALL
		getAccessibleRelationSet (void)
		throw (cssu::RuntimeException);

	virtual cssu::Reference<cssa::XAccessibleStateSet> SAL_CALL
		getAccessibleStateSet (void)
		throw (cssu::RuntimeException);

	virtual css::lang::Locale SAL_CALL getLocale (void)
		throw (cssu::RuntimeException,
			cssa::IllegalAccessibleComponentStateException);


	//----- XAccessibleComponent ----------------------------------------------

	virtual sal_Bool SAL_CALL containsPoint (
		const css::awt::Point& aPoint)
		throw (cssu::RuntimeException);

	virtual cssu::Reference<cssa::XAccessible> SAL_CALL
		getAccessibleAtPoint (
			const css::awt::Point& aPoint)
		throw (cssu::RuntimeException);

	virtual css::awt::Rectangle SAL_CALL getBounds (void)
		throw (cssu::RuntimeException);

	virtual css::awt::Point SAL_CALL getLocation (void)
		throw (cssu::RuntimeException);

	virtual css::awt::Point SAL_CALL getLocationOnScreen (void)
		throw (cssu::RuntimeException);

	virtual css::awt::Size SAL_CALL getSize (void)
		throw (cssu::RuntimeException);

	virtual void SAL_CALL grabFocus (void)
		throw (cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getForeground (void)
		throw (cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getBackground (void)
		throw (cssu::RuntimeException);


	//----- XAccessibleEventBroadcaster ---------------------------------------

	virtual void SAL_CALL addEventListener (
			const cssu::Reference<cssa::XAccessibleEventListener>& rxListener)
		throw (cssu::RuntimeException);

	virtual void SAL_CALL removeEventListener (
			const cssu::Reference<cssa::XAccessibleEventListener>& rxListener)
		throw (cssu::RuntimeException);

	using PresenterAccessibleObjectInterfaceBase::addEventListener;
	using PresenterAccessibleObjectInterfaceBase::removeEventListener;

	//----- XWindowListener ---------------------------------------------------

	virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent)
		throw (cssu::RuntimeException);

	virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent)
		throw (cssu::RuntimeException);

	virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent)
		throw (cssu::RuntimeException);

	virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent)
		throw (cssu::RuntimeException);


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

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


protected:
	::rtl::OUString msName;
	cssu::Reference<css::awt::XWindow2> mxContentWindow;
	cssu::Reference<css::awt::XWindow2> mxBorderWindow;
	const css::lang::Locale maLocale;
	const sal_Int16 mnRole;
	sal_uInt32 mnStateSet;
	bool mbIsFocused;
	cssu::Reference<cssa::XAccessible> mxParentAccessible;
	::std::vector<rtl::Reference<AccessibleObject> > maChildren;
	::std::vector<Reference<XAccessibleEventListener> > maListeners;

	virtual awt::Point GetRelativeLocation (void);
	virtual awt::Size GetSize (void);
	virtual awt::Point GetAbsoluteParentLocation (void);

	virtual bool GetWindowState (const sal_Int16 nType) const;

	void UpdateState (const sal_Int16 aState, const bool bValue);

	sal_Bool IsDisposed (void) const;

	void ThrowIfDisposed (void) const
		throw (css::lang::DisposedException);

	enum ExceptionType { ET_Runtime, ET_Disposed, ET_IndexOutOfBounds };
	void ThrowException (const sal_Char* pMessage, const ExceptionType eExceptionType) const;
};




//===== AccessibleStateSet ====================================================

namespace {
typedef ::cppu::WeakComponentImplHelper1 <
	cssa::XAccessibleStateSet
	> AccessibleStateSetInterfaceBase;
}

class AccessibleStateSet
	: public ::cppu::BaseMutex,
	  public AccessibleStateSetInterfaceBase
{
public:
	AccessibleStateSet (const sal_Int32 nStateSet);
	virtual ~AccessibleStateSet (void);

	static sal_uInt32 GetStateMask (const sal_Int16 nType);

	//----- XAccessibleStateSet -----------------------------------------------

	virtual sal_Bool SAL_CALL isEmpty (void)
		throw (cssu::RuntimeException);

	virtual sal_Bool SAL_CALL contains (sal_Int16 nState)
		throw (cssu::RuntimeException);

	virtual sal_Bool SAL_CALL containsAll (const cssu::Sequence<sal_Int16>& rStateSet)
		throw (cssu::RuntimeException);

	virtual cssu::Sequence<sal_Int16> SAL_CALL getStates (void)
		throw (cssu::RuntimeException);

private:
	const sal_Int32 mnStateSet;
};




//===== AccessibleRelationSet =================================================

namespace {
typedef ::cppu::WeakComponentImplHelper1 <
	cssa::XAccessibleRelationSet
	> AccessibleRelationSetInterfaceBase;
}

class AccessibleRelationSet
	: public ::cppu::BaseMutex,
	  public AccessibleRelationSetInterfaceBase
{
public:
	AccessibleRelationSet (void);
	virtual ~AccessibleRelationSet (void);

	void AddRelation (
		const sal_Int16 nRelationType,
		const Reference<XInterface>& rxObject);


	//----- XAccessibleRelationSet --------------------------------------------

	virtual sal_Int32 SAL_CALL getRelationCount (void)
		throw (cssu::RuntimeException);

	virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex)
		throw (cssu::RuntimeException, css::lang::IndexOutOfBoundsException);

	virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType)
		throw (cssu::RuntimeException);

	virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType)
		throw (cssu::RuntimeException);

private:
	::std::vector<AccessibleRelation> maRelations;
};




//===== PresenterAccessibleParagraph ==========================================

namespace {
typedef ::cppu::ImplInheritanceHelper1 <
	PresenterAccessible::AccessibleObject,
	cssa::XAccessibleText
	> PresenterAccessibleParagraphInterfaceBase;
}




class PresenterAccessible::AccessibleParagraph
	: public PresenterAccessibleParagraphInterfaceBase
{
public:
	AccessibleParagraph (
		const css::lang::Locale aLocale,
		const sal_Int16 nRole,
		const ::rtl::OUString& rsName,
		const SharedPresenterTextParagraph& rpParagraph,
		const sal_Int32 nParagraphIndex);

	virtual ~AccessibleParagraph (void);


	//----- XAccessibleContext ------------------------------------------------

	virtual cssu::Reference<cssa::XAccessibleRelationSet> SAL_CALL
		getAccessibleRelationSet (void)
		throw (cssu::RuntimeException);


	//----- XAccessibleText ---------------------------------------------------

	virtual sal_Int32 SAL_CALL getCaretPosition (void)
		throw (cssu::RuntimeException);

	virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex)
		throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex)
		throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual cssu::Sequence<css::beans::PropertyValue> SAL_CALL
		getCharacterAttributes (
			::sal_Int32 nIndex,
			const cssu::Sequence<rtl::OUString>& rRequestedAttributes)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getCharacterCount (void)
		throw (cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint)
		throw (cssu::RuntimeException);

	virtual ::rtl::OUString SAL_CALL getSelectedText (void)
		throw (cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getSelectionStart (void)
		throw (cssu::RuntimeException);

	virtual sal_Int32 SAL_CALL getSelectionEnd (void)
		throw (cssu::RuntimeException);

	virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual ::rtl::OUString SAL_CALL getText (void)
		throw (cssu::RuntimeException);

	virtual ::rtl::OUString SAL_CALL getTextRange (
		sal_Int32 nStartIndex,
		sal_Int32 nEndIndex)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);

	virtual cssa::TextSegment SAL_CALL getTextAtIndex (
		sal_Int32 nIndex,
		sal_Int16 nTextType)
		throw (css::lang::IndexOutOfBoundsException,
			css::lang::IllegalArgumentException,
			cssu::RuntimeException);

	virtual cssa::TextSegment SAL_CALL getTextBeforeIndex (
		sal_Int32 nIndex,
		sal_Int16 nTextType)
		throw (css::lang::IndexOutOfBoundsException,
			css::lang::IllegalArgumentException,
			cssu::RuntimeException);

	virtual cssa::TextSegment SAL_CALL getTextBehindIndex (
		sal_Int32 nIndex,
		sal_Int16 nTextType)
		throw (css::lang::IndexOutOfBoundsException,
			css::lang::IllegalArgumentException,
			cssu::RuntimeException);

	virtual ::sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex)
		throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException);


protected:
	virtual awt::Point GetRelativeLocation (void);
	virtual awt::Size GetSize (void);
	virtual awt::Point GetAbsoluteParentLocation (void);
	virtual bool GetWindowState (const sal_Int16 nType) const;

private:
	SharedPresenterTextParagraph mpParagraph;
	const sal_Int32 mnParagraphIndex;
};




//===== AccessibleConsole =====================================================

class AccessibleConsole
{
public:
	static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
		const css::uno::Reference<css::uno::XComponentContext>& rxContext,
		const lang::Locale aLocale)
	{
		OUString sName (A2S("Presenter Console"));
		PresenterConfigurationAccess aConfiguration (
			rxContext,
			OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
			PresenterConfigurationAccess::READ_ONLY);
		aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Console/String"))
			>>= sName;

		rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
			new PresenterAccessible::AccessibleObject(
				aLocale, AccessibleRole::PANEL, sName));
		pObject->LateInitialization();
		pObject->UpdateStateSet();

		return pObject;
	}
};




//===== AccessiblePreview =====================================================

class AccessiblePreview
{
public:
	static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
		const Reference<css::uno::XComponentContext>& rxContext,
		const lang::Locale aLocale,
		const Reference<awt::XWindow>& rxContentWindow,
		const Reference<awt::XWindow>& rxBorderWindow)
	{
		OUString sName (A2S("Presenter Notes Window"));
		{
			PresenterConfigurationAccess aConfiguration (
				rxContext,
				OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
				PresenterConfigurationAccess::READ_ONLY);
			aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Preview/String"))
				>>= sName;
		}

		rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
			new PresenterAccessible::AccessibleObject(
				aLocale,
				AccessibleRole::LABEL,
				sName));
		pObject->LateInitialization();
		pObject->UpdateStateSet();
		pObject->SetWindow(rxContentWindow, rxBorderWindow);

		return pObject;
	}
};




//===== AccessibleNotes =======================================================

class AccessibleNotes : public PresenterAccessible::AccessibleObject
{
public:
	AccessibleNotes (
		const css::lang::Locale aLocale,
		const sal_Int16 nRole,
		const ::rtl::OUString& rsName);


	static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
		const css::uno::Reference<css::uno::XComponentContext>& rxContext,
		const lang::Locale aLocale,
		const Reference<awt::XWindow>& rxContentWindow,
		const Reference<awt::XWindow>& rxBorderWindow,
		const ::boost::shared_ptr<PresenterTextView>& rpTextView);

	void SetTextView (const ::boost::shared_ptr<PresenterTextView>& rpTextView);

	virtual void SetWindow (
		const cssu::Reference<css::awt::XWindow>& rxContentWindow,
		const cssu::Reference<css::awt::XWindow>& rxBorderWindow);

private:
	::boost::shared_ptr<PresenterTextView> mpTextView;

	void NotifyCaretChange (
		const sal_Int32 nOldParagraphIndex,
		const sal_Int32 nOldCharacterIndex,
		const sal_Int32 nNewParagraphIndex,
		const sal_Int32 nNewCharacterIndex);
	void HandleTextChange (void);
};




//===== AccessibleFocusManager ================================================

/** A singleton class that makes sure that only one accessibility object in
    the PresenterConsole hierarchy has the focus.
*/
class AccessibleFocusManager
{
public:
	static ::boost::shared_ptr<AccessibleFocusManager> Instance (void);

	void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
	void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);

	void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);

private:
	static ::boost::shared_ptr<AccessibleFocusManager> mpInstance;
	::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects;

	AccessibleFocusManager (void);
};




//===== PresenterAccessible ===================================================

PresenterAccessible::PresenterAccessible (
	const css::uno::Reference<css::uno::XComponentContext>& rxContext,
	const ::rtl::Reference<PresenterController>& rpPresenterController,
	const Reference<drawing::framework::XPane>& rxMainPane)
	: PresenterAccessibleInterfaceBase(m_aMutex),
	  mxComponentContext(rxContext),
	  mpPresenterController(rpPresenterController),
	  mxMainPaneId(rxMainPane.is() ? rxMainPane->getResourceId() : Reference<XResourceId>()),
	  mxMainPane(rxMainPane, UNO_QUERY),
	  mxMainWindow(),
	  mxPreviewContentWindow(),
	  mxPreviewBorderWindow(),
	  mxNotesContentWindow(),
	  mxNotesBorderWindow(),
	  mpAccessibleConsole(),
	  mpAccessiblePreview(),
	  mpAccessibleNotes(),
	  mxAccessibleParent()
{
	if (mxMainPane.is())
		mxMainPane->setAccessible(this);
}




PresenterAccessible::~PresenterAccessible (void)
{
}




PresenterPaneContainer::SharedPaneDescriptor PresenterAccessible::GetPreviewPane (void) const
{
	PresenterPaneContainer::SharedPaneDescriptor pPreviewPane;

	if ( ! mpPresenterController.is())
		return pPreviewPane;

	rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer());
	if ( ! pContainer.is())
		return pPreviewPane;

	pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
	Reference<drawing::framework::XPane> xPreviewPane;
	if (pPreviewPane)
		xPreviewPane = pPreviewPane->mxPane.get();
	if ( ! xPreviewPane.is())
	{
		pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL);
	}
	return pPreviewPane;
}




void PresenterAccessible::UpdateAccessibilityHierarchy (void)
{
	if ( ! mpPresenterController.is())
		return;

	Reference<drawing::framework::XConfigurationController> xConfigurationController(
		mpPresenterController->GetConfigurationController());
	if ( ! xConfigurationController.is())
		return;

	rtl::Reference<PresenterPaneContainer> pPaneContainer (
		mpPresenterController->GetPaneContainer());
	if ( ! pPaneContainer.is())
		return;

	if ( ! mpAccessibleConsole.is())
		return;

	// Get the preview pane (standard or notes view) or the slide overview
	// pane.
	PresenterPaneContainer::SharedPaneDescriptor pPreviewPane(GetPreviewPane());
	Reference<drawing::framework::XPane> xPreviewPane;
	if (pPreviewPane)
		xPreviewPane = pPreviewPane->mxPane.get();

	// Get the notes pane.
	PresenterPaneContainer::SharedPaneDescriptor pNotesPane(
		pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
	Reference<drawing::framework::XPane> xNotesPane;
	if (pNotesPane)
		xNotesPane = pNotesPane->mxPane.get();

	// Get the notes view.
	Reference<drawing::framework::XView> xNotesView;
	if (pNotesPane)
		xNotesView = pNotesPane->mxView;
	rtl::Reference<PresenterNotesView> pNotesView (
		dynamic_cast<PresenterNotesView*>(xNotesView.get()));

	UpdateAccessibilityHierarchy(
		pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(),
		pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(),
		(pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(),
		pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(),
		pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(),
		pNotesView.is()
			? pNotesView->GetTextView()
			: ::boost::shared_ptr<PresenterTextView>());
}





void PresenterAccessible::UpdateAccessibilityHierarchy (
	const Reference<awt::XWindow>& rxPreviewContentWindow,
	const Reference<awt::XWindow>& rxPreviewBorderWindow,
	const ::rtl::OUString& rsTitle,
	const Reference<awt::XWindow>& rxNotesContentWindow,
	const Reference<awt::XWindow>& rxNotesBorderWindow,
	const ::boost::shared_ptr<PresenterTextView>& rpNotesTextView)
{
	if ( ! mpAccessibleConsole.is())
		return;

	if (mxPreviewContentWindow != rxPreviewContentWindow)
	{
		if (mpAccessiblePreview.is())
		{
			mpAccessibleConsole->RemoveChild(mpAccessiblePreview);
			mpAccessiblePreview = NULL;
		}

		mxPreviewContentWindow = rxPreviewContentWindow;
		mxPreviewBorderWindow = rxPreviewBorderWindow;

		if (mxPreviewContentWindow.is())
		{
			mpAccessiblePreview = AccessiblePreview::Create(
				mxComponentContext,
				lang::Locale(),
				mxPreviewContentWindow,
				mxPreviewBorderWindow);
			mpAccessibleConsole->AddChild(mpAccessiblePreview);
			mpAccessiblePreview->SetAccessibleName(rsTitle);
		}
	}

	if (mxNotesContentWindow != rxNotesContentWindow)
	{
		if (mpAccessibleNotes.is())
		{
			mpAccessibleConsole->RemoveChild(mpAccessibleConsole.get());
			mpAccessibleNotes = NULL;
		}

		mxNotesContentWindow = rxNotesContentWindow;
		mxNotesBorderWindow = rxNotesBorderWindow;

		if (mxNotesContentWindow.is())
		{
			mpAccessibleNotes = AccessibleNotes::Create(
				mxComponentContext,
				lang::Locale(),
				mxNotesContentWindow,
				mxNotesBorderWindow,
				rpNotesTextView);
			mpAccessibleConsole->AddChild(mpAccessibleNotes.get());
		}
	}
}




void PresenterAccessible::NotifyCurrentSlideChange (
	const sal_Int32 nCurrentSlideIndex,
	const sal_Int32 nSlideCount)
{
	(void)nCurrentSlideIndex;
	(void)nSlideCount;

	if (mpAccessiblePreview.is())
	{
		PresenterPaneContainer::SharedPaneDescriptor pPreviewPane (GetPreviewPane());
		mpAccessiblePreview->SetAccessibleName(
			(pPreviewPane&&pPreviewPane->mxPane.is()
				? pPreviewPane->mxPane->GetTitle()
				: rtl::OUString()));
	}

	// Play some focus ping-pong to trigger AT tools.
	//AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
	AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview);
}




bool PresenterAccessible::IsAccessibilityActive (void) const
{
	return mpAccessibleConsole.is();
}




void SAL_CALL PresenterAccessible::disposing (void)
{
	UpdateAccessibilityHierarchy(
		NULL,
		NULL,
		OUString(),
		NULL,
		NULL,
		::boost::shared_ptr<PresenterTextView>());

	if (mxMainWindow.is())
	{
		mxMainWindow->removeFocusListener(this);

		if (mxMainPane.is())
			mxMainPane->setAccessible(NULL);
	}

	mpAccessiblePreview = NULL;
	mpAccessibleNotes = NULL;
	mpAccessibleConsole = NULL;
}




//----- XAccessible -----------------------------------------------------------

Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext (void)
	throw (cssu::RuntimeException)
{
	if ( ! mpAccessibleConsole.is())
	{
		Reference<XPane> xMainPane (mxMainPane, UNO_QUERY);
		if (xMainPane.is())
		{
			mxMainWindow = Reference<awt::XWindow>(xMainPane->getWindow(), UNO_QUERY);
			mxMainWindow->addFocusListener(this);
		}
		mpAccessibleConsole = AccessibleConsole::Create(
			mxComponentContext, css::lang::Locale());
		mpAccessibleConsole->SetWindow(mxMainWindow, NULL);
		mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
		UpdateAccessibilityHierarchy();
		if (mpPresenterController.is())
			mpPresenterController->SetAccessibilityActiveState(true);
	}
	return mpAccessibleConsole->getAccessibleContext();
}





//----- XFocusListener ----------------------------------------------------

void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent& rEvent)
		throw (cssu::RuntimeException)
{
	(void)rEvent;

#ifdef VERBOSE
	OSL_TRACE("PresenterAccessible::focusGained at %x and window %x\r", this,
		mxMainWindow.get());
#endif

	AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
}




void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent& rEvent)
	throw (cssu::RuntimeException)
{
	(void)rEvent;

#ifdef VERBOSE
	OSL_TRACE("PresenterAccessible::focusLost at %x\r", this);
#endif

	AccessibleFocusManager::Instance()->FocusObject(NULL);
}




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

void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent)
	throw (cssu::RuntimeException)
{
	if (rEvent.Source == mxMainWindow)
		mxMainWindow = NULL;
}




//----- XInitialize -----------------------------------------------------------

void SAL_CALL PresenterAccessible::initialize (const cssu::Sequence<cssu::Any>& rArguments)
	throw (cssu::RuntimeException)
{
	if (rArguments.getLength() >= 1)
	{
		mxAccessibleParent = Reference<XAccessible>(rArguments[0], UNO_QUERY);
		if (mpAccessibleConsole.is())
			mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
	}
}




//===== PresenterAccessible::AccessibleObject =========================================

PresenterAccessible::AccessibleObject::AccessibleObject (
	const lang::Locale aLocale,
	const sal_Int16 nRole,
	const OUString& rsName)
	: PresenterAccessibleObjectInterfaceBase(m_aMutex),
		msName(rsName),
		mxContentWindow(),
		mxBorderWindow(),
		maLocale(aLocale),
		mnRole(nRole),
		mnStateSet(0),
		mbIsFocused(false),
		mxParentAccessible(),
		maChildren(),
		maListeners()
{
}




void PresenterAccessible::AccessibleObject::LateInitialization (void)
{
	AccessibleFocusManager::Instance()->AddFocusableObject(this);
}




PresenterAccessible::AccessibleObject::~AccessibleObject (void)
{
}




void PresenterAccessible::AccessibleObject::SetWindow (
	const Reference<awt::XWindow>& rxContentWindow,
	const Reference<awt::XWindow>& rxBorderWindow)
{
	Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);

	if (mxContentWindow.get() != xContentWindow.get())
	{
		if (mxContentWindow.is())
		{
			mxContentWindow->removeWindowListener(this);
		}

		mxContentWindow = xContentWindow;
		mxBorderWindow = Reference<awt::XWindow2>(rxBorderWindow, UNO_QUERY);

		if (mxContentWindow.is())
		{
			mxContentWindow->addWindowListener(this);
		}

		UpdateStateSet();
	}
}




void PresenterAccessible::AccessibleObject::SetAccessibleParent (
	const Reference<XAccessible>& rxAccessibleParent)
{
	mxParentAccessible = rxAccessibleParent;
}




void SAL_CALL PresenterAccessible::AccessibleObject::disposing (void)
{
	AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
	SetWindow(NULL, NULL);
}




//----- XAccessible -------------------------------------------------------

Reference<XAccessibleContext> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleContext (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return this;
}




//----- XAccessibleContext ------------------------------------------------

sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChildCount (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	const sal_Int32 nChildCount (maChildren.size());

	return nChildCount;
}




Reference<XAccessible> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleChild (sal_Int32 nIndex)
	throw (lang::IndexOutOfBoundsException, RuntimeException)
{
	ThrowIfDisposed();

	if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
		ThrowException("invalid child index", ET_IndexOutOfBounds);

	return Reference<XAccessible>(maChildren[nIndex].get());
}




Reference<XAccessible> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleParent (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return mxParentAccessible;
}




sal_Int32 SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleIndexInParent (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	const Reference<XAccessible> xThis (this);
	if (mxParentAccessible.is())
	{
		const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
		for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
			 nIndex<nCount;
			 ++nIndex)
		{
			if (xContext->getAccessibleChild(nIndex) == xThis)
				return nIndex;
		}
	}

	return 0;
}




sal_Int16 SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleRole (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return mnRole;
}




OUString SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleDescription (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return msName;
}




OUString SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleName (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	return msName;
}




Reference<XAccessibleRelationSet> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleRelationSet (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return NULL;
}




Reference<XAccessibleStateSet> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleStateSet (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
}




lang::Locale SAL_CALL
	PresenterAccessible::AccessibleObject::getLocale (void)
	throw (RuntimeException,
		IllegalAccessibleComponentStateException)
{
	ThrowIfDisposed();

	if (mxParentAccessible.is())
	{
		Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
		if (xParentContext.is())
			return xParentContext->getLocale();
	}
	return maLocale;
}




//----- XAccessibleComponent ----------------------------------------------

sal_Bool SAL_CALL PresenterAccessible::AccessibleObject::containsPoint (
	const awt::Point& rPoint)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	if (mxContentWindow.is())
	{
		const awt::Rectangle aBox (getBounds());
		return rPoint.X>=aBox.X
			&& rPoint.Y>=aBox.Y
			&& rPoint.X<aBox.X+aBox.Width
			&& rPoint.Y<aBox.Y+aBox.Height;
	}
	else
		return false;
}




Reference<XAccessible> SAL_CALL
	PresenterAccessible::AccessibleObject::getAccessibleAtPoint (const awt::Point& rPoint)
	throw (RuntimeException)
{
	(void)rPoint;
	ThrowIfDisposed();

	return Reference<XAccessible>();
}




awt::Rectangle SAL_CALL PresenterAccessible::AccessibleObject::getBounds (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	awt::Rectangle aBox;

	const awt::Point aLocation (GetRelativeLocation());
	const awt::Size aSize (GetSize());

	return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
}




awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocation (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	const awt::Point aLocation (GetRelativeLocation());

	return aLocation;
}




awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocationOnScreen (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	awt::Point aRelativeLocation (GetRelativeLocation());
	awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());

	return awt::Point(
		aRelativeLocation.X + aParentLocationOnScreen.X,
		aRelativeLocation.Y + aParentLocationOnScreen.Y);
}




awt::Size SAL_CALL PresenterAccessible::AccessibleObject::getSize (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	const awt::Size aSize (GetSize());

	return aSize;
}




void SAL_CALL PresenterAccessible::AccessibleObject::grabFocus (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();
	if (mxBorderWindow.is())
		mxBorderWindow->setFocus();
	else if (mxContentWindow.is())
		mxContentWindow->setFocus();
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getForeground (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return 0x00ffffff;
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getBackground (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	return 0x00000000;
}




//----- XAccessibleEventBroadcaster ---------------------------------------

void SAL_CALL PresenterAccessible::AccessibleObject::addEventListener (
	const Reference<XAccessibleEventListener>& rxListener)
	throw (RuntimeException)
{
	if (rxListener.is())
	{
		const osl::MutexGuard aGuard(m_aMutex);

		if (IsDisposed())
		{
			uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
			rxListener->disposing (lang::EventObject(xThis));
		}
		else
		{
			maListeners.push_back(rxListener);
		}
	}
}




void SAL_CALL PresenterAccessible::AccessibleObject::removeEventListener (
	const Reference<XAccessibleEventListener>& rxListener)
	throw (RuntimeException)
{
	ThrowIfDisposed();
	if (rxListener.is())
	{
		const osl::MutexGuard aGuard(m_aMutex);

		maListeners.erase(std::remove(maListeners.begin(), maListeners.end(), rxListener));
	}
}




//----- XWindowListener ---------------------------------------------------

void SAL_CALL PresenterAccessible::AccessibleObject::windowResized (
	const css::awt::WindowEvent& rEvent)
	throw (cssu::RuntimeException)
{
	(void)rEvent;

	FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
}




void SAL_CALL PresenterAccessible::AccessibleObject::windowMoved (
	const css::awt::WindowEvent& rEvent)
	throw (cssu::RuntimeException)
{
	(void)rEvent;

	FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
}




void SAL_CALL PresenterAccessible::AccessibleObject::windowShown (
	const css::lang::EventObject& rEvent)
	throw (cssu::RuntimeException)
{
	(void)rEvent;
	UpdateStateSet();
}




void SAL_CALL PresenterAccessible::AccessibleObject::windowHidden (
	const css::lang::EventObject& rEvent)
	throw (cssu::RuntimeException)
{
	(void)rEvent;
	UpdateStateSet();
}




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

void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
	throw (cssu::RuntimeException)
{
	if (rEvent.Source == mxContentWindow)
	{
		mxContentWindow = NULL;
		mxBorderWindow = NULL;
	}
	else
	{
		SetWindow(NULL, NULL);
	}
}




//----- private ---------------------------------------------------------------

bool PresenterAccessible::AccessibleObject::GetWindowState (const sal_Int16 nType) const
{
	switch (nType)
	{
		case AccessibleStateType::ENABLED:
			return mxContentWindow.is() && mxContentWindow->isEnabled();

		case AccessibleStateType::FOCUSABLE:
			return true;

		case AccessibleStateType::FOCUSED:
			return mbIsFocused;

		case AccessibleStateType::SHOWING:
			return mxContentWindow.is() && mxContentWindow->isVisible();

		default:
			return false;
	}
}




void PresenterAccessible::AccessibleObject::UpdateStateSet (void)
{
	UpdateState(AccessibleStateType::FOCUSABLE, true);
	UpdateState(AccessibleStateType::VISIBLE, true);
	UpdateState(AccessibleStateType::ENABLED, true);
	UpdateState(AccessibleStateType::MULTI_LINE, true);
	UpdateState(AccessibleStateType::SENSITIVE, true);

	UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
	UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
	UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
//	UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
}




void PresenterAccessible::AccessibleObject::UpdateState(
	const sal_Int16 nState,
	const bool bValue)
{
	const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
	if (((mnStateSet & nStateMask)!=0) != bValue)
	{
		if (bValue)
		{
			mnStateSet |= nStateMask;
			FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
		}
		else
		{
			mnStateSet &= ~nStateMask;
			FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
		}
	}
}




void PresenterAccessible::AccessibleObject::AddChild (
	const ::rtl::Reference<AccessibleObject>& rpChild)
{
	maChildren.push_back(rpChild);
	rpChild->SetAccessibleParent(this);
	FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
}




void PresenterAccessible::AccessibleObject::RemoveChild (
	const ::rtl::Reference<AccessibleObject>& rpChild)
{
	rpChild->SetAccessibleParent(Reference<XAccessible>());
	maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
	FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
}




void PresenterAccessible::AccessibleObject::SetIsFocused (const bool bIsFocused)
{
	if (mbIsFocused != bIsFocused)
	{
		mbIsFocused = bIsFocused;
		UpdateStateSet();
	}
}




void PresenterAccessible::AccessibleObject::SetAccessibleName (const ::rtl::OUString& rsName)
{
	if (msName != rsName)
	{
		const OUString sOldName(msName);
		msName = rsName;
		FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
	}
}




void PresenterAccessible::AccessibleObject::FireAccessibleEvent (
	const sal_Int16 nEventId,
	const uno::Any& rOldValue,
	const uno::Any& rNewValue )
{
	AccessibleEventObject aEventObject;

	aEventObject.Source = Reference<XWeak>(this);
	aEventObject.EventId = nEventId;
	aEventObject.NewValue = rNewValue;
	aEventObject.OldValue = rOldValue;

	::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
	for (::std::vector<Reference<XAccessibleEventListener> >::const_iterator
			iListener(aListenerCopy.begin()),
			iEnd(aListenerCopy.end());
			iListener!=iEnd;
			++iListener)
	{
		try
		{
			(*iListener)->notifyEvent(aEventObject);
		}
		catch(lang::DisposedException&)
		{
			// Listener has been disposed and should have been removed
			// already.
			removeEventListener(*iListener);
		}
		catch(Exception&)
		{
			// Ignore all other exceptions and assume that they are
			// caused by a temporary problem.
		}
	}
}



awt::Point PresenterAccessible::AccessibleObject::GetRelativeLocation (void)
{
	awt::Point aLocation;
	if (mxContentWindow.is())
	{
		const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
		aLocation.X = aContentBox.X;
		aLocation.Y = aContentBox.Y;
		if (mxBorderWindow.is())
		{
			const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
			aLocation.X += aBorderBox.X;
			aLocation.Y += aBorderBox.Y;
		}
	}
	return aLocation;
}




awt::Size PresenterAccessible::AccessibleObject::GetSize (void)
{
	if (mxContentWindow.is())
	{
		const awt::Rectangle aBox (mxContentWindow->getPosSize());
		return awt::Size(aBox.Width, aBox.Height);
	}
	else
		return awt::Size();
}




awt::Point PresenterAccessible::AccessibleObject::GetAbsoluteParentLocation (void)
{
	Reference<XAccessibleComponent> xParentComponent;
	if (mxParentAccessible.is())
		xParentComponent = Reference<XAccessibleComponent>(
			mxParentAccessible->getAccessibleContext(), UNO_QUERY);
	if (xParentComponent.is())
		return xParentComponent->getLocationOnScreen();
	else
		return awt::Point();
}




sal_Bool PresenterAccessible::AccessibleObject::IsDisposed (void) const
{
	return (rBHelper.bDisposed || rBHelper.bInDispose);
}




void PresenterAccessible::AccessibleObject::ThrowIfDisposed (void) const
	throw (lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
		ThrowException("object has already been disposed", ET_Disposed);
}




void PresenterAccessible::AccessibleObject::ThrowException (
	const sal_Char* pMessage,
	const ExceptionType eExceptionType) const
{
	const OUString sMessage (OUString(A2S("PresenterAccessible: ")) + OUString(A2S(pMessage)));
	const Reference<XInterface> xObject (
		const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
	switch (eExceptionType)
	{
		default:
		case ET_Runtime:
			throw RuntimeException(sMessage, xObject);
		case ET_Disposed:
			throw lang::DisposedException(sMessage, xObject);
		case ET_IndexOutOfBounds:
			throw lang::IndexOutOfBoundsException(sMessage, xObject);
	}
}





//===== AccessibleStateSet ====================================================

AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
	: AccessibleStateSetInterfaceBase(m_aMutex),
	  mnStateSet (nStateSet)
{
}




AccessibleStateSet::~AccessibleStateSet (void)
{
}




sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
{
	if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
	{
		throw RuntimeException(A2S("AccessibleStateSet::GetStateMask: invalid state"), NULL);
	}

	return 1<<nState;
}




//----- XAccessibleStateSet ---------------------------------------------------

sal_Bool SAL_CALL AccessibleStateSet::isEmpty (void)
	throw (cssu::RuntimeException)
{
	return mnStateSet==0;
}




sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
	throw (cssu::RuntimeException)
{
	return (mnStateSet & GetStateMask(nState)) != 0;
}




sal_Bool SAL_CALL AccessibleStateSet::containsAll (const cssu::Sequence<sal_Int16>& rStateSet)
	throw (cssu::RuntimeException)
{
	for (sal_Int32 nIndex=0,nCount=rStateSet.getLength(); nIndex<nCount; ++nIndex)
	{
		if ((mnStateSet & GetStateMask(rStateSet[nIndex])) == 0)
			return sal_False;
	}
	return sal_True;
}




cssu::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates (void)
	throw (cssu::RuntimeException)
{
	::std::vector<sal_Int16> aStates;
	aStates.reserve(sizeof(mnStateSet)*8);
	for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
		if ((mnStateSet & GetStateMask(nIndex)) != 0)
			aStates.push_back(nIndex);
	return Sequence<sal_Int16>(&aStates.front(), aStates.size());
}




//===== AccessibleRelationSet =================================================

AccessibleRelationSet::AccessibleRelationSet (void)
	: AccessibleRelationSetInterfaceBase(m_aMutex),
	  maRelations()
{
}




AccessibleRelationSet::~AccessibleRelationSet (void)
{
}




void AccessibleRelationSet::AddRelation (
	const sal_Int16 nRelationType,
	const Reference<XInterface>& rxObject)
{
	maRelations.resize(maRelations.size()+1);
	maRelations.back().RelationType = nRelationType;
	maRelations.back().TargetSet.realloc(1);
	maRelations.back().TargetSet[0] = rxObject;
}




//----- XAccessibleRelationSet ------------------------------------------------

sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount (void)
	throw (cssu::RuntimeException)
{
	return maRelations.size();
}




AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
	throw (cssu::RuntimeException, css::lang::IndexOutOfBoundsException)
{
	if (nIndex<0 && sal_uInt32(nIndex)>=maRelations.size())
		return AccessibleRelation();
	else
		return maRelations[nIndex];
}




sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
	throw (cssu::RuntimeException)
{
	for (::std::vector<AccessibleRelation>::const_iterator iRelation(maRelations.begin());
		 iRelation!=maRelations.end();
		 ++iRelation)
	{
		if (iRelation->RelationType == nRelationType)
			return sal_True;
	}
	return sal_False;
}




AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
	throw (cssu::RuntimeException)
{
	for (::std::vector<AccessibleRelation>::const_iterator iRelation(maRelations.begin());
		 iRelation!=maRelations.end();
		 ++iRelation)
	{
		if (iRelation->RelationType == nRelationType)
			return *iRelation;
	}
	return AccessibleRelation();
}




//===== PresenterAccessible::AccessibleParagraph ==============================

PresenterAccessible::AccessibleParagraph::AccessibleParagraph (
	const lang::Locale aLocale,
	const sal_Int16 nRole,
	const OUString& rsName,
	const SharedPresenterTextParagraph& rpParagraph,
	const sal_Int32 nParagraphIndex)
	: PresenterAccessibleParagraphInterfaceBase(aLocale, nRole, rsName),
	  mpParagraph(rpParagraph),
	  mnParagraphIndex(nParagraphIndex)
{
}




PresenterAccessible::AccessibleParagraph::~AccessibleParagraph (void)
{
}




//----- XAccessibleContext ----------------------------------------------------

Reference<XAccessibleRelationSet> SAL_CALL
	PresenterAccessible::AccessibleParagraph::getAccessibleRelationSet (void)
	throw (RuntimeException)
{
	ThrowIfDisposed();

	rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);

	if (mxParentAccessible.is())
	{
		Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
		if (xParentContext.is())
		{
			if (mnParagraphIndex>0)
				pSet->AddRelation(
					AccessibleRelationType::CONTENT_FLOWS_FROM,
					xParentContext->getAccessibleChild(mnParagraphIndex-1));

			if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
				pSet->AddRelation(
					AccessibleRelationType::CONTENT_FLOWS_TO,
					xParentContext->getAccessibleChild(mnParagraphIndex+1));
		}
	}

	return Reference<XAccessibleRelationSet>(pSet.get());
}






//----- XAccessibleText -------------------------------------------------------

sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCaretPosition (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	sal_Int32 nPosition (-1);
	if (mpParagraph)
		nPosition = mpParagraph->GetCaretPosition();

	return nPosition;
}




sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setCaretPosition (sal_Int32 nIndex)
	throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

	if (mpParagraph)
	{
		mpParagraph->SetCaretPosition(nIndex);
		return sal_True;
	}
	else
		return sal_False;
}




sal_Unicode SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacter (sal_Int32 nIndex)
	throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

	if (mpParagraph)
		return mpParagraph->GetCharacter(nIndex);
	else
	{
		ThrowException("no text support in current mode", ET_IndexOutOfBounds);
		// The method above throws an exception and the following line is
		// never reached. But there is at least one compiler that can not
		// detect this and we need the return to make it happy.
		return sal_Unicode();
	}
}




Sequence<css::beans::PropertyValue> SAL_CALL
	PresenterAccessible::AccessibleParagraph::getCharacterAttributes (
		::sal_Int32 nIndex,
		const cssu::Sequence<rtl::OUString>& rRequestedAttributes)
	throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

#ifdef VERBOSE
	OSL_TRACE("PresenterAccessible::AccessibleParagraph::getCharacterAttributes at %x,%d returns empty set\r",
		this,nIndex);
	for (sal_Int32 nAttributeIndex(0),nAttributeCount(rRequestedAttributes.getLength());
		 nAttributeIndex<nAttributeCount;
		 ++nAttributeIndex)
	{
		OSL_TRACE("    requested attribute %d is %s\r",
			nAttributeIndex,
			OUStringToOString(rRequestedAttributes[nAttributeIndex], RTL_TEXTENCODING_UTF8).getStr());
	}
#endif

	// Character properties are not supported.
	(void)nIndex;
	(void)rRequestedAttributes;
	return Sequence<css::beans::PropertyValue>();
}




awt::Rectangle SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterBounds (
	sal_Int32 nIndex)
	throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

	awt::Rectangle aCharacterBox;
	if (nIndex < 0)
	{
		ThrowException("invalid text index", ET_IndexOutOfBounds);
	}
	else if (mpParagraph)
	{
		aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
		// Convert coordinates relative to the window origin into absolute
		// screen coordinates.
		const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
		aCharacterBox.X += aWindowLocationOnScreen.X;
		aCharacterBox.Y += aWindowLocationOnScreen.Y;
	}
	else
	{
		ThrowException("no text support in current mode", ET_IndexOutOfBounds);
	}

	return aCharacterBox;
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterCount (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	sal_Int32 nCount (0);
	if (mpParagraph)
		nCount = mpParagraph->GetCharacterCount();

	return nCount;
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getIndexAtPoint (
	const css::awt::Point& rPoint)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	sal_Int32 nIndex (-1);
	if (mpParagraph)
		nIndex = mpParagraph->GetIndexAtPoint(rPoint);

	return nIndex;
}




::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectedText (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	return getTextRange(getSelectionStart(), getSelectionEnd());
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionStart (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	return getCaretPosition();
}




sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionEnd (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	return getCaretPosition();
}




sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setSelection (
	sal_Int32 nStartIndex,
	sal_Int32 nEndIndex)
	throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	(void)nEndIndex;
	ThrowIfDisposed();

	return setCaretPosition(nStartIndex);
}




::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getText (void)
	throw (cssu::RuntimeException)
{
	ThrowIfDisposed();

	::rtl::OUString sText;
	if (mpParagraph)
		sText = mpParagraph->GetText();

	return sText;
}




::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getTextRange (
	sal_Int32 nLocalStartIndex,
	sal_Int32 nLocalEndIndex)
	throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

	::rtl::OUString sText;
	if (mpParagraph)
	{
		const TextSegment aSegment (
			mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
		sText = aSegment.SegmentText;
	}

	return sText;
}




TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextAtIndex (
	sal_Int32 nLocalCharacterIndex,
	sal_Int16 nTextType)
	throw (css::lang::IndexOutOfBoundsException,
		css::lang::IllegalArgumentException,
		cssu::RuntimeException)
{
	ThrowIfDisposed();

	TextSegment aSegment;
	if (mpParagraph)
		aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);

	return aSegment;
}




TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBeforeIndex (
	sal_Int32 nLocalCharacterIndex,
	sal_Int16 nTextType)
	throw (css::lang::IndexOutOfBoundsException,
		   css::lang::IllegalArgumentException,
		   cssu::RuntimeException)
{
	ThrowIfDisposed();

	TextSegment aSegment;
	if (mpParagraph)
		aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);

	return aSegment;
}




TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBehindIndex (
	sal_Int32 nLocalCharacterIndex,
	sal_Int16 nTextType)
	throw (css::lang::IndexOutOfBoundsException,
		   css::lang::IllegalArgumentException,
		   cssu::RuntimeException)
{
	ThrowIfDisposed();

	TextSegment aSegment;
	if (mpParagraph)
		aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);

	return aSegment;
}




sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::copyText (
	sal_Int32 nStartIndex,
	sal_Int32 nEndIndex)
	throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException)
{
	ThrowIfDisposed();

	// Return false because copying to clipboard is not supported.
	// It IS supported in the notes view. There is no need to duplicate
	// this here.
	(void)nStartIndex;
	(void)nEndIndex;
	return sal_False;
}




//----- protected -------------------------------------------------------------

awt::Point PresenterAccessible::AccessibleParagraph::GetRelativeLocation (void)
{
	awt::Point aLocation (AccessibleObject::GetRelativeLocation());
	if (mpParagraph)
	{
		const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
		aLocation.X += aParagraphLocation.X;
		aLocation.Y += aParagraphLocation.Y;
	}

	return aLocation;
}




awt::Size PresenterAccessible::AccessibleParagraph::GetSize (void)
{
	if (mpParagraph)
		return mpParagraph->GetSize();
	else
		return AccessibleObject::GetSize();
}




awt::Point PresenterAccessible::AccessibleParagraph::GetAbsoluteParentLocation (void)
{
	if (mxParentAccessible.is())
	{
		Reference<XAccessibleContext> xParentContext(
			mxParentAccessible->getAccessibleContext(), UNO_QUERY);
		if (xParentContext.is())
		{
			Reference<XAccessibleComponent> xGrandParentComponent(
				xParentContext->getAccessibleParent(), UNO_QUERY);
			if (xGrandParentComponent.is())
				return xGrandParentComponent->getLocationOnScreen();
		}
	}

	return awt::Point();
}




bool PresenterAccessible::AccessibleParagraph::GetWindowState (const sal_Int16 nType) const
{
	switch (nType)
	{
		case AccessibleStateType::EDITABLE:
			return mpParagraph.get()!=NULL;

		case AccessibleStateType::ACTIVE:
			return true;

		default:
			return AccessibleObject::GetWindowState(nType);
	}
}






//===== AccessibleNotes =======================================================

AccessibleNotes::AccessibleNotes (
	const css::lang::Locale aLocale,
	const sal_Int16 nRole,
	const ::rtl::OUString& rsName)
	: AccessibleObject(aLocale,nRole,rsName),
	  mpTextView()
{
}




rtl::Reference<PresenterAccessible::AccessibleObject> AccessibleNotes::Create (
	const css::uno::Reference<css::uno::XComponentContext>& rxContext,
	const lang::Locale aLocale,
	const Reference<awt::XWindow>& rxContentWindow,
	const Reference<awt::XWindow>& rxBorderWindow,
	const ::boost::shared_ptr<PresenterTextView>& rpTextView)
{
	OUString sName (A2S("Presenter Notes Text"));
	{
		PresenterConfigurationAccess aConfiguration (
			rxContext,
			OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
			PresenterConfigurationAccess::READ_ONLY);
		aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Notes/String"))
			>>= sName;
	}

	rtl::Reference<AccessibleNotes> pObject (
		new AccessibleNotes(
			aLocale,
			AccessibleRole::PANEL,
			sName));
	pObject->LateInitialization();
	pObject->SetTextView(rpTextView);
	pObject->UpdateStateSet();
	pObject->SetWindow(rxContentWindow, rxBorderWindow);

	return rtl::Reference<PresenterAccessible::AccessibleObject>(pObject.get());
}




void AccessibleNotes::SetTextView (
	const ::boost::shared_ptr<PresenterTextView>& rpTextView)
{
	::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren;

	// Release any listeners to the current text view.
	if (mpTextView)
	{
		mpTextView->GetCaret()->SetCaretMotionBroadcaster(
			::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
		mpTextView->SetTextChangeBroadcaster(
			::boost::function<void(void)>());
	}

	mpTextView = rpTextView;

	if (mpTextView)
	{
		// Create a new set of children, one for each paragraph.
		const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
		for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
		{
			rtl::Reference<PresenterAccessible::AccessibleParagraph> pParagraph (
				new PresenterAccessible::AccessibleParagraph(
					css::lang::Locale(),
					AccessibleRole::PARAGRAPH,
					A2S("Paragraph")+OUString::valueOf(nIndex),
					rpTextView->GetParagraph(nIndex),
					nIndex));
			pParagraph->LateInitialization();
			pParagraph->SetWindow(
				Reference<awt::XWindow>(mxContentWindow, UNO_QUERY),
				Reference<awt::XWindow>(mxBorderWindow, UNO_QUERY));
			pParagraph->SetAccessibleParent(this);
			aChildren.push_back(
				rtl::Reference<PresenterAccessible::AccessibleObject>(pParagraph.get()));
		}
		maChildren.swap(aChildren);
		FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());

		// Dispose the old children. (This will remove them from the focus
		// manager).
		for (std::vector<rtl::Reference<AccessibleObject> >::const_iterator
				iChild(aChildren.begin()), iEnd(aChildren.end());
				iChild!=iEnd;
				++iChild)
		{
			Reference<lang::XComponent> xComponent (static_cast<XWeak*>(iChild->get()), UNO_QUERY);
			if (xComponent.is())
				xComponent->dispose();
		}

		// This class acts as a controller of who broadcasts caret motion
		// events and handles text changes. Register the corresponding
		// listeners here.
		mpTextView->GetCaret()->SetCaretMotionBroadcaster(
			::boost::bind(&AccessibleNotes::NotifyCaretChange, this, _1, _2, _3, _4));
		mpTextView->SetTextChangeBroadcaster(
			::boost::bind(&AccessibleNotes::HandleTextChange, this));
	}
}




void AccessibleNotes::SetWindow (
	const cssu::Reference<css::awt::XWindow>& rxContentWindow,
	const cssu::Reference<css::awt::XWindow>& rxBorderWindow)
{
	AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);

	// Set the windows at the children as well, so that every paragraph can
	// setup its geometry.
	for (::std::vector<rtl::Reference<AccessibleObject> >::const_iterator
			iChild(maChildren.begin()),
			iEnd(maChildren.end());
			iChild!=iEnd;
			++iChild)
	{
		(*iChild)->SetWindow(rxContentWindow, rxBorderWindow);
	}
}




void AccessibleNotes::NotifyCaretChange (
	const sal_Int32 nOldParagraphIndex,
	const sal_Int32 nOldCharacterIndex,
	const sal_Int32 nNewParagraphIndex,
	const sal_Int32 nNewCharacterIndex)
{
	AccessibleFocusManager::Instance()->FocusObject(
		nNewParagraphIndex >= 0
			? maChildren[nNewParagraphIndex]
			: this);

	if (nOldParagraphIndex != nNewParagraphIndex)
	{
		// Moved caret from one paragraph to another (or showed or
		// hid the caret). Move focus from one accessible
		// paragraph to another.
		if (nOldParagraphIndex >= 0)
		{
			maChildren[nOldParagraphIndex]->FireAccessibleEvent(
				AccessibleEventId::CARET_CHANGED,
				Any(nOldCharacterIndex),
				Any(sal_Int32(-1)));
		}
		if (nNewParagraphIndex >= 0)
		{
			maChildren[nNewParagraphIndex]->FireAccessibleEvent(
				AccessibleEventId::CARET_CHANGED,
				Any(sal_Int32(-1)),
				Any(nNewCharacterIndex));
		}
	}
	else if (nNewParagraphIndex >= 0)
	{
		// Caret moved inside one paragraph.
		maChildren[nNewParagraphIndex]->FireAccessibleEvent(
			AccessibleEventId::CARET_CHANGED,
			Any(nOldCharacterIndex),
			Any(nNewCharacterIndex));
	}
}




void AccessibleNotes::HandleTextChange (void)
{
	SetTextView(mpTextView);
}




//===== AccessibleFocusManager ================================================

::boost::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance;

::boost::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::Instance (void)
{
	if ( ! mpInstance)
	{
		mpInstance.reset(new AccessibleFocusManager());
	}
	return mpInstance;
}




AccessibleFocusManager::AccessibleFocusManager (void)
	: maFocusableObjects()
{
}




void AccessibleFocusManager::AddFocusableObject (
	const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
{
	OSL_ASSERT(rpObject.is());
	OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());

	maFocusableObjects.push_back(rpObject);
}




void AccessibleFocusManager::RemoveFocusableObject (
	const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
{
	::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
		::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));

	if (iObject != maFocusableObjects.end())
		maFocusableObjects.erase(iObject);
	else
	{
		OSL_ASSERT(iObject!=maFocusableObjects.end());
	}
}




void AccessibleFocusManager::FocusObject (
	const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
{
	// Remove the focus of any of the other focusable objects.
	for (::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::const_iterator
			iObject (maFocusableObjects.begin()),
			iEnd (maFocusableObjects.end());
		iObject != iEnd;
		++iObject)
	{
		if (*iObject!=rpObject)
			(*iObject)->SetIsFocused(false);
	}

	if (rpObject.is())
		rpObject->SetIsFocused(true);
}

} } // end of namespace ::sd::presenter
