1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: accdoc.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <vcl/window.hxx>
34 #include <rootfrm.hxx>
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
39 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <unotools/accessiblestatesethelper.hxx>
42 #include <tools/link.hxx>
43 #include <sfx2/viewsh.hxx>
44 #include <vos/mutex.hxx>
45 #include <vcl/svapp.hxx>
53 #include <pagefrm.hxx>
55 const sal_Char sServiceName
[] = "com.sun.star.text.AccessibleTextDocumentView";
56 const sal_Char sImplementationName
[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView";
59 using namespace ::com::sun::star
;
60 using namespace ::com::sun::star::accessibility
;
61 using ::rtl::OUString
;
63 using lang::IndexOutOfBoundsException
;
68 // SwAccessibleDocumentBase: base class for SwAccessibleDocument and
69 // SwAccessiblePreview
72 SwAccessibleDocumentBase::SwAccessibleDocumentBase ( SwAccessibleMap
* pInitMap
) :
73 SwAccessibleContext( pInitMap
, AccessibleRole::DOCUMENT
,
74 pInitMap
->GetShell()->getIDocumentLayoutAccess()->GetRootFrm() ),
75 mxParent( pInitMap
->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible() ),
80 SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
84 void SwAccessibleDocumentBase::SetVisArea()
86 vos::OGuard
aGuard(Application::GetSolarMutex());
88 SwRect
aOldVisArea( GetVisArea() );
89 const SwRect
& rNewVisArea
= GetMap()->GetVisArea();
90 if( aOldVisArea
!= rNewVisArea
)
92 SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
93 // --> OD 2007-12-07 #i58139#
94 // showing state of document view needs also be updated.
95 // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
96 // ChildrenScrolled( GetFrm(), aOldVisArea );
97 Scrolled( aOldVisArea
);
102 void SwAccessibleDocumentBase::AddChild( Window
*pWin
, sal_Bool bFireEvent
)
104 vos::OGuard
aGuard(Application::GetSolarMutex());
106 ASSERT( !mpChildWin
, "only one child window is supported" );
113 AccessibleEventObject aEvent
;
114 aEvent
.EventId
= AccessibleEventId::CHILD
;
115 aEvent
.NewValue
<<= mpChildWin
->GetAccessible();
116 FireAccessibleEvent( aEvent
);
121 void SwAccessibleDocumentBase::RemoveChild( Window
*pWin
)
123 vos::OGuard
aGuard(Application::GetSolarMutex());
125 ASSERT( !mpChildWin
|| pWin
== mpChildWin
, "invalid child window to remove" );
126 if( mpChildWin
&& pWin
== mpChildWin
)
128 AccessibleEventObject aEvent
;
129 aEvent
.EventId
= AccessibleEventId::CHILD
;
130 aEvent
.OldValue
<<= mpChildWin
->GetAccessible();
131 FireAccessibleEvent( aEvent
);
137 sal_Int32 SAL_CALL
SwAccessibleDocumentBase::getAccessibleChildCount( void )
138 throw (uno::RuntimeException
)
140 vos::OGuard
aGuard(Application::GetSolarMutex());
142 // CHECK_FOR_DEFUNC is called by parent
144 sal_Int32 nChildren
= SwAccessibleContext::getAccessibleChildCount();
145 if( !IsDisposing() && mpChildWin
)
151 uno::Reference
< XAccessible
> SAL_CALL
152 SwAccessibleDocumentBase::getAccessibleChild( sal_Int32 nIndex
)
153 throw (uno::RuntimeException
,
154 lang::IndexOutOfBoundsException
)
156 vos::OGuard
aGuard(Application::GetSolarMutex());
160 CHECK_FOR_DEFUNC( XAccessibleContext
)
161 if( nIndex
== GetChildCount() )
162 return mpChildWin
->GetAccessible();
165 return SwAccessibleContext::getAccessibleChild( nIndex
);
169 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleDocumentBase::getAccessibleParent (void)
170 throw (uno::RuntimeException
)
175 sal_Int32 SAL_CALL
SwAccessibleDocumentBase::getAccessibleIndexInParent (void)
176 throw (uno::RuntimeException
)
178 vos::OGuard
aGuard(Application::GetSolarMutex());
180 uno::Reference
< XAccessibleContext
> xAcc( mxParent
->getAccessibleContext() );
181 uno::Reference
< XAccessible
> xThis( this );
182 sal_Int32 nCount
= xAcc
->getAccessibleChildCount();
184 for( sal_Int32 i
=0; i
< nCount
; i
++ )
186 if( xAcc
->getAccessibleChild( i
) == xThis
)
192 OUString SAL_CALL
SwAccessibleDocumentBase::getAccessibleDescription (void)
193 throw (uno::RuntimeException
)
195 return GetResource( STR_ACCESS_DOC_DESC
);
198 awt::Rectangle SAL_CALL
SwAccessibleDocumentBase::getBounds()
199 throw (uno::RuntimeException
)
201 vos::OGuard
aGuard(Application::GetSolarMutex());
203 Window
*pWin
= GetWindow();
205 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
207 Rectangle
aPixBounds( pWin
->GetWindowExtentsRelative( pWin
->GetAccessibleParentWindow() ) );
208 awt::Rectangle
aBox( aPixBounds
.Left(), aPixBounds
.Top(),
209 aPixBounds
.GetWidth(), aPixBounds
.GetHeight() );
215 awt::Point SAL_CALL
SwAccessibleDocumentBase::getLocation()
216 throw (uno::RuntimeException
)
218 vos::OGuard
aGuard(Application::GetSolarMutex());
220 Window
*pWin
= GetWindow();
222 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
224 Point
aPixPos( pWin
->GetWindowExtentsRelative( pWin
->GetAccessibleParentWindow() ).TopLeft() );
225 awt::Point
aLoc( aPixPos
.X(), aPixPos
.Y() );
231 ::com::sun::star::awt::Point SAL_CALL
SwAccessibleDocumentBase::getLocationOnScreen()
232 throw (uno::RuntimeException
)
234 vos::OGuard
aGuard(Application::GetSolarMutex());
236 Window
*pWin
= GetWindow();
238 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
240 Point
aPixPos( pWin
->GetWindowExtentsRelative( 0 ).TopLeft() );
241 awt::Point
aLoc( aPixPos
.X(), aPixPos
.Y() );
247 ::com::sun::star::awt::Size SAL_CALL
SwAccessibleDocumentBase::getSize()
248 throw (uno::RuntimeException
)
250 vos::OGuard
aGuard(Application::GetSolarMutex());
252 Window
*pWin
= GetWindow();
254 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
256 Size
aPixSize( pWin
->GetWindowExtentsRelative( 0 ).GetSize() );
257 awt::Size
aSize( aPixSize
.Width(), aPixSize
.Height() );
262 sal_Bool SAL_CALL
SwAccessibleDocumentBase::containsPoint(
263 const awt::Point
& aPoint
)
264 throw (uno::RuntimeException
)
266 vos::OGuard
aGuard(Application::GetSolarMutex());
268 Window
*pWin
= GetWindow();
270 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
272 Rectangle
aPixBounds( pWin
->GetWindowExtentsRelative( 0 ) );
273 aPixBounds
.Move(-aPixBounds
.Left(), -aPixBounds
.Top());
275 Point
aPixPoint( aPoint
.X
, aPoint
.Y
);
276 return aPixBounds
.IsInside( aPixPoint
);
279 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleDocumentBase::getAccessibleAtPoint(
280 const awt::Point
& aPoint
)
281 throw (uno::RuntimeException
)
283 vos::OGuard
aGuard(Application::GetSolarMutex());
287 CHECK_FOR_DEFUNC( XAccessibleComponent
)
289 Window
*pWin
= GetWindow();
290 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
292 Point
aPixPoint( aPoint
.X
, aPoint
.Y
); // px rel to window
293 if( mpChildWin
->GetWindowExtentsRelative( pWin
).IsInside( aPixPoint
) )
294 return mpChildWin
->GetAccessible();
297 return SwAccessibleContext::getAccessibleAtPoint( aPoint
);
301 // SwAccessibeDocument
304 void SwAccessibleDocument::GetStates(
305 ::utl::AccessibleStateSetHelper
& rStateSet
)
307 SwAccessibleContext::GetStates( rStateSet
);
310 rStateSet
.AddState( AccessibleStateType::MULTI_SELECTABLE
);
314 SwAccessibleDocument::SwAccessibleDocument ( SwAccessibleMap
* pInitMap
) :
315 SwAccessibleDocumentBase( pInitMap
),
316 maSelectionHelper( *this )
318 SetName( GetResource( STR_ACCESS_DOC_NAME
) );
319 Window
*pWin
= pInitMap
->GetShell()->GetWin();
322 pWin
->AddChildEventListener( LINK( this, SwAccessibleDocument
, WindowChildEventListener
));
323 USHORT nCount
= pWin
->GetChildCount();
324 for( sal_uInt16 i
=0; i
< nCount
; i
++ )
326 Window
* pChildWin
= pWin
->GetChild( i
);
328 AccessibleRole::EMBEDDED_OBJECT
== pChildWin
->GetAccessibleRole() )
329 AddChild( pChildWin
, sal_False
);
334 SwAccessibleDocument::~SwAccessibleDocument()
336 Window
*pWin
= GetMap() ? GetMap()->GetShell()->GetWin() : 0;
338 pWin
->RemoveChildEventListener( LINK( this, SwAccessibleDocument
, WindowChildEventListener
));
341 void SwAccessibleDocument::Dispose( sal_Bool bRecursive
)
343 ASSERT( GetFrm() && GetMap(), "already disposed" );
345 Window
*pWin
= GetMap() ? GetMap()->GetShell()->GetWin() : 0;
347 pWin
->RemoveChildEventListener( LINK( this, SwAccessibleDocument
, WindowChildEventListener
));
348 SwAccessibleContext::Dispose( bRecursive
);
351 IMPL_LINK( SwAccessibleDocument
, WindowChildEventListener
, VclSimpleEvent
*, pEvent
)
353 DBG_ASSERT( pEvent
&& pEvent
->ISA( VclWindowEvent
), "Unknown WindowEvent!" );
354 if ( pEvent
&& pEvent
->ISA( VclWindowEvent
) )
356 VclWindowEvent
*pVclEvent
= static_cast< VclWindowEvent
* >( pEvent
);
357 DBG_ASSERT( pVclEvent
->GetWindow(), "Window???" );
358 switch ( pVclEvent
->GetId() )
360 case VCLEVENT_WINDOW_SHOW
: // send create on show for direct accessible children
362 Window
* pChildWin
= static_cast< Window
* >( pVclEvent
->GetData() );
363 if( pChildWin
&& AccessibleRole::EMBEDDED_OBJECT
== pChildWin
->GetAccessibleRole() )
365 AddChild( pChildWin
);
369 case VCLEVENT_WINDOW_HIDE
: // send destroy on hide for direct accessible children
371 Window
* pChildWin
= static_cast< Window
* >( pVclEvent
->GetData() );
372 if( pChildWin
&& AccessibleRole::EMBEDDED_OBJECT
== pChildWin
->GetAccessibleRole() )
374 RemoveChild( pChildWin
);
378 case VCLEVENT_OBJECT_DYING
: // send destroy on hide for direct accessible children
380 Window
* pChildWin
= pVclEvent
->GetWindow();
381 if( pChildWin
&& AccessibleRole::EMBEDDED_OBJECT
== pChildWin
->GetAccessibleRole() )
383 RemoveChild( pChildWin
);
393 OUString SAL_CALL
SwAccessibleDocument::getImplementationName()
394 throw( uno::RuntimeException
)
396 return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName
));
399 sal_Bool SAL_CALL
SwAccessibleDocument::supportsService(
400 const ::rtl::OUString
& sTestServiceName
)
401 throw (uno::RuntimeException
)
403 return sTestServiceName
.equalsAsciiL( sServiceName
,
404 sizeof(sServiceName
)-1 ) ||
405 sTestServiceName
.equalsAsciiL( sAccessibleServiceName
,
406 sizeof(sAccessibleServiceName
)-1 );
409 uno::Sequence
< OUString
> SAL_CALL
SwAccessibleDocument::getSupportedServiceNames()
410 throw( uno::RuntimeException
)
412 uno::Sequence
< OUString
> aRet(2);
413 OUString
* pArray
= aRet
.getArray();
414 pArray
[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName
) );
415 pArray
[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName
) );
419 //===== XInterface ======================================================
421 uno::Any
SwAccessibleDocument::queryInterface(
422 const uno::Type
& rType
)
423 throw ( uno::RuntimeException
)
426 if ( rType
== ::getCppuType( static_cast< uno::Reference
< XAccessibleSelection
> * >( 0 ) ) )
428 uno::Reference
<XAccessibleSelection
> aSelect
= this;
432 aRet
= SwAccessibleContext::queryInterface( rType
);
436 //====== XTypeProvider ====================================================
437 uno::Sequence
< uno::Type
> SAL_CALL
SwAccessibleDocument::getTypes()
438 throw(uno::RuntimeException
)
440 uno::Sequence
< uno::Type
> aTypes( SwAccessibleDocumentBase::getTypes() );
442 sal_Int32 nIndex
= aTypes
.getLength();
443 aTypes
.realloc( nIndex
+ 1 );
445 uno::Type
* pTypes
= aTypes
.getArray();
446 pTypes
[nIndex
] = ::getCppuType( static_cast< uno::Reference
< XAccessibleSelection
> * >( 0 ) );
451 uno::Sequence
< sal_Int8
> SAL_CALL
SwAccessibleDocument::getImplementationId()
452 throw(uno::RuntimeException
)
454 vos::OGuard
aGuard(Application::GetSolarMutex());
455 static uno::Sequence
< sal_Int8
> aId( 16 );
456 static sal_Bool bInit
= sal_False
;
459 rtl_createUuid( (sal_uInt8
*)(aId
.getArray() ), 0, sal_True
);
465 //===== XAccessibleSelection ============================================
467 void SwAccessibleDocument::selectAccessibleChild(
468 sal_Int32 nChildIndex
)
469 throw ( lang::IndexOutOfBoundsException
,
470 uno::RuntimeException
)
472 maSelectionHelper
.selectAccessibleChild(nChildIndex
);
475 sal_Bool
SwAccessibleDocument::isAccessibleChildSelected(
476 sal_Int32 nChildIndex
)
477 throw ( lang::IndexOutOfBoundsException
,
478 uno::RuntimeException
)
480 return maSelectionHelper
.isAccessibleChildSelected(nChildIndex
);
483 void SwAccessibleDocument::clearAccessibleSelection( )
484 throw ( uno::RuntimeException
)
486 maSelectionHelper
.clearAccessibleSelection();
489 void SwAccessibleDocument::selectAllAccessibleChildren( )
490 throw ( uno::RuntimeException
)
492 maSelectionHelper
.selectAllAccessibleChildren();
495 sal_Int32
SwAccessibleDocument::getSelectedAccessibleChildCount( )
496 throw ( uno::RuntimeException
)
498 return maSelectionHelper
.getSelectedAccessibleChildCount();
501 uno::Reference
<XAccessible
> SwAccessibleDocument::getSelectedAccessibleChild(
502 sal_Int32 nSelectedChildIndex
)
503 throw ( lang::IndexOutOfBoundsException
,
504 uno::RuntimeException
)
506 return maSelectionHelper
.getSelectedAccessibleChild(nSelectedChildIndex
);
509 // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
510 void SwAccessibleDocument::deselectAccessibleChild(
511 sal_Int32 nChildIndex
)
512 throw ( lang::IndexOutOfBoundsException
,
513 uno::RuntimeException
)
515 maSelectionHelper
.deselectAccessibleChild( nChildIndex
);