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