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>
23 #include <osl/mutex.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/window.hxx>
26 #include <frmfmt.hxx>
27 #include <flyfrm.hxx>
28 #include <fmtcntnt.hxx>
29 #include <ndindex.hxx>
30 #include <fesh.hxx>
31 #include <hints.hxx>
32 #include <accmap.hxx>
33 #include "accframebase.hxx"
34 
35 #include <crsrsh.hxx>
36 #include <notxtfrm.hxx>
37 #include <ndtxt.hxx>
38 #include <undobj.hxx>
39 #include <fmtanchr.hxx>
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::accessibility;
43 
45 {
46  bool bRet = false;
47 
48  assert(GetMap());
49  const SwViewShell *pVSh = GetMap()->GetShell();
50  assert(pVSh);
51  if( auto pFESh = dynamic_cast<const SwFEShell*>(pVSh) )
52  {
53  const SwFrame *pFlyFrame = pFESh->GetSelectedFlyFrame();
54  if( pFlyFrame == GetFrame() )
55  bRet = true;
56  }
57 
58  return bRet;
59 }
60 
62  ::utl::AccessibleStateSetHelper& rStateSet )
63 {
64  SwAccessibleContext::GetStates( rStateSet );
65 
66  const SwViewShell *pVSh = GetMap()->GetShell();
67  assert(pVSh);
68 
69  if (dynamic_cast<const SwFEShell*>(pVSh))
70  {
71  // SELECTABLE
72  rStateSet.AddState(AccessibleStateType::SELECTABLE);
73  // FOCUSABLE
74  rStateSet.AddState(AccessibleStateType::FOCUSABLE);
75  }
76 
77  // SELECTED and FOCUSED
78  if( IsSelected() )
79  {
80  rStateSet.AddState( AccessibleStateType::SELECTED );
81  SAL_WARN_IF(!m_bIsSelected, "sw.a11y", "bSelected out of sync");
83  GetMap()->SetCursorContext( xThis );
84 
85  vcl::Window *pWin = GetWindow();
86  if( pWin && pWin->HasFocus() )
87  rStateSet.AddState( AccessibleStateType::FOCUSED );
88  }
89  if( GetSelectedState() )
90  rStateSet.AddState( AccessibleStateType::SELECTED );
91 }
92 
94 {
96  if( pFlyFrame->Lower() )
97  {
98  if( pFlyFrame->Lower()->IsNoTextFrame() )
99  {
100  const SwNoTextFrame *const pContentFrame =
101  static_cast<const SwNoTextFrame *>(pFlyFrame->Lower());
102  nType = pContentFrame->GetNode()->GetNodeType();
103  }
104  }
105  else
106  {
107  const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
108  const SwFormatContent& rContent = pFrameFormat->GetContent();
109  const SwNodeIndex *pNdIdx = rContent.GetContentIdx();
110  if( pNdIdx )
111  {
112  const SwContentNode *pCNd =
113  (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetContentNode();
114  if( pCNd )
115  nType = pCNd->GetNodeType();
116  }
117  }
118 
119  return nType;
120 }
121 
123  std::shared_ptr<SwAccessibleMap> const& pInitMap,
124  sal_Int16 nInitRole,
125  const SwFlyFrame* pFlyFrame ) :
126  SwAccessibleContext( pInitMap, nInitRole, pFlyFrame ),
127  m_bIsSelected( false )
128 {
129  const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
130  if(pFrameFormat)
131  StartListening(const_cast<SwFrameFormat*>(pFrameFormat)->GetNotifier());
132 
133  SetName( pFrameFormat->GetName() );
134 
136 }
137 
139 {
140  bool bNewSelected = IsSelected();
141  bool bOldSelected;
142 
143  {
144  osl::MutexGuard aGuard( m_Mutex );
145  bOldSelected = m_bIsSelected;
146  m_bIsSelected = bNewSelected;
147  }
148 
149  if( bNewSelected )
150  {
151  // remember that object as the one that has the caret. This is
152  // necessary to notify that object if the cursor leaves it.
154  GetMap()->SetCursorContext( xThis );
155  }
156 
157  if( bOldSelected != bNewSelected )
158  {
159  vcl::Window *pWin = GetWindow();
160  if( pWin && pWin->HasFocus() && bNewSelected )
161  FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
162  if( pWin && pWin->HasFocus() && !bNewSelected )
163  FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
164  if(bNewSelected)
165  {
166  uno::Reference< XAccessible > xParent( GetWeakParent() );
167  if( xParent.is() )
168  {
169  SwAccessibleContext *pAcc =
170  static_cast <SwAccessibleContext *>( xParent.get() );
171 
172  AccessibleEventObject aEvent;
173  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
174  uno::Reference< XAccessible > xChild(this);
175  aEvent.NewValue <<= xChild;
176  pAcc->FireAccessibleEvent( aEvent );
177  }
178  }
179  }
180 }
181 
183 {
184  vcl::Window *pWin = GetWindow();
185  if( pWin )
186  {
187  bool bSelected;
188 
189  {
190  osl::MutexGuard aGuard( m_Mutex );
191  bSelected = m_bIsSelected;
192  }
193  assert(bSelected && "focus object should be selected");
194 
195  FireStateChangedEvent( AccessibleStateType::FOCUSED,
196  pWin->HasFocus() && bSelected );
197  }
198 }
199 
201 {
202  osl::MutexGuard aGuard( m_Mutex );
203  return m_bIsSelected;
204 }
205 
207 {
208 }
209 
211 {
212  if(rHint.GetId() == SfxHintId::Dying)
213  {
214  EndListeningAll();
215  }
216  else if(auto pLegacyModifyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
217  {
218  sal_uInt16 nWhich = pLegacyModifyHint->m_pOld ? pLegacyModifyHint->m_pOld->Which() : pLegacyModifyHint->m_pNew ? pLegacyModifyHint->m_pNew->Which() : 0;
219  const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(GetFrame());
220  if(nWhich == RES_NAME_CHANGED && pFlyFrame)
221  {
222  const SwFrameFormat* pFrameFormat = pFlyFrame->GetFormat();
223 
224  const OUString sOldName( GetName() );
225  assert( !pLegacyModifyHint->m_pOld ||
226  static_cast<const SwStringMsgPoolItem *>(pLegacyModifyHint->m_pOld)->GetString() == GetName());
227 
228  SetName( pFrameFormat->GetName() );
229  assert( !pLegacyModifyHint->m_pNew ||
230  static_cast<const SwStringMsgPoolItem *>(pLegacyModifyHint->m_pNew)->GetString() == GetName());
231 
232  if( sOldName != GetName() )
233  {
234  AccessibleEventObject aEvent;
235  aEvent.EventId = AccessibleEventId::NAME_CHANGED;
236  aEvent.OldValue <<= sOldName;
237  aEvent.NewValue <<= GetName();
238  FireAccessibleEvent( aEvent );
239  }
240  }
241  }
242 }
243 
244 void SwAccessibleFrameBase::Dispose(bool bRecursive, bool bCanSkipInvisible)
245 {
246  SolarMutexGuard aGuard;
247  EndListeningAll();
248  SwAccessibleContext::Dispose(bRecursive, bCanSkipInvisible);
249 }
250 
251 //Get the selection cursor of the document.
253 {
254  // get the cursor shell; if we don't have any, we don't have a
255  // cursor/selection either
256  SwPaM* pCursor = nullptr;
257  SwCursorShell* pCursorShell = GetCursorShell();
258  if( pCursorShell != nullptr && !pCursorShell->IsTableMode() )
259  {
260  SwFEShell *pFESh = dynamic_cast<const SwFEShell*>( pCursorShell) != nullptr
261  ? static_cast< SwFEShell * >( pCursorShell ) : nullptr;
262  if( !pFESh ||
263  !(pFESh->IsFrameSelected() || pFESh->IsObjSelected() > 0) )
264  {
265  // get the selection, and test whether it affects our text node
266  pCursor = pCursorShell->GetCursor( false /* ??? */ );
267  }
268  }
269 
270  return pCursor;
271 }
272 
273 //Return the selected state of the object.
274 //when the object's anchor are in the selection cursor, we should return true.
276 {
277  SolarMutexGuard aGuard;
278 
279  if(GetMap()->IsDocumentSelAll())
280  {
281  return true;
282  }
283 
284  // SELECTED.
285  SwFlyFrame* pFlyFrame = getFlyFrame();
286  const SwFrameFormat *pFrameFormat = pFlyFrame->GetFormat();
287  const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
288  const SwPosition *pPos = rAnchor.GetContentAnchor();
289  if( !pPos )
290  return false;
291  int nIndex = pPos->nContent.GetIndex();
292  if( pPos->nNode.GetNode().GetTextNode() )
293  {
294  SwPaM* pCursor = GetCursor();
295  if( pCursor != nullptr )
296  {
297  const SwTextNode* pNode = pPos->nNode.GetNode().GetTextNode();
298  sal_uLong nHere = pNode->GetIndex();
299 
300  // iterate over ring
301  SwPaM* pRingStart = pCursor;
302  do
303  {
304  // ignore, if no mark
305  if( pCursor->HasMark() )
306  {
307  // check whether nHere is 'inside' pCursor
308  SwPosition* pStart = pCursor->Start();
309  sal_uLong nStartIndex = pStart->nNode.GetIndex();
310  SwPosition* pEnd = pCursor->End();
311  sal_uLong nEndIndex = pEnd->nNode.GetIndex();
312  if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex) )
313  {
314  if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
315  {
316  if( ((nHere == nStartIndex) && (nIndex >= pStart->nContent.GetIndex())) || (nHere > nStartIndex) )
317  if( ((nHere == nEndIndex) && (nIndex < pEnd->nContent.GetIndex())) || (nHere < nEndIndex) )
318  return true;
319  }
320  else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA )
321  {
322  if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 )
323  && (nHere < nEndIndex ) )
324  return true;
325  }
326  else if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
327  {
328  if (IsDestroyFrameAnchoredAtChar(*pPos, *pStart, *pEnd))
329  {
330  return true;
331  }
332  }
333  break;
334  }
335  // else: this PaM doesn't point to this paragraph
336  }
337  // else: this PaM is collapsed and doesn't select anything
338 
339  // next PaM in ring
340  pCursor = pCursor->GetNext();
341  }
342  while( pCursor != pRingStart );
343  }
344  }
345  return false;
346 }
347 
349 {
350  SwFlyFrame* pFlyFrame = nullptr;
351 
352  const SwFrame* pFrame = GetFrame();
353  assert(pFrame);
354  if( pFrame->IsFlyFrame() )
355  {
356  pFlyFrame = static_cast<SwFlyFrame*>( const_cast<SwFrame*>( pFrame ) );
357  }
358 
359  return pFlyFrame;
360 }
361 
363 {
364  bool bParaSelected = GetSelectedState() || IsSelected();
365 
366  if (m_isSelectedInDoc != bParaSelected)
367  {
368  m_isSelectedInDoc = bParaSelected;
369  FireStateChangedEvent( AccessibleStateType::SELECTED, bParaSelected );
370  return true;
371  }
372  return false;
373 }
374 
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Base class of the Writer layout elements.
Definition: frame.hxx:295
sal_uLong GetIndex() const
Definition: node.hxx:282
void FireAccessibleEvent(css::accessibility::AccessibleEventObject &rEvent)
Definition: acccontext.cxx:440
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2814
Marks a position in the document model.
Definition: pam.hxx:35
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:184
virtual void GetStates(::utl::AccessibleStateSetHelper &rStateSet) override
virtual void InvalidateFocus_() override
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:646
SwAccessibleFrameBase(std::shared_ptr< SwAccessibleMap > const &pInitMap, sal_Int16 nInitRole, const SwFlyFrame *pFlyFrame)
sal_uIntPtr sal_uLong
vcl::Window * GetWindow()
Definition: acccontext.cxx:83
virtual void Notify(const SfxHint &) override
SwNode & GetNode() const
Definition: ndindex.hxx:119
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:31
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:1543
SfxHintId GetId() const
SwCursorShell * GetCursorShell()
convenience method to get SwCursorShell through accessibility map
Definition: acccontext.cxx:101
bool IsFlyFrame() const
Definition: frame.hxx:1186
SwViewShell * GetShell() const
Definition: accmap.hxx:169
FUNC_TYPE const nType
SwNodeType GetNodeType() const
Definition: node.hxx:144
SwIndex nContent
Definition: pam.hxx:38
const SwFrame * GetFrame() const
Definition: accframe.hxx:103
const OUString & GetName() const
Definition: format.hxx:111
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
virtual bool HasCursor() override
SwPaM * GetNext()
Definition: pam.hxx:264
SwFlyFrame * getFlyFrame() const
void FireStateChangedEvent(sal_Int16 nState, bool bNewState)
Definition: acccontext.cxx:464
void EndListeningAll()
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
Style of a layout element.
Definition: frmfmt.hxx:57
SwNodeType
Definition: ndtyp.hxx:28
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
const OUString & GetName() const
Definition: acccontext.hxx:333
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
const SwFrame * Lower() const
Definition: layfrm.hxx:100
SwContentNode * GetContentNode()
Definition: node.hxx:615
FlyAnchors.
Definition: fmtanchr.hxx:34
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
Marks a node in the document model.
Definition: ndindex.hxx:31
bool StartListening(SvtBroadcaster &rBroadcaster)
static SwNodeType GetNodeType(const SwFlyFrame *pFlyFrame)
const SwPosition * Start() const
Definition: pam.hxx:212
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
virtual void InvalidateCursorPos_() override
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
const SwContentNode * GetNode() const
Definition: notxtfrm.hxx:60
general base class for all free-flowing frames
Definition: flyfrm.hxx:60
virtual ~SwAccessibleFrameBase() override
#define SAL_WARN_IF(condition, area, stream)
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true)
const SwNodes & GetNodes() const
Definition: ndindex.hxx:156
virtual void GetStates(::utl::AccessibleStateSetHelper &rStateSet)
Definition: acccontext.cxx:478
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool IsNoTextFrame() const
Definition: frame.hxx:1214
const SwPosition * End() const
Definition: pam.hxx:217
#define RES_NAME_CHANGED
Definition: hintids.hxx:311
size_t IsObjSelected() const
Definition: feshview.cxx:1167
css::uno::Reference< css::accessibility::XAccessible > GetWeakParent() const
Definition: acccontext.cxx:75
SwAccessibleMap * GetMap()
Definition: acccontext.hxx:112
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
virtual bool SetSelectedState(bool bSeleted) override
mutable::osl::Mutex m_Mutex
Definition: acccontext.hxx:64
void SetCursorContext(const ::rtl::Reference< SwAccessibleContext > &rCursorContext)
Definition: accmap.cxx:2792
bool HasFocus() const
void AddState(sal_Int16 aState)
void SetName(const OUString &rName)
Definition: acccontext.hxx:99
bool IsFrameSelected() const
Definition: feshview.cxx:1175
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true) override
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842