xref: /trunk/main/sw/source/core/access/accframe.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 
32 
33 #include <hintids.hxx>
34 #include <editeng/brshitem.hxx>
35 #include <flyfrm.hxx>
36 #include <rootfrm.hxx>
37 #include <txtfrm.hxx>
38 #include <sectfrm.hxx>
39 #include <pagefrm.hxx>
40 #include <section.hxx>
41 #include <viewsh.hxx>
42 #include <viewopt.hxx>
43 #include <doc.hxx>
44 #include <frmatr.hxx>
45 #include <pagefrm.hxx>
46 #include <pagedesc.hxx>
47 #include <fmtanchr.hxx>
48 #include <fldbas.hxx>
49 #include <dcontact.hxx>
50 #include <accmap.hxx>
51 #include <accfrmobjslist.hxx>
52 #include <accfrmobjmap.hxx>
53 #include <accframe.hxx>
54 
55 using namespace sw::access;
56 
57 // Regarding visibilily (or in terms of accessibility: regarding the showing
58 // state): A frame is visible and therfor contained in the tree if its frame
59 // size overlaps with the visible area. The bounding box however is the
60 // frame's paint area.
61 /* static */ sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap,
62                                                          const SwRect& rVisArea,
63                                                          const SwFrm *pFrm,
64                                                          sal_Bool bInPagePreview )
65 {
66     sal_Int32 nCount = 0;
67 
68     const SwAccessibleChildSList aVisList( rVisArea, *pFrm, rAccMap );
69     SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
70     while( aIter != aVisList.end() )
71     {
72         const SwAccessibleChild& rLower = *aIter;
73         if( rLower.IsAccessible( bInPagePreview ) )
74         {
75             nCount++;
76         }
77         else if( rLower.GetSwFrm() )
78         {
79             // There are no unaccessible SdrObjects that count
80             nCount += GetChildCount( rAccMap,
81                                      rVisArea, rLower.GetSwFrm(),
82                                      bInPagePreview );
83         }
84         ++aIter;
85     }
86 
87     return nCount;
88 }
89 
90 /* static */ SwAccessibleChild SwAccessibleFrame::GetChild(
91                                                 SwAccessibleMap& rAccMap,
92                                                 const SwRect& rVisArea,
93                                                 const SwFrm& rFrm,
94                                                 sal_Int32& rPos,
95                                                 sal_Bool bInPagePreview )
96 {
97     SwAccessibleChild aRet;
98 
99     if( rPos >= 0 )
100     {
101         if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
102         {
103             // We need a sorted list here
104             const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
105             SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
106             while( aIter != aVisMap.end() && !aRet.IsValid() )
107             {
108                 const SwAccessibleChild& rLower = (*aIter).second;
109                 if( rLower.IsAccessible( bInPagePreview ) )
110                 {
111                     if( 0 == rPos )
112                         aRet = rLower;
113                     else
114                         rPos--;
115                 }
116                 else if( rLower.GetSwFrm() )
117                 {
118                     // There are no unaccessible SdrObjects that count
119                     aRet = GetChild( rAccMap,
120                                      rVisArea, *(rLower.GetSwFrm()), rPos,
121                                      bInPagePreview );
122                 }
123                 ++aIter;
124             }
125         }
126         else
127         {
128             // The unsorted list is sorted enough, because it return lower
129             // frames in the correct order.
130             const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
131             SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
132             while( aIter != aVisList.end() && !aRet.IsValid() )
133             {
134                 const SwAccessibleChild& rLower = *aIter;
135                 if( rLower.IsAccessible( bInPagePreview ) )
136                 {
137                     if( 0 == rPos )
138                         aRet = rLower;
139                     else
140                         rPos--;
141                 }
142                 else if( rLower.GetSwFrm() )
143                 {
144                     // There are no unaccessible SdrObjects that count
145                     aRet = GetChild( rAccMap,
146                                      rVisArea, *(rLower.GetSwFrm()), rPos,
147                                      bInPagePreview );
148                 }
149                 ++aIter;
150             }
151         }
152     }
153 
154     return aRet;
155 }
156 
157 /* static */ sal_Bool SwAccessibleFrame::GetChildIndex(
158                                                 SwAccessibleMap& rAccMap,
159                                                 const SwRect& rVisArea,
160                                                 const SwFrm& rFrm,
161                                                 const SwAccessibleChild& rChild,
162                                                 sal_Int32& rPos,
163                                                 sal_Bool bInPagePreview )
164 {
165     sal_Bool bFound = sal_False;
166 
167     if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
168     {
169         // We need a sorted list here
170         const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
171         SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
172         while( aIter != aVisMap.end() && !bFound )
173         {
174             const SwAccessibleChild& rLower = (*aIter).second;
175             if( rLower.IsAccessible( bInPagePreview ) )
176             {
177                 if( rChild == rLower )
178                     bFound = sal_True;
179                 else
180                     rPos++;
181             }
182             else if( rLower.GetSwFrm() )
183             {
184                 // There are no unaccessible SdrObjects that count
185                 bFound = GetChildIndex( rAccMap,
186                                         rVisArea, *(rLower.GetSwFrm()), rChild,
187                                         rPos, bInPagePreview );
188             }
189             ++aIter;
190         }
191     }
192     else
193     {
194         // The unsorted list is sorted enough, because it return lower
195         // frames in the correct order.
196         const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
197         SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
198         while( aIter != aVisList.end() && !bFound )
199         {
200             const SwAccessibleChild& rLower = *aIter;
201             if( rLower.IsAccessible( bInPagePreview ) )
202             {
203                 if( rChild == rLower )
204                     bFound = sal_True;
205                 else
206                     rPos++;
207             }
208             else if( rLower.GetSwFrm() )
209             {
210                 // There are no unaccessible SdrObjects that count
211                 bFound = GetChildIndex( rAccMap,
212                                         rVisArea, *(rLower.GetSwFrm()), rChild,
213                                         rPos, bInPagePreview );
214             }
215             ++aIter;
216         }
217     }
218 
219     return bFound;
220 }
221 
222 SwAccessibleChild SwAccessibleFrame::GetChildAtPixel( const SwRect& rVisArea,
223                                           const SwFrm& rFrm,
224                                           const Point& rPixPos,
225                                           sal_Bool bInPagePreview,
226                                           SwAccessibleMap& rAccMap )
227 {
228     SwAccessibleChild aRet;
229 
230     if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
231     {
232         // We need a sorted list here, and we have to reverse iterate,
233         // because objects in front should be returned.
234         const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
235         SwAccessibleChildMap::const_reverse_iterator aRIter( aVisMap.rbegin() );
236         while( aRIter != aVisMap.rend() && !aRet.IsValid() )
237         {
238             const SwAccessibleChild& rLower = (*aRIter).second;
239             // A frame is returned if it's frame size is inside the visarea
240             // and the positiion is inside the frame's paint area.
241             if( rLower.IsAccessible( bInPagePreview ) )
242             {
243                 SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
244                 if( !aLogBounds.IsEmpty() )
245                 {
246                     Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
247                     if( aPixBounds.IsInside( rPixPos ) )
248                         aRet = rLower;
249                 }
250             }
251             else if( rLower.GetSwFrm() )
252             {
253                 // There are no unaccessible SdrObjects that count
254                 aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
255                                         bInPagePreview, rAccMap );
256             }
257             aRIter++;
258         }
259     }
260     else
261     {
262         // The unsorted list is sorted enough, because it returns lower
263         // frames in the correct order. Morover, we can iterate forward,
264         // because the lowers don't overlap!
265         const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
266         SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
267         while( aIter != aVisList.end() && !aRet.IsValid() )
268         {
269             const SwAccessibleChild& rLower = *aIter;
270             // A frame is returned if it's frame size is inside the visarea
271             // and the positiion is inside the frame's paint area.
272             if( rLower.IsAccessible( bInPagePreview ) )
273             {
274                 SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
275                 if( !aLogBounds.IsEmpty() )
276                 {
277                     Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
278                     if( aPixBounds.IsInside( rPixPos ) )
279                         aRet = rLower;
280                 }
281             }
282             else if( rLower.GetSwFrm() )
283             {
284                 // There are no unaccessible SdrObjects that count
285                 aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
286                                    bInPagePreview, rAccMap );
287             }
288             ++aIter;
289         }
290     }
291 
292     return aRet;
293 }
294 
295 /* static */ void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
296                                                   const SwRect& rVisArea,
297                                                   const SwFrm& rFrm,
298                                                   ::std::list< SwAccessibleChild >& rChildren,
299                                                   sal_Bool bInPagePreview )
300 {
301     if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
302     {
303         // We need a sorted list here
304         const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
305         SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
306         while( aIter != aVisMap.end() )
307         {
308             const SwAccessibleChild& rLower = (*aIter).second;
309             if( rLower.IsAccessible( bInPagePreview ) )
310             {
311                 rChildren.push_back( rLower );
312             }
313             else if( rLower.GetSwFrm() )
314             {
315                 // There are no unaccessible SdrObjects that count
316                 GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
317                              rChildren, bInPagePreview );
318             }
319             ++aIter;
320         }
321     }
322     else
323     {
324         // The unsorted list is sorted enough, because it return lower
325         // frames in the correct order.
326         const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
327         SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
328         while( aIter != aVisList.end() )
329         {
330             const SwAccessibleChild& rLower = *aIter;
331             if( rLower.IsAccessible( bInPagePreview ) )
332             {
333                 rChildren.push_back( rLower );
334             }
335             else if( rLower.GetSwFrm() )
336             {
337                 // There are no unaccessible SdrObjects that count
338                 GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
339                              rChildren, bInPagePreview );
340             }
341             ++aIter;
342         }
343     }
344 }
345 
346 SwRect SwAccessibleFrame::GetBounds( const SwAccessibleMap& rAccMap,
347                                      const SwFrm *pFrm )
348 {
349     if( !pFrm )
350         pFrm = GetFrm();
351 
352     SwAccessibleChild aFrm( pFrm );
353     SwRect aBounds( aFrm.GetBounds( rAccMap ).Intersection( maVisArea ) );
354     return aBounds;
355 }
356 
357 sal_Bool SwAccessibleFrame::IsEditable( ViewShell *pVSh ) const
358 {
359     const SwFrm *pFrm = GetFrm();
360     if( !pFrm )
361         return sal_False;
362 
363     ASSERT( pVSh, "no view shell" );
364     if( pVSh && (pVSh->GetViewOptions()->IsReadonly() ||
365                  pVSh->IsPreView()) )
366         return sal_False;
367 
368     if( !pFrm->IsRootFrm() && pFrm->IsProtected() )
369         return sal_False;
370 
371     return sal_True;
372 }
373 
374 sal_Bool SwAccessibleFrame::IsOpaque( ViewShell *pVSh ) const
375 {
376     SwAccessibleChild aFrm( GetFrm() );
377     if( !aFrm.GetSwFrm() )
378         return sal_False;
379 
380     ASSERT( pVSh, "no view shell" );
381     if( !pVSh )
382         return sal_False;
383 
384     const SwViewOption *pVOpt = pVSh->GetViewOptions();
385     do
386     {
387         const SwFrm *pFrm = aFrm.GetSwFrm();
388         if( pFrm->IsRootFrm() )
389             return sal_True;
390 
391         if( pFrm->IsPageFrm() && !pVOpt->IsPageBack() )
392             return sal_False;
393 
394         const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
395         if( !rBack.GetColor().GetTransparency() ||
396              rBack.GetGraphicPos() != GPOS_NONE )
397             return sal_True;
398 
399         /// OD 20.08.2002 #99657#
400         ///     If a fly frame has a transparent background color, we have
401         ///     to consider the background.
402         ///     But a background color "no fill"/"auto fill" has *not* to be considered.
403         if( pFrm->IsFlyFrm() &&
404             (rBack.GetColor().GetTransparency() != 0) &&
405             (rBack.GetColor() != COL_TRANSPARENT)
406           )
407             return sal_True;
408 
409         if( pFrm->IsSctFrm() )
410         {
411             const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
412             if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
413                 TOX_CONTENT_SECTION == pSection->GetType() ) &&
414                 !pVOpt->IsReadonly() &&
415                 SwViewOption::IsIndexShadings() )
416                 return sal_True;
417         }
418         if( pFrm->IsFlyFrm() )
419             aFrm = static_cast<const SwFlyFrm*>(pFrm)->GetAnchorFrm();
420         else
421             aFrm = pFrm->GetUpper();
422     } while( aFrm.GetSwFrm() && !aFrm.IsAccessible( IsInPagePreview() ) );
423 
424     return sal_False;
425 }
426 
427 SwAccessibleFrame::SwAccessibleFrame( const SwRect& rVisArea,
428                                       const SwFrm *pF,
429                                       sal_Bool bIsPagePreview ) :
430     maVisArea( rVisArea ),
431     mpFrm( pF ),
432     mbIsInPagePreview( bIsPagePreview )
433 {
434 }
435 
436 SwAccessibleFrame::~SwAccessibleFrame()
437 {
438 }
439 
440 /* static */ const SwFrm* SwAccessibleFrame::GetParent( const SwAccessibleChild& rFrmOrObj,
441                                                         sal_Bool bInPagePreview )
442 {
443     return rFrmOrObj.GetParent( bInPagePreview );
444 }
445 
446 String SwAccessibleFrame::GetFormattedPageNumber() const
447 {
448     sal_uInt16 nPageNum = GetFrm()->GetVirtPageNum();
449     sal_uInt32 nFmt = GetFrm()->FindPageFrm()->GetPageDesc()
450                               ->GetNumType().GetNumberingType();
451     if( SVX_NUM_NUMBER_NONE == nFmt )
452         nFmt = SVX_NUM_ARABIC;
453 
454     String sRet( FormatNumber( nPageNum, nFmt ) );
455     return sRet;
456 }
457 
458 sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap ) const
459 {
460     return GetChildCount( rAccMap, maVisArea, mpFrm, IsInPagePreview() );
461 }
462 
463 sw::access::SwAccessibleChild SwAccessibleFrame::GetChild(
464                                                 SwAccessibleMap& rAccMap,
465                                                 sal_Int32 nPos ) const
466 {
467     return SwAccessibleFrame::GetChild( rAccMap, maVisArea, *mpFrm, nPos, IsInPagePreview() );
468 }
469 
470 sal_Int32 SwAccessibleFrame::GetChildIndex( SwAccessibleMap& rAccMap,
471                                             const sw::access::SwAccessibleChild& rChild ) const
472 {
473     sal_Int32 nPos = 0;
474     return GetChildIndex( rAccMap, maVisArea, *mpFrm, rChild, nPos, IsInPagePreview() )
475            ? nPos
476            : -1L;
477 }
478 
479 sw::access::SwAccessibleChild SwAccessibleFrame::GetChildAtPixel(
480                                                 const Point& rPos,
481                                                 SwAccessibleMap& rAccMap ) const
482 {
483     return GetChildAtPixel( maVisArea, *mpFrm, rPos, IsInPagePreview(), rAccMap );
484 }
485 
486 void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
487                                      ::std::list< sw::access::SwAccessibleChild >& rChildren ) const
488 {
489     GetChildren( rAccMap, maVisArea, *mpFrm, rChildren, IsInPagePreview() );
490 }
491 
492 sal_Bool SwAccessibleFrame::IsShowing( const SwAccessibleMap& rAccMap,
493                                        const sw::access::SwAccessibleChild& rFrmOrObj ) const
494 {
495     return IsShowing( rFrmOrObj.GetBox( rAccMap ) );
496 }
497 
498