Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / accessibility / svxrectctaccessiblecontext.cxx
blob6736cf5a7e5eb8f780e0af43e4749a9c2487517b
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 <svxrectctaccessiblecontext.hxx>
21 #include <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <toolkit/helper/convert.hxx>
26 #include <utility>
27 #include <vcl/svapp.hxx>
28 #include <osl/mutex.hxx>
29 #include <tools/debug.hxx>
30 #include <tools/gen.hxx>
31 #include <sal/log.hxx>
32 #include <vcl/settings.hxx>
33 #include <svx/strings.hrc>
34 #include <svx/dlgctrl.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
37 #include <unotools/accessiblerelationsethelper.hxx>
39 using namespace ::cppu;
40 using namespace ::osl;
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::accessibility;
45 using namespace ::com::sun::star::lang;
47 #define MAX_NUM_OF_CHILDREN 9
48 #define NOCHILDSELECTED -1
50 // internal
51 namespace
53 struct ChildIndexToPointData
55 TranslateId pResIdName;
56 TranslateId pResIdDescr;
57 RectPoint ePoint;
62 static const ChildIndexToPointData* IndexToPoint( tools::Long nIndex )
64 DBG_ASSERT( nIndex < 9 && nIndex >= 0, "-IndexToPoint(): invalid child index! You have been warned..." );
66 // corners are counted from left to right and top to bottom
67 static const ChildIndexToPointData pCornerData[] =
68 { // index
69 { RID_SVXSTR_RECTCTL_ACC_CHLD_LT, RID_SVXSTR_RECTCTL_ACC_CHLD_LT, RectPoint::LT }, // 0
70 { RID_SVXSTR_RECTCTL_ACC_CHLD_MT, RID_SVXSTR_RECTCTL_ACC_CHLD_MT, RectPoint::MT }, // 1
71 { RID_SVXSTR_RECTCTL_ACC_CHLD_RT, RID_SVXSTR_RECTCTL_ACC_CHLD_RT, RectPoint::RT }, // 2
72 { RID_SVXSTR_RECTCTL_ACC_CHLD_LM, RID_SVXSTR_RECTCTL_ACC_CHLD_LM, RectPoint::LM }, // 3
73 { RID_SVXSTR_RECTCTL_ACC_CHLD_MM, RID_SVXSTR_RECTCTL_ACC_CHLD_MM, RectPoint::MM }, // 4
74 { RID_SVXSTR_RECTCTL_ACC_CHLD_RM, RID_SVXSTR_RECTCTL_ACC_CHLD_RM, RectPoint::RM }, // 5
75 { RID_SVXSTR_RECTCTL_ACC_CHLD_LB, RID_SVXSTR_RECTCTL_ACC_CHLD_LB, RectPoint::LB }, // 6
76 { RID_SVXSTR_RECTCTL_ACC_CHLD_MB, RID_SVXSTR_RECTCTL_ACC_CHLD_MB, RectPoint::MB }, // 7
77 { RID_SVXSTR_RECTCTL_ACC_CHLD_RB, RID_SVXSTR_RECTCTL_ACC_CHLD_RB, RectPoint::RB } // 8
80 return pCornerData + nIndex;
84 static tools::Long PointToIndex( RectPoint ePoint )
86 tools::Long nRet( static_cast<tools::Long>(ePoint) );
87 // corner control
88 // corners are counted from left to right and top to bottom
89 DBG_ASSERT( int(RectPoint::LT) == 0 && int(RectPoint::MT) == 1 && int(RectPoint::RT) == 2 && int(RectPoint::LM) == 3 && int(RectPoint::MM) == 4 && int(RectPoint::RM) == 5 &&
90 int(RectPoint::LB) == 6 && int(RectPoint::MB) == 7 && int(RectPoint::RB) == 8, "*PointToIndex(): unexpected enum value!" );
92 nRet = static_cast<tools::Long>(ePoint);
94 return nRet;
97 SvxRectCtlAccessibleContext::SvxRectCtlAccessibleContext(SvxRectCtl* pRepr)
98 : mpRepr(pRepr)
99 , mnSelectedChild(NOCHILDSELECTED)
102 ::SolarMutexGuard aSolarGuard;
103 msName = SvxResId( RID_SVXSTR_RECTCTL_ACC_CORN_NAME );
104 msDescription = SvxResId( RID_SVXSTR_RECTCTL_ACC_CORN_DESCR );
107 mvChildren.resize(MAX_NUM_OF_CHILDREN);
110 SvxRectCtlAccessibleContext::~SvxRectCtlAccessibleContext()
112 ensureDisposed();
115 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleAtPoint( const awt::Point& rPoint )
117 ::osl::MutexGuard aGuard( m_aMutex );
119 Reference< XAccessible > xRet;
121 tools::Long nChild = mpRepr ? PointToIndex(mpRepr->GetApproxRPFromPixPt(rPoint)) : NOCHILDSELECTED;
123 if (nChild != NOCHILDSELECTED)
124 xRet = getAccessibleChild( nChild );
126 return xRet;
129 // XAccessibleContext
130 sal_Int64 SAL_CALL SvxRectCtlAccessibleContext::getAccessibleChildCount()
132 return SvxRectCtl::NO_CHILDREN;
135 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleChild( sal_Int64 nIndex )
137 checkChildIndex( nIndex );
139 Reference< XAccessible > xChild(mvChildren[ nIndex ]);
140 if( !xChild.is() )
142 ::SolarMutexGuard aSolarGuard;
144 ::osl::MutexGuard aGuard( m_aMutex );
146 xChild = mvChildren[ nIndex ].get();
148 if (!xChild.is() && mpRepr)
150 const ChildIndexToPointData* p = IndexToPoint( nIndex );
151 OUString aName(SvxResId(p->pResIdName));
152 OUString aDescr(SvxResId(p->pResIdDescr));
154 tools::Rectangle aFocusRect( mpRepr->CalculateFocusRectangle( p->ePoint ) );
156 rtl::Reference<SvxRectCtlChildAccessibleContext> pChild = new SvxRectCtlChildAccessibleContext(this, aName,
157 aDescr, aFocusRect, nIndex );
158 mvChildren[ nIndex ] = pChild;
159 xChild = pChild;
161 // set actual state
162 if( mnSelectedChild == nIndex )
163 pChild->setStateChecked( true );
167 return xChild;
170 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleParent()
172 ::osl::MutexGuard aGuard( m_aMutex );
173 if (mpRepr)
174 return mpRepr->getAccessibleParent();
175 return uno::Reference<css::accessibility::XAccessible>();
178 sal_Int16 SAL_CALL SvxRectCtlAccessibleContext::getAccessibleRole()
180 return AccessibleRole::PANEL;
183 OUString SAL_CALL SvxRectCtlAccessibleContext::getAccessibleDescription()
185 ::osl::MutexGuard aGuard( m_aMutex );
186 return msDescription + " Please use arrow key to selection.";
189 OUString SAL_CALL SvxRectCtlAccessibleContext::getAccessibleName()
191 ::osl::MutexGuard aGuard( m_aMutex );
192 return msName;
195 /** Return empty reference to indicate that the relation set is not
196 supported.
198 Reference< XAccessibleRelationSet > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleRelationSet()
200 ::osl::MutexGuard aGuard( m_aMutex );
201 if (mpRepr)
202 return mpRepr->get_accessible_relation_set();
203 return uno::Reference<css::accessibility::XAccessibleRelationSet>();
206 sal_Int64 SAL_CALL SvxRectCtlAccessibleContext::getAccessibleStateSet()
208 ::osl::MutexGuard aGuard( m_aMutex );
209 sal_Int64 nStateSet = 0;
211 if (mpRepr)
213 nStateSet |= AccessibleStateType::ENABLED;
214 nStateSet |= AccessibleStateType::FOCUSABLE;
215 if( mpRepr->HasFocus() )
216 nStateSet |= AccessibleStateType::FOCUSED;
217 nStateSet |= AccessibleStateType::OPAQUE;
219 nStateSet |= AccessibleStateType::SHOWING;
221 if( mpRepr->IsVisible() )
222 nStateSet |= AccessibleStateType::VISIBLE;
224 else
225 nStateSet |= AccessibleStateType::DEFUNC;
227 return nStateSet;
230 void SAL_CALL SvxRectCtlAccessibleContext::grabFocus()
232 ::SolarMutexGuard aSolarGuard;
233 ::osl::MutexGuard aGuard( m_aMutex );
235 if (mpRepr)
236 mpRepr->GrabFocus();
239 sal_Int32 SvxRectCtlAccessibleContext::getForeground()
241 ::SolarMutexGuard aSolarGuard;
242 ::osl::MutexGuard aGuard( m_aMutex );
244 //see SvxRectCtl::Paint
245 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
246 return sal_Int32(rStyles.GetLabelTextColor());
249 sal_Int32 SvxRectCtlAccessibleContext::getBackground( )
251 ::SolarMutexGuard aSolarGuard;
252 ::osl::MutexGuard aGuard( m_aMutex );
254 //see SvxRectCtl::Paint
255 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
256 return sal_Int32(rStyles.GetDialogColor());
259 // XAccessibleSelection
260 void SvxRectCtlAccessibleContext::implSelect(sal_Int64 nIndex, bool bSelect)
262 ::SolarMutexGuard aSolarGuard;
264 ::osl::MutexGuard aGuard( m_aMutex );
266 checkChildIndex( nIndex );
268 const ChildIndexToPointData* pData = IndexToPoint( nIndex );
270 DBG_ASSERT(pData, "SvxRectCtlAccessibleContext::selectAccessibleChild(): this is an impossible state! Or at least should be...");
272 if (mpRepr)
274 if (bSelect)
276 // this does all what is needed, including the change of the child's state!
277 mpRepr->SetActualRP( pData->ePoint );
279 else
281 SAL_WARN( "svx", "SvxRectCtlAccessibleContext::clearAccessibleSelection() is not possible!" );
286 bool SvxRectCtlAccessibleContext::implIsSelected( sal_Int64 nIndex )
288 ::osl::MutexGuard aGuard( m_aMutex );
290 checkChildIndex( nIndex );
292 return nIndex == mnSelectedChild;
295 // internals
296 void SvxRectCtlAccessibleContext::checkChildIndex( sal_Int64 nIndex )
298 if( nIndex < 0 || nIndex >= getAccessibleChildCount() )
299 throw lang::IndexOutOfBoundsException();
302 void SvxRectCtlAccessibleContext::FireChildFocus( RectPoint eButton )
304 ::osl::MutexGuard aGuard( m_aMutex );
305 tools::Long nNew = PointToIndex( eButton );
306 tools::Long nNumOfChildren = getAccessibleChildCount();
307 if( nNew < nNumOfChildren )
309 // select new child
310 mnSelectedChild = nNew;
311 if( nNew != NOCHILDSELECTED )
313 if( mvChildren[ nNew ].is() )
314 mvChildren[ nNew ]->FireFocusEvent();
316 else
318 Any aOld;
319 Any aNew;
320 aNew <<= AccessibleStateType::FOCUSED;
321 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
324 else
325 mnSelectedChild = NOCHILDSELECTED;
328 void SvxRectCtlAccessibleContext::selectChild( tools::Long nNew )
330 ::osl::MutexGuard aGuard( m_aMutex );
331 if( nNew == mnSelectedChild )
332 return;
334 tools::Long nNumOfChildren = getAccessibleChildCount();
335 if( nNew < nNumOfChildren )
336 { // valid index
337 if( mnSelectedChild != NOCHILDSELECTED )
338 { // deselect old selected child if one is selected
339 SvxRectCtlChildAccessibleContext* pChild = mvChildren[ mnSelectedChild ].get();
340 if( pChild )
341 pChild->setStateChecked( false );
344 // select new child
345 mnSelectedChild = nNew;
347 if( nNew != NOCHILDSELECTED )
349 if( mvChildren[ nNew ].is() )
350 mvChildren[ nNew ]->setStateChecked( true );
353 else
354 mnSelectedChild = NOCHILDSELECTED;
357 void SvxRectCtlAccessibleContext::selectChild(RectPoint eButton )
359 // no guard -> is done in next selectChild
360 selectChild(PointToIndex( eButton ));
363 void SAL_CALL SvxRectCtlAccessibleContext::disposing()
365 ::osl::MutexGuard aGuard(m_aMutex);
366 OAccessibleSelectionHelper::disposing();
367 for (auto & rxChild : mvChildren)
369 if( rxChild.is() )
370 rxChild->dispose();
372 mvChildren.clear();
373 mpRepr = nullptr;
376 awt::Rectangle SvxRectCtlAccessibleContext::implGetBounds()
378 ::SolarMutexGuard aSolarGuard;
379 ::osl::MutexGuard aGuard( m_aMutex );
381 awt::Rectangle aRet;
383 if (mpRepr)
385 const Point aOutPos;
386 Size aOutSize(mpRepr->GetOutputSizePixel());
388 aRet.X = aOutPos.X();
389 aRet.Y = aOutPos.Y();
390 aRet.Width = aOutSize.Width();
391 aRet.Height = aOutSize.Height();
394 return aRet;
397 SvxRectCtlChildAccessibleContext::SvxRectCtlChildAccessibleContext(
398 const Reference<XAccessible>& rxParent,
399 OUString aName,
400 OUString aDescription,
401 const tools::Rectangle& rBoundingBox,
402 tools::Long nIndexInParent )
403 : msDescription(std::move( aDescription ))
404 , msName(std::move( aName ))
405 , mxParent(rxParent)
406 , maBoundingBox( rBoundingBox )
407 , mnIndexInParent( nIndexInParent )
408 , mbIsChecked( false )
412 SvxRectCtlChildAccessibleContext::~SvxRectCtlChildAccessibleContext()
414 ensureDisposed();
417 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleAtPoint( const awt::Point& /*rPoint*/ )
419 return Reference< XAccessible >();
422 void SAL_CALL SvxRectCtlChildAccessibleContext::grabFocus()
426 sal_Int32 SvxRectCtlChildAccessibleContext::getForeground( )
428 ::SolarMutexGuard aSolarGuard;
429 ::osl::MutexGuard aGuard( m_aMutex );
431 //see SvxRectCtl::Paint
432 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
433 return sal_Int32(rStyles.GetLabelTextColor());
436 sal_Int32 SvxRectCtlChildAccessibleContext::getBackground( )
438 ::SolarMutexGuard aSolarGuard;
439 ::osl::MutexGuard aGuard( m_aMutex );
441 //see SvxRectCtl::Paint
442 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
443 return sal_Int32(rStyles.GetDialogColor());
446 // XAccessibleContext
447 sal_Int64 SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleChildCount()
449 return 0;
452 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleChild( sal_Int64 /*nIndex*/ )
454 throw lang::IndexOutOfBoundsException();
457 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleParent()
459 return mxParent;
462 sal_Int16 SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleRole()
464 return AccessibleRole::RADIO_BUTTON;
467 OUString SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleDescription()
469 ::osl::MutexGuard aGuard( m_aMutex );
470 return msDescription;
473 OUString SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleName()
475 ::osl::MutexGuard aGuard( m_aMutex );
476 return msName;
479 /** Return empty reference to indicate that the relation set is not
480 supported.
482 Reference<XAccessibleRelationSet> SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleRelationSet()
484 rtl::Reference<utl::AccessibleRelationSetHelper> pRelationSetHelper = new utl::AccessibleRelationSetHelper;
485 if( mxParent.is() )
487 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { mxParent };
488 pRelationSetHelper->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
491 return pRelationSetHelper;
494 sal_Int64 SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleStateSet()
496 ::osl::MutexGuard aGuard( m_aMutex );
497 sal_Int64 nStateSet = 0;
499 if (!rBHelper.bDisposed)
501 if( mbIsChecked )
503 nStateSet |= AccessibleStateType::CHECKED;
506 nStateSet |= AccessibleStateType::ENABLED;
507 nStateSet |= AccessibleStateType::SENSITIVE;
508 nStateSet |= AccessibleStateType::OPAQUE;
509 nStateSet |= AccessibleStateType::SELECTABLE;
510 nStateSet |= AccessibleStateType::SHOWING;
511 nStateSet |= AccessibleStateType::VISIBLE;
513 else
514 nStateSet |= AccessibleStateType::DEFUNC;
516 return nStateSet;
519 // XAccessibleValue
520 Any SAL_CALL SvxRectCtlChildAccessibleContext::getCurrentValue()
522 Any aRet;
523 aRet <<= ( mbIsChecked? 1.0 : 0.0 );
524 return aRet;
527 sal_Bool SAL_CALL SvxRectCtlChildAccessibleContext::setCurrentValue( const Any& /*aNumber*/ )
529 return false;
532 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMaximumValue()
534 Any aRet;
535 aRet <<= 1.0;
536 return aRet;
539 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMinimumValue()
541 Any aRet;
542 aRet <<= 0.0;
543 return aRet;
546 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMinimumIncrement()
548 Any aRet;
549 aRet <<= 1.0;
550 return aRet;
554 // XAccessibleAction
557 sal_Int32 SvxRectCtlChildAccessibleContext::getAccessibleActionCount( )
559 return 1;
563 sal_Bool SvxRectCtlChildAccessibleContext::doAccessibleAction ( sal_Int32 nIndex )
565 ::osl::MutexGuard aGuard( m_aMutex );
567 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
568 throw IndexOutOfBoundsException();
570 Reference<XAccessibleSelection> xSelection( mxParent, UNO_QUERY);
572 xSelection->selectAccessibleChild(mnIndexInParent);
574 return true;
578 OUString SvxRectCtlChildAccessibleContext::getAccessibleActionDescription ( sal_Int32 nIndex )
580 ::osl::MutexGuard aGuard( m_aMutex );
582 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
583 throw IndexOutOfBoundsException();
585 return "select";
589 Reference< XAccessibleKeyBinding > SvxRectCtlChildAccessibleContext::getAccessibleActionKeyBinding( sal_Int32 nIndex )
591 ::osl::MutexGuard aGuard( m_aMutex );
593 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
594 throw IndexOutOfBoundsException();
596 return Reference< XAccessibleKeyBinding >();
599 void SAL_CALL SvxRectCtlChildAccessibleContext::disposing()
601 OAccessibleComponentHelper::disposing();
602 mxParent.clear();
605 awt::Rectangle SvxRectCtlChildAccessibleContext::implGetBounds( )
607 // no guard necessary, because no one changes maBoundingBox after creating it
608 return AWTRectangle(maBoundingBox);
611 void SvxRectCtlChildAccessibleContext::setStateChecked( bool bChecked )
613 if( mbIsChecked == bChecked )
614 return;
616 mbIsChecked = bChecked;
618 Any aOld;
619 Any aNew;
620 Any& rMod = bChecked? aNew : aOld;
622 //Send the STATE_CHANGED(Focused) event to accessible
623 rMod <<= AccessibleStateType::FOCUSED;
624 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
626 rMod <<= AccessibleStateType::CHECKED;
628 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
631 void SvxRectCtlChildAccessibleContext::FireFocusEvent()
633 Any aOld;
634 Any aNew;
635 aNew <<= AccessibleStateType::FOCUSED;
636 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
639 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */