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     throw ( uno::RuntimeException )
132 {
133     BBSolarGuard aSolarGuard;
134     ::osl::MutexGuard aGuard( getOslMutex() );
135     ensureIsAlive();
136     return BBINDEX_FIRSTCONTROL + mpBrowseBox->GetAccessibleControlCount();
137 }
138 // -----------------------------------------------------------------------------
139 
140 Reference< XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nChildIndex)141 AccessibleBrowseBox::getAccessibleChild( sal_Int32 nChildIndex )
142     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
143 {
144     BBSolarGuard aSolarGuard;
145     ::osl::MutexGuard aGuard( getOslMutex() );
146     ensureIsAlive();
147 
148     Reference< XAccessible > xRet;
149     if( nChildIndex >= 0 )
150     {
151         if( nChildIndex < BBINDEX_FIRSTCONTROL )
152             xRet = implGetFixedChild( nChildIndex );
153         else
154         {
155             // additional controls
156             nChildIndex -= BBINDEX_FIRSTCONTROL;
157             if( nChildIndex < mpBrowseBox->GetAccessibleControlCount() )
158                 xRet = mpBrowseBox->CreateAccessibleControl( nChildIndex );
159         }
160     }
161 
162     if( !xRet.is() )
163         throw lang::IndexOutOfBoundsException();
164     return xRet;
165 }
166 // -----------------------------------------------------------------------------
167 
168 //sal_Int16 SAL_CALL AccessibleBrowseBox::getAccessibleRole()
169 //    throw ( uno::RuntimeException )
170 //{
171 //    ensureIsAlive();
172 //    return AccessibleRole::PANEL;
173 //}
174 // -----------------------------------------------------------------------------
175 
176 // XAccessibleComponent -------------------------------------------------------
177 
178 Reference< XAccessible > SAL_CALL
getAccessibleAtPoint(const awt::Point & rPoint)179 AccessibleBrowseBox::getAccessibleAtPoint( const awt::Point& rPoint )
180     throw ( uno::RuntimeException )
181 {
182     BBSolarGuard aSolarGuard;
183     ::osl::MutexGuard aGuard( getOslMutex() );
184     ensureIsAlive();
185 
186     Reference< XAccessible > xChild;
187     sal_Int32 nIndex = 0;
188     if( mpBrowseBox->ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
189         xChild = mpBrowseBox->CreateAccessibleControl( nIndex );
190     else
191     {
192         // try whether point is in one of the fixed children
193         // (table, header bars, corner control)
194         Point aPoint( VCLPoint( rPoint ) );
195         for( nIndex = 0; (nIndex < BBINDEX_FIRSTCONTROL) && !xChild.is(); ++nIndex )
196         {
197             Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
198             Reference< XAccessibleComponent >
199                 xCurrChildComp( xCurrChild, uno::UNO_QUERY );
200 
201             if( xCurrChildComp.is() &&
202                     VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) )
203                 xChild = xCurrChild;
204         }
205     }
206     return xChild;
207 }
208 // -----------------------------------------------------------------------------
209 
grabFocus()210 void SAL_CALL AccessibleBrowseBox::grabFocus()
211     throw ( uno::RuntimeException )
212 {
213     BBSolarGuard aSolarGuard;
214     ::osl::MutexGuard aGuard( getOslMutex() );
215     ensureIsAlive();
216     mpBrowseBox->GrabFocus();
217 }
218 // -----------------------------------------------------------------------------
219 
getAccessibleKeyBinding()220 Any SAL_CALL AccessibleBrowseBox::getAccessibleKeyBinding()
221     throw ( uno::RuntimeException )
222 {
223     ensureIsAlive();
224 	return Any();
225 }
226 // -----------------------------------------------------------------------------
227 
228 // XServiceInfo ---------------------------------------------------------------
229 
getImplementationName()230 OUString SAL_CALL AccessibleBrowseBox::getImplementationName()
231     throw ( uno::RuntimeException )
232 {
233     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.svtools.AccessibleBrowseBox" ) );
234 }
235 // -----------------------------------------------------------------------------
236 
237 // internal virtual methods ---------------------------------------------------
238 
implGetBoundingBox()239 Rectangle AccessibleBrowseBox::implGetBoundingBox()
240 {
241     Window* pParent = mpBrowseBox->GetAccessibleParentWindow();
242     DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
243     return mpBrowseBox->GetWindowExtentsRelative( pParent );
244 }
245 // -----------------------------------------------------------------------------
246 
implGetBoundingBoxOnScreen()247 Rectangle AccessibleBrowseBox::implGetBoundingBoxOnScreen()
248 {
249     return mpBrowseBox->GetWindowExtentsRelative( NULL );
250 }
251 // -----------------------------------------------------------------------------
252 
253 // internal helper methods ----------------------------------------------------
254 
implGetTable()255 Reference< XAccessible > AccessibleBrowseBox::implGetTable()
256 {
257     if( !m_pImpl->mxTable.is() )
258 	{
259         m_pImpl->m_pTable = createAccessibleTable();
260 		m_pImpl->mxTable  = m_pImpl->m_pTable;
261 
262 	}
263     return m_pImpl->mxTable;
264 }
265 // -----------------------------------------------------------------------------
266 
267 Reference< XAccessible >
implGetHeaderBar(AccessibleBrowseBoxObjType eObjType)268 AccessibleBrowseBox::implGetHeaderBar( AccessibleBrowseBoxObjType eObjType )
269 {
270     Reference< XAccessible > xRet;
271     Reference< XAccessible >* pxMember = NULL;
272 
273     if( eObjType == BBTYPE_ROWHEADERBAR )
274         pxMember = &m_pImpl->mxRowHeaderBar;
275     else if( eObjType ==  BBTYPE_COLUMNHEADERBAR )
276         pxMember = &m_pImpl->mxColumnHeaderBar;
277 
278     if( pxMember )
279     {
280         if( !pxMember->is() )
281 		{
282 			AccessibleBrowseBoxHeaderBar* pHeaderBar = new AccessibleBrowseBoxHeaderBar(
283                 (Reference< XAccessible >)m_pImpl->m_aCreator, *mpBrowseBox, eObjType );
284 
285             if ( BBTYPE_COLUMNHEADERBAR == eObjType)
286 				m_pImpl->m_pColumnHeaderBar = pHeaderBar;
287 			else
288 				m_pImpl->m_pRowHeaderBar	= pHeaderBar;
289 
290             *pxMember = pHeaderBar;
291 		}
292         xRet = *pxMember;
293     }
294     return xRet;
295 }
296 // -----------------------------------------------------------------------------
297 
298 Reference< XAccessible >
implGetFixedChild(sal_Int32 nChildIndex)299 AccessibleBrowseBox::implGetFixedChild( sal_Int32 nChildIndex )
300 {
301     Reference< XAccessible > xRet;
302     switch( nChildIndex )
303     {
304         case BBINDEX_COLUMNHEADERBAR:
305             xRet = implGetHeaderBar( BBTYPE_COLUMNHEADERBAR );
306         break;
307         case BBINDEX_ROWHEADERBAR:
308             xRet = implGetHeaderBar( BBTYPE_ROWHEADERBAR );
309         break;
310         case BBINDEX_TABLE:
311             xRet = implGetTable();
312         break;
313     }
314     return xRet;
315 }
316 // -----------------------------------------------------------------------------
createAccessibleTable()317 AccessibleBrowseBoxTable* AccessibleBrowseBox::createAccessibleTable()
318 {
319     Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator;
320     DBG_ASSERT( xCreator.is(), "accessibility/extended/AccessibleBrowseBox::createAccessibleTable: my creator died - how this?" );
321 	return new AccessibleBrowseBoxTable( xCreator, *mpBrowseBox );
322 }
323 // -----------------------------------------------------------------------------
commitTableEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue)324 void AccessibleBrowseBox::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
325 {
326 	if ( m_pImpl->mxTable.is() )
327 	{
328 		m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
329 	}
330 }
331 // -----------------------------------------------------------------------------
commitHeaderBarEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue,sal_Bool _bColumnHeaderBar)332 void AccessibleBrowseBox::commitHeaderBarEvent(	sal_Int16 _nEventId,
333 												const Any& _rNewValue,
334 												const Any& _rOldValue,sal_Bool _bColumnHeaderBar)
335 {
336 	Reference< XAccessible > xHeaderBar = _bColumnHeaderBar ? m_pImpl->mxColumnHeaderBar : m_pImpl->mxRowHeaderBar;
337 	AccessibleBrowseBoxHeaderBar* pHeaderBar = _bColumnHeaderBar ? m_pImpl->m_pColumnHeaderBar : m_pImpl->m_pRowHeaderBar;
338 	if ( xHeaderBar.is() )
339 		pHeaderBar->commitEvent(_nEventId,_rNewValue,_rOldValue);
340 }
341 
342 // ============================================================================
343 // = AccessibleBrowseBoxAccess
344 // ============================================================================
DBG_NAME(AccessibleBrowseBoxAccess)345 DBG_NAME( AccessibleBrowseBoxAccess )
346 // -----------------------------------------------------------------------------
347 AccessibleBrowseBoxAccess::AccessibleBrowseBoxAccess( const Reference< XAccessible >& _rxParent, IAccessibleTableProvider& _rBrowseBox )
348         :m_xParent( _rxParent )
349         ,m_rBrowseBox( _rBrowseBox )
350         ,m_pContext( NULL )
351 {
352     DBG_CTOR( AccessibleBrowseBoxAccess, NULL );
353 }
354 
355 // -----------------------------------------------------------------------------
~AccessibleBrowseBoxAccess()356 AccessibleBrowseBoxAccess::~AccessibleBrowseBoxAccess()
357 {
358     DBG_DTOR( AccessibleBrowseBoxAccess, NULL );
359 }
360 
361 // -----------------------------------------------------------------------------
dispose()362 void AccessibleBrowseBoxAccess::dispose()
363 {
364     ::osl::MutexGuard aGuard( m_aMutex );
365 
366     m_pContext = NULL;
367     ::comphelper::disposeComponent( m_xContext );
368 }
369 
370 // -----------------------------------------------------------------------------
getAccessibleContext()371 Reference< XAccessibleContext > SAL_CALL AccessibleBrowseBoxAccess::getAccessibleContext() throw ( RuntimeException )
372 {
373     ::osl::MutexGuard aGuard( m_aMutex );
374 
375     DBG_ASSERT( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ),
376         "accessibility/extended/AccessibleBrowseBoxAccess::getAccessibleContext: inconsistency!" );
377 
378     // if the context died meanwhile (we're no listener, so it won't tell us explicitily when this happens),
379     // then reset an re-create.
380     if ( m_pContext && !m_pContext->isAlive() )
381         m_xContext = m_pContext = NULL;
382 
383     if ( !m_xContext.is() )
384         m_xContext = m_pContext = new AccessibleBrowseBox( m_xParent, this, m_rBrowseBox );
385 
386     return m_xContext;
387 }
388 
389 // -----------------------------------------------------------------------------
isContextAlive() const390 bool AccessibleBrowseBoxAccess::isContextAlive() const
391 {
392     return  ( NULL != m_pContext ) && m_pContext->isAlive();
393 }
394 
395 // ============================================================================
396 
397 }   // namespace accessibility
398