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_editeng.hxx" 26 27 #include <com/sun/star/uno/Any.hxx> 28 #include <com/sun/star/uno/Reference.hxx> 29 #include <comphelper/accessiblekeybindinghelper.hxx> 30 31 #include "AccessibleHyperlink.hxx" 32 #include "editeng/unoedprx.hxx" 33 #include <editeng/flditem.hxx> 34 #include <vcl/keycodes.hxx> 35 36 using namespace ::com::sun::star; 37 38 39 //------------------------------------------------------------------------ 40 // 41 // AccessibleHyperlink implementation 42 // 43 //------------------------------------------------------------------------ 44 45 namespace accessibility 46 { 47 AccessibleHyperlink(SvxAccessibleTextAdapter & r,SvxFieldItem * p,sal_uInt16 nP,sal_uInt16 nR,sal_Int32 nStt,sal_Int32 nEnd,const::rtl::OUString & rD)48 AccessibleHyperlink::AccessibleHyperlink( SvxAccessibleTextAdapter& r, SvxFieldItem* p, sal_uInt16 nP, sal_uInt16 nR, sal_Int32 nStt, sal_Int32 nEnd, const ::rtl::OUString& rD ) 49 : rTA( r ) 50 { 51 pFld = p; 52 nPara = nP; 53 nRealIdx = nR; 54 nStartIdx = nStt; 55 nEndIdx = nEnd; 56 aDescription = rD; 57 } 58 ~AccessibleHyperlink()59 AccessibleHyperlink::~AccessibleHyperlink() 60 { 61 delete pFld; 62 } 63 64 // XAccessibleAction getAccessibleActionCount()65 sal_Int32 SAL_CALL AccessibleHyperlink::getAccessibleActionCount() throw (uno::RuntimeException) 66 { 67 return isValid() ? 1 : 0; 68 } 69 doAccessibleAction(sal_Int32 nIndex)70 sal_Bool SAL_CALL AccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 71 { 72 sal_Bool bRet = sal_False; 73 if ( isValid() && ( nIndex == 0 ) ) 74 { 75 rTA.FieldClicked( *pFld, nPara, nRealIdx ); 76 bRet = sal_True; 77 } 78 return bRet; 79 } 80 getAccessibleActionDescription(sal_Int32 nIndex)81 ::rtl::OUString SAL_CALL AccessibleHyperlink::getAccessibleActionDescription( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 82 { 83 ::rtl::OUString aDesc; 84 85 if ( isValid() && ( nIndex == 0 ) ) 86 aDesc = aDescription; 87 88 return aDesc; 89 } 90 getAccessibleActionKeyBinding(sal_Int32 nIndex)91 uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL AccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 92 { 93 uno::Reference< ::com::sun::star::accessibility::XAccessibleKeyBinding > xKeyBinding; 94 95 if( isValid() && ( nIndex == 0 ) ) 96 { 97 ::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper = new ::comphelper::OAccessibleKeyBindingHelper(); 98 xKeyBinding = pKeyBindingHelper; 99 100 awt::KeyStroke aKeyStroke; 101 aKeyStroke.Modifiers = 0; 102 aKeyStroke.KeyCode = KEY_RETURN; 103 aKeyStroke.KeyChar = 0; 104 aKeyStroke.KeyFunc = 0; 105 pKeyBindingHelper->AddKeyBinding( aKeyStroke ); 106 } 107 108 return xKeyBinding; 109 } 110 111 // XAccessibleHyperlink getAccessibleActionAnchor(sal_Int32)112 uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionAnchor( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 113 { 114 return uno::Any(); 115 } 116 getAccessibleActionObject(sal_Int32)117 uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionObject( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 118 { 119 return uno::Any(); 120 } 121 getStartIndex()122 sal_Int32 SAL_CALL AccessibleHyperlink::getStartIndex() throw (uno::RuntimeException) 123 { 124 return nStartIdx; 125 } 126 getEndIndex()127 sal_Int32 SAL_CALL AccessibleHyperlink::getEndIndex() throw (uno::RuntimeException) 128 { 129 return nEndIdx; 130 } 131 isValid()132 sal_Bool SAL_CALL AccessibleHyperlink::isValid( ) throw (uno::RuntimeException) 133 { 134 return rTA.IsValid(); 135 } 136 137 } // end of namespace accessibility 138 139 //------------------------------------------------------------------------ 140 141 // MT IA2: Accessiblehyperlink.hxx from IA2 CWS - meanwhile we also introduced one in DEV300 (above) 142 // Keeping this for reference - we probably should get support for image maps in our implementation... 143 144 145 /* 146 147 class SVX_DLLPUBLIC SvxAccessibleHyperlink : 148 public ::cppu::WeakImplHelper1< 149 ::com::sun::star::accessibility::XAccessibleHyperlink > 150 { 151 SvxURLField* mpField; 152 sal_Int32 nStartIdx; 153 sal_Int32 nEndIdx; 154 155 ImageMap* mpImageMap; 156 SdrObject* m_pShape; 157 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > shapeParent; 158 159 public: 160 161 SvxAccessibleHyperlink(){}; 162 //SvxAccessibleHyperlink(::rtl::OUString name, const Imagemap* pImageMap); 163 SvxAccessibleHyperlink(const SvxURLField* p, sal_Int32 nStt, sal_Int32 nEnd); 164 SvxAccessibleHyperlink(SdrObject* p, ::accessibility::AccessibleShape* pAcc); 165 virtual ~SvxAccessibleHyperlink(); 166 //void setImageMap(ImageMap* pMap); 167 //void setXAccessibleImage(::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > parent); 168 ::rtl::OUString GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException); 169 sal_Bool IsValidHyperlink(); 170 171 // XAccessibleAction 172 virtual sal_Int32 SAL_CALL getAccessibleActionCount() 173 throw (::com::sun::star::uno::RuntimeException); 174 virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex ) 175 throw (::com::sun::star::lang::IndexOutOfBoundsException, 176 ::com::sun::star::uno::RuntimeException); 177 virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription( 178 sal_Int32 nIndex ) 179 throw (::com::sun::star::lang::IndexOutOfBoundsException, 180 ::com::sun::star::uno::RuntimeException); 181 virtual ::com::sun::star::uno::Reference< 182 ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL 183 getAccessibleActionKeyBinding( sal_Int32 nIndex ) 184 throw (::com::sun::star::lang::IndexOutOfBoundsException, 185 ::com::sun::star::uno::RuntimeException); 186 187 // XAccessibleHyperlink 188 virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor( 189 sal_Int32 nIndex ) 190 throw (::com::sun::star::lang::IndexOutOfBoundsException, 191 ::com::sun::star::uno::RuntimeException); 192 virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject( 193 sal_Int32 nIndex ) 194 throw (::com::sun::star::lang::IndexOutOfBoundsException, 195 ::com::sun::star::uno::RuntimeException); 196 virtual sal_Int32 SAL_CALL getStartIndex() 197 throw (::com::sun::star::uno::RuntimeException); 198 virtual sal_Int32 SAL_CALL getEndIndex() 199 throw (::com::sun::star::uno::RuntimeException); 200 virtual sal_Bool SAL_CALL isValid( ) 201 throw (::com::sun::star::uno::RuntimeException); 202 }; 203 204 205 SvxAccessibleHyperlink::SvxAccessibleHyperlink( const SvxURLField *p, 206 sal_Int32 nStt, sal_Int32 nEnd ) : 207 nStartIdx( nStt ), 208 nEndIdx( nEnd ), 209 m_pShape(NULL), 210 shapeParent(NULL) 211 { 212 if(p) 213 mpField = (SvxURLField*)p->Clone(); 214 else 215 mpField = NULL; 216 } 217 218 SvxAccessibleHyperlink::SvxAccessibleHyperlink(SdrObject* p, 219 ::accessibility::AccessibleShape* pAcc) : 220 nStartIdx( -1 ), 221 nEndIdx( -1 ), 222 mpField(NULL), 223 m_pShape(p) 224 { 225 mpImageMap = m_pShape->GetModel()->GetImageMapForObject(m_pShape); 226 shapeParent = dynamic_cast< XAccessible* >(pAcc); 227 } 228 229 SvxAccessibleHyperlink::~SvxAccessibleHyperlink() 230 { 231 if(mpField) 232 delete mpField; 233 } 234 235 ::rtl::OUString SvxAccessibleHyperlink::GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException) 236 { 237 if( mpField ) 238 { 239 if (nIndex != 0) 240 throw ::com::sun::star::lang::IndexOutOfBoundsException(); 241 return ::rtl::OUString( mpField->GetURL() ); 242 } 243 else if (mpImageMap) 244 { 245 if (nIndex < 0 || nIndex >=mpImageMap->GetIMapObjectCount()) 246 throw IndexOutOfBoundsException(); 247 248 IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex)); 249 if (pMapObj->GetURL().Len()) 250 return ::rtl::OUString( pMapObj->GetURL() ); 251 } 252 else 253 { 254 if (nIndex != 0) 255 throw ::com::sun::star::lang::IndexOutOfBoundsException(); 256 257 SdrUnoObj* pUnoCtrl = dynamic_cast< SdrUnoObj* >( m_pShape ); 258 259 if(pUnoCtrl) 260 { 261 try 262 { 263 uno::Reference< awt::XControlModel > xControlModel( pUnoCtrl->GetUnoControlModel(), uno::UNO_QUERY_THROW ); 264 uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW ); 265 uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo(), uno::UNO_QUERY_THROW ); 266 267 form::FormButtonType eButtonType = form::FormButtonType_URL; 268 const ::rtl::OUString sButtonType( RTL_CONSTASCII_USTRINGPARAM( "ButtonType" ) ); 269 if(xPropInfo->hasPropertyByName( sButtonType ) && (xPropSet->getPropertyValue( sButtonType ) >>= eButtonType ) ) 270 { 271 ::rtl::OUString aString; 272 273 // URL 274 const ::rtl::OUString sTargetURL(RTL_CONSTASCII_USTRINGPARAM( "TargetURL" )); 275 if(xPropInfo->hasPropertyByName(sTargetURL)) 276 { 277 if( xPropSet->getPropertyValue(sTargetURL) >>= aString ) 278 return aString; 279 } 280 } 281 } 282 catch( uno::Exception& ) 283 { 284 } 285 } 286 // If hyperlink can't be got from sdrobject, query the corresponding document to retrieve the link info 287 uno::Reference< XAccessibleGroupPosition > xGroupPosition (shapeParent, uno::UNO_QUERY); 288 if (xGroupPosition.is()) 289 return xGroupPosition->getObjectLink( uno::makeAny( shapeParent ) ); 290 } 291 return ::rtl::OUString(); 292 } 293 294 // Just check whether the first hyperlink is valid 295 sal_Bool SvxAccessibleHyperlink::IsValidHyperlink() 296 { 297 ::rtl::OUString url = GetHyperlinkURL(0); 298 if (url.getLength() > 0) 299 return sal_True; 300 else 301 return sal_False; 302 } 303 // XAccessibleAction 304 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getAccessibleActionCount() 305 throw (RuntimeException) 306 { 307 if (mpImageMap) 308 return mpImageMap->GetIMapObjectCount(); 309 else 310 return 1; // only shape link or url field 311 312 //return mpField ? 1 : (mpImageMap ? mpImageMap->GetIMapObjectCount() : 0); 313 } 314 315 sal_Bool SAL_CALL SvxAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex ) 316 throw (IndexOutOfBoundsException, RuntimeException) 317 { 318 vos::OGuard aGuard(Application::GetSolarMutex()); 319 320 sal_Bool bRet = sal_False; 321 322 OUString url = GetHyperlinkURL(nIndex); 323 324 if( url.getLength() > 0 ) 325 { 326 SfxStringItem aStrItem(SID_FILE_NAME, url); 327 const SfxObjectShell* pDocSh = SfxObjectShell::Current(); 328 if( pDocSh ) 329 { 330 SfxMedium* pSfxMedium = pDocSh->GetMedium(); 331 if( pSfxMedium) 332 { 333 SfxStringItem aReferer(SID_REFERER, pSfxMedium->GetName()); 334 SfxBoolItem aBrowseItem( SID_BROWSE, TRUE ); 335 SfxViewFrame* pFrame = SfxViewFrame::Current(); 336 if( pFrame ) 337 { 338 pFrame->GetDispatcher()->Execute(SID_OPENDOC, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, 339 &aStrItem, &aBrowseItem, &aReferer, 0L); 340 bRet = sal_True; 341 } 342 } 343 } 344 } 345 346 return bRet; 347 } 348 349 OUString SAL_CALL SvxAccessibleHyperlink::getAccessibleActionDescription( 350 sal_Int32 nIndex ) 351 throw (IndexOutOfBoundsException, RuntimeException) 352 { 353 return GetHyperlinkURL(nIndex); 354 } 355 356 ::com::sun::star::uno::Reference< XAccessibleKeyBinding > SAL_CALL 357 SvxAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 ) 358 throw (IndexOutOfBoundsException, RuntimeException) 359 { 360 ::com::sun::star::uno::Reference< XAccessibleKeyBinding > xKeyBinding; 361 362 if( mpField || m_pShape) 363 { 364 ::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper = 365 new ::comphelper::OAccessibleKeyBindingHelper(); 366 xKeyBinding = pKeyBindingHelper; 367 368 ::com::sun::star::awt::KeyStroke aKeyStroke; 369 aKeyStroke.Modifiers = 0; 370 aKeyStroke.KeyCode = KEY_RETURN; 371 aKeyStroke.KeyChar = 0; 372 aKeyStroke.KeyFunc = 0; 373 pKeyBindingHelper->AddKeyBinding( aKeyStroke ); 374 } 375 376 return xKeyBinding; 377 } 378 379 // XAccessibleHyperlink 380 Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionAnchor( 381 sal_Int32 nIndex ) 382 throw (IndexOutOfBoundsException, RuntimeException) 383 { 384 Any aRet; 385 386 ::rtl::OUString retText; 387 if(mpField && nIndex == 0) 388 { 389 retText = mpField->GetRepresentation(); 390 aRet <<= retText; 391 return aRet; 392 } 393 else if(mpImageMap) 394 { 395 IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex)); 396 if(pMapObj && pMapObj->GetURL().Len()) 397 aRet <<= shapeParent; 398 return aRet; 399 } 400 else if (nIndex == 0) 401 { 402 aRet <<= shapeParent; 403 return aRet; 404 } 405 return aRet; 406 } 407 408 Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionObject( 409 sal_Int32 nIndex ) 410 throw (IndexOutOfBoundsException, RuntimeException) 411 { 412 ::rtl::OUString retText = GetHyperlinkURL(nIndex); 413 Any aRet; 414 aRet <<= retText; 415 return aRet; 416 } 417 418 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getStartIndex() 419 throw (RuntimeException) 420 { 421 return nStartIdx; 422 } 423 424 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getEndIndex() 425 throw (RuntimeException) 426 { 427 return nEndIdx; 428 } 429 430 sal_Bool SAL_CALL SvxAccessibleHyperlink::isValid( ) 431 throw (RuntimeException) 432 { 433 vos::OGuard aGuard(Application::GetSolarMutex()); 434 //return mpField ? sal_True: ( mpImageMap ? sal_True : sal_False ); 435 if (mpField || m_pShape) 436 return sal_True; 437 else 438 return sal_False; 439 } 440 441 */ 442 443 444 445