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 <extended/accessibleiconchoicectrlentry.hxx>
21 #include <vcl/toolkit/ivctrl.hxx>
22 #include <com/sun/star/awt/Rectangle.hpp>
23 #include <com/sun/star/accessibility/AccessibleRole.hpp>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <toolkit/helper/convert.hxx>
29 #include <unotools/accessiblestatesethelper.hxx>
30 #include <unotools/accessiblerelationsethelper.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <svtools/stringtransfer.hxx>
33 #include <comphelper/accessibleeventnotifier.hxx>
34 #include <i18nlangtag/languagetag.hxx>
36 #define ACCESSIBLE_ACTION_COUNT 1
40 /// @throws css::lang::IndexOutOfBoundsException
41 void checkActionIndex_Impl( sal_Int32 _nIndex
)
43 if ( _nIndex
< 0 || _nIndex
>= ACCESSIBLE_ACTION_COUNT
)
45 throw css::lang::IndexOutOfBoundsException();
50 namespace accessibility
54 using namespace ::com::sun::star::accessibility
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::lang
;
57 using namespace ::com::sun::star
;
62 AccessibleIconChoiceCtrlEntry::AccessibleIconChoiceCtrlEntry( SvtIconChoiceCtrl
& _rIconCtrl
,
64 const Reference
< XAccessible
>& _xParent
) :
66 AccessibleIconChoiceCtrlEntry_BASE ( m_aMutex
),
68 m_pIconCtrl ( &_rIconCtrl
),
71 m_xParent ( _xParent
)
74 osl_atomic_increment( &m_refCount
);
76 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
78 xComp
->addEventListener( this );
80 osl_atomic_decrement( &m_refCount
);
83 void AccessibleIconChoiceCtrlEntry::disposing( const css::lang::EventObject
& _rSource
)
85 if ( _rSource
.Source
== m_xParent
)
88 OSL_ENSURE( !m_xParent
.is() && ( m_pIconCtrl
== nullptr ), "" );
92 AccessibleIconChoiceCtrlEntry::~AccessibleIconChoiceCtrlEntry()
96 // increment ref count to prevent double call of Dtor
97 osl_atomic_increment( &m_refCount
);
102 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox_Impl() const
104 tools::Rectangle aRect
;
105 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
107 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
112 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen_Impl() const
114 tools::Rectangle aRect
;
115 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
118 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
119 Point aTopLeft
= aRect
.TopLeft();
120 aTopLeft
+= m_pIconCtrl
->GetWindowExtentsRelative( nullptr ).TopLeft();
121 aRect
= tools::Rectangle( aTopLeft
, aRect
.GetSize() );
127 bool AccessibleIconChoiceCtrlEntry::IsAlive_Impl() const
129 return ( !rBHelper
.bDisposed
&& !rBHelper
.bInDispose
&& m_pIconCtrl
);
132 bool AccessibleIconChoiceCtrlEntry::IsShowing_Impl() const
134 bool bShowing
= false;
135 Reference
< XAccessibleContext
> xParentContext
=
136 m_xParent
.is() ? m_xParent
->getAccessibleContext() : Reference
< XAccessibleContext
>();
137 if( xParentContext
.is() )
139 Reference
< XAccessibleComponent
> xParentComp( xParentContext
, uno::UNO_QUERY
);
140 if( xParentComp
.is() )
141 bShowing
= GetBoundingBox_Impl().Overlaps( VCLRectangle( xParentComp
->getBounds() ) );
147 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox()
149 SolarMutexGuard aSolarGuard
;
150 ::osl::MutexGuard
aGuard( m_aMutex
);
153 return GetBoundingBox_Impl();
156 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen()
158 SolarMutexGuard aSolarGuard
;
159 ::osl::MutexGuard
aGuard( m_aMutex
);
162 return GetBoundingBoxOnScreen_Impl();
165 void AccessibleIconChoiceCtrlEntry::EnsureIsAlive() const
167 if ( !IsAlive_Impl() )
168 throw lang::DisposedException();
171 OUString
AccessibleIconChoiceCtrlEntry::implGetText()
174 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
176 sRet
= pEntry
->GetDisplayText();
180 Locale
AccessibleIconChoiceCtrlEntry::implGetLocale()
182 return Application::GetSettings().GetUILanguageTag().getLocale();
184 void AccessibleIconChoiceCtrlEntry::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
193 Sequence
< sal_Int8
> AccessibleIconChoiceCtrlEntry::getImplementationId()
195 return css::uno::Sequence
<sal_Int8
>();
200 void SAL_CALL
AccessibleIconChoiceCtrlEntry::disposing()
202 ::osl::MutexGuard
aGuard( m_aMutex
);
204 // Send a disposing to all listeners.
207 sal_uInt32 nId
= m_nClientId
;
209 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId
, *this );
212 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
214 xComp
->removeEventListener( this );
216 m_pIconCtrl
= nullptr;
222 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getImplementationName()
224 return "com.sun.star.comp.svtools.AccessibleIconChoiceControlEntry";
227 Sequence
< OUString
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getSupportedServiceNames()
229 return {"com.sun.star.accessibility.AccessibleContext",
230 "com.sun.star.accessibility.AccessibleComponent",
231 "com.sun.star.awt.AccessibleIconChoiceControlEntry"};
234 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::supportsService( const OUString
& _rServiceName
)
236 return cppu::supportsService(this, _rServiceName
);
241 Reference
< XAccessibleContext
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleContext( )
247 // XAccessibleContext
249 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChildCount( )
251 return 0; // no children
254 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChild( sal_Int32
)
256 throw IndexOutOfBoundsException();
259 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleParent( )
261 ::osl::MutexGuard
aGuard( m_aMutex
);
267 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleIndexInParent( )
269 ::osl::MutexGuard
aGuard( m_aMutex
);
274 sal_Int16 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRole( )
276 //return AccessibleRole::LABEL;
277 return AccessibleRole::LIST_ITEM
;
280 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleDescription( )
282 // no description for every item
286 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleName( )
288 ::osl::MutexGuard
aGuard( m_aMutex
);
291 return implGetText();
294 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRelationSet( )
296 return new utl::AccessibleRelationSetHelper
;
299 Reference
< XAccessibleStateSet
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleStateSet( )
301 SolarMutexGuard aSolarGuard
;
302 ::osl::MutexGuard
aGuard( m_aMutex
);
304 rtl::Reference
<utl::AccessibleStateSetHelper
> pStateSetHelper
= new utl::AccessibleStateSetHelper
;
306 if ( IsAlive_Impl() )
308 pStateSetHelper
->AddState( AccessibleStateType::TRANSIENT
);
309 pStateSetHelper
->AddState( AccessibleStateType::SELECTABLE
);
310 pStateSetHelper
->AddState( AccessibleStateType::ENABLED
);
311 pStateSetHelper
->AddState( AccessibleStateType::SENSITIVE
);
312 if ( IsShowing_Impl() )
314 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
315 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
318 if ( m_pIconCtrl
&& m_pIconCtrl
->GetCursor() == m_pIconCtrl
->GetEntry( m_nIndex
) )
319 pStateSetHelper
->AddState( AccessibleStateType::SELECTED
);
322 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
324 return pStateSetHelper
;
327 Locale SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocale( )
329 SolarMutexGuard aSolarGuard
;
330 ::osl::MutexGuard
aGuard( m_aMutex
);
332 return implGetLocale();
335 // XAccessibleComponent
337 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::containsPoint( const awt::Point
& rPoint
)
339 return tools::Rectangle( Point(), GetBoundingBox().GetSize() ).Contains( VCLPoint( rPoint
) );
342 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleAtPoint( const awt::Point
& )
344 return Reference
< XAccessible
>();
347 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getBounds( )
349 return AWTRectangle( GetBoundingBox() );
352 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocation( )
354 return AWTPoint( GetBoundingBox().TopLeft() );
357 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocationOnScreen( )
359 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
362 awt::Size SAL_CALL
AccessibleIconChoiceCtrlEntry::getSize( )
364 return AWTSize( GetBoundingBox().GetSize() );
367 void SAL_CALL
AccessibleIconChoiceCtrlEntry::grabFocus( )
369 // do nothing, because no focus for each item
372 sal_Int32
AccessibleIconChoiceCtrlEntry::getForeground( )
374 SolarMutexGuard aSolarGuard
;
375 ::osl::MutexGuard
aGuard( m_aMutex
);
377 sal_Int32 nColor
= 0;
378 Reference
< XAccessible
> xParent
= getAccessibleParent();
381 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
382 if ( xParentComp
.is() )
383 nColor
= xParentComp
->getForeground();
389 sal_Int32
AccessibleIconChoiceCtrlEntry::getBackground( )
391 SolarMutexGuard aSolarGuard
;
392 ::osl::MutexGuard
aGuard( m_aMutex
);
394 sal_Int32 nColor
= 0;
395 Reference
< XAccessible
> xParent
= getAccessibleParent();
398 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
399 if ( xParentComp
.is() )
400 nColor
= xParentComp
->getBackground();
409 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterBounds( sal_Int32 _nIndex
)
411 SolarMutexGuard aSolarGuard
;
412 ::osl::MutexGuard
aGuard( m_aMutex
);
414 if ( ( 0 > _nIndex
) || ( implGetText().getLength() <= _nIndex
) )
415 throw IndexOutOfBoundsException();
417 awt::Rectangle
aBounds( 0, 0, 0, 0 );
420 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
421 tools::Rectangle aCharRect
= m_pIconCtrl
->GetEntryCharacterBounds( m_nIndex
, _nIndex
);
422 aCharRect
.Move( -aItemRect
.Left(), -aItemRect
.Top() );
423 aBounds
= AWTRectangle( aCharRect
);
429 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getIndexAtPoint( const awt::Point
& aPoint
)
431 SolarMutexGuard aSolarGuard
;
432 ::osl::MutexGuard
aGuard( m_aMutex
);
434 sal_Int32 nIndex
= -1;
437 vcl::ControlLayoutData aLayoutData
;
438 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
439 m_pIconCtrl
->RecordLayoutData( &aLayoutData
, aItemRect
);
440 Point
aPnt( VCLPoint( aPoint
) );
441 aPnt
+= aItemRect
.TopLeft();
442 nIndex
= aLayoutData
.GetIndexForPoint( aPnt
);
444 tools::Long nLen
= aLayoutData
.m_aUnicodeBoundRects
.size();
445 for ( tools::Long i
= 0; i
< nLen
; ++i
)
447 tools::Rectangle aRect
= aLayoutData
.GetCharacterBounds(i
);
448 bool bInside
= aRect
.Contains( aPnt
);
458 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
460 SolarMutexGuard aSolarGuard
;
461 ::osl::MutexGuard
aGuard( m_aMutex
);
464 OUString sText
= implGetText();
465 if ( ( 0 > nStartIndex
) || ( sText
.getLength() <= nStartIndex
)
466 || ( 0 > nEndIndex
) || ( sText
.getLength() <= nEndIndex
) )
467 throw IndexOutOfBoundsException();
469 sal_Int32 nLen
= nEndIndex
- nStartIndex
+ 1;
470 ::svt::OStringTransfer::CopyString( sText
.copy( nStartIndex
, nLen
), m_pIconCtrl
);
475 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::scrollSubstringTo( sal_Int32
, sal_Int32
, AccessibleScrollType
)
480 // XAccessibleEventBroadcaster
482 void SAL_CALL
AccessibleIconChoiceCtrlEntry::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
486 ::osl::MutexGuard
aGuard( m_aMutex
);
488 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
489 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, xListener
);
493 void SAL_CALL
AccessibleIconChoiceCtrlEntry::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
498 ::osl::MutexGuard
aGuard( m_aMutex
);
500 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, xListener
);
501 if ( !nListenerCount
)
503 // no listeners anymore
504 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
505 // and at least to us not firing any events anymore, in case somebody calls
506 // NotifyAccessibleEvent, again
507 sal_Int32 nId
= m_nClientId
;
509 comphelper::AccessibleEventNotifier::revokeClient( nId
);
513 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCaretPosition( )
517 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setCaretPosition ( sal_Int32 nIndex
)
519 SolarMutexGuard aSolarGuard
;
520 ::osl::MutexGuard
aGuard( m_aMutex
);
523 if ( !implIsValidRange( nIndex
, nIndex
, implGetText().getLength() ) )
524 throw IndexOutOfBoundsException();
528 sal_Unicode SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacter( sal_Int32 nIndex
)
530 SolarMutexGuard aSolarGuard
;
531 ::osl::MutexGuard
aGuard( m_aMutex
);
533 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex
);
535 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterAttributes( sal_Int32 nIndex
, const css::uno::Sequence
< OUString
>& )
537 SolarMutexGuard aSolarGuard
;
538 ::osl::MutexGuard
aGuard( m_aMutex
);
541 OUString
sText( implGetText() );
543 if ( !implIsValidIndex( nIndex
, sText
.getLength() ) )
544 throw IndexOutOfBoundsException();
546 return css::uno::Sequence
< css::beans::PropertyValue
>();
548 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterCount( )
550 SolarMutexGuard aSolarGuard
;
551 ::osl::MutexGuard
aGuard( m_aMutex
);
553 return implGetText().getLength();
556 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectedText( )
558 SolarMutexGuard aSolarGuard
;
559 ::osl::MutexGuard
aGuard( m_aMutex
);
563 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionStart( )
565 SolarMutexGuard aSolarGuard
;
566 ::osl::MutexGuard
aGuard( m_aMutex
);
570 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionEnd( )
572 SolarMutexGuard aSolarGuard
;
573 ::osl::MutexGuard
aGuard( m_aMutex
);
577 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
579 SolarMutexGuard aSolarGuard
;
580 ::osl::MutexGuard
aGuard( m_aMutex
);
583 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
584 throw IndexOutOfBoundsException();
588 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getText( )
590 SolarMutexGuard aSolarGuard
;
591 ::osl::MutexGuard
aGuard( m_aMutex
);
593 return implGetText( );
595 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
597 SolarMutexGuard aSolarGuard
;
598 ::osl::MutexGuard
aGuard( m_aMutex
);
600 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex
, nEndIndex
);
602 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
604 SolarMutexGuard aSolarGuard
;
605 ::osl::MutexGuard
aGuard( m_aMutex
);
607 return OCommonAccessibleText::getTextAtIndex( nIndex
,aTextType
);
609 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
611 SolarMutexGuard aSolarGuard
;
612 ::osl::MutexGuard
aGuard( m_aMutex
);
614 return OCommonAccessibleText::getTextBeforeIndex( nIndex
,aTextType
);
616 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
618 SolarMutexGuard aSolarGuard
;
619 ::osl::MutexGuard
aGuard( m_aMutex
);
622 return OCommonAccessibleText::getTextBehindIndex( nIndex
,aTextType
);
628 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionCount( )
630 ::osl::MutexGuard
aGuard( m_aMutex
);
632 // three actions supported
633 return ACCESSIBLE_ACTION_COUNT
;
636 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::doAccessibleAction( sal_Int32 nIndex
)
638 SolarMutexGuard aSolarGuard
;
639 ::osl::MutexGuard
aGuard( m_aMutex
);
642 checkActionIndex_Impl( nIndex
);
645 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
646 if ( pEntry
&& !pEntry
->IsSelected() )
648 m_pIconCtrl
->SetNoSelection();
649 m_pIconCtrl
->SetCursor( pEntry
);
656 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionDescription( sal_Int32 nIndex
)
658 SolarMutexGuard aSolarGuard
;
659 ::osl::MutexGuard
aGuard( m_aMutex
);
661 checkActionIndex_Impl( nIndex
);
667 Reference
< XAccessibleKeyBinding
> AccessibleIconChoiceCtrlEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex
)
669 ::osl::MutexGuard
aGuard( m_aMutex
);
671 Reference
< XAccessibleKeyBinding
> xRet
;
672 checkActionIndex_Impl( nIndex
);
677 }// namespace accessibility
680 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */