xref: /trunk/main/editeng/source/accessibility/AccessibleHyperlink.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
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 //IAccessibility2 Implementation 2009-----
145 
146 /*
147 
148 class SVX_DLLPUBLIC SvxAccessibleHyperlink :
149         public ::cppu::WeakImplHelper1<
150         ::com::sun::star::accessibility::XAccessibleHyperlink >
151 {
152     SvxURLField* mpField;
153     sal_Int32 nStartIdx;
154     sal_Int32 nEndIdx;
155 
156     ImageMap* mpImageMap;
157     SdrObject* m_pShape;
158     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >  shapeParent;
159 
160 public:
161 
162     SvxAccessibleHyperlink(){};
163     //SvxAccessibleHyperlink(::rtl::OUString name, const Imagemap* pImageMap);
164     SvxAccessibleHyperlink(const SvxURLField* p, sal_Int32 nStt, sal_Int32 nEnd);
165     SvxAccessibleHyperlink(SdrObject* p, ::accessibility::AccessibleShape* pAcc);
166     virtual ~SvxAccessibleHyperlink();
167     //void setImageMap(ImageMap* pMap);
168     //void setXAccessibleImage(::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > parent);
169     ::rtl::OUString GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException);
170     sal_Bool IsValidHyperlink();
171 
172     // XAccessibleAction
173     virtual sal_Int32 SAL_CALL getAccessibleActionCount()
174         throw (::com::sun::star::uno::RuntimeException);
175     virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex )
176         throw (::com::sun::star::lang::IndexOutOfBoundsException,
177                 ::com::sun::star::uno::RuntimeException);
178     virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription(
179                 sal_Int32 nIndex )
180         throw (::com::sun::star::lang::IndexOutOfBoundsException,
181                 ::com::sun::star::uno::RuntimeException);
182     virtual ::com::sun::star::uno::Reference<
183             ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL
184             getAccessibleActionKeyBinding( sal_Int32 nIndex )
185         throw (::com::sun::star::lang::IndexOutOfBoundsException,
186                 ::com::sun::star::uno::RuntimeException);
187 
188     // XAccessibleHyperlink
189     virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor(
190                 sal_Int32 nIndex )
191         throw (::com::sun::star::lang::IndexOutOfBoundsException,
192                 ::com::sun::star::uno::RuntimeException);
193     virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject(
194             sal_Int32 nIndex )
195         throw (::com::sun::star::lang::IndexOutOfBoundsException,
196                 ::com::sun::star::uno::RuntimeException);
197     virtual sal_Int32 SAL_CALL getStartIndex()
198         throw (::com::sun::star::uno::RuntimeException);
199     virtual sal_Int32 SAL_CALL getEndIndex()
200         throw (::com::sun::star::uno::RuntimeException);
201     virtual sal_Bool SAL_CALL isValid(  )
202         throw (::com::sun::star::uno::RuntimeException);
203 };
204 
205 
206 SvxAccessibleHyperlink::SvxAccessibleHyperlink( const SvxURLField *p,
207                                           sal_Int32 nStt, sal_Int32 nEnd ) :
208     nStartIdx( nStt ),
209     nEndIdx( nEnd ),
210     m_pShape(NULL),
211     shapeParent(NULL)
212 {
213     if(p)
214         mpField = (SvxURLField*)p->Clone();
215     else
216         mpField = NULL;
217 }
218 
219 SvxAccessibleHyperlink::SvxAccessibleHyperlink(SdrObject* p,
220                                             ::accessibility::AccessibleShape* pAcc) :
221     nStartIdx( -1 ),
222     nEndIdx( -1 ),
223     mpField(NULL),
224     m_pShape(p)
225 {
226     mpImageMap = m_pShape->GetModel()->GetImageMapForObject(m_pShape);
227     shapeParent = dynamic_cast< XAccessible* >(pAcc);
228 }
229 
230 SvxAccessibleHyperlink::~SvxAccessibleHyperlink()
231 {
232     if(mpField)
233         delete mpField;
234 }
235 
236 ::rtl::OUString SvxAccessibleHyperlink::GetHyperlinkURL(sal_Int32 nIndex) throw (::com::sun::star::lang::IndexOutOfBoundsException)
237 {
238     if( mpField )
239     {
240         if (nIndex != 0)
241             throw ::com::sun::star::lang::IndexOutOfBoundsException();
242         return ::rtl::OUString( mpField->GetURL() );
243     }
244     else if (mpImageMap)
245     {
246         if (nIndex < 0 || nIndex >=mpImageMap->GetIMapObjectCount())
247             throw IndexOutOfBoundsException();
248 
249         IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
250         if (pMapObj->GetURL().Len())
251             return ::rtl::OUString( pMapObj->GetURL() );
252     }
253     else
254     {
255         if (nIndex != 0)
256             throw ::com::sun::star::lang::IndexOutOfBoundsException();
257 
258         SdrUnoObj* pUnoCtrl = dynamic_cast< SdrUnoObj* >( m_pShape );
259 
260         if(pUnoCtrl)
261         {
262             try
263             {
264                 uno::Reference< awt::XControlModel > xControlModel( pUnoCtrl->GetUnoControlModel(), uno::UNO_QUERY_THROW );
265                 uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
266                 uno::Reference< beans::XPropertySetInfo > xPropInfo( xPropSet->getPropertySetInfo(), uno::UNO_QUERY_THROW );
267 
268                 form::FormButtonType eButtonType = form::FormButtonType_URL;
269                 const ::rtl::OUString sButtonType( RTL_CONSTASCII_USTRINGPARAM( "ButtonType" ) );
270                 if(xPropInfo->hasPropertyByName( sButtonType ) && (xPropSet->getPropertyValue( sButtonType ) >>= eButtonType ) )
271                 {
272                     ::rtl::OUString aString;
273 
274                     // URL
275                     const ::rtl::OUString sTargetURL(RTL_CONSTASCII_USTRINGPARAM( "TargetURL" ));
276                     if(xPropInfo->hasPropertyByName(sTargetURL))
277                     {
278                         if( xPropSet->getPropertyValue(sTargetURL) >>= aString )
279                             return aString;
280                     }
281                 }
282             }
283             catch( uno::Exception& )
284             {
285             }
286         }
287         // If hyperlink can't be got from sdrobject, query the corresponding document to retrieve the link info
288         uno::Reference< XAccessibleGroupPosition > xGroupPosition (shapeParent, uno::UNO_QUERY);
289         if (xGroupPosition.is())
290             return xGroupPosition->getObjectLink( uno::makeAny( shapeParent ) );
291     }
292     return ::rtl::OUString();
293 }
294 
295 // Just check whether the first hyperlink is valid
296 sal_Bool SvxAccessibleHyperlink::IsValidHyperlink()
297 {
298     ::rtl::OUString url = GetHyperlinkURL(0);
299     if (url.getLength() > 0)
300         return sal_True;
301     else
302         return sal_False;
303 }
304 // XAccessibleAction
305 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getAccessibleActionCount()
306         throw (RuntimeException)
307 {
308     if (mpImageMap)
309         return mpImageMap->GetIMapObjectCount();
310     else
311         return 1;   // only shape link or url field
312 
313     //return mpField ? 1 : (mpImageMap ? mpImageMap->GetIMapObjectCount() : 0);
314 }
315 
316 sal_Bool SAL_CALL SvxAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex )
317         throw (IndexOutOfBoundsException, RuntimeException)
318 {
319     vos::OGuard aGuard(Application::GetSolarMutex());
320 
321     sal_Bool bRet = sal_False;
322 
323     OUString url = GetHyperlinkURL(nIndex);
324 
325     if( url.getLength() > 0 )
326     {
327         SfxStringItem aStrItem(SID_FILE_NAME, url);
328         const SfxObjectShell* pDocSh = SfxObjectShell::Current();
329         if( pDocSh )
330         {
331             SfxMedium* pSfxMedium = pDocSh->GetMedium();
332             if( pSfxMedium)
333             {
334                 SfxStringItem aReferer(SID_REFERER, pSfxMedium->GetName());
335                 SfxBoolItem aBrowseItem( SID_BROWSE, TRUE );
336                 SfxViewFrame* pFrame = SfxViewFrame::Current();
337                 if( pFrame )
338                 {
339                     pFrame->GetDispatcher()->Execute(SID_OPENDOC, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
340                                 &aStrItem, &aBrowseItem, &aReferer, 0L);
341                     bRet = sal_True;
342                 }
343             }
344         }
345     }
346 
347     return bRet;
348 }
349 
350 OUString SAL_CALL SvxAccessibleHyperlink::getAccessibleActionDescription(
351         sal_Int32 nIndex )
352         throw (IndexOutOfBoundsException, RuntimeException)
353 {
354     return GetHyperlinkURL(nIndex);
355 }
356 
357 ::com::sun::star::uno::Reference< XAccessibleKeyBinding > SAL_CALL
358     SvxAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 )
359     throw (IndexOutOfBoundsException, RuntimeException)
360 {
361     ::com::sun::star::uno::Reference< XAccessibleKeyBinding > xKeyBinding;
362 
363     if( mpField || m_pShape)
364     {
365         ::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper =
366             new ::comphelper::OAccessibleKeyBindingHelper();
367         xKeyBinding = pKeyBindingHelper;
368 
369         ::com::sun::star::awt::KeyStroke aKeyStroke;
370         aKeyStroke.Modifiers = 0;
371         aKeyStroke.KeyCode = KEY_RETURN;
372         aKeyStroke.KeyChar = 0;
373         aKeyStroke.KeyFunc = 0;
374         pKeyBindingHelper->AddKeyBinding( aKeyStroke );
375     }
376 
377     return xKeyBinding;
378 }
379 
380 // XAccessibleHyperlink
381 Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionAnchor(
382         sal_Int32 nIndex )
383         throw (IndexOutOfBoundsException, RuntimeException)
384 {
385     Any aRet;
386 
387     ::rtl::OUString retText;
388     if(mpField && nIndex == 0)
389     {
390         retText = mpField->GetRepresentation();
391         aRet <<= retText;
392         return aRet;
393     }
394     else if(mpImageMap)
395     {
396         IMapObject* pMapObj = mpImageMap->GetIMapObject(sal_uInt16(nIndex));
397         if(pMapObj && pMapObj->GetURL().Len())
398             aRet <<= shapeParent;
399             return aRet;
400     }
401     else if (nIndex == 0)
402     {
403         aRet <<= shapeParent;
404         return aRet;
405     }
406     return aRet;
407 }
408 
409 Any SAL_CALL SvxAccessibleHyperlink::getAccessibleActionObject(
410             sal_Int32 nIndex )
411     throw (IndexOutOfBoundsException, RuntimeException)
412 {
413     ::rtl::OUString retText = GetHyperlinkURL(nIndex);
414     Any aRet;
415     aRet <<= retText;
416     return aRet;
417 }
418 
419 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getStartIndex()
420         throw (RuntimeException)
421 {
422     return nStartIdx;
423 }
424 
425 sal_Int32 SAL_CALL SvxAccessibleHyperlink::getEndIndex()
426         throw (RuntimeException)
427 {
428     return nEndIdx;
429 }
430 
431 sal_Bool SAL_CALL SvxAccessibleHyperlink::isValid(  )
432         throw (RuntimeException)
433 {
434     vos::OGuard aGuard(Application::GetSolarMutex());
435     //return mpField ? sal_True: ( mpImageMap ? sal_True : sal_False );
436     if (mpField || m_pShape)
437         return sal_True;
438     else
439         return sal_False;
440 }
441 
442 */
443 
444 //-----IAccessibility2 Implementation 2009
445 
446 
447