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