bump product version to 7.2.5.1
[LibreOffice.git] / svx / source / accessibility / svxrectctaccessiblecontext.cxx
blobf12352f1c5968c2089bd23d49cf878ccdf4028df
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 <unotools/accessiblestatesethelper.hxx>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <toolkit/helper/convert.hxx>
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 const char* pResIdName;
56 const char* 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 IMPLEMENT_FORWARD_XINTERFACE2( SvxRectCtlAccessibleContext, OAccessibleSelectionHelper, OAccessibleHelper_Base )
116 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvxRectCtlAccessibleContext, OAccessibleSelectionHelper, OAccessibleHelper_Base )
118 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleAtPoint( const awt::Point& rPoint )
120 ::osl::MutexGuard aGuard( m_aMutex );
122 Reference< XAccessible > xRet;
124 tools::Long nChild = mpRepr ? PointToIndex(mpRepr->GetApproxRPFromPixPt(rPoint)) : NOCHILDSELECTED;
126 if (nChild != NOCHILDSELECTED)
127 xRet = getAccessibleChild( nChild );
129 return xRet;
132 // XAccessibleContext
133 sal_Int32 SAL_CALL SvxRectCtlAccessibleContext::getAccessibleChildCount()
135 ::osl::MutexGuard aGuard( m_aMutex );
137 return SvxRectCtl::NO_CHILDREN;
140 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleChild( sal_Int32 nIndex )
142 checkChildIndex( nIndex );
144 Reference< XAccessible > xChild(mvChildren[ nIndex ]);
145 if( !xChild.is() )
147 ::SolarMutexGuard aSolarGuard;
149 ::osl::MutexGuard aGuard( m_aMutex );
151 xChild = mvChildren[ nIndex ].get();
153 if (!xChild.is() && mpRepr)
155 const ChildIndexToPointData* p = IndexToPoint( nIndex );
156 OUString aName(SvxResId(p->pResIdName));
157 OUString aDescr(SvxResId(p->pResIdDescr));
159 tools::Rectangle aFocusRect( mpRepr->CalculateFocusRectangle( p->ePoint ) );
161 rtl::Reference<SvxRectCtlChildAccessibleContext> pChild = new SvxRectCtlChildAccessibleContext(this, aName,
162 aDescr, aFocusRect, nIndex );
163 mvChildren[ nIndex ] = pChild;
164 xChild = pChild;
166 // set actual state
167 if( mnSelectedChild == nIndex )
168 pChild->setStateChecked( true );
172 return xChild;
175 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleParent()
177 ::osl::MutexGuard aGuard( m_aMutex );
178 if (mpRepr)
179 return mpRepr->getAccessibleParent();
180 return uno::Reference<css::accessibility::XAccessible>();
183 sal_Int16 SAL_CALL SvxRectCtlAccessibleContext::getAccessibleRole()
185 return AccessibleRole::PANEL;
188 OUString SAL_CALL SvxRectCtlAccessibleContext::getAccessibleDescription()
190 ::osl::MutexGuard aGuard( m_aMutex );
191 return msDescription + " Please use arrow key to selection.";
194 OUString SAL_CALL SvxRectCtlAccessibleContext::getAccessibleName()
196 ::osl::MutexGuard aGuard( m_aMutex );
197 return msName;
200 /** Return empty reference to indicate that the relation set is not
201 supported.
203 Reference< XAccessibleRelationSet > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleRelationSet()
205 ::osl::MutexGuard aGuard( m_aMutex );
206 if (mpRepr)
207 return mpRepr->get_accessible_relation_set();
208 return uno::Reference<css::accessibility::XAccessibleRelationSet>();
211 Reference< XAccessibleStateSet > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleStateSet()
213 ::osl::MutexGuard aGuard( m_aMutex );
214 rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
216 if (mpRepr)
218 pStateSetHelper->AddState( AccessibleStateType::ENABLED );
219 pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
220 if( mpRepr->HasFocus() )
221 pStateSetHelper->AddState( AccessibleStateType::FOCUSED );
222 pStateSetHelper->AddState( AccessibleStateType::OPAQUE );
224 pStateSetHelper->AddState( AccessibleStateType::SHOWING );
226 if( mpRepr->IsVisible() )
227 pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
229 else
230 pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
232 return pStateSetHelper;
235 void SAL_CALL SvxRectCtlAccessibleContext::grabFocus()
237 ::SolarMutexGuard aSolarGuard;
238 ::osl::MutexGuard aGuard( m_aMutex );
240 if (mpRepr)
241 mpRepr->GrabFocus();
244 sal_Int32 SvxRectCtlAccessibleContext::getForeground()
246 ::SolarMutexGuard aSolarGuard;
247 ::osl::MutexGuard aGuard( m_aMutex );
249 //see SvxRectCtl::Paint
250 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
251 return sal_Int32(rStyles.GetLabelTextColor());
254 sal_Int32 SvxRectCtlAccessibleContext::getBackground( )
256 ::SolarMutexGuard aSolarGuard;
257 ::osl::MutexGuard aGuard( m_aMutex );
259 //see SvxRectCtl::Paint
260 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
261 return sal_Int32(rStyles.GetDialogColor());
264 // XAccessibleSelection
265 void SvxRectCtlAccessibleContext::implSelect(sal_Int32 nIndex, bool bSelect)
267 ::SolarMutexGuard aSolarGuard;
269 ::osl::MutexGuard aGuard( m_aMutex );
271 checkChildIndex( nIndex );
273 const ChildIndexToPointData* pData = IndexToPoint( nIndex );
275 DBG_ASSERT(pData, "SvxRectCtlAccessibleContext::selectAccessibleChild(): this is an impossible state! Or at least should be...");
277 if (mpRepr)
279 if (bSelect)
281 // this does all what is needed, including the change of the child's state!
282 mpRepr->SetActualRP( pData->ePoint );
284 else
286 SAL_WARN( "svx", "SvxRectCtlAccessibleContext::clearAccessibleSelection() is not possible!" );
291 bool SvxRectCtlAccessibleContext::implIsSelected( sal_Int32 nIndex )
293 ::osl::MutexGuard aGuard( m_aMutex );
295 checkChildIndex( nIndex );
297 return nIndex == mnSelectedChild;
300 // internals
301 void SvxRectCtlAccessibleContext::checkChildIndex( tools::Long nIndex )
303 if( nIndex < 0 || nIndex >= getAccessibleChildCount() )
304 throw lang::IndexOutOfBoundsException();
307 void SvxRectCtlAccessibleContext::FireChildFocus( RectPoint eButton )
309 ::osl::MutexGuard aGuard( m_aMutex );
310 tools::Long nNew = PointToIndex( eButton );
311 tools::Long nNumOfChildren = getAccessibleChildCount();
312 if( nNew < nNumOfChildren )
314 // select new child
315 mnSelectedChild = nNew;
316 if( nNew != NOCHILDSELECTED )
318 if( mvChildren[ nNew ].is() )
319 mvChildren[ nNew ]->FireFocusEvent();
321 else
323 Any aOld;
324 Any aNew;
325 aNew <<= AccessibleStateType::FOCUSED;
326 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
329 else
330 mnSelectedChild = NOCHILDSELECTED;
333 void SvxRectCtlAccessibleContext::selectChild( tools::Long nNew )
335 ::osl::MutexGuard aGuard( m_aMutex );
336 if( nNew == mnSelectedChild )
337 return;
339 tools::Long nNumOfChildren = getAccessibleChildCount();
340 if( nNew < nNumOfChildren )
341 { // valid index
342 if( mnSelectedChild != NOCHILDSELECTED )
343 { // deselect old selected child if one is selected
344 SvxRectCtlChildAccessibleContext* pChild = mvChildren[ mnSelectedChild ].get();
345 if( pChild )
346 pChild->setStateChecked( false );
349 // select new child
350 mnSelectedChild = nNew;
352 if( nNew != NOCHILDSELECTED )
354 if( mvChildren[ nNew ].is() )
355 mvChildren[ nNew ]->setStateChecked( true );
358 else
359 mnSelectedChild = NOCHILDSELECTED;
362 void SvxRectCtlAccessibleContext::selectChild(RectPoint eButton )
364 // no guard -> is done in next selectChild
365 selectChild(PointToIndex( eButton ));
368 void SAL_CALL SvxRectCtlAccessibleContext::disposing()
370 ::osl::MutexGuard aGuard(m_aMutex);
371 OAccessibleSelectionHelper::disposing();
372 for (auto & rxChild : mvChildren)
374 if( rxChild.is() )
375 rxChild->dispose();
377 mvChildren.clear();
378 mpRepr = nullptr;
381 awt::Rectangle SvxRectCtlAccessibleContext::implGetBounds()
383 ::SolarMutexGuard aSolarGuard;
384 ::osl::MutexGuard aGuard( m_aMutex );
386 awt::Rectangle aRet;
388 if (mpRepr)
390 const Point aOutPos;
391 Size aOutSize(mpRepr->GetOutputSizePixel());
393 aRet.X = aOutPos.X();
394 aRet.Y = aOutPos.Y();
395 aRet.Width = aOutSize.Width();
396 aRet.Height = aOutSize.Height();
399 return aRet;
402 SvxRectCtlChildAccessibleContext::SvxRectCtlChildAccessibleContext(
403 const Reference<XAccessible>& rxParent,
404 const OUString& rName,
405 const OUString& rDescription,
406 const tools::Rectangle& rBoundingBox,
407 tools::Long nIndexInParent )
408 : msDescription( rDescription )
409 , msName( rName )
410 , mxParent(rxParent)
411 , maBoundingBox( rBoundingBox )
412 , mnIndexInParent( nIndexInParent )
413 , mbIsChecked( false )
417 SvxRectCtlChildAccessibleContext::~SvxRectCtlChildAccessibleContext()
419 ensureDisposed();
422 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleAtPoint( const awt::Point& /*rPoint*/ )
424 return Reference< XAccessible >();
427 void SAL_CALL SvxRectCtlChildAccessibleContext::grabFocus()
431 sal_Int32 SvxRectCtlChildAccessibleContext::getForeground( )
433 ::SolarMutexGuard aSolarGuard;
434 ::osl::MutexGuard aGuard( m_aMutex );
436 //see SvxRectCtl::Paint
437 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
438 return sal_Int32(rStyles.GetLabelTextColor());
441 sal_Int32 SvxRectCtlChildAccessibleContext::getBackground( )
443 ::SolarMutexGuard aSolarGuard;
444 ::osl::MutexGuard aGuard( m_aMutex );
446 //see SvxRectCtl::Paint
447 const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings();
448 return sal_Int32(rStyles.GetDialogColor());
451 // XAccessibleContext
452 sal_Int32 SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleChildCount()
454 return 0;
457 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleChild( sal_Int32 /*nIndex*/ )
459 throw lang::IndexOutOfBoundsException();
462 Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleParent()
464 return mxParent;
467 sal_Int16 SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleRole()
469 return AccessibleRole::RADIO_BUTTON;
472 OUString SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleDescription()
474 ::osl::MutexGuard aGuard( m_aMutex );
475 return msDescription;
478 OUString SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleName()
480 ::osl::MutexGuard aGuard( m_aMutex );
481 return msName;
484 /** Return empty reference to indicate that the relation set is not
485 supported.
487 Reference<XAccessibleRelationSet> SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleRelationSet()
489 rtl::Reference<utl::AccessibleRelationSetHelper> pRelationSetHelper = new utl::AccessibleRelationSetHelper;
490 if( mxParent.is() )
492 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { mxParent };
493 pRelationSetHelper->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
496 return pRelationSetHelper;
499 Reference< XAccessibleStateSet > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleStateSet()
501 ::osl::MutexGuard aGuard( m_aMutex );
502 rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
504 if (!rBHelper.bDisposed)
506 if( mbIsChecked )
508 pStateSetHelper->AddState( AccessibleStateType::CHECKED );
511 pStateSetHelper->AddState( AccessibleStateType::ENABLED );
512 pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
513 pStateSetHelper->AddState( AccessibleStateType::OPAQUE );
514 pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
515 pStateSetHelper->AddState( AccessibleStateType::SHOWING );
516 pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
518 else
519 pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
521 return pStateSetHelper;
524 // XAccessibleValue
525 Any SAL_CALL SvxRectCtlChildAccessibleContext::getCurrentValue()
527 Any aRet;
528 aRet <<= ( mbIsChecked? 1.0 : 0.0 );
529 return aRet;
532 sal_Bool SAL_CALL SvxRectCtlChildAccessibleContext::setCurrentValue( const Any& /*aNumber*/ )
534 return false;
537 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMaximumValue()
539 Any aRet;
540 aRet <<= 1.0;
541 return aRet;
544 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMinimumValue()
546 Any aRet;
547 aRet <<= 0.0;
548 return aRet;
552 // XAccessibleAction
555 sal_Int32 SvxRectCtlChildAccessibleContext::getAccessibleActionCount( )
557 return 1;
561 sal_Bool SvxRectCtlChildAccessibleContext::doAccessibleAction ( sal_Int32 nIndex )
563 ::osl::MutexGuard aGuard( m_aMutex );
565 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
566 throw IndexOutOfBoundsException();
568 Reference<XAccessibleSelection> xSelection( mxParent, UNO_QUERY);
570 xSelection->selectAccessibleChild(mnIndexInParent);
572 return true;
576 OUString SvxRectCtlChildAccessibleContext::getAccessibleActionDescription ( sal_Int32 nIndex )
578 ::osl::MutexGuard aGuard( m_aMutex );
580 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
581 throw IndexOutOfBoundsException();
583 return "select";
587 Reference< XAccessibleKeyBinding > SvxRectCtlChildAccessibleContext::getAccessibleActionKeyBinding( sal_Int32 nIndex )
589 ::osl::MutexGuard aGuard( m_aMutex );
591 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
592 throw IndexOutOfBoundsException();
594 return Reference< XAccessibleKeyBinding >();
597 void SAL_CALL SvxRectCtlChildAccessibleContext::disposing()
599 OAccessibleComponentHelper::disposing();
600 mxParent.clear();
603 awt::Rectangle SvxRectCtlChildAccessibleContext::implGetBounds( )
605 // no guard necessary, because no one changes maBoundingBox after creating it
606 return AWTRectangle(maBoundingBox);
609 void SvxRectCtlChildAccessibleContext::setStateChecked( bool bChecked )
611 if( mbIsChecked == bChecked )
612 return;
614 mbIsChecked = bChecked;
616 Any aOld;
617 Any aNew;
618 Any& rMod = bChecked? aNew : aOld;
620 //Send the STATE_CHANGED(Focused) event to accessible
621 rMod <<= AccessibleStateType::FOCUSED;
622 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
624 rMod <<= AccessibleStateType::CHECKED;
626 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
629 void SvxRectCtlChildAccessibleContext::FireFocusEvent()
631 Any aOld;
632 Any aNew;
633 aNew <<= AccessibleStateType::FOCUSED;
634 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
637 IMPLEMENT_FORWARD_XINTERFACE2( SvxRectCtlChildAccessibleContext, OAccessibleComponentHelper, OAccessibleHelper_Base_3 )
638 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SvxRectCtlChildAccessibleContext, OAccessibleComponentHelper, OAccessibleHelper_Base_3 )
640 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */