Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleContextBase.cxx
blobb8f90b2adb5173adc23682a7a9fef431e903d435
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 .
20 #include "AccessibleContextBase.hxx"
21 #include <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
25 #include <tools/debug.hxx>
26 #include <tools/gen.hxx>
27 #include <unotools/accessiblestatesethelper.hxx>
28 #include <toolkit/helper/convert.hxx>
29 #include <svl/smplhint.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <comphelper/servicehelper.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <unotools/accessiblerelationsethelper.hxx>
34 #include <vcl/unohelp.hxx>
35 #include <comphelper/accessibleeventnotifier.hxx>
36 #include <vcl/svapp.hxx>
38 using namespace ::rtl;
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::accessibility;
42 ScAccessibleContextBase::ScAccessibleContextBase(
43 const uno::Reference<XAccessible>& rxParent,
44 const sal_Int16 aRole)
46 ScAccessibleContextBaseWeakImpl(m_aMutex),
47 mxParent(rxParent),
48 mnClientId(0),
49 maRole(aRole)
54 ScAccessibleContextBase::~ScAccessibleContextBase(void)
56 if (!IsDefunc() && !rBHelper.bInDispose)
58 // increment refcount to prevent double call off dtor
59 osl_atomic_increment( &m_refCount );
60 // call dispose to inform object which have a weak reference to this object
61 dispose();
65 void ScAccessibleContextBase::Init()
67 // hold reference to make sure that the destructor is not called
68 uno::Reference< XAccessibleContext > xOwnContext(this);
70 if (mxParent.is())
72 uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
73 if (xBroadcaster.is())
74 xBroadcaster->addAccessibleEventListener(this);
76 msName = createAccessibleName();
77 msDescription = createAccessibleDescription();
80 void SAL_CALL ScAccessibleContextBase::disposing()
82 SolarMutexGuard aGuard;
83 // CommitDefunc(); not necessary and should not be send, because it cost a lot of time
85 // hold reference to make sure that the destructor is not called
86 uno::Reference< XAccessibleContext > xOwnContext(this);
88 if ( mnClientId )
90 sal_Int32 nTemClientId(mnClientId);
91 mnClientId = 0;
92 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nTemClientId, *this );
95 if (mxParent.is())
97 uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
98 if (xBroadcaster.is())
99 xBroadcaster->removeAccessibleEventListener(this);
100 mxParent = NULL;
103 ScAccessibleContextBaseWeakImpl::disposing();
106 //===== XInterface =====================================================
108 uno::Any SAL_CALL ScAccessibleContextBase::queryInterface( uno::Type const & rType )
109 throw (uno::RuntimeException, std::exception)
111 uno::Any aAny (ScAccessibleContextBaseWeakImpl::queryInterface(rType));
112 return aAny.hasValue() ? aAny : ScAccessibleContextBaseImplEvent::queryInterface(rType);
115 void SAL_CALL ScAccessibleContextBase::acquire()
116 throw ()
118 ScAccessibleContextBaseWeakImpl::acquire();
121 void SAL_CALL ScAccessibleContextBase::release()
122 throw ()
124 ScAccessibleContextBaseWeakImpl::release();
127 //===== SfxListener =====================================================
129 void ScAccessibleContextBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
131 if (rHint.ISA( SfxSimpleHint ) )
133 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
134 if (rRef.GetId() == SFX_HINT_DYING)
136 // it seems the Broadcaster is dying, since the view is dying
137 dispose();
142 //===== XAccessible =========================================================
144 uno::Reference< XAccessibleContext> SAL_CALL
145 ScAccessibleContextBase::getAccessibleContext(void)
146 throw (uno::RuntimeException, std::exception)
148 return this;
151 //===== XAccessibleComponent ================================================
153 sal_Bool SAL_CALL ScAccessibleContextBase::containsPoint(const awt::Point& rPoint )
154 throw (uno::RuntimeException, std::exception)
156 SolarMutexGuard aGuard;
157 IsObjectValid();
158 return Rectangle (Point(), GetBoundingBox().GetSize()).IsInside(VCLPoint(rPoint));
161 uno::Reference< XAccessible > SAL_CALL ScAccessibleContextBase::getAccessibleAtPoint(
162 const awt::Point& /* rPoint */ )
163 throw (uno::RuntimeException, std::exception)
165 OSL_FAIL("not implemented");
166 return uno::Reference<XAccessible>();
169 awt::Rectangle SAL_CALL ScAccessibleContextBase::getBounds( )
170 throw (uno::RuntimeException, std::exception)
172 SolarMutexGuard aGuard;
173 IsObjectValid();
174 return AWTRectangle(GetBoundingBox());
177 awt::Point SAL_CALL ScAccessibleContextBase::getLocation( )
178 throw (uno::RuntimeException, std::exception)
180 SolarMutexGuard aGuard;
181 IsObjectValid();
182 return AWTPoint(GetBoundingBox().TopLeft());
185 awt::Point SAL_CALL ScAccessibleContextBase::getLocationOnScreen( )
186 throw (uno::RuntimeException, std::exception)
188 SolarMutexGuard aGuard;
189 IsObjectValid();
190 return AWTPoint(GetBoundingBoxOnScreen().TopLeft());
193 awt::Size SAL_CALL ScAccessibleContextBase::getSize( )
194 throw (uno::RuntimeException, std::exception)
196 SolarMutexGuard aGuard;
197 IsObjectValid();
198 return AWTSize(GetBoundingBox().GetSize());
201 bool SAL_CALL ScAccessibleContextBase::isShowing( )
202 throw (uno::RuntimeException)
204 SolarMutexGuard aGuard;
205 IsObjectValid();
206 bool bShowing(false);
207 if (mxParent.is())
209 uno::Reference<XAccessibleComponent> xParentComponent (mxParent->getAccessibleContext(), uno::UNO_QUERY);
210 if (xParentComponent.is())
212 Rectangle aParentBounds(VCLRectangle(xParentComponent->getBounds()));
213 Rectangle aBounds(VCLRectangle(getBounds()));
214 bShowing = aBounds.IsOver(aParentBounds);
217 return bShowing;
220 bool SAL_CALL ScAccessibleContextBase::isVisible()
221 throw (uno::RuntimeException, std::exception)
223 return true;
226 void SAL_CALL ScAccessibleContextBase::grabFocus( )
227 throw (uno::RuntimeException, std::exception)
229 OSL_FAIL("not implemented");
232 sal_Int32 SAL_CALL ScAccessibleContextBase::getForeground( )
233 throw (uno::RuntimeException, std::exception)
235 return COL_BLACK;
238 sal_Int32 SAL_CALL ScAccessibleContextBase::getBackground( )
239 throw (uno::RuntimeException, std::exception)
241 return COL_WHITE;
244 //===== XAccessibleContext ==================================================
246 sal_Int32 SAL_CALL ScAccessibleContextBase::getAccessibleChildCount()
247 throw (uno::RuntimeException, std::exception)
249 OSL_FAIL("should be implemented in the abrevated class");
250 return 0;
253 uno::Reference<XAccessible> SAL_CALL
254 ScAccessibleContextBase::getAccessibleChild(sal_Int32 /* nIndex */)
255 throw (lang::IndexOutOfBoundsException, uno::RuntimeException,
256 std::exception)
258 OSL_FAIL("should be implemented in the abrevated class");
259 return uno::Reference<XAccessible>();
262 uno::Reference<XAccessible> SAL_CALL
263 ScAccessibleContextBase::getAccessibleParent(void)
264 throw (uno::RuntimeException, std::exception)
266 return mxParent;
269 sal_Int32 SAL_CALL
270 ScAccessibleContextBase::getAccessibleIndexInParent(void)
271 throw (uno::RuntimeException, std::exception)
273 SolarMutexGuard aGuard;
274 IsObjectValid();
275 // Use a simple but slow solution for now. Optimize later.
276 // Return -1 to indicate that this object's parent does not know about the
277 // object.
278 sal_Int32 nIndex(-1);
280 // Iterate over all the parent's children and search for this object.
281 if (mxParent.is())
283 uno::Reference<XAccessibleContext> xParentContext (
284 mxParent->getAccessibleContext());
285 if (xParentContext.is())
287 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
288 for (sal_Int32 i=0; i<nChildCount; ++i)
290 uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i));
291 if (xChild.is())
293 if (xChild.get() == this)
294 nIndex = i;
300 return nIndex;
303 sal_Int16 SAL_CALL
304 ScAccessibleContextBase::getAccessibleRole(void)
305 throw (uno::RuntimeException, std::exception)
307 return maRole;
310 OUString SAL_CALL
311 ScAccessibleContextBase::getAccessibleDescription(void)
312 throw (uno::RuntimeException, std::exception)
314 SolarMutexGuard aGuard;
315 IsObjectValid();
316 if (msDescription.isEmpty())
318 OUString sDescription(createAccessibleDescription());
320 if (msDescription != sDescription)
322 AccessibleEventObject aEvent;
323 aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
324 aEvent.Source = uno::Reference< XAccessibleContext >(this);
325 aEvent.OldValue <<= msDescription;
326 aEvent.NewValue <<= sDescription;
328 msDescription = sDescription;
330 CommitChange(aEvent);
333 return msDescription;
336 OUString SAL_CALL
337 ScAccessibleContextBase::getAccessibleName(void)
338 throw (uno::RuntimeException, std::exception)
340 SolarMutexGuard aGuard;
341 IsObjectValid();
342 if (msName.isEmpty())
344 OUString sName(createAccessibleName());
345 OSL_ENSURE(!sName.isEmpty(), "We should give always a name.");
347 if (msName != sName)
349 AccessibleEventObject aEvent;
350 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
351 aEvent.Source = uno::Reference< XAccessibleContext >(this);
352 aEvent.OldValue <<= msName;
353 aEvent.NewValue <<= sName;
355 msName = sName;
357 CommitChange(aEvent);
360 return msName;
363 uno::Reference<XAccessibleRelationSet> SAL_CALL
364 ScAccessibleContextBase::getAccessibleRelationSet()
365 throw (uno::RuntimeException, std::exception)
367 return new utl::AccessibleRelationSetHelper();
370 uno::Reference<XAccessibleStateSet> SAL_CALL
371 ScAccessibleContextBase::getAccessibleStateSet(void)
372 throw (uno::RuntimeException, std::exception)
374 return uno::Reference<XAccessibleStateSet>();
377 lang::Locale SAL_CALL
378 ScAccessibleContextBase::getLocale(void)
379 throw (IllegalAccessibleComponentStateException,
380 uno::RuntimeException, std::exception)
382 SolarMutexGuard aGuard;
383 IsObjectValid();
384 if (mxParent.is())
386 uno::Reference<XAccessibleContext> xParentContext (
387 mxParent->getAccessibleContext());
388 if (xParentContext.is())
389 return xParentContext->getLocale ();
392 // No locale and no parent. Therefore throw exception to indicate this
393 // cluelessness.
394 throw IllegalAccessibleComponentStateException ();
397 //===== XAccessibleEventBroadcaster =====================================
399 void SAL_CALL
400 ScAccessibleContextBase::addAccessibleEventListener(
401 const uno::Reference<XAccessibleEventListener>& xListener)
402 throw (uno::RuntimeException, std::exception)
404 if (xListener.is())
406 SolarMutexGuard aGuard;
407 IsObjectValid();
408 if (!IsDefunc())
410 if (!mnClientId)
411 mnClientId = comphelper::AccessibleEventNotifier::registerClient( );
412 comphelper::AccessibleEventNotifier::addEventListener( mnClientId, xListener );
417 void SAL_CALL
418 ScAccessibleContextBase::removeAccessibleEventListener(
419 const uno::Reference<XAccessibleEventListener>& xListener)
420 throw (uno::RuntimeException, std::exception)
422 if (xListener.is())
424 SolarMutexGuard aGuard;
425 if (!IsDefunc() && mnClientId)
427 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, xListener );
428 if ( !nListenerCount )
430 // no listeners anymore
431 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
432 // and at least to us not firing any events anymore, in case somebody calls
433 // NotifyAccessibleEvent, again
434 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
435 mnClientId = 0;
441 //===== XAccessibleEventListener ========================================
443 void SAL_CALL ScAccessibleContextBase::disposing(
444 const lang::EventObject& rSource )
445 throw (uno::RuntimeException, std::exception)
447 SolarMutexGuard aGuard;
448 if (rSource.Source == mxParent)
449 dispose();
452 void SAL_CALL ScAccessibleContextBase::notifyEvent(
453 const AccessibleEventObject& /* aEvent */ )
454 throw (uno::RuntimeException, std::exception)
458 //===== XServiceInfo ========================================================
459 OUString SAL_CALL ScAccessibleContextBase::getImplementationName(void)
460 throw (uno::RuntimeException, std::exception)
462 return OUString("ScAccessibleContextBase");
465 sal_Bool SAL_CALL ScAccessibleContextBase::supportsService(const OUString& sServiceName)
466 throw (uno::RuntimeException, std::exception)
468 return cppu::supportsService(this, sServiceName);
471 uno::Sequence< OUString> SAL_CALL
472 ScAccessibleContextBase::getSupportedServiceNames(void)
473 throw (uno::RuntimeException, std::exception)
475 uno::Sequence<OUString> aServiceNames(2);
476 OUString* pServiceNames = aServiceNames.getArray();
477 if (pServiceNames)
479 pServiceNames[0] = "com.sun.star.accessibility.Accessible";
480 pServiceNames[1] = "com.sun.star.accessibility.AccessibleContext";
483 return aServiceNames;
486 //===== XTypeProvider =======================================================
488 uno::Sequence< uno::Type > SAL_CALL ScAccessibleContextBase::getTypes()
489 throw (uno::RuntimeException, std::exception)
491 return comphelper::concatSequences(ScAccessibleContextBaseWeakImpl::getTypes(), ScAccessibleContextBaseImplEvent::getTypes());
494 uno::Sequence<sal_Int8> SAL_CALL
495 ScAccessibleContextBase::getImplementationId(void)
496 throw (uno::RuntimeException, std::exception)
498 return css::uno::Sequence<sal_Int8>();
501 //===== internal ============================================================
503 OUString SAL_CALL
504 ScAccessibleContextBase::createAccessibleDescription(void)
505 throw (uno::RuntimeException)
507 OSL_FAIL("should be implemented in the abrevated class");
508 return OUString();
511 OUString SAL_CALL ScAccessibleContextBase::createAccessibleName()
512 throw (uno::RuntimeException, std::exception)
514 OSL_FAIL("should be implemented in the abrevated class");
515 return OUString();
518 void ScAccessibleContextBase::CommitChange(const AccessibleEventObject& rEvent) const
520 if (mnClientId)
521 comphelper::AccessibleEventNotifier::addEvent( mnClientId, rEvent );
524 void ScAccessibleContextBase::CommitFocusGained() const
526 AccessibleEventObject aEvent;
527 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
528 aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
529 aEvent.NewValue <<= AccessibleStateType::FOCUSED;
531 CommitChange(aEvent);
533 ::vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent);
536 void ScAccessibleContextBase::CommitFocusLost() const
538 AccessibleEventObject aEvent;
539 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
540 aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
541 aEvent.OldValue <<= AccessibleStateType::FOCUSED;
543 CommitChange(aEvent);
545 vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent);
548 Rectangle ScAccessibleContextBase::GetBoundingBoxOnScreen() const
549 throw (uno::RuntimeException, std::exception)
551 OSL_FAIL("not implemented");
552 return Rectangle();
555 Rectangle ScAccessibleContextBase::GetBoundingBox() const
556 throw (uno::RuntimeException, std::exception)
558 OSL_FAIL("not implemented");
559 return Rectangle();
562 void ScAccessibleContextBase::IsObjectValid() const
563 throw (lang::DisposedException)
565 if (rBHelper.bDisposed || rBHelper.bInDispose)
566 throw lang::DisposedException();
569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */