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