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_sw.hxx" 30 31 32 #include <com/sun/star/accessibility/XAccessibleSelection.hpp> 33 #include <accselectionhelper.hxx> 34 35 #include <acccontext.hxx> 36 #include <accmap.hxx> 37 #include <svx/AccessibleShape.hxx> 38 #include <viewsh.hxx> 39 #include <fesh.hxx> 40 #include <vcl/svapp.hxx> // for SolarMutex 41 #include <tools/debug.hxx> 42 #include <flyfrm.hxx> 43 44 45 using namespace ::com::sun::star; 46 using namespace ::com::sun::star::uno; 47 48 using ::com::sun::star::accessibility::XAccessible; 49 using ::com::sun::star::accessibility::XAccessibleContext; 50 using ::com::sun::star::accessibility::XAccessibleSelection; 51 52 using namespace ::sw::access; 53 54 SwAccessibleSelectionHelper::SwAccessibleSelectionHelper( 55 SwAccessibleContext& rCtxt ) : 56 rContext( rCtxt ) 57 { 58 } 59 60 SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper() 61 { 62 } 63 64 SwFEShell* SwAccessibleSelectionHelper::GetFEShell() 65 { 66 DBG_ASSERT( rContext.GetMap() != NULL, "no map?" ); 67 ViewShell* pViewShell = rContext.GetMap()->GetShell(); 68 DBG_ASSERT( pViewShell != NULL, 69 "No view shell? Then what are you looking at?" ); 70 71 SwFEShell* pFEShell = NULL; 72 if( pViewShell->ISA( SwFEShell ) ) 73 { 74 pFEShell = static_cast<SwFEShell*>( pViewShell ); 75 } 76 77 return pFEShell; 78 } 79 80 void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException() 81 throw ( lang::IndexOutOfBoundsException ) 82 { 83 Reference < XAccessibleContext > xThis( &rContext ); 84 Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY ); 85 lang::IndexOutOfBoundsException aExcept( 86 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ), 87 xSelThis ); \ 88 throw aExcept; 89 } 90 91 92 //===== XAccessibleSelection ============================================ 93 94 void SwAccessibleSelectionHelper::selectAccessibleChild( 95 sal_Int32 nChildIndex ) 96 throw ( lang::IndexOutOfBoundsException, 97 RuntimeException ) 98 { 99 vos::OGuard aGuard(Application::GetSolarMutex()); 100 101 // Get the respective child as SwFrm (also do index checking), ... 102 const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()), 103 nChildIndex ); 104 if( !aChild.IsValid() ) 105 throwIndexOutOfBoundsException(); 106 107 // we can only select fly frames, so we ignore (should: return 108 // false) all other attempts at child selection 109 sal_Bool bRet = sal_False; 110 SwFEShell* pFEShell = GetFEShell(); 111 if( pFEShell != NULL ) 112 { 113 const SdrObject *pObj = aChild.GetDrawObject(); 114 if( pObj ) 115 { 116 bRet = rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm()); 117 } 118 } 119 // no frame shell, or no frame, or no fly frame -> can't select 120 121 // return bRet; 122 } 123 124 sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected( 125 sal_Int32 nChildIndex ) 126 throw ( lang::IndexOutOfBoundsException, 127 RuntimeException ) 128 { 129 vos::OGuard aGuard(Application::GetSolarMutex()); 130 131 // Get the respective child as SwFrm (also do index checking), ... 132 const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()), 133 nChildIndex ); 134 if( !aChild.IsValid() ) 135 throwIndexOutOfBoundsException(); 136 137 // ... and compare to the currently selected frame 138 sal_Bool bRet = sal_False; 139 SwFEShell* pFEShell = GetFEShell(); 140 if( pFEShell ) 141 { 142 if ( aChild.GetSwFrm() != 0 ) 143 { 144 bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm()); 145 } 146 else if ( aChild.GetDrawObject() ) 147 { 148 bRet = pFEShell->IsObjSelected( *aChild.GetDrawObject() ); 149 } 150 } 151 152 return bRet; 153 } 154 155 void SwAccessibleSelectionHelper::clearAccessibleSelection( ) 156 throw ( RuntimeException ) 157 { 158 // return sal_False // we can't deselect 159 } 160 161 void SwAccessibleSelectionHelper::selectAllAccessibleChildren( ) 162 throw ( RuntimeException ) 163 { 164 vos::OGuard aGuard(Application::GetSolarMutex()); 165 166 // We can select only one. So iterate over the children to find 167 // the first we can select, and select it. 168 169 SwFEShell* pFEShell = GetFEShell(); 170 if( pFEShell ) 171 { 172 ::std::list< SwAccessibleChild > aChildren; 173 rContext.GetChildren( *(rContext.GetMap()), aChildren ); 174 175 ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin(); 176 ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end(); 177 while( aIter != aEndIter ) 178 { 179 const SwAccessibleChild& rChild = *aIter; 180 const SdrObject* pObj = rChild.GetDrawObject(); 181 const SwFrm* pFrm = rChild.GetSwFrm(); 182 if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) ) 183 { 184 rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm ); 185 if( pFrm ) 186 break; 187 } 188 ++aIter; 189 } 190 } 191 } 192 193 sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) 194 throw ( RuntimeException ) 195 { 196 vos::OGuard aGuard(Application::GetSolarMutex()); 197 198 sal_Int32 nCount = 0; 199 // Only one frame can be selected at a time, and we only frames 200 // for selectable children. 201 SwFEShell* pFEShell = GetFEShell(); 202 if( pFEShell != 0 ) 203 { 204 const SwFlyFrm* pFlyFrm = pFEShell->GetCurrFlyFrm(); 205 if( pFlyFrm ) 206 { 207 if( rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) == 208 rContext.GetFrm() ) 209 { 210 nCount = 1; 211 } 212 } 213 else 214 { 215 sal_uInt16 nSelObjs = pFEShell->IsObjSelected(); 216 if( nSelObjs > 0 ) 217 { 218 ::std::list< SwAccessibleChild > aChildren; 219 rContext.GetChildren( *(rContext.GetMap()), aChildren ); 220 221 ::std::list< SwAccessibleChild >::const_iterator aIter = 222 aChildren.begin(); 223 ::std::list< SwAccessibleChild >::const_iterator aEndIter = 224 aChildren.end(); 225 while( aIter != aEndIter && nCount < nSelObjs ) 226 { 227 const SwAccessibleChild& rChild = *aIter; 228 if( rChild.GetDrawObject() && !rChild.GetSwFrm() && 229 rContext.GetParent(rChild, rContext.IsInPagePreview()) 230 == rContext.GetFrm() && 231 pFEShell->IsObjSelected( *rChild.GetDrawObject() ) ) 232 { 233 nCount++; 234 } 235 ++aIter; 236 } 237 } 238 } 239 } 240 return nCount; 241 } 242 243 Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild( 244 sal_Int32 nSelectedChildIndex ) 245 throw ( lang::IndexOutOfBoundsException, 246 RuntimeException) 247 { 248 vos::OGuard aGuard(Application::GetSolarMutex()); 249 250 // Since the index is relative to the selected children, and since 251 // there can be at most one selected frame child, the index must 252 // be 0, and a selection must exist, otherwise we have to throw an 253 // lang::IndexOutOfBoundsException 254 SwFEShell* pFEShell = GetFEShell(); 255 if( 0 == pFEShell ) 256 throwIndexOutOfBoundsException(); 257 258 SwAccessibleChild aChild; 259 const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm(); 260 if( pFlyFrm ) 261 { 262 if( 0 == nSelectedChildIndex && 263 rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) == 264 rContext.GetFrm() ) 265 { 266 aChild = pFlyFrm; 267 } 268 } 269 else 270 { 271 sal_uInt16 nSelObjs = pFEShell->IsObjSelected(); 272 if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs ) 273 throwIndexOutOfBoundsException(); 274 275 ::std::list< SwAccessibleChild > aChildren; 276 rContext.GetChildren( *(rContext.GetMap()), aChildren ); 277 278 ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin(); 279 ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end(); 280 while( aIter != aEndIter && !aChild.IsValid() ) 281 { 282 const SwAccessibleChild& rChild = *aIter; 283 if( rChild.GetDrawObject() && !rChild.GetSwFrm() && 284 rContext.GetParent(rChild, rContext.IsInPagePreview()) == 285 rContext.GetFrm() && 286 pFEShell->IsObjSelected( *rChild.GetDrawObject() ) ) 287 { 288 if( 0 == nSelectedChildIndex ) 289 aChild = rChild; 290 else 291 --nSelectedChildIndex; 292 } 293 ++aIter; 294 } 295 } 296 297 if( !aChild.IsValid() ) 298 throwIndexOutOfBoundsException(); 299 300 DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." ); 301 Reference< XAccessible > xChild; 302 if( aChild.GetSwFrm() ) 303 { 304 ::vos::ORef < SwAccessibleContext > xChildImpl( 305 rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(), 306 sal_True ) ); 307 if( xChildImpl.isValid() ) 308 { 309 xChildImpl->SetParent( &rContext ); 310 xChild = xChildImpl.getBodyPtr(); 311 } 312 } 313 else if ( aChild.GetDrawObject() ) 314 { 315 ::vos::ORef < ::accessibility::AccessibleShape > xChildImpl( 316 rContext.GetMap()->GetContextImpl( aChild.GetDrawObject(), 317 &rContext, sal_True ) ); 318 if( xChildImpl.isValid() ) 319 xChild = xChildImpl.getBodyPtr(); 320 } 321 return xChild; 322 } 323 324 // --> OD 2004-11-16 #111714# - index has to be treated as global child index. 325 void SwAccessibleSelectionHelper::deselectAccessibleChild( 326 sal_Int32 nChildIndex ) 327 throw ( lang::IndexOutOfBoundsException, 328 RuntimeException ) 329 { 330 // return sal_False // we can't deselect 331 if( nChildIndex < 0 || 332 nChildIndex >= rContext.GetChildCount( *(rContext.GetMap()) ) ) 333 throwIndexOutOfBoundsException(); 334 } 335