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 <rtl/ref.hxx>
21 : #include <rtl/strbuf.hxx>
22 : #include <cppuhelper/weakref.hxx>
23 : #include <vcl/window.hxx>
24 : #include <svx/svdmodel.hxx>
25 : #include <svx/unomod.hxx>
26 : #include <algorithm>
27 : #include <map>
28 : #include <list>
29 : #include <accmap.hxx>
30 : #include <acccontext.hxx>
31 : #include <accdoc.hxx>
32 : #include <accpreview.hxx>
33 : #include <accpage.hxx>
34 : #include <accpara.hxx>
35 : #include <accheaderfooter.hxx>
36 : #include <accfootnote.hxx>
37 : #include <acctextframe.hxx>
38 : #include <accgraphic.hxx>
39 : #include <accembedded.hxx>
40 : #include <acccell.hxx>
41 : #include <acctable.hxx>
42 : #include <fesh.hxx>
43 : #include <rootfrm.hxx>
44 : #include <txtfrm.hxx>
45 : #include <hffrm.hxx>
46 : #include <ftnfrm.hxx>
47 : #include <cellfrm.hxx>
48 : #include <tabfrm.hxx>
49 : #include <pagefrm.hxx>
50 : #include <flyfrm.hxx>
51 : #include <ndtyp.hxx>
52 : #include <IDocumentDrawModelAccess.hxx>
53 : #include <svx/ShapeTypeHandler.hxx>
54 : #include <vcl/svapp.hxx>
55 : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
56 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
57 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
58 : #include <cppuhelper/implbase1.hxx>
59 : #include <pagepreviewlayout.hxx>
60 : #include <pam.hxx>
61 : #include <ndtxt.hxx>
62 : #include <dflyobj.hxx>
63 : #include <prevwpage.hxx>
64 : #include <switerator.hxx>
65 : #include <boost/bind.hpp>
66 :
67 : using namespace ::com::sun::star;
68 : using namespace ::com::sun::star::accessibility;
69 : using namespace ::sw::access;
70 :
71 : struct SwFrmFunc
72 : {
73 1572 : bool operator()( const SwFrm * p1,
74 : const SwFrm * p2) const
75 : {
76 1572 : return p1 < p2;
77 : }
78 : };
79 :
80 : typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
81 :
82 12 : class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
83 : {
84 : public:
85 :
86 : #if OSL_DEBUG_LEVEL > 0
87 : bool mbLocked;
88 : #endif
89 :
90 12 : SwAccessibleContextMap_Impl()
91 : #if OSL_DEBUG_LEVEL > 0
92 : : mbLocked( false )
93 : #endif
94 12 : {}
95 :
96 : };
97 :
98 : class SwDrawModellListener_Impl : public SfxListener,
99 : public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
100 : {
101 : mutable ::osl::Mutex maListenerMutex;
102 : ::cppu::OInterfaceContainerHelper maEventListeners;
103 : SdrModel *mpDrawModel;
104 : protected:
105 : virtual ~SwDrawModellListener_Impl();
106 : public:
107 :
108 : SwDrawModellListener_Impl( SdrModel *pDrawModel );
109 :
110 :
111 : virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
112 : virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
113 :
114 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
115 : void Dispose();
116 : };
117 :
118 0 : SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
119 : maEventListeners( maListenerMutex ),
120 0 : mpDrawModel( pDrawModel )
121 : {
122 0 : StartListening( *mpDrawModel );
123 0 : }
124 :
125 0 : SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
126 : {
127 0 : EndListening( *mpDrawModel );
128 0 : }
129 :
130 0 : void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
131 : {
132 0 : maEventListeners.addInterface( xListener );
133 0 : }
134 :
135 0 : void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
136 : {
137 0 : maEventListeners.removeInterface( xListener );
138 0 : }
139 :
140 0 : void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
141 : const SfxHint& rHint )
142 : {
143 : // do not broadcast notifications for writer fly frames, because there
144 : // are no shapes that need to know about them.
145 0 : const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
146 0 : if ( !pSdrHint ||
147 0 : ( pSdrHint->GetObject() &&
148 0 : ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
149 0 : pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
150 0 : IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
151 : {
152 0 : return;
153 : }
154 :
155 : OSL_ENSURE( mpDrawModel, "draw model listener is disposed" );
156 0 : if( !mpDrawModel )
157 0 : return;
158 :
159 0 : document::EventObject aEvent;
160 0 : if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
161 0 : return;
162 :
163 0 : ::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
164 0 : while( aIter.hasMoreElements() )
165 : {
166 : uno::Reference < document::XEventListener > xListener( aIter.next(),
167 0 : uno::UNO_QUERY );
168 : try
169 : {
170 0 : xListener->notifyEvent( aEvent );
171 : }
172 0 : catch( uno::RuntimeException const & r )
173 : {
174 : SAL_WARN( "sw.core", "Runtime exception caught while notifying shape.: " << r.Message );
175 : }
176 0 : }
177 : }
178 :
179 0 : void SwDrawModellListener_Impl::Dispose()
180 : {
181 0 : mpDrawModel = 0;
182 0 : }
183 :
184 : struct SwShapeFunc
185 : {
186 0 : bool operator()( const SdrObject * p1,
187 : const SdrObject * p2) const
188 : {
189 0 : return p1 < p2;
190 : }
191 : };
192 : typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
193 : typedef ::std::pair < const SdrObject *, ::rtl::Reference < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
194 :
195 : class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
196 :
197 : {
198 : ::accessibility::AccessibleShapeTreeInfo maInfo;
199 :
200 : public:
201 :
202 : #if OSL_DEBUG_LEVEL > 0
203 : bool mbLocked;
204 : #endif
205 0 : SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
206 : #if OSL_DEBUG_LEVEL > 0
207 : : mbLocked( false )
208 : #endif
209 0 : {
210 0 : maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
211 0 : maInfo.SetWindow( pMap->GetShell()->GetWin() );
212 0 : maInfo.SetViewForwarder( pMap );
213 : uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
214 : new SwDrawModellListener_Impl(
215 0 : pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
216 0 : maInfo.SetControllerBroadcaster( xModelBroadcaster );
217 0 : }
218 :
219 : ~SwAccessibleShapeMap_Impl();
220 :
221 0 : const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
222 :
223 : SwAccessibleObjShape_Impl *Copy( size_t& rSize,
224 : const SwFEShell *pFESh = 0,
225 : SwAccessibleObjShape_Impl **pSelShape = 0 ) const;
226 : };
227 :
228 0 : SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
229 : {
230 0 : uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
231 0 : if( xBrd.is() )
232 0 : static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
233 0 : }
234 :
235 : SwAccessibleObjShape_Impl
236 0 : *SwAccessibleShapeMap_Impl::Copy(
237 : size_t& rSize, const SwFEShell *pFESh,
238 : SwAccessibleObjShape_Impl **pSelStart ) const
239 : {
240 0 : SwAccessibleObjShape_Impl *pShapes = 0;
241 0 : SwAccessibleObjShape_Impl *pSelShape = 0;
242 :
243 0 : sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
244 0 : rSize = size();
245 :
246 0 : if( rSize > 0 )
247 : {
248 : pShapes =
249 0 : new SwAccessibleObjShape_Impl[rSize];
250 :
251 0 : const_iterator aIter = begin();
252 0 : const_iterator aEndIter = end();
253 :
254 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
255 0 : pSelShape = &(pShapes[rSize]);
256 0 : while( aIter != aEndIter )
257 : {
258 0 : const SdrObject *pObj = (*aIter).first;
259 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
260 0 : if( nSelShapes && pFESh->IsObjSelected( *pObj ) )
261 : {
262 : // selected objects are inserted from the back
263 0 : --pSelShape;
264 0 : pSelShape->first = pObj;
265 0 : pSelShape->second =
266 : static_cast < ::accessibility::AccessibleShape* >(
267 0 : xAcc.get() );
268 0 : --nSelShapes;
269 : }
270 : else
271 : {
272 0 : pShape->first = pObj;
273 0 : pShape->second =
274 : static_cast < ::accessibility::AccessibleShape* >(
275 0 : xAcc.get() );
276 0 : ++pShape;
277 : }
278 0 : ++aIter;
279 0 : }
280 : OSL_ENSURE( pSelShape == pShape, "copying shapes went wrong!" );
281 : }
282 :
283 0 : if( pSelStart )
284 0 : *pSelStart = pSelShape;
285 :
286 0 : return pShapes;
287 : }
288 :
289 111 : struct SwAccessibleEvent_Impl
290 : {
291 : public:
292 : enum EventType { CARET_OR_STATES,
293 : INVALID_CONTENT,
294 : POS_CHANGED,
295 : CHILD_POS_CHANGED,
296 : SHAPE_SELECTION,
297 : DISPOSE,
298 : INVALID_ATTR };
299 :
300 : private:
301 : SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
302 : // and POS_CHANGED
303 : uno::WeakReference < XAccessible > mxAcc; // The object that fires the event
304 : SwAccessibleChild maFrmOrObj; // the child for CHILD_POS_CHANGED and
305 : // the same as xAcc for any other
306 : // event type
307 : EventType meType; // The event type
308 : tAccessibleStates mnStates; // check states or update caret pos
309 :
310 : SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
311 :
312 : public:
313 0 : SwAccessibleEvent_Impl( EventType eT,
314 : SwAccessibleContext *pA,
315 : const SwAccessibleChild& rFrmOrObj )
316 : : mxAcc( pA ),
317 : maFrmOrObj( rFrmOrObj ),
318 : meType( eT ),
319 0 : mnStates( 0 )
320 0 : {}
321 :
322 0 : SwAccessibleEvent_Impl( EventType eT,
323 : const SwAccessibleChild& rFrmOrObj )
324 : : maFrmOrObj( rFrmOrObj ),
325 : meType( eT ),
326 0 : mnStates( 0 )
327 : {
328 : OSL_ENSURE( SwAccessibleEvent_Impl::DISPOSE == meType,
329 : "wrong event constructor, DISPOSE only" );
330 0 : }
331 :
332 0 : SwAccessibleEvent_Impl( EventType eT )
333 : : meType( eT ),
334 0 : mnStates( 0 )
335 : {
336 : OSL_ENSURE( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
337 : "wrong event constructor, SHAPE_SELECTION only" );
338 0 : }
339 :
340 37 : SwAccessibleEvent_Impl( EventType eT,
341 : SwAccessibleContext *pA,
342 : const SwAccessibleChild& rFrmOrObj,
343 : const SwRect& rR )
344 : : maOldBox( rR ),
345 : mxAcc( pA ),
346 : maFrmOrObj( rFrmOrObj ),
347 : meType( eT ),
348 37 : mnStates( 0 )
349 : {
350 : OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
351 : SwAccessibleEvent_Impl::POS_CHANGED == meType,
352 : "wrong event constructor, (CHILD_)POS_CHANGED only" );
353 37 : }
354 :
355 0 : SwAccessibleEvent_Impl( EventType eT,
356 : SwAccessibleContext *pA,
357 : const SwAccessibleChild& rFrmOrObj,
358 : const tAccessibleStates _nStates )
359 : : mxAcc( pA ),
360 : maFrmOrObj( rFrmOrObj ),
361 : meType( eT ),
362 0 : mnStates( _nStates )
363 : {
364 : OSL_ENSURE( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
365 : "wrong event constructor, CARET_OR_STATES only" );
366 0 : }
367 :
368 : // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
369 0 : inline void SetType( EventType eT )
370 : {
371 0 : meType = eT;
372 0 : }
373 185 : inline EventType GetType() const
374 : {
375 185 : return meType;
376 : }
377 :
378 37 : inline ::rtl::Reference < SwAccessibleContext > GetContext() const
379 : {
380 37 : uno::Reference < XAccessible > xTmp( mxAcc );
381 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
382 37 : static_cast<SwAccessibleContext*>( xTmp.get() ) );
383 :
384 37 : return xAccImpl;
385 : }
386 :
387 37 : inline const SwRect& GetOldBox() const
388 : {
389 37 : return maOldBox;
390 : }
391 : // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
392 0 : inline void SetOldBox( const SwRect& rOldBox )
393 : {
394 0 : maOldBox = rOldBox;
395 0 : }
396 :
397 83 : inline const SwAccessibleChild& GetFrmOrObj() const
398 : {
399 83 : return maFrmOrObj;
400 : }
401 :
402 : // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
403 0 : inline void SetStates( tAccessibleStates _nStates )
404 : {
405 0 : mnStates |= _nStates;
406 0 : }
407 :
408 37 : inline bool IsUpdateCursorPos() const
409 : {
410 37 : return (mnStates & ACC_STATE_CARET) != 0;
411 : }
412 37 : inline bool IsInvalidateStates() const
413 : {
414 37 : return (mnStates & ACC_STATE_MASK) != 0;
415 : }
416 37 : inline bool IsInvalidateRelation() const
417 : {
418 37 : return (mnStates & ACC_STATE_RELATION_MASK) != 0;
419 : }
420 37 : inline bool IsInvalidateTextSelection() const
421 : {
422 37 : return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
423 : }
424 :
425 37 : inline bool IsInvalidateTextAttrs() const
426 : {
427 37 : return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
428 : }
429 :
430 0 : inline tAccessibleStates GetStates() const
431 : {
432 0 : return mnStates & ACC_STATE_MASK;
433 : }
434 :
435 0 : inline tAccessibleStates GetAllStates() const
436 : {
437 0 : return mnStates;
438 : }
439 :
440 : };
441 :
442 : typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
443 :
444 15 : class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
445 : {
446 : bool mbFiring;
447 :
448 : public:
449 :
450 15 : SwAccessibleEventList_Impl()
451 15 : : mbFiring( false )
452 15 : {}
453 :
454 15 : inline void SetFiring()
455 : {
456 15 : mbFiring = true;
457 15 : }
458 37 : inline bool IsFiring() const
459 : {
460 37 : return mbFiring;
461 : }
462 : };
463 :
464 : // The shape list is filled if an accessible shape is destroyed. It
465 : // simply keeps a reference to the accessible shape's XShape. These
466 : // references are destroyed within the EndAction when firing events.
467 : // There are two reason for this. First of all, a new accessible shape
468 : // for the XShape might be created soon. It's then cheaper if the XShape
469 : // still exists. The other reason are situations where an accessible shape
470 : // is destroyed within an SwFrmFmt::Modify. In this case, destroying
471 : // the XShape at the same time (indirectly by destroying the accessible
472 : // shape) leads to an assert, because a client of the Modify is destroyed
473 : // within a Modify call.
474 :
475 : typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
476 :
477 0 : class SwShapeList_Impl: public _SwShapeList_Impl
478 : {
479 : public:
480 :
481 0 : SwShapeList_Impl() {}
482 : };
483 :
484 : struct SwAccessibleChildFunc
485 : {
486 104 : bool operator()( const SwAccessibleChild& r1,
487 : const SwAccessibleChild& r2 ) const
488 : {
489 104 : const void *p1 = r1.GetSwFrm()
490 : ? static_cast < const void * >( r1.GetSwFrm())
491 0 : : ( r1.GetDrawObject()
492 : ? static_cast < const void * >( r1.GetDrawObject() )
493 104 : : static_cast < const void * >( r1.GetWindow() ) );
494 104 : const void *p2 = r2.GetSwFrm()
495 : ? static_cast < const void * >( r2.GetSwFrm())
496 0 : : ( r2.GetDrawObject()
497 : ? static_cast < const void * >( r2.GetDrawObject() )
498 104 : : static_cast < const void * >( r2.GetWindow() ) );
499 104 : return p1 < p2;
500 : }
501 : };
502 : typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator,
503 : SwAccessibleChildFunc > _SwAccessibleEventMap_Impl;
504 :
505 30 : class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
506 : {
507 : };
508 :
509 : struct SwAccessibleParaSelection
510 : {
511 : xub_StrLen nStartOfSelection;
512 : xub_StrLen nEndOfSelection;
513 :
514 0 : SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
515 : const xub_StrLen _nEndOfSelection )
516 : : nStartOfSelection( _nStartOfSelection ),
517 0 : nEndOfSelection( _nEndOfSelection )
518 0 : {}
519 : };
520 :
521 : struct SwXAccWeakRefComp
522 : {
523 0 : bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
524 : const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
525 : {
526 0 : return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
527 : }
528 : };
529 :
530 : typedef ::std::map< uno::WeakReference < XAccessible >,
531 : SwAccessibleParaSelection,
532 : SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;
533 :
534 0 : class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
535 : {};
536 :
537 : // helper class that stores preview data
538 : class SwAccPreviewData
539 : {
540 : typedef std::vector<Rectangle> Rectangles;
541 : Rectangles maPreviewRects;
542 : Rectangles maLogicRects;
543 :
544 : SwRect maVisArea;
545 : Fraction maScale;
546 :
547 : const SwPageFrm *mpSelPage;
548 :
549 : /** adjust logic page retangle to its visible part
550 :
551 : @param _iorLogicPgSwRect
552 : input/output parameter - reference to the logic page rectangle, which
553 : has to be adjusted.
554 :
555 : @param _rPrevwPgSwRect
556 : input parameter - constant reference to the corresponding preview page
557 : rectangle; needed to determine the visible part of the logic page rectangle.
558 :
559 : @param _rPrevwWinSize
560 : input paramter - constant reference to the preview window size in TWIP;
561 : needed to determine the visible part of the logic page rectangle
562 : */
563 : void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect,
564 : const SwRect& _rPrevwPgSwRect,
565 : const Size& _rPrevwWinSize );
566 :
567 : public:
568 : SwAccPreviewData();
569 : ~SwAccPreviewData();
570 :
571 : void Update( const SwAccessibleMap& rAccMap,
572 : const std::vector<PrevwPage*>& _rPrevwPages,
573 : const Fraction& _rScale,
574 : const SwPageFrm* _pSelectedPageFrm,
575 : const Size& _rPrevwWinSize );
576 :
577 : void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );
578 :
579 : const SwRect& GetVisArea() const;
580 :
581 : MapMode GetMapModeForPreview( ) const;
582 :
583 : /** Adjust the MapMode so that the preview page appears at the
584 : * proper position. rPoint identifies the page for which the
585 : * MapMode should be adjusted. If bFromPreview is true, rPoint is
586 : * a preview coordinate; else it's a document coordinate. */
587 : void AdjustMapMode( MapMode& rMapMode,
588 : const Point& rPoint ) const;
589 :
590 0 : inline const SwPageFrm *GetSelPage() const { return mpSelPage; }
591 :
592 : void DisposePage(const SwPageFrm *pPageFrm );
593 : };
594 :
595 0 : SwAccPreviewData::SwAccPreviewData() :
596 0 : mpSelPage( 0 )
597 : {
598 0 : }
599 :
600 0 : SwAccPreviewData::~SwAccPreviewData()
601 : {
602 0 : }
603 :
604 0 : void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
605 : const std::vector<PrevwPage*>& _rPrevwPages,
606 : const Fraction& _rScale,
607 : const SwPageFrm* _pSelectedPageFrm,
608 : const Size& _rPrevwWinSize )
609 : {
610 : // store preview scaling, maximal preview page size and selected page
611 0 : maScale = _rScale;
612 0 : mpSelPage = _pSelectedPageFrm;
613 :
614 : // prepare loop on preview pages
615 0 : maPreviewRects.clear();
616 0 : maLogicRects.clear();
617 0 : SwAccessibleChild aPage;
618 0 : maVisArea.Clear();
619 :
620 : // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
621 : // <maVisArea>
622 0 : for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
623 0 : aPageIter != _rPrevwPages.end();
624 : ++aPageIter )
625 : {
626 0 : aPage = (*aPageIter)->pPage;
627 :
628 : // add preview page rectangle to <maPreviewRects>
629 0 : Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
630 0 : maPreviewRects.push_back( aPrevwPgRect );
631 :
632 : // add logic page rectangle to <maLogicRects>
633 0 : SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
634 0 : Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
635 0 : maLogicRects.push_back( aLogicPgRect );
636 : // union visible area with visible part of logic page rectangle
637 0 : if ( (*aPageIter)->bVisible )
638 : {
639 0 : if ( !(*aPageIter)->pPage->IsEmptyPage() )
640 : {
641 : AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
642 : SwRect( aPrevwPgRect ),
643 0 : _rPrevwWinSize );
644 : }
645 0 : if ( maVisArea.IsEmpty() )
646 0 : maVisArea = aLogicPgSwRect;
647 : else
648 0 : maVisArea.Union( aLogicPgSwRect );
649 : }
650 : }
651 0 : }
652 :
653 0 : void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
654 : {
655 0 : mpSelPage = _pSelectedPageFrm;
656 : OSL_ENSURE( mpSelPage, "selected page not found" );
657 0 : }
658 :
659 : struct ContainsPredicate
660 : {
661 : const Point& mrPoint;
662 0 : ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
663 0 : bool operator() ( const Rectangle& rRect ) const
664 : {
665 0 : return rRect.IsInside( mrPoint ) ? true : false;
666 : }
667 : };
668 :
669 0 : const SwRect& SwAccPreviewData::GetVisArea() const
670 : {
671 0 : return maVisArea;
672 : }
673 :
674 0 : void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
675 : const Point& rPoint ) const
676 : {
677 : // adjust scale
678 0 : rMapMode.SetScaleX( maScale );
679 0 : rMapMode.SetScaleY( maScale );
680 :
681 : // find proper rectangle
682 0 : Rectangles::const_iterator aBegin = maLogicRects.begin();
683 0 : Rectangles::const_iterator aEnd = maLogicRects.end();
684 : Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
685 0 : ContainsPredicate( rPoint ) );
686 :
687 0 : if( aFound != aEnd )
688 : {
689 : // found! set new origin
690 0 : Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
691 0 : aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
692 0 : rMapMode.SetOrigin( aPoint );
693 : }
694 : // else: don't adjust MapMode
695 0 : }
696 :
697 0 : void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
698 : {
699 0 : if( mpSelPage == pPageFrm )
700 0 : mpSelPage = 0;
701 0 : }
702 :
703 : // adjust logic page retangle to its visible part
704 0 : void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
705 : SwRect& _iorLogicPgSwRect,
706 : const SwRect& _rPrevwPgSwRect,
707 : const Size& _rPrevwWinSize )
708 : {
709 : // determine preview window rectangle
710 0 : const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
711 : // calculate visible preview page rectangle
712 0 : SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
713 0 : aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
714 : // adjust logic page rectangle
715 : SwTwips nTmpDiff;
716 : // left
717 0 : nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
718 0 : if ( nTmpDiff > 0 )
719 0 : _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
720 : // top
721 0 : nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
722 0 : if ( nTmpDiff > 0 )
723 0 : _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
724 : // right
725 0 : nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
726 0 : if ( nTmpDiff > 0 )
727 0 : _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
728 : // bottom
729 0 : nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
730 0 : if ( nTmpDiff > 0 )
731 0 : _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
732 0 : }
733 :
734 15 : static bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
735 : const SwFrm *pFrm )
736 : {
737 15 : bool bRet = false;
738 :
739 15 : if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
740 : {
741 : // Is it in the same table? We check that
742 : // by comparing the last table frame in the
743 : // follow chain, because that's cheaper than
744 : // searching the first one.
745 : SwAccessibleContext *pAccImpl =
746 1 : static_cast< SwAccessibleContext *>( rAcc.get() );
747 1 : if( pAccImpl->GetFrm()->IsCellFrm() )
748 : {
749 1 : const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
750 2 : while( pTabFrm1->GetFollow() )
751 0 : pTabFrm1 = pTabFrm1->GetFollow();
752 :
753 1 : const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
754 2 : while( pTabFrm2->GetFollow() )
755 0 : pTabFrm2 = pTabFrm2->GetFollow();
756 :
757 1 : bRet = (pTabFrm1 == pTabFrm2);
758 : }
759 : }
760 :
761 15 : return bRet;
762 : }
763 :
764 37 : void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
765 : {
766 37 : ::rtl::Reference < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
767 37 : if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
768 : {
769 0 : DoInvalidateShapeSelection();
770 : }
771 37 : else if( xAccImpl.is() && xAccImpl->GetFrm() )
772 : {
773 74 : if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
774 37 : rEvent.IsInvalidateTextAttrs() )
775 : {
776 0 : xAccImpl->InvalidateAttr();
777 : }
778 37 : switch( rEvent.GetType() )
779 : {
780 : case SwAccessibleEvent_Impl::INVALID_CONTENT:
781 0 : xAccImpl->InvalidateContent();
782 0 : break;
783 : case SwAccessibleEvent_Impl::POS_CHANGED:
784 28 : xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
785 28 : break;
786 : case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
787 18 : xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
788 18 : rEvent.GetOldBox() );
789 9 : break;
790 : case SwAccessibleEvent_Impl::DISPOSE:
791 : OSL_ENSURE( xAccImpl.is(),
792 : "dispose event has been stored" );
793 0 : break;
794 : case SwAccessibleEvent_Impl::INVALID_ATTR:
795 : // nothing to do here - handled above
796 0 : break;
797 : default:
798 0 : break;
799 : }
800 37 : if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
801 : {
802 37 : if( rEvent.IsUpdateCursorPos() )
803 0 : xAccImpl->InvalidateCursorPos();
804 37 : if( rEvent.IsInvalidateStates() )
805 0 : xAccImpl->InvalidateStates( rEvent.GetStates() );
806 37 : if( rEvent.IsInvalidateRelation() )
807 : {
808 : // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
809 : // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
810 0 : if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
811 : {
812 : xAccImpl->InvalidateRelation(
813 0 : AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
814 : }
815 0 : if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
816 : {
817 : xAccImpl->InvalidateRelation(
818 0 : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
819 : }
820 : }
821 :
822 37 : if ( rEvent.IsInvalidateTextSelection() )
823 : {
824 0 : xAccImpl->InvalidateTextSelection();
825 : }
826 : }
827 37 : }
828 37 : }
829 :
830 37 : void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
831 : {
832 37 : osl::MutexGuard aGuard( maEventMutex );
833 :
834 37 : if( !mpEvents )
835 15 : mpEvents = new SwAccessibleEventList_Impl;
836 37 : if( !mpEventMap )
837 15 : mpEventMap = new SwAccessibleEventMap_Impl;
838 :
839 37 : if( mpEvents->IsFiring() )
840 : {
841 : // While events are fired new ones are generated. They have to be fired
842 : // now. This does not work for DISPOSE events!
843 : OSL_ENSURE( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
844 : "dispose event while firing events" );
845 0 : FireEvent( rEvent );
846 : }
847 : else
848 : {
849 :
850 : SwAccessibleEventMap_Impl::iterator aIter =
851 37 : mpEventMap->find( rEvent.GetFrmOrObj() );
852 37 : if( aIter != mpEventMap->end() )
853 : {
854 0 : SwAccessibleEvent_Impl aEvent( *(*aIter).second );
855 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
856 : "dispose events should not be stored" );
857 0 : bool bAppendEvent = true;
858 0 : switch( rEvent.GetType() )
859 : {
860 : case SwAccessibleEvent_Impl::CARET_OR_STATES:
861 : // A CARET_OR_STATES event is added to any other
862 : // event only. It is broadcasted after any other event, so the
863 : // event should be put to the back.
864 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
865 : "invalid event combination" );
866 0 : aEvent.SetStates( rEvent.GetAllStates() );
867 0 : break;
868 : case SwAccessibleEvent_Impl::INVALID_CONTENT:
869 : // An INVALID_CONTENT event overwrites a CARET_OR_STATES
870 : // event (but keeps its flags) and it is contained in a
871 : // POS_CHANGED event.
872 : // Therefore, the event's type has to be adapted and the event
873 : // has to be put at the end.
874 : //
875 : // fdo#56031 An INVALID_CONTENT event overwrites a INVALID_ATTR
876 : // event and overwrites its flags
877 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
878 : "invalid event combination" );
879 0 : if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
880 0 : aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
881 0 : else if ( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR )
882 : {
883 0 : aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
884 0 : aEvent.SetStates( rEvent.GetAllStates() );
885 : }
886 :
887 0 : break;
888 : case SwAccessibleEvent_Impl::POS_CHANGED:
889 : // A pos changed event overwrites CARET_STATES (keeping its
890 : // flags) as well as INVALID_CONTENT. The old box position
891 : // has to be stored however if the old event is not a
892 : // POS_CHANGED itself.
893 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
894 : "invalid event combination" );
895 0 : if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
896 0 : aEvent.SetOldBox( rEvent.GetOldBox() );
897 0 : aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
898 0 : break;
899 : case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
900 : // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
901 : // events. The only action that needs to be done again is
902 : // to put the old event to the back. The new one cannot be used,
903 : // because we are interested in the old frame bounds.
904 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
905 : "invalid event combination" );
906 0 : break;
907 : case SwAccessibleEvent_Impl::SHAPE_SELECTION:
908 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
909 : "invalid event combination" );
910 0 : break;
911 : case SwAccessibleEvent_Impl::DISPOSE:
912 : // DISPOSE events overwrite all others. They are not stored
913 : // but executed immediately to avoid broadcasting of
914 : // defunctional objects. So what needs to be done here is to
915 : // remove all events for the frame in question.
916 0 : bAppendEvent = false;
917 0 : break;
918 : case SwAccessibleEvent_Impl::INVALID_ATTR:
919 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
920 : "invalid event combination" );
921 0 : break;
922 : }
923 0 : if( bAppendEvent )
924 : {
925 0 : mpEvents->erase( (*aIter).second );
926 0 : (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
927 : }
928 : else
929 : {
930 0 : mpEvents->erase( (*aIter).second );
931 0 : mpEventMap->erase( aIter );
932 0 : }
933 : }
934 37 : else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
935 : {
936 37 : SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
937 74 : mpEvents->insert( mpEvents->end(), rEvent ) );
938 37 : mpEventMap->insert( aEntry );
939 : }
940 37 : }
941 37 : }
942 :
943 68 : void SwAccessibleMap::InvalidateCursorPosition(
944 : const uno::Reference< XAccessible >& rAcc )
945 : {
946 : SwAccessibleContext *pAccImpl =
947 68 : static_cast< SwAccessibleContext *>( rAcc.get() );
948 : OSL_ENSURE( pAccImpl, "no caret context" );
949 : OSL_ENSURE( pAccImpl->GetFrm(), "caret context is disposed" );
950 68 : if( GetShell()->ActionPend() )
951 : {
952 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
953 : pAccImpl,
954 : SwAccessibleChild(pAccImpl->GetFrm()),
955 0 : ACC_STATE_CARET );
956 0 : AppendEvent( aEvent );
957 : }
958 : else
959 : {
960 68 : FireEvents();
961 : // While firing events the current frame might have
962 : // been disposed because it moved out of the vis area.
963 : // Setting the cursor for such frames is useless and even
964 : // causes asserts.
965 68 : if( pAccImpl->GetFrm() )
966 68 : pAccImpl->InvalidateCursorPos();
967 : }
968 68 : }
969 :
970 0 : void SwAccessibleMap::InvalidateShapeSelection()
971 : {
972 0 : if( GetShell()->ActionPend() )
973 : {
974 : SwAccessibleEvent_Impl aEvent(
975 0 : SwAccessibleEvent_Impl::SHAPE_SELECTION );
976 0 : AppendEvent( aEvent );
977 : }
978 : else
979 : {
980 0 : FireEvents();
981 0 : DoInvalidateShapeSelection();
982 : }
983 0 : }
984 :
985 0 : void SwAccessibleMap::DoInvalidateShapeSelection()
986 : {
987 0 : SwAccessibleObjShape_Impl *pShapes = 0;
988 0 : SwAccessibleObjShape_Impl *pSelShape = 0;
989 0 : size_t nShapes = 0;
990 :
991 0 : const ViewShell *pVSh = GetShell();
992 0 : const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
993 0 : static_cast< const SwFEShell * >( pVSh ) : 0;
994 0 : sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
995 :
996 : {
997 0 : osl::MutexGuard aGuard( maMutex );
998 0 : if( mpShapeMap )
999 0 : pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1000 : }
1001 :
1002 0 : if( pShapes )
1003 : {
1004 0 : ::std::list< const SwFrm * > aParents;
1005 0 : Window *pWin = GetShell()->GetWin();
1006 0 : bool bFocused = pWin && pWin->HasFocus();
1007 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
1008 0 : while( nShapes )
1009 : {
1010 0 : if( pShape->second.is() )
1011 : {
1012 : sal_Bool bChanged;
1013 0 : if( pShape >= pSelShape )
1014 : {
1015 : bChanged =
1016 0 : pShape->second->SetState( AccessibleStateType::SELECTED );
1017 0 : if( bFocused && 1 == nSelShapes )
1018 0 : pShape->second->SetState( AccessibleStateType::FOCUSED );
1019 : else
1020 0 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1021 : }
1022 : else
1023 : {
1024 : bChanged =
1025 0 : pShape->second->ResetState( AccessibleStateType::SELECTED );
1026 0 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1027 : }
1028 0 : if( bChanged )
1029 : {
1030 : const SwFrm* pParent = SwAccessibleFrame::GetParent(
1031 : SwAccessibleChild( pShape->first ),
1032 0 : GetShell()->IsPreView() );
1033 0 : aParents.push_back( pParent );
1034 : }
1035 : }
1036 :
1037 0 : --nShapes;
1038 0 : ++pShape;
1039 : }
1040 0 : if( aParents.size() > 0 )
1041 : {
1042 0 : ::std::list< const SwFrm * >::const_iterator aIter = aParents.begin();
1043 0 : ::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end();
1044 0 : while( aIter != aEndIter )
1045 : {
1046 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
1047 : {
1048 0 : osl::MutexGuard aGuard( maMutex );
1049 0 : if( mpFrmMap )
1050 : {
1051 : SwAccessibleContextMap_Impl::const_iterator aMapIter =
1052 0 : mpFrmMap->find( *aIter );
1053 0 : if( aMapIter != mpFrmMap->end() )
1054 : {
1055 0 : uno::Reference < XAccessible > xAcc( (*aMapIter).second );
1056 0 : xParentAccImpl =
1057 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
1058 : }
1059 0 : }
1060 : }
1061 0 : if( xParentAccImpl.is() )
1062 : {
1063 0 : AccessibleEventObject aEvent;
1064 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1065 0 : xParentAccImpl->FireAccessibleEvent( aEvent );
1066 : }
1067 :
1068 0 : ++aIter;
1069 0 : }
1070 : }
1071 :
1072 0 : delete[] pShapes;
1073 : }
1074 0 : }
1075 :
1076 0 : void SwAccessibleMap::DoInvalidateShapeFocus()
1077 : {
1078 0 : const ViewShell *pVSh = GetShell();
1079 0 : const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1080 0 : static_cast< const SwFEShell * >( pVSh ) : 0;
1081 0 : sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1082 :
1083 0 : if( nSelShapes != 1 )
1084 0 : return;
1085 :
1086 0 : SwAccessibleObjShape_Impl *pShapes = 0;
1087 0 : SwAccessibleObjShape_Impl *pSelShape = 0;
1088 0 : size_t nShapes = 0;
1089 :
1090 : {
1091 0 : osl::MutexGuard aGuard( maMutex );
1092 0 : if( mpShapeMap )
1093 0 : pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1094 : }
1095 :
1096 0 : if( pShapes )
1097 : {
1098 0 : Window *pWin = GetShell()->GetWin();
1099 0 : bool bFocused = pWin && pWin->HasFocus();
1100 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
1101 0 : while( nShapes )
1102 : {
1103 0 : if( pShape->second.is() )
1104 : {
1105 0 : if( bFocused && pShape >= pSelShape )
1106 0 : pShape->second->SetState( AccessibleStateType::FOCUSED );
1107 : else
1108 0 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1109 : }
1110 :
1111 0 : --nShapes;
1112 0 : ++pShape;
1113 : }
1114 :
1115 0 : delete[] pShapes;
1116 : }
1117 : }
1118 :
1119 12 : SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
1120 : mpFrmMap( 0 ),
1121 : mpShapeMap( 0 ),
1122 : mpShapes( 0 ),
1123 : mpEvents( 0 ),
1124 : mpEventMap( 0 ),
1125 : mpSelectedParas( 0 ),
1126 : mpVSh( pSh ),
1127 : mpPreview( 0 ),
1128 : mnPara( 1 ),
1129 : mnFootnote( 1 ),
1130 : mnEndnote( 1 ),
1131 12 : mbShapeSelected( false )
1132 : {
1133 12 : pSh->GetLayout()->AddAccessibleShell();
1134 12 : }
1135 :
1136 36 : SwAccessibleMap::~SwAccessibleMap()
1137 : {
1138 12 : uno::Reference < XAccessible > xAcc;
1139 : {
1140 12 : osl::MutexGuard aGuard( maMutex );
1141 12 : if( mpFrmMap )
1142 : {
1143 12 : const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1144 12 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1145 12 : if( aIter != mpFrmMap->end() )
1146 12 : xAcc = (*aIter).second;
1147 12 : if( !xAcc.is() )
1148 0 : xAcc = new SwAccessibleDocument( this );
1149 12 : }
1150 : }
1151 :
1152 : SwAccessibleDocument *pAcc =
1153 12 : static_cast< SwAccessibleDocument * >( xAcc.get() );
1154 12 : pAcc->Dispose( sal_True );
1155 :
1156 : {
1157 12 : osl::MutexGuard aGuard( maMutex );
1158 : #if OSL_DEBUG_LEVEL > 0
1159 : OSL_ENSURE( !mpFrmMap || mpFrmMap->empty(),
1160 : "Frame map should be empty after disposing the root frame" );
1161 : if( mpFrmMap )
1162 : {
1163 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1164 : while( aIter != mpFrmMap->end() )
1165 : {
1166 : uno::Reference < XAccessible > xTmp = (*aIter).second;
1167 : if( xTmp.is() )
1168 : {
1169 : SwAccessibleContext *pTmp =
1170 : static_cast< SwAccessibleContext * >( xTmp.get() );
1171 : (void) pTmp;
1172 : }
1173 : ++aIter;
1174 : }
1175 : }
1176 : OSL_ENSURE( !mpShapeMap || mpShapeMap->empty(),
1177 : "Object map should be empty after disposing the root frame" );
1178 : if( mpShapeMap )
1179 : {
1180 : SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
1181 : while( aIter != mpShapeMap->end() )
1182 : {
1183 : uno::Reference < XAccessible > xTmp = (*aIter).second;
1184 : if( xTmp.is() )
1185 : {
1186 : ::accessibility::AccessibleShape *pTmp =
1187 : static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
1188 : (void) pTmp;
1189 : }
1190 : ++aIter;
1191 : }
1192 : }
1193 : #endif
1194 12 : delete mpFrmMap;
1195 12 : mpFrmMap = 0;
1196 12 : delete mpShapeMap;
1197 12 : mpShapeMap = 0;
1198 12 : delete mpShapes;
1199 12 : mpShapes = 0;
1200 12 : delete mpSelectedParas;
1201 12 : mpSelectedParas = 0;
1202 : }
1203 :
1204 12 : delete mpPreview;
1205 12 : mpPreview = NULL;
1206 :
1207 : {
1208 12 : osl::MutexGuard aGuard( maEventMutex );
1209 : #if OSL_DEBUG_LEVEL > 0
1210 : OSL_ENSURE( !(mpEvents || mpEventMap), "pending events" );
1211 : if( mpEvents )
1212 : {
1213 : SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
1214 : while( aIter != mpEvents->end() )
1215 : {
1216 : ++aIter;
1217 : }
1218 : }
1219 : if( mpEventMap )
1220 : {
1221 : SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
1222 : while( aIter != mpEventMap->end() )
1223 : {
1224 : ++aIter;
1225 : }
1226 : }
1227 : #endif
1228 12 : delete mpEventMap;
1229 12 : mpEventMap = 0;
1230 12 : delete mpEvents;
1231 12 : mpEvents = 0;
1232 : }
1233 12 : mpVSh->GetLayout()->RemoveAccessibleShell();
1234 24 : }
1235 :
1236 31 : uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
1237 : bool bPagePreview )
1238 : {
1239 31 : uno::Reference < XAccessible > xAcc;
1240 31 : bool bSetVisArea = false;
1241 :
1242 : {
1243 31 : osl::MutexGuard aGuard( maMutex );
1244 :
1245 31 : if( !mpFrmMap )
1246 : {
1247 12 : mpFrmMap = new SwAccessibleContextMap_Impl;
1248 : #if OSL_DEBUG_LEVEL > 0
1249 : mpFrmMap->mbLocked = false;
1250 : #endif
1251 : }
1252 :
1253 : #if OSL_DEBUG_LEVEL > 0
1254 : OSL_ENSURE( !mpFrmMap->mbLocked, "Map is locked" );
1255 : mpFrmMap->mbLocked = true;
1256 : #endif
1257 :
1258 31 : const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1259 31 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1260 31 : if( aIter != mpFrmMap->end() )
1261 19 : xAcc = (*aIter).second;
1262 31 : if( xAcc.is() )
1263 : {
1264 19 : bSetVisArea = true; // Set VisArea when map mutex is not locked
1265 : }
1266 : else
1267 : {
1268 12 : if( bPagePreview )
1269 0 : xAcc = new SwAccessiblePreview( this );
1270 : else
1271 12 : xAcc = new SwAccessibleDocument( this );
1272 :
1273 12 : if( aIter != mpFrmMap->end() )
1274 : {
1275 0 : (*aIter).second = xAcc;
1276 : }
1277 : else
1278 : {
1279 12 : SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
1280 12 : mpFrmMap->insert( aEntry );
1281 : }
1282 31 : }
1283 :
1284 : #if OSL_DEBUG_LEVEL > 0
1285 : mpFrmMap->mbLocked = false;
1286 : #endif
1287 : }
1288 :
1289 31 : if( bSetVisArea )
1290 : {
1291 : SwAccessibleDocumentBase *pAcc =
1292 19 : static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1293 19 : pAcc->SetVisArea();
1294 : }
1295 :
1296 31 : return xAcc;
1297 : }
1298 :
1299 31 : uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1300 : {
1301 31 : return _GetDocumentView( false );
1302 : }
1303 :
1304 0 : uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1305 : const std::vector<PrevwPage*>& _rPrevwPages,
1306 : const Fraction& _rScale,
1307 : const SwPageFrm* _pSelectedPageFrm,
1308 : const Size& _rPrevwWinSize )
1309 : {
1310 : // create & update preview data object
1311 0 : if( mpPreview == NULL )
1312 0 : mpPreview = new SwAccPreviewData();
1313 0 : mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
1314 :
1315 0 : uno::Reference<XAccessible> xAcc = _GetDocumentView( true );
1316 0 : return xAcc;
1317 : }
1318 :
1319 329 : uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
1320 : sal_Bool bCreate )
1321 : {
1322 329 : uno::Reference < XAccessible > xAcc;
1323 658 : uno::Reference < XAccessible > xOldCursorAcc;
1324 329 : bool bOldShapeSelected = false;
1325 :
1326 : {
1327 329 : osl::MutexGuard aGuard( maMutex );
1328 :
1329 329 : if( !mpFrmMap && bCreate )
1330 0 : mpFrmMap = new SwAccessibleContextMap_Impl;
1331 329 : if( mpFrmMap )
1332 : {
1333 329 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1334 329 : if( aIter != mpFrmMap->end() )
1335 211 : xAcc = (*aIter).second;
1336 :
1337 329 : if( !xAcc.is() && bCreate )
1338 : {
1339 28 : SwAccessibleContext *pAcc = 0;
1340 28 : switch( pFrm->GetType() )
1341 : {
1342 : case FRM_TXT:
1343 17 : mnPara++;
1344 34 : pAcc = new SwAccessibleParagraph( *this,
1345 34 : static_cast< const SwTxtFrm& >( *pFrm ) );
1346 17 : break;
1347 : case FRM_HEADER:
1348 : pAcc = new SwAccessibleHeaderFooter( this,
1349 0 : static_cast< const SwHeaderFrm *>( pFrm ) );
1350 0 : break;
1351 : case FRM_FOOTER:
1352 : pAcc = new SwAccessibleHeaderFooter( this,
1353 0 : static_cast< const SwFooterFrm *>( pFrm ) );
1354 0 : break;
1355 : case FRM_FTN:
1356 : {
1357 : const SwFtnFrm *pFtnFrm =
1358 1 : static_cast < const SwFtnFrm * >( pFrm );
1359 : sal_Bool bIsEndnote =
1360 1 : SwAccessibleFootnote::IsEndnote( pFtnFrm );
1361 : pAcc = new SwAccessibleFootnote( this, bIsEndnote,
1362 : (bIsEndnote ? mnEndnote++ : mnFootnote++),
1363 1 : pFtnFrm );
1364 : }
1365 1 : break;
1366 : case FRM_FLY:
1367 : {
1368 : const SwFlyFrm *pFlyFrm =
1369 1 : static_cast < const SwFlyFrm * >( pFrm );
1370 1 : switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
1371 : {
1372 : case ND_GRFNODE:
1373 1 : pAcc = new SwAccessibleGraphic( this, pFlyFrm );
1374 1 : break;
1375 : case ND_OLENODE:
1376 0 : pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
1377 0 : break;
1378 : default:
1379 0 : pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
1380 0 : break;
1381 : }
1382 : }
1383 1 : break;
1384 : case FRM_CELL:
1385 : pAcc = new SwAccessibleCell( this,
1386 7 : static_cast< const SwCellFrm *>( pFrm ) );
1387 7 : break;
1388 : case FRM_TAB:
1389 : pAcc = new SwAccessibleTable( this,
1390 2 : static_cast< const SwTabFrm *>( pFrm ) );
1391 2 : break;
1392 : case FRM_PAGE:
1393 : OSL_ENSURE( GetShell()->IsPreView(),
1394 : "accessible page frames only in PagePreview" );
1395 0 : pAcc = new SwAccessiblePage( this, pFrm );
1396 0 : break;
1397 : }
1398 28 : xAcc = pAcc;
1399 :
1400 : OSL_ENSURE( xAcc.is(), "unknown frame type" );
1401 28 : if( xAcc.is() )
1402 : {
1403 28 : if( aIter != mpFrmMap->end() )
1404 : {
1405 0 : (*aIter).second = xAcc;
1406 : }
1407 : else
1408 : {
1409 28 : SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
1410 28 : mpFrmMap->insert( aEntry );
1411 : }
1412 :
1413 98 : if( pAcc->HasCursor() &&
1414 70 : !AreInSameTable( mxCursorContext, pFrm ) )
1415 : {
1416 : // If the new context has the focus, and if we know
1417 : // another context that had the focus, then the focus
1418 : // just moves from the old context to the new one. We
1419 : // then have to send a focus event and a caret event for
1420 : // the old context. We have to to that now,
1421 : // because after we have left this method, anyone might
1422 : // call getStates for the new context and will get a
1423 : // focused state then. Sending the focus changes event
1424 : // after that seems to be strange. However, we cannot
1425 : // send a focus event for the new context now, because
1426 : // noone except us knows it. In any case, we remember
1427 : // the new context as the one that has the focus
1428 : // currently.
1429 :
1430 14 : xOldCursorAcc = mxCursorContext;
1431 14 : mxCursorContext = xAcc;
1432 :
1433 14 : bOldShapeSelected = mbShapeSelected;
1434 14 : mbShapeSelected = false;
1435 : }
1436 : }
1437 : }
1438 329 : }
1439 : }
1440 :
1441 : // Invalidate focus for old object when map is not locked
1442 329 : if( xOldCursorAcc.is() )
1443 0 : InvalidateCursorPosition( xOldCursorAcc );
1444 329 : if( bOldShapeSelected )
1445 0 : InvalidateShapeSelection();
1446 :
1447 658 : return xAcc;
1448 : }
1449 :
1450 283 : ::rtl::Reference < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
1451 : const SwFrm *pFrm,
1452 : sal_Bool bCreate )
1453 : {
1454 283 : uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
1455 :
1456 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
1457 283 : static_cast< SwAccessibleContext * >( xAcc.get() ) );
1458 :
1459 283 : return xAccImpl;
1460 : }
1461 :
1462 0 : uno::Reference< XAccessible> SwAccessibleMap::GetContext(
1463 : const SdrObject *pObj,
1464 : SwAccessibleContext *pParentImpl,
1465 : sal_Bool bCreate )
1466 : {
1467 0 : uno::Reference < XAccessible > xAcc;
1468 0 : uno::Reference < XAccessible > xOldCursorAcc;
1469 :
1470 : {
1471 0 : osl::MutexGuard aGuard( maMutex );
1472 :
1473 0 : if( !mpShapeMap && bCreate )
1474 0 : mpShapeMap = new SwAccessibleShapeMap_Impl( this );
1475 0 : if( mpShapeMap )
1476 : {
1477 : SwAccessibleShapeMap_Impl::iterator aIter =
1478 0 : mpShapeMap->find( pObj );
1479 0 : if( aIter != mpShapeMap->end() )
1480 0 : xAcc = (*aIter).second;
1481 :
1482 0 : if( !xAcc.is() && bCreate )
1483 : {
1484 0 : ::accessibility::AccessibleShape *pAcc = 0;
1485 : uno::Reference < drawing::XShape > xShape(
1486 0 : const_cast< SdrObject * >( pObj )->getUnoShape(),
1487 0 : uno::UNO_QUERY );
1488 0 : if( xShape.is() )
1489 : {
1490 : ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
1491 0 : ::accessibility::ShapeTypeHandler::Instance();
1492 0 : uno::Reference < XAccessible > xParent( pParentImpl );
1493 : ::accessibility::AccessibleShapeInfo aShapeInfo(
1494 0 : xShape, xParent, this );
1495 :
1496 : pAcc = rShapeTypeHandler.CreateAccessibleObject(
1497 0 : aShapeInfo, mpShapeMap->GetInfo() );
1498 : }
1499 0 : xAcc = pAcc;
1500 :
1501 : OSL_ENSURE( xAcc.is(), "unknown shape type" );
1502 0 : if( xAcc.is() )
1503 : {
1504 0 : pAcc->Init();
1505 0 : if( aIter != mpShapeMap->end() )
1506 : {
1507 0 : (*aIter).second = xAcc;
1508 : }
1509 : else
1510 : {
1511 : SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
1512 0 : xAcc );
1513 0 : mpShapeMap->insert( aEntry );
1514 : }
1515 : // TODO: focus!!!
1516 0 : }
1517 : }
1518 0 : }
1519 : }
1520 :
1521 : // Invalidate focus for old object when map is not locked
1522 0 : if( xOldCursorAcc.is() )
1523 0 : InvalidateCursorPosition( xOldCursorAcc );
1524 :
1525 0 : return xAcc;
1526 : }
1527 :
1528 0 : ::rtl::Reference < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
1529 : const SdrObject *pObj,
1530 : SwAccessibleContext *pParentImpl,
1531 : sal_Bool bCreate )
1532 : {
1533 0 : uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
1534 :
1535 : ::rtl::Reference < ::accessibility::AccessibleShape > xAccImpl(
1536 0 : static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
1537 :
1538 0 : return xAccImpl;
1539 : }
1540 :
1541 40 : void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
1542 : {
1543 40 : osl::MutexGuard aGuard( maMutex );
1544 :
1545 40 : if( mpFrmMap )
1546 : {
1547 : SwAccessibleContextMap_Impl::iterator aIter =
1548 40 : mpFrmMap->find( pFrm );
1549 40 : if( aIter != mpFrmMap->end() )
1550 : {
1551 40 : mpFrmMap->erase( aIter );
1552 :
1553 : // Remove reference to old caret object. Though mxCursorContext
1554 : // is a weak reference and cleared automatically, clearing it
1555 : // directly makes sure to not keep a non-functional object.
1556 40 : uno::Reference < XAccessible > xOldAcc( mxCursorContext );
1557 40 : if( xOldAcc.is() )
1558 : {
1559 : SwAccessibleContext *pOldAccImpl =
1560 10 : static_cast< SwAccessibleContext *>( xOldAcc.get() );
1561 : OSL_ENSURE( pOldAccImpl->GetFrm(), "old caret context is disposed" );
1562 10 : if( pOldAccImpl->GetFrm() == pFrm )
1563 : {
1564 9 : xOldAcc.clear(); // get an empty ref
1565 9 : mxCursorContext = xOldAcc;
1566 : }
1567 : }
1568 :
1569 40 : if( mpFrmMap->empty() )
1570 : {
1571 12 : delete mpFrmMap;
1572 12 : mpFrmMap = 0;
1573 40 : }
1574 : }
1575 40 : }
1576 40 : }
1577 :
1578 0 : void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
1579 : {
1580 0 : osl::MutexGuard aGuard( maMutex );
1581 :
1582 0 : if( mpShapeMap )
1583 : {
1584 : SwAccessibleShapeMap_Impl::iterator aIter =
1585 0 : mpShapeMap->find( pObj );
1586 0 : if( aIter != mpShapeMap->end() )
1587 : {
1588 0 : mpShapeMap->erase( aIter );
1589 :
1590 : // The shape selection flag is not cleared, but one might do
1591 : // so but has to make sure that the removed context is the one
1592 : // that is selected.
1593 :
1594 0 : if( mpShapeMap->empty() )
1595 : {
1596 0 : delete mpShapeMap;
1597 0 : mpShapeMap = 0;
1598 : }
1599 : }
1600 0 : }
1601 0 : }
1602 :
1603 0 : void SwAccessibleMap::Dispose( const SwFrm *pFrm,
1604 : const SdrObject *pObj,
1605 : Window* pWindow,
1606 : sal_Bool bRecursive )
1607 : {
1608 0 : SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
1609 :
1610 : // Indeed, the following assert checks the frame's accessible flag,
1611 : // because that's the one that is evaluated in the layout. The frame
1612 : // might not be accessible anyway. That's the case for cell frames that
1613 : // contain further cells.
1614 : OSL_ENSURE( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
1615 : "non accessible frame should be disposed" );
1616 :
1617 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1618 : {
1619 0 : ::rtl::Reference< SwAccessibleContext > xAccImpl;
1620 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
1621 0 : ::rtl::Reference< ::accessibility::AccessibleShape > xShapeAccImpl;
1622 : // get accessible context for frame
1623 : {
1624 0 : osl::MutexGuard aGuard( maMutex );
1625 :
1626 : // First of all look for an accessible context for a frame
1627 0 : if( aFrmOrObj.GetSwFrm() && mpFrmMap )
1628 : {
1629 : SwAccessibleContextMap_Impl::iterator aIter =
1630 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1631 0 : if( aIter != mpFrmMap->end() )
1632 : {
1633 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1634 0 : xAccImpl =
1635 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
1636 : }
1637 : }
1638 0 : if( !xAccImpl.is() && mpFrmMap )
1639 : {
1640 : // If there is none, look if the parent is accessible.
1641 : const SwFrm *pParent =
1642 : SwAccessibleFrame::GetParent( aFrmOrObj,
1643 0 : GetShell()->IsPreView());
1644 :
1645 0 : if( pParent )
1646 : {
1647 : SwAccessibleContextMap_Impl::iterator aIter =
1648 0 : mpFrmMap->find( pParent );
1649 0 : if( aIter != mpFrmMap->end() )
1650 : {
1651 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1652 0 : xParentAccImpl =
1653 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
1654 : }
1655 : }
1656 : }
1657 0 : if( !xParentAccImpl.is() && !aFrmOrObj.GetSwFrm() &&
1658 : mpShapeMap )
1659 : {
1660 : SwAccessibleShapeMap_Impl::iterator aIter =
1661 0 : mpShapeMap->find( aFrmOrObj.GetDrawObject() );
1662 0 : if( aIter != mpShapeMap->end() )
1663 : {
1664 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1665 0 : xShapeAccImpl =
1666 0 : static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
1667 : }
1668 : }
1669 0 : if( pObj && GetShell()->ActionPend() &&
1670 0 : (xParentAccImpl.is() || xShapeAccImpl.is()) )
1671 : {
1672 : // Keep a reference to the XShape to avoid that it
1673 : // is deleted with a SwFrmFmt::Modify.
1674 : uno::Reference < drawing::XShape > xShape(
1675 0 : const_cast< SdrObject * >( pObj )->getUnoShape(),
1676 0 : uno::UNO_QUERY );
1677 0 : if( xShape.is() )
1678 : {
1679 0 : if( !mpShapes )
1680 0 : mpShapes = new SwShapeList_Impl;
1681 0 : mpShapes->push_back( xShape );
1682 0 : }
1683 0 : }
1684 : }
1685 :
1686 : // remove events stored for the frame
1687 : {
1688 0 : osl::MutexGuard aGuard( maEventMutex );
1689 0 : if( mpEvents )
1690 : {
1691 : SwAccessibleEventMap_Impl::iterator aIter =
1692 0 : mpEventMap->find( aFrmOrObj );
1693 0 : if( aIter != mpEventMap->end() )
1694 : {
1695 : SwAccessibleEvent_Impl aEvent(
1696 0 : SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
1697 0 : AppendEvent( aEvent );
1698 : }
1699 0 : }
1700 : }
1701 :
1702 : // If the frame is accessible and there is a context for it, dispose
1703 : // the frame. If the frame is no context for it but disposing should
1704 : // take place recursive, the frame's children have to be disposed
1705 : // anyway, so we have to create the context then.
1706 0 : if( xAccImpl.is() )
1707 : {
1708 0 : xAccImpl->Dispose( bRecursive );
1709 : }
1710 0 : else if( xParentAccImpl.is() )
1711 : {
1712 : // If the frame is a cell frame, the table must be notified.
1713 : // If we are in an action, a table model change event will
1714 : // be broadcasted at the end of the action to give the table
1715 : // a chance to generate a single table change event.
1716 :
1717 0 : xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
1718 : }
1719 0 : else if( xShapeAccImpl.is() )
1720 : {
1721 0 : RemoveContext( aFrmOrObj.GetDrawObject() );
1722 0 : xShapeAccImpl->dispose();
1723 : }
1724 :
1725 0 : if( mpPreview && pFrm && pFrm->IsPageFrm() )
1726 0 : mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
1727 : }
1728 0 : }
1729 :
1730 59 : void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
1731 : const SdrObject *pObj,
1732 : Window* pWindow,
1733 : const SwRect& rOldBox )
1734 : {
1735 59 : SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
1736 59 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1737 : {
1738 37 : ::rtl::Reference< SwAccessibleContext > xAccImpl;
1739 74 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
1740 : {
1741 37 : osl::MutexGuard aGuard( maMutex );
1742 :
1743 37 : if( mpFrmMap )
1744 : {
1745 37 : if( aFrmOrObj.GetSwFrm() )
1746 : {
1747 : SwAccessibleContextMap_Impl::iterator aIter =
1748 37 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1749 37 : if( aIter != mpFrmMap->end() )
1750 : {
1751 : // If there is an accesible object already it is
1752 : // notified directly.
1753 28 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1754 28 : xAccImpl =
1755 56 : static_cast< SwAccessibleContext *>( xAcc.get() );
1756 : }
1757 : }
1758 37 : if( !xAccImpl.is() )
1759 : {
1760 : // Otherwise we look if the parent is accessible.
1761 : // If not, there is nothing to do.
1762 : const SwFrm *pParent =
1763 : SwAccessibleFrame::GetParent( aFrmOrObj,
1764 9 : GetShell()->IsPreView());
1765 :
1766 9 : if( pParent )
1767 : {
1768 : SwAccessibleContextMap_Impl::iterator aIter =
1769 9 : mpFrmMap->find( pParent );
1770 9 : if( aIter != mpFrmMap->end() )
1771 : {
1772 9 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1773 9 : xParentAccImpl =
1774 18 : static_cast< SwAccessibleContext *>( xAcc.get() );
1775 : }
1776 : }
1777 : }
1778 37 : }
1779 : }
1780 :
1781 37 : if( xAccImpl.is() )
1782 : {
1783 28 : if( GetShell()->ActionPend() )
1784 : {
1785 : SwAccessibleEvent_Impl aEvent(
1786 : SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.get(),
1787 28 : aFrmOrObj, rOldBox );
1788 28 : AppendEvent( aEvent );
1789 : }
1790 : else
1791 : {
1792 0 : FireEvents();
1793 0 : xAccImpl->InvalidatePosOrSize( rOldBox );
1794 : }
1795 : }
1796 9 : else if( xParentAccImpl.is() )
1797 : {
1798 9 : if( GetShell()->ActionPend() )
1799 : {
1800 : SwAccessibleEvent_Impl aEvent(
1801 : SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1802 9 : xParentAccImpl.get(), aFrmOrObj, rOldBox );
1803 9 : AppendEvent( aEvent );
1804 : }
1805 : else
1806 : {
1807 0 : FireEvents();
1808 0 : xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
1809 0 : rOldBox );
1810 : }
1811 37 : }
1812 : }
1813 59 : }
1814 :
1815 0 : void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
1816 : {
1817 0 : SwAccessibleChild aFrmOrObj( pFrm );
1818 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1819 : {
1820 0 : uno::Reference < XAccessible > xAcc;
1821 : {
1822 0 : osl::MutexGuard aGuard( maMutex );
1823 :
1824 0 : if( mpFrmMap )
1825 : {
1826 : SwAccessibleContextMap_Impl::iterator aIter =
1827 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1828 0 : if( aIter != mpFrmMap->end() )
1829 0 : xAcc = (*aIter).second;
1830 0 : }
1831 : }
1832 :
1833 0 : if( xAcc.is() )
1834 : {
1835 : SwAccessibleContext *pAccImpl =
1836 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
1837 0 : if( GetShell()->ActionPend() )
1838 : {
1839 : SwAccessibleEvent_Impl aEvent(
1840 : SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
1841 0 : aFrmOrObj );
1842 0 : AppendEvent( aEvent );
1843 : }
1844 : else
1845 : {
1846 0 : FireEvents();
1847 0 : pAccImpl->InvalidateContent();
1848 : }
1849 0 : }
1850 : }
1851 0 : }
1852 :
1853 0 : void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
1854 : {
1855 0 : SwAccessibleChild aFrmOrObj( &rTxtFrm );
1856 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1857 : {
1858 0 : uno::Reference < XAccessible > xAcc;
1859 : {
1860 0 : osl::MutexGuard aGuard( maMutex );
1861 :
1862 0 : if( mpFrmMap )
1863 : {
1864 : SwAccessibleContextMap_Impl::iterator aIter =
1865 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1866 0 : if( aIter != mpFrmMap->end() )
1867 0 : xAcc = (*aIter).second;
1868 0 : }
1869 : }
1870 :
1871 0 : if( xAcc.is() )
1872 : {
1873 : SwAccessibleContext *pAccImpl =
1874 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
1875 0 : if( GetShell()->ActionPend() )
1876 : {
1877 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
1878 0 : pAccImpl, aFrmOrObj );
1879 0 : aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
1880 0 : AppendEvent( aEvent );
1881 : }
1882 : else
1883 : {
1884 0 : FireEvents();
1885 0 : pAccImpl->InvalidateAttr();
1886 : }
1887 0 : }
1888 : }
1889 0 : }
1890 :
1891 76 : void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
1892 : {
1893 76 : SwAccessibleChild aFrmOrObj( pFrm );
1894 76 : bool bShapeSelected = false;
1895 76 : const ViewShell *pVSh = GetShell();
1896 76 : if( pVSh->ISA( SwCrsrShell ) )
1897 : {
1898 76 : const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
1899 76 : if( pCSh->IsTableMode() )
1900 : {
1901 24 : while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
1902 8 : aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
1903 : }
1904 68 : else if( pVSh->ISA( SwFEShell ) )
1905 : {
1906 68 : const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
1907 68 : const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
1908 68 : if( pFlyFrm )
1909 : {
1910 : OSL_ENSURE( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
1911 : "cursor is not contained in fly frame" );
1912 0 : aFrmOrObj = pFlyFrm;
1913 : }
1914 68 : else if( pFESh->IsObjSelected() > 0 )
1915 : {
1916 0 : bShapeSelected = true;
1917 0 : aFrmOrObj = static_cast<const SwFrm *>( 0 );
1918 : }
1919 : }
1920 : }
1921 :
1922 : OSL_ENSURE( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
1923 : "frame is not accessible" );
1924 :
1925 76 : uno::Reference < XAccessible > xOldAcc;
1926 152 : uno::Reference < XAccessible > xAcc;
1927 76 : bool bOldShapeSelected = false;
1928 :
1929 : {
1930 76 : osl::MutexGuard aGuard( maMutex );
1931 :
1932 76 : xOldAcc = mxCursorContext;
1933 76 : mxCursorContext = xAcc; // clear reference
1934 :
1935 76 : bOldShapeSelected = mbShapeSelected;
1936 76 : mbShapeSelected = bShapeSelected;
1937 :
1938 76 : if( aFrmOrObj.GetSwFrm() && mpFrmMap )
1939 : {
1940 : SwAccessibleContextMap_Impl::iterator aIter =
1941 76 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1942 76 : if( aIter != mpFrmMap->end() )
1943 60 : xAcc = (*aIter).second;
1944 :
1945 : // For cells, some extra thoughts are necessary,
1946 : // because invalidating the cursor for one cell
1947 : // invalidates the cursor for all cells of the same
1948 : // table. For this reason, we don't want to
1949 : // invalidate the cursor for the old cursor object
1950 : // and the new one if they are within the same table,
1951 : // because this would result in doing the work twice.
1952 : // Moreover, we have to make sure to invalidate the
1953 : // cursor even if the current cell has no accessible object.
1954 : // If the old cursor objects exists and is in the same
1955 : // table, its the best choice, because using it avoids
1956 : // an unnessarary cursor invalidation cycle when creating
1957 : // a new object for the current cell.
1958 76 : if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
1959 : {
1960 9 : if( xOldAcc.is() &&
1961 1 : AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
1962 : {
1963 1 : if( xAcc.is() )
1964 1 : xOldAcc = xAcc; // avoid extra invalidation
1965 : else
1966 0 : xAcc = xOldAcc; // make sure ate least one
1967 : }
1968 8 : if( !xAcc.is() )
1969 5 : xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
1970 : }
1971 76 : }
1972 : }
1973 :
1974 76 : if( xOldAcc.is() && xOldAcc != xAcc )
1975 3 : InvalidateCursorPosition( xOldAcc );
1976 76 : if( bOldShapeSelected || bShapeSelected )
1977 0 : InvalidateShapeSelection();
1978 76 : if( xAcc.is() )
1979 141 : InvalidateCursorPosition( xAcc );
1980 76 : }
1981 :
1982 12 : void SwAccessibleMap::InvalidateFocus()
1983 : {
1984 12 : uno::Reference < XAccessible > xAcc;
1985 : bool bShapeSelected;
1986 : {
1987 12 : osl::MutexGuard aGuard( maMutex );
1988 :
1989 12 : xAcc = mxCursorContext;
1990 12 : bShapeSelected = mbShapeSelected;
1991 : }
1992 :
1993 12 : if( xAcc.is() )
1994 : {
1995 : SwAccessibleContext *pAccImpl =
1996 9 : static_cast< SwAccessibleContext *>( xAcc.get() );
1997 9 : pAccImpl->InvalidateFocus();
1998 : }
1999 3 : else if( bShapeSelected )
2000 : {
2001 0 : DoInvalidateShapeFocus();
2002 12 : }
2003 12 : }
2004 :
2005 79 : void SwAccessibleMap::SetCursorContext(
2006 : const ::rtl::Reference < SwAccessibleContext >& rCursorContext )
2007 : {
2008 79 : osl::MutexGuard aGuard( maMutex );
2009 158 : uno::Reference < XAccessible > xAcc( rCursorContext.get() );
2010 158 : mxCursorContext = xAcc;
2011 79 : }
2012 :
2013 0 : void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
2014 : const SwFrm* _pFrm )
2015 : {
2016 : // Start with the frame or the first upper that is accessible
2017 0 : SwAccessibleChild aFrmOrObj( _pFrm );
2018 0 : while( aFrmOrObj.GetSwFrm() &&
2019 0 : !aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2020 0 : aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2021 0 : if( !aFrmOrObj.GetSwFrm() )
2022 0 : aFrmOrObj = GetShell()->GetLayout();
2023 :
2024 0 : uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
2025 : SwAccessibleContext *pAccImpl =
2026 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2027 0 : if( GetShell()->ActionPend() )
2028 : {
2029 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2030 : pAccImpl,
2031 : SwAccessibleChild(pAccImpl->GetFrm()),
2032 0 : _nStates );
2033 0 : AppendEvent( aEvent );
2034 : }
2035 : else
2036 : {
2037 0 : FireEvents();
2038 0 : pAccImpl->InvalidateStates( _nStates );
2039 0 : }
2040 0 : }
2041 :
2042 0 : void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
2043 : bool bFrom )
2044 : {
2045 : // first, see if this frame is accessible, and if so, get the respective
2046 0 : SwAccessibleChild aFrmOrObj( pFrm );
2047 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2048 : {
2049 0 : uno::Reference < XAccessible > xAcc;
2050 : {
2051 0 : osl::MutexGuard aGuard( maMutex );
2052 :
2053 0 : if( mpFrmMap )
2054 : {
2055 : SwAccessibleContextMap_Impl::iterator aIter =
2056 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2057 0 : if( aIter != mpFrmMap->end() )
2058 : {
2059 0 : xAcc = (*aIter).second;
2060 : }
2061 0 : }
2062 : }
2063 :
2064 : // deliver event directly, or queue event
2065 0 : if( xAcc.is() )
2066 : {
2067 : SwAccessibleContext *pAccImpl =
2068 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2069 0 : if( GetShell()->ActionPend() )
2070 : {
2071 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2072 : pAccImpl, SwAccessibleChild(pFrm),
2073 : ( bFrom
2074 : ? ACC_STATE_RELATION_FROM
2075 0 : : ACC_STATE_RELATION_TO ) );
2076 0 : AppendEvent( aEvent );
2077 : }
2078 : else
2079 : {
2080 0 : FireEvents();
2081 : pAccImpl->InvalidateRelation( bFrom
2082 : ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
2083 0 : : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
2084 : }
2085 0 : }
2086 : }
2087 0 : }
2088 :
2089 0 : void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
2090 : const SwFrm* pFollow )
2091 : {
2092 0 : _InvalidateRelationSet( pMaster, false );
2093 0 : _InvalidateRelationSet( pFollow, true );
2094 0 : }
2095 :
2096 : // invalidation of CONTENT_FLOW_FROM/_TO relation of a paragraph
2097 0 : void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
2098 : const bool _bFrom )
2099 : {
2100 0 : _InvalidateRelationSet( &_rTxtFrm, _bFrom );
2101 0 : }
2102 :
2103 : // invalidation of text selection of a paragraph
2104 0 : void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
2105 : {
2106 : // first, see if this frame is accessible, and if so, get the respective
2107 0 : SwAccessibleChild aFrmOrObj( &_rTxtFrm );
2108 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2109 : {
2110 0 : uno::Reference < XAccessible > xAcc;
2111 : {
2112 0 : osl::MutexGuard aGuard( maMutex );
2113 :
2114 0 : if( mpFrmMap )
2115 : {
2116 : SwAccessibleContextMap_Impl::iterator aIter =
2117 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2118 0 : if( aIter != mpFrmMap->end() )
2119 : {
2120 0 : xAcc = (*aIter).second;
2121 : }
2122 0 : }
2123 : }
2124 :
2125 : // deliver event directly, or queue event
2126 0 : if( xAcc.is() )
2127 : {
2128 : SwAccessibleContext *pAccImpl =
2129 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2130 0 : if( GetShell()->ActionPend() )
2131 : {
2132 : SwAccessibleEvent_Impl aEvent(
2133 : SwAccessibleEvent_Impl::CARET_OR_STATES,
2134 : pAccImpl,
2135 : SwAccessibleChild( &_rTxtFrm ),
2136 0 : ACC_STATE_TEXT_SELECTION_CHANGED );
2137 0 : AppendEvent( aEvent );
2138 : }
2139 : else
2140 : {
2141 0 : FireEvents();
2142 0 : pAccImpl->InvalidateTextSelection();
2143 : }
2144 0 : }
2145 : }
2146 0 : }
2147 :
2148 0 : sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
2149 : Window& rChild ) const
2150 : {
2151 0 : sal_Int32 nIndex( -1 );
2152 :
2153 0 : SwAccessibleChild aFrmOrObj( &rParentFrm );
2154 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
2155 : {
2156 0 : uno::Reference < XAccessible > xAcc;
2157 : {
2158 0 : osl::MutexGuard aGuard( maMutex );
2159 :
2160 0 : if( mpFrmMap )
2161 : {
2162 : SwAccessibleContextMap_Impl::iterator aIter =
2163 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2164 0 : if( aIter != mpFrmMap->end() )
2165 : {
2166 0 : xAcc = (*aIter).second;
2167 : }
2168 0 : }
2169 : }
2170 :
2171 0 : if( xAcc.is() )
2172 : {
2173 : SwAccessibleContext *pAccImpl =
2174 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2175 :
2176 : nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
2177 0 : SwAccessibleChild( &rChild ) );
2178 0 : }
2179 : }
2180 :
2181 0 : return nIndex;
2182 : }
2183 :
2184 0 : void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
2185 : const Fraction& _rScale,
2186 : const SwPageFrm* _pSelectedPageFrm,
2187 : const Size& _rPrevwWinSize )
2188 : {
2189 : OSL_ENSURE( GetShell()->IsPreView(), "no preview?" );
2190 : OSL_ENSURE( mpPreview != NULL, "no preview data?" );
2191 :
2192 0 : mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
2193 :
2194 : // propagate change of VisArea through the document's
2195 : // accessibility tree; this will also send appropriate scroll
2196 : // events
2197 : SwAccessibleContext* pDoc =
2198 0 : GetContextImpl( GetShell()->GetLayout() ).get();
2199 0 : static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
2200 :
2201 0 : uno::Reference < XAccessible > xOldAcc;
2202 0 : uno::Reference < XAccessible > xAcc;
2203 : {
2204 0 : osl::MutexGuard aGuard( maMutex );
2205 :
2206 0 : xOldAcc = mxCursorContext;
2207 :
2208 0 : const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2209 0 : if( pSelPage && mpFrmMap )
2210 : {
2211 : SwAccessibleContextMap_Impl::iterator aIter =
2212 0 : mpFrmMap->find( pSelPage );
2213 0 : if( aIter != mpFrmMap->end() )
2214 0 : xAcc = (*aIter).second;
2215 0 : }
2216 : }
2217 :
2218 0 : if( xOldAcc.is() && xOldAcc != xAcc )
2219 0 : InvalidateCursorPosition( xOldAcc );
2220 0 : if( xAcc.is() )
2221 0 : InvalidateCursorPosition( xAcc );
2222 0 : }
2223 :
2224 0 : void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
2225 : {
2226 : OSL_ENSURE( GetShell()->IsPreView(), "no preview?" );
2227 : OSL_ENSURE( mpPreview != NULL, "no preview data?" );
2228 :
2229 0 : mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
2230 :
2231 0 : uno::Reference < XAccessible > xOldAcc;
2232 0 : uno::Reference < XAccessible > xAcc;
2233 : {
2234 0 : osl::MutexGuard aGuard( maMutex );
2235 :
2236 0 : xOldAcc = mxCursorContext;
2237 :
2238 0 : const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2239 0 : if( pSelPage && mpFrmMap )
2240 : {
2241 : SwAccessibleContextMap_Impl::iterator aIter =
2242 0 : mpFrmMap->find( pSelPage );
2243 0 : if( aIter != mpFrmMap->end() )
2244 0 : xAcc = (*aIter).second;
2245 0 : }
2246 : }
2247 :
2248 0 : if( xOldAcc.is() && xOldAcc != xAcc )
2249 0 : InvalidateCursorPosition( xOldAcc );
2250 0 : if( xAcc.is() )
2251 0 : InvalidateCursorPosition( xAcc );
2252 0 : }
2253 :
2254 :
2255 0 : bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
2256 : {
2257 0 : return mpPreview && mpPreview->GetSelPage() == pPageFrm;
2258 : }
2259 :
2260 :
2261 144 : void SwAccessibleMap::FireEvents()
2262 : {
2263 : {
2264 144 : osl::MutexGuard aGuard( maEventMutex );
2265 144 : if( mpEvents )
2266 : {
2267 15 : mpEvents->SetFiring();
2268 : ::std::for_each(mpEvents->begin(), mpEvents->end(),
2269 15 : boost::bind(&SwAccessibleMap::FireEvent, this, _1));
2270 :
2271 15 : delete mpEventMap;
2272 15 : mpEventMap = 0;
2273 :
2274 15 : delete mpEvents;
2275 15 : mpEvents = 0;
2276 144 : }
2277 : }
2278 : {
2279 144 : osl::MutexGuard aGuard( maMutex );
2280 144 : if( mpShapes )
2281 : {
2282 0 : delete mpShapes;
2283 0 : mpShapes = 0;
2284 144 : }
2285 : }
2286 :
2287 144 : }
2288 :
2289 0 : sal_Bool SwAccessibleMap::IsValid() const
2290 : {
2291 0 : return sal_True;
2292 : }
2293 :
2294 0 : Rectangle SwAccessibleMap::GetVisibleArea() const
2295 : {
2296 0 : MapMode aSrc( MAP_TWIP );
2297 0 : MapMode aDest( MAP_100TH_MM );
2298 0 : return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
2299 : }
2300 :
2301 : // Convert a MM100 value relative to the document root into a pixel value
2302 : // relative to the screen!
2303 0 : Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
2304 : {
2305 0 : MapMode aSrc( MAP_100TH_MM );
2306 0 : MapMode aDest( MAP_TWIP );
2307 :
2308 0 : Point aPoint = rPoint;
2309 :
2310 0 : aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2311 0 : Window *pWin = GetShell()->GetWin();
2312 0 : if( pWin )
2313 : {
2314 0 : MapMode aMapMode;
2315 0 : GetMapMode( aPoint, aMapMode );
2316 0 : aPoint = pWin->LogicToPixel( aPoint, aMapMode );
2317 0 : aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
2318 : }
2319 :
2320 0 : return aPoint;
2321 : }
2322 :
2323 0 : Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
2324 : {
2325 0 : MapMode aSrc( MAP_100TH_MM );
2326 0 : MapMode aDest( MAP_TWIP );
2327 0 : Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
2328 0 : if( GetShell()->GetWin() )
2329 : {
2330 0 : MapMode aMapMode;
2331 0 : GetMapMode( Point(0,0), aMapMode );
2332 0 : aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
2333 : }
2334 :
2335 0 : return aSize;
2336 : }
2337 :
2338 0 : Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
2339 : {
2340 0 : Point aPoint;
2341 0 : Window *pWin = GetShell()->GetWin();
2342 0 : if( pWin )
2343 : {
2344 0 : aPoint = pWin->ScreenToOutputPixel( rPoint );
2345 0 : MapMode aMapMode;
2346 0 : GetMapMode( aPoint, aMapMode );
2347 0 : aPoint = pWin->PixelToLogic( aPoint, aMapMode );
2348 0 : MapMode aSrc( MAP_TWIP );
2349 0 : MapMode aDest( MAP_100TH_MM );
2350 0 : aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2351 : }
2352 :
2353 0 : return aPoint;
2354 : }
2355 :
2356 0 : Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
2357 : {
2358 0 : Size aSize;
2359 0 : if( GetShell()->GetWin() )
2360 : {
2361 0 : MapMode aMapMode;
2362 0 : GetMapMode( Point(0,0), aMapMode );
2363 0 : aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
2364 0 : MapMode aSrc( MAP_TWIP );
2365 0 : MapMode aDest( MAP_100TH_MM );
2366 0 : aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
2367 : }
2368 :
2369 0 : return aSize;
2370 : }
2371 :
2372 0 : sal_Bool SwAccessibleMap::ReplaceChild (
2373 : ::accessibility::AccessibleShape* pCurrentChild,
2374 : const uno::Reference< drawing::XShape >& _rxShape,
2375 : const long /*_nIndex*/,
2376 : const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
2377 : ) throw (uno::RuntimeException)
2378 : {
2379 0 : const SdrObject *pObj = 0;
2380 : {
2381 0 : osl::MutexGuard aGuard( maMutex );
2382 0 : if( mpShapeMap )
2383 : {
2384 0 : SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
2385 0 : SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
2386 0 : while( aIter != aEndIter && !pObj )
2387 : {
2388 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2389 : ::accessibility::AccessibleShape *pAccShape =
2390 0 : static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
2391 0 : if( pAccShape == pCurrentChild )
2392 : {
2393 0 : pObj = (*aIter).first;
2394 : }
2395 0 : ++aIter;
2396 0 : }
2397 0 : }
2398 : }
2399 0 : if( !pObj )
2400 0 : return sal_False;
2401 :
2402 0 : uno::Reference < drawing::XShape > xShape( _rxShape ); // keep reference to shape, because
2403 : // we might be the only one that
2404 : // holds it.
2405 : // Also get keep parent.
2406 0 : uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
2407 0 : pCurrentChild = 0; // will be released by dispose
2408 0 : Dispose( 0, pObj, 0 );
2409 :
2410 : {
2411 0 : osl::MutexGuard aGuard( maMutex );
2412 :
2413 0 : if( !mpShapeMap )
2414 0 : mpShapeMap = new SwAccessibleShapeMap_Impl( this );
2415 :
2416 : // create the new child
2417 : ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2418 0 : ::accessibility::ShapeTypeHandler::Instance();
2419 : ::accessibility::AccessibleShapeInfo aShapeInfo(
2420 0 : xShape, xParent, this );
2421 : ::accessibility::AccessibleShape* pReplacement =
2422 : rShapeTypeHandler.CreateAccessibleObject (
2423 0 : aShapeInfo, mpShapeMap->GetInfo() );
2424 :
2425 0 : uno::Reference < XAccessible > xAcc( pReplacement );
2426 0 : if( xAcc.is() )
2427 : {
2428 0 : pReplacement->Init();
2429 :
2430 : SwAccessibleShapeMap_Impl::iterator aIter =
2431 0 : mpShapeMap->find( pObj );
2432 0 : if( aIter != mpShapeMap->end() )
2433 : {
2434 0 : (*aIter).second = xAcc;
2435 : }
2436 : else
2437 : {
2438 0 : SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
2439 0 : mpShapeMap->insert( aEntry );
2440 : }
2441 0 : }
2442 : }
2443 :
2444 0 : SwRect aEmptyRect;
2445 0 : InvalidatePosOrSize( 0, pObj, 0, aEmptyRect );
2446 :
2447 0 : return sal_True;
2448 : }
2449 :
2450 0 : Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
2451 : {
2452 0 : Point aPoint;
2453 0 : if( GetShell()->GetWin() )
2454 : {
2455 0 : MapMode aMapMode;
2456 0 : GetMapMode( rPoint, aMapMode );
2457 0 : aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
2458 : }
2459 0 : return aPoint;
2460 : }
2461 :
2462 12572 : static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
2463 : long aRefValue, bool bToLower)
2464 : {
2465 12572 : long aResult = aCoarseValue;
2466 :
2467 12572 : if (bToLower)
2468 : {
2469 6286 : if (aFineValue < aRefValue)
2470 2622 : aResult -= 1;
2471 : }
2472 : else
2473 : {
2474 6286 : if (aFineValue > aRefValue)
2475 188 : aResult += 1;
2476 : }
2477 :
2478 12572 : return aResult;
2479 : }
2480 :
2481 3143 : static inline void lcl_CorrectRectangle(Rectangle & rRect,
2482 : const Rectangle & rSource,
2483 : const Rectangle & rInGrid)
2484 : {
2485 6286 : rRect.Left() = lcl_CorrectCoarseValue(rRect.Left(), rSource.Left(),
2486 6286 : rInGrid.Left(), false);
2487 6286 : rRect.Top() = lcl_CorrectCoarseValue(rRect.Top(), rSource.Top(),
2488 6286 : rInGrid.Top(), false);
2489 6286 : rRect.Right() = lcl_CorrectCoarseValue(rRect.Right(), rSource.Right(),
2490 6286 : rInGrid.Right(), true);
2491 6286 : rRect.Bottom() = lcl_CorrectCoarseValue(rRect.Bottom(), rSource.Bottom(),
2492 6286 : rInGrid.Bottom(), true);
2493 3143 : }
2494 :
2495 3143 : Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
2496 : {
2497 3143 : Rectangle aRect;
2498 3143 : if( GetShell()->GetWin() )
2499 : {
2500 3143 : MapMode aMapMode;
2501 3143 : GetMapMode( rRect.TopLeft(), aMapMode );
2502 3143 : aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
2503 :
2504 3143 : Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
2505 3143 : lcl_CorrectRectangle(aRect, rRect, aTmpRect);
2506 : }
2507 :
2508 3143 : return aRect;
2509 : }
2510 :
2511 : /** get mapping mode for LogicToPixel and PixelToLogic conversions
2512 :
2513 : Method returns mapping mode of current output device and adjusts it,
2514 : if the shell is in page/print preview.
2515 : Necessary, because <PreviewAdjust(..)> changes mapping mode at current
2516 : output device for mapping logic document positions to page preview window
2517 : positions and vice versa and doesn't take care to recover its changes.
2518 : */
2519 3143 : void SwAccessibleMap::GetMapMode( const Point& _rPoint,
2520 : MapMode& _orMapMode ) const
2521 : {
2522 3143 : MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
2523 3143 : if( GetShell()->IsPreView() )
2524 : {
2525 : OSL_ENSURE( mpPreview != NULL, "need preview data" );
2526 :
2527 0 : mpPreview->AdjustMapMode( aMapMode, _rPoint );
2528 : }
2529 3143 : _orMapMode = aMapMode;
2530 3143 : }
2531 :
2532 0 : Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
2533 : {
2534 : OSL_ENSURE( mpVSh->IsPreView(), "no page preview accessible." );
2535 : OSL_ENSURE( mpVSh->IsPreView() && ( mpPreview != NULL ),
2536 : "missing accessible preview data at page preview" );
2537 0 : if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
2538 : {
2539 0 : return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
2540 : }
2541 : else
2542 : {
2543 0 : return Size( 0, 0 );
2544 : }
2545 : }
2546 :
2547 : /** method to build up a new data structure of the accessible pararaphs,
2548 : which have a selection
2549 : Important note: method has to be used inside a mutual exclusive section
2550 : */
2551 76 : SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
2552 : {
2553 : // no accessible contexts, no selection
2554 76 : if ( !mpFrmMap )
2555 : {
2556 0 : return 0L;
2557 : }
2558 :
2559 : // get cursor as an instance of its base class <SwPaM>
2560 76 : SwPaM* pCrsr( 0L );
2561 : {
2562 76 : SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
2563 76 : if ( pCrsrShell )
2564 : {
2565 76 : SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
2566 228 : if ( !pFEShell ||
2567 152 : ( !pFEShell->IsFrmSelected() &&
2568 76 : pFEShell->IsObjSelected() == 0 ) )
2569 : {
2570 : // get cursor without updating an existing table cursor.
2571 76 : pCrsr = pCrsrShell->GetCrsr( sal_False );
2572 : }
2573 : }
2574 : }
2575 : // no cursor, no selection
2576 76 : if ( !pCrsr )
2577 : {
2578 0 : return 0L;
2579 : }
2580 :
2581 76 : SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );
2582 :
2583 : // loop on all cursors
2584 76 : SwPaM* pRingStart = pCrsr;
2585 91 : do {
2586 :
2587 : // for a selection the cursor has to have a mark.
2588 : // for safety reasons assure that point and mark are in text nodes
2589 205 : if ( pCrsr->HasMark() &&
2590 114 : pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
2591 23 : pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
2592 : {
2593 23 : SwPosition* pStartPos = pCrsr->Start();
2594 23 : SwPosition* pEndPos = pCrsr->End();
2595 : // loop on all text nodes inside the selection
2596 23 : SwNodeIndex aIdx( pStartPos->nNode );
2597 46 : for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
2598 : {
2599 23 : SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
2600 23 : if ( pTxtNode )
2601 : {
2602 : // loop on all text frames registered at the text node.
2603 23 : SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode );
2604 46 : for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
2605 : {
2606 23 : uno::WeakReference < XAccessible > xWeakAcc;
2607 : SwAccessibleContextMap_Impl::iterator aMapIter =
2608 23 : mpFrmMap->find( pTxtFrm );
2609 23 : if( aMapIter != mpFrmMap->end() )
2610 : {
2611 0 : xWeakAcc = (*aMapIter).second;
2612 : SwAccessibleParaSelection aDataEntry(
2613 0 : pTxtNode == &(pStartPos->nNode.GetNode())
2614 0 : ? pStartPos->nContent.GetIndex()
2615 : : 0,
2616 0 : pTxtNode == &(pEndPos->nNode.GetNode())
2617 0 : ? pEndPos->nContent.GetIndex()
2618 0 : : STRING_LEN );
2619 : SwAccessibleSelectedParas_Impl::value_type
2620 0 : aEntry( xWeakAcc, aDataEntry );
2621 0 : if ( !pRetSelectedParas )
2622 : {
2623 : pRetSelectedParas =
2624 0 : new SwAccessibleSelectedParas_Impl;
2625 : }
2626 0 : pRetSelectedParas->insert( aEntry );
2627 : }
2628 46 : }
2629 : }
2630 23 : }
2631 : }
2632 :
2633 : // prepare next turn: get next cursor in ring
2634 91 : pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
2635 : } while ( pCrsr != pRingStart );
2636 :
2637 76 : return pRetSelectedParas;
2638 : }
2639 :
2640 76 : void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
2641 : {
2642 76 : osl::MutexGuard aGuard( maMutex );
2643 :
2644 : // keep previously known selected paragraphs
2645 76 : SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
2646 :
2647 : // determine currently selected paragraphs
2648 76 : mpSelectedParas = _BuildSelectedParas();
2649 :
2650 : // compare currently selected paragraphs with the previously selected
2651 : // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
2652 : // first, search for new and changed selections.
2653 : // on the run remove selections from previously known ones, if they are
2654 : // also in the current ones.
2655 76 : if ( mpSelectedParas )
2656 : {
2657 0 : SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
2658 0 : for ( ; aIter != mpSelectedParas->end(); ++aIter )
2659 : {
2660 0 : bool bSubmitEvent( false );
2661 0 : if ( !pPrevSelectedParas )
2662 : {
2663 : // new selection
2664 0 : bSubmitEvent = true;
2665 : }
2666 : else
2667 : {
2668 : SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
2669 0 : pPrevSelectedParas->find( (*aIter).first );
2670 0 : if ( aPrevSelected != pPrevSelectedParas->end() )
2671 : {
2672 : // check, if selection has changed
2673 0 : if ( (*aIter).second.nStartOfSelection !=
2674 0 : (*aPrevSelected).second.nStartOfSelection ||
2675 0 : (*aIter).second.nEndOfSelection !=
2676 0 : (*aPrevSelected).second.nEndOfSelection )
2677 : {
2678 : // changed selection
2679 0 : bSubmitEvent = true;
2680 : }
2681 0 : pPrevSelectedParas->erase( aPrevSelected );
2682 : }
2683 : else
2684 : {
2685 : // new selection
2686 0 : bSubmitEvent = true;
2687 : }
2688 : }
2689 :
2690 0 : if ( bSubmitEvent )
2691 : {
2692 0 : uno::Reference < XAccessible > xAcc( (*aIter).first );
2693 0 : if ( xAcc.is() )
2694 : {
2695 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
2696 0 : static_cast<SwAccessibleContext*>( xAcc.get() ) );
2697 0 : if ( xAccImpl.is() && xAccImpl->GetFrm() )
2698 : {
2699 : const SwTxtFrm* pTxtFrm(
2700 0 : dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2701 : OSL_ENSURE( pTxtFrm,
2702 : "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2703 0 : if ( pTxtFrm )
2704 : {
2705 0 : InvalidateParaTextSelection( *pTxtFrm );
2706 : }
2707 0 : }
2708 0 : }
2709 : }
2710 : }
2711 : }
2712 :
2713 : // second, handle previous selections - after the first step the data
2714 : // structure of the previously known only contains the 'old' selections
2715 76 : if ( pPrevSelectedParas )
2716 : {
2717 0 : SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
2718 0 : for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
2719 : {
2720 0 : uno::Reference < XAccessible > xAcc( (*aIter).first );
2721 0 : if ( xAcc.is() )
2722 : {
2723 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
2724 0 : static_cast<SwAccessibleContext*>( xAcc.get() ) );
2725 0 : if ( xAccImpl.is() && xAccImpl->GetFrm() )
2726 : {
2727 : const SwTxtFrm* pTxtFrm(
2728 0 : dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2729 : OSL_ENSURE( pTxtFrm,
2730 : "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2731 0 : if ( pTxtFrm )
2732 : {
2733 0 : InvalidateParaTextSelection( *pTxtFrm );
2734 : }
2735 0 : }
2736 : }
2737 0 : }
2738 :
2739 0 : delete pPrevSelectedParas;
2740 76 : }
2741 76 : }
2742 :
2743 135 : const SwRect& SwAccessibleMap::GetVisArea() const
2744 : {
2745 : OSL_ENSURE( !GetShell()->IsPreView() || (mpPreview != NULL),
2746 : "preview without preview data?" );
2747 :
2748 135 : return GetShell()->IsPreView()
2749 0 : ? mpPreview->GetVisArea()
2750 135 : : GetShell()->VisArea();
2751 99 : }
2752 :
2753 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|