1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_editeng.hxx" 30 31 //------------------------------------------------------------------------ 32 // 33 // Global header 34 // 35 //------------------------------------------------------------------------ 36 #include <com/sun/star/uno/Any.hxx> 37 #include <com/sun/star/uno/Reference.hxx> 38 #include <cppuhelper/weakref.hxx> 39 #include <com/sun/star/accessibility/XAccessible.hpp> 40 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 41 42 //------------------------------------------------------------------------ 43 // 44 // Project-local header 45 // 46 //------------------------------------------------------------------------ 47 48 #include <editeng/unoedhlp.hxx> 49 #include <editeng/unopracc.hxx> 50 #include <editeng/unoedsrc.hxx> 51 #include "editeng/AccessibleParaManager.hxx" 52 #include "editeng/AccessibleEditableTextPara.hxx" 53 54 55 using namespace ::com::sun::star; 56 using namespace ::com::sun::star::accessibility; 57 58 59 60 namespace accessibility 61 { 62 AccessibleParaManager::AccessibleParaManager() : 63 maChildren(1), 64 maEEOffset( 0, 0 ), 65 mnFocusedChild( -1 ), 66 mbActive( sal_False ) 67 { 68 } 69 70 AccessibleParaManager::~AccessibleParaManager() 71 { 72 // owner is responsible for possible child defuncs 73 } 74 75 void AccessibleParaManager::SetAdditionalChildStates( const VectorOfStates& rChildStates ) 76 { 77 maChildStates = rChildStates; 78 } 79 80 const AccessibleParaManager::VectorOfStates& AccessibleParaManager::GetAdditionalChildStates() const 81 { 82 return maChildStates; 83 } 84 85 void AccessibleParaManager::SetNum( sal_Int32 nNumParas ) 86 { 87 if( (size_t)nNumParas < maChildren.size() ) 88 Release( nNumParas, maChildren.size() ); 89 90 maChildren.resize( nNumParas ); 91 92 if( mnFocusedChild >= nNumParas ) 93 mnFocusedChild = -1; 94 } 95 96 sal_uInt32 AccessibleParaManager::GetNum() const 97 { 98 return maChildren.size(); 99 } 100 101 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin() 102 { 103 return maChildren.begin(); 104 } 105 106 AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end() 107 { 108 return maChildren.end(); 109 } 110 111 AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::begin() const 112 { 113 return maChildren.begin(); 114 } 115 116 AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::end() const 117 { 118 return maChildren.end(); 119 } 120 121 void AccessibleParaManager::Release( sal_uInt32 nPara ) 122 { 123 DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::Release: invalid index" ); 124 125 if( maChildren.size() > nPara ) 126 { 127 ShutdownPara( GetChild( nPara ) ); 128 129 // clear reference and rect 130 maChildren[ nPara ] = WeakChild(); 131 } 132 } 133 134 void AccessibleParaManager::FireEvent( sal_uInt32 nPara, 135 const sal_Int16 nEventId, 136 const uno::Any& rNewValue, 137 const uno::Any& rOldValue ) const 138 { 139 DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::FireEvent: invalid index" ); 140 141 if( maChildren.size() > nPara ) 142 { 143 WeakPara::HardRefType maChild( GetChild( nPara ).first.get() ); 144 if( maChild.is() ) 145 maChild->FireEvent( nEventId, rNewValue, rOldValue ); 146 } 147 } 148 149 sal_Bool AccessibleParaManager::IsReferencable( WeakPara::HardRefType aChild ) 150 { 151 return aChild.is(); 152 } 153 154 sal_Bool AccessibleParaManager::IsReferencable( sal_uInt32 nChild ) const 155 { 156 DBG_ASSERT( maChildren.size() > nChild, "AccessibleParaManager::IsReferencable: invalid index" ); 157 158 if( maChildren.size() > nChild ) 159 { 160 // retrieve hard reference from weak one 161 return IsReferencable( GetChild( nChild ).first.get() ); 162 } 163 else 164 { 165 return sal_False; 166 } 167 } 168 169 AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_uInt32 nParagraphIndex ) const 170 { 171 DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::GetChild: invalid index" ); 172 173 if( maChildren.size() > nParagraphIndex ) 174 { 175 return maChildren[ nParagraphIndex ]; 176 } 177 else 178 { 179 return WeakChild(); 180 } 181 } 182 183 AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild, 184 const uno::Reference< XAccessible >& xFrontEnd, 185 SvxEditSourceAdapter& rEditSource, 186 sal_uInt32 nParagraphIndex ) 187 { 188 DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::CreateChild: invalid index" ); 189 190 if( maChildren.size() > nParagraphIndex ) 191 { 192 // retrieve hard reference from weak one 193 WeakPara::HardRefType aChild( GetChild( nParagraphIndex ).first.get() ); 194 195 if( !IsReferencable( nParagraphIndex ) ) 196 { 197 // there is no hard reference available, create object then 198 // --> OD 2006-01-11 #i27138# 199 AccessibleEditableTextPara* pChild = new AccessibleEditableTextPara( xFrontEnd, this ); 200 // <-- 201 uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY ); 202 203 if( !xChild.is() ) 204 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), xFrontEnd); 205 206 aChild = WeakPara::HardRefType( xChild, pChild ); 207 208 InitChild( *aChild, rEditSource, nChild, nParagraphIndex ); 209 210 maChildren[ nParagraphIndex ] = WeakChild( aChild, pChild->getBounds() ); 211 } 212 213 return Child( aChild.getRef(), GetChild( nParagraphIndex ).second ); 214 } 215 else 216 { 217 return Child(); 218 } 219 } 220 221 void AccessibleParaManager::SetEEOffset( const Point& rOffset ) 222 { 223 maEEOffset = rOffset; 224 225 MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset ); 226 ::std::for_each( begin(), end(), aAdapter ); 227 } 228 229 void AccessibleParaManager::SetActive( sal_Bool bActive ) 230 { 231 mbActive = bActive; 232 233 if( bActive ) 234 { 235 SetState( AccessibleStateType::ACTIVE ); 236 SetState( AccessibleStateType::EDITABLE ); 237 } 238 else 239 { 240 UnSetState( AccessibleStateType::ACTIVE ); 241 UnSetState( AccessibleStateType::EDITABLE ); 242 } 243 } 244 245 void AccessibleParaManager::SetFocus( sal_Int32 nChild ) 246 { 247 if( mnFocusedChild != -1 ) 248 UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED ); 249 250 mnFocusedChild = nChild; 251 252 if( mnFocusedChild != -1 ) 253 SetState( mnFocusedChild, AccessibleStateType::FOCUSED ); 254 } 255 256 void AccessibleParaManager::InitChild( AccessibleEditableTextPara& rChild, 257 SvxEditSourceAdapter& rEditSource, 258 sal_Int32 nChild, 259 sal_uInt32 nParagraphIndex ) const 260 { 261 rChild.SetEditSource( &rEditSource ); 262 rChild.SetIndexInParent( nChild ); 263 rChild.SetParagraphIndex( nParagraphIndex ); 264 265 rChild.SetEEOffset( maEEOffset ); 266 267 if( mbActive ) 268 { 269 rChild.SetState( AccessibleStateType::ACTIVE ); 270 rChild.SetState( AccessibleStateType::EDITABLE ); 271 } 272 273 if( mnFocusedChild == static_cast<sal_Int32>(nParagraphIndex) ) 274 rChild.SetState( AccessibleStateType::FOCUSED ); 275 276 // add states passed from outside 277 for( VectorOfStates::const_iterator aIt = maChildStates.begin(), aEnd = maChildStates.end(); aIt != aEnd; ++aIt ) 278 rChild.SetState( *aIt ); 279 } 280 281 void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int16 nStateId ) 282 { 283 MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::SetState, 284 nStateId ); 285 aFunc( GetChild(nChild) ); 286 } 287 288 void AccessibleParaManager::SetState( const sal_Int16 nStateId ) 289 { 290 ::std::for_each( begin(), end(), 291 MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::SetState, 292 nStateId ) ); 293 } 294 295 void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ) 296 { 297 MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::UnSetState, 298 nStateId ); 299 aFunc( GetChild(nChild) ); 300 } 301 302 void AccessibleParaManager::UnSetState( const sal_Int16 nStateId ) 303 { 304 ::std::for_each( begin(), end(), 305 MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::UnSetState, 306 nStateId ) ); 307 } 308 309 void AccessibleParaManager::SetEditSource( SvxEditSourceAdapter* pEditSource ) 310 { 311 MemFunAdapter< SvxEditSourceAdapter* > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEditSource, pEditSource ); 312 ::std::for_each( begin(), end(), aAdapter ); 313 } 314 315 // not generic yet, no arguments... 316 class AccessibleParaManager_DisposeChildren : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > 317 { 318 public: 319 AccessibleParaManager_DisposeChildren() {} 320 void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) 321 { 322 rPara.Dispose(); 323 } 324 }; 325 326 void AccessibleParaManager::Dispose() 327 { 328 AccessibleParaManager_DisposeChildren aFunctor; 329 330 ::std::for_each( begin(), end(), 331 WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) ); 332 } 333 334 // not generic yet, too many method arguments... 335 class StateChangeEvent : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > 336 { 337 public: 338 typedef void return_type; 339 StateChangeEvent( const sal_Int16 nEventId, 340 const uno::Any& rNewValue, 341 const uno::Any& rOldValue ) : 342 mnEventId( nEventId ), 343 mrNewValue( rNewValue ), 344 mrOldValue( rOldValue ) {} 345 void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) 346 { 347 rPara.FireEvent( mnEventId, mrNewValue, mrOldValue ); 348 } 349 350 private: 351 const sal_Int16 mnEventId; 352 const uno::Any& mrNewValue; 353 const uno::Any& mrOldValue; 354 }; 355 356 void AccessibleParaManager::FireEvent( sal_uInt32 nStartPara, 357 sal_uInt32 nEndPara, 358 const sal_Int16 nEventId, 359 const uno::Any& rNewValue, 360 const uno::Any& rOldValue ) const 361 { 362 DBG_ASSERT( maChildren.size() > nStartPara && 363 maChildren.size() >= nEndPara , "AccessibleParaManager::FireEvent: invalid index" ); 364 365 if( maChildren.size() > nStartPara && 366 maChildren.size() >= nEndPara ) 367 { 368 VectorOfChildren::const_iterator front = maChildren.begin(); 369 VectorOfChildren::const_iterator back = front; 370 371 ::std::advance( front, nStartPara ); 372 ::std::advance( back, nEndPara ); 373 374 StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue ); 375 376 ::std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) ); 377 } 378 } 379 380 class ReleaseChild : public ::std::unary_function< const AccessibleParaManager::WeakChild&, AccessibleParaManager::WeakChild > 381 { 382 public: 383 AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara ) 384 { 385 AccessibleParaManager::ShutdownPara( rPara ); 386 387 // clear reference 388 return AccessibleParaManager::WeakChild(); 389 } 390 }; 391 392 void AccessibleParaManager::Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara ) 393 { 394 DBG_ASSERT( maChildren.size() > nStartPara && 395 maChildren.size() >= nEndPara, "AccessibleParaManager::Release: invalid index" ); 396 397 if( maChildren.size() > nStartPara && 398 maChildren.size() >= nEndPara ) 399 { 400 VectorOfChildren::iterator front = maChildren.begin(); 401 VectorOfChildren::iterator back = front; 402 403 ::std::advance( front, nStartPara ); 404 ::std::advance( back, nEndPara ); 405 406 ::std::transform( front, back, front, ReleaseChild() ); 407 } 408 } 409 410 void AccessibleParaManager::ShutdownPara( const WeakChild& rChild ) 411 { 412 WeakPara::HardRefType aChild( rChild.first.get() ); 413 414 if( IsReferencable( aChild ) ) 415 aChild->SetEditSource( NULL ); 416 } 417 418 } 419 420 //------------------------------------------------------------------------ 421