LibreOffice Module editeng (master) 1
AccessibleParaManager.cxx
Go to the documentation of this file.
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
21// Global header
22
23
24#include <com/sun/star/uno/Any.hxx>
25#include <com/sun/star/uno/Reference.hxx>
26#include <o3tl/safeint.hxx>
27#include <sal/log.hxx>
28#include <tools/debug.hxx>
29#include <com/sun/star/accessibility/XAccessible.hpp>
30#include <com/sun/star/accessibility/AccessibleStateType.hpp>
31
32
33// Project-local header
34
35
38
39
40using namespace ::com::sun::star;
41using namespace ::com::sun::star::accessibility;
42
43
44namespace accessibility
45{
46 AccessibleParaManager::AccessibleParaManager() :
47 maChildren(1),
48 mnChildStates( 0 ),
49 maEEOffset( 0, 0 ),
50 mnFocusedChild( -1 ),
51 mbActive( false )
52 {
53 }
54
55 AccessibleParaManager::~AccessibleParaManager()
56 {
57 // owner is responsible for possible child death
58 }
59
60 void AccessibleParaManager::SetAdditionalChildStates( sal_Int64 nChildStates )
61 {
62 mnChildStates = nChildStates;
63 }
64
65 void AccessibleParaManager::SetNum( sal_Int32 nNumParas )
66 {
67 if( o3tl::make_unsigned(nNumParas) < maChildren.size() )
68 Release( nNumParas, maChildren.size() );
69
70 maChildren.resize( nNumParas );
71
72 if( mnFocusedChild >= nNumParas )
73 mnFocusedChild = -1;
74 }
75
76 sal_Int32 AccessibleParaManager::GetNum() const
77 {
78 size_t nSize = maChildren.size();
79 if (nSize > SAL_MAX_INT32)
80 {
81 SAL_WARN( "editeng", "AccessibleParaManager::GetNum - overflow " << nSize);
82 return SAL_MAX_INT32;
83 }
84 return static_cast<sal_Int32>(nSize);
85 }
86
87 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin()
88 {
89 return maChildren.begin();
90 }
91
92 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end()
93 {
94 return maChildren.end();
95 }
96
97 void AccessibleParaManager::FireEvent( sal_Int32 nPara,
98 const sal_Int16 nEventId ) const
99 {
100 DBG_ASSERT( 0 <= nPara && maChildren.size() > o3tl::make_unsigned(nPara),
101 "AccessibleParaManager::FireEvent: invalid index" );
102
103 if( 0 <= nPara && maChildren.size() > o3tl::make_unsigned(nPara) )
104 {
105 auto aChild( GetChild( nPara ).first.get() );
106 if( aChild.is() )
107 aChild->FireEvent( nEventId );
108 }
109 }
110
111 bool AccessibleParaManager::IsReferencable(
113 {
114 return aChild.is();
115 }
116
117 bool AccessibleParaManager::IsReferencable( sal_Int32 nChild ) const
118 {
119 DBG_ASSERT( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild),
120 "AccessibleParaManager::IsReferencable: invalid index" );
121
122 if( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild) )
123 {
124 // retrieve hard reference from weak one
125 return IsReferencable( GetChild( nChild ).first.get() );
126 }
127 else
128 {
129 return false;
130 }
131 }
132
133 AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_Int32 nParagraphIndex ) const
134 {
135 DBG_ASSERT( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex),
136 "AccessibleParaManager::GetChild: invalid index" );
137
138 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
139 {
140 return maChildren[ nParagraphIndex ];
141 }
142 else
143 {
144 return WeakChild();
145 }
146 }
147
148 bool AccessibleParaManager::HasCreatedChild( sal_Int32 nParagraphIndex ) const
149 {
150 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
151 {
152 auto const & rChild = maChildren[ nParagraphIndex ];
153 return rChild.second.Width != 0 || rChild.second.Height != 0;
154 }
155 else
156 return false;
157 }
158
159 AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild,
160 const uno::Reference< XAccessible >& xFrontEnd,
161 SvxEditSourceAdapter& rEditSource,
162 sal_Int32 nParagraphIndex )
163 {
164 DBG_ASSERT( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex),
165 "AccessibleParaManager::CreateChild: invalid index" );
166
167 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
168 {
169 // retrieve hard reference from weak one
170 auto aChild( GetChild( nParagraphIndex ).first.get() );
171
172 if( !IsReferencable( nParagraphIndex ) )
173 {
174 // there is no hard reference available, create object then
175 // #i27138#
176 aChild = new AccessibleEditableTextPara(xFrontEnd, this);
177
178 InitChild( *aChild, rEditSource, nChild, nParagraphIndex );
179
180 maChildren[ nParagraphIndex ] = WeakChild( aChild, aChild->getBounds() );
181 }
182
183 return Child( aChild.get(), GetChild( nParagraphIndex ).second );
184 }
185 else
186 {
187 return Child();
188 }
189 }
190
191 void AccessibleParaManager::SetEEOffset( const Point& rOffset )
192 {
193 maEEOffset = rOffset;
194
195 MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset );
196 std::for_each( begin(), end(), aAdapter );
197 }
198
199 void AccessibleParaManager::SetActive( bool bActive )
200 {
201 mbActive = bActive;
202
203 if( bActive )
204 {
205 SetState( AccessibleStateType::ACTIVE );
206 SetState( AccessibleStateType::EDITABLE );
207 }
208 else
209 {
210 UnSetState( AccessibleStateType::ACTIVE );
211 UnSetState( AccessibleStateType::EDITABLE );
212 }
213 }
214
215 void AccessibleParaManager::SetFocus( sal_Int32 nChild )
216 {
217 if( mnFocusedChild != -1 )
218 UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED );
219
220 mnFocusedChild = nChild;
221
222 if( mnFocusedChild != -1 )
223 SetState( mnFocusedChild, AccessibleStateType::FOCUSED );
224 }
225
226 void AccessibleParaManager::InitChild( AccessibleEditableTextPara& rChild,
227 SvxEditSourceAdapter& rEditSource,
228 sal_Int32 nChild,
229 sal_Int32 nParagraphIndex ) const
230 {
231 rChild.SetEditSource( &rEditSource );
232 rChild.SetIndexInParent( nChild );
233 rChild.SetParagraphIndex( nParagraphIndex );
234
235 rChild.SetEEOffset( maEEOffset );
236
237 if( mbActive )
238 {
239 rChild.SetState( AccessibleStateType::ACTIVE );
240 rChild.SetState( AccessibleStateType::EDITABLE );
241 }
242
243 if( mnFocusedChild == nParagraphIndex )
244 rChild.SetState( AccessibleStateType::FOCUSED );
245
246 // add states passed from outside
247 for (int i=0; i<63; i++)
248 {
249 sal_Int64 nState = sal_Int64(1) << i;
250 if ( nState & mnChildStates )
251 rChild.SetState( nState );
252 }
253 }
254
255 void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int64 nStateId )
256 {
257 MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::SetState,
258 nStateId );
259 aFunc( GetChild(nChild) );
260 }
261
262 void AccessibleParaManager::SetState( const sal_Int64 nStateId )
263 {
264 std::for_each( begin(), end(),
265 MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::SetState,
266 nStateId ) );
267 }
268
269 void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int64 nStateId )
270 {
271 MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::UnSetState,
272 nStateId );
273 aFunc( GetChild(nChild) );
274 }
275
276 void AccessibleParaManager::UnSetState( const sal_Int64 nStateId )
277 {
278 std::for_each( begin(), end(),
279 MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::UnSetState,
280 nStateId ) );
281 }
282
283 namespace {
284
285 // not generic yet, no arguments...
286 class AccessibleParaManager_DisposeChildren
287 {
288 public:
289 AccessibleParaManager_DisposeChildren() {}
290 void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
291 {
292 rPara.Dispose();
293 }
294 };
295
296 }
297
298 void AccessibleParaManager::Dispose()
299 {
300 AccessibleParaManager_DisposeChildren aFunctor;
301
302 std::for_each( begin(), end(),
303 WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) );
304 }
305
306 namespace {
307
308 // not generic yet, too many method arguments...
309 class StateChangeEvent
310 {
311 public:
312 StateChangeEvent( const sal_Int16 nEventId,
313 const uno::Any& rNewValue,
314 const uno::Any& rOldValue ) :
315 mnEventId( nEventId ),
316 mrNewValue( rNewValue ),
317 mrOldValue( rOldValue ) {}
318 void operator()( ::accessibility::AccessibleEditableTextPara const & rPara )
319 {
320 rPara.FireEvent( mnEventId, mrNewValue, mrOldValue );
321 }
322
323 private:
324 const sal_Int16 mnEventId;
327 };
328
329 }
330
331 void AccessibleParaManager::FireEvent( sal_Int32 nStartPara,
332 sal_Int32 nEndPara,
333 const sal_Int16 nEventId,
334 const uno::Any& rNewValue,
335 const uno::Any& rOldValue ) const
336 {
337 DBG_ASSERT( 0 <= nStartPara && 0 <= nEndPara &&
338 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
339 maChildren.size() >= o3tl::make_unsigned(nEndPara) &&
340 nEndPara >= nStartPara, "AccessibleParaManager::FireEvent: invalid index" );
341
342
343 if( 0 <= nStartPara && 0 <= nEndPara &&
344 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
345 maChildren.size() >= o3tl::make_unsigned(nEndPara) &&
346 nEndPara >= nStartPara )
347 {
348 VectorOfChildren::const_iterator front = maChildren.begin();
349 VectorOfChildren::const_iterator back = front;
350
351 std::advance( front, nStartPara );
352 std::advance( back, nEndPara );
353
354 StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue );
355
356 std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) );
357 }
358 }
359
360 namespace {
361
362 class ReleaseChild
363 {
364 public:
365 AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara )
366 {
367 AccessibleParaManager::ShutdownPara( rPara );
368
369 // clear reference
370 return AccessibleParaManager::WeakChild();
371 }
372 };
373
374 }
375
376 void AccessibleParaManager::Release( sal_Int32 nStartPara, sal_Int32 nEndPara )
377 {
378 DBG_ASSERT( 0 <= nStartPara && 0 <= nEndPara &&
379 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
380 maChildren.size() >= o3tl::make_unsigned(nEndPara),
381 "AccessibleParaManager::Release: invalid index" );
382
383 if( 0 <= nStartPara && 0 <= nEndPara &&
384 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
385 maChildren.size() >= o3tl::make_unsigned(nEndPara) )
386 {
387 VectorOfChildren::iterator front = maChildren.begin();
388 VectorOfChildren::iterator back = front;
389
390 std::advance( front, nStartPara );
391 std::advance( back, nEndPara );
392
393 std::transform( front, back, front, ReleaseChild() );
394 }
395 }
396
397 void AccessibleParaManager::ShutdownPara( const WeakChild& rChild )
398 {
399 auto aChild( rChild.first.get() );
400
401 if( IsReferencable( aChild ) )
402 aChild->SetEditSource( nullptr );
403 }
404
405}
406
407
408/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_Int16 mnEventId
const uno::Any & mrNewValue
const uno::Any & mrOldValue
std::vector< Reference< XAnimationNode > > maChildren
#define DBG_ASSERT(sCon, aError)
sal_Int32 nState
#define SAL_WARN(area, stream)
int i
constexpr OUStringLiteral first
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
enumrange< T >::Iterator begin(enumrange< T >)
end
bool mbActive
#define SAL_MAX_INT32