merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / Accessibility / AccessibleContextBase.cxx
blob8978bfacce6848923bb159e9b9e5911c19d5a343
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleContextBase.cxx,v $
10 * $Revision: 1.33.32.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 #include "AccessibleContextBase.hxx"
36 #include "unoguard.hxx"
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
40 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
41 #endif
42 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
43 #include <rtl/uuid.h>
44 #include <tools/debug.hxx>
45 #include <tools/gen.hxx>
46 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
47 #include <unotools/accessiblestatesethelper.hxx>
48 #endif
49 #include <toolkit/helper/convert.hxx>
50 #include <svtools/smplhint.hxx>
51 #include <comphelper/sequence.hxx>
52 #include <unotools/accessiblerelationsethelper.hxx>
53 #include <vcl/unohelp.hxx>
54 #include <tools/color.hxx>
55 #include <comphelper/accessibleeventnotifier.hxx>
57 using namespace ::rtl;
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::accessibility;
61 //===== internal ============================================================
63 DBG_NAME(ScAccessibleContextBase)
65 ScAccessibleContextBase::ScAccessibleContextBase(
66 const uno::Reference<XAccessible>& rxParent,
67 const sal_Int16 aRole)
69 ScAccessibleContextBaseWeakImpl(m_aMutex),
70 mxParent(rxParent),
71 mnClientId(0),
72 maRole(aRole)
74 DBG_CTOR(ScAccessibleContextBase, NULL);
78 ScAccessibleContextBase::~ScAccessibleContextBase(void)
80 DBG_DTOR(ScAccessibleContextBase, NULL);
82 if (!IsDefunc() && !rBHelper.bInDispose)
84 // increment refcount to prevent double call off dtor
85 osl_incrementInterlockedCount( &m_refCount );
86 // call dispose to inform object wich have a weak reference to this object
87 dispose();
91 void ScAccessibleContextBase::Init()
93 // hold reference to make sure that the destructor is not called
94 uno::Reference< XAccessibleContext > xOwnContext(this);
96 if (mxParent.is())
98 uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
99 if (xBroadcaster.is())
100 xBroadcaster->addEventListener(this);
102 msName = createAccessibleName();
103 msDescription = createAccessibleDescription();
106 void SAL_CALL ScAccessibleContextBase::disposing()
108 ScUnoGuard aGuard;
109 // CommitDefunc(); not necessary and should not be send, because it cost a lot of time
111 // hold reference to make sure that the destructor is not called
112 uno::Reference< XAccessibleContext > xOwnContext(this);
114 if ( mnClientId )
116 sal_Int32 nTemClientId(mnClientId);
117 mnClientId = 0;
118 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nTemClientId, *this );
121 if (mxParent.is())
123 uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
124 if (xBroadcaster.is())
125 xBroadcaster->removeEventListener(this);
126 mxParent = NULL;
129 ScAccessibleContextBaseWeakImpl::disposing();
132 //===== XInterface =====================================================
134 uno::Any SAL_CALL ScAccessibleContextBase::queryInterface( uno::Type const & rType )
135 throw (uno::RuntimeException)
137 uno::Any aAny (ScAccessibleContextBaseWeakImpl::queryInterface(rType));
138 return aAny.hasValue() ? aAny : ScAccessibleContextBaseImplEvent::queryInterface(rType);
141 void SAL_CALL ScAccessibleContextBase::acquire()
142 throw ()
144 ScAccessibleContextBaseWeakImpl::acquire();
147 void SAL_CALL ScAccessibleContextBase::release()
148 throw ()
150 ScAccessibleContextBaseWeakImpl::release();
153 //===== SfxListener =====================================================
155 void ScAccessibleContextBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
157 if (rHint.ISA( SfxSimpleHint ) )
159 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
160 if (rRef.GetId() == SFX_HINT_DYING)
162 // it seems the Broadcaster is dying, since the view is dying
163 dispose();
168 //===== XAccessible =========================================================
170 uno::Reference< XAccessibleContext> SAL_CALL
171 ScAccessibleContextBase::getAccessibleContext(void)
172 throw (uno::RuntimeException)
174 return this;
177 //===== XAccessibleComponent ================================================
179 sal_Bool SAL_CALL ScAccessibleContextBase::containsPoint(const awt::Point& rPoint )
180 throw (uno::RuntimeException)
182 ScUnoGuard aGuard;
183 IsObjectValid();
184 return Rectangle (Point(), GetBoundingBox().GetSize()).IsInside(VCLPoint(rPoint));
187 uno::Reference< XAccessible > SAL_CALL ScAccessibleContextBase::getAccessibleAtPoint(
188 const awt::Point& /* rPoint */ )
189 throw (uno::RuntimeException)
191 DBG_ERROR("not implemented");
192 return uno::Reference<XAccessible>();
195 awt::Rectangle SAL_CALL ScAccessibleContextBase::getBounds( )
196 throw (uno::RuntimeException)
198 ScUnoGuard aGuard;
199 IsObjectValid();
200 return AWTRectangle(GetBoundingBox());
203 awt::Point SAL_CALL ScAccessibleContextBase::getLocation( )
204 throw (uno::RuntimeException)
206 ScUnoGuard aGuard;
207 IsObjectValid();
208 return AWTPoint(GetBoundingBox().TopLeft());
211 awt::Point SAL_CALL ScAccessibleContextBase::getLocationOnScreen( )
212 throw (uno::RuntimeException)
214 ScUnoGuard aGuard;
215 IsObjectValid();
216 return AWTPoint(GetBoundingBoxOnScreen().TopLeft());
219 awt::Size SAL_CALL ScAccessibleContextBase::getSize( )
220 throw (uno::RuntimeException)
222 ScUnoGuard aGuard;
223 IsObjectValid();
224 return AWTSize(GetBoundingBox().GetSize());
227 sal_Bool SAL_CALL ScAccessibleContextBase::isShowing( )
228 throw (uno::RuntimeException)
230 ScUnoGuard aGuard;
231 IsObjectValid();
232 sal_Bool bShowing(sal_False);
233 if (mxParent.is())
235 uno::Reference<XAccessibleComponent> xParentComponent (mxParent->getAccessibleContext(), uno::UNO_QUERY);
236 if (xParentComponent.is())
238 Rectangle aParentBounds(VCLRectangle(xParentComponent->getBounds()));
239 Rectangle aBounds(VCLRectangle(getBounds()));
240 bShowing = aBounds.IsOver(aParentBounds);
243 return bShowing;
246 sal_Bool SAL_CALL ScAccessibleContextBase::isVisible( )
247 throw (uno::RuntimeException)
249 return sal_True;
252 void SAL_CALL ScAccessibleContextBase::grabFocus( )
253 throw (uno::RuntimeException)
255 DBG_ERROR("not implemented");
258 sal_Int32 SAL_CALL ScAccessibleContextBase::getForeground( )
259 throw (uno::RuntimeException)
261 return COL_BLACK;
264 sal_Int32 SAL_CALL ScAccessibleContextBase::getBackground( )
265 throw (uno::RuntimeException)
267 return COL_WHITE;
270 //===== XAccessibleContext ==================================================
272 sal_Int32 SAL_CALL
273 ScAccessibleContextBase::getAccessibleChildCount(void)
274 throw (uno::RuntimeException)
276 DBG_ERROR("should be implemented in the abrevated class");
277 return 0;
280 uno::Reference<XAccessible> SAL_CALL
281 ScAccessibleContextBase::getAccessibleChild(sal_Int32 /* nIndex */)
282 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
284 DBG_ERROR("should be implemented in the abrevated class");
285 return uno::Reference<XAccessible>();
288 uno::Reference<XAccessible> SAL_CALL
289 ScAccessibleContextBase::getAccessibleParent(void)
290 throw (uno::RuntimeException)
292 return mxParent;
295 sal_Int32 SAL_CALL
296 ScAccessibleContextBase::getAccessibleIndexInParent(void)
297 throw (uno::RuntimeException)
299 ScUnoGuard aGuard;
300 IsObjectValid();
301 // Use a simple but slow solution for now. Optimize later.
302 // Return -1 to indicate that this object's parent does not know about the
303 // object.
304 sal_Int32 nIndex(-1);
306 // Iterate over all the parent's children and search for this object.
307 if (mxParent.is())
309 uno::Reference<XAccessibleContext> xParentContext (
310 mxParent->getAccessibleContext());
311 if (xParentContext.is())
313 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
314 for (sal_Int32 i=0; i<nChildCount; ++i)
316 uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i));
317 if (xChild.is())
319 if (xChild.get() == this)
320 nIndex = i;
326 return nIndex;
329 sal_Int16 SAL_CALL
330 ScAccessibleContextBase::getAccessibleRole(void)
331 throw (uno::RuntimeException)
333 return maRole;
336 ::rtl::OUString SAL_CALL
337 ScAccessibleContextBase::getAccessibleDescription(void)
338 throw (uno::RuntimeException)
340 ScUnoGuard aGuard;
341 IsObjectValid();
342 if (!msDescription.getLength())
344 OUString sDescription(createAccessibleDescription());
345 // DBG_ASSERT(sDescription.getLength(), "We should give always a descripition.");
347 if (msDescription != sDescription)
349 AccessibleEventObject aEvent;
350 aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
351 aEvent.Source = uno::Reference< XAccessibleContext >(this);
352 aEvent.OldValue <<= msDescription;
353 aEvent.NewValue <<= sDescription;
355 msDescription = sDescription;
357 CommitChange(aEvent);
360 return msDescription;
363 OUString SAL_CALL
364 ScAccessibleContextBase::getAccessibleName(void)
365 throw (uno::RuntimeException)
367 ScUnoGuard aGuard;
368 IsObjectValid();
369 if (!msName.getLength())
371 OUString sName(createAccessibleName());
372 DBG_ASSERT(sName.getLength(), "We should give always a name.");
374 if (msName != sName)
376 AccessibleEventObject aEvent;
377 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
378 aEvent.Source = uno::Reference< XAccessibleContext >(this);
379 aEvent.OldValue <<= msName;
380 aEvent.NewValue <<= sName;
382 msName = sName;
384 CommitChange(aEvent);
387 return msName;
390 uno::Reference<XAccessibleRelationSet> SAL_CALL
391 ScAccessibleContextBase::getAccessibleRelationSet(void)
392 throw (uno::RuntimeException)
394 return new utl::AccessibleRelationSetHelper();
397 uno::Reference<XAccessibleStateSet> SAL_CALL
398 ScAccessibleContextBase::getAccessibleStateSet(void)
399 throw (uno::RuntimeException)
401 return uno::Reference<XAccessibleStateSet>();
404 lang::Locale SAL_CALL
405 ScAccessibleContextBase::getLocale(void)
406 throw (IllegalAccessibleComponentStateException,
407 uno::RuntimeException)
409 ScUnoGuard aGuard;
410 IsObjectValid();
411 if (mxParent.is())
413 uno::Reference<XAccessibleContext> xParentContext (
414 mxParent->getAccessibleContext());
415 if (xParentContext.is())
416 return xParentContext->getLocale ();
419 // No locale and no parent. Therefore throw exception to indicate this
420 // cluelessness.
421 throw IllegalAccessibleComponentStateException ();
424 //===== XAccessibleEventBroadcaster =====================================
426 void SAL_CALL
427 ScAccessibleContextBase::addEventListener(
428 const uno::Reference<XAccessibleEventListener>& xListener)
429 throw (uno::RuntimeException)
431 if (xListener.is())
433 ScUnoGuard aGuard;
434 IsObjectValid();
435 if (!IsDefunc())
437 if (!mnClientId)
438 mnClientId = comphelper::AccessibleEventNotifier::registerClient( );
439 comphelper::AccessibleEventNotifier::addEventListener( mnClientId, xListener );
444 void SAL_CALL
445 ScAccessibleContextBase::removeEventListener(
446 const uno::Reference<XAccessibleEventListener>& xListener)
447 throw (uno::RuntimeException)
449 if (xListener.is())
451 ScUnoGuard aGuard;
452 if (!IsDefunc() && mnClientId)
454 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, xListener );
455 if ( !nListenerCount )
457 // no listeners anymore
458 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
459 // and at least to us not firing any events anymore, in case somebody calls
460 // NotifyAccessibleEvent, again
461 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
462 mnClientId = 0;
468 //===== XAccessibleEventListener ========================================
470 void SAL_CALL ScAccessibleContextBase::disposing(
471 const lang::EventObject& rSource )
472 throw (uno::RuntimeException)
474 ScUnoGuard aGuard;
475 if (rSource.Source == mxParent)
476 dispose();
479 void SAL_CALL ScAccessibleContextBase::notifyEvent(
480 const AccessibleEventObject& /* aEvent */ )
481 throw (uno::RuntimeException)
485 //===== XServiceInfo ========================================================
487 ::rtl::OUString SAL_CALL
488 ScAccessibleContextBase::getImplementationName(void)
489 throw (uno::RuntimeException)
491 return OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleContextBase"));
494 sal_Bool SAL_CALL
495 ScAccessibleContextBase::supportsService(const OUString& sServiceName)
496 throw (uno::RuntimeException)
498 // Iterate over all supported service names and return true if on of them
499 // matches the given name.
500 uno::Sequence< ::rtl::OUString> aSupportedServices (
501 getSupportedServiceNames ());
502 sal_Int32 nLength(aSupportedServices.getLength());
503 const OUString* pServiceNames = aSupportedServices.getConstArray();
504 for (int i=0; i<nLength; ++i, ++pServiceNames)
505 if (sServiceName == *pServiceNames)
506 return sal_True;
507 return sal_False;
510 uno::Sequence< ::rtl::OUString> SAL_CALL
511 ScAccessibleContextBase::getSupportedServiceNames(void)
512 throw (uno::RuntimeException)
514 uno::Sequence<OUString> aServiceNames(2);
515 OUString* pServiceNames = aServiceNames.getArray();
516 if (pServiceNames)
518 pServiceNames[0] = OUString(RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.accessibility.Accessible"));
519 pServiceNames[1] = OUString(RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.accessibility.AccessibleContext"));
522 return aServiceNames;
525 //===== XTypeProvider =======================================================
527 uno::Sequence< uno::Type > SAL_CALL ScAccessibleContextBase::getTypes()
528 throw (uno::RuntimeException)
530 return comphelper::concatSequences(ScAccessibleContextBaseWeakImpl::getTypes(), ScAccessibleContextBaseImplEvent::getTypes());
533 uno::Sequence<sal_Int8> SAL_CALL
534 ScAccessibleContextBase::getImplementationId(void)
535 throw (uno::RuntimeException)
537 ScUnoGuard aGuard;
538 IsObjectValid();
539 static uno::Sequence<sal_Int8> aId;
540 if (aId.getLength() == 0)
542 aId.realloc (16);
543 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
545 return aId;
548 //===== internal ============================================================
550 ::rtl::OUString SAL_CALL
551 ScAccessibleContextBase::createAccessibleDescription(void)
552 throw (uno::RuntimeException)
554 DBG_ERROR("should be implemented in the abrevated class");
555 return rtl::OUString();
558 ::rtl::OUString SAL_CALL
559 ScAccessibleContextBase::createAccessibleName(void)
560 throw (uno::RuntimeException)
562 DBG_ERROR("should be implemented in the abrevated class");
563 return rtl::OUString();
566 void ScAccessibleContextBase::CommitChange(const AccessibleEventObject& rEvent) const
568 if (mnClientId)
569 comphelper::AccessibleEventNotifier::addEvent( mnClientId, rEvent );
572 void ScAccessibleContextBase::ChangeName()
574 AccessibleEventObject aEvent;
575 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
576 aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
577 aEvent.OldValue <<= msName;
579 msName = rtl::OUString(); // reset the name so it will be hold again
580 getAccessibleName(); // create the new name
582 aEvent.NewValue <<= msName;
584 CommitChange(aEvent);
587 void ScAccessibleContextBase::CommitFocusGained() const
589 AccessibleEventObject aEvent;
590 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
591 aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
592 aEvent.NewValue <<= AccessibleStateType::FOCUSED;
594 CommitChange(aEvent);
596 ::vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent);
599 void ScAccessibleContextBase::CommitFocusLost() const
601 AccessibleEventObject aEvent;
602 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
603 aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
604 aEvent.OldValue <<= AccessibleStateType::FOCUSED;
606 CommitChange(aEvent);
608 vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent);
611 Rectangle ScAccessibleContextBase::GetBoundingBoxOnScreen(void) const
612 throw (uno::RuntimeException)
614 DBG_ERROR("not implemented");
615 return Rectangle();
618 Rectangle ScAccessibleContextBase::GetBoundingBox(void) const
619 throw (uno::RuntimeException)
621 DBG_ERROR("not implemented");
622 return Rectangle();
625 void ScAccessibleContextBase::IsObjectValid() const
626 throw (lang::DisposedException)
628 if (rBHelper.bDisposed || rBHelper.bInDispose)
629 throw lang::DisposedException();
632 void ScAccessibleContextBase::SetRole(sal_Int16 nRole)
634 maRole = nRole;