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