summaryrefslogtreecommitdiff
path: root/sd/source/ui/accessibility/AccessibleTreeNode.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/accessibility/AccessibleTreeNode.cxx')
-rwxr-xr-xsd/source/ui/accessibility/AccessibleTreeNode.cxx722
1 files changed, 722 insertions, 0 deletions
diff --git a/sd/source/ui/accessibility/AccessibleTreeNode.cxx b/sd/source/ui/accessibility/AccessibleTreeNode.cxx
new file mode 100755
index 000000000000..5c7462581d0b
--- /dev/null
+++ b/sd/source/ui/accessibility/AccessibleTreeNode.cxx
@@ -0,0 +1,722 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "AccessibleTreeNode.hxx"
+
+#include "taskpane/TaskPaneTreeNode.hxx"
+#include "taskpane/ControlContainer.hxx"
+
+#include "sdresid.hxx"
+#include "accessibility.hrc"
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <comphelper/accessibleeventnotifier.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <svtools/colorcfg.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::sd::toolpanel;
+
+namespace accessibility {
+
+
+
+//===== AccessibleTreeNode =============================================
+
+AccessibleTreeNode::AccessibleTreeNode(
+ ::sd::toolpanel::TreeNode& rNode,
+ const OUString& rsName,
+ const OUString& rsDescription,
+ sal_Int16 eRole)
+ : AccessibleTreeNodeBase(MutexOwner::maMutex),
+ mxParent(NULL),
+ mrTreeNode(rNode),
+ mrStateSet(new ::utl::AccessibleStateSetHelper()),
+ msName(rsName),
+ msDescription(rsDescription),
+ meRole(eRole),
+ mnClientId(0)
+{
+ ::Window* pWindow = mrTreeNode.GetWindow();
+ if (pWindow != NULL)
+ {
+ ::Window* pParentWindow = pWindow->GetAccessibleParentWindow();
+ if (pParentWindow != NULL && pParentWindow != pWindow)
+ mxParent = pParentWindow->GetAccessible();
+ }
+ CommonConstructor();
+}
+
+
+
+
+AccessibleTreeNode::AccessibleTreeNode(
+ const Reference<XAccessible>& rxParent,
+ ::sd::toolpanel::TreeNode& rNode,
+ const OUString& rsName,
+ const OUString& rsDescription,
+ const sal_Int16 eRole)
+ : AccessibleTreeNodeBase(MutexOwner::maMutex),
+ mxParent(rxParent),
+ mrTreeNode(rNode),
+ mrStateSet(new ::utl::AccessibleStateSetHelper()),
+ msName(rsName),
+ msDescription(rsDescription),
+ meRole(eRole),
+ mnClientId(0)
+{
+ CommonConstructor();
+}
+
+
+
+
+void AccessibleTreeNode::CommonConstructor (void)
+{
+ UpdateStateSet();
+
+ Link aStateChangeLink (LINK(this,AccessibleTreeNode,StateChangeListener));
+ mrTreeNode.AddStateChangeListener(aStateChangeLink);
+
+ if (mrTreeNode.GetWindow() != NULL)
+ {
+ Link aWindowEventLink (LINK(this,AccessibleTreeNode,WindowEventListener));
+ mrTreeNode.GetWindow()->AddEventListener(aWindowEventLink);
+ }
+}
+
+
+
+
+AccessibleTreeNode::~AccessibleTreeNode (void)
+{
+ OSL_ASSERT(IsDisposed());
+}
+
+
+
+
+void AccessibleTreeNode::FireAccessibleEvent (
+ short nEventId,
+ const uno::Any& rOldValue,
+ const uno::Any& rNewValue )
+{
+ if (mnClientId != 0)
+ {
+ AccessibleEventObject aEventObject;
+
+ aEventObject.Source = Reference<XWeak>(this);
+ aEventObject.EventId = nEventId;
+ aEventObject.NewValue = rNewValue;
+ aEventObject.OldValue = rOldValue;
+
+ comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
+ }
+}
+
+
+
+
+void SAL_CALL AccessibleTreeNode::disposing (void)
+{
+ // We are still listening to the tree node and its window. Both
+ // probably are by now more or less dead and we must not call them to
+ // unregister.
+
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
+ mnClientId = 0;
+}
+
+
+
+
+//===== XAccessible =========================================================
+
+Reference<XAccessibleContext > SAL_CALL
+ AccessibleTreeNode::getAccessibleContext (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ return this;
+}
+
+
+
+
+//===== XAccessibleContext ==================================================
+
+sal_Int32 SAL_CALL AccessibleTreeNode::getAccessibleChildCount (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ return mrTreeNode.GetControlContainer().GetControlCount();
+}
+
+
+
+
+Reference<XAccessible > SAL_CALL
+ AccessibleTreeNode::getAccessibleChild (sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+
+ if (nIndex<0 || (sal_uInt32)nIndex>=mrTreeNode.GetControlContainer().GetControlCount())
+ throw lang::IndexOutOfBoundsException();
+
+ Reference<XAccessible> xChild;
+
+ ::sd::toolpanel::TreeNode* pNode = mrTreeNode.GetControlContainer().GetControl(nIndex);
+ if (pNode != NULL)
+ xChild = pNode->GetAccessibleObject();
+
+ return xChild;
+}
+
+
+
+
+Reference<XAccessible > SAL_CALL AccessibleTreeNode::getAccessibleParent (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ return mxParent;
+}
+
+
+
+
+sal_Int32 SAL_CALL AccessibleTreeNode::getAccessibleIndexInParent (void)
+ throw (uno::RuntimeException)
+{
+ OSL_ASSERT(getAccessibleParent().is());
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ sal_Int32 nIndexInParent(-1);
+
+
+ Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
+ if (xParentContext.is())
+ {
+ sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
+ for (sal_Int32 i=0; i<nChildCount; ++i)
+ if (xParentContext->getAccessibleChild(i).get()
+ == static_cast<XAccessible*>(this))
+ {
+ nIndexInParent = i;
+ break;
+ }
+ }
+
+ return nIndexInParent;
+}
+
+
+
+
+sal_Int16 SAL_CALL AccessibleTreeNode::getAccessibleRole (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return meRole;
+}
+
+
+
+
+::rtl::OUString SAL_CALL AccessibleTreeNode::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return msDescription;
+}
+
+
+
+
+::rtl::OUString SAL_CALL AccessibleTreeNode::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return msName;
+}
+
+
+
+
+Reference<XAccessibleRelationSet> SAL_CALL
+ AccessibleTreeNode::getAccessibleRelationSet (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return Reference<XAccessibleRelationSet>();
+}
+
+
+
+
+Reference<XAccessibleStateSet > SAL_CALL
+ AccessibleTreeNode::getAccessibleStateSet (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ return mrStateSet.get();
+}
+
+
+
+
+void AccessibleTreeNode::UpdateStateSet (void)
+{
+ if (mrTreeNode.IsExpandable())
+ {
+ UpdateState(AccessibleStateType::EXPANDABLE, true);
+ UpdateState(AccessibleStateType::EXPANDED, mrTreeNode.IsExpanded());
+ }
+
+ UpdateState(AccessibleStateType::FOCUSABLE, true);
+
+ ::Window* pWindow = mrTreeNode.GetWindow();
+ if (pWindow != NULL)
+ {
+ UpdateState(AccessibleStateType::ENABLED, pWindow->IsEnabled());
+ UpdateState(AccessibleStateType::FOCUSED, pWindow->HasFocus());
+ UpdateState(AccessibleStateType::VISIBLE, pWindow->IsVisible());
+ UpdateState(AccessibleStateType::SHOWING, pWindow->IsReallyVisible());
+ }
+}
+
+
+
+
+void AccessibleTreeNode::UpdateState(
+ sal_Int16 aState,
+ bool bValue)
+{
+ if ((mrStateSet->contains(aState)!=sal_False) != bValue)
+ {
+ if (bValue)
+ {
+ mrStateSet->AddState(aState);
+ FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(),Any(aState));
+ }
+ else
+ {
+ mrStateSet->RemoveState(aState);
+ FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(aState),Any());
+ }
+ }
+}
+
+
+
+
+lang::Locale SAL_CALL AccessibleTreeNode::getLocale (void)
+ throw (IllegalAccessibleComponentStateException,
+ RuntimeException)
+{
+ ThrowIfDisposed ();
+ Reference<XAccessibleContext> xParentContext;
+ Reference<XAccessible> xParent (getAccessibleParent());
+ if (xParent.is())
+ xParentContext = xParent->getAccessibleContext();
+
+ if (xParentContext.is())
+ return xParentContext->getLocale();
+ else
+ // Strange, no parent! Anyway, return the default locale.
+ return Application::GetSettings().GetLocale();
+}
+
+
+
+
+void SAL_CALL AccessibleTreeNode::addEventListener(
+ const Reference<XAccessibleEventListener >& rxListener)
+ throw (RuntimeException)
+{
+ if (rxListener.is())
+ {
+ const osl::MutexGuard aGuard(maMutex);
+
+ if (IsDisposed())
+ {
+ uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
+ rxListener->disposing (lang::EventObject (x));
+ }
+ else
+ {
+ if ( ! mnClientId)
+ mnClientId = comphelper::AccessibleEventNotifier::registerClient();
+ comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
+ }
+ }
+}
+
+
+
+
+void SAL_CALL AccessibleTreeNode::removeEventListener(
+ const Reference<XAccessibleEventListener >& rxListener)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (rxListener.is())
+ {
+ const osl::MutexGuard aGuard(maMutex);
+
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
+ mnClientId = 0;
+ }
+ }
+}
+
+
+
+
+//===== XAccessibleComponent ==================================================
+
+sal_Bool SAL_CALL AccessibleTreeNode::containsPoint (const awt::Point& aPoint)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aBBox (getBounds());
+ return (aPoint.X >= 0)
+ && (aPoint.X < aBBox.Width)
+ && (aPoint.Y >= 0)
+ && (aPoint.Y < aBBox.Height);
+}
+
+
+
+
+Reference<XAccessible> SAL_CALL
+ AccessibleTreeNode::getAccessibleAtPoint (const awt::Point& aPoint)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ Reference<XAccessible> xChildAtPoint;
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+
+ sal_Int32 nChildCount = getAccessibleChildCount();
+ for (sal_Int32 nIndex=0; nIndex<nChildCount; ++nIndex)
+ {
+ Reference<XAccessibleComponent> xChildComponent(
+ getAccessibleChild(nIndex), UNO_QUERY);
+ if (xChildComponent.is())
+ {
+ awt::Point aChildPoint(aPoint);
+ awt::Point aChildOrigin(xChildComponent->getLocation());
+ aChildPoint.X -= aChildOrigin.X;
+ aChildPoint.Y -= aChildOrigin.Y;
+ if (xChildComponent->containsPoint(aChildPoint))
+ {
+ xChildAtPoint = getAccessibleChild(nIndex);
+ break;
+ }
+ }
+ }
+
+ return xChildAtPoint;
+}
+
+
+
+
+awt::Rectangle SAL_CALL AccessibleTreeNode::getBounds (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed ();
+
+ awt::Rectangle aBBox;
+
+ ::Window* pWindow = mrTreeNode.GetWindow();
+ if (pWindow != NULL)
+ {
+ Point aPosition;
+ if (mxParent.is())
+ {
+ aPosition = pWindow->OutputToAbsoluteScreenPixel(Point(0,0));
+ Reference<XAccessibleComponent> xParentComponent (
+ mxParent->getAccessibleContext(), UNO_QUERY);
+ if (xParentComponent.is())
+ {
+ awt::Point aParentPosition (xParentComponent->getLocationOnScreen());
+ aPosition.X() -= aParentPosition.X;
+ aPosition.Y() -= aParentPosition.Y;
+ }
+ }
+ else
+ aPosition = pWindow->GetPosPixel();
+ aBBox.X = aPosition.X();
+ aBBox.Y = aPosition.Y();
+
+ Size aSize (pWindow->GetSizePixel());
+ aBBox.Width = aSize.Width();
+ aBBox.Height = aSize.Height();
+ }
+
+ return aBBox;
+}
+
+
+
+
+awt::Point SAL_CALL AccessibleTreeNode::getLocation (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aBBox (getBounds());
+ return awt::Point(aBBox.X,aBBox.Y);
+}
+
+
+
+
+/** Calculate the location on screen from the parent's location on screen
+ and our own relative location.
+*/
+awt::Point SAL_CALL AccessibleTreeNode::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ awt::Point aLocationOnScreen;
+
+ ::Window* pWindow = mrTreeNode.GetWindow();
+ if (pWindow != NULL)
+ {
+ Point aPoint (pWindow->OutputToAbsoluteScreenPixel(Point(0,0)));
+ aLocationOnScreen.X = aPoint.X();
+ aLocationOnScreen.Y = aPoint.Y();
+ }
+
+ return aLocationOnScreen;
+}
+
+
+
+
+awt::Size SAL_CALL AccessibleTreeNode::getSize (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aBBox (getBounds());
+ return awt::Size(aBBox.Width,aBBox.Height);
+}
+
+
+
+
+void SAL_CALL AccessibleTreeNode::grabFocus (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard (Application::GetSolarMutex());
+
+ if (mrTreeNode.GetWindow() != NULL)
+ mrTreeNode.GetWindow()->GrabFocus();
+}
+
+
+
+
+sal_Int32 SAL_CALL AccessibleTreeNode::getForeground (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ svtools::ColorConfig aColorConfig;
+ UINT32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
+ return static_cast<sal_Int32>(nColor);
+}
+
+
+
+
+sal_Int32 SAL_CALL AccessibleTreeNode::getBackground (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ UINT32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+
+
+
+//===== XServiceInfo ========================================================
+
+::rtl::OUString SAL_CALL
+ AccessibleTreeNode::getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTreeNode"));
+}
+
+
+
+
+sal_Bool SAL_CALL
+ AccessibleTreeNode::supportsService (const OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+
+ // Iterate over all supported service names and return true if on of them
+ // matches the given name.
+ uno::Sequence< ::rtl::OUString> aSupportedServices (
+ getSupportedServiceNames ());
+ for (int i=0; i<aSupportedServices.getLength(); i++)
+ if (sServiceName == aSupportedServices[i])
+ return sal_True;
+ return sal_False;
+}
+
+
+
+
+uno::Sequence< ::rtl::OUString> SAL_CALL
+ AccessibleTreeNode::getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ static const OUString sServiceNames[2] = {
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.accessibility.Accessible")),
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.accessibility.AccessibleContext")),
+ };
+ return uno::Sequence<OUString> (sServiceNames, 2);
+}
+
+
+
+
+void AccessibleTreeNode::ThrowIfDisposed (void)
+ throw (lang::DisposedException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ OSL_TRACE ("Calling disposed object. Throwing exception:");
+ throw lang::DisposedException (
+ OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
+ static_cast<uno::XWeak*>(this));
+ }
+}
+
+
+
+sal_Bool AccessibleTreeNode::IsDisposed (void)
+{
+ return (rBHelper.bDisposed || rBHelper.bInDispose);
+}
+
+
+
+
+IMPL_LINK(AccessibleTreeNode, StateChangeListener, TreeNodeStateChangeEvent*, pEvent)
+{
+ OSL_ASSERT(pEvent!=NULL);
+ OSL_ASSERT(&pEvent->mrSource==&mrTreeNode);
+
+ switch(pEvent->meEventId)
+ {
+ case EID_CHILD_ADDED:
+ if (pEvent->mpChild != NULL)
+ FireAccessibleEvent(AccessibleEventId::CHILD,
+ Any(),
+ Any(pEvent->mpChild->GetAccessibleObject()));
+ else
+ FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN,Any(),Any());
+ break;
+
+ case EID_ALL_CHILDREN_REMOVED:
+ FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN,Any(),Any());
+ break;
+
+ case EID_EXPANSION_STATE_CHANGED:
+ case EID_FOCUSED_STATE_CHANGED:
+ case EID_SHOWING_STATE_CHANGED:
+ UpdateStateSet();
+ break;
+ }
+ return 1;
+}
+
+
+
+
+IMPL_LINK(AccessibleTreeNode, WindowEventListener, VclWindowEvent*, pEvent)
+{
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_HIDE:
+ // This event may be sent while the window is destroyed so do
+ // not call UpdateStateSet() which calls back to the window but
+ // just set the two states VISIBLE and SHOWING to false.
+ UpdateState(AccessibleStateType::VISIBLE, false);
+ UpdateState(AccessibleStateType::SHOWING, false);
+ break;
+
+ case VCLEVENT_WINDOW_SHOW:
+ case VCLEVENT_WINDOW_DATACHANGED:
+ UpdateStateSet();
+ break;
+
+ case VCLEVENT_WINDOW_MOVE:
+ case VCLEVENT_WINDOW_RESIZE:
+ FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED,Any(),Any());
+ break;
+
+ case VCLEVENT_WINDOW_GETFOCUS:
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ UpdateStateSet();
+ break;
+ }
+ return 1;
+}
+
+} // end of namespace ::accessibility