Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / editeng / source / accessibility / AccessibleParaManager.cxx
blobc88f82d677097a9d8b073ffc1b2d741f93f055fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 // Global header
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>
33 // Project-local header
36 #include <editeng/AccessibleParaManager.hxx>
37 #include <editeng/AccessibleEditableTextPara.hxx>
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::accessibility;
44 namespace accessibility
46 AccessibleParaManager::AccessibleParaManager() :
47 maChildren(1),
48 mnChildStates( 0 ),
49 maEEOffset( 0, 0 ),
50 mnFocusedChild( -1 ),
51 mbActive( false )
55 AccessibleParaManager::~AccessibleParaManager()
57 // owner is responsible for possible child death
60 void AccessibleParaManager::SetAdditionalChildStates( sal_Int64 nChildStates )
62 mnChildStates = nChildStates;
65 void AccessibleParaManager::SetNum( sal_Int32 nNumParas )
67 if( o3tl::make_unsigned(nNumParas) < maChildren.size() )
68 Release( nNumParas, maChildren.size() );
70 maChildren.resize( nNumParas );
72 if( mnFocusedChild >= nNumParas )
73 mnFocusedChild = -1;
76 sal_Int32 AccessibleParaManager::GetNum() const
78 size_t nSize = maChildren.size();
79 if (nSize > SAL_MAX_INT32)
81 SAL_WARN( "editeng", "AccessibleParaManager::GetNum - overflow " << nSize);
82 return SAL_MAX_INT32;
84 return static_cast<sal_Int32>(nSize);
87 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin()
89 return maChildren.begin();
92 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end()
94 return maChildren.end();
97 void AccessibleParaManager::FireEvent( sal_Int32 nPara,
98 const sal_Int16 nEventId ) const
100 DBG_ASSERT( 0 <= nPara && maChildren.size() > o3tl::make_unsigned(nPara),
101 "AccessibleParaManager::FireEvent: invalid index" );
103 if( 0 <= nPara && maChildren.size() > o3tl::make_unsigned(nPara) )
105 auto aChild( GetChild( nPara ).first.get() );
106 if( aChild.is() )
107 aChild->FireEvent( nEventId );
111 bool AccessibleParaManager::IsReferencable(
112 rtl::Reference<AccessibleEditableTextPara> const & aChild)
114 return aChild.is();
117 bool AccessibleParaManager::IsReferencable( sal_Int32 nChild ) const
119 DBG_ASSERT( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild),
120 "AccessibleParaManager::IsReferencable: invalid index" );
122 if( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild) )
124 // retrieve hard reference from weak one
125 return IsReferencable( GetChild( nChild ).first.get() );
127 else
129 return false;
133 AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_Int32 nParagraphIndex ) const
135 DBG_ASSERT( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex),
136 "AccessibleParaManager::GetChild: invalid index" );
138 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
140 return maChildren[ nParagraphIndex ];
142 else
144 return WeakChild();
148 bool AccessibleParaManager::HasCreatedChild( sal_Int32 nParagraphIndex ) const
150 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
152 auto const & rChild = maChildren[ nParagraphIndex ];
153 return rChild.second.Width != 0 || rChild.second.Height != 0;
155 else
156 return false;
159 AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild,
160 const uno::Reference< XAccessible >& xFrontEnd,
161 SvxEditSourceAdapter& rEditSource,
162 sal_Int32 nParagraphIndex )
164 DBG_ASSERT( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex),
165 "AccessibleParaManager::CreateChild: invalid index" );
167 if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) )
169 // retrieve hard reference from weak one
170 auto aChild( GetChild( nParagraphIndex ).first.get() );
172 if( !IsReferencable( nParagraphIndex ) )
174 // there is no hard reference available, create object then
175 // #i27138#
176 aChild = new AccessibleEditableTextPara(xFrontEnd, this);
178 InitChild( *aChild, rEditSource, nChild, nParagraphIndex );
180 maChildren[ nParagraphIndex ] = WeakChild( aChild, aChild->getBounds() );
183 return Child( aChild.get(), GetChild( nParagraphIndex ).second );
185 else
187 return Child();
191 void AccessibleParaManager::SetEEOffset( const Point& rOffset )
193 maEEOffset = rOffset;
195 MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset );
196 std::for_each( begin(), end(), aAdapter );
199 void AccessibleParaManager::SetActive( bool bActive )
201 mbActive = bActive;
203 if( bActive )
205 SetState( AccessibleStateType::ACTIVE );
206 SetState( AccessibleStateType::EDITABLE );
208 else
210 UnSetState( AccessibleStateType::ACTIVE );
211 UnSetState( AccessibleStateType::EDITABLE );
215 void AccessibleParaManager::SetFocus( sal_Int32 nChild )
217 if( mnFocusedChild != -1 )
218 UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED );
220 mnFocusedChild = nChild;
222 if( mnFocusedChild != -1 )
223 SetState( mnFocusedChild, AccessibleStateType::FOCUSED );
226 void AccessibleParaManager::InitChild( AccessibleEditableTextPara& rChild,
227 SvxEditSourceAdapter& rEditSource,
228 sal_Int32 nChild,
229 sal_Int32 nParagraphIndex ) const
231 rChild.SetEditSource( &rEditSource );
232 rChild.SetIndexInParent( nChild );
233 rChild.SetParagraphIndex( nParagraphIndex );
235 rChild.SetEEOffset( maEEOffset );
237 if( mbActive )
239 rChild.SetState( AccessibleStateType::ACTIVE );
240 rChild.SetState( AccessibleStateType::EDITABLE );
243 if( mnFocusedChild == nParagraphIndex )
244 rChild.SetState( AccessibleStateType::FOCUSED );
246 // add states passed from outside
247 for (int i=0; i<63; i++)
249 sal_Int64 nState = sal_Int64(1) << i;
250 if ( nState & mnChildStates )
251 rChild.SetState( nState );
255 void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int64 nStateId )
257 MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::SetState,
258 nStateId );
259 aFunc( GetChild(nChild) );
262 void AccessibleParaManager::SetState( const sal_Int64 nStateId )
264 std::for_each( begin(), end(),
265 MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::SetState,
266 nStateId ) );
269 void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int64 nStateId )
271 MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::UnSetState,
272 nStateId );
273 aFunc( GetChild(nChild) );
276 void AccessibleParaManager::UnSetState( const sal_Int64 nStateId )
278 std::for_each( begin(), end(),
279 MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::UnSetState,
280 nStateId ) );
283 namespace {
285 // not generic yet, no arguments...
286 class AccessibleParaManager_DisposeChildren
288 public:
289 AccessibleParaManager_DisposeChildren() {}
290 void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
292 rPara.Dispose();
298 void AccessibleParaManager::Dispose()
300 AccessibleParaManager_DisposeChildren aFunctor;
302 std::for_each( begin(), end(),
303 WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) );
306 namespace {
308 // not generic yet, too many method arguments...
309 class StateChangeEvent
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 )
320 rPara.FireEvent( mnEventId, mrNewValue, mrOldValue );
323 private:
324 const sal_Int16 mnEventId;
325 const uno::Any& mrNewValue;
326 const uno::Any& mrOldValue;
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
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" );
343 if( 0 <= nStartPara && 0 <= nEndPara &&
344 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
345 maChildren.size() >= o3tl::make_unsigned(nEndPara) &&
346 nEndPara >= nStartPara )
348 VectorOfChildren::const_iterator front = maChildren.begin();
349 VectorOfChildren::const_iterator back = front;
351 std::advance( front, nStartPara );
352 std::advance( back, nEndPara );
354 StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue );
356 std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) );
360 namespace {
362 class ReleaseChild
364 public:
365 AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara )
367 AccessibleParaManager::ShutdownPara( rPara );
369 // clear reference
370 return AccessibleParaManager::WeakChild();
376 void AccessibleParaManager::Release( sal_Int32 nStartPara, sal_Int32 nEndPara )
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" );
383 if( 0 <= nStartPara && 0 <= nEndPara &&
384 maChildren.size() > o3tl::make_unsigned(nStartPara) &&
385 maChildren.size() >= o3tl::make_unsigned(nEndPara) )
387 VectorOfChildren::iterator front = maChildren.begin();
388 VectorOfChildren::iterator back = front;
390 std::advance( front, nStartPara );
391 std::advance( back, nEndPara );
393 std::transform( front, back, front, ReleaseChild() );
397 void AccessibleParaManager::ShutdownPara( const WeakChild& rChild )
399 auto aChild( rChild.first.get() );
401 if( IsReferencable( aChild ) )
402 aChild->SetEditSource( nullptr );
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */