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 <vector>
30 : #include <accmap.hxx>
31 : #include <acccontext.hxx>
32 : #include <accdoc.hxx>
33 : #include <accpreview.hxx>
34 : #include <accpage.hxx>
35 : #include <accpara.hxx>
36 : #include <accheaderfooter.hxx>
37 : #include <accfootnote.hxx>
38 : #include <acctextframe.hxx>
39 : #include <accgraphic.hxx>
40 : #include <accembedded.hxx>
41 : #include <acccell.hxx>
42 : #include <acctable.hxx>
43 : #include <fesh.hxx>
44 : #include <rootfrm.hxx>
45 : #include <txtfrm.hxx>
46 : #include <hffrm.hxx>
47 : #include <ftnfrm.hxx>
48 : #include <cellfrm.hxx>
49 : #include <tabfrm.hxx>
50 : #include <pagefrm.hxx>
51 : #include <flyfrm.hxx>
52 : #include <ndtyp.hxx>
53 : #include <IDocumentDrawModelAccess.hxx>
54 : #include <svx/ShapeTypeHandler.hxx>
55 : #include <vcl/svapp.hxx>
56 : #include <svx/SvxShapeTypes.hxx>
57 : #include <svx/svdpage.hxx>
58 : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
59 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
60 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
61 : #include <com/sun/star/accessibility/AccessibleRole.hpp>
62 : #include <cppuhelper/implbase.hxx>
63 : #include <pagepreviewlayout.hxx>
64 : #include <dcontact.hxx>
65 : #include <svx/unoapi.hxx>
66 : #include <svx/svdmark.hxx>
67 : #include <doc.hxx>
68 : #include <drawdoc.hxx>
69 : #include <pam.hxx>
70 : #include <ndtxt.hxx>
71 : #include <dflyobj.hxx>
72 : #include <prevwpage.hxx>
73 : #include <calbck.hxx>
74 : #include <boost/bind.hpp>
75 :
76 : using namespace ::com::sun::star;
77 : using namespace ::com::sun::star::accessibility;
78 : using namespace ::sw::access;
79 :
80 : struct SwFrmFunc
81 : {
82 2630 : bool operator()( const SwFrm * p1, const SwFrm * p2) const
83 : {
84 2630 : return p1 < p2;
85 : }
86 : };
87 :
88 107 : class SwAccessibleContextMap_Impl
89 : {
90 : public:
91 : typedef const SwFrm * key_type;
92 : typedef uno::WeakReference < XAccessible > mapped_type;
93 : typedef std::pair<const key_type,mapped_type> value_type;
94 : typedef SwFrmFunc key_compare;
95 : typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
96 : typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
97 : private:
98 : std::map <key_type,mapped_type,key_compare> maMap;
99 : public:
100 :
101 : #if OSL_DEBUG_LEVEL > 0
102 : bool mbLocked;
103 : #endif
104 :
105 107 : SwAccessibleContextMap_Impl()
106 : #if OSL_DEBUG_LEVEL > 0
107 : : mbLocked( false )
108 : #endif
109 107 : {}
110 :
111 83 : iterator begin() { return maMap.begin(); }
112 1244 : iterator end() { return maMap.end(); }
113 263 : bool empty() const { return maMap.empty(); }
114 0 : void clear() { maMap.clear(); }
115 809 : iterator find(const key_type& key) { return maMap.find(key); }
116 97 : std::pair<iterator,bool> insert(const value_type& value ) { return maMap.insert(value); }
117 97 : iterator erase(const_iterator pos) { return maMap.erase(pos); }
118 : };
119 :
120 : class SwDrawModellListener_Impl : public SfxListener,
121 : public ::cppu::WeakImplHelper< document::XEventBroadcaster >
122 : {
123 : mutable ::osl::Mutex maListenerMutex;
124 : ::cppu::OInterfaceContainerHelper maEventListeners;
125 : SdrModel *mpDrawModel;
126 : protected:
127 : virtual ~SwDrawModellListener_Impl();
128 :
129 : public:
130 : explicit SwDrawModellListener_Impl( SdrModel *pDrawModel );
131 :
132 : virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
133 : virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
134 :
135 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
136 : void Dispose();
137 : };
138 :
139 0 : SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
140 : maEventListeners( maListenerMutex ),
141 0 : mpDrawModel( pDrawModel )
142 : {
143 0 : StartListening( *mpDrawModel );
144 0 : }
145 :
146 0 : SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
147 : {
148 0 : EndListening( *mpDrawModel );
149 0 : }
150 :
151 0 : void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException, std::exception)
152 : {
153 0 : maEventListeners.addInterface( xListener );
154 0 : }
155 :
156 0 : void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException, std::exception)
157 : {
158 0 : maEventListeners.removeInterface( xListener );
159 0 : }
160 :
161 0 : void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
162 : const SfxHint& rHint )
163 : {
164 : // do not broadcast notifications for writer fly frames, because there
165 : // are no shapes that need to know about them.
166 0 : const SdrHint *pSdrHint = dynamic_cast<const SdrHint*>( &rHint );
167 0 : if ( !pSdrHint ||
168 0 : ( pSdrHint->GetObject() &&
169 0 : ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
170 0 : pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
171 0 : IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
172 : {
173 0 : return;
174 : }
175 :
176 : OSL_ENSURE( mpDrawModel, "draw model listener is disposed" );
177 0 : if( !mpDrawModel )
178 0 : return;
179 :
180 0 : document::EventObject aEvent;
181 0 : if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
182 0 : return;
183 :
184 0 : ::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
185 0 : while( aIter.hasMoreElements() )
186 : {
187 : uno::Reference < document::XEventListener > xListener( aIter.next(),
188 0 : uno::UNO_QUERY );
189 : try
190 : {
191 0 : xListener->notifyEvent( aEvent );
192 : }
193 0 : catch( uno::RuntimeException const & r )
194 : {
195 : SAL_WARN( "sw.core", "Runtime exception caught while notifying shape.: " << r.Message );
196 : }
197 0 : }
198 : }
199 :
200 0 : void SwDrawModellListener_Impl::Dispose()
201 : {
202 0 : mpDrawModel = nullptr;
203 0 : }
204 :
205 : struct SwShapeFunc
206 : {
207 0 : bool operator()( const SdrObject * p1, const SdrObject * p2) const
208 : {
209 0 : return p1 < p2;
210 : }
211 : };
212 : typedef ::std::pair < const SdrObject *, ::rtl::Reference < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
213 :
214 : class SwAccessibleShapeMap_Impl
215 : {
216 : public:
217 :
218 : typedef const SdrObject * key_type;
219 : typedef uno::WeakReference<XAccessible> mapped_type;
220 : typedef std::pair<const key_type,mapped_type> value_type;
221 : typedef SwShapeFunc key_compare;
222 : typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
223 : typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
224 :
225 : private:
226 :
227 : ::accessibility::AccessibleShapeTreeInfo maInfo;
228 : std::map<key_type,mapped_type,SwShapeFunc> maMap;
229 :
230 : public:
231 :
232 : #if OSL_DEBUG_LEVEL > 0
233 : bool mbLocked;
234 : #endif
235 0 : explicit SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
236 0 : : maMap()
237 : #if OSL_DEBUG_LEVEL > 0
238 : , mbLocked( false )
239 : #endif
240 : {
241 0 : maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
242 0 : maInfo.SetWindow( pMap->GetShell()->GetWin() );
243 0 : maInfo.SetViewForwarder( pMap );
244 : uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
245 : new SwDrawModellListener_Impl(
246 0 : pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
247 0 : maInfo.SetModelBroadcaster( xModelBroadcaster );
248 0 : }
249 :
250 : ~SwAccessibleShapeMap_Impl();
251 :
252 0 : const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
253 :
254 : SwAccessibleObjShape_Impl *Copy( size_t& rSize,
255 : const SwFEShell *pFESh = nullptr,
256 : SwAccessibleObjShape_Impl **pSelShape = nullptr ) const;
257 :
258 : iterator begin() { return maMap.begin(); }
259 0 : iterator end() { return maMap.end(); }
260 0 : const_iterator cbegin() const { return maMap.cbegin(); }
261 0 : const_iterator cend() const { return maMap.cend(); }
262 0 : bool empty() const { return maMap.empty(); }
263 0 : iterator find(const key_type& key) { return maMap.find(key); }
264 0 : std::pair<iterator,bool> insert(const value_type& value ) { return maMap.insert(value); }
265 0 : iterator erase(const_iterator pos) { return maMap.erase(pos); }
266 : };
267 :
268 0 : SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
269 : {
270 0 : uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetModelBroadcaster() );
271 0 : if( xBrd.is() )
272 0 : static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
273 0 : }
274 :
275 : SwAccessibleObjShape_Impl
276 0 : *SwAccessibleShapeMap_Impl::Copy(
277 : size_t& rSize, const SwFEShell *pFESh,
278 : SwAccessibleObjShape_Impl **pSelStart ) const
279 : {
280 0 : SwAccessibleObjShape_Impl *pShapes = nullptr;
281 0 : SwAccessibleObjShape_Impl *pSelShape = nullptr;
282 :
283 0 : size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
284 0 : rSize = maMap.size();
285 :
286 0 : if( rSize > 0 )
287 : {
288 0 : pShapes = new SwAccessibleObjShape_Impl[rSize];
289 :
290 0 : const_iterator aIter = maMap.cbegin();
291 0 : const_iterator aEndIter = maMap.cend();
292 :
293 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
294 0 : pSelShape = &(pShapes[rSize]);
295 0 : while( aIter != aEndIter )
296 : {
297 0 : const SdrObject *pObj = (*aIter).first;
298 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
299 0 : if( nSelShapes && pFESh && pFESh->IsObjSelected( *pObj ) )
300 : {
301 : // selected objects are inserted from the back
302 0 : --pSelShape;
303 0 : pSelShape->first = pObj;
304 0 : pSelShape->second =
305 : static_cast < ::accessibility::AccessibleShape* >(
306 0 : xAcc.get() );
307 0 : --nSelShapes;
308 : }
309 : else
310 : {
311 0 : pShape->first = pObj;
312 0 : pShape->second =
313 : static_cast < ::accessibility::AccessibleShape* >(
314 0 : xAcc.get() );
315 0 : ++pShape;
316 : }
317 0 : ++aIter;
318 0 : }
319 : OSL_ENSURE( pSelShape == pShape, "copying shapes went wrong!" );
320 : }
321 :
322 0 : if( pSelStart )
323 0 : *pSelStart = pSelShape;
324 :
325 0 : return pShapes;
326 : }
327 :
328 180 : struct SwAccessibleEvent_Impl
329 : {
330 : public:
331 : enum EventType { CARET_OR_STATES,
332 : INVALID_CONTENT,
333 : POS_CHANGED,
334 : CHILD_POS_CHANGED,
335 : SHAPE_SELECTION,
336 : DISPOSE,
337 : INVALID_ATTR };
338 :
339 : private:
340 : SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
341 : // and POS_CHANGED
342 : uno::WeakReference < XAccessible > mxAcc; // The object that fires the event
343 : SwAccessibleChild maFrmOrObj; // the child for CHILD_POS_CHANGED and
344 : // the same as xAcc for any other
345 : // event type
346 : EventType meType; // The event type
347 : AccessibleStates mnStates; // check states or update caret pos
348 :
349 : public:
350 : const SwFrm* mpParentFrm; // The object that fires the event
351 36 : bool IsNoXaccParentFrm() const
352 : {
353 36 : return CHILD_POS_CHANGED == meType && mpParentFrm != nullptr;
354 : }
355 :
356 : public:
357 0 : SwAccessibleEvent_Impl( EventType eT,
358 : SwAccessibleContext *pA,
359 : const SwAccessibleChild& rFrmOrObj )
360 : : mxAcc( pA ),
361 : maFrmOrObj( rFrmOrObj ),
362 : meType( eT ),
363 : mnStates( AccessibleStates::NONE ),
364 0 : mpParentFrm( nullptr )
365 0 : {}
366 :
367 0 : SwAccessibleEvent_Impl( EventType eT,
368 : const SwAccessibleChild& rFrmOrObj )
369 : : maFrmOrObj( rFrmOrObj ),
370 : meType( eT ),
371 : mnStates( AccessibleStates::NONE ),
372 0 : mpParentFrm( nullptr )
373 : {
374 : assert(SwAccessibleEvent_Impl::DISPOSE == meType &&
375 : "wrong event constructor, DISPOSE only");
376 0 : }
377 :
378 0 : explicit SwAccessibleEvent_Impl( EventType eT )
379 : : meType( eT ),
380 : mnStates( AccessibleStates::NONE ),
381 0 : mpParentFrm( nullptr )
382 : {
383 : assert(SwAccessibleEvent_Impl::SHAPE_SELECTION == meType &&
384 : "wrong event constructor, SHAPE_SELECTION only" );
385 0 : }
386 :
387 36 : SwAccessibleEvent_Impl( EventType eT,
388 : SwAccessibleContext *pA,
389 : const SwAccessibleChild& rFrmOrObj,
390 : const SwRect& rR )
391 : : maOldBox( rR ),
392 : mxAcc( pA ),
393 : maFrmOrObj( rFrmOrObj ),
394 : meType( eT ),
395 : mnStates( AccessibleStates::NONE ),
396 36 : mpParentFrm( nullptr )
397 : {
398 : assert((SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
399 : SwAccessibleEvent_Impl::POS_CHANGED == meType) &&
400 : "wrong event constructor, (CHILD_)POS_CHANGED only" );
401 36 : }
402 :
403 0 : SwAccessibleEvent_Impl( EventType eT,
404 : SwAccessibleContext *pA,
405 : const SwAccessibleChild& rFrmOrObj,
406 : const AccessibleStates _nStates )
407 : : mxAcc( pA ),
408 : maFrmOrObj( rFrmOrObj ),
409 : meType( eT ),
410 : mnStates( _nStates ),
411 0 : mpParentFrm( nullptr )
412 : {
413 : assert( SwAccessibleEvent_Impl::CARET_OR_STATES == meType &&
414 : "wrong event constructor, CARET_OR_STATES only" );
415 0 : }
416 :
417 0 : SwAccessibleEvent_Impl( EventType eT, const SwFrm *pParentFrm,
418 : const SwAccessibleChild& rFrmOrObj, const SwRect& rR ) :
419 : maOldBox( rR ),
420 : maFrmOrObj( rFrmOrObj ),
421 : meType( eT ),
422 : mnStates( AccessibleStates::NONE ),
423 0 : mpParentFrm( pParentFrm )
424 : {
425 : assert( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType &&
426 : "wrong event constructor, CHILD_POS_CHANGED only" );
427 0 : }
428 :
429 : // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
430 0 : inline void SetType( EventType eT )
431 : {
432 0 : meType = eT;
433 0 : }
434 180 : inline EventType GetType() const
435 : {
436 180 : return meType;
437 : }
438 :
439 36 : inline ::rtl::Reference < SwAccessibleContext > GetContext() const
440 : {
441 36 : uno::Reference < XAccessible > xTmp( mxAcc );
442 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
443 36 : static_cast<SwAccessibleContext*>( xTmp.get() ) );
444 :
445 36 : return xAccImpl;
446 : }
447 :
448 36 : inline const SwRect& GetOldBox() const
449 : {
450 36 : return maOldBox;
451 : }
452 : // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
453 0 : inline void SetOldBox( const SwRect& rOldBox )
454 : {
455 0 : maOldBox = rOldBox;
456 0 : }
457 :
458 80 : inline const SwAccessibleChild& GetFrmOrObj() const
459 : {
460 80 : return maFrmOrObj;
461 : }
462 :
463 : // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
464 0 : inline void SetStates( AccessibleStates _nStates )
465 : {
466 0 : mnStates |= _nStates;
467 0 : }
468 :
469 36 : inline bool IsUpdateCursorPos() const
470 : {
471 36 : return bool(mnStates & AccessibleStates::CARET);
472 : }
473 36 : inline bool IsInvalidateStates() const
474 : {
475 36 : return bool(mnStates & (AccessibleStates::EDITABLE | AccessibleStates::OPAQUE));
476 : }
477 36 : inline bool IsInvalidateRelation() const
478 : {
479 36 : return bool(mnStates & (AccessibleStates::RELATION_FROM | AccessibleStates::RELATION_TO));
480 : }
481 36 : inline bool IsInvalidateTextSelection() const
482 : {
483 36 : return bool( mnStates & AccessibleStates::TEXT_SELECTION_CHANGED );
484 : }
485 :
486 36 : inline bool IsInvalidateTextAttrs() const
487 : {
488 36 : return bool( mnStates & AccessibleStates::TEXT_ATTRIBUTE_CHANGED );
489 : }
490 :
491 0 : inline AccessibleStates GetStates() const
492 : {
493 0 : return mnStates;
494 : }
495 :
496 0 : inline AccessibleStates GetAllStates() const
497 : {
498 0 : return mnStates;
499 : }
500 : };
501 :
502 : typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
503 :
504 28 : class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
505 : {
506 : bool mbFiring;
507 :
508 : public:
509 28 : SwAccessibleEventList_Impl()
510 28 : : mbFiring( false )
511 28 : {}
512 :
513 14 : inline void SetFiring()
514 : {
515 14 : mbFiring = true;
516 14 : }
517 36 : inline bool IsFiring() const
518 : {
519 36 : return mbFiring;
520 : }
521 :
522 : void MoveInvalidXAccToEnd();
523 : };
524 :
525 14 : void SwAccessibleEventList_Impl::MoveInvalidXAccToEnd()
526 : {
527 14 : size_t nSize = size();
528 14 : if (nSize < 2 )
529 : {
530 14 : return;
531 : }
532 14 : SwAccessibleEventList_Impl lstEvent;
533 14 : iterator li = begin();
534 64 : for ( ;li != end();)
535 : {
536 36 : SwAccessibleEvent_Impl e = *li;
537 36 : if (e.IsNoXaccParentFrm())
538 : {
539 0 : iterator liNext = li;
540 0 : ++liNext;
541 0 : erase(li);
542 0 : li = liNext;
543 0 : lstEvent.insert(lstEvent.end(),e);
544 : }
545 : else
546 36 : ++li;
547 36 : }
548 : OSL_ENSURE(size() + lstEvent.size() == nSize ,"");
549 14 : insert(end(),lstEvent.begin(),lstEvent.end());
550 14 : OSL_ENSURE(size() == nSize ,"");
551 : }
552 :
553 : // The shape list is filled if an accessible shape is destroyed. It
554 : // simply keeps a reference to the accessible shape's XShape. These
555 : // references are destroyed within the EndAction when firing events.
556 : // There are two reason for this. First of all, a new accessible shape
557 : // for the XShape might be created soon. It's then cheaper if the XShape
558 : // still exists. The other reason are situations where an accessible shape
559 : // is destroyed within an SwFrameFormat::Modify. In this case, destroying
560 : // the XShape at the same time (indirectly by destroying the accessible
561 : // shape) leads to an assert, because a client of the Modify is destroyed
562 : // within a Modify call.
563 :
564 : typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
565 :
566 0 : class SwShapeList_Impl: public _SwShapeList_Impl
567 : {
568 : public:
569 0 : SwShapeList_Impl() {}
570 : };
571 :
572 : struct SwAccessibleChildFunc
573 : {
574 104 : bool operator()( const SwAccessibleChild& r1,
575 : const SwAccessibleChild& r2 ) const
576 : {
577 104 : const void *p1 = r1.GetSwFrm()
578 : ? static_cast < const void * >( r1.GetSwFrm())
579 0 : : ( r1.GetDrawObject()
580 : ? static_cast < const void * >( r1.GetDrawObject() )
581 104 : : static_cast < const void * >( r1.GetWindow() ) );
582 104 : const void *p2 = r2.GetSwFrm()
583 : ? static_cast < const void * >( r2.GetSwFrm())
584 0 : : ( r2.GetDrawObject()
585 : ? static_cast < const void * >( r2.GetDrawObject() )
586 104 : : static_cast < const void * >( r2.GetWindow() ) );
587 104 : return p1 < p2;
588 : }
589 : };
590 :
591 28 : class SwAccessibleEventMap_Impl
592 : {
593 : public:
594 : typedef SwAccessibleChild key_type;
595 : typedef SwAccessibleEventList_Impl::iterator mapped_type;
596 : typedef std::pair<const key_type,mapped_type> value_type;
597 : typedef SwAccessibleChildFunc key_compare;
598 : typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
599 : typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
600 : private:
601 : std::map <key_type,mapped_type,key_compare> maMap;
602 : public:
603 : iterator begin() { return maMap.begin(); }
604 36 : iterator end() { return maMap.end(); }
605 36 : iterator find(const key_type& key) { return maMap.find(key); }
606 36 : std::pair<iterator,bool> insert(const value_type& value ) { return maMap.insert(value); }
607 0 : iterator erase(const_iterator pos) { return maMap.erase(pos); }
608 : };
609 :
610 : struct SwAccessibleParaSelection
611 : {
612 : sal_Int32 nStartOfSelection;
613 : sal_Int32 nEndOfSelection;
614 :
615 0 : SwAccessibleParaSelection( const sal_Int32 _nStartOfSelection,
616 : const sal_Int32 _nEndOfSelection )
617 : : nStartOfSelection( _nStartOfSelection ),
618 0 : nEndOfSelection( _nEndOfSelection )
619 0 : {}
620 : };
621 :
622 : struct SwXAccWeakRefComp
623 : {
624 0 : bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
625 : const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
626 : {
627 0 : return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
628 : }
629 : };
630 :
631 0 : class SwAccessibleSelectedParas_Impl
632 : {
633 : public:
634 : typedef uno::WeakReference < XAccessible > key_type;
635 : typedef SwAccessibleParaSelection mapped_type;
636 : typedef std::pair<const key_type,mapped_type> value_type;
637 : typedef SwXAccWeakRefComp key_compare;
638 : typedef std::map<key_type,mapped_type,key_compare>::iterator iterator;
639 : typedef std::map<key_type,mapped_type,key_compare>::const_iterator const_iterator;
640 : private:
641 : std::map<key_type,mapped_type,key_compare> maMap;
642 : public:
643 0 : iterator begin() { return maMap.begin(); }
644 0 : iterator end() { return maMap.end(); }
645 0 : iterator find(const key_type& key) { return maMap.find(key); }
646 0 : std::pair<iterator,bool> insert(const value_type& value ) { return maMap.insert(value); }
647 0 : iterator erase(const_iterator pos) { return maMap.erase(pos); }
648 : };
649 :
650 : // helper class that stores preview data
651 : class SwAccPreviewData
652 : {
653 : typedef std::vector<Rectangle> Rectangles;
654 : Rectangles maPreviewRects;
655 : Rectangles maLogicRects;
656 :
657 : SwRect maVisArea;
658 : Fraction maScale;
659 :
660 : const SwPageFrm *mpSelPage;
661 :
662 : /** adjust logic page rectangle to its visible part
663 :
664 : @param _iorLogicPgSwRect
665 : input/output parameter - reference to the logic page rectangle, which
666 : has to be adjusted.
667 :
668 : @param _rPreviewPgSwRect
669 : input parameter - constant reference to the corresponding preview page
670 : rectangle; needed to determine the visible part of the logic page rectangle.
671 :
672 : @param _rPreviewWinSize
673 : input parameter - constant reference to the preview window size in TWIP;
674 : needed to determine the visible part of the logic page rectangle
675 : */
676 : static void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect,
677 : const SwRect& _rPreviewPgSwRect,
678 : const Size& _rPreviewWinSize );
679 :
680 : public:
681 : SwAccPreviewData();
682 : ~SwAccPreviewData();
683 :
684 : void Update( const SwAccessibleMap& rAccMap,
685 : const std::vector<PreviewPage*>& _rPreviewPages,
686 : const Fraction& _rScale,
687 : const SwPageFrm* _pSelectedPageFrm,
688 : const Size& _rPreviewWinSize );
689 :
690 : void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );
691 :
692 0 : const SwRect& GetVisArea() const { return maVisArea;}
693 :
694 : /** Adjust the MapMode so that the preview page appears at the
695 : * proper position. rPoint identifies the page for which the
696 : * MapMode should be adjusted. If bFromPreview is true, rPoint is
697 : * a preview coordinate; else it's a document coordinate. */
698 : void AdjustMapMode( MapMode& rMapMode,
699 : const Point& rPoint ) const;
700 :
701 0 : inline const SwPageFrm *GetSelPage() const { return mpSelPage; }
702 :
703 : void DisposePage(const SwPageFrm *pPageFrm );
704 : };
705 :
706 0 : SwAccPreviewData::SwAccPreviewData() :
707 0 : mpSelPage( nullptr )
708 : {
709 0 : }
710 :
711 0 : SwAccPreviewData::~SwAccPreviewData()
712 : {
713 0 : }
714 :
715 0 : void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
716 : const std::vector<PreviewPage*>& _rPreviewPages,
717 : const Fraction& _rScale,
718 : const SwPageFrm* _pSelectedPageFrm,
719 : const Size& _rPreviewWinSize )
720 : {
721 : // store preview scaling, maximal preview page size and selected page
722 0 : maScale = _rScale;
723 0 : mpSelPage = _pSelectedPageFrm;
724 :
725 : // prepare loop on preview pages
726 0 : maPreviewRects.clear();
727 0 : maLogicRects.clear();
728 0 : SwAccessibleChild aPage;
729 0 : maVisArea.Clear();
730 :
731 : // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
732 : // <maVisArea>
733 0 : for ( std::vector<PreviewPage*>::const_iterator aPageIter = _rPreviewPages.begin();
734 0 : aPageIter != _rPreviewPages.end();
735 : ++aPageIter )
736 : {
737 0 : aPage = (*aPageIter)->pPage;
738 :
739 : // add preview page rectangle to <maPreviewRects>
740 0 : Rectangle aPreviewPgRect( (*aPageIter)->aPreviewWinPos, (*aPageIter)->aPageSize );
741 0 : maPreviewRects.push_back( aPreviewPgRect );
742 :
743 : // add logic page rectangle to <maLogicRects>
744 0 : SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
745 0 : Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
746 0 : maLogicRects.push_back( aLogicPgRect );
747 : // union visible area with visible part of logic page rectangle
748 0 : if ( (*aPageIter)->bVisible )
749 : {
750 0 : if ( !(*aPageIter)->pPage->IsEmptyPage() )
751 : {
752 : AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
753 : SwRect( aPreviewPgRect ),
754 0 : _rPreviewWinSize );
755 : }
756 0 : if ( maVisArea.IsEmpty() )
757 0 : maVisArea = aLogicPgSwRect;
758 : else
759 0 : maVisArea.Union( aLogicPgSwRect );
760 : }
761 0 : }
762 0 : }
763 :
764 0 : void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
765 : {
766 0 : mpSelPage = _pSelectedPageFrm;
767 : OSL_ENSURE( mpSelPage, "selected page not found" );
768 0 : }
769 :
770 : struct ContainsPredicate
771 : {
772 : const Point& mrPoint;
773 0 : explicit ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
774 0 : bool operator() ( const Rectangle& rRect ) const
775 : {
776 0 : return rRect.IsInside( mrPoint );
777 : }
778 : };
779 :
780 :
781 0 : void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
782 : const Point& rPoint ) const
783 : {
784 : // adjust scale
785 0 : rMapMode.SetScaleX( maScale );
786 0 : rMapMode.SetScaleY( maScale );
787 :
788 : // find proper rectangle
789 0 : Rectangles::const_iterator aBegin = maLogicRects.begin();
790 0 : Rectangles::const_iterator aEnd = maLogicRects.end();
791 : Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
792 0 : ContainsPredicate( rPoint ) );
793 :
794 0 : if( aFound != aEnd )
795 : {
796 : // found! set new origin
797 0 : Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
798 0 : aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
799 0 : rMapMode.SetOrigin( aPoint );
800 : }
801 : // else: don't adjust MapMode
802 0 : }
803 :
804 0 : void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
805 : {
806 0 : if( mpSelPage == pPageFrm )
807 0 : mpSelPage = nullptr;
808 0 : }
809 :
810 : // adjust logic page rectangle to its visible part
811 0 : void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
812 : SwRect& _iorLogicPgSwRect,
813 : const SwRect& _rPreviewPgSwRect,
814 : const Size& _rPreviewWinSize )
815 : {
816 : // determine preview window rectangle
817 0 : const SwRect aPreviewWinSwRect( Point( 0, 0 ), _rPreviewWinSize );
818 : // calculate visible preview page rectangle
819 0 : SwRect aVisPreviewPgSwRect( _rPreviewPgSwRect );
820 0 : aVisPreviewPgSwRect.Intersection( aPreviewWinSwRect );
821 : // adjust logic page rectangle
822 : SwTwips nTmpDiff;
823 : // left
824 0 : nTmpDiff = aVisPreviewPgSwRect.Left() - _rPreviewPgSwRect.Left();
825 0 : if ( nTmpDiff > 0 )
826 0 : _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
827 : // top
828 0 : nTmpDiff = aVisPreviewPgSwRect.Top() - _rPreviewPgSwRect.Top();
829 0 : if ( nTmpDiff > 0 )
830 0 : _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
831 : // right
832 0 : nTmpDiff = _rPreviewPgSwRect.Right() - aVisPreviewPgSwRect.Right();
833 0 : if ( nTmpDiff > 0 )
834 0 : _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
835 : // bottom
836 0 : nTmpDiff = _rPreviewPgSwRect.Bottom() - aVisPreviewPgSwRect.Bottom();
837 0 : if ( nTmpDiff > 0 )
838 0 : _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
839 0 : }
840 :
841 31 : static bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
842 : const SwFrm *pFrm )
843 : {
844 31 : bool bRet = false;
845 :
846 31 : if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
847 : {
848 : // Is it in the same table? We check that
849 : // by comparing the last table frame in the
850 : // follow chain, because that's cheaper than
851 : // searching the first one.
852 : SwAccessibleContext *pAccImpl =
853 1 : static_cast< SwAccessibleContext *>( rAcc.get() );
854 1 : if( pAccImpl->GetFrm()->IsCellFrm() )
855 : {
856 1 : const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
857 1 : if (pTabFrm1)
858 : {
859 2 : while (pTabFrm1->GetFollow())
860 0 : pTabFrm1 = pTabFrm1->GetFollow();
861 : }
862 :
863 1 : const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
864 1 : if (pTabFrm2)
865 : {
866 2 : while (pTabFrm2->GetFollow())
867 0 : pTabFrm2 = pTabFrm2->GetFollow();
868 : }
869 :
870 1 : bRet = (pTabFrm1 == pTabFrm2);
871 : }
872 : }
873 :
874 31 : return bRet;
875 : }
876 :
877 36 : void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
878 : {
879 36 : ::rtl::Reference < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
880 36 : if (!xAccImpl.is() && rEvent.mpParentFrm != nullptr)
881 : {
882 : SwAccessibleContextMap_Impl::iterator aIter =
883 0 : mpFrmMap->find( rEvent.mpParentFrm );
884 0 : if( aIter != mpFrmMap->end() )
885 : {
886 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
887 0 : if (xAcc.is())
888 : {
889 0 : uno::Reference < XAccessibleContext > xContext(xAcc,uno::UNO_QUERY);
890 0 : if (xContext.is() && xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
891 : {
892 0 : xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
893 0 : }
894 0 : }
895 : }
896 : }
897 36 : if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
898 : {
899 0 : DoInvalidateShapeSelection();
900 : }
901 36 : else if( xAccImpl.is() && xAccImpl->GetFrm() )
902 : {
903 72 : if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
904 36 : rEvent.IsInvalidateTextAttrs() )
905 : {
906 0 : xAccImpl->InvalidateAttr();
907 : }
908 36 : switch( rEvent.GetType() )
909 : {
910 : case SwAccessibleEvent_Impl::INVALID_CONTENT:
911 0 : xAccImpl->InvalidateContent();
912 0 : break;
913 : case SwAccessibleEvent_Impl::POS_CHANGED:
914 28 : xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
915 28 : break;
916 : case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
917 16 : xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
918 16 : rEvent.GetOldBox() );
919 8 : break;
920 : case SwAccessibleEvent_Impl::DISPOSE:
921 : OSL_ENSURE( xAccImpl.is(),
922 : "dispose event has been stored" );
923 0 : break;
924 : case SwAccessibleEvent_Impl::INVALID_ATTR:
925 : // nothing to do here - handled above
926 0 : break;
927 : default:
928 0 : break;
929 : }
930 36 : if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
931 : {
932 36 : if( rEvent.IsUpdateCursorPos() )
933 0 : xAccImpl->InvalidateCursorPos();
934 36 : if( rEvent.IsInvalidateStates() )
935 0 : xAccImpl->InvalidateStates( rEvent.GetStates() );
936 36 : if( rEvent.IsInvalidateRelation() )
937 : {
938 : // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
939 : // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
940 0 : if ( rEvent.GetAllStates() & AccessibleStates::RELATION_FROM )
941 : {
942 : xAccImpl->InvalidateRelation(
943 0 : AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
944 : }
945 0 : if ( rEvent.GetAllStates() & AccessibleStates::RELATION_TO )
946 : {
947 : xAccImpl->InvalidateRelation(
948 0 : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
949 : }
950 : }
951 :
952 36 : if ( rEvent.IsInvalidateTextSelection() )
953 : {
954 0 : xAccImpl->InvalidateTextSelection();
955 : }
956 : }
957 36 : }
958 36 : }
959 :
960 36 : void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
961 : {
962 36 : osl::MutexGuard aGuard( maEventMutex );
963 :
964 36 : if( !mpEvents )
965 14 : mpEvents = new SwAccessibleEventList_Impl;
966 36 : if( !mpEventMap )
967 14 : mpEventMap = new SwAccessibleEventMap_Impl;
968 :
969 36 : if( mpEvents->IsFiring() )
970 : {
971 : // While events are fired new ones are generated. They have to be fired
972 : // now. This does not work for DISPOSE events!
973 : OSL_ENSURE( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
974 : "dispose event while firing events" );
975 0 : FireEvent( rEvent );
976 : }
977 : else
978 : {
979 :
980 : SwAccessibleEventMap_Impl::iterator aIter =
981 36 : mpEventMap->find( rEvent.GetFrmOrObj() );
982 36 : if( aIter != mpEventMap->end() )
983 : {
984 0 : SwAccessibleEvent_Impl aEvent( *(*aIter).second );
985 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
986 : "dispose events should not be stored" );
987 0 : bool bAppendEvent = true;
988 0 : switch( rEvent.GetType() )
989 : {
990 : case SwAccessibleEvent_Impl::CARET_OR_STATES:
991 : // A CARET_OR_STATES event is added to any other
992 : // event only. It is broadcasted after any other event, so the
993 : // event should be put to the back.
994 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
995 : "invalid event combination" );
996 0 : aEvent.SetStates( rEvent.GetAllStates() );
997 0 : break;
998 : case SwAccessibleEvent_Impl::INVALID_CONTENT:
999 : // An INVALID_CONTENT event overwrites a CARET_OR_STATES
1000 : // event (but keeps its flags) and it is contained in a
1001 : // POS_CHANGED event.
1002 : // Therefore, the event's type has to be adapted and the event
1003 : // has to be put at the end.
1004 : //
1005 : // fdo#56031 An INVALID_CONTENT event overwrites a INVALID_ATTR
1006 : // event and overwrites its flags
1007 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1008 : "invalid event combination" );
1009 0 : if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
1010 0 : aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
1011 0 : else if ( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR )
1012 : {
1013 0 : aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
1014 0 : aEvent.SetStates( rEvent.GetAllStates() );
1015 : }
1016 :
1017 0 : break;
1018 : case SwAccessibleEvent_Impl::POS_CHANGED:
1019 : // A pos changed event overwrites CARET_STATES (keeping its
1020 : // flags) as well as INVALID_CONTENT. The old box position
1021 : // has to be stored however if the old event is not a
1022 : // POS_CHANGED itself.
1023 : OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1024 : "invalid event combination" );
1025 0 : if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
1026 0 : aEvent.SetOldBox( rEvent.GetOldBox() );
1027 0 : aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
1028 0 : break;
1029 : case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
1030 : // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
1031 : // events. The only action that needs to be done again is
1032 : // to put the old event to the back. The new one cannot be used,
1033 : // because we are interested in the old frame bounds.
1034 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1035 : "invalid event combination" );
1036 0 : break;
1037 : case SwAccessibleEvent_Impl::SHAPE_SELECTION:
1038 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
1039 : "invalid event combination" );
1040 0 : break;
1041 : case SwAccessibleEvent_Impl::DISPOSE:
1042 : // DISPOSE events overwrite all others. They are not stored
1043 : // but executed immediately to avoid broadcasting of
1044 : // defunctional objects. So what needs to be done here is to
1045 : // remove all events for the frame in question.
1046 0 : bAppendEvent = false;
1047 0 : break;
1048 : case SwAccessibleEvent_Impl::INVALID_ATTR:
1049 : OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
1050 : "invalid event combination" );
1051 0 : break;
1052 : }
1053 0 : if( bAppendEvent )
1054 : {
1055 0 : mpEvents->erase( (*aIter).second );
1056 0 : (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
1057 : }
1058 : else
1059 : {
1060 0 : mpEvents->erase( (*aIter).second );
1061 0 : mpEventMap->erase( aIter );
1062 0 : }
1063 : }
1064 36 : else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
1065 : {
1066 36 : SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
1067 72 : mpEvents->insert( mpEvents->end(), rEvent ) );
1068 36 : mpEventMap->insert( aEntry );
1069 : }
1070 36 : }
1071 36 : }
1072 :
1073 68 : void SwAccessibleMap::InvalidateCursorPosition(
1074 : const uno::Reference< XAccessible >& rAcc )
1075 : {
1076 : SwAccessibleContext *pAccImpl =
1077 68 : static_cast< SwAccessibleContext *>( rAcc.get() );
1078 : OSL_ENSURE( pAccImpl, "no caret context" );
1079 : OSL_ENSURE( pAccImpl->GetFrm(), "caret context is disposed" );
1080 68 : if( GetShell()->ActionPend() )
1081 : {
1082 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
1083 : pAccImpl,
1084 : SwAccessibleChild(pAccImpl->GetFrm()),
1085 0 : AccessibleStates::CARET );
1086 0 : AppendEvent( aEvent );
1087 : }
1088 : else
1089 : {
1090 68 : FireEvents();
1091 : // While firing events the current frame might have
1092 : // been disposed because it moved out of the vis area.
1093 : // Setting the cursor for such frames is useless and even
1094 : // causes asserts.
1095 68 : if( pAccImpl->GetFrm() )
1096 68 : pAccImpl->InvalidateCursorPos();
1097 : }
1098 68 : }
1099 :
1100 0 : void SwAccessibleMap::InvalidateShapeSelection()
1101 : {
1102 0 : if( GetShell()->ActionPend() )
1103 : {
1104 : SwAccessibleEvent_Impl aEvent(
1105 0 : SwAccessibleEvent_Impl::SHAPE_SELECTION );
1106 0 : AppendEvent( aEvent );
1107 : }
1108 : else
1109 : {
1110 0 : FireEvents();
1111 0 : DoInvalidateShapeSelection();
1112 : }
1113 0 : }
1114 :
1115 : //This method should implement the following functions:
1116 : //1.find the shape objects and set the selected state.
1117 : //2.find the Swframe objects and set the selected state.
1118 : //3.find the paragraph objects and set the selected state.
1119 83 : void SwAccessibleMap::InvalidateShapeInParaSelection()
1120 : {
1121 83 : SwAccessibleObjShape_Impl *pShapes = nullptr;
1122 83 : SwAccessibleObjShape_Impl *pSelShape = nullptr;
1123 83 : size_t nShapes = 0;
1124 :
1125 83 : const SwViewShell *pVSh = GetShell();
1126 83 : const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1127 83 : static_cast< const SwFEShell * >( pVSh ) : nullptr;
1128 83 : SwPaM* pCrsr = pFESh ? pFESh->GetCrsr( false /* ??? */ ) : nullptr;
1129 :
1130 : //const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1131 :
1132 : {
1133 83 : osl::MutexGuard aGuard( maMutex );
1134 83 : if( mpShapeMap )
1135 0 : pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1136 : }
1137 :
1138 83 : bool bIsSelAll =IsDocumentSelAll();
1139 :
1140 83 : if( mpShapeMap )
1141 : {
1142 : //Checked for shapes.
1143 0 : SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
1144 0 : SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
1145 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
1146 :
1147 0 : if( bIsSelAll)
1148 : {
1149 0 : while( aIter != aEndIter )
1150 : {
1151 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1152 0 : if( xAcc.is() )
1153 0 : (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED );
1154 :
1155 0 : ++aIter;
1156 0 : }
1157 : }
1158 : else
1159 : {
1160 0 : while( aIter != aEndIter )
1161 : {
1162 0 : bool bMarked = false;
1163 0 : SwAccessibleChild pFrm( (*aIter).first );
1164 :
1165 0 : const SwFrameFormat *pFrameFormat = (*aIter).first ? ::FindFrameFormat( (*aIter).first ) : nullptr;
1166 0 : if( !pFrameFormat )
1167 : {
1168 0 : ++aIter;
1169 0 : continue;
1170 : }
1171 0 : const SwFormatAnchor& pAnchor = pFrameFormat->GetAnchor();
1172 0 : const SwPosition *pPos = pAnchor.GetContentAnchor();
1173 :
1174 0 : if(pAnchor.GetAnchorId() == FLY_AT_PAGE)
1175 : {
1176 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1177 0 : if(xAcc.is())
1178 0 : (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1179 :
1180 0 : ++aIter;
1181 0 : continue;
1182 : }
1183 :
1184 0 : if( !pPos )
1185 : {
1186 0 : ++aIter;
1187 0 : continue;
1188 : }
1189 0 : if( pPos->nNode.GetNode().GetTextNode() )
1190 : {
1191 0 : int pIndex = pPos->nContent.GetIndex();
1192 0 : if( pCrsr != NULL )
1193 : {
1194 0 : const SwTextNode* pNode = pPos->nNode.GetNode().GetTextNode();
1195 0 : sal_uLong nHere = pNode->GetIndex();
1196 :
1197 0 : for(SwPaM& rTmpCrsr : pCrsr->GetRingContainer())
1198 : {
1199 : // ignore, if no mark
1200 0 : if( rTmpCrsr.HasMark() )
1201 : {
1202 0 : bMarked = true;
1203 : // check whether nHere is 'inside' pCrsr
1204 0 : SwPosition* pStart = rTmpCrsr.Start();
1205 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
1206 0 : SwPosition* pEnd = rTmpCrsr.End();
1207 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
1208 0 : if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex) )
1209 : {
1210 0 : if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1211 : {
1212 0 : if( ( ((nHere == nStartIndex) && (pIndex >= pStart->nContent.GetIndex())) || (nHere > nStartIndex) )
1213 0 : &&( ((nHere == nEndIndex) && (pIndex < pEnd->nContent.GetIndex())) || (nHere < nEndIndex) ) )
1214 : {
1215 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1216 0 : if( xAcc.is() )
1217 0 : static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1218 : }
1219 : else
1220 : {
1221 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1222 0 : if( xAcc.is() )
1223 0 : static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->ResetState( AccessibleStateType::SELECTED );
1224 : }
1225 : }
1226 0 : else if( pAnchor.GetAnchorId() == FLY_AT_PARA )
1227 : {
1228 0 : if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 )
1229 0 : && (nHere < nEndIndex ) )
1230 : {
1231 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1232 0 : if( xAcc.is() )
1233 0 : static_cast < ::accessibility::AccessibleShape* >(xAcc.get())->SetState( AccessibleStateType::SELECTED );
1234 : }
1235 : else
1236 : {
1237 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1238 0 : if(xAcc.is())
1239 0 : (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1240 : }
1241 : }
1242 : }
1243 : }
1244 : }
1245 : }
1246 0 : if( !bMarked )
1247 : {
1248 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
1249 0 : size_t nNumShapes = nShapes;
1250 0 : while( nNumShapes )
1251 : {
1252 0 : if( pShape < pSelShape && (pShape->first==(*aIter).first) )
1253 : {
1254 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
1255 0 : if(xAcc.is())
1256 0 : (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED );
1257 : }
1258 0 : --nNumShapes;
1259 0 : ++pShape;
1260 : }
1261 : }
1262 : }
1263 :
1264 0 : ++aIter;
1265 0 : }//while( aIter != aEndIter )
1266 0 : }//else
1267 : }
1268 :
1269 83 : delete[] pShapes;
1270 :
1271 : //Checked for FlyFrm
1272 83 : if (mpFrmMap)
1273 : {
1274 83 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1275 421 : while( aIter != mpFrmMap->end() )
1276 : {
1277 255 : const SwFrm *pFrm = (*aIter).first;
1278 255 : if(pFrm->IsFlyFrm())
1279 : {
1280 23 : uno::Reference < XAccessible > xAcc = (*aIter).second;
1281 :
1282 23 : if(xAcc.is())
1283 : {
1284 23 : SwAccessibleFrameBase *pAccFrame = (static_cast< SwAccessibleFrameBase * >(xAcc.get()));
1285 23 : bool bFrmChanged = pAccFrame->SetSelectedState( true );
1286 23 : if (bFrmChanged)
1287 : {
1288 0 : const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( pFrm );
1289 0 : const SwFrameFormat *pFrameFormat = pFlyFrm->GetFormat();
1290 0 : if (pFrameFormat)
1291 : {
1292 0 : const SwFormatAnchor& pAnchor = pFrameFormat->GetAnchor();
1293 0 : if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1294 : {
1295 0 : uno::Reference< XAccessible > xAccParent = pAccFrame->getAccessibleParent();
1296 0 : if (xAccParent.is())
1297 : {
1298 0 : uno::Reference< XAccessibleContext > xAccContext = xAccParent->getAccessibleContext();
1299 0 : if(xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1300 : {
1301 0 : SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xAccContext.get());
1302 0 : if(pAccFrame->IsSeletedInDoc())
1303 : {
1304 0 : m_setParaAdd.insert(pAccPara);
1305 : }
1306 0 : else if(m_setParaAdd.count(pAccPara) == 0)
1307 : {
1308 0 : m_setParaRemove.insert(pAccPara);
1309 : }
1310 0 : }
1311 0 : }
1312 : }
1313 : }
1314 : }
1315 23 : }
1316 : }
1317 255 : ++aIter;
1318 : }
1319 : }
1320 :
1321 : typedef std::vector< SwAccessibleContext* > VEC_PARA;
1322 83 : VEC_PARA vecAdd;
1323 166 : VEC_PARA vecRemove;
1324 : //Checked for Paras.
1325 83 : bool bMarkChanged = false;
1326 166 : SwAccessibleContextMap_Impl mapTemp;
1327 83 : if( pCrsr != NULL )
1328 : {
1329 181 : for(SwPaM& rTmpCrsr : pCrsr->GetRingContainer())
1330 : {
1331 98 : if( rTmpCrsr.HasMark() )
1332 : {
1333 23 : SwNodeIndex nStartIndex( rTmpCrsr.Start()->nNode );
1334 46 : SwNodeIndex nEndIndex( rTmpCrsr.End()->nNode );
1335 69 : while(nStartIndex <= nEndIndex)
1336 : {
1337 23 : SwFrm *pFrm = NULL;
1338 23 : if(nStartIndex.GetNode().IsContentNode())
1339 : {
1340 23 : SwContentNode* pCNd = static_cast<SwContentNode*>(&(nStartIndex.GetNode()));
1341 23 : pFrm = SwIterator<SwFrm, SwContentNode>(*pCNd).First();
1342 : }
1343 0 : else if( nStartIndex.GetNode().IsTableNode() )
1344 : {
1345 0 : SwTableNode * pTable = static_cast<SwTableNode *>(&(nStartIndex.GetNode()));
1346 0 : SwTableFormat* pFormat = pTable->GetTable().GetFrameFormat();
1347 0 : pFrm = SwIterator<SwFrm, SwTableFormat>(*pFormat).First();
1348 : }
1349 :
1350 23 : if( pFrm && mpFrmMap)
1351 : {
1352 23 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1353 23 : if( aIter != mpFrmMap->end() )
1354 : {
1355 0 : uno::Reference < XAccessible > xAcc = (*aIter).second;
1356 0 : bool isChanged = false;
1357 0 : if( xAcc.is() )
1358 : {
1359 0 : isChanged = (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( true );
1360 : }
1361 0 : if(!isChanged)
1362 : {
1363 0 : SwAccessibleContextMap_Impl::iterator aEraseIter = mpSeletedFrmMap->find( pFrm );
1364 0 : if(aEraseIter != mpSeletedFrmMap->end())
1365 0 : mpSeletedFrmMap->erase(aEraseIter);
1366 : }
1367 : else
1368 : {
1369 0 : bMarkChanged = true;
1370 0 : vecAdd.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1371 : }
1372 :
1373 0 : mapTemp.insert( SwAccessibleContextMap_Impl::value_type( pFrm, xAcc ) );
1374 : }
1375 : }
1376 23 : ++nStartIndex;
1377 23 : }
1378 : }
1379 : }
1380 : }
1381 83 : if( !mpSeletedFrmMap )
1382 12 : mpSeletedFrmMap = new SwAccessibleContextMap_Impl;
1383 83 : if( !mpSeletedFrmMap->empty() )
1384 : {
1385 0 : SwAccessibleContextMap_Impl::iterator aIter = mpSeletedFrmMap->begin();
1386 0 : while( aIter != mpSeletedFrmMap->end() )
1387 : {
1388 0 : uno::Reference < XAccessible > xAcc = (*aIter).second;
1389 0 : if(xAcc.is())
1390 0 : (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( false );
1391 0 : ++aIter;
1392 0 : vecRemove.push_back(static_cast< SwAccessibleContext * >(xAcc.get()));
1393 0 : }
1394 0 : bMarkChanged = true;
1395 0 : mpSeletedFrmMap->clear();
1396 : }
1397 :
1398 83 : if( !mapTemp.empty() )
1399 : {
1400 0 : SwAccessibleContextMap_Impl::iterator aIter = mapTemp.begin();
1401 0 : while( aIter != mapTemp.end() )
1402 : {
1403 0 : mpSeletedFrmMap->insert( SwAccessibleContextMap_Impl::value_type( (*aIter).first, (*aIter).second ) );
1404 0 : ++aIter;
1405 : }
1406 0 : mapTemp.clear();
1407 : }
1408 83 : if( bMarkChanged && mpFrmMap)
1409 : {
1410 0 : VEC_PARA::iterator vi = vecAdd.begin();
1411 0 : for (; vi != vecAdd.end() ; ++vi)
1412 : {
1413 0 : AccessibleEventObject aEvent;
1414 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1415 0 : SwAccessibleContext* pAccPara = *vi;
1416 0 : if (pAccPara)
1417 : {
1418 0 : pAccPara->FireAccessibleEvent( aEvent );
1419 : }
1420 0 : }
1421 0 : vi = vecRemove.begin();
1422 0 : for (; vi != vecRemove.end() ; ++vi)
1423 : {
1424 0 : AccessibleEventObject aEvent;
1425 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1426 0 : SwAccessibleContext* pAccPara = *vi;
1427 0 : if (pAccPara)
1428 : {
1429 0 : pAccPara->FireAccessibleEvent( aEvent );
1430 : }
1431 0 : }
1432 83 : }
1433 83 : }
1434 :
1435 : //Marge with DoInvalidateShapeFocus
1436 3 : void SwAccessibleMap::DoInvalidateShapeSelection(bool bInvalidateFocusMode /*=false*/)
1437 : {
1438 3 : SwAccessibleObjShape_Impl *pShapes = nullptr;
1439 3 : SwAccessibleObjShape_Impl *pSelShape = nullptr;
1440 3 : size_t nShapes = 0;
1441 :
1442 3 : const SwViewShell *pVSh = GetShell();
1443 3 : const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1444 3 : static_cast< const SwFEShell * >( pVSh ) : nullptr;
1445 3 : const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1446 :
1447 : //when InvalidateFocus Call this function ,and the current selected shape count is not 1 ,
1448 : //return
1449 3 : if (bInvalidateFocusMode && nSelShapes != 1)
1450 : {
1451 6 : return;
1452 : }
1453 : {
1454 0 : osl::MutexGuard aGuard( maMutex );
1455 0 : if( mpShapeMap )
1456 0 : pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1457 : }
1458 :
1459 0 : if( pShapes )
1460 : {
1461 : typedef std::vector< ::rtl::Reference < ::accessibility::AccessibleShape > > VEC_SHAPE;
1462 0 : VEC_SHAPE vecxShapeAdd;
1463 0 : VEC_SHAPE vecxShapeRemove;
1464 0 : int nCountSelectedShape=0;
1465 :
1466 0 : vcl::Window *pWin = GetShell()->GetWin();
1467 0 : bool bFocused = pWin && pWin->HasFocus();
1468 0 : SwAccessibleObjShape_Impl *pShape = pShapes;
1469 0 : int nShapeCount = nShapes;
1470 0 : while( nShapeCount )
1471 : {
1472 0 : if (pShape->second.is() && IsInSameLevel(pShape->first, pFESh))
1473 : {
1474 0 : if( pShape < pSelShape )
1475 : {
1476 0 : if(pShape->second->ResetState( AccessibleStateType::SELECTED ))
1477 : {
1478 0 : vecxShapeRemove.push_back(pShape->second);
1479 : }
1480 0 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1481 : }
1482 : }
1483 0 : --nShapeCount;
1484 0 : ++pShape;
1485 : }
1486 :
1487 0 : VEC_SHAPE::iterator vi =vecxShapeRemove.begin();
1488 0 : for (; vi != vecxShapeRemove.end(); ++vi)
1489 : {
1490 0 : ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->get());
1491 0 : if (pAccShape)
1492 : {
1493 0 : pAccShape->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, uno::Any(), uno::Any());
1494 : }
1495 : }
1496 :
1497 0 : pShape = pShapes;
1498 :
1499 0 : while( nShapes )
1500 : {
1501 0 : if (pShape->second.is() && IsInSameLevel(pShape->first, pFESh))
1502 : {
1503 0 : if( pShape >= pSelShape )
1504 : {
1505 : //first fire focus event
1506 0 : if( bFocused && 1 == nSelShapes )
1507 0 : pShape->second->SetState( AccessibleStateType::FOCUSED );
1508 : else
1509 0 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1510 :
1511 0 : if(pShape->second->SetState( AccessibleStateType::SELECTED ))
1512 : {
1513 0 : vecxShapeAdd.push_back(pShape->second);
1514 : }
1515 0 : ++nCountSelectedShape;
1516 : }
1517 : }
1518 :
1519 0 : --nShapes;
1520 0 : ++pShape;
1521 : }
1522 :
1523 0 : const unsigned int SELECTION_WITH_NUM = 10;
1524 0 : if (vecxShapeAdd.size() > SELECTION_WITH_NUM )
1525 : {
1526 0 : uno::Reference< XAccessible > xDoc = GetDocumentView( );
1527 0 : SwAccessibleContext * pCont = static_cast<SwAccessibleContext *>(xDoc.get());
1528 0 : if (pCont)
1529 : {
1530 0 : AccessibleEventObject aEvent;
1531 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1532 0 : pCont->FireAccessibleEvent(aEvent);
1533 0 : }
1534 : }
1535 : else
1536 : {
1537 0 : short nEventID = AccessibleEventId::SELECTION_CHANGED_ADD;
1538 0 : if (nCountSelectedShape <= 1 && vecxShapeAdd.size() == 1 )
1539 : {
1540 0 : nEventID = AccessibleEventId::SELECTION_CHANGED;
1541 : }
1542 0 : vi = vecxShapeAdd.begin();
1543 0 : for (; vi != vecxShapeAdd.end(); ++vi)
1544 : {
1545 0 : ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->get());
1546 0 : if (pAccShape)
1547 : {
1548 0 : pAccShape->CommitChange(nEventID, uno::Any(), uno::Any());
1549 : }
1550 : }
1551 : }
1552 :
1553 0 : vi = vecxShapeAdd.begin();
1554 0 : for (; vi != vecxShapeAdd.end(); ++vi)
1555 : {
1556 0 : ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->get());
1557 0 : if (pAccShape)
1558 : {
1559 0 : SdrObject *pObj = GetSdrObjectFromXShape(pAccShape->GetXShape());
1560 0 : SwFrameFormat *pFrameFormat = pObj ? FindFrameFormat( pObj ) : NULL;
1561 0 : if (pFrameFormat)
1562 : {
1563 0 : const SwFormatAnchor& pAnchor = pFrameFormat->GetAnchor();
1564 0 : if( pAnchor.GetAnchorId() == FLY_AS_CHAR )
1565 : {
1566 0 : uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1567 0 : if (xPara.is())
1568 : {
1569 0 : uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1570 0 : if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1571 : {
1572 0 : SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1573 0 : if (pAccPara)
1574 : {
1575 0 : m_setParaAdd.insert(pAccPara);
1576 : }
1577 0 : }
1578 0 : }
1579 : }
1580 : }
1581 : }
1582 : }
1583 0 : vi = vecxShapeRemove.begin();
1584 0 : for (; vi != vecxShapeRemove.end(); ++vi)
1585 : {
1586 0 : ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->get());
1587 0 : if (pAccShape)
1588 : {
1589 0 : uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent();
1590 0 : uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext();
1591 0 : if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1592 : {
1593 0 : SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get());
1594 0 : if (m_setParaAdd.count(pAccPara) == 0 )
1595 : {
1596 0 : m_setParaRemove.insert(pAccPara);
1597 : }
1598 0 : }
1599 : }
1600 : }
1601 :
1602 0 : delete[] pShapes;
1603 : }
1604 : }
1605 :
1606 : //Marge with DoInvalidateShapeSelection
1607 : /*
1608 : void SwAccessibleMap::DoInvalidateShapeFocus()
1609 : {
1610 : const SwViewShell *pVSh = GetShell();
1611 : const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
1612 : static_cast< const SwFEShell * >( pVSh ) : nullptr;
1613 : const size_t nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
1614 :
1615 : if( nSelShapes != 1 )
1616 : return;
1617 :
1618 : SwAccessibleObjShape_Impl *pShapes = nullptr;
1619 : SwAccessibleObjShape_Impl *pSelShape = nullptr;
1620 : size_t nShapes = 0;
1621 :
1622 : {
1623 : osl::MutexGuard aGuard( maMutex );
1624 : if( mpShapeMap )
1625 : pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
1626 : }
1627 :
1628 : if( pShapes )
1629 : {
1630 : vcl::Window *pWin = GetShell()->GetWin();
1631 : bool bFocused = pWin && pWin->HasFocus();
1632 : SwAccessibleObjShape_Impl *pShape = pShapes;
1633 : while( nShapes )
1634 : {
1635 : if( pShape->second.is() )
1636 : {
1637 : if( bFocused && pShape >= pSelShape )
1638 : pShape->second->SetState( AccessibleStateType::FOCUSED );
1639 : else
1640 : pShape->second->ResetState( AccessibleStateType::FOCUSED );
1641 : }
1642 :
1643 : --nShapes;
1644 : ++pShape;
1645 : }
1646 :
1647 : delete[] pShapes;
1648 : }
1649 : }
1650 :
1651 : */
1652 :
1653 12 : SwAccessibleMap::SwAccessibleMap( SwViewShell *pSh ) :
1654 : mpFrmMap( nullptr ),
1655 : mpShapeMap( nullptr ),
1656 : mpShapes( nullptr ),
1657 : mpEvents( nullptr ),
1658 : mpEventMap( nullptr ),
1659 : mpSelectedParas( nullptr ),
1660 : mpVSh( pSh ),
1661 : mpPreview( nullptr ),
1662 : mnPara( 1 ),
1663 : mbShapeSelected( false ),
1664 12 : mpSeletedFrmMap(NULL)
1665 : {
1666 12 : pSh->GetLayout()->AddAccessibleShell();
1667 12 : }
1668 :
1669 36 : SwAccessibleMap::~SwAccessibleMap()
1670 : {
1671 12 : uno::Reference < XAccessible > xAcc;
1672 : {
1673 12 : osl::MutexGuard aGuard( maMutex );
1674 12 : if( mpFrmMap )
1675 : {
1676 12 : const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1677 12 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1678 12 : if( aIter != mpFrmMap->end() )
1679 12 : xAcc = (*aIter).second;
1680 12 : if( !xAcc.is() )
1681 0 : xAcc = new SwAccessibleDocument( this );
1682 12 : }
1683 : }
1684 :
1685 12 : if(xAcc.is())
1686 : {
1687 12 : SwAccessibleDocument *pAcc = static_cast< SwAccessibleDocument * >( xAcc.get() );
1688 12 : pAcc->Dispose( true );
1689 : }
1690 12 : if( mpFrmMap )
1691 : {
1692 0 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1693 0 : while( aIter != mpFrmMap->end() )
1694 : {
1695 0 : uno::Reference < XAccessible > xTmp = (*aIter).second;
1696 0 : if( xTmp.is() )
1697 : {
1698 0 : SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() );
1699 0 : pTmp->SetMap(NULL);
1700 : }
1701 0 : ++aIter;
1702 0 : }
1703 : }
1704 : {
1705 12 : osl::MutexGuard aGuard( maMutex );
1706 : #if OSL_DEBUG_LEVEL > 0
1707 : OSL_ENSURE( !mpFrmMap || mpFrmMap->empty(),
1708 : "Frame map should be empty after disposing the root frame" );
1709 : if( mpFrmMap )
1710 : {
1711 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1712 : while( aIter != mpFrmMap->end() )
1713 : {
1714 : uno::Reference < XAccessible > xTmp = (*aIter).second;
1715 : if( xTmp.is() )
1716 : {
1717 : SwAccessibleContext *pTmp =
1718 : static_cast< SwAccessibleContext * >( xTmp.get() );
1719 : (void) pTmp;
1720 : }
1721 : ++aIter;
1722 : }
1723 : }
1724 : OSL_ENSURE( !mpShapeMap || mpShapeMap->empty(),
1725 : "Object map should be empty after disposing the root frame" );
1726 : if( mpShapeMap )
1727 : {
1728 : SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
1729 : while( aIter != mpShapeMap->end() )
1730 : {
1731 : uno::Reference < XAccessible > xTmp = (*aIter).second;
1732 : if( xTmp.is() )
1733 : {
1734 : ::accessibility::AccessibleShape *pTmp =
1735 : static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
1736 : (void) pTmp;
1737 : }
1738 : ++aIter;
1739 : }
1740 : }
1741 : #endif
1742 12 : delete mpFrmMap;
1743 12 : mpFrmMap = nullptr;
1744 12 : delete mpShapeMap;
1745 12 : mpShapeMap = nullptr;
1746 12 : delete mpShapes;
1747 12 : mpShapes = nullptr;
1748 12 : delete mpSelectedParas;
1749 12 : mpSelectedParas = nullptr;
1750 : }
1751 :
1752 12 : delete mpPreview;
1753 12 : mpPreview = NULL;
1754 :
1755 : {
1756 12 : osl::MutexGuard aGuard( maEventMutex );
1757 : #if OSL_DEBUG_LEVEL > 0
1758 : OSL_ENSURE( !(mpEvents || mpEventMap), "pending events" );
1759 : if( mpEvents )
1760 : {
1761 : SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
1762 : while( aIter != mpEvents->end() )
1763 : {
1764 : ++aIter;
1765 : }
1766 : }
1767 : if( mpEventMap )
1768 : {
1769 : SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
1770 : while( aIter != mpEventMap->end() )
1771 : {
1772 : ++aIter;
1773 : }
1774 : }
1775 : #endif
1776 12 : delete mpEventMap;
1777 12 : mpEventMap = nullptr;
1778 12 : delete mpEvents;
1779 12 : mpEvents = nullptr;
1780 : }
1781 12 : mpVSh->GetLayout()->RemoveAccessibleShell();
1782 12 : delete mpSeletedFrmMap;
1783 24 : }
1784 :
1785 37 : uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
1786 : bool bPagePreview )
1787 : {
1788 37 : uno::Reference < XAccessible > xAcc;
1789 37 : bool bSetVisArea = false;
1790 :
1791 : {
1792 37 : osl::MutexGuard aGuard( maMutex );
1793 :
1794 37 : if( !mpFrmMap )
1795 : {
1796 12 : mpFrmMap = new SwAccessibleContextMap_Impl;
1797 : #if OSL_DEBUG_LEVEL > 0
1798 : mpFrmMap->mbLocked = false;
1799 : #endif
1800 : }
1801 :
1802 : #if OSL_DEBUG_LEVEL > 0
1803 : OSL_ENSURE( !mpFrmMap->mbLocked, "Map is locked" );
1804 : mpFrmMap->mbLocked = true;
1805 : #endif
1806 :
1807 37 : const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1808 37 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1809 37 : if( aIter != mpFrmMap->end() )
1810 25 : xAcc = (*aIter).second;
1811 37 : if( xAcc.is() )
1812 : {
1813 25 : bSetVisArea = true; // Set VisArea when map mutex is not locked
1814 : }
1815 : else
1816 : {
1817 12 : if( bPagePreview )
1818 0 : xAcc = new SwAccessiblePreview( this );
1819 : else
1820 12 : xAcc = new SwAccessibleDocument( this );
1821 :
1822 12 : if( aIter != mpFrmMap->end() )
1823 : {
1824 0 : (*aIter).second = xAcc;
1825 : }
1826 : else
1827 : {
1828 12 : SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
1829 12 : mpFrmMap->insert( aEntry );
1830 : }
1831 37 : }
1832 :
1833 : #if OSL_DEBUG_LEVEL > 0
1834 : mpFrmMap->mbLocked = false;
1835 : #endif
1836 : }
1837 :
1838 37 : if( bSetVisArea )
1839 : {
1840 : SwAccessibleDocumentBase *pAcc =
1841 25 : static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1842 25 : pAcc->SetVisArea();
1843 : }
1844 :
1845 37 : return xAcc;
1846 : }
1847 :
1848 37 : uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1849 : {
1850 37 : return _GetDocumentView( false );
1851 : }
1852 :
1853 0 : uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1854 : const std::vector<PreviewPage*>& _rPreviewPages,
1855 : const Fraction& _rScale,
1856 : const SwPageFrm* _pSelectedPageFrm,
1857 : const Size& _rPreviewWinSize )
1858 : {
1859 : // create & update preview data object
1860 0 : if( mpPreview == NULL )
1861 0 : mpPreview = new SwAccPreviewData();
1862 0 : mpPreview->Update( *this, _rPreviewPages, _rScale, _pSelectedPageFrm, _rPreviewWinSize );
1863 :
1864 0 : uno::Reference<XAccessible> xAcc = _GetDocumentView( true );
1865 0 : return xAcc;
1866 : }
1867 :
1868 430 : uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
1869 : bool bCreate )
1870 : {
1871 430 : uno::Reference < XAccessible > xAcc;
1872 860 : uno::Reference < XAccessible > xOldCursorAcc;
1873 430 : bool bOldShapeSelected = false;
1874 :
1875 : {
1876 430 : osl::MutexGuard aGuard( maMutex );
1877 :
1878 430 : if( !mpFrmMap && bCreate )
1879 0 : mpFrmMap = new SwAccessibleContextMap_Impl;
1880 430 : if( mpFrmMap )
1881 : {
1882 430 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1883 430 : if( aIter != mpFrmMap->end() )
1884 280 : xAcc = (*aIter).second;
1885 :
1886 430 : if( !xAcc.is() && bCreate )
1887 : {
1888 85 : SwAccessibleContext *pAcc = nullptr;
1889 85 : switch( pFrm->GetType() )
1890 : {
1891 : case FRM_TXT:
1892 65 : mnPara++;
1893 130 : pAcc = new SwAccessibleParagraph( *this,
1894 130 : static_cast< const SwTextFrm& >( *pFrm ) );
1895 65 : break;
1896 : case FRM_HEADER:
1897 : pAcc = new SwAccessibleHeaderFooter( this,
1898 0 : static_cast< const SwHeaderFrm *>( pFrm ) );
1899 0 : break;
1900 : case FRM_FOOTER:
1901 : pAcc = new SwAccessibleHeaderFooter( this,
1902 0 : static_cast< const SwFooterFrm *>( pFrm ) );
1903 0 : break;
1904 : case FRM_FTN:
1905 : {
1906 : const SwFootnoteFrm *pFootnoteFrm =
1907 1 : static_cast < const SwFootnoteFrm * >( pFrm );
1908 : bool bIsEndnote =
1909 1 : SwAccessibleFootnote::IsEndnote( pFootnoteFrm );
1910 : pAcc = new SwAccessibleFootnote( this, bIsEndnote,
1911 : /*(bIsEndnote ? mnEndnote++ : mnFootnote++),*/
1912 1 : pFootnoteFrm );
1913 : }
1914 1 : break;
1915 : case FRM_FLY:
1916 : {
1917 : const SwFlyFrm *pFlyFrm =
1918 1 : static_cast < const SwFlyFrm * >( pFrm );
1919 1 : switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
1920 : {
1921 : case ND_GRFNODE:
1922 1 : pAcc = new SwAccessibleGraphic( this, pFlyFrm );
1923 1 : break;
1924 : case ND_OLENODE:
1925 0 : pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
1926 0 : break;
1927 : default:
1928 0 : pAcc = new SwAccessibleTextFrame( this, *pFlyFrm );
1929 0 : break;
1930 : }
1931 : }
1932 1 : break;
1933 : case FRM_CELL:
1934 : pAcc = new SwAccessibleCell( this,
1935 16 : static_cast< const SwCellFrm *>( pFrm ) );
1936 16 : break;
1937 : case FRM_TAB:
1938 : pAcc = new SwAccessibleTable( this,
1939 2 : static_cast< const SwTabFrm *>( pFrm ) );
1940 2 : break;
1941 : case FRM_PAGE:
1942 : OSL_ENSURE( GetShell()->IsPreview(),
1943 : "accessible page frames only in PagePreview" );
1944 0 : pAcc = new SwAccessiblePage( this, pFrm );
1945 0 : break;
1946 : }
1947 85 : xAcc = pAcc;
1948 :
1949 : OSL_ENSURE( xAcc.is(), "unknown frame type" );
1950 85 : if( xAcc.is() )
1951 : {
1952 85 : if( aIter != mpFrmMap->end() )
1953 : {
1954 0 : (*aIter).second = xAcc;
1955 : }
1956 : else
1957 : {
1958 85 : SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
1959 85 : mpFrmMap->insert( aEntry );
1960 : }
1961 :
1962 285 : if( pAcc->HasCursor() &&
1963 175 : !AreInSameTable( mxCursorContext, pFrm ) )
1964 : {
1965 : // If the new context has the focus, and if we know
1966 : // another context that had the focus, then the focus
1967 : // just moves from the old context to the new one. We
1968 : // then have to send a focus event and a caret event for
1969 : // the old context. We have to do that now,
1970 : // because after we have left this method, anyone might
1971 : // call getStates for the new context and will get a
1972 : // focused state then. Sending the focus changes event
1973 : // after that seems to be strange. However, we cannot
1974 : // send a focus event for the new context now, because
1975 : // no one except us knows it. In any case, we remember
1976 : // the new context as the one that has the focus
1977 : // currently.
1978 :
1979 30 : xOldCursorAcc = mxCursorContext;
1980 30 : mxCursorContext = xAcc;
1981 :
1982 30 : bOldShapeSelected = mbShapeSelected;
1983 30 : mbShapeSelected = false;
1984 : }
1985 : }
1986 : }
1987 430 : }
1988 : }
1989 :
1990 : // Invalidate focus for old object when map is not locked
1991 430 : if( xOldCursorAcc.is() )
1992 0 : InvalidateCursorPosition( xOldCursorAcc );
1993 430 : if( bOldShapeSelected )
1994 0 : InvalidateShapeSelection();
1995 :
1996 860 : return xAcc;
1997 : }
1998 :
1999 360 : ::rtl::Reference < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
2000 : const SwFrm *pFrm,
2001 : bool bCreate )
2002 : {
2003 360 : uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
2004 :
2005 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
2006 360 : static_cast< SwAccessibleContext * >( xAcc.get() ) );
2007 :
2008 360 : return xAccImpl;
2009 : }
2010 :
2011 0 : uno::Reference< XAccessible> SwAccessibleMap::GetContext(
2012 : const SdrObject *pObj,
2013 : SwAccessibleContext *pParentImpl,
2014 : bool bCreate )
2015 : {
2016 0 : uno::Reference < XAccessible > xAcc;
2017 0 : uno::Reference < XAccessible > xOldCursorAcc;
2018 :
2019 : {
2020 0 : osl::MutexGuard aGuard( maMutex );
2021 :
2022 0 : if( !mpShapeMap && bCreate )
2023 0 : mpShapeMap = new SwAccessibleShapeMap_Impl( this );
2024 0 : if( mpShapeMap )
2025 : {
2026 0 : SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
2027 0 : if( aIter != mpShapeMap->end() )
2028 0 : xAcc = (*aIter).second;
2029 :
2030 0 : if( !xAcc.is() && bCreate )
2031 : {
2032 0 : ::accessibility::AccessibleShape *pAcc = nullptr;
2033 : uno::Reference < drawing::XShape > xShape(
2034 0 : const_cast< SdrObject * >( pObj )->getUnoShape(),
2035 0 : uno::UNO_QUERY );
2036 0 : if( xShape.is() )
2037 : {
2038 : ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2039 0 : ::accessibility::ShapeTypeHandler::Instance();
2040 0 : uno::Reference < XAccessible > xParent( pParentImpl );
2041 : ::accessibility::AccessibleShapeInfo aShapeInfo(
2042 0 : xShape, xParent, this );
2043 :
2044 : pAcc = rShapeTypeHandler.CreateAccessibleObject(
2045 0 : aShapeInfo, mpShapeMap->GetInfo() );
2046 : }
2047 0 : xAcc = pAcc;
2048 :
2049 : OSL_ENSURE( xAcc.is(), "unknown shape type" );
2050 0 : if( xAcc.is() )
2051 : {
2052 0 : pAcc->Init();
2053 0 : if( aIter != mpShapeMap->end() )
2054 : {
2055 0 : (*aIter).second = xAcc;
2056 : }
2057 : else
2058 : {
2059 : SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
2060 0 : xAcc );
2061 0 : mpShapeMap->insert( aEntry );
2062 : }
2063 : // TODO: focus!!!
2064 : }
2065 0 : if (xAcc.is())
2066 0 : AddGroupContext(pObj, xAcc);
2067 : }
2068 0 : }
2069 : }
2070 :
2071 : // Invalidate focus for old object when map is not locked
2072 0 : if( xOldCursorAcc.is() )
2073 0 : InvalidateCursorPosition( xOldCursorAcc );
2074 :
2075 0 : return xAcc;
2076 : }
2077 :
2078 0 : bool SwAccessibleMap::IsInSameLevel(const SdrObject* pObj, const SwFEShell* pFESh)
2079 : {
2080 0 : if (pFESh)
2081 0 : return pFESh->IsObjSameLevelWithMarked(pObj);
2082 0 : return false;
2083 : }
2084 :
2085 0 : void SwAccessibleMap::AddShapeContext(const SdrObject *pObj, uno::Reference < XAccessible > xAccShape)
2086 : {
2087 0 : osl::MutexGuard aGuard( maMutex );
2088 :
2089 0 : if( mpShapeMap )
2090 : {
2091 0 : SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAccShape );
2092 0 : mpShapeMap->insert( aEntry );
2093 0 : }
2094 :
2095 0 : }
2096 :
2097 : //Added by yanjun for sym2_6407
2098 0 : void SwAccessibleMap::RemoveGroupContext(const SdrObject *pParentObj, ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccParent)
2099 : {
2100 0 : osl::MutexGuard aGuard( maMutex );
2101 0 : if (mpShapeMap && pParentObj && pParentObj->IsGroupObject() && xAccParent.is())
2102 : {
2103 0 : uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
2104 0 : if (xContext.is())
2105 : {
2106 0 : for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i)
2107 : {
2108 0 : uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
2109 0 : if (xChild.is())
2110 : {
2111 0 : uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
2112 0 : if (xChildContext.is())
2113 : {
2114 0 : if (xChildContext->getAccessibleRole() == AccessibleRole::SHAPE)
2115 : {
2116 0 : ::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
2117 0 : uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
2118 0 : if (xShape.is())
2119 : {
2120 0 : SdrObject* pObj = GetSdrObjectFromXShape(xShape);
2121 0 : if (pObj)
2122 0 : RemoveContext(pObj);
2123 0 : }
2124 : }
2125 0 : }
2126 : }
2127 0 : }
2128 0 : }
2129 0 : }
2130 0 : }
2131 : //End
2132 :
2133 0 : void SwAccessibleMap::AddGroupContext(const SdrObject *pParentObj, uno::Reference < XAccessible > xAccParent)
2134 : {
2135 0 : osl::MutexGuard aGuard( maMutex );
2136 0 : if( mpShapeMap )
2137 : {
2138 : //here get all the sub list.
2139 0 : if (pParentObj->IsGroupObject())
2140 : {
2141 0 : if (xAccParent.is())
2142 : {
2143 0 : uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext();
2144 0 : if (xContext.is())
2145 : {
2146 0 : sal_Int32 nChildren = xContext->getAccessibleChildCount();
2147 0 : for(sal_Int32 i = 0; i<nChildren; i++)
2148 : {
2149 0 : uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i);
2150 0 : if (xChild.is())
2151 : {
2152 0 : uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext();
2153 0 : if (xChildContext.is())
2154 : {
2155 0 : short nRole = xChildContext->getAccessibleRole();
2156 0 : if (nRole == AccessibleRole::SHAPE)
2157 : {
2158 0 : ::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get());
2159 0 : uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape();
2160 0 : if (xShape.is())
2161 : {
2162 0 : SdrObject* pObj = GetSdrObjectFromXShape(xShape);
2163 0 : AddShapeContext(pObj, xChild);
2164 0 : AddGroupContext(pObj,xChild);
2165 0 : }
2166 : }
2167 0 : }
2168 : }
2169 0 : }
2170 0 : }
2171 : }
2172 : }
2173 0 : }
2174 0 : }
2175 :
2176 0 : ::rtl::Reference < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
2177 : const SdrObject *pObj,
2178 : SwAccessibleContext *pParentImpl,
2179 : bool bCreate )
2180 : {
2181 0 : uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
2182 :
2183 : ::rtl::Reference < ::accessibility::AccessibleShape > xAccImpl(
2184 0 : static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
2185 :
2186 0 : return xAccImpl;
2187 : }
2188 :
2189 97 : void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
2190 : {
2191 97 : osl::MutexGuard aGuard( maMutex );
2192 :
2193 97 : if( mpFrmMap )
2194 : {
2195 : SwAccessibleContextMap_Impl::iterator aIter =
2196 97 : mpFrmMap->find( pFrm );
2197 97 : if( aIter != mpFrmMap->end() )
2198 : {
2199 97 : mpFrmMap->erase( aIter );
2200 :
2201 : // Remove reference to old caret object. Though mxCursorContext
2202 : // is a weak reference and cleared automatically, clearing it
2203 : // directly makes sure to not keep a non-functional object.
2204 97 : uno::Reference < XAccessible > xOldAcc( mxCursorContext );
2205 97 : if( xOldAcc.is() )
2206 : {
2207 : SwAccessibleContext *pOldAccImpl =
2208 29 : static_cast< SwAccessibleContext *>( xOldAcc.get() );
2209 : OSL_ENSURE( pOldAccImpl->GetFrm(), "old caret context is disposed" );
2210 29 : if( pOldAccImpl->GetFrm() == pFrm )
2211 : {
2212 8 : xOldAcc.clear(); // get an empty ref
2213 8 : mxCursorContext = xOldAcc;
2214 : }
2215 : }
2216 :
2217 97 : if( mpFrmMap->empty() )
2218 : {
2219 12 : delete mpFrmMap;
2220 12 : mpFrmMap = nullptr;
2221 97 : }
2222 : }
2223 97 : }
2224 97 : }
2225 :
2226 0 : void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
2227 : {
2228 0 : osl::MutexGuard aGuard( maMutex );
2229 :
2230 0 : if( mpShapeMap )
2231 : {
2232 0 : SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
2233 0 : if( aIter != mpShapeMap->end() )
2234 : {
2235 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2236 0 : mpShapeMap->erase( aIter );
2237 0 : RemoveGroupContext(pObj, xAcc);
2238 : // The shape selection flag is not cleared, but one might do
2239 : // so but has to make sure that the removed context is the one
2240 : // that is selected.
2241 :
2242 0 : if( mpShapeMap && mpShapeMap->empty() )
2243 : {
2244 0 : delete mpShapeMap;
2245 0 : mpShapeMap = nullptr;
2246 0 : }
2247 : }
2248 0 : }
2249 0 : }
2250 :
2251 0 : void SwAccessibleMap::Dispose( const SwFrm *pFrm,
2252 : const SdrObject *pObj,
2253 : vcl::Window* pWindow,
2254 : bool bRecursive )
2255 : {
2256 0 : SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
2257 :
2258 : // Indeed, the following assert checks the frame's accessible flag,
2259 : // because that's the one that is evaluated in the layout. The frame
2260 : // might not be accessible anyway. That's the case for cell frames that
2261 : // contain further cells.
2262 : OSL_ENSURE( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
2263 : "non accessible frame should be disposed" );
2264 :
2265 0 : if (aFrmOrObj.IsAccessible( GetShell()->IsPreview() )
2266 : // fdo#87199 dispose the darn thing if it ever was accessible
2267 0 : || (pFrm && mpFrmMap && mpFrmMap->find(pFrm) != mpFrmMap->end()))
2268 : {
2269 0 : ::rtl::Reference< SwAccessibleContext > xAccImpl;
2270 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
2271 0 : ::rtl::Reference< ::accessibility::AccessibleShape > xShapeAccImpl;
2272 : // get accessible context for frame
2273 : {
2274 0 : osl::MutexGuard aGuard( maMutex );
2275 :
2276 : // First of all look for an accessible context for a frame
2277 0 : if( aFrmOrObj.GetSwFrm() && mpFrmMap )
2278 : {
2279 : SwAccessibleContextMap_Impl::iterator aIter =
2280 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2281 0 : if( aIter != mpFrmMap->end() )
2282 : {
2283 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2284 0 : xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2285 : }
2286 : }
2287 0 : if( !xAccImpl.is() && mpFrmMap )
2288 : {
2289 : // If there is none, look if the parent is accessible.
2290 : const SwFrm *pParent =
2291 : SwAccessibleFrame::GetParent( aFrmOrObj,
2292 0 : GetShell()->IsPreview());
2293 :
2294 0 : if( pParent )
2295 : {
2296 : SwAccessibleContextMap_Impl::iterator aIter =
2297 0 : mpFrmMap->find( pParent );
2298 0 : if( aIter != mpFrmMap->end() )
2299 : {
2300 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2301 0 : xParentAccImpl =
2302 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2303 : }
2304 : }
2305 : }
2306 0 : if( !xParentAccImpl.is() && !aFrmOrObj.GetSwFrm() && mpShapeMap )
2307 : {
2308 : SwAccessibleShapeMap_Impl::iterator aIter =
2309 0 : mpShapeMap->find( aFrmOrObj.GetDrawObject() );
2310 0 : if( aIter != mpShapeMap->end() )
2311 : {
2312 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2313 0 : xShapeAccImpl =
2314 0 : static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
2315 : }
2316 : }
2317 0 : if( pObj && GetShell()->ActionPend() &&
2318 0 : (xParentAccImpl.is() || xShapeAccImpl.is()) )
2319 : {
2320 : // Keep a reference to the XShape to avoid that it
2321 : // is deleted with a SwFrameFormat::Modify.
2322 : uno::Reference < drawing::XShape > xShape(
2323 0 : const_cast< SdrObject * >( pObj )->getUnoShape(),
2324 0 : uno::UNO_QUERY );
2325 0 : if( xShape.is() )
2326 : {
2327 0 : if( !mpShapes )
2328 0 : mpShapes = new SwShapeList_Impl;
2329 0 : mpShapes->push_back( xShape );
2330 0 : }
2331 0 : }
2332 : }
2333 :
2334 : // remove events stored for the frame
2335 : {
2336 0 : osl::MutexGuard aGuard( maEventMutex );
2337 0 : if( mpEvents )
2338 : {
2339 : SwAccessibleEventMap_Impl::iterator aIter =
2340 0 : mpEventMap->find( aFrmOrObj );
2341 0 : if( aIter != mpEventMap->end() )
2342 : {
2343 : SwAccessibleEvent_Impl aEvent(
2344 0 : SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
2345 0 : AppendEvent( aEvent );
2346 : }
2347 0 : }
2348 : }
2349 :
2350 : // If the frame is accessible and there is a context for it, dispose
2351 : // the frame. If the frame is no context for it but disposing should
2352 : // take place recursive, the frame's children have to be disposed
2353 : // anyway, so we have to create the context then.
2354 0 : if( xAccImpl.is() )
2355 : {
2356 0 : xAccImpl->Dispose( bRecursive );
2357 : }
2358 0 : else if( xParentAccImpl.is() )
2359 : {
2360 : // If the frame is a cell frame, the table must be notified.
2361 : // If we are in an action, a table model change event will
2362 : // be broadcasted at the end of the action to give the table
2363 : // a chance to generate a single table change event.
2364 :
2365 0 : xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
2366 : }
2367 0 : else if( xShapeAccImpl.is() )
2368 : {
2369 0 : RemoveContext( aFrmOrObj.GetDrawObject() );
2370 0 : xShapeAccImpl->dispose();
2371 : }
2372 :
2373 0 : if( mpPreview && pFrm && pFrm->IsPageFrm() )
2374 0 : mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
2375 0 : }
2376 0 : }
2377 :
2378 81 : void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
2379 : const SdrObject *pObj,
2380 : vcl::Window* pWindow,
2381 : const SwRect& rOldBox )
2382 : {
2383 81 : SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
2384 81 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2385 : {
2386 59 : ::rtl::Reference< SwAccessibleContext > xAccImpl;
2387 118 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
2388 59 : const SwFrm *pParent =NULL;
2389 : {
2390 59 : osl::MutexGuard aGuard( maMutex );
2391 :
2392 59 : if( mpFrmMap )
2393 : {
2394 59 : if( aFrmOrObj.GetSwFrm() )
2395 : {
2396 : SwAccessibleContextMap_Impl::iterator aIter =
2397 59 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2398 59 : if( aIter != mpFrmMap->end() )
2399 : {
2400 : // If there is an accessible object already it is
2401 : // notified directly.
2402 37 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2403 37 : xAccImpl =
2404 74 : static_cast< SwAccessibleContext *>( xAcc.get() );
2405 : }
2406 : }
2407 59 : if( !xAccImpl.is() )
2408 : {
2409 : // Otherwise we look if the parent is accessible.
2410 : // If not, there is nothing to do.
2411 : pParent =
2412 : SwAccessibleFrame::GetParent( aFrmOrObj,
2413 22 : GetShell()->IsPreview());
2414 :
2415 22 : if( pParent )
2416 : {
2417 : SwAccessibleContextMap_Impl::iterator aIter =
2418 22 : mpFrmMap->find( pParent );
2419 22 : if( aIter != mpFrmMap->end() )
2420 : {
2421 22 : uno::Reference < XAccessible > xAcc( (*aIter).second );
2422 22 : xParentAccImpl =
2423 44 : static_cast< SwAccessibleContext *>( xAcc.get() );
2424 : }
2425 : }
2426 : }
2427 59 : }
2428 : }
2429 :
2430 59 : if( xAccImpl.is() )
2431 : {
2432 37 : if( GetShell()->ActionPend() )
2433 : {
2434 : SwAccessibleEvent_Impl aEvent(
2435 : SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.get(),
2436 28 : aFrmOrObj, rOldBox );
2437 28 : AppendEvent( aEvent );
2438 : }
2439 : else
2440 : {
2441 9 : FireEvents();
2442 9 : xAccImpl->InvalidatePosOrSize( rOldBox );
2443 : }
2444 : }
2445 22 : else if( xParentAccImpl.is() )
2446 : {
2447 22 : if( GetShell()->ActionPend() )
2448 : {
2449 : SwAccessibleEvent_Impl aEvent(
2450 : SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2451 8 : xParentAccImpl.get(), aFrmOrObj, rOldBox );
2452 8 : AppendEvent( aEvent );
2453 : }
2454 : else
2455 : {
2456 14 : FireEvents();
2457 14 : xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
2458 14 : rOldBox );
2459 : }
2460 : }
2461 0 : else if(pParent)
2462 : {
2463 : /*
2464 : For child graphic and its parent paragraph,if split 2 graphic to 2 paragraph,
2465 : will delete one graphic swfrm and new create 1 graphic swfrm ,
2466 : then the new paragraph and the new graphic SwFrm will add .
2467 : but when add graphic SwFrm ,the accessible of the new Paragraph is not created yet.
2468 : so the new graphic accessible 'parent is NULL,
2469 : so run here: save the parent's SwFrm not the accessible object parent,
2470 : */
2471 0 : bool bIsValidFrm = false;
2472 0 : bool bIsTextParent = false;
2473 0 : if (aFrmOrObj.GetSwFrm())
2474 : {
2475 0 : int nType = pFrm->GetType();
2476 0 : if ( FRM_FLY == nType )
2477 : {
2478 0 : bIsValidFrm =true;
2479 : }
2480 : }
2481 0 : else if(pObj)
2482 : {
2483 0 : int nType = pParent->GetType();
2484 0 : if (FRM_TXT == nType)
2485 : {
2486 0 : bIsTextParent =true;
2487 : }
2488 : }
2489 : // bool bIsVisibleChildrenOnly =aFrmOrObj.IsVisibleChildrenOnly() ;
2490 : // bool bIsBoundAsChar =aFrmOrObj.IsBoundAsChar() ;//bIsVisibleChildrenOnly && bIsBoundAsChar &&
2491 0 : if((bIsValidFrm || bIsTextParent) )
2492 : {
2493 0 : if( GetShell()->ActionPend() )
2494 : {
2495 : SwAccessibleEvent_Impl aEvent(
2496 : SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2497 0 : pParent, aFrmOrObj, rOldBox );
2498 0 : AppendEvent( aEvent );
2499 : }
2500 : else
2501 : {
2502 : OSL_ENSURE(false,"");
2503 : }
2504 : }
2505 59 : }
2506 81 : }
2507 81 : }
2508 :
2509 0 : void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
2510 : {
2511 0 : SwAccessibleChild aFrmOrObj( pFrm );
2512 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2513 : {
2514 0 : uno::Reference < XAccessible > xAcc;
2515 : {
2516 0 : osl::MutexGuard aGuard( maMutex );
2517 :
2518 0 : if( mpFrmMap )
2519 : {
2520 : SwAccessibleContextMap_Impl::iterator aIter =
2521 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2522 0 : if( aIter != mpFrmMap->end() )
2523 0 : xAcc = (*aIter).second;
2524 0 : }
2525 : }
2526 :
2527 0 : if( xAcc.is() )
2528 : {
2529 : SwAccessibleContext *pAccImpl =
2530 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2531 0 : if( GetShell()->ActionPend() )
2532 : {
2533 : SwAccessibleEvent_Impl aEvent(
2534 : SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
2535 0 : aFrmOrObj );
2536 0 : AppendEvent( aEvent );
2537 : }
2538 : else
2539 : {
2540 0 : FireEvents();
2541 0 : pAccImpl->InvalidateContent();
2542 : }
2543 0 : }
2544 0 : }
2545 0 : }
2546 :
2547 0 : void SwAccessibleMap::InvalidateAttr( const SwTextFrm& rTextFrm )
2548 : {
2549 0 : SwAccessibleChild aFrmOrObj( &rTextFrm );
2550 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2551 : {
2552 0 : uno::Reference < XAccessible > xAcc;
2553 : {
2554 0 : osl::MutexGuard aGuard( maMutex );
2555 :
2556 0 : if( mpFrmMap )
2557 : {
2558 : SwAccessibleContextMap_Impl::iterator aIter =
2559 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2560 0 : if( aIter != mpFrmMap->end() )
2561 0 : xAcc = (*aIter).second;
2562 0 : }
2563 : }
2564 :
2565 0 : if( xAcc.is() )
2566 : {
2567 : SwAccessibleContext *pAccImpl =
2568 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2569 0 : if( GetShell()->ActionPend() )
2570 : {
2571 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
2572 0 : pAccImpl, aFrmOrObj );
2573 0 : aEvent.SetStates( AccessibleStates::TEXT_ATTRIBUTE_CHANGED );
2574 0 : AppendEvent( aEvent );
2575 : }
2576 : else
2577 : {
2578 0 : FireEvents();
2579 0 : pAccImpl->InvalidateAttr();
2580 : }
2581 0 : }
2582 0 : }
2583 0 : }
2584 :
2585 83 : void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
2586 : {
2587 83 : SwAccessibleChild aFrmOrObj( pFrm );
2588 83 : bool bShapeSelected = false;
2589 83 : const SwViewShell *pVSh = GetShell();
2590 83 : if( pVSh->ISA( SwCrsrShell ) )
2591 : {
2592 83 : const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
2593 83 : if( pCSh->IsTableMode() )
2594 : {
2595 24 : while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
2596 8 : aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2597 : }
2598 75 : else if( pVSh->ISA( SwFEShell ) )
2599 : {
2600 75 : const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
2601 75 : const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
2602 75 : if( pFlyFrm )
2603 : {
2604 : OSL_ENSURE( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
2605 : "cursor is not contained in fly frame" );
2606 0 : aFrmOrObj = pFlyFrm;
2607 : }
2608 75 : else if( pFESh->IsObjSelected() > 0 )
2609 : {
2610 0 : bShapeSelected = true;
2611 0 : aFrmOrObj = static_cast<const SwFrm *>( nullptr );
2612 : }
2613 : }
2614 : }
2615 :
2616 : OSL_ENSURE( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreview()),
2617 : "frame is not accessible" );
2618 :
2619 166 : uno::Reference < XAccessible > xOldAcc;
2620 166 : uno::Reference < XAccessible > xAcc;
2621 83 : bool bOldShapeSelected = false;
2622 :
2623 : {
2624 83 : osl::MutexGuard aGuard( maMutex );
2625 :
2626 83 : xOldAcc = mxCursorContext;
2627 83 : mxCursorContext = xAcc; // clear reference
2628 :
2629 83 : bOldShapeSelected = mbShapeSelected;
2630 83 : mbShapeSelected = bShapeSelected;
2631 :
2632 83 : if( aFrmOrObj.GetSwFrm() && mpFrmMap )
2633 : {
2634 : SwAccessibleContextMap_Impl::iterator aIter =
2635 83 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2636 83 : if( aIter != mpFrmMap->end() )
2637 60 : xAcc = (*aIter).second;
2638 : else
2639 : {
2640 23 : SwRect rcEmpty;
2641 23 : const SwTabFrm* pTabFrm = aFrmOrObj.GetSwFrm()->FindTabFrm();
2642 23 : if (pTabFrm)
2643 : {
2644 9 : InvalidatePosOrSize(pTabFrm, nullptr, nullptr, rcEmpty);
2645 : }
2646 : else
2647 : {
2648 14 : InvalidatePosOrSize(aFrmOrObj.GetSwFrm(), nullptr, nullptr, rcEmpty);
2649 : }
2650 :
2651 23 : aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2652 23 : if( aIter != mpFrmMap->end() )
2653 : {
2654 0 : xAcc = (*aIter).second;
2655 : }
2656 : }
2657 :
2658 : // For cells, some extra thoughts are necessary,
2659 : // because invalidating the cursor for one cell
2660 : // invalidates the cursor for all cells of the same
2661 : // table. For this reason, we don't want to
2662 : // invalidate the cursor for the old cursor object
2663 : // and the new one if they are within the same table,
2664 : // because this would result in doing the work twice.
2665 : // Moreover, we have to make sure to invalidate the
2666 : // cursor even if the current cell has no accessible object.
2667 : // If the old cursor objects exists and is in the same
2668 : // table, its the best choice, because using it avoids
2669 : // an unnecessary cursor invalidation cycle when creating
2670 : // a new object for the current cell.
2671 83 : if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
2672 : {
2673 9 : if( xOldAcc.is() &&
2674 1 : AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
2675 : {
2676 1 : if( xAcc.is() )
2677 1 : xOldAcc = xAcc; // avoid extra invalidation
2678 : else
2679 0 : xAcc = xOldAcc; // make sure ate least one
2680 : }
2681 8 : if( !xAcc.is() )
2682 5 : xAcc = GetContext( aFrmOrObj.GetSwFrm(), true );
2683 : }
2684 : }
2685 0 : else if (bShapeSelected)
2686 : {
2687 0 : const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
2688 0 : const SdrMarkList *pMarkList = pFESh->GetMarkList();
2689 0 : if (pMarkList != NULL && pMarkList->GetMarkCount() == 1)
2690 : {
2691 0 : SdrObject *pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
2692 0 : ::rtl::Reference < ::accessibility::AccessibleShape > pAccShapeImpl = GetContextImpl(pObj,NULL,false);
2693 0 : if (!pAccShapeImpl.is())
2694 : {
2695 0 : while (pObj && pObj->GetUpGroup())
2696 : {
2697 0 : pObj = pObj->GetUpGroup();
2698 : }
2699 0 : if (pObj != NULL)
2700 : {
2701 0 : const SwFrm *pParent = SwAccessibleFrame::GetParent( SwAccessibleChild(pObj), GetShell()->IsPreview() );
2702 0 : if( pParent )
2703 : {
2704 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImpl = GetContextImpl(pParent,false);
2705 0 : if (!xParentAccImpl.is())
2706 : {
2707 0 : const SwTabFrm* pTabFrm = pParent->FindTabFrm();
2708 0 : if (pTabFrm)
2709 : {
2710 : //The Table should not add in acc.because the "pParent" is not add to acc .
2711 0 : uno::Reference< XAccessible> xAccParentTab = GetContext(pTabFrm,true);//Should Create.
2712 :
2713 0 : const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pTabFrm), GetShell()->IsPreview() );
2714 0 : if (pParentRoot)
2715 : {
2716 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,false);
2717 0 : if(xParentAccImplRoot.is())
2718 : {
2719 0 : AccessibleEventObject aEvent;
2720 0 : aEvent.EventId = AccessibleEventId::CHILD;
2721 0 : aEvent.NewValue <<= xAccParentTab;
2722 0 : xParentAccImplRoot->FireAccessibleEvent( aEvent );
2723 0 : }
2724 : }
2725 :
2726 : //Get "pParent" acc again.
2727 0 : xParentAccImpl = GetContextImpl(pParent,false);
2728 : }
2729 : else
2730 : {
2731 : //directly create this acc para .
2732 0 : xParentAccImpl = GetContextImpl(pParent,true);//Should Create.
2733 :
2734 0 : const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pParent), GetShell()->IsPreview() );
2735 :
2736 0 : ::rtl::Reference< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,false);
2737 0 : if(xParentAccImplRoot.is())
2738 : {
2739 0 : AccessibleEventObject aEvent;
2740 0 : aEvent.EventId = AccessibleEventId::CHILD;
2741 0 : aEvent.NewValue <<= uno::Reference< XAccessible>(xParentAccImpl.get());
2742 0 : xParentAccImplRoot->FireAccessibleEvent( aEvent );
2743 0 : }
2744 : }
2745 : }
2746 0 : if (xParentAccImpl.is())
2747 : {
2748 : uno::Reference< XAccessible> xAccShape =
2749 0 : GetContext(pObj,xParentAccImpl.get(),true);
2750 :
2751 0 : AccessibleEventObject aEvent;
2752 0 : aEvent.EventId = AccessibleEventId::CHILD;
2753 0 : aEvent.NewValue <<= xAccShape;
2754 0 : xParentAccImpl->FireAccessibleEvent( aEvent );
2755 0 : }
2756 : }
2757 : }
2758 0 : }
2759 : }
2760 83 : }
2761 : }
2762 :
2763 83 : m_setParaAdd.clear();
2764 83 : m_setParaRemove.clear();
2765 83 : if( xOldAcc.is() && xOldAcc != xAcc )
2766 3 : InvalidateCursorPosition( xOldAcc );
2767 83 : if( bOldShapeSelected || bShapeSelected )
2768 0 : InvalidateShapeSelection();
2769 83 : if( xAcc.is() )
2770 65 : InvalidateCursorPosition( xAcc );
2771 :
2772 83 : InvalidateShapeInParaSelection();
2773 :
2774 83 : SET_PARA::iterator si = m_setParaRemove.begin();
2775 83 : for (; si != m_setParaRemove.end() ; ++si)
2776 : {
2777 0 : SwAccessibleParagraph* pAccPara = *si;
2778 0 : if(pAccPara && pAccPara->getSelectedAccessibleChildCount() == 0 && pAccPara->getSelectedText().getLength() == 0)
2779 : {
2780 0 : if(pAccPara->SetSelectedState(false))
2781 : {
2782 0 : AccessibleEventObject aEvent;
2783 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
2784 0 : pAccPara->FireAccessibleEvent( aEvent );
2785 : }
2786 : }
2787 : }
2788 83 : si = m_setParaAdd.begin();
2789 83 : for (; si != m_setParaAdd.end() ; ++si)
2790 : {
2791 0 : SwAccessibleParagraph* pAccPara = *si;
2792 0 : if(pAccPara && pAccPara->SetSelectedState(true))
2793 : {
2794 0 : AccessibleEventObject aEvent;
2795 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
2796 0 : pAccPara->FireAccessibleEvent( aEvent );
2797 : }
2798 83 : }
2799 83 : }
2800 :
2801 8 : void SwAccessibleMap::InvalidateFocus()
2802 : {
2803 8 : if(GetShell()->IsPreview())
2804 : {
2805 0 : uno::Reference<XAccessible> xAcc = _GetDocumentView( true );
2806 0 : if (xAcc.get())
2807 : {
2808 0 : SwAccessiblePreview *pAccPreview = static_cast<SwAccessiblePreview *>(xAcc.get());
2809 0 : if (pAccPreview)
2810 : {
2811 0 : pAccPreview->InvalidateFocus();
2812 8 : return ;
2813 : }
2814 0 : }
2815 : }
2816 8 : uno::Reference < XAccessible > xAcc;
2817 : {
2818 8 : osl::MutexGuard aGuard( maMutex );
2819 :
2820 8 : xAcc = mxCursorContext;
2821 : }
2822 :
2823 8 : if( xAcc.is() )
2824 : {
2825 5 : SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2826 5 : pAccImpl->InvalidateFocus();
2827 : }
2828 : else
2829 : {
2830 3 : DoInvalidateShapeSelection(true);
2831 8 : }
2832 : }
2833 :
2834 90 : void SwAccessibleMap::SetCursorContext(
2835 : const ::rtl::Reference < SwAccessibleContext >& rCursorContext )
2836 : {
2837 90 : osl::MutexGuard aGuard( maMutex );
2838 180 : uno::Reference < XAccessible > xAcc( rCursorContext.get() );
2839 180 : mxCursorContext = xAcc;
2840 90 : }
2841 :
2842 0 : void SwAccessibleMap::InvalidateStates( AccessibleStates _nStates,
2843 : const SwFrm* _pFrm )
2844 : {
2845 : // Start with the frame or the first upper that is accessible
2846 0 : SwAccessibleChild aFrmOrObj( _pFrm );
2847 0 : while( aFrmOrObj.GetSwFrm() &&
2848 0 : !aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2849 0 : aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2850 0 : if( !aFrmOrObj.GetSwFrm() )
2851 0 : aFrmOrObj = GetShell()->GetLayout();
2852 :
2853 0 : uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), true ) );
2854 0 : SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() );
2855 0 : if( GetShell()->ActionPend() )
2856 : {
2857 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2858 : pAccImpl,
2859 : SwAccessibleChild(pAccImpl->GetFrm()),
2860 0 : _nStates );
2861 0 : AppendEvent( aEvent );
2862 : }
2863 : else
2864 : {
2865 0 : FireEvents();
2866 0 : pAccImpl->InvalidateStates( _nStates );
2867 0 : }
2868 0 : }
2869 :
2870 0 : void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
2871 : bool bFrom )
2872 : {
2873 : // first, see if this frame is accessible, and if so, get the respective
2874 0 : SwAccessibleChild aFrmOrObj( pFrm );
2875 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2876 : {
2877 0 : uno::Reference < XAccessible > xAcc;
2878 : {
2879 0 : osl::MutexGuard aGuard( maMutex );
2880 :
2881 0 : if( mpFrmMap )
2882 : {
2883 : SwAccessibleContextMap_Impl::iterator aIter =
2884 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2885 0 : if( aIter != mpFrmMap->end() )
2886 : {
2887 0 : xAcc = (*aIter).second;
2888 : }
2889 0 : }
2890 : }
2891 :
2892 : // deliver event directly, or queue event
2893 0 : if( xAcc.is() )
2894 : {
2895 : SwAccessibleContext *pAccImpl =
2896 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2897 0 : if( GetShell()->ActionPend() )
2898 : {
2899 : SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
2900 : pAccImpl, SwAccessibleChild(pFrm),
2901 : ( bFrom
2902 : ? AccessibleStates::RELATION_FROM
2903 0 : : AccessibleStates::RELATION_TO ) );
2904 0 : AppendEvent( aEvent );
2905 : }
2906 : else
2907 : {
2908 0 : FireEvents();
2909 : pAccImpl->InvalidateRelation( bFrom
2910 : ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
2911 0 : : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
2912 : }
2913 0 : }
2914 0 : }
2915 0 : }
2916 :
2917 0 : void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
2918 : const SwFrm* pFollow )
2919 : {
2920 0 : _InvalidateRelationSet( pMaster, false );
2921 0 : _InvalidateRelationSet( pFollow, true );
2922 0 : }
2923 :
2924 : // invalidation of CONTENT_FLOW_FROM/_TO relation of a paragraph
2925 0 : void SwAccessibleMap::InvalidateParaFlowRelation( const SwTextFrm& _rTextFrm,
2926 : const bool _bFrom )
2927 : {
2928 0 : _InvalidateRelationSet( &_rTextFrm, _bFrom );
2929 0 : }
2930 :
2931 : // invalidation of text selection of a paragraph
2932 0 : void SwAccessibleMap::InvalidateParaTextSelection( const SwTextFrm& _rTextFrm )
2933 : {
2934 : // first, see if this frame is accessible, and if so, get the respective
2935 0 : SwAccessibleChild aFrmOrObj( &_rTextFrm );
2936 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2937 : {
2938 0 : uno::Reference < XAccessible > xAcc;
2939 : {
2940 0 : osl::MutexGuard aGuard( maMutex );
2941 :
2942 0 : if( mpFrmMap )
2943 : {
2944 : SwAccessibleContextMap_Impl::iterator aIter =
2945 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2946 0 : if( aIter != mpFrmMap->end() )
2947 : {
2948 0 : xAcc = (*aIter).second;
2949 : }
2950 0 : }
2951 : }
2952 :
2953 : // deliver event directly, or queue event
2954 0 : if( xAcc.is() )
2955 : {
2956 : SwAccessibleContext *pAccImpl =
2957 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
2958 0 : if( GetShell()->ActionPend() )
2959 : {
2960 : SwAccessibleEvent_Impl aEvent(
2961 : SwAccessibleEvent_Impl::CARET_OR_STATES,
2962 : pAccImpl,
2963 : SwAccessibleChild( &_rTextFrm ),
2964 0 : AccessibleStates::TEXT_SELECTION_CHANGED );
2965 0 : AppendEvent( aEvent );
2966 : }
2967 : else
2968 : {
2969 0 : FireEvents();
2970 0 : pAccImpl->InvalidateTextSelection();
2971 : }
2972 0 : }
2973 0 : }
2974 0 : }
2975 :
2976 0 : sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
2977 : vcl::Window& rChild ) const
2978 : {
2979 0 : sal_Int32 nIndex( -1 );
2980 :
2981 0 : SwAccessibleChild aFrmOrObj( &rParentFrm );
2982 0 : if( aFrmOrObj.IsAccessible( GetShell()->IsPreview() ) )
2983 : {
2984 0 : uno::Reference < XAccessible > xAcc;
2985 : {
2986 0 : osl::MutexGuard aGuard( maMutex );
2987 :
2988 0 : if( mpFrmMap )
2989 : {
2990 : SwAccessibleContextMap_Impl::iterator aIter =
2991 0 : mpFrmMap->find( aFrmOrObj.GetSwFrm() );
2992 0 : if( aIter != mpFrmMap->end() )
2993 : {
2994 0 : xAcc = (*aIter).second;
2995 : }
2996 0 : }
2997 : }
2998 :
2999 0 : if( xAcc.is() )
3000 : {
3001 : SwAccessibleContext *pAccImpl =
3002 0 : static_cast< SwAccessibleContext *>( xAcc.get() );
3003 :
3004 : nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
3005 0 : SwAccessibleChild( &rChild ) );
3006 0 : }
3007 : }
3008 :
3009 0 : return nIndex;
3010 : }
3011 :
3012 0 : void SwAccessibleMap::UpdatePreview( const std::vector<PreviewPage*>& _rPreviewPages,
3013 : const Fraction& _rScale,
3014 : const SwPageFrm* _pSelectedPageFrm,
3015 : const Size& _rPreviewWinSize )
3016 : {
3017 : assert(GetShell()->IsPreview() && "no preview?");
3018 : assert(mpPreview != NULL && "no preview data?");
3019 :
3020 0 : mpPreview->Update( *this, _rPreviewPages, _rScale, _pSelectedPageFrm, _rPreviewWinSize );
3021 :
3022 : // propagate change of VisArea through the document's
3023 : // accessibility tree; this will also send appropriate scroll
3024 : // events
3025 : SwAccessibleContext* pDoc =
3026 0 : GetContextImpl( GetShell()->GetLayout() ).get();
3027 0 : static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
3028 :
3029 0 : uno::Reference < XAccessible > xOldAcc;
3030 0 : uno::Reference < XAccessible > xAcc;
3031 : {
3032 0 : osl::MutexGuard aGuard( maMutex );
3033 :
3034 0 : xOldAcc = mxCursorContext;
3035 :
3036 0 : const SwPageFrm *pSelPage = mpPreview->GetSelPage();
3037 0 : if( pSelPage && mpFrmMap )
3038 : {
3039 : SwAccessibleContextMap_Impl::iterator aIter =
3040 0 : mpFrmMap->find( pSelPage );
3041 0 : if( aIter != mpFrmMap->end() )
3042 0 : xAcc = (*aIter).second;
3043 0 : }
3044 : }
3045 :
3046 0 : if( xOldAcc.is() && xOldAcc != xAcc )
3047 0 : InvalidateCursorPosition( xOldAcc );
3048 0 : if( xAcc.is() )
3049 0 : InvalidateCursorPosition( xAcc );
3050 0 : }
3051 :
3052 0 : void SwAccessibleMap::InvalidatePreviewSelection( sal_uInt16 nSelPage )
3053 : {
3054 : OSL_ENSURE( GetShell()->IsPreview(), "no preview?" );
3055 : OSL_ENSURE( mpPreview != NULL, "no preview data?" );
3056 :
3057 0 : mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
3058 :
3059 0 : uno::Reference < XAccessible > xOldAcc;
3060 0 : uno::Reference < XAccessible > xAcc;
3061 : {
3062 0 : osl::MutexGuard aGuard( maMutex );
3063 :
3064 0 : xOldAcc = mxCursorContext;
3065 :
3066 0 : const SwPageFrm *pSelPage = mpPreview->GetSelPage();
3067 0 : if( pSelPage && mpFrmMap )
3068 : {
3069 0 : SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pSelPage );
3070 0 : if( aIter != mpFrmMap->end() )
3071 0 : xAcc = (*aIter).second;
3072 0 : }
3073 : }
3074 :
3075 0 : if( xOldAcc.is() && xOldAcc != xAcc )
3076 0 : InvalidateCursorPosition( xOldAcc );
3077 0 : if( xAcc.is() )
3078 0 : InvalidateCursorPosition( xAcc );
3079 0 : }
3080 :
3081 0 : bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
3082 : {
3083 0 : return mpPreview && mpPreview->GetSelPage() == pPageFrm;
3084 : }
3085 :
3086 5377164 : void SwAccessibleMap::FireEvents()
3087 : {
3088 : {
3089 5377164 : osl::MutexGuard aGuard( maEventMutex );
3090 5377164 : if( mpEvents )
3091 : {
3092 14 : mpEvents->SetFiring();
3093 14 : mpEvents->MoveInvalidXAccToEnd();
3094 : ::std::for_each(mpEvents->begin(), mpEvents->end(),
3095 14 : boost::bind(&SwAccessibleMap::FireEvent, this, _1));
3096 :
3097 14 : delete mpEventMap;
3098 14 : mpEventMap = nullptr;
3099 :
3100 14 : delete mpEvents;
3101 14 : mpEvents = nullptr;
3102 5377164 : }
3103 : }
3104 : {
3105 5377164 : osl::MutexGuard aGuard( maMutex );
3106 5377164 : if( mpShapes )
3107 : {
3108 0 : delete mpShapes;
3109 0 : mpShapes = nullptr;
3110 5377164 : }
3111 : }
3112 :
3113 5377164 : }
3114 :
3115 0 : bool SwAccessibleMap::IsValid() const
3116 : {
3117 0 : return true;
3118 : }
3119 :
3120 0 : Rectangle SwAccessibleMap::GetVisibleArea() const
3121 : {
3122 0 : MapMode aSrc( MAP_TWIP );
3123 0 : MapMode aDest( MAP_100TH_MM );
3124 0 : return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
3125 : }
3126 :
3127 : // Convert a MM100 value relative to the document root into a pixel value
3128 : // relative to the screen!
3129 0 : Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
3130 : {
3131 0 : MapMode aSrc( MAP_100TH_MM );
3132 0 : MapMode aDest( MAP_TWIP );
3133 :
3134 0 : Point aPoint = rPoint;
3135 :
3136 0 : aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
3137 0 : vcl::Window *pWin = GetShell()->GetWin();
3138 0 : if( pWin )
3139 : {
3140 0 : MapMode aMapMode;
3141 0 : GetMapMode( aPoint, aMapMode );
3142 0 : aPoint = pWin->LogicToPixel( aPoint, aMapMode );
3143 0 : aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
3144 : }
3145 :
3146 0 : return aPoint;
3147 : }
3148 :
3149 0 : Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
3150 : {
3151 0 : MapMode aSrc( MAP_100TH_MM );
3152 0 : MapMode aDest( MAP_TWIP );
3153 0 : Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
3154 0 : if( GetShell()->GetWin() )
3155 : {
3156 0 : MapMode aMapMode;
3157 0 : GetMapMode( Point(0,0), aMapMode );
3158 0 : aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
3159 : }
3160 :
3161 0 : return aSize;
3162 : }
3163 :
3164 0 : Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
3165 : {
3166 0 : Point aPoint;
3167 0 : vcl::Window *pWin = GetShell()->GetWin();
3168 0 : if( pWin )
3169 : {
3170 0 : aPoint = pWin->ScreenToOutputPixel( rPoint );
3171 0 : MapMode aMapMode;
3172 0 : GetMapMode( aPoint, aMapMode );
3173 0 : aPoint = pWin->PixelToLogic( aPoint, aMapMode );
3174 0 : MapMode aSrc( MAP_TWIP );
3175 0 : MapMode aDest( MAP_100TH_MM );
3176 0 : aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
3177 : }
3178 :
3179 0 : return aPoint;
3180 : }
3181 :
3182 0 : Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
3183 : {
3184 0 : Size aSize;
3185 0 : if( GetShell()->GetWin() )
3186 : {
3187 0 : MapMode aMapMode;
3188 0 : GetMapMode( Point(0,0), aMapMode );
3189 0 : aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
3190 0 : MapMode aSrc( MAP_TWIP );
3191 0 : MapMode aDest( MAP_100TH_MM );
3192 0 : aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
3193 : }
3194 :
3195 0 : return aSize;
3196 : }
3197 :
3198 0 : bool SwAccessibleMap::ReplaceChild (
3199 : ::accessibility::AccessibleShape* pCurrentChild,
3200 : const uno::Reference< drawing::XShape >& _rxShape,
3201 : const long /*_nIndex*/,
3202 : const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
3203 : ) throw (uno::RuntimeException)
3204 : {
3205 0 : const SdrObject *pObj = nullptr;
3206 : {
3207 0 : osl::MutexGuard aGuard( maMutex );
3208 0 : if( mpShapeMap )
3209 : {
3210 0 : SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
3211 0 : SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
3212 0 : while( aIter != aEndIter && !pObj )
3213 : {
3214 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
3215 : ::accessibility::AccessibleShape *pAccShape =
3216 0 : static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3217 0 : if( pAccShape == pCurrentChild )
3218 : {
3219 0 : pObj = (*aIter).first;
3220 : }
3221 0 : ++aIter;
3222 0 : }
3223 0 : }
3224 : }
3225 0 : if( !pObj )
3226 0 : return false;
3227 :
3228 0 : uno::Reference < drawing::XShape > xShape( _rxShape ); // keep reference to shape, because
3229 : // we might be the only one that
3230 : // holds it.
3231 : // Also get keep parent.
3232 0 : uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
3233 0 : pCurrentChild = nullptr; // will be released by dispose
3234 0 : Dispose( nullptr, pObj, nullptr );
3235 :
3236 : {
3237 0 : osl::MutexGuard aGuard( maMutex );
3238 :
3239 0 : if( !mpShapeMap )
3240 0 : mpShapeMap = new SwAccessibleShapeMap_Impl( this );
3241 :
3242 : // create the new child
3243 : ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
3244 0 : ::accessibility::ShapeTypeHandler::Instance();
3245 : ::accessibility::AccessibleShapeInfo aShapeInfo(
3246 0 : xShape, xParent, this );
3247 : ::accessibility::AccessibleShape* pReplacement =
3248 : rShapeTypeHandler.CreateAccessibleObject (
3249 0 : aShapeInfo, mpShapeMap->GetInfo() );
3250 :
3251 0 : uno::Reference < XAccessible > xAcc( pReplacement );
3252 0 : if( xAcc.is() )
3253 : {
3254 0 : pReplacement->Init();
3255 :
3256 0 : SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj );
3257 0 : if( aIter != mpShapeMap->end() )
3258 : {
3259 0 : (*aIter).second = xAcc;
3260 : }
3261 : else
3262 : {
3263 0 : SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
3264 0 : mpShapeMap->insert( aEntry );
3265 : }
3266 0 : }
3267 : }
3268 :
3269 0 : SwRect aEmptyRect;
3270 0 : InvalidatePosOrSize( nullptr, pObj, nullptr, aEmptyRect );
3271 :
3272 0 : return true;
3273 : }
3274 :
3275 : //Get the accessible control shape from the model object, here model object is with XPropertySet type
3276 0 : ::accessibility::AccessibleControlShape * SwAccessibleMap::GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet* pSet) throw (::com::sun::star::uno::RuntimeException)
3277 : {
3278 0 : if( mpShapeMap )
3279 : {
3280 0 : SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->cbegin();
3281 0 : SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->cend();
3282 0 : while( aIter != aEndIter)
3283 : {
3284 0 : uno::Reference < XAccessible > xAcc( (*aIter).second );
3285 : ::accessibility::AccessibleShape *pAccShape =
3286 0 : static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
3287 0 : if(pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
3288 : {
3289 0 : ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape);
3290 0 : if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
3291 0 : return pCtlAccShape;
3292 : }
3293 0 : ++aIter;
3294 0 : }
3295 : }
3296 0 : return NULL;
3297 : }
3298 :
3299 : ::com::sun::star::uno::Reference< XAccessible >
3300 0 : SwAccessibleMap::GetAccessibleCaption (const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >&)
3301 : throw (::com::sun::star::uno::RuntimeException)
3302 : {
3303 0 : return NULL;
3304 : }
3305 :
3306 0 : Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
3307 : {
3308 0 : Point aPoint;
3309 0 : if( GetShell()->GetWin() )
3310 : {
3311 0 : MapMode aMapMode;
3312 0 : GetMapMode( rPoint, aMapMode );
3313 0 : aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
3314 : }
3315 0 : return aPoint;
3316 : }
3317 :
3318 12404 : static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
3319 : long aRefValue, bool bToLower)
3320 : {
3321 12404 : long aResult = aCoarseValue;
3322 :
3323 12404 : if (bToLower)
3324 : {
3325 6202 : if (aFineValue < aRefValue)
3326 2396 : aResult -= 1;
3327 : }
3328 : else
3329 : {
3330 6202 : if (aFineValue > aRefValue)
3331 190 : aResult += 1;
3332 : }
3333 :
3334 12404 : return aResult;
3335 : }
3336 :
3337 3101 : static inline void lcl_CorrectRectangle(Rectangle & rRect,
3338 : const Rectangle & rSource,
3339 : const Rectangle & rInGrid)
3340 : {
3341 6202 : rRect.Left() = lcl_CorrectCoarseValue(rRect.Left(), rSource.Left(),
3342 6202 : rInGrid.Left(), false);
3343 6202 : rRect.Top() = lcl_CorrectCoarseValue(rRect.Top(), rSource.Top(),
3344 6202 : rInGrid.Top(), false);
3345 6202 : rRect.Right() = lcl_CorrectCoarseValue(rRect.Right(), rSource.Right(),
3346 6202 : rInGrid.Right(), true);
3347 6202 : rRect.Bottom() = lcl_CorrectCoarseValue(rRect.Bottom(), rSource.Bottom(),
3348 6202 : rInGrid.Bottom(), true);
3349 3101 : }
3350 :
3351 3101 : Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
3352 : {
3353 3101 : Rectangle aRect;
3354 3101 : if( GetShell()->GetWin() )
3355 : {
3356 3101 : MapMode aMapMode;
3357 3101 : GetMapMode( rRect.TopLeft(), aMapMode );
3358 3101 : aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
3359 :
3360 3101 : Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
3361 3101 : lcl_CorrectRectangle(aRect, rRect, aTmpRect);
3362 : }
3363 :
3364 3101 : return aRect;
3365 : }
3366 :
3367 : /** get mapping mode for LogicToPixel and PixelToLogic conversions
3368 :
3369 : Method returns mapping mode of current output device and adjusts it,
3370 : if the shell is in page/print preview.
3371 : Necessary, because <PreviewAdjust(..)> changes mapping mode at current
3372 : output device for mapping logic document positions to page preview window
3373 : positions and vice versa and doesn't take care to recover its changes.
3374 : */
3375 3101 : void SwAccessibleMap::GetMapMode( const Point& _rPoint,
3376 : MapMode& _orMapMode ) const
3377 : {
3378 3101 : MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
3379 3101 : if( GetShell()->IsPreview() )
3380 : {
3381 : OSL_ENSURE( mpPreview != NULL, "need preview data" );
3382 :
3383 0 : mpPreview->AdjustMapMode( aMapMode, _rPoint );
3384 : }
3385 3101 : _orMapMode = aMapMode;
3386 3101 : }
3387 :
3388 0 : Size SwAccessibleMap::GetPreviewPageSize( sal_uInt16 _nPreviewPageNum ) const
3389 : {
3390 : OSL_ENSURE( mpVSh->IsPreview(), "no page preview accessible." );
3391 : OSL_ENSURE( mpVSh->IsPreview() && ( mpPreview != NULL ),
3392 : "missing accessible preview data at page preview" );
3393 0 : if ( mpVSh->IsPreview() && ( mpPreview != NULL ) )
3394 : {
3395 0 : return mpVSh->PagePreviewLayout()->GetPreviewPageSizeByPageNum( _nPreviewPageNum );
3396 : }
3397 : else
3398 : {
3399 0 : return Size( 0, 0 );
3400 : }
3401 : }
3402 :
3403 : /** method to build up a new data structure of the accessible paragraphs,
3404 : which have a selection
3405 : Important note: method has to be used inside a mutual exclusive section
3406 : */
3407 83 : SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
3408 : {
3409 : // no accessible contexts, no selection
3410 83 : if ( !mpFrmMap )
3411 : {
3412 0 : return nullptr;
3413 : }
3414 :
3415 : // get cursor as an instance of its base class <SwPaM>
3416 83 : SwPaM* pCrsr( nullptr );
3417 : {
3418 83 : SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
3419 83 : if ( pCrsrShell )
3420 : {
3421 83 : SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
3422 249 : if ( !pFEShell ||
3423 166 : ( !pFEShell->IsFrmSelected() &&
3424 83 : pFEShell->IsObjSelected() == 0 ) )
3425 : {
3426 : // get cursor without updating an existing table cursor.
3427 83 : pCrsr = pCrsrShell->GetCrsr( false );
3428 : }
3429 : }
3430 : }
3431 : // no cursor, no selection
3432 83 : if ( !pCrsr )
3433 : {
3434 0 : return nullptr;
3435 : }
3436 :
3437 83 : SwAccessibleSelectedParas_Impl* pRetSelectedParas( nullptr );
3438 :
3439 : // loop on all cursors
3440 83 : SwPaM* pRingStart = pCrsr;
3441 98 : do {
3442 :
3443 : // for a selection the cursor has to have a mark.
3444 : // for safety reasons assure that point and mark are in text nodes
3445 219 : if ( pCrsr->HasMark() &&
3446 121 : pCrsr->GetPoint()->nNode.GetNode().IsTextNode() &&
3447 23 : pCrsr->GetMark()->nNode.GetNode().IsTextNode() )
3448 : {
3449 23 : SwPosition* pStartPos = pCrsr->Start();
3450 23 : SwPosition* pEndPos = pCrsr->End();
3451 : // loop on all text nodes inside the selection
3452 23 : SwNodeIndex aIdx( pStartPos->nNode );
3453 46 : for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
3454 : {
3455 23 : SwTextNode* pTextNode( aIdx.GetNode().GetTextNode() );
3456 23 : if ( pTextNode )
3457 : {
3458 : // loop on all text frames registered at the text node.
3459 23 : SwIterator<SwTextFrm,SwTextNode> aIter( *pTextNode );
3460 46 : for( SwTextFrm* pTextFrm = aIter.First(); pTextFrm; pTextFrm = aIter.Next() )
3461 : {
3462 23 : uno::WeakReference < XAccessible > xWeakAcc;
3463 : SwAccessibleContextMap_Impl::iterator aMapIter =
3464 23 : mpFrmMap->find( pTextFrm );
3465 23 : if( aMapIter != mpFrmMap->end() )
3466 : {
3467 0 : xWeakAcc = (*aMapIter).second;
3468 : SwAccessibleParaSelection aDataEntry(
3469 0 : pTextNode == &(pStartPos->nNode.GetNode())
3470 0 : ? pStartPos->nContent.GetIndex()
3471 : : 0,
3472 0 : pTextNode == &(pEndPos->nNode.GetNode())
3473 0 : ? pEndPos->nContent.GetIndex()
3474 0 : : -1 );
3475 : SwAccessibleSelectedParas_Impl::value_type
3476 0 : aEntry( xWeakAcc, aDataEntry );
3477 0 : if ( !pRetSelectedParas )
3478 : {
3479 : pRetSelectedParas =
3480 0 : new SwAccessibleSelectedParas_Impl;
3481 : }
3482 0 : pRetSelectedParas->insert( aEntry );
3483 : }
3484 46 : }
3485 : }
3486 23 : }
3487 : }
3488 :
3489 : // prepare next turn: get next cursor in ring
3490 98 : pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3491 : } while ( pCrsr != pRingStart );
3492 :
3493 83 : return pRetSelectedParas;
3494 : }
3495 :
3496 83 : void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
3497 : {
3498 83 : osl::MutexGuard aGuard( maMutex );
3499 :
3500 : // keep previously known selected paragraphs
3501 83 : SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
3502 :
3503 : // determine currently selected paragraphs
3504 83 : mpSelectedParas = _BuildSelectedParas();
3505 :
3506 : // compare currently selected paragraphs with the previously selected
3507 : // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
3508 : // first, search for new and changed selections.
3509 : // on the run remove selections from previously known ones, if they are
3510 : // also in the current ones.
3511 83 : if ( mpSelectedParas )
3512 : {
3513 0 : SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
3514 0 : for ( ; aIter != mpSelectedParas->end(); ++aIter )
3515 : {
3516 0 : bool bSubmitEvent( false );
3517 0 : if ( !pPrevSelectedParas )
3518 : {
3519 : // new selection
3520 0 : bSubmitEvent = true;
3521 : }
3522 : else
3523 : {
3524 : SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
3525 0 : pPrevSelectedParas->find( (*aIter).first );
3526 0 : if ( aPrevSelected != pPrevSelectedParas->end() )
3527 : {
3528 : // check, if selection has changed
3529 0 : if ( (*aIter).second.nStartOfSelection !=
3530 0 : (*aPrevSelected).second.nStartOfSelection ||
3531 0 : (*aIter).second.nEndOfSelection !=
3532 0 : (*aPrevSelected).second.nEndOfSelection )
3533 : {
3534 : // changed selection
3535 0 : bSubmitEvent = true;
3536 : }
3537 0 : pPrevSelectedParas->erase( aPrevSelected );
3538 : }
3539 : else
3540 : {
3541 : // new selection
3542 0 : bSubmitEvent = true;
3543 : }
3544 : }
3545 :
3546 0 : if ( bSubmitEvent )
3547 : {
3548 0 : uno::Reference < XAccessible > xAcc( (*aIter).first );
3549 0 : if ( xAcc.is() )
3550 : {
3551 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
3552 0 : static_cast<SwAccessibleContext*>( xAcc.get() ) );
3553 0 : if ( xAccImpl.is() && xAccImpl->GetFrm() )
3554 : {
3555 : const SwTextFrm* pTextFrm(
3556 0 : dynamic_cast<const SwTextFrm*>(xAccImpl->GetFrm()) );
3557 : OSL_ENSURE( pTextFrm,
3558 : "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame" );
3559 0 : if ( pTextFrm )
3560 : {
3561 0 : InvalidateParaTextSelection( *pTextFrm );
3562 : }
3563 0 : }
3564 0 : }
3565 : }
3566 : }
3567 : }
3568 :
3569 : // second, handle previous selections - after the first step the data
3570 : // structure of the previously known only contains the 'old' selections
3571 83 : if ( pPrevSelectedParas )
3572 : {
3573 0 : SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
3574 0 : for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
3575 : {
3576 0 : uno::Reference < XAccessible > xAcc( (*aIter).first );
3577 0 : if ( xAcc.is() )
3578 : {
3579 : ::rtl::Reference < SwAccessibleContext > xAccImpl(
3580 0 : static_cast<SwAccessibleContext*>( xAcc.get() ) );
3581 0 : if ( xAccImpl.is() && xAccImpl->GetFrm() )
3582 : {
3583 : const SwTextFrm* pTextFrm(
3584 0 : dynamic_cast<const SwTextFrm*>(xAccImpl->GetFrm()) );
3585 : OSL_ENSURE( pTextFrm,
3586 : "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexpected type of frame" );
3587 0 : if ( pTextFrm )
3588 : {
3589 0 : InvalidateParaTextSelection( *pTextFrm );
3590 : }
3591 0 : }
3592 : }
3593 0 : }
3594 :
3595 0 : delete pPrevSelectedParas;
3596 83 : }
3597 83 : }
3598 :
3599 254 : const SwRect& SwAccessibleMap::GetVisArea() const
3600 : {
3601 : OSL_ENSURE( !GetShell()->IsPreview() || (mpPreview != NULL),
3602 : "preview without preview data?" );
3603 :
3604 254 : return GetShell()->IsPreview()
3605 0 : ? mpPreview->GetVisArea()
3606 254 : : GetShell()->VisArea();
3607 : }
3608 :
3609 108 : bool SwAccessibleMap::IsDocumentSelAll()
3610 : {
3611 108 : return GetShell()->GetDoc()->IsPrepareSelAll();
3612 177 : }
3613 :
3614 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|