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 //------------------------------------------------------------------------
28 //
29 // Global header
30 //
31 //------------------------------------------------------------------------
32 #include <com/sun/star/uno/Any.hxx>
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <cppuhelper/weakref.hxx>
35 #include <com/sun/star/accessibility/XAccessible.hpp>
36 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 
38 //------------------------------------------------------------------------
39 //
40 // Project-local header
41 //
42 //------------------------------------------------------------------------
43 
44 #include <editeng/unoedhlp.hxx>
45 #include <editeng/unopracc.hxx>
46 #include <editeng/unoedsrc.hxx>
47 #include "editeng/AccessibleParaManager.hxx"
48 #include "editeng/AccessibleEditableTextPara.hxx"
49 
50 
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::accessibility;
53 
54 
55 
56 namespace accessibility
57 {
58     AccessibleParaManager::AccessibleParaManager() :
59         maChildren(1),
60         maEEOffset( 0, 0 ),
61         mnFocusedChild( -1 ),
62         mbActive( sal_False )
63     {
64     }
65 
66     AccessibleParaManager::~AccessibleParaManager()
67     {
68         // owner is responsible for possible child defuncs
69     }
70 
71     void AccessibleParaManager::SetAdditionalChildStates( const VectorOfStates& rChildStates )
72     {
73         maChildStates = rChildStates;
74     }
75 
76     const AccessibleParaManager::VectorOfStates& AccessibleParaManager::GetAdditionalChildStates() const
77     {
78         return maChildStates;
79     }
80 
81     void AccessibleParaManager::SetNum( sal_Int32 nNumParas )
82     {
83         if( (size_t)nNumParas < maChildren.size() )
84             Release( nNumParas, maChildren.size() );
85 
86         maChildren.resize( nNumParas );
87 
88         if( mnFocusedChild >= nNumParas )
89             mnFocusedChild = -1;
90     }
91 
92     sal_uInt32 AccessibleParaManager::GetNum() const
93     {
94         return maChildren.size();
95     }
96 
97     AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin()
98     {
99         return maChildren.begin();
100     }
101 
102     AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end()
103     {
104         return maChildren.end();
105     }
106 
107     AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::begin() const
108     {
109         return maChildren.begin();
110     }
111 
112     AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::end() const
113     {
114         return maChildren.end();
115     }
116 
117     void AccessibleParaManager::Release( sal_uInt32 nPara )
118     {
119         DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::Release: invalid index" );
120 
121         if( maChildren.size() > nPara )
122         {
123             ShutdownPara( GetChild( nPara ) );
124 
125             // clear reference and rect
126             maChildren[ nPara ] = WeakChild();
127         }
128     }
129 
130     void AccessibleParaManager::FireEvent( sal_uInt32 nPara,
131                                            const sal_Int16 nEventId,
132                                            const uno::Any& rNewValue,
133                                            const uno::Any& rOldValue ) const
134     {
135         DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::FireEvent: invalid index" );
136 
137         if( maChildren.size() > nPara )
138         {
139             WeakPara::HardRefType maChild( GetChild( nPara ).first.get() );
140             if( maChild.is() )
141                 maChild->FireEvent( nEventId, rNewValue, rOldValue );
142         }
143     }
144 
145     sal_Bool AccessibleParaManager::IsReferencable( WeakPara::HardRefType aChild )
146     {
147         return aChild.is();
148     }
149 
150     sal_Bool AccessibleParaManager::IsReferencable( sal_uInt32 nChild ) const
151     {
152         DBG_ASSERT( maChildren.size() > nChild, "AccessibleParaManager::IsReferencable: invalid index" );
153 
154         if( maChildren.size() > nChild )
155         {
156             // retrieve hard reference from weak one
157             return IsReferencable( GetChild( nChild ).first.get() );
158         }
159         else
160         {
161             return sal_False;
162         }
163     }
164 
165     AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_uInt32 nParagraphIndex ) const
166     {
167         DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::GetChild: invalid index" );
168 
169         if( maChildren.size() > nParagraphIndex )
170         {
171             return maChildren[ nParagraphIndex ];
172         }
173         else
174         {
175             return WeakChild();
176         }
177     }
178 
179     AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 								nChild,
180                                                                      const uno::Reference< XAccessible >& 	xFrontEnd,
181                                                                      SvxEditSourceAdapter& 					rEditSource,
182                                                                      sal_uInt32 							nParagraphIndex	)
183     {
184         DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::CreateChild: invalid index" );
185 
186         if( maChildren.size() > nParagraphIndex )
187         {
188             // retrieve hard reference from weak one
189             WeakPara::HardRefType aChild( GetChild( nParagraphIndex ).first.get() );
190 
191             if( !IsReferencable( nParagraphIndex ) )
192             {
193                 // there is no hard reference available, create object then
194                 // --> OD 2006-01-11 #i27138#
195                 AccessibleEditableTextPara* pChild = new AccessibleEditableTextPara( xFrontEnd, this );
196                 // <--
197                 uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY );
198 
199                 if( !xChild.is() )
200                     throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), xFrontEnd);
201 
202                 aChild = WeakPara::HardRefType( xChild, pChild );
203 
204                 InitChild( *aChild, rEditSource, nChild, nParagraphIndex );
205 
206                 maChildren[ nParagraphIndex ] = WeakChild( aChild, pChild->getBounds() );
207             }
208 
209             return Child( aChild.getRef(), GetChild( nParagraphIndex ).second );
210         }
211         else
212         {
213             return Child();
214         }
215     }
216 
217     void AccessibleParaManager::SetEEOffset( const Point& rOffset )
218     {
219         maEEOffset = rOffset;
220 
221         MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset );
222         ::std::for_each( begin(), end(), aAdapter );
223     }
224 
225     void AccessibleParaManager::SetActive( sal_Bool bActive )
226     {
227         mbActive = bActive;
228 
229         if( bActive )
230         {
231             SetState( AccessibleStateType::ACTIVE );
232             SetState( AccessibleStateType::EDITABLE );
233         }
234         else
235         {
236             UnSetState( AccessibleStateType::ACTIVE );
237             UnSetState( AccessibleStateType::EDITABLE );
238         }
239     }
240 
241     void AccessibleParaManager::SetFocus( sal_Int32 nChild )
242     {
243         if( mnFocusedChild != -1 )
244             UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED );
245 
246         mnFocusedChild = nChild;
247 
248         if( mnFocusedChild != -1 )
249             SetState( mnFocusedChild, AccessibleStateType::FOCUSED );
250     }
251 
252     void AccessibleParaManager::InitChild( AccessibleEditableTextPara& 	rChild,
253                                            SvxEditSourceAdapter& 		rEditSource,
254                                            sal_Int32 					nChild,
255                                            sal_uInt32 					nParagraphIndex ) const
256     {
257         rChild.SetEditSource( &rEditSource );
258         rChild.SetIndexInParent( nChild );
259         rChild.SetParagraphIndex( nParagraphIndex );
260 
261         rChild.SetEEOffset( maEEOffset );
262 
263         if( mbActive )
264         {
265             rChild.SetState( AccessibleStateType::ACTIVE );
266             rChild.SetState( AccessibleStateType::EDITABLE );
267         }
268 
269         if( mnFocusedChild == static_cast<sal_Int32>(nParagraphIndex) )
270             rChild.SetState( AccessibleStateType::FOCUSED );
271 
272         // add states passed from outside
273         for( VectorOfStates::const_iterator aIt = maChildStates.begin(), aEnd = maChildStates.end(); aIt != aEnd; ++aIt )
274             rChild.SetState( *aIt );
275     }
276 
277     void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int16 nStateId )
278     {
279         MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::SetState,
280                                                 nStateId );
281         aFunc( GetChild(nChild) );
282     }
283 
284     void AccessibleParaManager::SetState( const sal_Int16 nStateId )
285     {
286         ::std::for_each( begin(), end(),
287                          MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::SetState,
288                                                            nStateId ) );
289     }
290 
291     void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int16 nStateId )
292     {
293         MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::UnSetState,
294                                                 nStateId );
295         aFunc( GetChild(nChild) );
296     }
297 
298     void AccessibleParaManager::UnSetState( const sal_Int16 nStateId )
299     {
300         ::std::for_each( begin(), end(),
301                          MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::UnSetState,
302                                                            nStateId ) );
303     }
304 
305     void AccessibleParaManager::SetEditSource( SvxEditSourceAdapter* pEditSource )
306     {
307         MemFunAdapter< SvxEditSourceAdapter* > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEditSource, pEditSource );
308         ::std::for_each( begin(), end(), aAdapter );
309     }
310 
311     // not generic yet, no arguments...
312     class AccessibleParaManager_DisposeChildren : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
313     {
314     public:
315         AccessibleParaManager_DisposeChildren() {}
316         void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
317         {
318             rPara.Dispose();
319         }
320     };
321 
322     void AccessibleParaManager::Dispose()
323     {
324         AccessibleParaManager_DisposeChildren aFunctor;
325 
326         ::std::for_each( begin(), end(),
327                          WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) );
328     }
329 
330     // not generic yet, too many method arguments...
331     class StateChangeEvent : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
332     {
333     public:
334         typedef void return_type;
335         StateChangeEvent( const sal_Int16 nEventId,
336                           const uno::Any& rNewValue,
337                           const uno::Any& rOldValue ) :
338             mnEventId( nEventId ),
339             mrNewValue( rNewValue ),
340             mrOldValue( rOldValue ) {}
341         void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
342         {
343             rPara.FireEvent( mnEventId, mrNewValue, mrOldValue );
344         }
345 
346     private:
347         const sal_Int16 mnEventId;
348         const uno::Any& mrNewValue;
349         const uno::Any& mrOldValue;
350     };
351 
352     void AccessibleParaManager::FireEvent( sal_uInt32 nStartPara,
353                                            sal_uInt32 nEndPara,
354                                            const sal_Int16 nEventId,
355                                            const uno::Any& rNewValue,
356                                            const uno::Any& rOldValue ) const
357     {
358         DBG_ASSERT( maChildren.size() > nStartPara &&
359                     maChildren.size() >= nEndPara , "AccessibleParaManager::FireEvent: invalid index" );
360 
361         if( maChildren.size() > nStartPara &&
362             maChildren.size() >= nEndPara )
363         {
364             VectorOfChildren::const_iterator front = maChildren.begin();
365             VectorOfChildren::const_iterator back = front;
366 
367             ::std::advance( front, nStartPara );
368             ::std::advance( back, nEndPara );
369 
370             StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue );
371 
372             ::std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) );
373         }
374     }
375 
376     class ReleaseChild : public ::std::unary_function< const AccessibleParaManager::WeakChild&, AccessibleParaManager::WeakChild >
377     {
378     public:
379         AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara )
380         {
381             AccessibleParaManager::ShutdownPara( rPara );
382 
383             // clear reference
384             return AccessibleParaManager::WeakChild();
385         }
386     };
387 
388     void AccessibleParaManager::Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara )
389     {
390         DBG_ASSERT( maChildren.size() > nStartPara &&
391                     maChildren.size() >= nEndPara, "AccessibleParaManager::Release: invalid index" );
392 
393         if( maChildren.size() > nStartPara &&
394             maChildren.size() >= nEndPara )
395         {
396             VectorOfChildren::iterator front = maChildren.begin();
397             VectorOfChildren::iterator back = front;
398 
399             ::std::advance( front, nStartPara );
400             ::std::advance( back, nEndPara );
401 
402             ::std::transform( front, back, front, ReleaseChild() );
403         }
404     }
405 
406     void AccessibleParaManager::ShutdownPara( const WeakChild& rChild )
407     {
408         WeakPara::HardRefType aChild( rChild.first.get() );
409 
410         if( IsReferencable( aChild ) )
411             aChild->SetEditSource( NULL );
412     }
413 
414 }
415 
416 //------------------------------------------------------------------------
417