LibreOffice Module sw (master)  1
acccell.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 <osl/mutex.hxx>
21 #include <sal/log.hxx>
22 #include <com/sun/star/accessibility/AccessibleRole.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <vcl/svapp.hxx>
29 #include <cellfrm.hxx>
30 #include <tabfrm.hxx>
31 #include <swtable.hxx>
32 #include <crsrsh.hxx>
33 #include <viscrs.hxx>
34 #include "accfrmobj.hxx"
35 #include "accfrmobjslist.hxx"
36 #include <frmfmt.hxx>
37 #include <cellatr.hxx>
38 #include <accmap.hxx>
39 #include "acccell.hxx"
40 
41 #include <cfloat>
42 
43 #include <editeng/brushitem.hxx>
44 #include <swatrset.hxx>
45 #include <frmatr.hxx>
46 #include "acctable.hxx"
47 
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::accessibility;
50 using namespace sw::access;
51 
52 const char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleCellView";
53 
55 {
56  bool bRet = false;
57 
58  assert(GetMap());
59  const SwViewShell *pVSh = GetMap()->GetShell();
60  assert(pVSh);
61  if( auto pCSh = dynamic_cast<const SwCursorShell*>(pVSh) )
62  {
63  if( pCSh->IsTableMode() )
64  {
65  const SwCellFrame *pCFrame =
66  static_cast< const SwCellFrame * >( GetFrame() );
67  SwTableBox *pBox =
68  const_cast< SwTableBox *>( pCFrame->GetTabBox() );
69  SwSelBoxes const& rBoxes(pCSh->GetTableCursor()->GetSelectedBoxes());
70  bRet = rBoxes.find(pBox) != rBoxes.end();
71  }
72  }
73 
74  return bRet;
75 }
76 
78 {
79  SwAccessibleContext::GetStates( rStateSet );
80 
81  // SELECTABLE
82  const SwViewShell *pVSh = GetMap()->GetShell();
83  assert(pVSh);
84  if( dynamic_cast<const SwCursorShell*>( pVSh) != nullptr )
85  rStateSet.AddState( AccessibleStateType::SELECTABLE );
86  //Add resizable state to table cell.
87  rStateSet.AddState( AccessibleStateType::RESIZABLE );
88 
89  if (IsDisposing()) // tdf#135098
90  return;
91 
92  // SELECTED
93  if( IsSelected() )
94  {
95  rStateSet.AddState( AccessibleStateType::SELECTED );
96  SAL_WARN_IF(!m_bIsSelected, "sw.a11y", "bSelected out of sync");
98  GetMap()->SetCursorContext( xThis );
99  }
100 }
101 
102 SwAccessibleCell::SwAccessibleCell(std::shared_ptr<SwAccessibleMap> const& pInitMap,
103  const SwCellFrame *pCellFrame )
104  : SwAccessibleContext( pInitMap, AccessibleRole::TABLE_CELL, pCellFrame )
105  , m_aSelectionHelper( *this )
106  , m_bIsSelected( false )
107 {
108  OUString sBoxName( pCellFrame->GetTabBox()->GetName() );
109  SetName( sBoxName );
110 
112 
113  css::uno::Reference<css::accessibility::XAccessible> xTableReference(
115  css::uno::Reference<css::accessibility::XAccessibleContext> xContextTable(
116  xTableReference, css::uno::UNO_QUERY);
117  SAL_WARN_IF(
118  (!xContextTable.is()
119  || xContextTable->getAccessibleRole() != AccessibleRole::TABLE),
120  "sw.a11y", "bad accessible context");
121  m_pAccTable = static_cast<SwAccessibleTable *>(xTableReference.get());
122 }
123 
125 {
126  bool bNew = IsSelected();
127  bool bOld;
128  {
129  osl::MutexGuard aGuard( m_Mutex );
130  bOld = m_bIsSelected;
131  m_bIsSelected = bNew;
132  }
133  if( bNew )
134  {
135  // remember that object as the one that has the caret. This is
136  // necessary to notify that object if the cursor leaves it.
138  GetMap()->SetCursorContext( xThis );
139  }
140 
141  bool bChanged = bOld != bNew;
142  if( bChanged )
143  {
144  FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
145  if (m_pAccTable.is())
146  {
147  m_pAccTable->AddSelectionCell(this,bNew);
148  }
149  }
150  return bChanged;
151 }
152 
154 {
155  bool bChanged = false;
156 
157  const SwAccessibleChildSList aVisList( GetVisArea(), *pFrame, *GetMap() );
158  SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
159  while( aIter != aVisList.end() )
160  {
161  const SwAccessibleChild& rLower = *aIter;
162  const SwFrame *pLower = rLower.GetSwFrame();
163  if( pLower )
164  {
165  if( rLower.IsAccessible( GetMap()->GetShell()->IsPreview() ) )
166  {
168  GetMap()->GetContextImpl( pLower, false ) );
169  if( xAccImpl.is() )
170  {
171  assert(xAccImpl->GetFrame()->IsCellFrame());
172  bChanged = static_cast< SwAccessibleCell *>(
173  xAccImpl.get() )->InvalidateMyCursorPos();
174  }
175  else
176  bChanged = true; // If the context is not know we
177  // don't know whether the selection
178  // changed or not.
179  }
180  else
181  {
182  // This is a box with sub rows.
183  bChanged |= InvalidateChildrenCursorPos( pLower );
184  }
185  }
186  ++aIter;
187  }
188 
189  return bChanged;
190 }
191 
193 {
194  if (IsSelected())
195  {
196  const SwAccessibleChild aChild( GetChild( *(GetMap()), 0 ) );
197  if( aChild.IsValid() && aChild.GetSwFrame() )
198  {
199  ::rtl::Reference < SwAccessibleContext > xChildImpl( GetMap()->GetContextImpl( aChild.GetSwFrame()) );
200  if (xChildImpl.is())
201  {
202  AccessibleEventObject aEvent;
203  aEvent.EventId = AccessibleEventId::STATE_CHANGED;
204  aEvent.NewValue <<= AccessibleStateType::FOCUSED;
205  xChildImpl->FireAccessibleEvent( aEvent );
206  }
207  }
208  }
209 
210  const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
211  assert(pParent->IsTabFrame());
212  const SwTabFrame *pTabFrame = static_cast< const SwTabFrame * >( pParent );
213  if( pTabFrame->IsFollow() )
214  pTabFrame = pTabFrame->FindMaster();
215 
216  while( pTabFrame )
217  {
218  InvalidateChildrenCursorPos( pTabFrame );
219  pTabFrame = pTabFrame->GetFollow();
220  }
221  if (m_pAccTable.is())
222  {
223  m_pAccTable->FireSelectionEvent();
224  }
225 }
226 
228 {
229  osl::MutexGuard aGuard( m_Mutex );
230  return m_bIsSelected;
231 }
232 
234 {
235 }
236 
238 {
239  return GetName();
240 }
241 
243 {
244  return sImplementationName;
245 }
246 
247 sal_Bool SAL_CALL SwAccessibleCell::supportsService(const OUString& sTestServiceName)
248 {
249  return cppu::supportsService(this, sTestServiceName);
250 }
251 
252 uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
253 {
254  return { "com.sun.star.table.AccessibleCellView", sAccessibleServiceName };
255 }
256 
257 void SwAccessibleCell::Dispose(bool bRecursive, bool bCanSkipInvisible)
258 {
259  const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
261  GetMap()->GetContextImpl( pParent, false ) );
262  if( xAccImpl.is() )
263  xAccImpl->DisposeChild(SwAccessibleChild(GetFrame()), bRecursive, bCanSkipInvisible);
264  SwAccessibleContext::Dispose( bRecursive );
265 }
266 
268 {
269  const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
271  GetMap()->GetContextImpl( pParent, false ) );
272  if( xAccImpl.is() )
273  xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrame()), rOldBox );
275 }
276 
277 // XAccessibleInterface
278 
280 {
282  {
283  uno::Any aR;
284  aR <<= uno::Reference<XAccessibleExtendedAttributes>(this);
285  return aR;
286  }
287 
289  {
290  uno::Any aR;
291  aR <<= uno::Reference<XAccessibleSelection>(this);
292  return aR;
293  }
294  if ( rType == ::cppu::UnoType<XAccessibleValue>::get() )
295  {
296  uno::Reference<XAccessibleValue> xValue = this;
297  uno::Any aRet;
298  aRet <<= xValue;
299  return aRet;
300  }
301  else
302  {
303  return SwAccessibleContext::queryInterface( rType );
304  }
305 }
306 
307 // XTypeProvider
308 uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
309 {
310  return cppu::OTypeCollection(
312  SwAccessibleContext::getTypes() ).getTypes();
313 }
314 
315 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
316 {
317  return css::uno::Sequence<sal_Int8>();
318 }
319 
320 // XAccessibleValue
321 
323 {
324  assert(GetFrame());
325  assert(GetFrame()->IsCellFrame());
326 
327  const SwCellFrame* pCellFrame = static_cast<const SwCellFrame*>( GetFrame() );
328  return pCellFrame->GetTabBox()->GetFrameFormat();
329 }
330 
331 //Implement TableCell currentValue
333 {
334  SolarMutexGuard aGuard;
335 
336  ThrowIfDisposed();
337 
338  return uno::Any( GetTableBoxFormat()->GetTableBoxValue().GetValue() );
339 }
340 
342 {
343  SolarMutexGuard aGuard;
344 
345  ThrowIfDisposed();
346 
347  double fValue = 0;
348  bool bValid = (aNumber >>= fValue);
349  if( bValid )
350  {
351  SwTableBoxValue aValue( fValue );
352  GetTableBoxFormat()->SetFormatAttr( aValue );
353  }
354  return bValid;
355 }
356 
358 {
359  return uno::Any(DBL_MAX);
360 }
361 
363 {
364  return uno::Any(-DBL_MAX);
365 }
366 
367 static OUString ReplaceOneChar(const OUString& oldOUString, const OUString& replacedChar, const OUString& replaceStr)
368 {
369  int iReplace = oldOUString.lastIndexOf(replacedChar);
370  OUString aRet = oldOUString;
371  while(iReplace > -1)
372  {
373  aRet = aRet.replaceAt(iReplace,1, replaceStr);
374  iReplace = aRet.lastIndexOf(replacedChar,iReplace);
375  }
376  return aRet;
377 }
378 
379 static OUString ReplaceFourChar(const OUString& oldOUString)
380 {
381  OUString aRet = ReplaceOneChar(oldOUString,"\\","\\\\");
382  aRet = ReplaceOneChar(aRet,";","\\;");
383  aRet = ReplaceOneChar(aRet,"=","\\=");
384  aRet = ReplaceOneChar(aRet,",","\\,");
385  aRet = ReplaceOneChar(aRet,":","\\:");
386  return aRet;
387 }
388 
390 {
391  SolarMutexGuard g;
392 
393  css::uno::Any strRet;
394  SwFrameFormat *pFrameFormat = GetTableBoxFormat();
395  assert(pFrameFormat);
396 
397  const SwTableBoxFormula& tbl_formula = pFrameFormat->GetTableBoxFormula();
398 
399  OUString strFormula = ReplaceFourChar(tbl_formula.GetFormula());
400  OUString strFor = "Formula:" + strFormula + ";";
401  strRet <<= strFor;
402 
403  return strRet;
404 }
405 
407 {
408  SolarMutexGuard g;
409 
410  const SvxBrushItem &rBack = GetFrame()->GetAttrSet()->GetBackground();
411  Color crBack = rBack.GetColor();
412 
413  if (COL_AUTO == crBack)
414  {
415  uno::Reference<XAccessible> xAccDoc = getAccessibleParent();
416  if (xAccDoc.is())
417  {
418  uno::Reference<XAccessibleComponent> xComponentDoc(xAccDoc, uno::UNO_QUERY);
419  if (xComponentDoc.is())
420  {
421  crBack = Color(xComponentDoc->getBackground());
422  }
423  }
424  }
425  return sal_Int32(crBack);
426 }
427 
428 // XAccessibleSelection
430  sal_Int32 nChildIndex )
431 {
433 }
434 
436  sal_Int32 nChildIndex )
437 {
438  return m_aSelectionHelper.isAccessibleChildSelected(nChildIndex);
439 }
440 
442 {
443 }
444 
446 {
448 }
449 
451 {
453 }
454 
456  sal_Int32 nSelectedChildIndex )
457 {
458  return m_aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
459 }
460 
462  sal_Int32 nSelectedChildIndex )
463 {
464  m_aSelectionHelper.deselectAccessibleChild(nSelectedChildIndex);
465 }
466 
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::accessibility::XAccessible > getAccessibleParentImpl()
Definition: acccontext.cxx:664
Base class of the Writer layout elements.
Definition: frame.hxx:297
static OUString ReplaceOneChar(const OUString &oldOUString, const OUString &replacedChar, const OUString &replaceStr)
Definition: acccell.cxx:367
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true) override
Definition: acccell.cxx:257
const SvxBrushItem & GetBackground(bool=true) const
Definition: frmatr.hxx:58
virtual bool HasCursor() override
Definition: acccell.cxx:227
std::string GetValue
virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount() override
Definition: acccell.cxx:450
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwViewShell * GetShell()
convenience method to get the SwViewShell through accessibility map
Definition: acccontext.hxx:117
const_iterator find(const Value &x) const
virtual void SAL_CALL deselectAccessibleChild(sal_Int32 nSelectedChildIndex) override
Definition: acccell.cxx:461
virtual void SAL_CALL clearAccessibleSelection() override
Definition: acccell.cxx:441
virtual css::uno::Any SAL_CALL getMaximumValue() override
Definition: acccell.cxx:357
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: acccell.cxx:308
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool IsInPagePreview() const
Definition: accframe.hxx:87
const char sImplementationName[]
Definition: acccell.cxx:52
constexpr::Color COL_AUTO(0xFF, 0xFF, 0xFF, 0xFF)
bool IsSelected()
Definition: acccell.cxx:54
static sw::access::SwAccessibleChild GetChild(SwAccessibleMap &rAccMap, const SwRect &rVisArea, const SwFrame &rFrame, sal_Int32 &rPos, bool bInPagePreview)
Definition: accframe.cxx:71
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
const SwFrame * GetFrame() const
Definition: accframe.hxx:103
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
bool isAccessibleChildSelected(sal_Int32 nChildIndex)
virtual void InvalidatePosOrSize(const SwRect &rFrame) override
Definition: acccell.cxx:267
virtual void SAL_CALL selectAccessibleChild(sal_Int32 nChildIndex) override
Definition: acccell.cxx:429
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Definition: acccell.cxx:315
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:674
css::uno::Reference< css::accessibility::XAccessible > getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)
const Color & GetColor() const
void FireStateChangedEvent(sal_Int16 nState, bool bNewState)
Definition: acccontext.cxx:467
const SwFrame * GetSwFrame() const
Definition: accfrmobj.hxx:58
OUString GetName() const
Definition: swtable.cxx:1829
virtual css::uno::Any SAL_CALL getCurrentValue() override
Definition: acccell.cxx:332
Style of a layout element.
Definition: frmfmt.hxx:57
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:717
virtual sal_Bool SAL_CALL setCurrentValue(const css::uno::Any &aNumber) override
Definition: acccell.cxx:341
const_iterator begin() const
const OUString & GetName() const
Definition: acccontext.hxx:337
rtl::Reference< SwAccessibleTable > m_pAccTable
Definition: acccell.hxx:44
SwFrameFormat * GetTableBoxFormat() const
Definition: acccell.cxx:322
SwAccessibleCell(std::shared_ptr< SwAccessibleMap > const &pInitMap, const SwCellFrame *pCellFrame)
Definition: acccell.cxx:102
virtual OUString SAL_CALL getImplementationName() override
Definition: acccell.cxx:242
unsigned char sal_Bool
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Definition: acccontext.cxx:686
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:425
virtual void InvalidateCursorPos_() override
Definition: acccell.cxx:192
virtual void InvalidatePosOrSize(const SwRect &rFrame)
const_iterator end() const
const char sAccessibleServiceName[]
Definition: acccontext.hxx:43
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex) override
Definition: acccell.cxx:455
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:460
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: acccell.cxx:252
virtual void GetStates(::utl::AccessibleStateSetHelper &rStateSet) override
Definition: acccell.cxx:77
const OUString & GetFormula() const
Definition: cellfml.hxx:136
virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int32 nChildIndex) override
Definition: acccell.cxx:435
bool IsTabFrame() const
Definition: frame.hxx:1196
#define SAL_WARN_IF(condition, area, stream)
bool m_bIsSelected
Definition: acccell.hxx:37
virtual void Dispose(bool bRecursive, bool bCanSkipInvisible=true)
virtual css::uno::Any SAL_CALL getMinimumValue() override
Definition: acccell.cxx:362
virtual void GetStates(::utl::AccessibleStateSetHelper &rStateSet)
Definition: acccontext.cxx:481
bool IsAccessible(bool bPagePreview) const
Definition: accfrmobj.cxx:122
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
Definition: acccell.cxx:279
void selectAccessibleChild(sal_Int32 nChildIndex)
sal_Int32 SAL_CALL getBackground() override
Definition: acccell.cxx:406
const SwFrame * GetParent() const
Definition: accframe.hxx:155
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
static OUString ReplaceFourChar(const OUString &oldOUString)
Definition: acccell.cxx:379
bool InvalidateMyCursorPos()
Definition: acccell.cxx:124
css::uno::Any SAL_CALL getExtendedAttributes() override
Definition: acccell.cxx:389
virtual ~SwAccessibleCell() override
Definition: acccell.cxx:233
css::uno::Sequence< css::uno::Type > SAL_CALL getTypes()
SwAccessibleMap * GetMap()
Definition: acccontext.hxx:113
virtual OUString SAL_CALL getAccessibleDescription() override
Return this object's description.
Definition: acccell.cxx:237
void deselectAccessibleChild(sal_Int32 nChildIndex)
virtual void SAL_CALL selectAllAccessibleChildren() override
Definition: acccell.cxx:445
mutable::osl::Mutex m_Mutex
Definition: acccontext.hxx:65
void SetCursorContext(const ::rtl::Reference< SwAccessibleContext > &rCursorContext)
Definition: accmap.cxx:2806
virtual sal_Bool SAL_CALL supportsService(const OUString &sServiceName) override
Return whether the specified service is supported by this class.
Definition: acccell.cxx:247
const SwRect & GetVisArea() const
Definition: accframe.hxx:136
bool InvalidateChildrenCursorPos(const SwFrame *pFrame)
Definition: acccell.cxx:153
SwAccessibleSelectionHelper m_aSelectionHelper
Definition: acccell.hxx:36
void AddState(sal_Int16 aState)
void SetName(const OUString &rName)
Definition: acccontext.hxx:100
AnyEventRef aEvent
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
const SwTableBoxFormula & GetTableBoxFormula(bool=true) const
Definition: cellatr.hxx:107