LibreOffice Module svx (master) 1
svxrectctaccessiblecontext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
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>
38
39using namespace ::cppu;
40using namespace ::osl;
41using namespace ::com::sun::star;
42using namespace ::com::sun::star::uno;
43using namespace ::com::sun::star::accessibility;
44
45using namespace ::com::sun::star::lang;
46
47#define MAX_NUM_OF_CHILDREN 9
48#define NOCHILDSELECTED -1
49
50// internal
51namespace
52{
53 struct ChildIndexToPointData
54 {
55 TranslateId pResIdName;
56 TranslateId pResIdDescr;
57 RectPoint ePoint;
58 };
59}
60
61
62static const ChildIndexToPointData* IndexToPoint( tools::Long nIndex )
63{
64 DBG_ASSERT( nIndex < 9 && nIndex >= 0, "-IndexToPoint(): invalid child index! You have been warned..." );
65
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
78 };
79
80 return pCornerData + nIndex;
81}
82
83
85{
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!" );
91
92 nRet = static_cast<tools::Long>(ePoint);
93
94 return nRet;
95}
96
98 : mpRepr(pRepr)
99 , mnSelectedChild(NOCHILDSELECTED)
100{
101 {
102 ::SolarMutexGuard aSolarGuard;
103 msName = SvxResId( RID_SVXSTR_RECTCTL_ACC_CORN_NAME );
104 msDescription = SvxResId( RID_SVXSTR_RECTCTL_ACC_CORN_DESCR );
105 }
106
108}
109
111{
112 ensureDisposed();
113}
114
115Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleAtPoint( const awt::Point& rPoint )
116{
117 ::osl::MutexGuard aGuard( m_aMutex );
118
119 Reference< XAccessible > xRet;
120
122
123 if (nChild != NOCHILDSELECTED)
124 xRet = getAccessibleChild( nChild );
125
126 return xRet;
127}
128
129// XAccessibleContext
131{
133}
134
135Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleChild( sal_Int64 nIndex )
136{
138
139 Reference< XAccessible > xChild(mvChildren[ nIndex ]);
140 if( !xChild.is() )
141 {
142 ::SolarMutexGuard aSolarGuard;
143
144 ::osl::MutexGuard aGuard( m_aMutex );
145
146 xChild = mvChildren[ nIndex ].get();
147
148 if (!xChild.is() && mpRepr)
149 {
150 const ChildIndexToPointData* p = IndexToPoint( nIndex );
151 OUString aName(SvxResId(p->pResIdName));
152 OUString aDescr(SvxResId(p->pResIdDescr));
153
154 tools::Rectangle aFocusRect( mpRepr->CalculateFocusRectangle( p->ePoint ) );
155
157 aDescr, aFocusRect, nIndex );
158 mvChildren[ nIndex ] = pChild;
159 xChild = pChild;
160
161 // set actual state
162 if( mnSelectedChild == nIndex )
163 pChild->setStateChecked( true );
164 }
165 }
166
167 return xChild;
168}
169
170Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleParent()
171{
172 ::osl::MutexGuard aGuard( m_aMutex );
173 if (mpRepr)
174 return mpRepr->getAccessibleParent();
175 return uno::Reference<css::accessibility::XAccessible>();
176}
177
179{
180 return AccessibleRole::PANEL;
181}
182
184{
185 ::osl::MutexGuard aGuard( m_aMutex );
186 return msDescription + " Please use arrow key to selection.";
187}
188
190{
191 ::osl::MutexGuard aGuard( m_aMutex );
192 return msName;
193}
194
198Reference< XAccessibleRelationSet > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleRelationSet()
199{
200 ::osl::MutexGuard aGuard( m_aMutex );
201 if (mpRepr)
203 return uno::Reference<css::accessibility::XAccessibleRelationSet>();
204}
205
207{
208 ::osl::MutexGuard aGuard( m_aMutex );
209 sal_Int64 nStateSet = 0;
210
211 if (mpRepr)
212 {
213 nStateSet |= AccessibleStateType::ENABLED;
214 nStateSet |= AccessibleStateType::FOCUSABLE;
215 if( mpRepr->HasFocus() )
216 nStateSet |= AccessibleStateType::FOCUSED;
217 nStateSet |= AccessibleStateType::OPAQUE;
218
219 nStateSet |= AccessibleStateType::SHOWING;
220
221 if( mpRepr->IsVisible() )
222 nStateSet |= AccessibleStateType::VISIBLE;
223 }
224 else
225 nStateSet |= AccessibleStateType::DEFUNC;
226
227 return nStateSet;
228}
229
231{
232 ::SolarMutexGuard aSolarGuard;
233 ::osl::MutexGuard aGuard( m_aMutex );
234
235 if (mpRepr)
236 mpRepr->GrabFocus();
237}
238
240{
241 ::SolarMutexGuard aSolarGuard;
242 ::osl::MutexGuard aGuard( m_aMutex );
243
244 //see SvxRectCtl::Paint
246 return sal_Int32(rStyles.GetLabelTextColor());
247}
248
250{
251 ::SolarMutexGuard aSolarGuard;
252 ::osl::MutexGuard aGuard( m_aMutex );
253
254 //see SvxRectCtl::Paint
256 return sal_Int32(rStyles.GetDialogColor());
257}
258
259// XAccessibleSelection
260void SvxRectCtlAccessibleContext::implSelect(sal_Int64 nIndex, bool bSelect)
261{
262 ::SolarMutexGuard aSolarGuard;
263
264 ::osl::MutexGuard aGuard( m_aMutex );
265
267
268 const ChildIndexToPointData* pData = IndexToPoint( nIndex );
269
270 DBG_ASSERT(pData, "SvxRectCtlAccessibleContext::selectAccessibleChild(): this is an impossible state! Or at least should be...");
271
272 if (mpRepr)
273 {
274 if (bSelect)
275 {
276 // this does all what is needed, including the change of the child's state!
277 mpRepr->SetActualRP( pData->ePoint );
278 }
279 else
280 {
281 SAL_WARN( "svx", "SvxRectCtlAccessibleContext::clearAccessibleSelection() is not possible!" );
282 }
283 }
284}
285
287{
288 ::osl::MutexGuard aGuard( m_aMutex );
289
291
292 return nIndex == mnSelectedChild;
293}
294
295// internals
297{
298 if( nIndex < 0 || nIndex >= getAccessibleChildCount() )
299 throw lang::IndexOutOfBoundsException();
300}
301
303{
304 ::osl::MutexGuard aGuard( m_aMutex );
305 tools::Long nNew = PointToIndex( eButton );
306 tools::Long nNumOfChildren = getAccessibleChildCount();
307 if( nNew < nNumOfChildren )
308 {
309 // select new child
310 mnSelectedChild = nNew;
311 if( nNew != NOCHILDSELECTED )
312 {
313 if( mvChildren[ nNew ].is() )
314 mvChildren[ nNew ]->FireFocusEvent();
315 }
316 else
317 {
318 Any aOld;
319 Any aNew;
320 aNew <<= AccessibleStateType::FOCUSED;
321 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
322 }
323 }
324 else
326}
327
329{
330 ::osl::MutexGuard aGuard( m_aMutex );
331 if( nNew == mnSelectedChild )
332 return;
333
334 tools::Long nNumOfChildren = getAccessibleChildCount();
335 if( nNew < nNumOfChildren )
336 { // valid index
338 { // deselect old selected child if one is selected
340 if( pChild )
341 pChild->setStateChecked( false );
342 }
343
344 // select new child
345 mnSelectedChild = nNew;
346
347 if( nNew != NOCHILDSELECTED )
348 {
349 if( mvChildren[ nNew ].is() )
350 mvChildren[ nNew ]->setStateChecked( true );
351 }
352 }
353 else
355}
356
358{
359 // no guard -> is done in next selectChild
360 selectChild(PointToIndex( eButton ));
361}
362
364{
365 ::osl::MutexGuard aGuard(m_aMutex);
366 OAccessibleSelectionHelper::disposing();
367 for (auto & rxChild : mvChildren)
368 {
369 if( rxChild.is() )
370 rxChild->dispose();
371 }
372 mvChildren.clear();
373 mpRepr = nullptr;
374}
375
377{
378 ::SolarMutexGuard aSolarGuard;
379 ::osl::MutexGuard aGuard( m_aMutex );
380
381 awt::Rectangle aRet;
382
383 if (mpRepr)
384 {
385 const Point aOutPos;
386 Size aOutSize(mpRepr->GetOutputSizePixel());
387
388 aRet.X = aOutPos.X();
389 aRet.Y = aOutPos.Y();
390 aRet.Width = aOutSize.Width();
391 aRet.Height = aOutSize.Height();
392 }
393
394 return aRet;
395}
396
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 )
409{
410}
411
413{
414 ensureDisposed();
415}
416
417Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleAtPoint( const awt::Point& /*rPoint*/ )
418{
419 return Reference< XAccessible >();
420}
421
423{
424}
425
427{
428 ::SolarMutexGuard aSolarGuard;
429 ::osl::MutexGuard aGuard( m_aMutex );
430
431 //see SvxRectCtl::Paint
433 return sal_Int32(rStyles.GetLabelTextColor());
434}
435
437{
438 ::SolarMutexGuard aSolarGuard;
439 ::osl::MutexGuard aGuard( m_aMutex );
440
441 //see SvxRectCtl::Paint
443 return sal_Int32(rStyles.GetDialogColor());
444}
445
446// XAccessibleContext
448{
449 return 0;
450}
451
452Reference< XAccessible > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleChild( sal_Int64 /*nIndex*/ )
453{
454 throw lang::IndexOutOfBoundsException();
455}
456
458{
459 return mxParent;
460}
461
463{
464 return AccessibleRole::RADIO_BUTTON;
465}
466
468{
469 ::osl::MutexGuard aGuard( m_aMutex );
470 return msDescription;
471}
472
474{
475 ::osl::MutexGuard aGuard( m_aMutex );
476 return msName;
477}
478
482Reference<XAccessibleRelationSet> SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleRelationSet()
483{
485 if( mxParent.is() )
486 {
487 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { mxParent };
488 pRelationSetHelper->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
489 }
490
491 return pRelationSetHelper;
492}
493
495{
496 ::osl::MutexGuard aGuard( m_aMutex );
497 sal_Int64 nStateSet = 0;
498
499 if (!rBHelper.bDisposed)
500 {
501 if( mbIsChecked )
502 {
503 nStateSet |= AccessibleStateType::CHECKED;
504 }
505
506 nStateSet |= AccessibleStateType::ENABLED;
507 nStateSet |= AccessibleStateType::SENSITIVE;
508 nStateSet |= AccessibleStateType::OPAQUE;
509 nStateSet |= AccessibleStateType::SELECTABLE;
510 nStateSet |= AccessibleStateType::SHOWING;
511 nStateSet |= AccessibleStateType::VISIBLE;
512 }
513 else
514 nStateSet |= AccessibleStateType::DEFUNC;
515
516 return nStateSet;
517}
518
519// XAccessibleValue
521{
522 Any aRet;
523 aRet <<= ( mbIsChecked? 1.0 : 0.0 );
524 return aRet;
525}
526
528{
529 return false;
530}
531
533{
534 Any aRet;
535 aRet <<= 1.0;
536 return aRet;
537}
538
540{
541 Any aRet;
542 aRet <<= 0.0;
543 return aRet;
544}
545
547{
548 Any aRet;
549 aRet <<= 1.0;
550 return aRet;
551}
552
553
554// XAccessibleAction
555
556
558{
559 return 1;
560}
561
562
564{
565 ::osl::MutexGuard aGuard( m_aMutex );
566
567 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
568 throw IndexOutOfBoundsException();
569
570 Reference<XAccessibleSelection> xSelection( mxParent, UNO_QUERY);
571
572 xSelection->selectAccessibleChild(mnIndexInParent);
573
574 return true;
575}
576
577
579{
580 ::osl::MutexGuard aGuard( m_aMutex );
581
582 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
583 throw IndexOutOfBoundsException();
584
585 return "select";
586}
587
588
589Reference< XAccessibleKeyBinding > SvxRectCtlChildAccessibleContext::getAccessibleActionKeyBinding( sal_Int32 nIndex )
590{
591 ::osl::MutexGuard aGuard( m_aMutex );
592
593 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
594 throw IndexOutOfBoundsException();
595
596 return Reference< XAccessibleKeyBinding >();
597}
598
600{
601 OAccessibleComponentHelper::disposing();
602 mxParent.clear();
603}
604
606{
607 // no guard necessary, because no one changes maBoundingBox after creating it
609}
610
612{
613 if( mbIsChecked == bChecked )
614 return;
615
616 mbIsChecked = bChecked;
617
618 Any aOld;
619 Any aNew;
620 Any& rMod = bChecked? aNew : aOld;
621
622 //Send the STATE_CHANGED(Focused) event to accessible
623 rMod <<= AccessibleStateType::FOCUSED;
624 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
625
626 rMod <<= AccessibleStateType::CHECKED;
627
628 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
629}
630
632{
633 Any aOld;
634 Any aNew;
635 aNew <<= AccessibleStateType::FOCUSED;
636 NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOld, aNew);
637}
638
639/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
unotools::WeakReference< AnimationNode > mxParent
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
constexpr tools::Long Y() const
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
const Color & GetLabelTextColor() const
const Color & GetDialogColor() const
virtual css::awt::Rectangle implGetBounds() override
virtual OUString SAL_CALL getAccessibleDescription() override
virtual bool implIsSelected(sal_Int64 nAccessibleChildIndex) override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
virtual sal_Int32 SAL_CALL getForeground() override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
Return empty reference to indicate that the relation set is not supported.
virtual void SAL_CALL disposing() override
void selectChild(RectPoint ePoint)
Selects a new child by point.
virtual void SAL_CALL grabFocus() override
virtual sal_Int16 SAL_CALL getAccessibleRole() override
SvxRectCtlAccessibleContext(SvxRectCtl *pRepresentation)
std::vector< rtl::Reference< SvxRectCtlChildAccessibleContext > > mvChildren
array for all possible children
virtual sal_Int32 SAL_CALL getBackground() override
SvxRectCtl * mpRepr
pointer to internal representation
OUString msDescription
Description of this object.
virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
tools::Long mnSelectedChild
actual selected child
virtual void implSelect(sal_Int64 nAccessibleChildIndex, bool bSelect) override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 nIndex) override
OUString msName
Name of this object.
virtual OUString SAL_CALL getAccessibleName() override
bool mbIsChecked
Indicates, if object is checked.
virtual css::uno::Any SAL_CALL getMaximumValue() override
virtual css::uno::Reference< css::accessibility::XAccessibleKeyBinding > SAL_CALL getAccessibleActionKeyBinding(sal_Int32 nIndex) override
virtual sal_Bool SAL_CALL doAccessibleAction(sal_Int32 nIndex) override
virtual void SAL_CALL grabFocus() override
virtual void SAL_CALL disposing() override
virtual css::uno::Any SAL_CALL getMinimumIncrement() override
tools::Long mnIndexInParent
index of child in parent
virtual OUString SAL_CALL getAccessibleActionDescription(sal_Int32 nIndex) override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
Return empty reference to indicate that the relation set is not supported.
virtual OUString SAL_CALL getAccessibleName() override
css::uno::Reference< css::accessibility::XAccessible > mxParent
Reference to the parent object.
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
virtual OUString SAL_CALL getAccessibleDescription() override
SvxRectCtlChildAccessibleContext(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, OUString aName, OUString aDescription, const tools::Rectangle &rBoundingBox, tools::Long nIndexInParent)
virtual sal_Bool SAL_CALL setCurrentValue(const css::uno::Any &aNumber) override
virtual sal_Int32 SAL_CALL getForeground() override
virtual sal_Int32 SAL_CALL getBackground() override
tools::Rectangle maBoundingBox
Bounding box.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
OUString msDescription
Description of this object.
void setStateChecked(bool bChecked)
Sets the checked status.
virtual sal_Int32 SAL_CALL getAccessibleActionCount() override
virtual css::uno::Any SAL_CALL getCurrentValue() override
virtual css::awt::Rectangle implGetBounds() override
implements the calculation of the bounding rectangle
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 nIndex) override
virtual sal_Int16 SAL_CALL getAccessibleRole() override
virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
virtual css::uno::Any SAL_CALL getMinimumValue() override
a11yrelationset get_accessible_relation_set() const
Definition: dlgctrl.hxx:130
tools::Rectangle CalculateFocusRectangle() const
Definition: dlgctrl.cxx:535
css::uno::Reference< css::accessibility::XAccessible > getAccessibleParent() const
Definition: dlgctrl.hxx:128
RectPoint GetApproxRPFromPixPt(const css::awt::Point &rPixelPoint) const
Definition: dlgctrl.cxx:569
static const sal_uInt8 NO_CHILDREN
Definition: dlgctrl.hxx:123
void SetActualRP(RectPoint eNewRP)
Definition: dlgctrl.cxx:502
Size const & GetOutputSizePixel() const
css::awt::Rectangle AWTRectangle(const ::tools::Rectangle &rVCLRect)
#define DBG_ASSERT(sCon, aError)
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
std::mutex m_aMutex
sal_Int32 nIndex
OUString aName
void * p
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
long Long
RectPoint
Definition: rectenum.hxx:23
#define NOCHILDSELECTED
static const ChildIndexToPointData * IndexToPoint(tools::Long nIndex)
static tools::Long PointToIndex(RectPoint ePoint)
#define MAX_NUM_OF_CHILDREN
OUString msName
unsigned char sal_Bool