xref: /AOO41X/main/sw/source/core/access/accselectionhelper.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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 <com/sun/star/accessibility/XAccessibleSelection.hpp>
29 #include <accselectionhelper.hxx>
30 
31 #include <acccontext.hxx>
32 #include <accmap.hxx>
33 #include <svx/AccessibleShape.hxx>
34 #include <viewsh.hxx>
35 #include <fesh.hxx>
36 #include <vcl/svapp.hxx>        // for SolarMutex
37 #include <tools/debug.hxx>
38 #include <flyfrm.hxx>
39 
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 
44 using ::com::sun::star::accessibility::XAccessible;
45 using ::com::sun::star::accessibility::XAccessibleContext;
46 using ::com::sun::star::accessibility::XAccessibleSelection;
47 
48 using namespace ::sw::access;
49 
50 SwAccessibleSelectionHelper::SwAccessibleSelectionHelper(
51     SwAccessibleContext& rCtxt ) :
52         rContext( rCtxt )
53 {
54 }
55 
56 SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper()
57 {
58 }
59 
60 SwFEShell* SwAccessibleSelectionHelper::GetFEShell()
61 {
62     DBG_ASSERT( rContext.GetMap() != NULL, "no map?" );
63     ViewShell* pViewShell = rContext.GetMap()->GetShell();
64     DBG_ASSERT( pViewShell != NULL,
65                 "No view shell? Then what are you looking at?" );
66 
67     SwFEShell* pFEShell = NULL;
68     if( pViewShell->ISA( SwFEShell ) )
69     {
70         pFEShell = static_cast<SwFEShell*>( pViewShell );
71     }
72 
73     return pFEShell;
74 }
75 
76 void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException()
77         throw ( lang::IndexOutOfBoundsException )
78 {
79     Reference < XAccessibleContext > xThis( &rContext );
80     Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY );
81     lang::IndexOutOfBoundsException aExcept(
82                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
83                 xSelThis );                                     \
84     throw aExcept;
85 }
86 
87 
88 //=====  XAccessibleSelection  ============================================
89 
90 void SwAccessibleSelectionHelper::selectAccessibleChild(
91     sal_Int32 nChildIndex )
92     throw ( lang::IndexOutOfBoundsException,
93             RuntimeException )
94 {
95     vos::OGuard aGuard(Application::GetSolarMutex());
96 
97     // Get the respective child as SwFrm (also do index checking), ...
98     const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
99                                                         nChildIndex );
100     if( !aChild.IsValid() )
101         throwIndexOutOfBoundsException();
102 
103     // we can only select fly frames, so we ignore (should: return
104     // false) all other attempts at child selection
105     sal_Bool bRet = sal_False;
106     SwFEShell* pFEShell = GetFEShell();
107     if( pFEShell != NULL )
108     {
109         const SdrObject *pObj = aChild.GetDrawObject();
110         if( pObj )
111         {
112             bRet = rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm());
113         }
114     }
115     // no frame shell, or no frame, or no fly frame -> can't select
116 
117     // return bRet;
118 }
119 
120 sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected(
121     sal_Int32 nChildIndex )
122     throw ( lang::IndexOutOfBoundsException,
123             RuntimeException )
124 {
125     vos::OGuard aGuard(Application::GetSolarMutex());
126 
127     // Get the respective child as SwFrm (also do index checking), ...
128     const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
129                                                         nChildIndex );
130     if( !aChild.IsValid() )
131         throwIndexOutOfBoundsException();
132 
133     // ... and compare to the currently selected frame
134     sal_Bool bRet = sal_False;
135     SwFEShell* pFEShell = GetFEShell();
136     if( pFEShell )
137     {
138         if ( aChild.GetSwFrm() != 0 )
139         {
140             bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm());
141         }
142         else if ( aChild.GetDrawObject() )
143         {
144             bRet = pFEShell->IsObjSelected( *aChild.GetDrawObject() );
145         }
146     }
147 
148     return bRet;
149 }
150 
151 void SwAccessibleSelectionHelper::clearAccessibleSelection(  )
152     throw ( RuntimeException )
153 {
154     // return sal_False     // we can't deselect
155 }
156 
157 void SwAccessibleSelectionHelper::selectAllAccessibleChildren(  )
158     throw ( RuntimeException )
159 {
160     vos::OGuard aGuard(Application::GetSolarMutex());
161 
162     // We can select only one. So iterate over the children to find
163     // the first we can select, and select it.
164 
165     SwFEShell* pFEShell = GetFEShell();
166     if( pFEShell )
167     {
168         ::std::list< SwAccessibleChild > aChildren;
169         rContext.GetChildren( *(rContext.GetMap()), aChildren );
170 
171         ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
172         ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
173         while( aIter != aEndIter )
174         {
175             const SwAccessibleChild& rChild = *aIter;
176             const SdrObject* pObj = rChild.GetDrawObject();
177             const SwFrm* pFrm = rChild.GetSwFrm();
178             if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) )
179             {
180                 rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm );
181                 if( pFrm )
182                     break;
183             }
184             ++aIter;
185         }
186     }
187 }
188 
189 sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount(  )
190     throw ( RuntimeException )
191 {
192     vos::OGuard aGuard(Application::GetSolarMutex());
193 
194     sal_Int32 nCount = 0;
195     // Only one frame can be selected at a time, and we only frames
196     // for selectable children.
197     SwFEShell* pFEShell = GetFEShell();
198     if( pFEShell != 0 )
199     {
200         const SwFlyFrm* pFlyFrm = pFEShell->GetCurrFlyFrm();
201         if( pFlyFrm )
202         {
203             if( rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
204                     rContext.GetFrm() )
205             {
206                 nCount = 1;
207             }
208         }
209         else
210         {
211             sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
212             if( nSelObjs > 0 )
213             {
214                 ::std::list< SwAccessibleChild > aChildren;
215                 rContext.GetChildren( *(rContext.GetMap()), aChildren );
216 
217                 ::std::list< SwAccessibleChild >::const_iterator aIter =
218                     aChildren.begin();
219                 ::std::list< SwAccessibleChild >::const_iterator aEndIter =
220                     aChildren.end();
221                 while( aIter != aEndIter && nCount < nSelObjs )
222                 {
223                     const SwAccessibleChild& rChild = *aIter;
224                     if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
225                         rContext.GetParent(rChild, rContext.IsInPagePreview())
226                            == rContext.GetFrm() &&
227                         pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
228                     {
229                         nCount++;
230                     }
231                     ++aIter;
232                 }
233             }
234         }
235     }
236     return nCount;
237 }
238 
239 Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild(
240     sal_Int32 nSelectedChildIndex )
241     throw ( lang::IndexOutOfBoundsException,
242             RuntimeException)
243 {
244     vos::OGuard aGuard(Application::GetSolarMutex());
245 
246     // Since the index is relative to the selected children, and since
247     // there can be at most one selected frame child, the index must
248     // be 0, and a selection must exist, otherwise we have to throw an
249     // lang::IndexOutOfBoundsException
250     SwFEShell* pFEShell = GetFEShell();
251     if( 0 == pFEShell )
252         throwIndexOutOfBoundsException();
253 
254     SwAccessibleChild aChild;
255     const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
256     if( pFlyFrm )
257     {
258         if( 0 == nSelectedChildIndex &&
259             rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
260                 rContext.GetFrm() )
261         {
262             aChild = pFlyFrm;
263         }
264     }
265     else
266     {
267         sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
268         if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs )
269             throwIndexOutOfBoundsException();
270 
271         ::std::list< SwAccessibleChild > aChildren;
272         rContext.GetChildren( *(rContext.GetMap()), aChildren );
273 
274         ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
275         ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
276         while( aIter != aEndIter && !aChild.IsValid() )
277         {
278             const SwAccessibleChild& rChild = *aIter;
279             if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
280                 rContext.GetParent(rChild, rContext.IsInPagePreview()) ==
281                     rContext.GetFrm() &&
282                 pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
283             {
284                 if( 0 == nSelectedChildIndex )
285                     aChild = rChild;
286                 else
287                     --nSelectedChildIndex;
288             }
289             ++aIter;
290         }
291     }
292 
293     if( !aChild.IsValid() )
294         throwIndexOutOfBoundsException();
295 
296     DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." );
297     Reference< XAccessible > xChild;
298     if( aChild.GetSwFrm() )
299     {
300         ::vos::ORef < SwAccessibleContext > xChildImpl(
301                 rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(),
302                 sal_True ) );
303         if( xChildImpl.isValid() )
304         {
305             xChildImpl->SetParent( &rContext );
306             xChild = xChildImpl.getBodyPtr();
307         }
308     }
309     else if ( aChild.GetDrawObject() )
310     {
311         ::vos::ORef < ::accessibility::AccessibleShape > xChildImpl(
312                 rContext.GetMap()->GetContextImpl( aChild.GetDrawObject(),
313                                           &rContext, sal_True )  );
314         if( xChildImpl.isValid() )
315             xChild = xChildImpl.getBodyPtr();
316     }
317     return xChild;
318 }
319 
320 // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
321 void SwAccessibleSelectionHelper::deselectAccessibleChild(
322     sal_Int32 nChildIndex )
323     throw ( lang::IndexOutOfBoundsException,
324             RuntimeException )
325 {
326     // return sal_False     // we can't deselect
327     if( nChildIndex < 0 ||
328         nChildIndex >= rContext.GetChildCount( *(rContext.GetMap()) ) )
329         throwIndexOutOfBoundsException();
330 }
331