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 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
28 #include <rtl/uuid.h>
29 #include <vos/mutex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
33 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
34 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
35 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <unotools/accessiblestatesethelper.hxx>
38 #include <frmfmt.hxx>
39 #include <flyfrm.hxx>
40 #include <accmap.hxx>
41 #include <unotools/accessiblerelationsethelper.hxx>
42 // --> OD 2009-07-14 #i73249#
43 #include <hints.hxx>
44 // <--
45 #include "acctextframe.hxx"
46
47 #ifndef _DOC_HXX
48 #include <doc.hxx>
49 #endif
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::accessibility;
52 using ::rtl::OUString;
53
54 using utl::AccessibleRelationSetHelper;
55 using ::com::sun::star::accessibility::XAccessibleContext;
56
57 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextFrameView";
58 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTextFrameView";
59
SwAccessibleTextFrame(SwAccessibleMap * pInitMap,const SwFlyFrm * pFlyFrm)60 SwAccessibleTextFrame::SwAccessibleTextFrame(
61 SwAccessibleMap* pInitMap,
62 const SwFlyFrm* pFlyFrm ) :
63 SwAccessibleFrameBase( pInitMap, AccessibleRole::TEXT_FRAME, pFlyFrm ),
64 msTitle(),
65 msDesc()
66 {
67 if ( pFlyFrm )
68 {
69 const SwFlyFrmFmt* pFlyFrmFmt =
70 dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
71 msTitle = pFlyFrmFmt->GetObjTitle();
72
73 msDesc = pFlyFrmFmt->GetObjDescription();
74 if ( msDesc.getLength() == 0 &&
75 msTitle != GetName() )
76 {
77 msDesc = msTitle;
78 }
79 }
80 }
81
~SwAccessibleTextFrame()82 SwAccessibleTextFrame::~SwAccessibleTextFrame()
83 {
84 }
85
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)86 void SwAccessibleTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
87 {
88 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
89 // --> OD 2009-07-14 #i73249#
90 // suppress handling of RES_NAME_CHANGED in case that attribute Title is
91 // used as the accessible name.
92 if ( nWhich != RES_NAME_CHANGED ||
93 msTitle.getLength() == 0 )
94 {
95 SwAccessibleFrameBase::Modify( pOld, pNew );
96 }
97
98 const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
99 switch( nWhich )
100 {
101 // --> OD 2009-07-14 #i73249#
102 case RES_TITLE_CHANGED:
103 {
104 const String& sOldTitle(
105 dynamic_cast<const SwStringMsgPoolItem*>(pOld)->GetString() );
106 const String& sNewTitle(
107 dynamic_cast<const SwStringMsgPoolItem*>(pNew)->GetString() );
108 if ( sOldTitle == sNewTitle )
109 {
110 break;
111 }
112 msTitle = sNewTitle;
113 AccessibleEventObject aEvent;
114 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
115 aEvent.OldValue <<= OUString( sOldTitle );
116 aEvent.NewValue <<= msTitle;
117 FireAccessibleEvent( aEvent );
118
119 const SwFlyFrmFmt* pFlyFrmFmt =
120 dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
121 if ( pFlyFrmFmt->GetObjDescription().Len() != 0 )
122 {
123 break;
124 }
125 }
126 // intentional no break here
127 case RES_DESCRIPTION_CHANGED:
128 {
129 if ( pFlyFrm )
130 {
131 const OUString sOldDesc( msDesc );
132
133 const SwFlyFrmFmt* pFlyFrmFmt =
134 dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
135 const String& rDesc = pFlyFrmFmt->GetObjDescription();
136 msDesc = rDesc;
137 if ( msDesc.getLength() == 0 &&
138 msTitle != GetName() )
139 {
140 msDesc = msTitle;
141 }
142
143 if ( msDesc != sOldDesc )
144 {
145 AccessibleEventObject aEvent;
146 aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
147 aEvent.OldValue <<= sOldDesc;
148 aEvent.NewValue <<= msDesc;
149 FireAccessibleEvent( aEvent );
150 }
151 }
152 }
153 break;
154 // <--
155 }
156 }
157
158 //===== XInterface ==========================================================
159
160 com::sun::star::uno::Any SAL_CALL
queryInterface(const com::sun::star::uno::Type & rType)161 SwAccessibleTextFrame::queryInterface (const com::sun::star::uno::Type & rType)
162 throw (::com::sun::star::uno::RuntimeException)
163 {
164 ::com::sun::star::uno::Any aReturn = SwAccessibleContext::queryInterface (rType);
165 if ( ! aReturn.hasValue())
166 aReturn = ::cppu::queryInterface (rType,
167 static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this)
168 );
169 return aReturn;
170 }
171
172
173
174
175 void SAL_CALL
acquire(void)176 SwAccessibleTextFrame::acquire (void)
177 throw ()
178 {
179 SwAccessibleContext::acquire ();
180 }
181
182 void SAL_CALL
release(void)183 SwAccessibleTextFrame::release (void)
184 throw ()
185 {
186 SwAccessibleContext::release ();
187 }
188
189 //
190 //===== XAccessibleSelection ============================================
191 //
192
193 //--------------------------------------------------------------------------------
selectAccessibleChild(sal_Int32)194 void SAL_CALL SwAccessibleTextFrame::selectAccessibleChild( sal_Int32 )
195 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
196 {
197 DBG_ASSERT( false, "<SwAccessibleTextFrame::selectAccessibleChild( sal_Int32 )> - missing implementation" );
198 }
199
200 //----------------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)201 sal_Bool SAL_CALL SwAccessibleTextFrame::isAccessibleChildSelected( sal_Int32 nChildIndex )
202 throw (lang::IndexOutOfBoundsException, uno::RuntimeException )
203 {
204 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
205 uno::Reference<XAccessibleContext> xContext;
206 if( xAcc.is() )
207 xContext = xAcc->getAccessibleContext();
208
209 if( xContext.is() )
210 {
211 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
212 {
213 uno::Reference< ::com::sun::star::accessibility::XAccessibleText >
214 xText(xAcc, uno::UNO_QUERY);
215 if( xText.is() )
216 {
217 if( xText->getSelectionStart() >= 0 ) return sal_True;
218 }
219 }
220 }
221
222 return sal_False;
223 }
224
225 //---------------------------------------------------------------------
clearAccessibleSelection()226 void SAL_CALL SwAccessibleTextFrame::clearAccessibleSelection( )
227 throw ( uno::RuntimeException )
228 {
229 DBG_ASSERT( false, "<SwAccessibleTextFrame::clearAccessibleSelection( )> - missing implementation" );
230 }
231
232 //-------------------------------------------------------------------------
selectAllAccessibleChildren()233 void SAL_CALL SwAccessibleTextFrame::selectAllAccessibleChildren( )
234 throw ( uno::RuntimeException )
235 {
236 DBG_ASSERT( false, "<SwAccessibleTextFrame::selectAllAccessibleChildren( )> - missing implementation" );
237 }
238
239 //----------------------------------------------------------------------------
getSelectedAccessibleChildCount()240 sal_Int32 SAL_CALL SwAccessibleTextFrame::getSelectedAccessibleChildCount()
241 throw ( uno::RuntimeException )
242 {
243 sal_Int32 nCount = 0;
244 sal_Int32 TotalCount = getAccessibleChildCount();
245 for( sal_Int32 i = 0; i < TotalCount; i++ )
246 if( isAccessibleChildSelected(i) ) nCount++;
247
248 return nCount;
249 }
250
251 //--------------------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)252 uno::Reference<XAccessible> SAL_CALL SwAccessibleTextFrame::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
253 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException)
254 {
255 if ( nSelectedChildIndex > getSelectedAccessibleChildCount() )
256 throw lang::IndexOutOfBoundsException();
257 sal_Int32 i1, i2;
258 for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
259 if( isAccessibleChildSelected(i1) )
260 {
261 if( i2 == nSelectedChildIndex )
262 return getAccessibleChild( i1 );
263 i2++;
264 }
265 return uno::Reference<XAccessible>();
266 }
267
268 //----------------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32)269 void SAL_CALL SwAccessibleTextFrame::deselectAccessibleChild( sal_Int32 )
270 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
271 {
272 DBG_ASSERT( false, "<SwAccessibleTextFrame::selectAllAccessibleChildren( sal_Int32 )> - missing implementation" );
273 }
274
275 // --> OD 2009-07-14 #i73249#
getAccessibleName(void)276 OUString SAL_CALL SwAccessibleTextFrame::getAccessibleName (void)
277 throw (uno::RuntimeException)
278 {
279 vos::OGuard aGuard(Application::GetSolarMutex());
280
281 CHECK_FOR_DEFUNC( XAccessibleContext )
282
283 if ( msTitle.getLength() != 0 )
284 {
285 return msTitle;
286 }
287
288 return SwAccessibleFrameBase::getAccessibleName();
289 }
290 // <--
291
getAccessibleDescription(void)292 OUString SAL_CALL SwAccessibleTextFrame::getAccessibleDescription (void)
293 throw (uno::RuntimeException)
294 {
295 vos::OGuard aGuard(Application::GetSolarMutex());
296
297 CHECK_FOR_DEFUNC( XAccessibleContext )
298 /* MT: I guess msDesc is correct noadays?
299 OUString longDesc;
300 const SwFlyFrmFmt* pFlyFmt = GetShell()->GetDoc()->FindFlyByName( GetName(), 0);
301 if( pFlyFmt )
302 {
303 longDesc = OUString( pFlyFmt->GetDescription() );
304 }
305 if( longDesc.getLength() > 0 )
306 return GetName() + OUString(' ') + longDesc;
307 else
308 return GetName();
309 */
310
311 return msDesc;
312 }
313
getImplementationName()314 OUString SAL_CALL SwAccessibleTextFrame::getImplementationName()
315 throw( uno::RuntimeException )
316 {
317 return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
318 }
319
supportsService(const OUString & sTestServiceName)320 sal_Bool SAL_CALL SwAccessibleTextFrame::supportsService(
321 const OUString& sTestServiceName)
322 throw (uno::RuntimeException)
323 {
324 return sTestServiceName.equalsAsciiL( sServiceName,
325 sizeof(sServiceName)-1 ) ||
326 sTestServiceName.equalsAsciiL( sAccessibleServiceName,
327 sizeof(sAccessibleServiceName)-1 );
328 }
329
getSupportedServiceNames()330 uno::Sequence< OUString > SAL_CALL SwAccessibleTextFrame::getSupportedServiceNames()
331 throw( uno::RuntimeException )
332 {
333 uno::Sequence< OUString > aRet(2);
334 OUString* pArray = aRet.getArray();
335 pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
336 pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
337 return aRet;
338 }
339
getImplementationId()340 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTextFrame::getImplementationId()
341 throw(uno::RuntimeException)
342 {
343 vos::OGuard aGuard(Application::GetSolarMutex());
344 static uno::Sequence< sal_Int8 > aId( 16 );
345 static sal_Bool bInit = sal_False;
346 if(!bInit)
347 {
348 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
349 bInit = sal_True;
350 }
351 return aId;
352 }
353
354
355 //
356 // XAccessibleRelationSet
357 //
358
359
getFlyFrm() const360 SwFlyFrm* SwAccessibleTextFrame::getFlyFrm() const
361 {
362 SwFlyFrm* pFlyFrm = NULL;
363
364 const SwFrm* pFrm = GetFrm();
365 DBG_ASSERT( pFrm != NULL, "frame expected" );
366 if( pFrm->IsFlyFrm() )
367 {
368 pFlyFrm = static_cast<SwFlyFrm*>( const_cast<SwFrm*>( pFrm ) );
369 }
370
371 return pFlyFrm;
372 }
373
makeRelation(sal_Int16 nType,const SwFlyFrm * pFrm)374 AccessibleRelation SwAccessibleTextFrame::makeRelation( sal_Int16 nType, const SwFlyFrm* pFrm )
375 {
376 uno::Sequence<uno::Reference<XInterface> > aSequence(1);
377 aSequence[0] = GetMap()->GetContext( pFrm );
378 return AccessibleRelation( nType, aSequence );
379 }
380
381
getAccessibleRelationSet()382 uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleTextFrame::getAccessibleRelationSet( )
383 throw ( uno::RuntimeException )
384 {
385 vos::OGuard aGuard(Application::GetSolarMutex());
386 CHECK_FOR_DEFUNC( XAccessibleContext );
387
388 // get the frame, and insert prev/next relations into helper
389
390 AccessibleRelationSetHelper* pHelper = new AccessibleRelationSetHelper();
391
392 SwFlyFrm* pFlyFrm = getFlyFrm();
393 DBG_ASSERT( pFlyFrm != NULL, "fly frame expected" );
394
395 const SwFlyFrm* pPrevFrm = pFlyFrm->GetPrevLink();
396 if( pPrevFrm != NULL )
397 pHelper->AddRelation( makeRelation(
398 AccessibleRelationType::CONTENT_FLOWS_FROM, pPrevFrm ) );
399
400 const SwFlyFrm* pNextFrm = pFlyFrm->GetNextLink();
401 if( pNextFrm != NULL )
402 pHelper->AddRelation( makeRelation(
403 AccessibleRelationType::CONTENT_FLOWS_TO, pNextFrm ) );
404
405 return pHelper;
406 }
407