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