/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::drawing::framework; //===== PresenterAccessibleObject ============================================= namespace sdext { namespace presenter { namespace { typedef ::cppu::PartialWeakComponentImplHelper5 < css::accessibility::XAccessible, css::accessibility::XAccessibleContext, css::accessibility::XAccessibleComponent, css::accessibility::XAccessibleEventBroadcaster, css::awt::XWindowListener > PresenterAccessibleObjectInterfaceBase; } class PresenterAccessible::AccessibleObject : public ::cppu::BaseMutex, public PresenterAccessibleObjectInterfaceBase { public: AccessibleObject ( const css::lang::Locale& rLocale, const sal_Int16 nRole, const OUString& rsName); void LateInitialization(); virtual ~AccessibleObject(); virtual void SetWindow ( const css::uno::Reference& rxContentWindow, const css::uno::Reference& rxBorderWindow); void SetAccessibleParent (const css::uno::Reference& rxAccessibleParent); virtual void SAL_CALL disposing() SAL_OVERRIDE; void AddChild (const ::rtl::Reference& rpChild); void RemoveChild (const ::rtl::Reference& rpChild); void SetIsFocused (const bool bIsFocused); void SetAccessibleName (const OUString& rsName); void FireAccessibleEvent ( const sal_Int16 nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue); void UpdateStateSet(); //----- XComponent --------------------------------------------------- virtual void SAL_CALL dispose()throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { WeakComponentImplHelperBase::dispose(); } virtual void SAL_CALL addEventListener(const css::uno::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { WeakComponentImplHelperBase::addEventListener(xListener); } virtual void SAL_CALL removeEventListener(const css::uno::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { WeakComponentImplHelperBase::removeEventListener(xListener); } //----- XAccessible ------------------------------------------------------- virtual css::uno::Reference SAL_CALL getAccessibleContext() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; //----- XAccessibleContext ---------------------------------------------- virtual sal_Int32 SAL_CALL getAccessibleChildCount() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleChild (sal_Int32 nIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleParent() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int16 SAL_CALL getAccessibleRole() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual OUString SAL_CALL getAccessibleDescription() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual OUString SAL_CALL getAccessibleName() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Reference SAL_CALL getAccessibleRelationSet() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Reference SAL_CALL getAccessibleStateSet() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::lang::Locale SAL_CALL getLocale() throw (css::uno::RuntimeException, css::accessibility::IllegalAccessibleComponentStateException, std::exception) SAL_OVERRIDE; //----- XAccessibleComponent -------------------------------------------- virtual sal_Bool SAL_CALL containsPoint ( const css::awt::Point& aPoint) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Reference SAL_CALL getAccessibleAtPoint ( const css::awt::Point& aPoint) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::awt::Rectangle SAL_CALL getBounds() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::awt::Point SAL_CALL getLocation() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::awt::Point SAL_CALL getLocationOnScreen() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::awt::Size SAL_CALL getSize() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual void SAL_CALL grabFocus() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getForeground() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getBackground() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; //----- XAccessibleEventBroadcaster -------------------------------------- virtual void SAL_CALL addAccessibleEventListener ( const css::uno::Reference& rxListener) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual void SAL_CALL removeAccessibleEventListener ( const css::uno::Reference& rxListener) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; //----- XWindowListener --------------------------------------------------- virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; //----- XEventListener ---------------------------------------------------- virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; protected: OUString msName; css::uno::Reference mxContentWindow; css::uno::Reference mxBorderWindow; const css::lang::Locale maLocale; const sal_Int16 mnRole; sal_uInt32 mnStateSet; bool mbIsFocused; css::uno::Reference mxParentAccessible; ::std::vector > maChildren; ::std::vector > maListeners; virtual awt::Point GetRelativeLocation(); virtual awt::Size GetSize(); virtual awt::Point GetAbsoluteParentLocation(); virtual bool GetWindowState (const sal_Int16 nType) const; void UpdateState (const sal_Int16 aState, const bool bValue); bool IsDisposed() const; void ThrowIfDisposed() const throw (css::lang::DisposedException); }; //===== AccessibleStateSet ==================================================== namespace { typedef ::cppu::WeakComponentImplHelper1 < css::accessibility::XAccessibleStateSet > AccessibleStateSetInterfaceBase; } class AccessibleStateSet : public ::cppu::BaseMutex, public AccessibleStateSetInterfaceBase { public: AccessibleStateSet (const sal_Int32 nStateSet); virtual ~AccessibleStateSet(); static sal_uInt32 GetStateMask (const sal_Int16 nType); //----- XAccessibleStateSet ----------------------------------------------- virtual sal_Bool SAL_CALL isEmpty() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL contains (sal_Int16 nState) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL containsAll (const css::uno::Sequence& rStateSet) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Sequence SAL_CALL getStates() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; private: const sal_Int32 mnStateSet; }; //===== AccessibleRelationSet ================================================= namespace { typedef ::cppu::WeakComponentImplHelper1 < css::accessibility::XAccessibleRelationSet > AccessibleRelationSetInterfaceBase; } class AccessibleRelationSet : public ::cppu::BaseMutex, public AccessibleRelationSetInterfaceBase { public: AccessibleRelationSet(); virtual ~AccessibleRelationSet(); void AddRelation ( const sal_Int16 nRelationType, const Reference& rxObject); //----- XAccessibleRelationSet -------------------------------------------- virtual sal_Int32 SAL_CALL getRelationCount() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) throw (css::uno::RuntimeException, css::lang::IndexOutOfBoundsException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; private: ::std::vector maRelations; }; //===== PresenterAccessibleParagraph ========================================== namespace { typedef ::cppu::ImplInheritanceHelper1 < PresenterAccessible::AccessibleObject, css::accessibility::XAccessibleText > PresenterAccessibleParagraphInterfaceBase; } class PresenterAccessible::AccessibleParagraph : public PresenterAccessibleParagraphInterfaceBase { public: AccessibleParagraph ( const css::lang::Locale& rLocale, const sal_Int16 nRole, const OUString& rsName, const SharedPresenterTextParagraph& rpParagraph, const sal_Int32 nParagraphIndex); virtual ~AccessibleParagraph(); //----- XAccessibleContext ------------------------------------------------ virtual css::uno::Reference SAL_CALL getAccessibleRelationSet() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; //----- XAccessibleText --------------------------------------------------- virtual sal_Int32 SAL_CALL getCaretPosition() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::uno::Sequence SAL_CALL getCharacterAttributes ( ::sal_Int32 nIndex, const css::uno::Sequence& rRequestedAttributes) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getCharacterCount() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual OUString SAL_CALL getSelectedText() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getSelectionStart() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Int32 SAL_CALL getSelectionEnd() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual OUString SAL_CALL getText() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual OUString SAL_CALL getTextRange ( sal_Int32 nStartIndex, sal_Int32 nEndIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex ( sal_Int32 nIndex, sal_Int16 nTextType) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex ( sal_Int32 nIndex, sal_Int16 nTextType) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex ( sal_Int32 nIndex, sal_Int16 nTextType) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; virtual sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; protected: virtual awt::Point GetRelativeLocation() SAL_OVERRIDE; virtual awt::Size GetSize() SAL_OVERRIDE; virtual awt::Point GetAbsoluteParentLocation() SAL_OVERRIDE; virtual bool GetWindowState (const sal_Int16 nType) const SAL_OVERRIDE; private: SharedPresenterTextParagraph mpParagraph; const sal_Int32 mnParagraphIndex; }; //===== AccessibleConsole ===================================================== class AccessibleConsole { public: static rtl::Reference Create ( const css::uno::Reference& rxContext, const lang::Locale& rLocale) { OUString sName ("Presenter Console"); PresenterConfigurationAccess aConfiguration ( rxContext, OUString("/org.openoffice.Office.PresenterScreen/"), PresenterConfigurationAccess::READ_ONLY); aConfiguration.GetConfigurationNode("Presenter/Accessibility/Console/String") >>= sName; rtl::Reference pObject ( new PresenterAccessible::AccessibleObject( rLocale, AccessibleRole::PANEL, sName)); pObject->LateInitialization(); pObject->UpdateStateSet(); return pObject; } }; //===== AccessiblePreview ===================================================== class AccessiblePreview { public: static rtl::Reference Create ( const Reference& rxContext, const lang::Locale& rLocale, const Reference& rxContentWindow, const Reference& rxBorderWindow) { OUString sName ("Presenter Notes Window"); { PresenterConfigurationAccess aConfiguration ( rxContext, OUString("/org.openoffice.Office.PresenterScreen/"), PresenterConfigurationAccess::READ_ONLY); aConfiguration.GetConfigurationNode("Presenter/Accessibility/Preview/String") >>= sName; } rtl::Reference pObject ( new PresenterAccessible::AccessibleObject( rLocale, 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& rLocale, const sal_Int16 nRole, const OUString& rsName); static rtl::Reference Create ( const css::uno::Reference& rxContext, const lang::Locale& rLocale, const Reference& rxContentWindow, const Reference& rxBorderWindow, const ::boost::shared_ptr& rpTextView); void SetTextView (const ::boost::shared_ptr& rpTextView); virtual void SetWindow ( const css::uno::Reference& rxContentWindow, const css::uno::Reference& rxBorderWindow) SAL_OVERRIDE; private: ::boost::shared_ptr mpTextView; void NotifyCaretChange ( const sal_Int32 nOldParagraphIndex, const sal_Int32 nOldCharacterIndex, const sal_Int32 nNewParagraphIndex, const sal_Int32 nNewCharacterIndex); void HandleTextChange(); }; //===== 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 Instance(); void AddFocusableObject (const ::rtl::Reference& rpObject); void RemoveFocusableObject (const ::rtl::Reference& rpObject); void FocusObject (const ::rtl::Reference& rpObject); private: static ::boost::shared_ptr mpInstance; ::std::vector > maFocusableObjects; AccessibleFocusManager(); }; //===== PresenterAccessible =================================================== PresenterAccessible::PresenterAccessible ( const css::uno::Reference& rxContext, const ::rtl::Reference& rpPresenterController, const Reference& rxMainPane) : PresenterAccessibleInterfaceBase(m_aMutex), mxComponentContext(rxContext), mpPresenterController(rpPresenterController), mxMainPaneId(rxMainPane.is() ? rxMainPane->getResourceId() : Reference()), mxMainPane(rxMainPane, UNO_QUERY), mxMainWindow(), mxPreviewContentWindow(), mxPreviewBorderWindow(), mxNotesContentWindow(), mxNotesBorderWindow(), mpAccessibleConsole(), mpAccessiblePreview(), mpAccessibleNotes(), mxAccessibleParent() { if (mxMainPane.is()) mxMainPane->setAccessible(this); } PresenterAccessible::~PresenterAccessible() { } PresenterPaneContainer::SharedPaneDescriptor PresenterAccessible::GetPreviewPane() const { PresenterPaneContainer::SharedPaneDescriptor pPreviewPane; if ( ! mpPresenterController.is()) return pPreviewPane; rtl::Reference pContainer (mpPresenterController->GetPaneContainer()); if ( ! pContainer.is()) return pPreviewPane; pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL); Reference xPreviewPane; if (pPreviewPane) xPreviewPane = pPreviewPane->mxPane.get(); if ( ! xPreviewPane.is()) { pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL); } return pPreviewPane; } void PresenterAccessible::UpdateAccessibilityHierarchy() { if ( ! mpPresenterController.is()) return; Reference xConfigurationController( mpPresenterController->GetConfigurationController()); if ( ! xConfigurationController.is()) return; rtl::Reference 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 xPreviewPane; if (pPreviewPane) xPreviewPane = pPreviewPane->mxPane.get(); // Get the notes pane. PresenterPaneContainer::SharedPaneDescriptor pNotesPane( pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL)); Reference xNotesPane; if (pNotesPane) xNotesPane = pNotesPane->mxPane.get(); // Get the notes view. Reference xNotesView; if (pNotesPane) xNotesView = pNotesPane->mxView; rtl::Reference pNotesView ( dynamic_cast(xNotesView.get())); UpdateAccessibilityHierarchy( pPreviewPane ? pPreviewPane->mxContentWindow : Reference(), pPreviewPane ? pPreviewPane->mxBorderWindow : Reference(), (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(), pNotesPane ? pNotesPane->mxContentWindow : Reference(), pNotesPane ? pNotesPane->mxBorderWindow : Reference(), pNotesView.is() ? pNotesView->GetTextView() : ::boost::shared_ptr()); } void PresenterAccessible::UpdateAccessibilityHierarchy ( const Reference& rxPreviewContentWindow, const Reference& rxPreviewBorderWindow, const OUString& rsTitle, const Reference& rxNotesContentWindow, const Reference& rxNotesBorderWindow, const ::boost::shared_ptr& 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(mpAccessibleNotes); 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() : OUString())); } // Play some focus ping-pong to trigger AT tools. //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole); AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview); } void SAL_CALL PresenterAccessible::disposing() { UpdateAccessibilityHierarchy( NULL, NULL, OUString(), NULL, NULL, ::boost::shared_ptr()); if (mxMainWindow.is()) { mxMainWindow->removeFocusListener(this); if (mxMainPane.is()) mxMainPane->setAccessible(NULL); } mpAccessiblePreview = NULL; mpAccessibleNotes = NULL; mpAccessibleConsole = NULL; } //----- XAccessible ----------------------------------------------------------- Reference SAL_CALL PresenterAccessible::getAccessibleContext() throw (css::uno::RuntimeException, std::exception) { if ( ! mpAccessibleConsole.is()) { Reference xMainPane (mxMainPane, UNO_QUERY); if (xMainPane.is()) { mxMainWindow = Reference(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 (css::uno::RuntimeException, std::exception) { (void)rEvent; SAL_INFO("sdext.presenter", OSL_THIS_FUNC << ": PresenterAccessible::focusGained at " << this << " and window " << mxMainWindow.get()); AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole); } void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent& rEvent) throw (css::uno::RuntimeException, std::exception) { (void)rEvent; SAL_INFO("sdext.presenter", OSL_THIS_FUNC << ": PresenterAccessible::focusLost at " << this); AccessibleFocusManager::Instance()->FocusObject(NULL); } //----- XEventListener ---------------------------------------------------- void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) { if (rEvent.Source == mxMainWindow) mxMainWindow = NULL; } //----- XInitialize ----------------------------------------------------------- void SAL_CALL PresenterAccessible::initialize (const css::uno::Sequence& rArguments) throw (css::uno::RuntimeException, std::exception) { if (rArguments.getLength() >= 1) { mxAccessibleParent = Reference(rArguments[0], UNO_QUERY); if (mpAccessibleConsole.is()) mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent); } } //===== PresenterAccessible::AccessibleObject ========================================= PresenterAccessible::AccessibleObject::AccessibleObject ( const lang::Locale& rLocale, const sal_Int16 nRole, const OUString& rsName) : PresenterAccessibleObjectInterfaceBase(m_aMutex), msName(rsName), mxContentWindow(), mxBorderWindow(), maLocale(rLocale), mnRole(nRole), mnStateSet(0), mbIsFocused(false), mxParentAccessible(), maChildren(), maListeners() { } void PresenterAccessible::AccessibleObject::LateInitialization() { AccessibleFocusManager::Instance()->AddFocusableObject(this); } PresenterAccessible::AccessibleObject::~AccessibleObject() { } void PresenterAccessible::AccessibleObject::SetWindow ( const Reference& rxContentWindow, const Reference& rxBorderWindow) { Reference xContentWindow (rxContentWindow, UNO_QUERY); if (mxContentWindow.get() != xContentWindow.get()) { if (mxContentWindow.is()) { mxContentWindow->removeWindowListener(this); } mxContentWindow = xContentWindow; mxBorderWindow = Reference(rxBorderWindow, UNO_QUERY); if (mxContentWindow.is()) { mxContentWindow->addWindowListener(this); } UpdateStateSet(); } } void PresenterAccessible::AccessibleObject::SetAccessibleParent ( const Reference& rxAccessibleParent) { mxParentAccessible = rxAccessibleParent; } void SAL_CALL PresenterAccessible::AccessibleObject::disposing() { AccessibleFocusManager::Instance()->RemoveFocusableObject(this); SetWindow(NULL, NULL); } //----- XAccessible ------------------------------------------------------- Reference SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleContext() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return this; } //----- XAccessibleContext ---------------------------------------------- sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChildCount() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); const sal_Int32 nChildCount (maChildren.size()); return nChildCount; } Reference SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChild (sal_Int32 nIndex) throw (lang::IndexOutOfBoundsException, RuntimeException, std::exception) { ThrowIfDisposed(); if (nIndex<0 || nIndex>=sal_Int32(maChildren.size())) throw lang::IndexOutOfBoundsException("invalid child index", static_cast(this)); return Reference(maChildren[nIndex].get()); } Reference SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleParent() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return mxParentAccessible; } sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleIndexInParent() throw (RuntimeException, std::exception) { ThrowIfDisposed(); const Reference xThis (this); if (mxParentAccessible.is()) { const Reference xContext (mxParentAccessible->getAccessibleContext()); for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount(); nIndexgetAccessibleChild(nIndex) == xThis) return nIndex; } } return 0; } sal_Int16 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleRole() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return mnRole; } OUString SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleDescription() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return msName; } OUString SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleName() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); return msName; } Reference SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleRelationSet() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return NULL; } Reference SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleStateSet() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return Reference(new AccessibleStateSet(mnStateSet)); } lang::Locale SAL_CALL PresenterAccessible::AccessibleObject::getLocale() throw (RuntimeException, IllegalAccessibleComponentStateException, std::exception) { ThrowIfDisposed(); if (mxParentAccessible.is()) { Reference 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, std::exception) { ThrowIfDisposed(); if (mxContentWindow.is()) { const awt::Rectangle aBox (getBounds()); return rPoint.X>=aBox.X && rPoint.Y>=aBox.Y && rPoint.X SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleAtPoint (const awt::Point& rPoint) throw (RuntimeException, std::exception) { (void)rPoint; ThrowIfDisposed(); return Reference(); } awt::Rectangle SAL_CALL PresenterAccessible::AccessibleObject::getBounds() throw (RuntimeException, std::exception) { 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() throw (RuntimeException, std::exception) { ThrowIfDisposed(); const awt::Point aLocation (GetRelativeLocation()); return aLocation; } awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocationOnScreen() throw (RuntimeException, std::exception) { 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() throw (RuntimeException, std::exception) { ThrowIfDisposed(); const awt::Size aSize (GetSize()); return aSize; } void SAL_CALL PresenterAccessible::AccessibleObject::grabFocus() throw (RuntimeException, std::exception) { ThrowIfDisposed(); if (mxBorderWindow.is()) mxBorderWindow->setFocus(); else if (mxContentWindow.is()) mxContentWindow->setFocus(); } sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getForeground() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return 0x00ffffff; } sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getBackground() throw (RuntimeException, std::exception) { ThrowIfDisposed(); return 0x00000000; } //----- XAccessibleEventBroadcaster ------------------------------------------- void SAL_CALL PresenterAccessible::AccessibleObject::addAccessibleEventListener ( const Reference& rxListener) throw (RuntimeException, std::exception) { if (rxListener.is()) { const osl::MutexGuard aGuard(m_aMutex); if (IsDisposed()) { uno::Reference xThis (static_cast(this), UNO_QUERY); rxListener->disposing (lang::EventObject(xThis)); } else { maListeners.push_back(rxListener); } } } void SAL_CALL PresenterAccessible::AccessibleObject::removeAccessibleEventListener ( const Reference& rxListener) throw (RuntimeException, std::exception) { 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 (css::uno::RuntimeException, std::exception) { (void)rEvent; FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any()); } void SAL_CALL PresenterAccessible::AccessibleObject::windowMoved ( const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException, std::exception) { (void)rEvent; FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any()); } void SAL_CALL PresenterAccessible::AccessibleObject::windowShown ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) { (void)rEvent; UpdateStateSet(); } void SAL_CALL PresenterAccessible::AccessibleObject::windowHidden ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) { (void)rEvent; UpdateStateSet(); } //----- XEventListener -------------------------------------------------------- void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException, std::exception) { 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() { 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& rpChild) { maChildren.push_back(rpChild); rpChild->SetAccessibleParent(this); FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any()); } void PresenterAccessible::AccessibleObject::RemoveChild ( const ::rtl::Reference& rpChild) { rpChild->SetAccessibleParent(Reference()); 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 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(this); aEventObject.EventId = nEventId; aEventObject.NewValue = rNewValue; aEventObject.OldValue = rOldValue; ::std::vector > aListenerCopy(maListeners); for (::std::vector >::const_iterator iListener(aListenerCopy.begin()), iEnd(aListenerCopy.end()); iListener!=iEnd; ++iListener) { try { (*iListener)->notifyEvent(aEventObject); } catch (const lang::DisposedException&) { // Listener has been disposed and should have been removed // already. removeAccessibleEventListener(*iListener); } catch (const Exception&) { // Ignore all other exceptions and assume that they are // caused by a temporary problem. } } } awt::Point PresenterAccessible::AccessibleObject::GetRelativeLocation() { 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() { 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() { Reference xParentComponent; if (mxParentAccessible.is()) xParentComponent = Reference( mxParentAccessible->getAccessibleContext(), UNO_QUERY); if (xParentComponent.is()) return xParentComponent->getLocationOnScreen(); else return awt::Point(); } bool PresenterAccessible::AccessibleObject::IsDisposed() const { return (rBHelper.bDisposed || rBHelper.bInDispose); } void PresenterAccessible::AccessibleObject::ThrowIfDisposed() const throw (lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose) throw lang::DisposedException("object has already been disposed", uno::Reference((uno::XWeak*)(this))); } //===== AccessibleStateSet ==================================================== AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet) : AccessibleStateSetInterfaceBase(m_aMutex), mnStateSet (nStateSet) { } AccessibleStateSet::~AccessibleStateSet() { } sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState) { if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8)) { throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state"); } return 1<& rStateSet) throw (css::uno::RuntimeException, std::exception) { for (sal_Int32 nIndex=0,nCount=rStateSet.getLength(); nIndex SAL_CALL AccessibleStateSet::getStates() throw (css::uno::RuntimeException, std::exception) { ::std::vector aStates; aStates.reserve(sizeof(mnStateSet)*8); for (sal_uInt16 nIndex=0; nIndex(&aStates.front(), aStates.size()); } //===== AccessibleRelationSet ================================================= AccessibleRelationSet::AccessibleRelationSet() : AccessibleRelationSetInterfaceBase(m_aMutex), maRelations() { } AccessibleRelationSet::~AccessibleRelationSet() { } void AccessibleRelationSet::AddRelation ( const sal_Int16 nRelationType, const Reference& 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() throw (css::uno::RuntimeException, std::exception) { return maRelations.size(); } AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex) throw (css::uno::RuntimeException, css::lang::IndexOutOfBoundsException, std::exception) { if (nIndex<0 && sal_uInt32(nIndex)>=maRelations.size()) return AccessibleRelation(); else return maRelations[nIndex]; } sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType) throw (css::uno::RuntimeException, std::exception) { for (::std::vector::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 (css::uno::RuntimeException, std::exception) { for (::std::vector::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& rLocale, const sal_Int16 nRole, const OUString& rsName, const SharedPresenterTextParagraph& rpParagraph, const sal_Int32 nParagraphIndex) : PresenterAccessibleParagraphInterfaceBase(rLocale, nRole, rsName), mpParagraph(rpParagraph), mnParagraphIndex(nParagraphIndex) { } PresenterAccessible::AccessibleParagraph::~AccessibleParagraph() { } //----- XAccessibleContext ---------------------------------------------------- Reference SAL_CALL PresenterAccessible::AccessibleParagraph::getAccessibleRelationSet() throw (RuntimeException, std::exception) { ThrowIfDisposed(); rtl::Reference pSet (new AccessibleRelationSet); if (mxParentAccessible.is()) { Reference xParentContext (mxParentAccessible->getAccessibleContext()); if (xParentContext.is()) { if (mnParagraphIndex>0) pSet->AddRelation( AccessibleRelationType::CONTENT_FLOWS_FROM, xParentContext->getAccessibleChild(mnParagraphIndex-1)); if (mnParagraphIndexgetAccessibleChildCount()-1) pSet->AddRelation( AccessibleRelationType::CONTENT_FLOWS_TO, xParentContext->getAccessibleChild(mnParagraphIndex+1)); } } return Reference(pSet.get()); } //----- XAccessibleText ------------------------------------------------------- sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCaretPosition() throw (css::uno::RuntimeException, std::exception) { 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, css::uno::RuntimeException, std::exception) { 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, css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); if (!mpParagraph) throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast(this)); return mpParagraph->GetCharacter(nIndex); } Sequence SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterAttributes ( ::sal_Int32 nIndex, const css::uno::Sequence& rRequestedAttributes) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); #if OSL_DEBUG_LEVEL > 1 OSL_TRACE("PresenterAccessible::AccessibleParagraph::getCharacterAttributes at %p,%d returns empty set\r", this,nIndex); for (sal_Int32 nAttributeIndex(0),nAttributeCount(rRequestedAttributes.getLength()); nAttributeIndex(); } awt::Rectangle SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterBounds ( sal_Int32 nIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); awt::Rectangle aCharacterBox; if (nIndex < 0) { throw lang::IndexOutOfBoundsException("invalid text index", static_cast(this)); } 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 { throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast(this)); } return aCharacterBox; } sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterCount() throw (css::uno::RuntimeException, std::exception) { 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 (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); sal_Int32 nIndex (-1); if (mpParagraph) nIndex = mpParagraph->GetIndexAtPoint(rPoint); return nIndex; } OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectedText() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); return getTextRange(getSelectionStart(), getSelectionEnd()); } sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionStart() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); return getCaretPosition(); } sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionEnd() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); return getCaretPosition(); } sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setSelection ( sal_Int32 nStartIndex, sal_Int32 nEndIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) { (void)nEndIndex; ThrowIfDisposed(); return setCaretPosition(nStartIndex); } OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getText() throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); OUString sText; if (mpParagraph) sText = mpParagraph->GetText(); return sText; } OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getTextRange ( sal_Int32 nLocalStartIndex, sal_Int32 nLocalEndIndex) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); 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, css::uno::RuntimeException, std::exception) { 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, css::uno::RuntimeException, std::exception) { 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, css::uno::RuntimeException, std::exception) { 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, css::uno::RuntimeException, std::exception) { 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() { 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() { if (mpParagraph) return mpParagraph->GetSize(); else return AccessibleObject::GetSize(); } awt::Point PresenterAccessible::AccessibleParagraph::GetAbsoluteParentLocation() { if (mxParentAccessible.is()) { Reference xParentContext( mxParentAccessible->getAccessibleContext(), UNO_QUERY); if (xParentContext.is()) { Reference 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& rLocale, const sal_Int16 nRole, const OUString& rsName) : AccessibleObject(rLocale,nRole,rsName), mpTextView() { } rtl::Reference AccessibleNotes::Create ( const css::uno::Reference& rxContext, const lang::Locale& rLocale, const Reference& rxContentWindow, const Reference& rxBorderWindow, const ::boost::shared_ptr& rpTextView) { OUString sName ("Presenter Notes Text"); { PresenterConfigurationAccess aConfiguration ( rxContext, OUString("/org.openoffice.Office.PresenterScreen/"), PresenterConfigurationAccess::READ_ONLY); aConfiguration.GetConfigurationNode("Presenter/Accessibility/Notes/String") >>= sName; } rtl::Reference pObject ( new AccessibleNotes( rLocale, AccessibleRole::PANEL, sName)); pObject->LateInitialization(); pObject->SetTextView(rpTextView); pObject->UpdateStateSet(); pObject->SetWindow(rxContentWindow, rxBorderWindow); return rtl::Reference(pObject.get()); } void AccessibleNotes::SetTextView ( const ::boost::shared_ptr& rpTextView) { ::std::vector > aChildren; // Release any listeners to the current text view. if (mpTextView) { mpTextView->GetCaret()->SetCaretMotionBroadcaster( ::boost::function()); mpTextView->SetTextChangeBroadcaster( ::boost::function()); } 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 pParagraph ( new PresenterAccessible::AccessibleParagraph( css::lang::Locale(), AccessibleRole::PARAGRAPH, "Paragraph"+OUString::number(nIndex), rpTextView->GetParagraph(nIndex), nIndex)); pParagraph->LateInitialization(); pParagraph->SetWindow( Reference(mxContentWindow, UNO_QUERY), Reference(mxBorderWindow, UNO_QUERY)); pParagraph->SetAccessibleParent(this); aChildren.push_back( rtl::Reference(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 >::const_iterator iChild(aChildren.begin()), iEnd(aChildren.end()); iChild!=iEnd; ++iChild) { Reference xComponent (static_cast(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 css::uno::Reference& rxContentWindow, const css::uno::Reference& rxBorderWindow) { AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow); // Set the windows at the children as well, so that every paragraph can // setup its geometry. for (::std::vector >::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 focuse 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() { SetTextView(mpTextView); } //===== AccessibleFocusManager ================================================ ::boost::shared_ptr AccessibleFocusManager::mpInstance; ::boost::shared_ptr AccessibleFocusManager::Instance() { if ( ! mpInstance) { mpInstance.reset(new AccessibleFocusManager()); } return mpInstance; } AccessibleFocusManager::AccessibleFocusManager() : maFocusableObjects() { } void AccessibleFocusManager::AddFocusableObject ( const ::rtl::Reference& 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& rpObject) { ::std::vector >::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& rpObject) { // Remove the focus of any of the other focusable objects. for (::std::vector >::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 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */