xref: /trunk/main/sw/source/core/access/accdoc.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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