xref: /AOO41X/main/editeng/source/accessibility/AccessibleHyperlink.cxx (revision 83137a03adbb58b5b3bdafefefa1e93de35e0011)
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 
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 
59     AccessibleHyperlink::~AccessibleHyperlink()
60     {
61         delete pFld;
62     }
63 
64     // XAccessibleAction
65     sal_Int32 SAL_CALL AccessibleHyperlink::getAccessibleActionCount() throw (uno::RuntimeException)
66     {
67          return isValid() ? 1 : 0;
68     }
69 
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 
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 
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
112     uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionAnchor( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
113     {
114         return uno::Any();
115     }
116 
117     uno::Any SAL_CALL AccessibleHyperlink::getAccessibleActionObject( sal_Int32 /*nIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
118     {
119         return uno::Any();
120     }
121 
122     sal_Int32 SAL_CALL AccessibleHyperlink::getStartIndex() throw (uno::RuntimeException)
123     {
124         return nStartIdx;
125     }
126 
127     sal_Int32 SAL_CALL AccessibleHyperlink::getEndIndex() throw (uno::RuntimeException)
128     {
129         return nEndIdx;
130     }
131 
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