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 constexpr OUStringLiteral sImplementationName
= u
"com.sun.star.comp.Writer.SwAccessibleCellView";
53 bool SwAccessibleCell::IsSelected()
58 const SwViewShell
*pVSh
= GetMap()->GetShell();
60 if( auto pCSh
= dynamic_cast<const SwCursorShell
*>(pVSh
) )
62 if( pCSh
->IsTableMode() )
64 const SwCellFrame
*pCFrame
=
65 static_cast< const SwCellFrame
* >( GetFrame() );
67 const_cast< SwTableBox
*>( pCFrame
->GetTabBox() );
68 SwSelBoxes
const& rBoxes(pCSh
->GetTableCursor()->GetSelectedBoxes());
69 bRet
= rBoxes
.find(pBox
) != rBoxes
.end();
76 void SwAccessibleCell::GetStates( sal_Int64
& rStateSet
)
78 SwAccessibleContext::GetStates( rStateSet
);
81 const SwViewShell
*pVSh
= GetMap()->GetShell();
83 if( dynamic_cast<const SwCursorShell
*>( pVSh
) != nullptr )
84 rStateSet
|= AccessibleStateType::SELECTABLE
;
85 //Add resizable state to table cell.
86 rStateSet
|= AccessibleStateType::RESIZABLE
;
88 if (IsDisposing()) // tdf#135098
94 rStateSet
|= AccessibleStateType::SELECTED
;
95 SAL_WARN_IF(!m_bIsSelected
, "sw.a11y", "bSelected out of sync");
96 ::rtl::Reference
< SwAccessibleContext
> xThis( this );
97 GetMap()->SetCursorContext( xThis
);
101 SwAccessibleCell::SwAccessibleCell(std::shared_ptr
<SwAccessibleMap
> const& pInitMap
,
102 const SwCellFrame
*pCellFrame
)
103 : SwAccessibleContext( pInitMap
, AccessibleRole::TABLE_CELL
, pCellFrame
)
104 , m_aSelectionHelper( *this )
105 , m_bIsSelected( false )
107 OUString
sBoxName( pCellFrame
->GetTabBox()->GetName() );
110 m_bIsSelected
= IsSelected();
112 css::uno::Reference
<css::accessibility::XAccessible
> xTableReference(
113 getAccessibleParentImpl());
114 css::uno::Reference
<css::accessibility::XAccessibleContext
> xContextTable(
115 xTableReference
, css::uno::UNO_QUERY
);
118 || xContextTable
->getAccessibleRole() != AccessibleRole::TABLE
),
119 "sw.a11y", "bad accessible context");
120 m_pAccTable
= static_cast<SwAccessibleTable
*>(xTableReference
.get());
123 bool SwAccessibleCell::InvalidateMyCursorPos()
125 bool bNew
= IsSelected();
128 std::scoped_lock
aGuard( m_Mutex
);
129 bOld
= m_bIsSelected
;
130 m_bIsSelected
= bNew
;
134 // remember that object as the one that has the caret. This is
135 // necessary to notify that object if the cursor leaves it.
136 ::rtl::Reference
< SwAccessibleContext
> xThis( this );
137 GetMap()->SetCursorContext( xThis
);
140 bool bChanged
= bOld
!= bNew
;
143 FireStateChangedEvent( AccessibleStateType::SELECTED
, bNew
);
144 if (m_pAccTable
.is())
146 m_pAccTable
->AddSelectionCell(this,bNew
);
152 bool SwAccessibleCell::InvalidateChildrenCursorPos( const SwFrame
*pFrame
)
154 bool bChanged
= false;
156 const SwAccessibleChildSList
aVisList( GetVisArea(), *pFrame
, *GetMap() );
157 SwAccessibleChildSList::const_iterator
aIter( aVisList
.begin() );
158 while( aIter
!= aVisList
.end() )
160 const SwAccessibleChild
& rLower
= *aIter
;
161 const SwFrame
*pLower
= rLower
.GetSwFrame();
164 if( rLower
.IsAccessible( GetMap()->GetShell()->IsPreview() ) )
166 ::rtl::Reference
< SwAccessibleContext
> xAccImpl(
167 GetMap()->GetContextImpl( pLower
, false ) );
170 assert(xAccImpl
->GetFrame()->IsCellFrame());
171 bChanged
= static_cast< SwAccessibleCell
*>(
172 xAccImpl
.get() )->InvalidateMyCursorPos();
175 bChanged
= true; // If the context is not know we
176 // don't know whether the selection
181 // This is a box with sub rows.
182 bChanged
|= InvalidateChildrenCursorPos( pLower
);
191 void SwAccessibleCell::InvalidateCursorPos_()
195 const SwAccessibleChild
aChild( GetChild( *(GetMap()), 0 ) );
196 if( aChild
.IsValid() && aChild
.GetSwFrame() )
198 ::rtl::Reference
< SwAccessibleContext
> xChildImpl( GetMap()->GetContextImpl( aChild
.GetSwFrame()) );
201 AccessibleEventObject aEvent
;
202 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
203 aEvent
.NewValue
<<= AccessibleStateType::FOCUSED
;
204 xChildImpl
->FireAccessibleEvent( aEvent
);
209 const SwFrame
*pParent
= GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
210 assert(pParent
->IsTabFrame());
211 const SwTabFrame
*pTabFrame
= static_cast< const SwTabFrame
* >( pParent
);
212 if( pTabFrame
->IsFollow() )
213 pTabFrame
= pTabFrame
->FindMaster();
217 InvalidateChildrenCursorPos( pTabFrame
);
218 pTabFrame
= pTabFrame
->GetFollow();
220 if (m_pAccTable
.is())
222 m_pAccTable
->FireSelectionEvent();
226 bool SwAccessibleCell::HasCursor()
228 std::scoped_lock
aGuard( m_Mutex
);
229 return m_bIsSelected
;
232 SwAccessibleCell::~SwAccessibleCell()
236 OUString SAL_CALL
SwAccessibleCell::getAccessibleDescription()
241 OUString SAL_CALL
SwAccessibleCell::getImplementationName()
243 return sImplementationName
;
246 sal_Bool SAL_CALL
SwAccessibleCell::supportsService(const OUString
& sTestServiceName
)
248 return cppu::supportsService(this, sTestServiceName
);
251 uno::Sequence
< OUString
> SAL_CALL
SwAccessibleCell::getSupportedServiceNames()
253 return { "com.sun.star.table.AccessibleCellView", sAccessibleServiceName
};
256 void SwAccessibleCell::Dispose(bool bRecursive
, bool bCanSkipInvisible
)
258 const SwFrame
*pParent
= GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
259 ::rtl::Reference
< SwAccessibleContext
> xAccImpl(
260 GetMap()->GetContextImpl( pParent
, false ) );
262 xAccImpl
->DisposeChild(SwAccessibleChild(GetFrame()), bRecursive
, bCanSkipInvisible
);
263 SwAccessibleContext::Dispose( bRecursive
);
266 void SwAccessibleCell::InvalidatePosOrSize( const SwRect
& rOldBox
)
268 const SwFrame
*pParent
= GetParent( SwAccessibleChild(GetFrame()), IsInPagePreview() );
269 ::rtl::Reference
< SwAccessibleContext
> xAccImpl(
270 GetMap()->GetContextImpl( pParent
, false ) );
272 xAccImpl
->InvalidateChildPosOrSize( SwAccessibleChild(GetFrame()), rOldBox
);
273 SwAccessibleContext::InvalidatePosOrSize( rOldBox
);
276 // XAccessibleInterface
278 uno::Any
SwAccessibleCell::queryInterface( const uno::Type
& rType
)
280 if (rType
== cppu::UnoType
<XAccessibleExtendedAttributes
>::get())
283 aR
<<= uno::Reference
<XAccessibleExtendedAttributes
>(this);
287 if (rType
== cppu::UnoType
<XAccessibleSelection
>::get())
290 aR
<<= uno::Reference
<XAccessibleSelection
>(this);
293 if ( rType
== ::cppu::UnoType
<XAccessibleValue
>::get() )
295 uno::Reference
<XAccessibleValue
> xValue
= this;
302 return SwAccessibleContext::queryInterface( rType
);
307 uno::Sequence
< uno::Type
> SAL_CALL
SwAccessibleCell::getTypes()
309 return cppu::OTypeCollection(
310 ::cppu::UnoType
<XAccessibleValue
>::get(),
311 SwAccessibleContext::getTypes() ).getTypes();
314 uno::Sequence
< sal_Int8
> SAL_CALL
SwAccessibleCell::getImplementationId()
316 return css::uno::Sequence
<sal_Int8
>();
321 SwFrameFormat
* SwAccessibleCell::GetTableBoxFormat() const
324 assert(GetFrame()->IsCellFrame());
326 const SwCellFrame
* pCellFrame
= static_cast<const SwCellFrame
*>( GetFrame() );
327 return pCellFrame
->GetTabBox()->GetFrameFormat();
330 //Implement TableCell currentValue
331 uno::Any
SwAccessibleCell::getCurrentValue( )
333 SolarMutexGuard aGuard
;
337 return uno::Any( GetTableBoxFormat()->GetTableBoxValue().GetValue() );
340 sal_Bool
SwAccessibleCell::setCurrentValue( const uno::Any
& aNumber
)
342 SolarMutexGuard aGuard
;
347 bool bValid
= (aNumber
>>= fValue
);
350 SwTableBoxValue
aValue( fValue
);
351 GetTableBoxFormat()->SetFormatAttr( aValue
);
356 uno::Any
SwAccessibleCell::getMaximumValue( )
358 return uno::Any(DBL_MAX
);
361 uno::Any
SwAccessibleCell::getMinimumValue( )
363 return uno::Any(-DBL_MAX
);
366 uno::Any
SwAccessibleCell::getMinimumIncrement( )
371 css::uno::Any SAL_CALL
SwAccessibleCell::getExtendedAttributes()
375 css::uno::Any strRet
;
376 SwFrameFormat
*pFrameFormat
= GetTableBoxFormat();
377 assert(pFrameFormat
);
379 const SwTableBoxFormula
& tbl_formula
= pFrameFormat
->GetTableBoxFormula();
381 OUString strFormula
= tbl_formula
.GetFormula()
382 .replaceAll(u
"\\", u
"\\\\")
383 .replaceAll(u
";", u
"\\;")
384 .replaceAll(u
"=", u
"\\=")
385 .replaceAll(u
",", u
"\\,")
386 .replaceAll(u
":", u
"\\:");
387 OUString strFor
= "Formula:" + strFormula
+ ";";
393 sal_Int32 SAL_CALL
SwAccessibleCell::getBackground()
397 const SvxBrushItem
&rBack
= GetFrame()->GetAttrSet()->GetBackground();
398 Color crBack
= rBack
.GetColor();
400 if (COL_AUTO
== crBack
)
402 uno::Reference
<XAccessible
> xAccDoc
= getAccessibleParent();
405 uno::Reference
<XAccessibleComponent
> xComponentDoc(xAccDoc
, uno::UNO_QUERY
);
406 if (xComponentDoc
.is())
408 crBack
= Color(ColorTransparency
, xComponentDoc
->getBackground());
412 return sal_Int32(crBack
);
415 // XAccessibleSelection
416 void SwAccessibleCell::selectAccessibleChild(
417 sal_Int64 nChildIndex
)
419 m_aSelectionHelper
.selectAccessibleChild(nChildIndex
);
422 sal_Bool
SwAccessibleCell::isAccessibleChildSelected(
423 sal_Int64 nChildIndex
)
425 return m_aSelectionHelper
.isAccessibleChildSelected(nChildIndex
);
428 void SwAccessibleCell::clearAccessibleSelection( )
432 void SwAccessibleCell::selectAllAccessibleChildren( )
434 m_aSelectionHelper
.selectAllAccessibleChildren();
437 sal_Int64
SwAccessibleCell::getSelectedAccessibleChildCount( )
439 return m_aSelectionHelper
.getSelectedAccessibleChildCount();
442 uno::Reference
<XAccessible
> SwAccessibleCell::getSelectedAccessibleChild(
443 sal_Int64 nSelectedChildIndex
)
445 return m_aSelectionHelper
.getSelectedAccessibleChild(nSelectedChildIndex
);
448 void SwAccessibleCell::deselectAccessibleChild(
449 sal_Int64 nSelectedChildIndex
)
451 m_aSelectionHelper
.deselectAccessibleChild(nSelectedChildIndex
);
454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */