1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documentfocuslistener.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "documentfocuslistener.hxx"
34 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEEVENTBROADCASTER_HPP_
35 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
39 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
42 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLESTATETYPE_HPP_
43 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
46 using namespace ::com::sun::star::accessibility
;
47 using namespace ::com::sun::star::lang
;
48 using namespace ::com::sun::star::uno
;
51 //------------------------------------------------------------------------------
53 DocumentFocusListener::DocumentFocusListener(AquaA11yFocusTracker
& rTracker
) :
54 m_aFocusTracker(rTracker
)
58 //------------------------------------------------------------------------------
61 DocumentFocusListener::disposing( const EventObject
& aEvent
)
62 throw (RuntimeException
)
64 // Unref the object here, but do not remove as listener since the object
65 // might no longer be in a state that safely allows this.
66 if( aEvent
.Source
.is() )
67 m_aRefList
.erase(aEvent
.Source
);
70 //------------------------------------------------------------------------------
73 DocumentFocusListener::notifyEvent( const AccessibleEventObject
& aEvent
)
74 throw( RuntimeException
)
76 switch( aEvent
.EventId
)
78 case AccessibleEventId::STATE_CHANGED
:
81 sal_Int16 nState
= AccessibleStateType::INVALID
;
82 aEvent
.NewValue
>>= nState
;
84 if( AccessibleStateType::FOCUSED
== nState
)
85 m_aFocusTracker
.setFocusedObject( getAccessible(aEvent
) );
87 catch(IndexOutOfBoundsException e
)
89 OSL_TRACE("Focused object has invalid index in parent");
93 case AccessibleEventId::CHILD
:
95 Reference
< XAccessible
> xChild
;
96 if( (aEvent
.OldValue
>>= xChild
) && xChild
.is() )
97 detachRecursive(xChild
);
99 if( (aEvent
.NewValue
>>= xChild
) && xChild
.is() )
100 attachRecursive(xChild
);
104 case AccessibleEventId::INVALIDATE_ALL_CHILDREN
:
106 Reference< XAccessible > xAccessible( getAccessible(aEvent) );
107 detachRecursive(xAccessible);
108 attachRecursive(xAccessible);
111 OSL_TRACE( "Invalidate all children called\n" );
118 //------------------------------------------------------------------------------
120 Reference
< XAccessible
> DocumentFocusListener::getAccessible(const EventObject
& aEvent
)
121 throw (IndexOutOfBoundsException
, RuntimeException
)
123 Reference
< XAccessible
> xAccessible(aEvent
.Source
, UNO_QUERY
);
125 if( xAccessible
.is() )
128 Reference
< XAccessibleContext
> xContext(aEvent
.Source
, UNO_QUERY
);
132 Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
135 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
136 if( xParentContext
.is() )
138 return xParentContext
->getAccessibleChild( xContext
->getAccessibleIndexInParent() );
143 return Reference
< XAccessible
>();
146 //------------------------------------------------------------------------------
148 void DocumentFocusListener::attachRecursive(const Reference
< XAccessible
>& xAccessible
)
149 throw (IndexOutOfBoundsException
, RuntimeException
)
151 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
154 attachRecursive(xAccessible
, xContext
);
157 //------------------------------------------------------------------------------
159 void DocumentFocusListener::attachRecursive(
160 const Reference
< XAccessible
>& xAccessible
,
161 const Reference
< XAccessibleContext
>& xContext
162 ) throw (IndexOutOfBoundsException
, RuntimeException
)
166 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
169 attachRecursive(xAccessible
, xContext
, xStateSet
);
173 //------------------------------------------------------------------------------
175 void DocumentFocusListener::attachRecursive(
176 const Reference
< XAccessible
>& xAccessible
,
177 const Reference
< XAccessibleContext
>& xContext
,
178 const Reference
< XAccessibleStateSet
>& xStateSet
179 ) throw (IndexOutOfBoundsException
,RuntimeException
)
181 if( xStateSet
->contains(AccessibleStateType::FOCUSED
) )
182 m_aFocusTracker
.setFocusedObject( xAccessible
);
184 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
185 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
187 // If not already done, add the broadcaster to the list and attach as listener.
188 if( xBroadcaster
.is() && m_aRefList
.insert(xBroadcaster
).second
)
190 xBroadcaster
->addEventListener(static_cast< XAccessibleEventListener
*>(this));
192 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
194 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
195 for( n
= 0; n
< nmax
; n
++ )
197 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
200 attachRecursive(xChild
);
206 //------------------------------------------------------------------------------
208 void DocumentFocusListener::detachRecursive(const Reference
< XAccessible
>& xAccessible
)
209 throw (IndexOutOfBoundsException
, RuntimeException
)
211 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
214 detachRecursive(xAccessible
, xContext
);
217 //------------------------------------------------------------------------------
219 void DocumentFocusListener::detachRecursive(
220 const Reference
< XAccessible
>& xAccessible
,
221 const Reference
< XAccessibleContext
>& xContext
222 ) throw (IndexOutOfBoundsException
, RuntimeException
)
224 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
227 detachRecursive(xAccessible
, xContext
, xStateSet
);
230 //------------------------------------------------------------------------------
232 void DocumentFocusListener::detachRecursive(
233 const Reference
< XAccessible
>&,
234 const Reference
< XAccessibleContext
>& xContext
,
235 const Reference
< XAccessibleStateSet
>& xStateSet
236 ) throw (IndexOutOfBoundsException
, RuntimeException
)
238 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
239 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
241 if( xBroadcaster
.is() && 0 < m_aRefList
.erase(xBroadcaster
) )
243 xBroadcaster
->removeEventListener(static_cast< XAccessibleEventListener
*>(this));
245 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
247 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
248 for( n
= 0; n
< nmax
; n
++ )
250 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
253 detachRecursive(xChild
);