xref: /AOO41X/main/sw/source/core/access/accdoc.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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