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