xref: /trunk/main/accessibility/source/extended/AccessibleBrowseBox.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_accessibility.hxx"
26 #include "accessibility/extended/AccessibleBrowseBox.hxx"
27 #include "accessibility/extended/AccessibleBrowseBoxTable.hxx"
28 #include "accessibility/extended/AccessibleBrowseBoxHeaderBar.hxx"
29 #include <svtools/accessibletableprovider.hxx>
30 #include <comphelper/types.hxx>
31 #include <toolkit/helper/vclunohelper.hxx>
32 
33 // ============================================================================
34 
35 namespace accessibility
36 {
37 
38 // ============================================================================
39 
40 using ::rtl::OUString;
41 
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::accessibility;
46 using namespace ::svt;
47 
48 // ============================================================================
49 class AccessibleBrowseBoxImpl
50 {
51 public:
52     /// the XAccessible which created the AccessibleBrowseBox
53     WeakReference< XAccessible >                                m_aCreator;
54 
55     /** The data table child. */
56     Reference<
57         ::com::sun::star::accessibility::XAccessible >          mxTable;
58     AccessibleBrowseBoxTable*                                   m_pTable;
59 
60     /** The header bar for rows ("handle column"). */
61     Reference<
62         ::com::sun::star::accessibility::XAccessible >          mxRowHeaderBar;
63     AccessibleBrowseBoxHeaderBar*                               m_pRowHeaderBar;
64 
65     /** The header bar for columns (first row of the table). */
66     Reference<
67         ::com::sun::star::accessibility::XAccessible >          mxColumnHeaderBar;
68     AccessibleBrowseBoxHeaderBar*                               m_pColumnHeaderBar;
69 };
70 
71 // Ctor/Dtor/disposing --------------------------------------------------------
72 
DBG_NAME(AccessibleBrowseBox)73 DBG_NAME( AccessibleBrowseBox )
74 
75 AccessibleBrowseBox::AccessibleBrowseBox(
76             const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxCreator,
77             IAccessibleTableProvider& _rBrowseBox )
78     : AccessibleBrowseBoxBase( _rxParent, _rBrowseBox,NULL, BBTYPE_BROWSEBOX )
79 {
80     DBG_CTOR( AccessibleBrowseBox, NULL );
81     m_pImpl.reset( new AccessibleBrowseBoxImpl() );
82     m_pImpl->m_aCreator = _rxCreator;
83 
84     m_xFocusWindow = VCLUnoHelper::GetInterface(mpBrowseBox->GetWindowInstance());
85 }
86 // -----------------------------------------------------------------------------
setCreator(const Reference<XAccessible> & _rxCreator)87 void AccessibleBrowseBox::setCreator( const Reference< XAccessible >& _rxCreator )
88 {
89 #if OSL_DEBUG_LEVEL > 0
90     Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator;
91     DBG_ASSERT( !xCreator.is(), "accessibility/extended/AccessibleBrowseBox::setCreator: creator already set!" );
92 #endif
93     m_pImpl->m_aCreator = _rxCreator;
94 }
95 
96 // -----------------------------------------------------------------------------
~AccessibleBrowseBox()97 AccessibleBrowseBox::~AccessibleBrowseBox()
98 {
99     DBG_DTOR( AccessibleBrowseBox, NULL );
100 }
101 // -----------------------------------------------------------------------------
102 
disposing()103 void SAL_CALL AccessibleBrowseBox::disposing()
104 {
105     ::osl::MutexGuard aGuard( getOslMutex() );
106 
107     m_pImpl->m_pTable           = NULL;
108     m_pImpl->m_pColumnHeaderBar = NULL;
109     m_pImpl->m_pRowHeaderBar    = NULL;
110     m_pImpl->m_aCreator         = Reference< XAccessible >();
111 
112     Reference< XAccessible > xTable = m_pImpl->mxTable;
113 
114     Reference< XComponent > xComp( m_pImpl->mxTable, UNO_QUERY );
115     if ( xComp.is() )
116     {
117         xComp->dispose();
118 
119     }
120 //!    ::comphelper::disposeComponent(m_pImpl->mxTable);
121     ::comphelper::disposeComponent(m_pImpl->mxRowHeaderBar);
122     ::comphelper::disposeComponent(m_pImpl->mxColumnHeaderBar);
123 
124     AccessibleBrowseBoxBase::disposing();
125 }
126 // -----------------------------------------------------------------------------
127 
128 // XAccessibleContext ---------------------------------------------------------
129 
getAccessibleChildCount()130 sal_Int32 SAL_CALL AccessibleBrowseBox::getAccessibleChildCount()
131 {
132     BBSolarGuard aSolarGuard;
133     ::osl::MutexGuard aGuard( getOslMutex() );
134     ensureIsAlive();
135     return BBINDEX_FIRSTCONTROL + mpBrowseBox->GetAccessibleControlCount();
136 }
137 // -----------------------------------------------------------------------------
138 
139 Reference< XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nChildIndex)140 AccessibleBrowseBox::getAccessibleChild( sal_Int32 nChildIndex )
141 {
142     BBSolarGuard aSolarGuard;
143     ::osl::MutexGuard aGuard( getOslMutex() );
144     ensureIsAlive();
145 
146     Reference< XAccessible > xRet;
147     if( nChildIndex >= 0 )
148     {
149         if( nChildIndex < BBINDEX_FIRSTCONTROL )
150             xRet = implGetFixedChild( nChildIndex );
151         else
152         {
153             // additional controls
154             nChildIndex -= BBINDEX_FIRSTCONTROL;
155             if( nChildIndex < mpBrowseBox->GetAccessibleControlCount() )
156                 xRet = mpBrowseBox->CreateAccessibleControl( nChildIndex );
157         }
158     }
159 
160     if( !xRet.is() )
161         throw lang::IndexOutOfBoundsException();
162     return xRet;
163 }
164 // -----------------------------------------------------------------------------
165 
166 //sal_Int16 SAL_CALL AccessibleBrowseBox::getAccessibleRole()
167 //    throw ( uno::RuntimeException )
168 //{
169 //    ensureIsAlive();
170 //    return AccessibleRole::PANEL;
171 //}
172 // -----------------------------------------------------------------------------
173 
174 // XAccessibleComponent -------------------------------------------------------
175 
176 Reference< XAccessible > SAL_CALL
getAccessibleAtPoint(const awt::Point & rPoint)177 AccessibleBrowseBox::getAccessibleAtPoint( const awt::Point& rPoint )
178 {
179     BBSolarGuard aSolarGuard;
180     ::osl::MutexGuard aGuard( getOslMutex() );
181     ensureIsAlive();
182 
183     Reference< XAccessible > xChild;
184     sal_Int32 nIndex = 0;
185     if( mpBrowseBox->ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
186         xChild = mpBrowseBox->CreateAccessibleControl( nIndex );
187     else
188     {
189         // try whether point is in one of the fixed children
190         // (table, header bars, corner control)
191         Point aPoint( VCLPoint( rPoint ) );
192         for( nIndex = 0; (nIndex < BBINDEX_FIRSTCONTROL) && !xChild.is(); ++nIndex )
193         {
194             Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
195             Reference< XAccessibleComponent >
196                 xCurrChildComp( xCurrChild, uno::UNO_QUERY );
197 
198             if( xCurrChildComp.is() &&
199                     VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) )
200                 xChild = xCurrChild;
201         }
202     }
203     return xChild;
204 }
205 // -----------------------------------------------------------------------------
206 
grabFocus()207 void SAL_CALL AccessibleBrowseBox::grabFocus()
208 {
209     BBSolarGuard aSolarGuard;
210     ::osl::MutexGuard aGuard( getOslMutex() );
211     ensureIsAlive();
212     mpBrowseBox->GrabFocus();
213 }
214 // -----------------------------------------------------------------------------
215 
getAccessibleKeyBinding()216 Any SAL_CALL AccessibleBrowseBox::getAccessibleKeyBinding()
217 {
218     ensureIsAlive();
219     return Any();
220 }
221 // -----------------------------------------------------------------------------
222 
223 // XServiceInfo ---------------------------------------------------------------
224 
getImplementationName()225 OUString SAL_CALL AccessibleBrowseBox::getImplementationName()
226 {
227     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.svtools.AccessibleBrowseBox" ) );
228 }
229 // -----------------------------------------------------------------------------
230 
231 // internal virtual methods ---------------------------------------------------
232 
implGetBoundingBox()233 Rectangle AccessibleBrowseBox::implGetBoundingBox()
234 {
235     Window* pParent = mpBrowseBox->GetAccessibleParentWindow();
236     DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
237     return mpBrowseBox->GetWindowExtentsRelative( pParent );
238 }
239 // -----------------------------------------------------------------------------
240 
implGetBoundingBoxOnScreen()241 Rectangle AccessibleBrowseBox::implGetBoundingBoxOnScreen()
242 {
243     return mpBrowseBox->GetWindowExtentsRelative( NULL );
244 }
245 // -----------------------------------------------------------------------------
246 
247 // internal helper methods ----------------------------------------------------
248 
implGetTable()249 Reference< XAccessible > AccessibleBrowseBox::implGetTable()
250 {
251     if( !m_pImpl->mxTable.is() )
252     {
253         m_pImpl->m_pTable = createAccessibleTable();
254         m_pImpl->mxTable  = m_pImpl->m_pTable;
255 
256     }
257     return m_pImpl->mxTable;
258 }
259 // -----------------------------------------------------------------------------
260 
261 Reference< XAccessible >
implGetHeaderBar(AccessibleBrowseBoxObjType eObjType)262 AccessibleBrowseBox::implGetHeaderBar( AccessibleBrowseBoxObjType eObjType )
263 {
264     Reference< XAccessible > xRet;
265     Reference< XAccessible >* pxMember = NULL;
266 
267     if( eObjType == BBTYPE_ROWHEADERBAR )
268         pxMember = &m_pImpl->mxRowHeaderBar;
269     else if( eObjType == BBTYPE_COLUMNHEADERBAR )
270         pxMember = &m_pImpl->mxColumnHeaderBar;
271 
272     if( pxMember )
273     {
274         if( !pxMember->is() )
275         {
276             AccessibleBrowseBoxHeaderBar* pHeaderBar = new AccessibleBrowseBoxHeaderBar(
277                 (Reference< XAccessible >)m_pImpl->m_aCreator, *mpBrowseBox, eObjType );
278 
279             if ( BBTYPE_COLUMNHEADERBAR == eObjType)
280                 m_pImpl->m_pColumnHeaderBar = pHeaderBar;
281             else
282                 m_pImpl->m_pRowHeaderBar    = pHeaderBar;
283 
284             *pxMember = pHeaderBar;
285         }
286         xRet = *pxMember;
287     }
288     return xRet;
289 }
290 // -----------------------------------------------------------------------------
291 
292 Reference< XAccessible >
implGetFixedChild(sal_Int32 nChildIndex)293 AccessibleBrowseBox::implGetFixedChild( sal_Int32 nChildIndex )
294 {
295     Reference< XAccessible > xRet;
296     switch( nChildIndex )
297     {
298         case BBINDEX_COLUMNHEADERBAR:
299             xRet = implGetHeaderBar( BBTYPE_COLUMNHEADERBAR );
300         break;
301         case BBINDEX_ROWHEADERBAR:
302             xRet = implGetHeaderBar( BBTYPE_ROWHEADERBAR );
303         break;
304         case BBINDEX_TABLE:
305             xRet = implGetTable();
306         break;
307     }
308     return xRet;
309 }
310 // -----------------------------------------------------------------------------
createAccessibleTable()311 AccessibleBrowseBoxTable* AccessibleBrowseBox::createAccessibleTable()
312 {
313     Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator;
314     DBG_ASSERT( xCreator.is(), "accessibility/extended/AccessibleBrowseBox::createAccessibleTable: my creator died - how this?" );
315     return new AccessibleBrowseBoxTable( xCreator, *mpBrowseBox );
316 }
317 // -----------------------------------------------------------------------------
commitTableEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue)318 void AccessibleBrowseBox::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
319 {
320     if ( m_pImpl->mxTable.is() )
321     {
322         m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
323     }
324 }
325 // -----------------------------------------------------------------------------
commitHeaderBarEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue,sal_Bool _bColumnHeaderBar)326 void AccessibleBrowseBox::commitHeaderBarEvent( sal_Int16 _nEventId,
327                                                 const Any& _rNewValue,
328                                                 const Any& _rOldValue,sal_Bool _bColumnHeaderBar)
329 {
330     Reference< XAccessible > xHeaderBar = _bColumnHeaderBar ? m_pImpl->mxColumnHeaderBar : m_pImpl->mxRowHeaderBar;
331     AccessibleBrowseBoxHeaderBar* pHeaderBar = _bColumnHeaderBar ? m_pImpl->m_pColumnHeaderBar : m_pImpl->m_pRowHeaderBar;
332     if ( xHeaderBar.is() )
333         pHeaderBar->commitEvent(_nEventId,_rNewValue,_rOldValue);
334 }
335 
336 // ============================================================================
337 // = AccessibleBrowseBoxAccess
338 // ============================================================================
DBG_NAME(AccessibleBrowseBoxAccess)339 DBG_NAME( AccessibleBrowseBoxAccess )
340 // -----------------------------------------------------------------------------
341 AccessibleBrowseBoxAccess::AccessibleBrowseBoxAccess( const Reference< XAccessible >& _rxParent, IAccessibleTableProvider& _rBrowseBox )
342         :m_xParent( _rxParent )
343         ,m_rBrowseBox( _rBrowseBox )
344         ,m_pContext( NULL )
345 {
346     DBG_CTOR( AccessibleBrowseBoxAccess, NULL );
347 }
348 
349 // -----------------------------------------------------------------------------
~AccessibleBrowseBoxAccess()350 AccessibleBrowseBoxAccess::~AccessibleBrowseBoxAccess()
351 {
352     DBG_DTOR( AccessibleBrowseBoxAccess, NULL );
353 }
354 
355 // -----------------------------------------------------------------------------
dispose()356 void AccessibleBrowseBoxAccess::dispose()
357 {
358     ::osl::MutexGuard aGuard( m_aMutex );
359 
360     m_pContext = NULL;
361     ::comphelper::disposeComponent( m_xContext );
362 }
363 
364 // -----------------------------------------------------------------------------
getAccessibleContext()365 Reference< XAccessibleContext > SAL_CALL AccessibleBrowseBoxAccess::getAccessibleContext()
366 {
367     ::osl::MutexGuard aGuard( m_aMutex );
368 
369     DBG_ASSERT( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ),
370         "accessibility/extended/AccessibleBrowseBoxAccess::getAccessibleContext: inconsistency!" );
371 
372     // if the context died meanwhile (we're no listener, so it won't tell us explicitly when this happens),
373     // then reset an re-create.
374     if ( m_pContext && !m_pContext->isAlive() )
375         m_xContext = m_pContext = NULL;
376 
377     if ( !m_xContext.is() )
378         m_xContext = m_pContext = new AccessibleBrowseBox( m_xParent, this, m_rBrowseBox );
379 
380     return m_xContext;
381 }
382 
383 // -----------------------------------------------------------------------------
isContextAlive() const384 bool AccessibleBrowseBoxAccess::isContextAlive() const
385 {
386     return ( NULL != m_pContext ) && m_pContext->isAlive();
387 }
388 
389 // ============================================================================
390 
391 }   // namespace accessibility
392