1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
29 #include <swtable.hxx>
32 #include "accfrmobj.hxx"
33 #include "accfrmobjslist.hxx"
35 #include <cellatr.hxx>
37 #include "acccell.hxx"
40 #include <string_view>
42 #include <editeng/brushitem.hxx>
43 #include <swatrset.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()
56 const SwViewShell
*pVSh
= GetMap()->GetShell();
58 if( auto pCSh
= dynamic_cast<const SwCursorShell
*>(pVSh
) )
60 if( pCSh
->IsTableMode() )
62 const SwCellFrame
*pCFrame
=
63 static_cast< const SwCellFrame
* >( GetFrame() );
65 const_cast< SwTableBox
*>( pCFrame
->GetTabBox() );
66 SwSelBoxes
const& rBoxes(pCSh
->GetTableCursor()->GetSelectedBoxes());
67 bRet
= rBoxes
.find(pBox
) != rBoxes
.end();
74 void SwAccessibleCell::GetStates( sal_Int64
& rStateSet
)
76 SwAccessibleContext::GetStates( rStateSet
);
79 const SwViewShell
*pVSh
= GetMap()->GetShell();
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
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() );
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
);
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();
126 std::scoped_lock
aGuard( m_Mutex
);
127 bOld
= m_bIsSelected
;
128 m_bIsSelected
= 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
;
141 FireStateChangedEvent( AccessibleStateType::SELECTED
, bNew
);
142 if (m_pAccTable
.is())
144 m_pAccTable
->AddSelectionCell(this,bNew
);
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();
162 if( rLower
.IsAccessible( GetMap()->GetShell()->IsPreview() ) )
164 ::rtl::Reference
< SwAccessibleContext
> xAccImpl(
165 GetMap()->GetContextImpl( pLower
, false ) );
168 assert(xAccImpl
->GetFrame()->IsCellFrame());
169 bChanged
= static_cast< SwAccessibleCell
*>(
170 xAccImpl
.get() )->InvalidateMyCursorPos();
173 bChanged
= true; // If the context is not know we
174 // don't know whether the selection
179 // This is a box with sub rows.
180 bChanged
|= InvalidateChildrenCursorPos( pLower
);
189 void SwAccessibleCell::InvalidateCursorPos_()
193 const SwAccessibleChild
aChild( GetChild( *(GetMap()), 0 ) );
194 if( aChild
.IsValid() && aChild
.GetSwFrame() )
196 ::rtl::Reference
< SwAccessibleContext
> xChildImpl( GetMap()->GetContextImpl( aChild
.GetSwFrame()) );
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();
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()
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 ) );
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 ) );
270 xAccImpl
->InvalidateChildPosOrSize( SwAccessibleChild(GetFrame()), rOldBox
);
271 SwAccessibleContext::InvalidatePosOrSize( rOldBox
);
276 SwFrameFormat
* SwAccessibleCell::GetTableBoxFormat() const
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
;
292 return uno::Any( GetTableBoxFormat()->GetTableBoxValue().GetValue() );
295 sal_Bool
SwAccessibleCell::setCurrentValue( const uno::Any
& aNumber
)
297 SolarMutexGuard aGuard
;
302 bool bValid
= (aNumber
>>= fValue
);
305 SwTableBoxValue
aValue( fValue
);
306 GetTableBoxFormat()->SetFormatAttr( aValue
);
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( )
326 css::uno::Any SAL_CALL
SwAccessibleCell::getExtendedAttributes()
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
+ ";";
348 sal_Int32 SAL_CALL
SwAccessibleCell::getBackground()
352 const SvxBrushItem
&rBack
= GetFrame()->GetAttrSet()->GetBackground();
353 Color crBack
= rBack
.GetColor();
355 if (COL_AUTO
== crBack
)
357 uno::Reference
<XAccessible
> xAccDoc
= getAccessibleParent();
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: */