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