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