LibreOffice Module comphelper (master) 1
accessiblecontexthelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21#include <osl/diagnose.h>
23#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
26
27
28namespace comphelper
29{
30 using namespace ::com::sun::star::uno;
31 using namespace ::com::sun::star::lang;
32 using namespace ::com::sun::star::accessibility;
33
36 ,m_nClientId( 0 )
37 {
38 }
39
40
42 {
43 // this ensures that the lock, which may be already destroyed as part of the derivee,
44 // is not used anymore
45
47 }
48
49
51 {
52 // rhbz#1001768: de facto this class is locked by SolarMutex;
53 // do not lock m_Mutex because it may cause deadlock
54 osl::Guard<SolarMutex> aGuard(SolarMutex::get());
55
56 if ( m_nClientId )
57 {
60 }
61 }
62
63
64 void SAL_CALL OAccessibleContextHelper::addAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener )
65 {
66 osl::Guard<SolarMutex> aGuard(SolarMutex::get());
67 // don't use the OContextEntryGuard - it will throw an exception if we're not alive
68 // anymore, while the most recent specification for XComponent states that we should
69 // silently ignore the call in such a situation
70 if ( !isAlive() )
71 {
72 if ( _rxListener.is() )
73 _rxListener->disposing( EventObject( *this ) );
74 return;
75 }
76
77 if ( _rxListener.is() )
78 {
79 if ( !m_nClientId )
81
83 }
84 }
85
86
87 void SAL_CALL OAccessibleContextHelper::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener )
88 {
89 osl::Guard<SolarMutex> aGuard(SolarMutex::get());
90 // don't use the OContextEntryGuard - it will throw an exception if we're not alive
91 // anymore, while the most recent specification for XComponent states that we should
92 // silently ignore the call in such a situation
93 if ( !isAlive() )
94 return;
95
96 if ( !(_rxListener.is() && m_nClientId) )
97 return;
98
99 sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_nClientId, _rxListener );
100 if ( !nListenerCount )
101 {
102 // no listeners anymore
103 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
104 // and at least to us not firing any events anymore, in case somebody calls
105 // NotifyAccessibleEvent, again
107 m_nClientId = 0;
108 }
109 }
110
111
112 void OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId,
113 const Any& _rOldValue, const Any& _rNewValue )
114 {
115 if ( !m_nClientId )
116 // if we don't have a client id for the notifier, then we don't have listeners, then
117 // we don't need to notify anything
118 return;
119
120 // build an event object
121 AccessibleEventObject aEvent;
122 aEvent.Source = *this;
123 aEvent.EventId = _nEventId;
124 aEvent.OldValue = _rOldValue;
125 aEvent.NewValue = _rNewValue;
126
127 // let the notifier handle this event
129 }
130
131
133 {
134 return !rBHelper.bDisposed && !rBHelper.bInDispose;
135 }
136
137
139 {
140 if( !isAlive() )
141 throw DisposedException();
142 }
143
144
146 {
147 if ( !rBHelper.bDisposed )
148 {
149 OSL_ENSURE( 0 == m_refCount, "OAccessibleContextHelper::ensureDisposed: this method _has_ to be called from without your dtor only!" );
150 acquire();
151 dispose();
152 }
153 }
154
155
156 void OAccessibleContextHelper::lateInit( const Reference< XAccessible >& _rxAccessible )
157 {
158 m_aCreator = _rxAccessible;
159 }
160
161
162 Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const
163 {
164 return m_aCreator;
165 }
166
167
169 {
170 return OUString();
171 }
172
173
175 {
176 OExternalLockGuard aGuard( this );
177
178 // -1 for child not found/no parent (according to specification)
179 sal_Int64 nRet = -1;
180
181 try
182 {
183
184 Reference< XAccessibleContext > xParentContext( implGetParentContext() );
185
186 // iterate over parent's children and search for this object
187 if ( xParentContext.is() )
188 {
189 // our own XAccessible for comparing with the children of our parent
190 Reference< XAccessible > xCreator( m_aCreator);
191
192 OSL_ENSURE( xCreator.is(), "OAccessibleContextHelper::getAccessibleIndexInParent: invalid creator!" );
193 // two ideas why this could be NULL:
194 // * nobody called our late ctor (init), so we never had a creator at all -> bad
195 // * the creator is already dead. In this case, we should have been disposed, and
196 // never survived the above OContextEntryGuard.
197 // in all other situations the creator should be non-NULL
198
199 if ( xCreator.is() )
200 {
201 sal_Int64 nChildCount = xParentContext->getAccessibleChildCount();
202 for ( sal_Int64 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild )
203 {
204 Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) );
205 if ( xChild.get() == xCreator.get() )
206 nRet = nChild;
207 }
208 }
209 }
210 }
211 catch( const Exception& )
212 {
213 OSL_FAIL( "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" );
214 }
215
216 return nRet;
217 }
218
219
221 {
222 // simply ask the parent
223 Reference< XAccessible > xParent = getAccessibleParent();
224 Reference< XAccessibleContext > xParentContext;
225 if ( xParent.is() )
226 xParentContext = xParent->getAccessibleContext();
227
228 if ( !xParentContext.is() )
229 throw IllegalAccessibleComponentStateException( OUString(), *this );
230
231 return xParentContext->getLocale();
232 }
233
234
235 Reference< XAccessibleContext > OAccessibleContextHelper::implGetParentContext()
236 {
237 Reference< XAccessible > xParent = getAccessibleParent();
238 Reference< XAccessibleContext > xParentContext;
239 if ( xParent.is() )
240 xParentContext = xParent->getAccessibleContext();
241 return xParentContext;
242 }
243
244
245} // namespace comphelper
246
247
248/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
static sal_Int32 addEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
registers a listener for the given client
static void addEvent(const TClientId _nClient, const css::accessibility::AccessibleEventObject &_rEvent)
adds an event, which is to be broadcasted, to the queue
static sal_Int32 removeEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
revokes a listener for the given client
static TClientId registerClient()
registers a client of this class, means a broadcaster of AccessibleEvents
static void revokeClient(const TClientId _nClient)
revokes a broadcaster of AccessibleEvents
static void revokeClientNotifyDisposing(const TClientId _nClient, const css::uno::Reference< css::uno::XInterface > &_rxEventSource)
revokes a client, with additionally notifying a disposing event to all listeners registered for this ...
virtual void SAL_CALL disposing() override
css::uno::Reference< css::accessibility::XAccessibleContext > implGetParentContext()
shortcut for retrieving the context of the parent (returned by getAccessibleParent)
virtual OUString SAL_CALL getAccessibleId() override
bool isAlive() const
checks whether the object is alive (returns <TRUE> then) or disposed
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override=0
void lateInit(const css::uno::Reference< css::accessibility::XAccessible > &_rxAccessible)
late construction
void ensureDisposed()
ensures that the object is disposed.
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
void ensureAlive() const
checks for being alive. If the object is already disposed (i.e. not alive), an exception is thrown.
virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
default implementation for retrieving the index of this object within the parent
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
css::uno::WeakReference< css::accessibility::XAccessible > m_aCreator
void NotifyAccessibleEvent(const sal_Int16 _nEventId, const css::uno::Any &_rOldValue, const css::uno::Any &_rNewValue)
notifies all AccessibleEventListeners of a certain event
AccessibleEventNotifier::TClientId m_nClientId
css::uno::Reference< css::accessibility::XAccessible > getAccessibleCreator() const
retrieves the creator previously set with <method>lateInit</method>
virtual css::lang::Locale SAL_CALL getLocale() override
default implementation for retrieving the locale
static SolarMutex * get()
Help components to get the SolarMutex easily.
Definition: solarmutex.cxx:34
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
ULONG m_refCount
@ Exception
void dispose()