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