xref: /aoo41x/main/sw/source/core/access/accdoc.cxx (revision cdf0e10c)
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_sw.hxx"
30 #include <vcl/window.hxx>
31 #include <rootfrm.hxx>
32 
33 
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
37 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 #include <unotools/accessiblestatesethelper.hxx>
39 #include <tools/link.hxx>
40 #include <sfx2/viewsh.hxx>
41 #include <vos/mutex.hxx>
42 #include <vcl/svapp.hxx>
43 #include <viewsh.hxx>
44 #include <doc.hxx>
45 #include <accmap.hxx>
46 #include <accdoc.hxx>
47 #ifndef _ACCESS_HRC
48 #include "access.hrc"
49 #endif
50 #include <pagefrm.hxx>
51 
52 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentView";
53 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView";
54 
55 
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::accessibility;
58 using ::rtl::OUString;
59 
60 using lang::IndexOutOfBoundsException;
61 
62 
63 
64 //
65 // SwAccessibleDocumentBase: base class for SwAccessibleDocument and
66 // SwAccessiblePreview
67 //
68 
69 SwAccessibleDocumentBase::SwAccessibleDocumentBase ( SwAccessibleMap *_pMap ) :
70 	SwAccessibleContext( _pMap, AccessibleRole::DOCUMENT,
71                          _pMap->GetShell()->GetLayout() ),//swmod 071107//swmod 071225
72 	mxParent( _pMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible() ),
73     mpChildWin( 0 )
74 {
75 }
76 
77 SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
78 {
79 }
80 
81 void SwAccessibleDocumentBase::SetVisArea()
82 {
83 	vos::OGuard aGuard(Application::GetSolarMutex());
84 
85 	SwRect aOldVisArea( GetVisArea() );
86 	const SwRect& rNewVisArea = GetMap()->GetVisArea();
87 	if( aOldVisArea != rNewVisArea )
88 	{
89 		SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
90         // --> OD 2007-12-07 #i58139#
91         // showing state of document view needs also be updated.
92         // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
93 //        ChildrenScrolled( GetFrm(), aOldVisArea );
94         Scrolled( aOldVisArea );
95         // <--
96 	}
97 }
98 
99 void SwAccessibleDocumentBase::AddChild( Window *pWin, sal_Bool bFireEvent )
100 {
101 	vos::OGuard aGuard(Application::GetSolarMutex());
102 
103     ASSERT( !mpChildWin, "only one child window is supported" );
104     if( !mpChildWin )
105 	{
106         mpChildWin = pWin;
107 
108 		if( bFireEvent )
109 		{
110 			AccessibleEventObject aEvent;
111 			aEvent.EventId = AccessibleEventId::CHILD;
112             aEvent.NewValue <<= mpChildWin->GetAccessible();
113 			FireAccessibleEvent( aEvent );
114 		}
115 	}
116 }
117 
118 void SwAccessibleDocumentBase::RemoveChild( Window *pWin )
119 {
120 	vos::OGuard aGuard(Application::GetSolarMutex());
121 
122     ASSERT( !mpChildWin || pWin == mpChildWin, "invalid child window to remove" );
123     if( mpChildWin && pWin == mpChildWin )
124 	{
125 		AccessibleEventObject aEvent;
126 		aEvent.EventId = AccessibleEventId::CHILD;
127         aEvent.OldValue <<= mpChildWin->GetAccessible();
128 		FireAccessibleEvent( aEvent );
129 
130         mpChildWin = 0;
131 	}
132 }
133 
134 sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount( void )
135         throw (uno::RuntimeException)
136 {
137 	vos::OGuard aGuard(Application::GetSolarMutex());
138 
139 	// CHECK_FOR_DEFUNC is called by parent
140 
141 	sal_Int32 nChildren = SwAccessibleContext::getAccessibleChildCount();
142     if( !IsDisposing() && mpChildWin )
143 		nChildren++;
144 
145 	return nChildren;
146 }
147 
148 uno::Reference< XAccessible> SAL_CALL
149 	SwAccessibleDocumentBase::getAccessibleChild( sal_Int32 nIndex )
150         throw (uno::RuntimeException,
151                 lang::IndexOutOfBoundsException)
152 {
153 	vos::OGuard aGuard(Application::GetSolarMutex());
154 
155     if( mpChildWin  )
156 	{
157 		CHECK_FOR_DEFUNC( XAccessibleContext )
158         if ( nIndex == GetChildCount( *(GetMap()) ) )
159         {
160             return mpChildWin->GetAccessible();
161         }
162 	}
163 
164 	return SwAccessibleContext::getAccessibleChild( nIndex );
165 }
166 
167 
168 uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent (void)
169         throw (uno::RuntimeException)
170 {
171     return mxParent;
172 }
173 
174 sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent (void)
175         throw (uno::RuntimeException)
176 {
177 	vos::OGuard aGuard(Application::GetSolarMutex());
178 
179 	uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() );
180 	uno::Reference < XAccessible > xThis( this );
181 	sal_Int32 nCount = xAcc->getAccessibleChildCount();
182 
183 	for( sal_Int32 i=0; i < nCount; i++ )
184 	{
185 		if( xAcc->getAccessibleChild( i ) == xThis )
186 			return i;
187 	}
188 	return -1L;
189 }
190 
191 OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription (void)
192     throw (uno::RuntimeException)
193 {
194 	return GetResource( STR_ACCESS_DOC_DESC );
195 }
196 
197 awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds()
198 		throw (uno::RuntimeException)
199 {
200 	vos::OGuard aGuard(Application::GetSolarMutex());
201 
202 	Window *pWin = GetWindow();
203 
204 	CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
205 
206 	Rectangle aPixBounds( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ) );
207 	awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
208 						 aPixBounds.GetWidth(), aPixBounds.GetHeight() );
209 
210 	return aBox;
211 }
212 
213 
214 awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation()
215 		throw (uno::RuntimeException)
216 {
217 	vos::OGuard aGuard(Application::GetSolarMutex());
218 
219 	Window *pWin = GetWindow();
220 
221 	CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
222 
223 	Point aPixPos( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ).TopLeft() );
224 	awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
225 
226 	return aLoc;
227 }
228 
229 
230 ::com::sun::star::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen()
231 		throw (uno::RuntimeException)
232 {
233 	vos::OGuard aGuard(Application::GetSolarMutex());
234 
235 	Window *pWin = GetWindow();
236 
237 	CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
238 
239 	Point aPixPos( pWin->GetWindowExtentsRelative( 0 ).TopLeft() );
240 	awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
241 
242 	return aLoc;
243 }
244 
245 
246 ::com::sun::star::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize()
247 		throw (uno::RuntimeException)
248 {
249 	vos::OGuard aGuard(Application::GetSolarMutex());
250 
251 	Window *pWin = GetWindow();
252 
253 	CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
254 
255 	Size aPixSize( pWin->GetWindowExtentsRelative( 0 ).GetSize() );
256 	awt::Size aSize( aPixSize.Width(), aPixSize.Height() );
257 
258 	return aSize;
259 }
260 
261 sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint(
262 			const awt::Point& aPoint )
263 		throw (uno::RuntimeException)
264 {
265 	vos::OGuard aGuard(Application::GetSolarMutex());
266 
267 	Window *pWin = GetWindow();
268 
269 	CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
270 
271 	Rectangle aPixBounds( pWin->GetWindowExtentsRelative( 0 ) );
272     aPixBounds.Move(-aPixBounds.Left(), -aPixBounds.Top());
273 
274 	Point aPixPoint( aPoint.X, aPoint.Y );
275 	return aPixBounds.IsInside( aPixPoint );
276 }
277 
278 uno::Reference< XAccessible > SAL_CALL SwAccessibleDocumentBase::getAccessibleAtPoint(
279 				const awt::Point& aPoint )
280 		throw (uno::RuntimeException)
281 {
282 	vos::OGuard aGuard(Application::GetSolarMutex());
283 
284     if( mpChildWin  )
285 	{
286 		CHECK_FOR_DEFUNC( XAccessibleComponent )
287 
288 		Window *pWin = GetWindow();
289 		CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
290 
291 		Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window
292         if( mpChildWin->GetWindowExtentsRelative( pWin ).IsInside( aPixPoint ) )
293             return mpChildWin->GetAccessible();
294 	}
295 
296 	return SwAccessibleContext::getAccessibleAtPoint( aPoint );
297 }
298 
299 //
300 // SwAccessibeDocument
301 //
302 
303 void SwAccessibleDocument::GetStates(
304 		::utl::AccessibleStateSetHelper& rStateSet )
305 {
306 	SwAccessibleContext::GetStates( rStateSet );
307 
308 	// MULTISELECTABLE
309 	rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
310 }
311 
312 
313 SwAccessibleDocument::SwAccessibleDocument ( SwAccessibleMap* pInitMap ) :
314     SwAccessibleDocumentBase( pInitMap ),
315     maSelectionHelper( *this )
316 {
317 	SetName( GetResource( STR_ACCESS_DOC_NAME ) );
318     Window *pWin = pInitMap->GetShell()->GetWin();
319 	if( pWin )
320 	{
321 		pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
322 		sal_uInt16 nCount =   pWin->GetChildCount();
323 		for( sal_uInt16 i=0; i < nCount; i++ )
324 		{
325             Window* pChildWin = pWin->GetChild( i );
326             if( pChildWin &&
327                 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
328                 AddChild( pChildWin, sal_False );
329 		}
330 	}
331 }
332 
333 SwAccessibleDocument::~SwAccessibleDocument()
334 {
335 	Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
336 	if( pWin )
337 		pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
338 }
339 
340 void SwAccessibleDocument::Dispose( sal_Bool bRecursive )
341 {
342 	ASSERT( GetFrm() && GetMap(), "already disposed" );
343 
344 	Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
345 	if( pWin )
346 		pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
347 	SwAccessibleContext::Dispose( bRecursive );
348 }
349 
350 IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
351 {
352 	DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
353 	if ( pEvent && pEvent->ISA( VclWindowEvent ) )
354 	{
355 		VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
356 		DBG_ASSERT( pVclEvent->GetWindow(), "Window???" );
357 		switch ( pVclEvent->GetId() )
358 		{
359         case VCLEVENT_WINDOW_SHOW:  // send create on show for direct accessible children
360 			{
361 				Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
362 				if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
363 				{
364 					AddChild( pChildWin );
365 				}
366 			}
367 			break;
368         case VCLEVENT_WINDOW_HIDE:  // send destroy on hide for direct accessible children
369 			{
370 				Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
371 				if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
372 				{
373 					RemoveChild( pChildWin );
374 				}
375 			}
376 			break;
377         case VCLEVENT_OBJECT_DYING:  // send destroy on hide for direct accessible children
378 			{
379 				Window* pChildWin = pVclEvent->GetWindow();
380 				if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
381 				{
382 					RemoveChild( pChildWin );
383 				}
384 			}
385 			break;
386 		}
387 	}
388 	return 0;
389 }
390 
391 
392 OUString SAL_CALL SwAccessibleDocument::getImplementationName()
393         throw( uno::RuntimeException )
394 {
395 	return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
396 }
397 
398 sal_Bool SAL_CALL SwAccessibleDocument::supportsService(
399 		const ::rtl::OUString& sTestServiceName)
400 	throw (uno::RuntimeException)
401 {
402 	return sTestServiceName.equalsAsciiL( sServiceName,
403 										  sizeof(sServiceName)-1 ) ||
404 		   sTestServiceName.equalsAsciiL( sAccessibleServiceName,
405 				   						  sizeof(sAccessibleServiceName)-1 );
406 }
407 
408 uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames()
409 		throw( uno::RuntimeException )
410 {
411 	uno::Sequence< OUString > aRet(2);
412 	OUString* pArray = aRet.getArray();
413 	pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
414 	pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
415 	return aRet;
416 }
417 
418 //=====  XInterface  ======================================================
419 
420 uno::Any SwAccessibleDocument::queryInterface(
421     const uno::Type& rType )
422     throw ( uno::RuntimeException )
423 {
424     uno::Any aRet;
425     if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) )
426     {
427         uno::Reference<XAccessibleSelection> aSelect = this;
428         aRet <<= aSelect;
429     }
430     else
431         aRet = SwAccessibleContext::queryInterface( rType );
432     return aRet;
433 }
434 
435 //====== XTypeProvider ====================================================
436 uno::Sequence< uno::Type > SAL_CALL SwAccessibleDocument::getTypes()
437     throw(uno::RuntimeException)
438 {
439 	uno::Sequence< uno::Type > aTypes( SwAccessibleDocumentBase::getTypes() );
440 
441 	sal_Int32 nIndex = aTypes.getLength();
442 	aTypes.realloc( nIndex + 1 );
443 
444 	uno::Type* pTypes = aTypes.getArray();
445 	pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
446 
447 	return aTypes;
448 }
449 
450 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleDocument::getImplementationId()
451 		throw(uno::RuntimeException)
452 {
453     vos::OGuard aGuard(Application::GetSolarMutex());
454     static uno::Sequence< sal_Int8 > aId( 16 );
455     static sal_Bool bInit = sal_False;
456     if(!bInit)
457     {
458         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
459         bInit = sal_True;
460     }
461     return aId;
462 }
463 
464 //=====  XAccessibleSelection  ============================================
465 
466 void SwAccessibleDocument::selectAccessibleChild(
467     sal_Int32 nChildIndex )
468     throw ( lang::IndexOutOfBoundsException,
469             uno::RuntimeException )
470 {
471     maSelectionHelper.selectAccessibleChild(nChildIndex);
472 }
473 
474 sal_Bool SwAccessibleDocument::isAccessibleChildSelected(
475     sal_Int32 nChildIndex )
476     throw ( lang::IndexOutOfBoundsException,
477             uno::RuntimeException )
478 {
479     return maSelectionHelper.isAccessibleChildSelected(nChildIndex);
480 }
481 
482 void SwAccessibleDocument::clearAccessibleSelection(  )
483     throw ( uno::RuntimeException )
484 {
485     maSelectionHelper.clearAccessibleSelection();
486 }
487 
488 void SwAccessibleDocument::selectAllAccessibleChildren(  )
489     throw ( uno::RuntimeException )
490 {
491     maSelectionHelper.selectAllAccessibleChildren();
492 }
493 
494 sal_Int32 SwAccessibleDocument::getSelectedAccessibleChildCount(  )
495     throw ( uno::RuntimeException )
496 {
497     return maSelectionHelper.getSelectedAccessibleChildCount();
498 }
499 
500 uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild(
501     sal_Int32 nSelectedChildIndex )
502     throw ( lang::IndexOutOfBoundsException,
503             uno::RuntimeException)
504 {
505     return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
506 }
507 
508 // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
509 void SwAccessibleDocument::deselectAccessibleChild(
510     sal_Int32 nChildIndex )
511     throw ( lang::IndexOutOfBoundsException,
512             uno::RuntimeException )
513 {
514     maSelectionHelper.deselectAccessibleChild( nChildIndex );
515 }
516