fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / ui / accessibility / AccessibleTreeNode.cxx
blob282208555d924829909fd5becb147f377204cce0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "AccessibleTreeNode.hxx"
23 #include "taskpane/TaskPaneTreeNode.hxx"
24 #include "taskpane/ControlContainer.hxx"
26 #include "sdresid.hxx"
27 #include "accessibility.hrc"
28 #include <com/sun/star/accessibility/AccessibleRole.hpp>
29 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
30 #include <comphelper/accessibleeventnotifier.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/window.hxx>
34 #include <svtools/colorcfg.hxx>
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::accessibility;
39 using namespace ::sd::toolpanel;
41 namespace accessibility {
45 //===== AccessibleTreeNode =============================================
47 AccessibleTreeNode::AccessibleTreeNode(
48 ::sd::toolpanel::TreeNode& rNode,
49 const OUString& rsName,
50 const OUString& rsDescription,
51 sal_Int16 eRole)
52 : AccessibleTreeNodeBase(MutexOwner::maMutex),
53 mxParent(NULL),
54 mrTreeNode(rNode),
55 mrStateSet(new ::utl::AccessibleStateSetHelper()),
56 msName(rsName),
57 msDescription(rsDescription),
58 meRole(eRole),
59 mnClientId(0)
61 ::Window* pWindow = mrTreeNode.GetWindow();
62 if (pWindow != NULL)
64 ::Window* pParentWindow = pWindow->GetAccessibleParentWindow();
65 if (pParentWindow != NULL && pParentWindow != pWindow)
66 mxParent = pParentWindow->GetAccessible();
68 CommonConstructor();
74 void AccessibleTreeNode::CommonConstructor (void)
76 UpdateStateSet();
78 Link aStateChangeLink (LINK(this,AccessibleTreeNode,StateChangeListener));
79 mrTreeNode.AddStateChangeListener(aStateChangeLink);
81 if (mrTreeNode.GetWindow() != NULL)
83 Link aWindowEventLink (LINK(this,AccessibleTreeNode,WindowEventListener));
84 mrTreeNode.GetWindow()->AddEventListener(aWindowEventLink);
91 AccessibleTreeNode::~AccessibleTreeNode (void)
93 OSL_ASSERT(IsDisposed());
99 void AccessibleTreeNode::FireAccessibleEvent (
100 short nEventId,
101 const uno::Any& rOldValue,
102 const uno::Any& rNewValue )
104 if (mnClientId != 0)
106 AccessibleEventObject aEventObject;
108 aEventObject.Source = Reference<XWeak>(this);
109 aEventObject.EventId = nEventId;
110 aEventObject.NewValue = rNewValue;
111 aEventObject.OldValue = rOldValue;
113 comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
120 void SAL_CALL AccessibleTreeNode::disposing (void)
122 // We are still listening to the tree node and its window. Both
123 // probably are by now more or less dead and we must not call them to
124 // unregister.
126 if (mnClientId != 0)
128 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
129 mnClientId = 0;
136 //===== XAccessible =========================================================
138 Reference<XAccessibleContext > SAL_CALL
139 AccessibleTreeNode::getAccessibleContext (void)
140 throw (uno::RuntimeException)
142 ThrowIfDisposed ();
143 return this;
149 //===== XAccessibleContext ==================================================
151 sal_Int32 SAL_CALL AccessibleTreeNode::getAccessibleChildCount (void)
152 throw (RuntimeException)
154 ThrowIfDisposed();
155 const SolarMutexGuard aSolarGuard;
156 return mrTreeNode.GetControlContainer().GetControlCount();
162 Reference<XAccessible > SAL_CALL
163 AccessibleTreeNode::getAccessibleChild (sal_Int32 nIndex)
164 throw (lang::IndexOutOfBoundsException, RuntimeException)
166 ThrowIfDisposed();
167 const SolarMutexGuard aSolarGuard;
169 if (nIndex<0 || (sal_uInt32)nIndex>=mrTreeNode.GetControlContainer().GetControlCount())
170 throw lang::IndexOutOfBoundsException();
172 Reference<XAccessible> xChild;
174 ::sd::toolpanel::TreeNode* pNode = mrTreeNode.GetControlContainer().GetControl(nIndex);
175 if (pNode != NULL)
176 xChild = pNode->GetAccessibleObject();
178 return xChild;
184 Reference<XAccessible > SAL_CALL AccessibleTreeNode::getAccessibleParent (void)
185 throw (uno::RuntimeException)
187 ThrowIfDisposed();
188 const SolarMutexGuard aSolarGuard;
189 return mxParent;
195 sal_Int32 SAL_CALL AccessibleTreeNode::getAccessibleIndexInParent (void)
196 throw (uno::RuntimeException)
198 OSL_ASSERT(getAccessibleParent().is());
199 ThrowIfDisposed();
200 const SolarMutexGuard aSolarGuard;
201 sal_Int32 nIndexInParent(-1);
204 Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
205 if (xParentContext.is())
207 sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
208 for (sal_Int32 i=0; i<nChildCount; ++i)
209 if (xParentContext->getAccessibleChild(i).get()
210 == static_cast<XAccessible*>(this))
212 nIndexInParent = i;
213 break;
217 return nIndexInParent;
223 sal_Int16 SAL_CALL AccessibleTreeNode::getAccessibleRole (void)
224 throw (uno::RuntimeException)
226 ThrowIfDisposed();
227 return meRole;
233 OUString SAL_CALL AccessibleTreeNode::getAccessibleDescription (void)
234 throw (uno::RuntimeException)
236 ThrowIfDisposed();
237 return msDescription;
243 OUString SAL_CALL AccessibleTreeNode::getAccessibleName (void)
244 throw (uno::RuntimeException)
246 ThrowIfDisposed();
247 return msName;
253 Reference<XAccessibleRelationSet> SAL_CALL
254 AccessibleTreeNode::getAccessibleRelationSet (void)
255 throw (uno::RuntimeException)
257 ThrowIfDisposed();
258 return Reference<XAccessibleRelationSet>();
264 Reference<XAccessibleStateSet > SAL_CALL
265 AccessibleTreeNode::getAccessibleStateSet (void)
266 throw (uno::RuntimeException)
268 ThrowIfDisposed();
269 const SolarMutexGuard aSolarGuard;
270 return mrStateSet.get();
276 void AccessibleTreeNode::UpdateStateSet (void)
278 if (mrTreeNode.IsExpandable())
280 UpdateState(AccessibleStateType::EXPANDABLE, true);
281 UpdateState(AccessibleStateType::EXPANDED, mrTreeNode.IsExpanded());
284 UpdateState(AccessibleStateType::FOCUSABLE, true);
286 ::Window* pWindow = mrTreeNode.GetWindow();
287 if (pWindow != NULL)
289 UpdateState(AccessibleStateType::ENABLED, pWindow->IsEnabled());
290 UpdateState(AccessibleStateType::FOCUSED, pWindow->HasFocus());
291 UpdateState(AccessibleStateType::VISIBLE, pWindow->IsVisible());
292 UpdateState(AccessibleStateType::SHOWING, pWindow->IsReallyVisible());
299 void AccessibleTreeNode::UpdateState(
300 sal_Int16 aState,
301 bool bValue)
303 if ((mrStateSet->contains(aState)!=sal_False) != bValue)
305 if (bValue)
307 mrStateSet->AddState(aState);
308 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(),Any(aState));
310 else
312 mrStateSet->RemoveState(aState);
313 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(aState),Any());
321 lang::Locale SAL_CALL AccessibleTreeNode::getLocale (void)
322 throw (IllegalAccessibleComponentStateException,
323 RuntimeException)
325 ThrowIfDisposed ();
326 Reference<XAccessibleContext> xParentContext;
327 Reference<XAccessible> xParent (getAccessibleParent());
328 if (xParent.is())
329 xParentContext = xParent->getAccessibleContext();
331 if (xParentContext.is())
332 return xParentContext->getLocale();
333 else
334 // Strange, no parent! Anyway, return the default locale.
335 return Application::GetSettings().GetLanguageTag().getLocale();
341 void SAL_CALL AccessibleTreeNode::addAccessibleEventListener(
342 const Reference<XAccessibleEventListener >& rxListener)
343 throw (RuntimeException)
345 if (rxListener.is())
347 const osl::MutexGuard aGuard(maMutex);
349 if (IsDisposed())
351 uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
352 rxListener->disposing (lang::EventObject (x));
354 else
356 if (mnClientId == 0)
357 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
358 if (mnClientId != 0)
359 comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
367 void SAL_CALL AccessibleTreeNode::removeAccessibleEventListener(
368 const Reference<XAccessibleEventListener >& rxListener)
369 throw (RuntimeException)
371 ThrowIfDisposed();
372 if (rxListener.is())
374 const osl::MutexGuard aGuard(maMutex);
376 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener );
377 if ( !nListenerCount )
379 // no listeners anymore
380 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
381 // and at least to us not firing any events anymore, in case somebody calls
382 // NotifyAccessibleEvent, again
383 if (mnClientId != 0)
385 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
386 mnClientId = 0;
395 //===== XAccessibleComponent ==================================================
397 sal_Bool SAL_CALL AccessibleTreeNode::containsPoint (const awt::Point& aPoint)
398 throw (RuntimeException)
400 ThrowIfDisposed();
401 const awt::Rectangle aBBox (getBounds());
402 return (aPoint.X >= 0)
403 && (aPoint.X < aBBox.Width)
404 && (aPoint.Y >= 0)
405 && (aPoint.Y < aBBox.Height);
411 Reference<XAccessible> SAL_CALL
412 AccessibleTreeNode::getAccessibleAtPoint (const awt::Point& aPoint)
413 throw (RuntimeException)
415 ThrowIfDisposed();
416 Reference<XAccessible> xChildAtPoint;
417 const SolarMutexGuard aSolarGuard;
419 sal_Int32 nChildCount = getAccessibleChildCount();
420 for (sal_Int32 nIndex=0; nIndex<nChildCount; ++nIndex)
422 Reference<XAccessibleComponent> xChildComponent(
423 getAccessibleChild(nIndex), UNO_QUERY);
424 if (xChildComponent.is())
426 awt::Point aChildPoint(aPoint);
427 awt::Point aChildOrigin(xChildComponent->getLocation());
428 aChildPoint.X -= aChildOrigin.X;
429 aChildPoint.Y -= aChildOrigin.Y;
430 if (xChildComponent->containsPoint(aChildPoint))
432 xChildAtPoint = getAccessibleChild(nIndex);
433 break;
438 return xChildAtPoint;
444 awt::Rectangle SAL_CALL AccessibleTreeNode::getBounds (void)
445 throw (RuntimeException)
447 ThrowIfDisposed ();
449 awt::Rectangle aBBox;
451 ::Window* pWindow = mrTreeNode.GetWindow();
452 if (pWindow != NULL)
454 Point aPosition;
455 if (mxParent.is())
457 aPosition = pWindow->OutputToAbsoluteScreenPixel(Point(0,0));
458 Reference<XAccessibleComponent> xParentComponent (
459 mxParent->getAccessibleContext(), UNO_QUERY);
460 if (xParentComponent.is())
462 awt::Point aParentPosition (xParentComponent->getLocationOnScreen());
463 aPosition.X() -= aParentPosition.X;
464 aPosition.Y() -= aParentPosition.Y;
467 else
468 aPosition = pWindow->GetPosPixel();
469 aBBox.X = aPosition.X();
470 aBBox.Y = aPosition.Y();
472 Size aSize (pWindow->GetSizePixel());
473 aBBox.Width = aSize.Width();
474 aBBox.Height = aSize.Height();
477 return aBBox;
483 awt::Point SAL_CALL AccessibleTreeNode::getLocation (void)
484 throw (uno::RuntimeException)
486 ThrowIfDisposed();
487 const awt::Rectangle aBBox (getBounds());
488 return awt::Point(aBBox.X,aBBox.Y);
494 /** Calculate the location on screen from the parent's location on screen
495 and our own relative location.
497 awt::Point SAL_CALL AccessibleTreeNode::getLocationOnScreen()
498 throw (uno::RuntimeException)
500 ThrowIfDisposed();
501 const SolarMutexGuard aSolarGuard;
502 awt::Point aLocationOnScreen;
504 ::Window* pWindow = mrTreeNode.GetWindow();
505 if (pWindow != NULL)
507 Point aPoint (pWindow->OutputToAbsoluteScreenPixel(Point(0,0)));
508 aLocationOnScreen.X = aPoint.X();
509 aLocationOnScreen.Y = aPoint.Y();
512 return aLocationOnScreen;
518 awt::Size SAL_CALL AccessibleTreeNode::getSize (void)
519 throw (uno::RuntimeException)
521 ThrowIfDisposed();
522 const awt::Rectangle aBBox (getBounds());
523 return awt::Size(aBBox.Width,aBBox.Height);
529 void SAL_CALL AccessibleTreeNode::grabFocus (void)
530 throw (uno::RuntimeException)
532 ThrowIfDisposed();
533 const SolarMutexGuard aSolarGuard;
535 if (mrTreeNode.GetWindow() != NULL)
536 mrTreeNode.GetWindow()->GrabFocus();
542 sal_Int32 SAL_CALL AccessibleTreeNode::getForeground (void)
543 throw (RuntimeException)
545 ThrowIfDisposed();
546 svtools::ColorConfig aColorConfig;
547 sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
548 return static_cast<sal_Int32>(nColor);
554 sal_Int32 SAL_CALL AccessibleTreeNode::getBackground (void)
555 throw (RuntimeException)
557 ThrowIfDisposed();
558 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
559 return static_cast<sal_Int32>(nColor);
565 //===== XServiceInfo ========================================================
567 OUString SAL_CALL
568 AccessibleTreeNode::getImplementationName (void)
569 throw (::com::sun::star::uno::RuntimeException)
571 return OUString("AccessibleTreeNode");
577 sal_Bool SAL_CALL
578 AccessibleTreeNode::supportsService (const OUString& sServiceName)
579 throw (::com::sun::star::uno::RuntimeException)
581 ThrowIfDisposed ();
583 // Iterate over all supported service names and return true if on of them
584 // matches the given name.
585 uno::Sequence< OUString> aSupportedServices (
586 getSupportedServiceNames ());
587 for (int i=0; i<aSupportedServices.getLength(); i++)
588 if (sServiceName == aSupportedServices[i])
589 return sal_True;
590 return sal_False;
596 uno::Sequence< OUString> SAL_CALL
597 AccessibleTreeNode::getSupportedServiceNames (void)
598 throw (::com::sun::star::uno::RuntimeException)
600 ThrowIfDisposed ();
601 static const OUString sServiceNames[2] = {
602 OUString("com.sun.star.accessibility.Accessible"),
603 OUString("com.sun.star.accessibility.AccessibleContext"),
605 return uno::Sequence<OUString> (sServiceNames, 2);
611 void AccessibleTreeNode::ThrowIfDisposed (void)
612 throw (lang::DisposedException)
614 if (rBHelper.bDisposed || rBHelper.bInDispose)
616 OSL_TRACE ("Calling disposed object. Throwing exception:");
617 throw lang::DisposedException ("object has been already disposed",
618 static_cast<uno::XWeak*>(this));
624 sal_Bool AccessibleTreeNode::IsDisposed (void)
626 return (rBHelper.bDisposed || rBHelper.bInDispose);
632 IMPL_LINK(AccessibleTreeNode, StateChangeListener, TreeNodeStateChangeEvent*, pEvent)
634 if (rBHelper.bDisposed || rBHelper.bInDispose)
635 return 1; // mrTreeNode is probably dead
637 OSL_ASSERT(pEvent!=NULL);
638 OSL_ASSERT(&pEvent->mrSource==&mrTreeNode);
640 switch(pEvent->meEventId)
642 case EID_CHILD_ADDED:
643 if (pEvent->mpChild != NULL)
644 FireAccessibleEvent(AccessibleEventId::CHILD,
645 Any(),
646 Any(pEvent->mpChild->GetAccessibleObject()));
647 else
648 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN,Any(),Any());
649 break;
651 case EID_ALL_CHILDREN_REMOVED:
652 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN,Any(),Any());
653 break;
655 case EID_EXPANSION_STATE_CHANGED:
656 case EID_FOCUSED_STATE_CHANGED:
657 case EID_SHOWING_STATE_CHANGED:
658 UpdateStateSet();
659 break;
661 return 1;
667 IMPL_LINK(AccessibleTreeNode, WindowEventListener, VclWindowEvent*, pEvent)
669 if (rBHelper.bDisposed || rBHelper.bInDispose)
670 return 1; // mrTreeNode is probably dead
672 switch (pEvent->GetId())
674 case VCLEVENT_WINDOW_HIDE:
675 // This event may be sent while the window is destroyed so do
676 // not call UpdateStateSet() which calls back to the window but
677 // just set the two states VISIBLE and SHOWING to false.
678 UpdateState(AccessibleStateType::VISIBLE, false);
679 UpdateState(AccessibleStateType::SHOWING, false);
680 break;
682 case VCLEVENT_WINDOW_SHOW:
683 case VCLEVENT_WINDOW_DATACHANGED:
684 UpdateStateSet();
685 break;
687 case VCLEVENT_WINDOW_MOVE:
688 case VCLEVENT_WINDOW_RESIZE:
689 FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED,Any(),Any());
690 break;
692 case VCLEVENT_WINDOW_GETFOCUS:
693 case VCLEVENT_WINDOW_LOSEFOCUS:
694 UpdateStateSet();
695 break;
697 return 1;
700 } // end of namespace ::accessibility
702 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */