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 <svtools/ivctrl.hxx>
22 #include <com/sun/star/awt/Point.hpp>
23 #include <com/sun/star/awt/Rectangle.hpp>
24 #include <com/sun/star/awt/Size.hpp>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
29 #include <vcl/svapp.hxx>
30 #include <vcl/controllayout.hxx>
31 #include <vcl/settings.hxx>
32 #include <toolkit/awt/vclxwindow.hxx>
33 #include <toolkit/helper/convert.hxx>
34 #include <unotools/accessiblestatesethelper.hxx>
35 #include <unotools/accessiblerelationsethelper.hxx>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <cppuhelper/typeprovider.hxx>
38 #include <svtools/stringtransfer.hxx>
39 #include <comphelper/accessibleeventnotifier.hxx>
41 #define ACCESSIBLE_ACTION_COUNT 1
45 /// @throws css::lang::IndexOutOfBoundsException
46 void checkActionIndex_Impl( sal_Int32 _nIndex
)
48 if ( _nIndex
< 0 || _nIndex
>= ACCESSIBLE_ACTION_COUNT
)
50 throw css::lang::IndexOutOfBoundsException();
55 namespace accessibility
58 // class AccessibleIconChoiceCtrlEntry
60 using namespace ::com::sun::star::accessibility
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::lang
;
63 using namespace ::com::sun::star
;
68 AccessibleIconChoiceCtrlEntry::AccessibleIconChoiceCtrlEntry( SvtIconChoiceCtrl
& _rIconCtrl
,
70 const Reference
< XAccessible
>& _xParent
) :
72 AccessibleIconChoiceCtrlEntry_BASE ( m_aMutex
),
74 m_pIconCtrl ( &_rIconCtrl
),
77 m_xParent ( _xParent
)
80 osl_atomic_increment( &m_refCount
);
82 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
84 xComp
->addEventListener( this );
86 osl_atomic_decrement( &m_refCount
);
89 void AccessibleIconChoiceCtrlEntry::disposing( const css::lang::EventObject
& _rSource
)
91 if ( _rSource
.Source
== m_xParent
)
94 OSL_ENSURE( !m_xParent
.is() && ( m_pIconCtrl
== nullptr ), "" );
98 AccessibleIconChoiceCtrlEntry::~AccessibleIconChoiceCtrlEntry()
100 if ( IsAlive_Impl() )
102 // increment ref count to prevent double call of Dtor
103 osl_atomic_increment( &m_refCount
);
108 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox_Impl() const
110 tools::Rectangle aRect
;
111 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
113 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
118 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen_Impl() const
120 tools::Rectangle aRect
;
121 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
124 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
125 Point aTopLeft
= aRect
.TopLeft();
126 aTopLeft
+= m_pIconCtrl
->GetWindowExtentsRelative( nullptr ).TopLeft();
127 aRect
= tools::Rectangle( aTopLeft
, aRect
.GetSize() );
133 bool AccessibleIconChoiceCtrlEntry::IsAlive_Impl() const
135 return ( !rBHelper
.bDisposed
&& !rBHelper
.bInDispose
&& m_pIconCtrl
);
138 bool AccessibleIconChoiceCtrlEntry::IsShowing_Impl() const
140 bool bShowing
= false;
141 Reference
< XAccessibleContext
> xParentContext
=
142 m_xParent
.is() ? m_xParent
->getAccessibleContext() : Reference
< XAccessibleContext
>();
143 if( xParentContext
.is() )
145 Reference
< XAccessibleComponent
> xParentComp( xParentContext
, uno::UNO_QUERY
);
146 if( xParentComp
.is() )
147 bShowing
= GetBoundingBox_Impl().IsOver( VCLRectangle( xParentComp
->getBounds() ) );
153 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox()
155 SolarMutexGuard aSolarGuard
;
156 ::osl::MutexGuard
aGuard( m_aMutex
);
159 return GetBoundingBox_Impl();
162 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen()
164 SolarMutexGuard aSolarGuard
;
165 ::osl::MutexGuard
aGuard( m_aMutex
);
168 return GetBoundingBoxOnScreen_Impl();
171 void AccessibleIconChoiceCtrlEntry::EnsureIsAlive() const
173 if ( !IsAlive_Impl() )
174 throw lang::DisposedException();
177 OUString
AccessibleIconChoiceCtrlEntry::implGetText()
180 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
182 sRet
= pEntry
->GetDisplayText();
186 Locale
AccessibleIconChoiceCtrlEntry::implGetLocale()
189 aLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
193 void AccessibleIconChoiceCtrlEntry::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
202 Sequence
< sal_Int8
> AccessibleIconChoiceCtrlEntry::getImplementationId()
204 return css::uno::Sequence
<sal_Int8
>();
209 void SAL_CALL
AccessibleIconChoiceCtrlEntry::disposing()
211 ::osl::MutexGuard
aGuard( m_aMutex
);
213 // Send a disposing to all listeners.
216 sal_uInt32 nId
= m_nClientId
;
218 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId
, *this );
221 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
223 xComp
->removeEventListener( this );
225 m_pIconCtrl
= nullptr;
231 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getImplementationName()
233 return OUString( "com.sun.star.comp.svtools.AccessibleIconChoiceControlEntry" );
236 Sequence
< OUString
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getSupportedServiceNames()
238 return {"com.sun.star.accessibility.AccessibleContext",
239 "com.sun.star.accessibility.AccessibleComponent",
240 "com.sun.star.awt.AccessibleIconChoiceControlEntry"};
243 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::supportsService( const OUString
& _rServiceName
)
245 return cppu::supportsService(this, _rServiceName
);
250 Reference
< XAccessibleContext
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleContext( )
256 // XAccessibleContext
258 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChildCount( )
260 return 0; // no children
263 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChild( sal_Int32
)
265 throw IndexOutOfBoundsException();
268 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleParent( )
270 ::osl::MutexGuard
aGuard( m_aMutex
);
276 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleIndexInParent( )
278 ::osl::MutexGuard
aGuard( m_aMutex
);
283 sal_Int16 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRole( )
285 //return AccessibleRole::LABEL;
286 return AccessibleRole::LIST_ITEM
;
289 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleDescription( )
291 // no description for every item
295 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleName( )
297 ::osl::MutexGuard
aGuard( m_aMutex
);
300 return implGetText();
303 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRelationSet( )
305 return new utl::AccessibleRelationSetHelper
;
308 Reference
< XAccessibleStateSet
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleStateSet( )
310 SolarMutexGuard aSolarGuard
;
311 ::osl::MutexGuard
aGuard( m_aMutex
);
313 utl::AccessibleStateSetHelper
* pStateSetHelper
= new utl::AccessibleStateSetHelper
;
314 Reference
< XAccessibleStateSet
> xStateSet
= pStateSetHelper
;
316 if ( IsAlive_Impl() )
318 pStateSetHelper
->AddState( AccessibleStateType::TRANSIENT
);
319 pStateSetHelper
->AddState( AccessibleStateType::SELECTABLE
);
320 pStateSetHelper
->AddState( AccessibleStateType::ENABLED
);
321 pStateSetHelper
->AddState( AccessibleStateType::SENSITIVE
);
322 if ( IsShowing_Impl() )
324 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
325 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
328 if ( m_pIconCtrl
&& m_pIconCtrl
->GetCursor() == m_pIconCtrl
->GetEntry( m_nIndex
) )
329 pStateSetHelper
->AddState( AccessibleStateType::SELECTED
);
332 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
337 Locale SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocale( )
339 SolarMutexGuard aSolarGuard
;
340 ::osl::MutexGuard
aGuard( m_aMutex
);
342 return implGetLocale();
345 // XAccessibleComponent
347 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::containsPoint( const awt::Point
& rPoint
)
349 return tools::Rectangle( Point(), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint
) );
352 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleAtPoint( const awt::Point
& )
354 return Reference
< XAccessible
>();
357 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getBounds( )
359 return AWTRectangle( GetBoundingBox() );
362 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocation( )
364 return AWTPoint( GetBoundingBox().TopLeft() );
367 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocationOnScreen( )
369 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
372 awt::Size SAL_CALL
AccessibleIconChoiceCtrlEntry::getSize( )
374 return AWTSize( GetBoundingBox().GetSize() );
377 void SAL_CALL
AccessibleIconChoiceCtrlEntry::grabFocus( )
379 // do nothing, because no focus for each item
382 sal_Int32
AccessibleIconChoiceCtrlEntry::getForeground( )
384 SolarMutexGuard aSolarGuard
;
385 ::osl::MutexGuard
aGuard( m_aMutex
);
387 sal_Int32 nColor
= 0;
388 Reference
< XAccessible
> xParent
= getAccessibleParent();
391 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
392 if ( xParentComp
.is() )
393 nColor
= xParentComp
->getForeground();
399 sal_Int32
AccessibleIconChoiceCtrlEntry::getBackground( )
401 SolarMutexGuard aSolarGuard
;
402 ::osl::MutexGuard
aGuard( m_aMutex
);
404 sal_Int32 nColor
= 0;
405 Reference
< XAccessible
> xParent
= getAccessibleParent();
408 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
409 if ( xParentComp
.is() )
410 nColor
= xParentComp
->getBackground();
419 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterBounds( sal_Int32 _nIndex
)
421 SolarMutexGuard aSolarGuard
;
422 ::osl::MutexGuard
aGuard( m_aMutex
);
424 if ( ( 0 > _nIndex
) || ( implGetText().getLength() <= _nIndex
) )
425 throw IndexOutOfBoundsException();
427 awt::Rectangle
aBounds( 0, 0, 0, 0 );
430 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
431 tools::Rectangle aCharRect
= m_pIconCtrl
->GetEntryCharacterBounds( m_nIndex
, _nIndex
);
432 aCharRect
.Move( -aItemRect
.Left(), -aItemRect
.Top() );
433 aBounds
= AWTRectangle( aCharRect
);
439 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getIndexAtPoint( const awt::Point
& aPoint
)
441 SolarMutexGuard aSolarGuard
;
442 ::osl::MutexGuard
aGuard( m_aMutex
);
444 sal_Int32 nIndex
= -1;
447 vcl::ControlLayoutData aLayoutData
;
448 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
449 m_pIconCtrl
->RecordLayoutData( &aLayoutData
, aItemRect
);
450 Point
aPnt( VCLPoint( aPoint
) );
451 aPnt
+= aItemRect
.TopLeft();
452 nIndex
= aLayoutData
.GetIndexForPoint( aPnt
);
454 long nLen
= aLayoutData
.m_aUnicodeBoundRects
.size();
455 for ( long i
= 0; i
< nLen
; ++i
)
457 tools::Rectangle aRect
= aLayoutData
.GetCharacterBounds(i
);
458 bool bInside
= aRect
.IsInside( aPnt
);
468 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
470 SolarMutexGuard aSolarGuard
;
471 ::osl::MutexGuard
aGuard( m_aMutex
);
474 OUString sText
= implGetText();
475 if ( ( 0 > nStartIndex
) || ( sText
.getLength() <= nStartIndex
)
476 || ( 0 > nEndIndex
) || ( sText
.getLength() <= nEndIndex
) )
477 throw IndexOutOfBoundsException();
479 sal_Int32 nLen
= nEndIndex
- nStartIndex
+ 1;
480 ::svt::OStringTransfer::CopyString( sText
.copy( nStartIndex
, nLen
), m_pIconCtrl
);
485 // XAccessibleEventBroadcaster
487 void SAL_CALL
AccessibleIconChoiceCtrlEntry::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
491 ::osl::MutexGuard
aGuard( m_aMutex
);
493 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
494 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, xListener
);
498 void SAL_CALL
AccessibleIconChoiceCtrlEntry::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
502 ::osl::MutexGuard
aGuard( m_aMutex
);
504 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, xListener
);
505 if ( !nListenerCount
)
507 // no listeners anymore
508 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
509 // and at least to us not firing any events anymore, in case somebody calls
510 // NotifyAccessibleEvent, again
511 sal_Int32 nId
= m_nClientId
;
513 comphelper::AccessibleEventNotifier::revokeClient( nId
);
518 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCaretPosition( )
522 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setCaretPosition ( sal_Int32 nIndex
)
524 SolarMutexGuard aSolarGuard
;
525 ::osl::MutexGuard
aGuard( m_aMutex
);
528 if ( !implIsValidRange( nIndex
, nIndex
, implGetText().getLength() ) )
529 throw IndexOutOfBoundsException();
533 sal_Unicode SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacter( sal_Int32 nIndex
)
535 SolarMutexGuard aSolarGuard
;
536 ::osl::MutexGuard
aGuard( m_aMutex
);
538 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex
);
540 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterAttributes( sal_Int32 nIndex
, const css::uno::Sequence
< OUString
>& )
542 SolarMutexGuard aSolarGuard
;
543 ::osl::MutexGuard
aGuard( m_aMutex
);
546 OUString
sText( implGetText() );
548 if ( !implIsValidIndex( nIndex
, sText
.getLength() ) )
549 throw IndexOutOfBoundsException();
551 return css::uno::Sequence
< css::beans::PropertyValue
>();
553 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterCount( )
555 SolarMutexGuard aSolarGuard
;
556 ::osl::MutexGuard
aGuard( m_aMutex
);
558 return implGetText().getLength();
561 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectedText( )
563 SolarMutexGuard aSolarGuard
;
564 ::osl::MutexGuard
aGuard( m_aMutex
);
568 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionStart( )
570 SolarMutexGuard aSolarGuard
;
571 ::osl::MutexGuard
aGuard( m_aMutex
);
575 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionEnd( )
577 SolarMutexGuard aSolarGuard
;
578 ::osl::MutexGuard
aGuard( m_aMutex
);
582 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
584 SolarMutexGuard aSolarGuard
;
585 ::osl::MutexGuard
aGuard( m_aMutex
);
588 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
589 throw IndexOutOfBoundsException();
593 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getText( )
595 SolarMutexGuard aSolarGuard
;
596 ::osl::MutexGuard
aGuard( m_aMutex
);
598 return implGetText( );
600 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
602 SolarMutexGuard aSolarGuard
;
603 ::osl::MutexGuard
aGuard( m_aMutex
);
605 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex
, nEndIndex
);
607 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
609 SolarMutexGuard aSolarGuard
;
610 ::osl::MutexGuard
aGuard( m_aMutex
);
612 return OCommonAccessibleText::getTextAtIndex( nIndex
,aTextType
);
614 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
616 SolarMutexGuard aSolarGuard
;
617 ::osl::MutexGuard
aGuard( m_aMutex
);
619 return OCommonAccessibleText::getTextBeforeIndex( nIndex
,aTextType
);
621 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
623 SolarMutexGuard aSolarGuard
;
624 ::osl::MutexGuard
aGuard( m_aMutex
);
627 return OCommonAccessibleText::getTextBehindIndex( nIndex
,aTextType
);
633 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionCount( )
635 ::osl::MutexGuard
aGuard( m_aMutex
);
637 // three actions supported
638 return ACCESSIBLE_ACTION_COUNT
;
641 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::doAccessibleAction( sal_Int32 nIndex
)
643 SolarMutexGuard aSolarGuard
;
644 ::osl::MutexGuard
aGuard( m_aMutex
);
647 checkActionIndex_Impl( nIndex
);
650 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
651 if ( pEntry
&& !pEntry
->IsSelected() )
653 m_pIconCtrl
->SetNoSelection();
654 m_pIconCtrl
->SetCursor( pEntry
);
661 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionDescription( sal_Int32 nIndex
)
663 SolarMutexGuard aSolarGuard
;
664 ::osl::MutexGuard
aGuard( m_aMutex
);
666 checkActionIndex_Impl( nIndex
);
669 return OUString( "Select" );
672 Reference
< XAccessibleKeyBinding
> AccessibleIconChoiceCtrlEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex
)
674 ::osl::MutexGuard
aGuard( m_aMutex
);
676 Reference
< XAccessibleKeyBinding
> xRet
;
677 checkActionIndex_Impl( nIndex
);
682 }// namespace accessibility
685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */