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