android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / access / accframebase.cxx
blobfc94259b5bfdbdf6e489989aa306861b90a67ddc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
21 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
22 #include <vcl/svapp.hxx>
23 #include <vcl/window.hxx>
24 #include <frmfmt.hxx>
25 #include <flyfrm.hxx>
26 #include <fmtcntnt.hxx>
27 #include <ndindex.hxx>
28 #include <fesh.hxx>
29 #include <hints.hxx>
30 #include <accmap.hxx>
31 #include "accframebase.hxx"
33 #include <crsrsh.hxx>
34 #include <notxtfrm.hxx>
35 #include <ndtxt.hxx>
36 #include <undobj.hxx>
37 #include <fmtanchr.hxx>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::accessibility;
42 bool SwAccessibleFrameBase::IsSelected()
44 bool bRet = false;
46 assert(GetMap());
47 const SwViewShell *pVSh = GetMap()->GetShell();
48 assert(pVSh);
49 if( auto pFESh = dynamic_cast<const SwFEShell*>(pVSh) )
51 const SwFrame *pFlyFrame = pFESh->GetSelectedFlyFrame();
52 if( pFlyFrame == GetFrame() )
53 bRet = true;
56 return bRet;
59 void SwAccessibleFrameBase::GetStates( sal_Int64& rStateSet )
61 SwAccessibleContext::GetStates( rStateSet );
63 const SwViewShell *pVSh = GetMap()->GetShell();
64 assert(pVSh);
66 if (dynamic_cast<const SwFEShell*>(pVSh))
68 // SELECTABLE
69 rStateSet |= AccessibleStateType::SELECTABLE;
70 // FOCUSABLE
71 rStateSet |= AccessibleStateType::FOCUSABLE;
74 // SELECTED and FOCUSED
75 if( IsSelected() )
77 rStateSet |= AccessibleStateType::SELECTED;
78 SAL_WARN_IF(!m_bIsSelected, "sw.a11y", "bSelected out of sync");
79 ::rtl::Reference < SwAccessibleContext > xThis( this );
80 GetMap()->SetCursorContext( xThis );
82 vcl::Window *pWin = GetWindow();
83 if( pWin && pWin->HasFocus() )
84 rStateSet |= AccessibleStateType::FOCUSED;
86 if( GetSelectedState() )
87 rStateSet |= AccessibleStateType::SELECTED;
90 SwNodeType SwAccessibleFrameBase::GetNodeType( const SwFlyFrame *pFlyFrame )
92 SwNodeType nType = SwNodeType::Text;
93 if( pFlyFrame->Lower() )
95 if( pFlyFrame->Lower()->IsNoTextFrame() )
97 const SwNoTextFrame *const pContentFrame =
98 static_cast<const SwNoTextFrame *>(pFlyFrame->Lower());
99 nType = pContentFrame->GetNode()->GetNodeType();
102 else
104 const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
105 const SwFormatContent& rContent = pFrameFormat->GetContent();
106 const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
107 if( pNdIdx )
109 const SwContentNode *pCNd =
110 (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetContentNode();
111 if( pCNd )
112 nType = pCNd->GetNodeType();
116 return nType;
119 SwAccessibleFrameBase::SwAccessibleFrameBase(
120 std::shared_ptr<SwAccessibleMap> const& pInitMap,
121 sal_Int16 nInitRole,
122 const SwFlyFrame* pFlyFrame ) :
123 SwAccessibleContext( pInitMap, nInitRole, pFlyFrame ),
124 m_bIsSelected( false )
126 const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
128 StartListening(const_cast<SwFrameFormat*>(pFrameFormat)->GetNotifier());
130 SetName( pFrameFormat->GetName() );
132 m_bIsSelected = IsSelected();
135 void SwAccessibleFrameBase::InvalidateCursorPos_()
137 bool bNewSelected = IsSelected();
138 bool bOldSelected;
141 std::scoped_lock aGuard( m_Mutex );
142 bOldSelected = m_bIsSelected;
143 m_bIsSelected = bNewSelected;
146 if( bNewSelected )
148 // remember that object as the one that has the caret. This is
149 // necessary to notify that object if the cursor leaves it.
150 ::rtl::Reference < SwAccessibleContext > xThis( this );
151 GetMap()->SetCursorContext( xThis );
154 if( bOldSelected == bNewSelected )
155 return;
157 vcl::Window *pWin = GetWindow();
158 if( pWin && pWin->HasFocus() && bNewSelected )
159 FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
160 if( pWin && pWin->HasFocus() && !bNewSelected )
161 FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
162 if(!bNewSelected)
163 return;
165 uno::Reference< XAccessible > xParent( GetWeakParent() );
166 if( xParent.is() )
168 SwAccessibleContext *pAcc =
169 static_cast <SwAccessibleContext *>( xParent.get() );
171 AccessibleEventObject aEvent;
172 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
173 uno::Reference< XAccessible > xChild(this);
174 aEvent.NewValue <<= xChild;
175 pAcc->FireAccessibleEvent( aEvent );
179 void SwAccessibleFrameBase::InvalidateFocus_()
181 vcl::Window *pWin = GetWindow();
182 if( !pWin )
183 return;
185 bool bSelected;
188 std::scoped_lock aGuard( m_Mutex );
189 bSelected = m_bIsSelected;
191 assert(bSelected && "focus object should be selected");
193 FireStateChangedEvent( AccessibleStateType::FOCUSED,
194 pWin->HasFocus() && bSelected );
197 bool SwAccessibleFrameBase::HasCursor()
199 std::scoped_lock aGuard( m_Mutex );
200 return m_bIsSelected;
203 SwAccessibleFrameBase::~SwAccessibleFrameBase()
207 void SwAccessibleFrameBase::Notify(const SfxHint& rHint)
209 const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(GetFrame());
210 if(rHint.GetId() == SfxHintId::Dying)
212 EndListeningAll();
214 else if (rHint.GetId() == SfxHintId::SwNameChanged && pFlyFrame)
216 auto rNameChanged = static_cast<const sw::NameChanged&>(rHint);
217 const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
219 const OUString sOldName( GetName() );
220 assert( rNameChanged.m_sOld == sOldName);
222 SetName( pFrameFormat->GetName() );
223 assert( rNameChanged.m_sNew == GetName());
225 if( sOldName != GetName() )
227 AccessibleEventObject aEvent;
228 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
229 aEvent.OldValue <<= sOldName;
230 aEvent.NewValue <<= GetName();
231 FireAccessibleEvent( aEvent );
236 void SwAccessibleFrameBase::Dispose(bool bRecursive, bool bCanSkipInvisible)
238 SolarMutexGuard aGuard;
239 EndListeningAll();
240 SwAccessibleContext::Dispose(bRecursive, bCanSkipInvisible);
243 //Get the selection cursor of the document.
244 SwPaM* SwAccessibleFrameBase::GetCursor()
246 // get the cursor shell; if we don't have any, we don't have a
247 // cursor/selection either
248 SwPaM* pCursor = nullptr;
249 SwCursorShell* pCursorShell = GetCursorShell();
250 if( pCursorShell != nullptr && !pCursorShell->IsTableMode() )
252 SwFEShell *pFESh = dynamic_cast<SwFEShell*>( pCursorShell);
253 if( !pFESh ||
254 !(pFESh->IsFrameSelected() || pFESh->IsObjSelected() > 0) )
256 // get the selection, and test whether it affects our text node
257 pCursor = pCursorShell->GetCursor( false /* ??? */ );
261 return pCursor;
264 //Return the selected state of the object.
265 //when the object's anchor are in the selection cursor, we should return true.
266 bool SwAccessibleFrameBase::GetSelectedState( )
268 SolarMutexGuard aGuard;
270 if(GetMap()->IsDocumentSelAll())
272 return true;
275 // SELECTED.
276 SwFlyFrame* pFlyFrame = getFlyFrame();
277 const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
278 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
279 const SwPosition *pPos = rAnchor.GetContentAnchor();
280 if( !pPos )
281 return false;
282 int nIndex = pPos->GetContentIndex();
283 if( pPos->GetNode().GetTextNode() )
285 SwPaM* pCursor = GetCursor();
286 if( pCursor != nullptr )
288 const SwTextNode* pNode = pPos->GetNode().GetTextNode();
289 SwNodeOffset nHere = pNode->GetIndex();
291 // iterate over ring
292 SwPaM* pRingStart = pCursor;
295 // ignore, if no mark
296 if( pCursor->HasMark() )
298 // check whether nHere is 'inside' pCursor
299 SwPosition* pStart = pCursor->Start();
300 SwNodeOffset nStartIndex = pStart->GetNodeIndex();
301 SwPosition* pEnd = pCursor->End();
302 SwNodeOffset nEndIndex = pEnd->GetNodeIndex();
303 if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex) )
305 if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
307 if( ((nHere == nStartIndex) && (nIndex >= pStart->GetContentIndex())) || (nHere > nStartIndex) )
308 if( ((nHere == nEndIndex) && (nIndex < pEnd->GetContentIndex())) || (nHere < nEndIndex) )
309 return true;
311 else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA )
313 if (IsSelectFrameAnchoredAtPara(*pPos, *pStart, *pEnd))
314 return true;
316 else if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
318 if (IsDestroyFrameAnchoredAtChar(*pPos, *pStart, *pEnd))
320 return true;
323 break;
325 // else: this PaM doesn't point to this paragraph
327 // else: this PaM is collapsed and doesn't select anything
329 // next PaM in ring
330 pCursor = pCursor->GetNext();
332 while( pCursor != pRingStart );
335 return false;
338 SwFlyFrame* SwAccessibleFrameBase::getFlyFrame() const
340 SwFlyFrame* pFlyFrame = nullptr;
342 const SwFrame* pFrame = GetFrame();
343 assert(pFrame);
344 if( pFrame->IsFlyFrame() )
346 pFlyFrame = static_cast<SwFlyFrame*>( const_cast<SwFrame*>( pFrame ) );
349 return pFlyFrame;
352 bool SwAccessibleFrameBase::SetSelectedState( bool )
354 bool bParaSelected = GetSelectedState() || IsSelected();
356 if (m_isSelectedInDoc != bParaSelected)
358 m_isSelectedInDoc = bParaSelected;
359 FireStateChangedEvent( AccessibleStateType::SELECTED, bParaSelected );
360 return true;
362 return false;
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */