sc: factor out some more code
[LibreOffice.git] / sw / source / core / access / acccell.cxx
blob2ce7b0302ea70ae6a4942e1a18a422e0e6cc863c
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 <sal/log.hxx>
21 #include <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
23 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <cppuhelper/typeprovider.hxx>
26 #include <vcl/svapp.hxx>
27 #include <cellfrm.hxx>
28 #include <tabfrm.hxx>
29 #include <swtable.hxx>
30 #include <crsrsh.hxx>
31 #include <viscrs.hxx>
32 #include "accfrmobj.hxx"
33 #include "accfrmobjslist.hxx"
34 #include <frmfmt.hxx>
35 #include <cellatr.hxx>
36 #include <accmap.hxx>
37 #include "acccell.hxx"
39 #include <cfloat>
40 #include <string_view>
42 #include <editeng/brushitem.hxx>
43 #include <swatrset.hxx>
44 #include <frmatr.hxx>
45 #include "acctable.hxx"
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::accessibility;
49 using namespace sw::access;
51 bool SwAccessibleCell::IsSelected()
53 bool bRet = false;
55 assert(GetMap());
56 const SwViewShell *pVSh = GetMap()->GetShell();
57 assert(pVSh);
58 if( auto pCSh = dynamic_cast<const SwCursorShell*>(pVSh) )
60 if( pCSh->IsTableMode() )
62 const SwCellFrame *pCFrame =
63 static_cast< const SwCellFrame * >( GetFrame() );
64 SwTableBox *pBox =
65 const_cast< SwTableBox *>( pCFrame->GetTabBox() );
66 SwSelBoxes const& rBoxes(pCSh->GetTableCursor()->GetSelectedBoxes());
67 bRet = rBoxes.find(pBox) != rBoxes.end();
71 return bRet;
74 void SwAccessibleCell::GetStates( sal_Int64& rStateSet )
76 SwAccessibleContext::GetStates( rStateSet );
78 // SELECTABLE
79 const SwViewShell *pVSh = GetMap()->GetShell();
80 assert(pVSh);
81 if( dynamic_cast<const SwCursorShell*>( pVSh) != nullptr )
82 rStateSet |= AccessibleStateType::SELECTABLE;
83 //Add resizable state to table cell.
84 rStateSet |= AccessibleStateType::RESIZABLE;
86 if (IsDisposing()) // tdf#135098
87 return;
89 // SELECTED
90 if( IsSelected() )
92 rStateSet |= AccessibleStateType::SELECTED;
93 SAL_WARN_IF(!m_bIsSelected, "sw.a11y", "bSelected out of sync");
94 ::rtl::Reference < SwAccessibleContext > xThis( this );
95 GetMap()->SetCursorContext( xThis );
99 SwAccessibleCell::SwAccessibleCell(std::shared_ptr<SwAccessibleMap> const& pInitMap,
100 const SwCellFrame *pCellFrame )
101 : SwAccessibleCell_BASE(pInitMap, AccessibleRole::TABLE_CELL, pCellFrame)
102 , m_aSelectionHelper( *this )
103 , m_bIsSelected( false )
105 OUString sBoxName( pCellFrame->GetTabBox()->GetName() );
106 SetName( sBoxName );
108 m_bIsSelected = IsSelected();
110 css::uno::Reference<css::accessibility::XAccessible> xTableReference(
111 getAccessibleParentImpl());
112 css::uno::Reference<css::accessibility::XAccessibleContext> xContextTable(
113 xTableReference, css::uno::UNO_QUERY);
114 SAL_WARN_IF(
115 (!xContextTable.is()
116 || xContextTable->getAccessibleRole() != AccessibleRole::TABLE),
117 "sw.a11y", "bad accessible context");
118 m_pAccTable = static_cast<SwAccessibleTable *>(xTableReference.get());
121 bool SwAccessibleCell::InvalidateMyCursorPos()
123 bool bNew = IsSelected();
124 bool bOld;
126 std::scoped_lock aGuard( m_Mutex );
127 bOld = m_bIsSelected;
128 m_bIsSelected = bNew;
130 if( bNew )
132 // remember that object as the one that has the caret. This is
133 // necessary to notify that object if the cursor leaves it.
134 ::rtl::Reference < SwAccessibleContext > xThis( this );
135 GetMap()->SetCursorContext( xThis );
138 bool bChanged = bOld != bNew;
139 if( bChanged )
141 FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
142 if (m_pAccTable.is())
144 m_pAccTable->AddSelectionCell(this,bNew);
147 return bChanged;
150 bool SwAccessibleCell::InvalidateChildrenCursorPos( const SwFrame *pFrame )
152 bool bChanged = false;
154 const SwAccessibleChildSList aVisList( GetVisArea(), *pFrame, *GetMap() );
155 SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
156 while( aIter != aVisList.end() )
158 const SwAccessibleChild& rLower = *aIter;
159 const SwFrame *pLower = rLower.GetSwFrame();
160 if( pLower )
162 if( rLower.IsAccessible( GetMap()->GetShell()->IsPreview() ) )
164 ::rtl::Reference< SwAccessibleContext > xAccImpl(
165 GetMap()->GetContextImpl( pLower, false ) );
166 if( xAccImpl.is() )
168 assert(xAccImpl->GetFrame()->IsCellFrame());
169 bChanged = static_cast< SwAccessibleCell *>(
170 xAccImpl.get() )->InvalidateMyCursorPos();
172 else
173 bChanged = true; // If the context is not know we
174 // don't know whether the selection
175 // changed or not.
177 else
179 // This is a box with sub rows.
180 bChanged |= InvalidateChildrenCursorPos( pLower );
183 ++aIter;
186 return bChanged;
189 void SwAccessibleCell::InvalidateCursorPos_()
191 if (IsSelected())
193 const SwAccessibleChild aChild( GetChild( *(GetMap()), 0 ) );
194 if( aChild.IsValid() && aChild.GetSwFrame() )
196 ::rtl::Reference < SwAccessibleContext > xChildImpl( GetMap()->GetContextImpl( aChild.GetSwFrame()) );
197 if (xChildImpl.is())
199 AccessibleEventObject aEvent;
200 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
201 aEvent.NewValue <<= AccessibleStateType::FOCUSED;
202 xChildImpl->FireAccessibleEvent( aEvent );
207 const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
208 assert(pParent->IsTabFrame());
209 const SwTabFrame *pTabFrame = static_cast< const SwTabFrame * >( pParent );
210 if( pTabFrame->IsFollow() )
211 pTabFrame = pTabFrame->FindMaster();
213 while( pTabFrame )
215 InvalidateChildrenCursorPos( pTabFrame );
216 pTabFrame = pTabFrame->GetFollow();
218 if (m_pAccTable.is())
220 m_pAccTable->FireSelectionEvent();
224 bool SwAccessibleCell::HasCursor()
226 std::scoped_lock aGuard( m_Mutex );
227 return m_bIsSelected;
230 SwAccessibleCell::~SwAccessibleCell()
234 OUString SAL_CALL SwAccessibleCell::getAccessibleDescription()
236 return GetName();
239 OUString SAL_CALL SwAccessibleCell::getImplementationName()
241 return u"com.sun.star.comp.Writer.SwAccessibleCellView"_ustr;
244 sal_Bool SAL_CALL SwAccessibleCell::supportsService(const OUString& sTestServiceName)
246 return cppu::supportsService(this, sTestServiceName);
249 uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
251 return { u"com.sun.star.table.AccessibleCellView"_ustr, sAccessibleServiceName };
254 void SwAccessibleCell::Dispose(bool bRecursive, bool bCanSkipInvisible)
256 const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
257 ::rtl::Reference< SwAccessibleContext > xAccImpl(
258 GetMap()->GetContextImpl( pParent, false ) );
259 if( xAccImpl.is() )
260 xAccImpl->DisposeChild(SwAccessibleChild(GetFrame()), bRecursive, bCanSkipInvisible);
261 SwAccessibleContext::Dispose( bRecursive );
264 void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
266 const SwFrame *pParent = GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
267 ::rtl::Reference< SwAccessibleContext > xAccImpl(
268 GetMap()->GetContextImpl( pParent, false ) );
269 if( xAccImpl.is() )
270 xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrame()), rOldBox );
271 SwAccessibleContext::InvalidatePosOrSize( rOldBox );
274 // XAccessibleValue
276 SwFrameFormat* SwAccessibleCell::GetTableBoxFormat() const
278 assert(GetFrame());
279 assert(GetFrame()->IsCellFrame());
281 const SwCellFrame* pCellFrame = static_cast<const SwCellFrame*>( GetFrame() );
282 return pCellFrame->GetTabBox()->GetFrameFormat();
285 //Implement TableCell currentValue
286 uno::Any SwAccessibleCell::getCurrentValue( )
288 SolarMutexGuard aGuard;
290 ThrowIfDisposed();
292 return uno::Any( GetTableBoxFormat()->GetTableBoxValue().GetValue() );
295 sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
297 SolarMutexGuard aGuard;
299 ThrowIfDisposed();
301 double fValue = 0;
302 bool bValid = (aNumber >>= fValue);
303 if( bValid )
305 SwTableBoxValue aValue( fValue );
306 GetTableBoxFormat()->SetFormatAttr( aValue );
308 return bValid;
311 uno::Any SwAccessibleCell::getMaximumValue( )
313 return uno::Any(DBL_MAX);
316 uno::Any SwAccessibleCell::getMinimumValue( )
318 return uno::Any(-DBL_MAX);
321 uno::Any SwAccessibleCell::getMinimumIncrement( )
323 return uno::Any();
326 css::uno::Any SAL_CALL SwAccessibleCell::getExtendedAttributes()
328 SolarMutexGuard g;
330 css::uno::Any strRet;
331 SwFrameFormat *pFrameFormat = GetTableBoxFormat();
332 assert(pFrameFormat);
334 const SwTableBoxFormula& tbl_formula = pFrameFormat->GetTableBoxFormula();
336 OUString strFormula = tbl_formula.GetFormula()
337 .replaceAll(u"\\", u"\\\\")
338 .replaceAll(u";", u"\\;")
339 .replaceAll(u"=", u"\\=")
340 .replaceAll(u",", u"\\,")
341 .replaceAll(u":", u"\\:");
342 OUString strFor = "Formula:" + strFormula + ";";
343 strRet <<= strFor;
345 return strRet;
348 sal_Int32 SAL_CALL SwAccessibleCell::getBackground()
350 SolarMutexGuard g;
352 const SvxBrushItem &rBack = GetFrame()->GetAttrSet()->GetBackground();
353 Color crBack = rBack.GetColor();
355 if (COL_AUTO == crBack)
357 uno::Reference<XAccessible> xAccDoc = getAccessibleParent();
358 if (xAccDoc.is())
360 uno::Reference<XAccessibleComponent> xComponentDoc(xAccDoc, uno::UNO_QUERY);
361 if (xComponentDoc.is())
363 crBack = Color(ColorTransparency, xComponentDoc->getBackground());
367 return sal_Int32(crBack);
370 // XAccessibleSelection
371 void SwAccessibleCell::selectAccessibleChild(
372 sal_Int64 nChildIndex )
374 m_aSelectionHelper.selectAccessibleChild(nChildIndex);
377 sal_Bool SwAccessibleCell::isAccessibleChildSelected(
378 sal_Int64 nChildIndex )
380 return m_aSelectionHelper.isAccessibleChildSelected(nChildIndex);
383 void SwAccessibleCell::clearAccessibleSelection( )
387 void SwAccessibleCell::selectAllAccessibleChildren( )
389 m_aSelectionHelper.selectAllAccessibleChildren();
392 sal_Int64 SwAccessibleCell::getSelectedAccessibleChildCount( )
394 return m_aSelectionHelper.getSelectedAccessibleChildCount();
397 uno::Reference<XAccessible> SwAccessibleCell::getSelectedAccessibleChild(
398 sal_Int64 nSelectedChildIndex )
400 return m_aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
403 void SwAccessibleCell::deselectAccessibleChild(
404 sal_Int64 nSelectedChildIndex )
406 m_aSelectionHelper.deselectAccessibleChild(nSelectedChildIndex);
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */