LibreOffice Module sw (master) 1
accframebase.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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"
32
33#include <crsrsh.hxx>
34#include <notxtfrm.hxx>
35#include <ndtxt.hxx>
36#include <undobj.hxx>
37#include <fmtanchr.hxx>
38
39using namespace ::com::sun::star;
40using namespace ::com::sun::star::accessibility;
41
43{
44 bool bRet = false;
45
46 assert(GetMap());
47 const SwViewShell *pVSh = GetMap()->GetShell();
48 assert(pVSh);
49 if( auto pFESh = dynamic_cast<const SwFEShell*>(pVSh) )
50 {
51 const SwFrame *pFlyFrame = pFESh->GetSelectedFlyFrame();
52 if( pFlyFrame == GetFrame() )
53 bRet = true;
54 }
55
56 return bRet;
57}
58
59void SwAccessibleFrameBase::GetStates( sal_Int64& rStateSet )
60{
62
63 const SwViewShell *pVSh = GetMap()->GetShell();
64 assert(pVSh);
65
66 if (dynamic_cast<const SwFEShell*>(pVSh))
67 {
68 // SELECTABLE
69 rStateSet |= AccessibleStateType::SELECTABLE;
70 // FOCUSABLE
71 rStateSet |= AccessibleStateType::FOCUSABLE;
72 }
73
74 // SELECTED and FOCUSED
75 if( IsSelected() )
76 {
77 rStateSet |= AccessibleStateType::SELECTED;
78 SAL_WARN_IF(!m_bIsSelected, "sw.a11y", "bSelected out of sync");
80 GetMap()->SetCursorContext( xThis );
81
82 vcl::Window *pWin = GetWindow();
83 if( pWin && pWin->HasFocus() )
84 rStateSet |= AccessibleStateType::FOCUSED;
85 }
86 if( GetSelectedState() )
87 rStateSet |= AccessibleStateType::SELECTED;
88}
89
91{
93 if( pFlyFrame->Lower() )
94 {
95 if( pFlyFrame->Lower()->IsNoTextFrame() )
96 {
97 const SwNoTextFrame *const pContentFrame =
98 static_cast<const SwNoTextFrame *>(pFlyFrame->Lower());
99 nType = pContentFrame->GetNode()->GetNodeType();
100 }
101 }
102 else
103 {
104 const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
105 const SwFormatContent& rContent = pFrameFormat->GetContent();
106 const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
107 if( pNdIdx )
108 {
109 const SwContentNode *pCNd =
110 (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetContentNode();
111 if( pCNd )
112 nType = pCNd->GetNodeType();
113 }
114 }
115
116 return nType;
117}
118
120 std::shared_ptr<SwAccessibleMap> const& pInitMap,
121 sal_Int16 nInitRole,
122 const SwFlyFrame* pFlyFrame ) :
123 SwAccessibleContext( pInitMap, nInitRole, pFlyFrame ),
124 m_bIsSelected( false )
125{
126 const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
127
128 StartListening(const_cast<SwFrameFormat*>(pFrameFormat)->GetNotifier());
129
130 SetName( pFrameFormat->GetName() );
131
133}
134
136{
137 bool bNewSelected = IsSelected();
138 bool bOldSelected;
139
140 {
141 std::scoped_lock aGuard( m_Mutex );
142 bOldSelected = m_bIsSelected;
143 m_bIsSelected = bNewSelected;
144 }
145
146 if( bNewSelected )
147 {
148 // remember that object as the one that has the caret. This is
149 // necessary to notify that object if the cursor leaves it.
151 GetMap()->SetCursorContext( xThis );
152 }
153
154 if( bOldSelected == bNewSelected )
155 return;
156
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;
164
165 uno::Reference< XAccessible > xParent( GetWeakParent() );
166 if( xParent.is() )
167 {
168 SwAccessibleContext *pAcc =
169 static_cast <SwAccessibleContext *>( xParent.get() );
170
171 AccessibleEventObject aEvent;
172 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
173 uno::Reference< XAccessible > xChild(this);
174 aEvent.NewValue <<= xChild;
176 }
177}
178
180{
181 vcl::Window *pWin = GetWindow();
182 if( !pWin )
183 return;
184
185 bool bSelected;
186
187 {
188 std::scoped_lock aGuard( m_Mutex );
189 bSelected = m_bIsSelected;
190 }
191 assert(bSelected && "focus object should be selected");
192
193 FireStateChangedEvent( AccessibleStateType::FOCUSED,
194 pWin->HasFocus() && bSelected );
195}
196
198{
199 std::scoped_lock aGuard( m_Mutex );
200 return m_bIsSelected;
201}
202
204{
205}
206
208{
209 const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(GetFrame());
210 if(rHint.GetId() == SfxHintId::Dying)
211 {
213 }
214 else if (rHint.GetId() == SfxHintId::SwNameChanged && pFlyFrame)
215 {
216 auto rNameChanged = static_cast<const sw::NameChanged&>(rHint);
217 const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
218
219 const OUString sOldName( GetName() );
220 assert( rNameChanged.m_sOld == sOldName);
221
222 SetName( pFrameFormat->GetName() );
223 assert( rNameChanged.m_sNew == GetName());
224
225 if( sOldName != GetName() )
226 {
227 AccessibleEventObject aEvent;
228 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
229 aEvent.OldValue <<= sOldName;
230 aEvent.NewValue <<= GetName();
232 }
233 }
234}
235
236void SwAccessibleFrameBase::Dispose(bool bRecursive, bool bCanSkipInvisible)
237{
238 SolarMutexGuard aGuard;
240 SwAccessibleContext::Dispose(bRecursive, bCanSkipInvisible);
241}
242
243//Get the selection cursor of the document.
245{
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() )
251 {
252 SwFEShell *pFESh = dynamic_cast<SwFEShell*>( pCursorShell);
253 if( !pFESh ||
254 !(pFESh->IsFrameSelected() || pFESh->IsObjSelected() > 0) )
255 {
256 // get the selection, and test whether it affects our text node
257 pCursor = pCursorShell->GetCursor( false /* ??? */ );
258 }
259 }
260
261 return pCursor;
262}
263
264//Return the selected state of the object.
265//when the object's anchor are in the selection cursor, we should return true.
267{
268 SolarMutexGuard aGuard;
269
270 if(GetMap()->IsDocumentSelAll())
271 {
272 return true;
273 }
274
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() )
284 {
285 SwPaM* pCursor = GetCursor();
286 if( pCursor != nullptr )
287 {
288 const SwTextNode* pNode = pPos->GetNode().GetTextNode();
289 SwNodeOffset nHere = pNode->GetIndex();
290
291 // iterate over ring
292 SwPaM* pRingStart = pCursor;
293 do
294 {
295 // ignore, if no mark
296 if( pCursor->HasMark() )
297 {
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) )
304 {
305 if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
306 {
307 if( ((nHere == nStartIndex) && (nIndex >= pStart->GetContentIndex())) || (nHere > nStartIndex) )
308 if( ((nHere == nEndIndex) && (nIndex < pEnd->GetContentIndex())) || (nHere < nEndIndex) )
309 return true;
310 }
311 else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA )
312 {
313 if (IsSelectFrameAnchoredAtPara(*pPos, *pStart, *pEnd))
314 return true;
315 }
316 else if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
317 {
318 if (IsDestroyFrameAnchoredAtChar(*pPos, *pStart, *pEnd))
319 {
320 return true;
321 }
322 }
323 break;
324 }
325 // else: this PaM doesn't point to this paragraph
326 }
327 // else: this PaM is collapsed and doesn't select anything
328
329 // next PaM in ring
330 pCursor = pCursor->GetNext();
331 }
332 while( pCursor != pRingStart );
333 }
334 }
335 return false;
336}
337
339{
340 SwFlyFrame* pFlyFrame = nullptr;
341
342 const SwFrame* pFrame = GetFrame();
343 assert(pFrame);
344 if( pFrame->IsFlyFrame() )
345 {
346 pFlyFrame = static_cast<SwFlyFrame*>( const_cast<SwFrame*>( pFrame ) );
347 }
348
349 return pFlyFrame;
350}
351
353{
354 bool bParaSelected = GetSelectedState() || IsSelected();
355
356 if (m_isSelectedInDoc != bParaSelected)
357 {
358 m_isSelectedInDoc = bParaSelected;
359 FireStateChangedEvent( AccessibleStateType::SELECTED, bParaSelected );
360 return true;
361 }
362 return false;
363}
364
365/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
SfxHintId GetId() const
void EndListeningAll()
bool StartListening(SvtBroadcaster &rBroadcaster)
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true)
const OUString & GetName() const
Definition: acccontext.hxx:334
void FireStateChangedEvent(sal_Int64 nState, bool bNewState)
Definition: acccontext.cxx:467
void SetName(const OUString &rName)
Definition: acccontext.hxx:99
void FireAccessibleEvent(css::accessibility::AccessibleEventObject &rEvent)
Definition: acccontext.cxx:441
virtual void GetStates(sal_Int64 &rStateSet)
Definition: acccontext.cxx:481
vcl::Window * GetWindow()
Definition: acccontext.cxx:80
SwAccessibleMap * GetMap()
Definition: acccontext.hxx:112
std::mutex m_Mutex
Definition: acccontext.hxx:64
css::uno::Reference< css::accessibility::XAccessible > GetWeakParent() const
Definition: acccontext.cxx:72
SwCursorShell * GetCursorShell()
convenience method to get SwCursorShell through accessibility map
Definition: acccontext.cxx:98
virtual void Notify(const SfxHint &) override
virtual void InvalidateCursorPos_() override
virtual void GetStates(sal_Int64 &rStateSet) override
virtual ~SwAccessibleFrameBase() override
virtual void InvalidateFocus_() override
SwAccessibleFrameBase(std::shared_ptr< SwAccessibleMap > const &pInitMap, sal_Int16 nInitRole, const SwFlyFrame *pFlyFrame)
virtual bool HasCursor() override
SwFlyFrame * getFlyFrame() const
virtual bool SetSelectedState(bool bSelected) override
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true) override
static SwNodeType GetNodeType(const SwFlyFrame *pFlyFrame)
const SwFrame * GetFrame() const
Definition: accframe.hxx:102
void SetCursorContext(const ::rtl::Reference< SwAccessibleContext > &rCursorContext)
Definition: accmap.cxx:2732
SwViewShell * GetShell() const
Definition: accmap.hxx:173
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
bool IsTableMode() const
Definition: crsrsh.hxx:668
bool IsFrameSelected() const
Definition: feshview.cxx:1133
size_t IsObjSelected() const
Definition: feshview.cxx:1125
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:3119
FlyAnchors.
Definition: fmtanchr.hxx:37
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:74
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:32
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const OUString & GetName() const
Definition: format.hxx:131
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
Style of a layout element.
Definition: frmfmt.hxx:72
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsNoTextFrame() const
Definition: frame.hxx:1244
bool IsFlyFrame() const
Definition: frame.hxx:1216
const SwFrame * Lower() const
Definition: layfrm.hxx:101
const SwContentNode * GetNode() const
Definition: notxtfrm.hxx:77
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:119
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwNodeType GetNodeType() const
Definition: node.hxx:166
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * End() const
Definition: pam.hxx:263
SwPaM * GetNext()
Definition: pam.hxx:314
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
bool HasFocus() const
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
SwNodeType
Definition: ndtyp.hxx:28
QPRO_FUNC_TYPE nType
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
bool IsSelectFrameAnchoredAtPara(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
is a fly anchored at paragraph at rAnchorPos selected?
Definition: undobj.cxx:1688
bool IsDestroyFrameAnchoredAtChar(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
will DelContentIndex destroy a frame anchored at character at rAnchorPos?
Definition: undobj.cxx:1647