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