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_sw.hxx"
26 
27 
28 #include <vos/mutex.hxx>
29 #include <vcl/svapp.hxx>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
33 #include <unotools/accessiblestatesethelper.hxx>
34 #include <frmfmt.hxx>
35 #include <ndnotxt.hxx>
36 #include <flyfrm.hxx>
37 #include <cntfrm.hxx>
38 // --> OD 2009-07-14 #i73249#
39 #include <hints.hxx>
40 // <--
41 #include "accnotextframe.hxx"
42 #include <fmturl.hxx>
43 #include <accnotexthyperlink.hxx>
44 #include <svtools/imap.hxx>
45 #include <unotools/accessiblerelationsethelper.hxx>
46 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
47 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
48 #include <doc.hxx>
49 
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::accessibility;
52 using ::rtl::OUString;
53 using utl::AccessibleRelationSetHelper;
54 
GetNoTxtNode() const55 const SwNoTxtNode *SwAccessibleNoTextFrame::GetNoTxtNode() const
56 {
57 	const SwNoTxtNode *pNd  = 0;
58 	const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm *>( GetFrm() );
59 	if( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
60 	{
61 		const SwCntntFrm *pCntFrm =
62 			static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
63 		const SwCntntNode* pSwCntntNode = pCntFrm->GetNode();
64 		if(pSwCntntNode != NULL)
65 		{
66 			pNd = pSwCntntNode->GetNoTxtNode();
67 		}
68 	}
69 
70 	return pNd;
71 }
72 
SwAccessibleNoTextFrame(SwAccessibleMap * pInitMap,sal_Int16 nInitRole,const SwFlyFrm * pFlyFrm)73 SwAccessibleNoTextFrame::SwAccessibleNoTextFrame(
74         SwAccessibleMap* pInitMap,
75         sal_Int16 nInitRole,
76         const SwFlyFrm* pFlyFrm  ) :
77     SwAccessibleFrameBase( pInitMap, nInitRole, pFlyFrm ),
78     aDepend( this, const_cast < SwNoTxtNode * >( GetNoTxtNode() ) ),
79     msTitle(),
80     msDesc()
81 {
82     const SwNoTxtNode* pNd = GetNoTxtNode();
83     // --> OD 2009-07-14 #i73249#
84     // consider new attributes Title and Description
85     if( pNd )
86     {
87         msTitle = pNd->GetTitle();
88 
89         msDesc = pNd->GetDescription();
90         if ( msDesc.getLength() == 0 &&
91              msTitle != GetName() )
92         {
93             msDesc = msTitle;
94         }
95     }
96     // <--
97 }
98 
~SwAccessibleNoTextFrame()99 SwAccessibleNoTextFrame::~SwAccessibleNoTextFrame()
100 {
101 }
102 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)103 void SwAccessibleNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
104 {
105     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
106     // --> OD 2009-07-14 #i73249#
107     // suppress handling of RES_NAME_CHANGED in case that attribute Title is
108     // used as the accessible name.
109     if ( nWhich != RES_NAME_CHANGED ||
110          msTitle.getLength() == 0 )
111     {
112         SwAccessibleFrameBase::Modify( pOld, pNew );
113     }
114 
115     const SwNoTxtNode *pNd = GetNoTxtNode();
116     ASSERT( pNd == aDepend.GetRegisteredIn(), "invalid frame" );
117     switch( nWhich )
118 	{
119         // --> OD 2009-07-14 #i73249#
120         case RES_TITLE_CHANGED:
121         {
122             const String& sOldTitle(
123                         dynamic_cast<const SwStringMsgPoolItem*>(pOld)->GetString() );
124             const String& sNewTitle(
125                         dynamic_cast<const SwStringMsgPoolItem*>(pNew)->GetString() );
126             if ( sOldTitle == sNewTitle )
127             {
128                 break;
129             }
130             msTitle = sNewTitle;
131             AccessibleEventObject aEvent;
132             aEvent.EventId = AccessibleEventId::NAME_CHANGED;
133             aEvent.OldValue <<= OUString( sOldTitle );
134             aEvent.NewValue <<= msTitle;
135             FireAccessibleEvent( aEvent );
136 
137             if ( pNd->GetDescription().Len() != 0 )
138             {
139                 break;
140             }
141         }
142         // intentional no break here
143         case RES_DESCRIPTION_CHANGED:
144         {
145             if ( pNd && GetFrm() )
146             {
147                 const OUString sOldDesc( msDesc );
148 
149                 const String& rDesc = pNd->GetDescription();
150                 msDesc = rDesc;
151                 if ( msDesc.getLength() == 0 &&
152                      msTitle != GetName() )
153                 {
154                     msDesc = msTitle;
155                 }
156 
157                 if ( msDesc != sOldDesc )
158                 {
159                     AccessibleEventObject aEvent;
160                     aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
161                     aEvent.OldValue <<= sOldDesc;
162                     aEvent.NewValue <<= msDesc;
163                     FireAccessibleEvent( aEvent );
164                 }
165             }
166         }
167         break;
168         // <--
169         /*
170 	case RES_OBJECTDYING:
171 		if( aDepend.GetRegisteredIn() ==
172 				static_cast< SwModify *>( static_cast< SwPtrMsgPoolItem * >( pOld )->pObject ) )
173 			const_cast < SwModify *>( aDepend.GetRegisteredIn()->Remove( aDepend );
174 		break;
175 
176 	case RES_FMT_CHG:
177 		if( static_cast< SwFmtChg * >(pNew)->pChangedFmt == GetRegisteredIn() &&
178 			static_cast< SwFmtChg * >(pOld)->pChangedFmt->IsFmtInDTOR() )
179 			GetRegisteredIn()->Remove( this );
180 		break;
181 	*/
182 	}
183 }
184 
Dispose(sal_Bool bRecursive)185 void SwAccessibleNoTextFrame::Dispose( sal_Bool bRecursive )
186 {
187 	vos::OGuard aGuard(Application::GetSolarMutex());
188 
189 	if( aDepend.GetRegisteredIn() )
190 		const_cast < SwModify *>( aDepend.GetRegisteredIn() )->Remove( &aDepend );
191 
192 	SwAccessibleFrameBase::Dispose( bRecursive );
193 }
194 
195 // --> OD 2009-07-14 #i73249#
getAccessibleName(void)196 OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleName (void)
197         throw (uno::RuntimeException)
198 {
199     vos::OGuard aGuard(Application::GetSolarMutex());
200 
201     CHECK_FOR_DEFUNC( XAccessibleContext )
202 
203     if ( msTitle.getLength() != 0 )
204     {
205         return msTitle;
206     }
207 
208     return SwAccessibleFrameBase::getAccessibleName();
209 }
210 // <--
211 
getAccessibleDescription(void)212 OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleDescription (void)
213         throw (uno::RuntimeException)
214 {
215 	vos::OGuard aGuard(Application::GetSolarMutex());
216 
217 	CHECK_FOR_DEFUNC( XAccessibleContext )
218 	// OUString longDesc;
219 	// const SwFlyFrmFmt* pFlyFmt = GetShell()->GetDoc()->FindFlyByName( GetName(), 0);
220 	// longDesc = OUString( pFlyFmt->GetLongDescription() );
221 	// return  longDesc; MT: Do not return longDesc, which still is empty - why was the line above commented out?
222 
223     return msDesc;
224 }
225 
226 
227 
228 //
229 // XInterface
230 //
231 
queryInterface(const uno::Type & aType)232 uno::Any SAL_CALL SwAccessibleNoTextFrame::queryInterface( const uno::Type& aType )
233     throw (uno::RuntimeException)
234 {
235     if( aType ==
236         ::getCppuType( static_cast<uno::Reference<XAccessibleImage>*>( NULL ) ) )
237     {
238         uno::Reference<XAccessibleImage> xImage = this;
239         uno::Any aAny;
240         aAny <<= xImage;
241         return aAny;
242     }
243 	else if ( aType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) )
244     {
245 		uno::Reference<XAccessibleHypertext> aAccHypertext = this;
246 		uno::Any aAny;
247 		aAny <<= aAccHypertext;
248 		return aAny;
249     }
250     else
251         return SwAccessibleContext::queryInterface( aType );
252 }
253 
254 
255 //====== XTypeProvider ====================================================
getTypes()256 uno::Sequence< uno::Type > SAL_CALL SwAccessibleNoTextFrame::getTypes() throw(uno::RuntimeException)
257 {
258 	uno::Sequence< uno::Type > aTypes( SwAccessibleFrameBase::getTypes() );
259 
260 	sal_Int32 nIndex = aTypes.getLength();
261 	aTypes.realloc( nIndex + 1 );
262 
263 	uno::Type* pTypes = aTypes.getArray();
264 	pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleImage > * >( 0 ) );
265 
266 	return aTypes;
267 }
268 
269 
270 //
271 // XAccessibleImage
272 //
273 
274 // implementation of the XAccessibleImage methods is a no-brainer, as
275 // all releveant information is already accessible through other
276 // methods. So we just delegate to those.
277 
getAccessibleImageDescription()278 OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageDescription()
279     throw ( uno::RuntimeException )
280 {
281     return getAccessibleDescription();
282 }
283 
getAccessibleImageHeight()284 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageHeight(  )
285     throw ( uno::RuntimeException )
286 {
287     return getSize().Height;
288 }
289 
getAccessibleImageWidth()290 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageWidth(  )
291     throw ( uno::RuntimeException )
292 {
293     return getSize().Width;
294 }
295 //=====  XAccesibleText  ==================================================
getCaretPosition()296 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getCaretPosition(  ) throw (::com::sun::star::uno::RuntimeException){return 0;}
setCaretPosition(sal_Int32)297 sal_Bool SAL_CALL SwAccessibleNoTextFrame::setCaretPosition( sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException){return 0;}
getCharacter(sal_Int32)298 sal_Unicode SAL_CALL SwAccessibleNoTextFrame::getCharacter( sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException){return 0;}
getCharacterAttributes(sal_Int32,const::com::sun::star::uno::Sequence<::rtl::OUString> &)299 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SwAccessibleNoTextFrame::getCharacterAttributes( sal_Int32 , const ::com::sun::star::uno::Sequence< ::rtl::OUString >& ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
300 {
301 	uno::Sequence<beans::PropertyValue> aValues(0);
302 	return aValues;
303 }
getCharacterBounds(sal_Int32)304 ::com::sun::star::awt::Rectangle SAL_CALL SwAccessibleNoTextFrame::getCharacterBounds( sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
305 {
306 	return com::sun::star::awt::Rectangle(0, 0, 0, 0 );
307 }
getCharacterCount()308 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getCharacterCount(  ) throw (::com::sun::star::uno::RuntimeException){return 0;}
getIndexAtPoint(const::com::sun::star::awt::Point &)309 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getIndexAtPoint( const ::com::sun::star::awt::Point& ) throw (::com::sun::star::uno::RuntimeException){return 0;}
getSelectedText()310 ::rtl::OUString SAL_CALL SwAccessibleNoTextFrame::getSelectedText(  ) throw (::com::sun::star::uno::RuntimeException){return OUString();}
getSelectionStart()311 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getSelectionStart(  ) throw (::com::sun::star::uno::RuntimeException){return 0;}
getSelectionEnd()312 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getSelectionEnd(  ) throw (::com::sun::star::uno::RuntimeException){return 0;}
setSelection(sal_Int32,sal_Int32)313 sal_Bool SAL_CALL SwAccessibleNoTextFrame::setSelection( sal_Int32 , sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException){return sal_True;}
getText()314 ::rtl::OUString SAL_CALL SwAccessibleNoTextFrame::getText(  ) throw (::com::sun::star::uno::RuntimeException){return OUString();}
getTextRange(sal_Int32,sal_Int32)315 ::rtl::OUString SAL_CALL SwAccessibleNoTextFrame::getTextRange( sal_Int32 , sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException){return OUString();}
getTextAtIndex(sal_Int32,sal_Int16)316 ::com::sun::star::accessibility::TextSegment SAL_CALL SwAccessibleNoTextFrame::getTextAtIndex( sal_Int32 , sal_Int16 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
317 {
318 	::com::sun::star::accessibility::TextSegment aResult;
319 	return aResult;
320 }
getTextBeforeIndex(sal_Int32,sal_Int16)321 ::com::sun::star::accessibility::TextSegment SAL_CALL SwAccessibleNoTextFrame::getTextBeforeIndex( sal_Int32, sal_Int16 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
322 {
323 	::com::sun::star::accessibility::TextSegment aResult;
324 	return aResult;
325 }
getTextBehindIndex(sal_Int32,sal_Int16)326 ::com::sun::star::accessibility::TextSegment SAL_CALL SwAccessibleNoTextFrame::getTextBehindIndex( sal_Int32 , sal_Int16 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
327 {
328 	::com::sun::star::accessibility::TextSegment aResult;
329 	return aResult;
330 }
331 
copyText(sal_Int32,sal_Int32)332 sal_Bool SAL_CALL SwAccessibleNoTextFrame::copyText( sal_Int32, sal_Int32 ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException){return sal_True;}
333 
334 
335 //
336 //  XAccessibleHyperText
337 //
getHyperLinkCount()338 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getHyperLinkCount()
339 throw (uno::RuntimeException)
340 {
341 	vos::OGuard aGuard(Application::GetSolarMutex());
342 
343 	CHECK_FOR_DEFUNC( XAccessibleHypertext );
344 
345 	sal_Int32 nCount = 0;
346 	SwFmtURL aURL( ((SwLayoutFrm*)GetFrm())->GetFmt()->GetURL() );
347 
348 	if(aURL.GetMap() || aURL.GetURL().Len())
349 		nCount = 1;
350 
351 	return nCount;
352 }
353 
354 uno::Reference< XAccessibleHyperlink > SAL_CALL
getHyperLink(sal_Int32 nLinkIndex)355 	SwAccessibleNoTextFrame::getHyperLink( sal_Int32 nLinkIndex )
356 	throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
357 {
358 	vos::OGuard aGuard(Application::GetSolarMutex());
359 	CHECK_FOR_DEFUNC( XAccessibleHypertext );
360 
361 	uno::Reference< XAccessibleHyperlink > xRet;
362 
363 	SwFmtURL aURL( ((SwLayoutFrm*)GetFrm())->GetFmt()->GetURL() );
364 
365 	if( nLinkIndex > 0 )
366 		throw lang::IndexOutOfBoundsException();
367 
368 	if( aURL.GetMap() || aURL.GetURL().Len() )
369 	{
370 		if ( !alink.is() )
371 		{
372 			alink = new SwAccessibleNoTextHyperlink( this, GetFrm() );
373 		}
374 
375 		return alink;
376 	}
377 
378 	return NULL;
379 }
380 
getHyperLinkIndex(sal_Int32)381 sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getHyperLinkIndex( sal_Int32 )
382 	throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
383 {
384 	vos::OGuard aGuard(Application::GetSolarMutex());
385 	CHECK_FOR_DEFUNC( XAccessibleHypertext );
386 
387 	sal_Int32 nRet = 0;
388 
389 	return nRet;
390 }
391 
makeRelation(sal_Int16 nType,const SwFlyFrm * pFrm)392 AccessibleRelation SwAccessibleNoTextFrame::makeRelation( sal_Int16 nType, const SwFlyFrm* pFrm )
393 {
394 	uno::Sequence<uno::Reference<XInterface> > aSequence(1);
395     aSequence[0] = GetMap()->GetContext( pFrm );
396 	return AccessibleRelation( nType, aSequence );
397 }
398 
399 
getAccessibleRelationSet()400 uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleNoTextFrame::getAccessibleRelationSet( )
401 	throw ( uno::RuntimeException )
402 {
403 	vos::OGuard aGuard(Application::GetSolarMutex());
404 	CHECK_FOR_DEFUNC( XAccessibleContext );
405 
406     // get the caption frame, and insert label relations into helper
407 
408     AccessibleRelationSetHelper* pHelper = new AccessibleRelationSetHelper();
409 
410 	SwFlyFrm* pFlyFrm = getFlyFrm();
411 	DBG_ASSERT( pFlyFrm != NULL, "fly frame expected" );
412 
413 	SwFlyFrm* pCaptionFrm = NULL;
414 	const SwFrmFmt* pFrm = pFlyFrm ->GetFmt()->GetCaptionFmt();
415 	if (pFrm)
416 	{
417 		SwClientIter aIter (*(SwModify*)pFrm);
418 		pCaptionFrm = (SwFlyFrm*)aIter.First( TYPE ( SwFlyFrm ));
419 	}
420 	if(pCaptionFrm!=NULL)
421 	{
422 		pHelper->AddRelation( makeRelation( AccessibleRelationType::DESCRIBED_BY, pCaptionFrm ) );
423 	}
424 
425 	return pHelper;
426 }
427