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