xref: /trunk/main/sw/source/core/access/accframebase.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 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 #include <unotools/accessiblestatesethelper.hxx>
35 #include <vos/mutex.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/window.hxx>
38 #include <frmfmt.hxx>
39 #include <ndnotxt.hxx>
40 #include <flyfrm.hxx>
41 #include <cntfrm.hxx>
42 #include <fmtcntnt.hxx>
43 #include <ndindex.hxx>
44 #include "fesh.hxx"
45 #include <hints.hxx>
46 #include "accmap.hxx"
47 #include "accframebase.hxx"
48 
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::accessibility;
51 using ::rtl::OUString;
52 
53 sal_Bool SwAccessibleFrameBase::IsSelected()
54 {
55     sal_Bool bRet = sal_False;
56 
57     DBG_ASSERT( GetMap(), "no map?" );
58     const ViewShell *pVSh = GetMap()->GetShell();
59     DBG_ASSERT( pVSh, "no shell?" );
60     if( pVSh->ISA( SwFEShell ) )
61     {
62         const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
63         const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
64         if( pFlyFrm == GetFrm() )
65             bRet = sal_True;
66     }
67 
68     return bRet;
69 }
70 
71 void SwAccessibleFrameBase::GetStates(
72         ::utl::AccessibleStateSetHelper& rStateSet )
73 {
74     SwAccessibleContext::GetStates( rStateSet );
75 
76     const ViewShell *pVSh = GetMap()->GetShell();
77     DBG_ASSERT( pVSh, "no shell?" );
78     sal_Bool bSelectable =  pVSh->ISA( SwFEShell );
79 
80     // SELECTABLE
81     if( bSelectable )
82         rStateSet.AddState( AccessibleStateType::SELECTABLE );
83 
84     // FOCUSABLE
85     if( bSelectable )
86         rStateSet.AddState( AccessibleStateType::FOCUSABLE );
87 
88     // SELECTED and FOCUSED
89     if( IsSelected() )
90     {
91         rStateSet.AddState( AccessibleStateType::SELECTED );
92         ASSERT( bIsSelected, "bSelected out of sync" );
93         ::vos::ORef < SwAccessibleContext > xThis( this );
94         GetMap()->SetCursorContext( xThis );
95 
96         Window *pWin = GetWindow();
97         if( pWin && pWin->HasFocus() )
98             rStateSet.AddState( AccessibleStateType::FOCUSED );
99     }
100 }
101 
102 
103 sal_uInt8 SwAccessibleFrameBase::GetNodeType( const SwFlyFrm *pFlyFrm )
104 {
105     sal_uInt8 nType = ND_TEXTNODE;
106     if( pFlyFrm->Lower() )
107     {
108         if( pFlyFrm->Lower()->IsNoTxtFrm() )
109         {
110             const SwCntntFrm *pCntFrm =
111                 static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
112             nType = pCntFrm->GetNode()->GetNodeType();
113         }
114     }
115     else
116     {
117         const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
118         const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
119         const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx();
120         if( pNdIdx )
121         {
122             const SwCntntNode *pCNd =
123                 (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetCntntNode();
124             if( pCNd )
125                 nType = pCNd->GetNodeType();
126         }
127     }
128 
129     return nType;
130 }
131 
132 SwAccessibleFrameBase::SwAccessibleFrameBase(
133         SwAccessibleMap* pInitMap,
134         sal_Int16 nInitRole,
135         const SwFlyFrm* pFlyFrm  ) :
136     SwAccessibleContext( pInitMap, nInitRole, pFlyFrm ),
137     bIsSelected( sal_False )
138 {
139     vos::OGuard aGuard(Application::GetSolarMutex());
140 
141     const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
142     const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
143 
144     SetName( pFrmFmt->GetName() );
145 
146     bIsSelected = IsSelected();
147 }
148 
149 void SwAccessibleFrameBase::_InvalidateCursorPos()
150 {
151     sal_Bool bNewSelected = IsSelected();
152     sal_Bool bOldSelected;
153 
154     {
155         vos::OGuard aGuard( aMutex );
156         bOldSelected = bIsSelected;
157         bIsSelected = bNewSelected;
158     }
159 
160     if( bNewSelected )
161     {
162         // remember that object as the one that has the caret. This is
163         // neccessary to notify that object if the cursor leaves it.
164         ::vos::ORef < SwAccessibleContext > xThis( this );
165         GetMap()->SetCursorContext( xThis );
166     }
167 
168     if( bOldSelected != bNewSelected )
169     {
170         Window *pWin = GetWindow();
171         if( pWin && pWin->HasFocus() && bNewSelected )
172             FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
173         FireStateChangedEvent( AccessibleStateType::SELECTED, bNewSelected );
174         if( pWin && pWin->HasFocus() && !bNewSelected )
175             FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
176 
177         uno::Reference< XAccessible > xParent( GetWeakParent() );
178         if( xParent.is() )
179         {
180             SwAccessibleContext *pAcc =
181                 static_cast <SwAccessibleContext *>( xParent.get() );
182 
183             AccessibleEventObject aEvent;
184             aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
185             pAcc->FireAccessibleEvent( aEvent );
186         }
187     }
188 }
189 
190 void SwAccessibleFrameBase::_InvalidateFocus()
191 {
192     Window *pWin = GetWindow();
193     if( pWin )
194     {
195         sal_Bool bSelected;
196 
197         {
198             vos::OGuard aGuard( aMutex );
199             bSelected = bIsSelected;
200         }
201         ASSERT( bSelected, "focus object should be selected" );
202 
203         FireStateChangedEvent( AccessibleStateType::FOCUSED,
204                                pWin->HasFocus() && bSelected );
205     }
206 }
207 
208 sal_Bool SwAccessibleFrameBase::HasCursor()
209 {
210     vos::OGuard aGuard( aMutex );
211     return bIsSelected;
212 }
213 
214 
215 SwAccessibleFrameBase::~SwAccessibleFrameBase()
216 {
217 }
218 
219 void SwAccessibleFrameBase::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
220 {
221     sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
222     const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
223     switch( nWhich )
224     {
225     case RES_NAME_CHANGED:
226         if(  pFlyFrm )
227         {
228             const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
229             ASSERT( pFrmFmt == GetRegisteredIn(), "invalid frame" );
230 
231             OUString sOldName( GetName() );
232             ASSERT( !pOld ||
233                     static_cast < const SwStringMsgPoolItem * >( pOld )->GetString() == String( sOldName ),
234                     "invalid old name" );
235 
236             const String& rNewName = pFrmFmt->GetName();
237             SetName( rNewName );
238             ASSERT( !pNew ||
239                     static_cast < const SwStringMsgPoolItem * >( pNew )->GetString() == rNewName,
240                     "invalid new name" );
241 
242             if( sOldName != GetName() )
243             {
244                 AccessibleEventObject aEvent;
245                 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
246                 aEvent.OldValue <<= sOldName;
247                 aEvent.NewValue <<= GetName();
248                 FireAccessibleEvent( aEvent );
249             }
250         }
251         break;
252     case RES_OBJECTDYING:
253         // mba: it seems that this class intentionally does not call code in base class SwClient
254         if( GetRegisteredIn() ==
255                 static_cast< SwModify *>( static_cast< const SwPtrMsgPoolItem * >( pOld )->pObject ) )
256             GetRegisteredInNonConst()->Remove( this );
257         break;
258 
259     case RES_FMT_CHG:
260         if( static_cast< const SwFmtChg * >(pNew)->pChangedFmt == GetRegisteredIn() &&
261             static_cast< const SwFmtChg * >(pOld)->pChangedFmt->IsFmtInDTOR() )
262             GetRegisteredInNonConst()->Remove( this );
263         break;
264 
265     default:
266         // mba: former call to base class method removed as it is meant to handle only RES_OBJECTDYING
267         break;
268     }
269 }
270 
271 void SwAccessibleFrameBase::Dispose( sal_Bool bRecursive )
272 {
273     vos::OGuard aGuard(Application::GetSolarMutex());
274 
275     if( GetRegisteredIn() )
276         GetRegisteredInNonConst()->Remove( this );
277 
278     SwAccessibleContext::Dispose( bRecursive );
279 }
280