1  /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
32 #include <rtl/uuid.h>
33 #include <vos/mutex.hxx>
34 #include <vcl/svapp.hxx>
35 #include <com/sun/star/accessibility/AccessibleRole.hpp>
36 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
38 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
39 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <unotools/accessiblestatesethelper.hxx>
42 #include <frmfmt.hxx>
43 #include <flyfrm.hxx>
44 #include <accmap.hxx>
45 #include <unotools/accessiblerelationsethelper.hxx>
46 // --> OD 2009-07-14 #i73249#
47 #include <hints.hxx>
48 // <--
49 #include "acctextframe.hxx"
50 
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::accessibility;
53 using ::rtl::OUString;
54 
55 using utl::AccessibleRelationSetHelper;
56 using ::com::sun::star::accessibility::XAccessibleContext;
57 
58 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextFrameView";
59 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTextFrameView";
60 
61 SwAccessibleTextFrame::SwAccessibleTextFrame(
62         SwAccessibleMap* pInitMap,
63         const SwFlyFrm* pFlyFrm  ) :
64     SwAccessibleFrameBase( pInitMap, AccessibleRole::TEXT_FRAME, pFlyFrm ),
65     msTitle(),
66     msDesc()
67 {
68     if ( pFlyFrm )
69     {
70         const SwFlyFrmFmt* pFlyFrmFmt =
71                         dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
72         msTitle = pFlyFrmFmt->GetObjTitle();
73 
74         msDesc = pFlyFrmFmt->GetObjDescription();
75         if ( msDesc.getLength() == 0 &&
76              msTitle != GetName() )
77         {
78             msDesc = msTitle;
79         }
80     }
81 }
82 
83 SwAccessibleTextFrame::~SwAccessibleTextFrame()
84 {
85 }
86 
87 void SwAccessibleTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
88 {
89     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
90     // --> OD 2009-07-14 #i73249#
91     // suppress handling of RES_NAME_CHANGED in case that attribute Title is
92     // used as the accessible name.
93     if ( nWhich != RES_NAME_CHANGED ||
94          msTitle.getLength() == 0 )
95     {
96         SwAccessibleFrameBase::Modify( pOld, pNew );
97     }
98 
99     const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
100 	switch( nWhich )
101 	{
102         // --> OD 2009-07-14 #i73249#
103         case RES_TITLE_CHANGED:
104         {
105             const String& sOldTitle(
106                         dynamic_cast<const SwStringMsgPoolItem*>(pOld)->GetString() );
107             const String& sNewTitle(
108                         dynamic_cast<const SwStringMsgPoolItem*>(pNew)->GetString() );
109             if ( sOldTitle == sNewTitle )
110             {
111                 break;
112             }
113             msTitle = sNewTitle;
114             AccessibleEventObject aEvent;
115             aEvent.EventId = AccessibleEventId::NAME_CHANGED;
116             aEvent.OldValue <<= OUString( sOldTitle );
117             aEvent.NewValue <<= msTitle;
118             FireAccessibleEvent( aEvent );
119 
120             const SwFlyFrmFmt* pFlyFrmFmt =
121                             dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
122             if ( pFlyFrmFmt->GetObjDescription().Len() != 0 )
123             {
124                 break;
125             }
126         }
127         // intentional no break here
128         case RES_DESCRIPTION_CHANGED:
129         {
130             if ( pFlyFrm )
131             {
132                 const OUString sOldDesc( msDesc );
133 
134                 const SwFlyFrmFmt* pFlyFrmFmt =
135                                 dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
136                 const String& rDesc = pFlyFrmFmt->GetObjDescription();
137                 msDesc = rDesc;
138                 if ( msDesc.getLength() == 0 &&
139                      msTitle != GetName() )
140                 {
141                     msDesc = msTitle;
142                 }
143 
144                 if ( msDesc != sOldDesc )
145                 {
146                     AccessibleEventObject aEvent;
147                     aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
148                     aEvent.OldValue <<= sOldDesc;
149                     aEvent.NewValue <<= msDesc;
150                     FireAccessibleEvent( aEvent );
151                 }
152             }
153         }
154         break;
155         // <--
156 	}
157 }
158 
159 // --> OD 2009-07-14 #i73249#
160 OUString SAL_CALL SwAccessibleTextFrame::getAccessibleName (void)
161         throw (uno::RuntimeException)
162 {
163     vos::OGuard aGuard(Application::GetSolarMutex());
164 
165     CHECK_FOR_DEFUNC( XAccessibleContext )
166 
167     if ( msTitle.getLength() != 0 )
168     {
169         return msTitle;
170     }
171 
172     return SwAccessibleFrameBase::getAccessibleName();
173 }
174 // <--
175 OUString SAL_CALL SwAccessibleTextFrame::getAccessibleDescription (void)
176         throw (uno::RuntimeException)
177 {
178 	vos::OGuard aGuard(Application::GetSolarMutex());
179 
180     CHECK_FOR_DEFUNC( XAccessibleContext )
181 
182     return msDesc;
183 
184 }
185 
186 OUString SAL_CALL SwAccessibleTextFrame::getImplementationName()
187         throw( uno::RuntimeException )
188 {
189 	return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
190 }
191 
192 sal_Bool SAL_CALL SwAccessibleTextFrame::supportsService(
193         const OUString& sTestServiceName)
194     throw (uno::RuntimeException)
195 {
196 	return sTestServiceName.equalsAsciiL( sServiceName,
197 										  sizeof(sServiceName)-1 ) ||
198 		   sTestServiceName.equalsAsciiL( sAccessibleServiceName,
199 				   						  sizeof(sAccessibleServiceName)-1 );
200 }
201 
202 uno::Sequence< OUString > SAL_CALL SwAccessibleTextFrame::getSupportedServiceNames()
203 		throw( uno::RuntimeException )
204 {
205 	uno::Sequence< OUString > aRet(2);
206 	OUString* pArray = aRet.getArray();
207 	pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
208 	pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
209 	return aRet;
210 }
211 
212 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTextFrame::getImplementationId()
213 		throw(uno::RuntimeException)
214 {
215     vos::OGuard aGuard(Application::GetSolarMutex());
216     static uno::Sequence< sal_Int8 > aId( 16 );
217     static sal_Bool bInit = sal_False;
218     if(!bInit)
219     {
220         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
221         bInit = sal_True;
222     }
223     return aId;
224 }
225 
226 
227 //
228 // XAccessibleRelationSet
229 //
230 
231 
232 SwFlyFrm* SwAccessibleTextFrame::getFlyFrm() const
233 {
234 	SwFlyFrm* pFlyFrm = NULL;
235 
236 	const SwFrm* pFrm = GetFrm();
237 	DBG_ASSERT( pFrm != NULL, "frame expected" );
238 	if( pFrm->IsFlyFrm() )
239 	{
240 		pFlyFrm = static_cast<SwFlyFrm*>( const_cast<SwFrm*>( pFrm ) );
241 	}
242 
243 	return pFlyFrm;
244 }
245 
246 AccessibleRelation SwAccessibleTextFrame::makeRelation( sal_Int16 nType, const SwFlyFrm* pFrm )
247 {
248     uno::Sequence<uno::Reference<XInterface> > aSequence(1);
249     aSequence[0] = GetMap()->GetContext( pFrm );
250 	return AccessibleRelation( nType, aSequence );
251 }
252 
253 
254 uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleTextFrame::getAccessibleRelationSet( )
255     throw ( uno::RuntimeException )
256 {
257 	vos::OGuard aGuard(Application::GetSolarMutex());
258     CHECK_FOR_DEFUNC( XAccessibleContext );
259 
260     // get the frame, and insert prev/next relations into helper
261 
262     AccessibleRelationSetHelper* pHelper = new AccessibleRelationSetHelper();
263 
264 	SwFlyFrm* pFlyFrm = getFlyFrm();
265 	DBG_ASSERT( pFlyFrm != NULL, "fly frame expected" );
266 
267 	const SwFlyFrm* pPrevFrm = pFlyFrm->GetPrevLink();
268     if( pPrevFrm != NULL )
269         pHelper->AddRelation( makeRelation(
270             AccessibleRelationType::CONTENT_FLOWS_FROM, pPrevFrm ) );
271 
272 	const SwFlyFrm* pNextFrm = pFlyFrm->GetNextLink();
273     if( pNextFrm != NULL )
274         pHelper->AddRelation( makeRelation(
275             AccessibleRelationType::CONTENT_FLOWS_TO, pNextFrm ) );
276 
277 	return pHelper;
278 }
279