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/accessiblerelationsethelper.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <svtools/stringtransfer.hxx>
32 #include <comphelper/accessibleeventnotifier.hxx>
33 #include <i18nlangtag/languagetag.hxx>
35 #define ACCESSIBLE_ACTION_COUNT 1
39 /// @throws css::lang::IndexOutOfBoundsException
40 void checkActionIndex_Impl( sal_Int32 _nIndex
)
42 if ( _nIndex
< 0 || _nIndex
>= ACCESSIBLE_ACTION_COUNT
)
44 throw css::lang::IndexOutOfBoundsException();
49 namespace accessibility
53 using namespace ::com::sun::star::accessibility
;
54 using namespace ::com::sun::star::uno
;
55 using namespace ::com::sun::star::lang
;
56 using namespace ::com::sun::star
;
61 AccessibleIconChoiceCtrlEntry::AccessibleIconChoiceCtrlEntry( SvtIconChoiceCtrl
& _rIconCtrl
,
63 const Reference
< XAccessible
>& _xParent
) :
65 AccessibleIconChoiceCtrlEntry_BASE ( m_aMutex
),
67 m_pIconCtrl ( &_rIconCtrl
),
70 m_xParent ( _xParent
)
73 osl_atomic_increment( &m_refCount
);
75 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
77 xComp
->addEventListener( this );
79 osl_atomic_decrement( &m_refCount
);
82 void AccessibleIconChoiceCtrlEntry::disposing( const css::lang::EventObject
& _rSource
)
84 if ( _rSource
.Source
== m_xParent
)
87 OSL_ENSURE( !m_xParent
.is() && ( m_pIconCtrl
== nullptr ), "" );
91 AccessibleIconChoiceCtrlEntry::~AccessibleIconChoiceCtrlEntry()
95 // increment ref count to prevent double call of Dtor
96 osl_atomic_increment( &m_refCount
);
101 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox_Impl() const
103 tools::Rectangle aRect
;
104 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
106 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
111 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen_Impl() const
113 tools::Rectangle aRect
;
114 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
117 aRect
= m_pIconCtrl
->GetBoundingBox( pEntry
);
118 Point aTopLeft
= aRect
.TopLeft();
119 aTopLeft
+= m_pIconCtrl
->GetWindowExtentsRelative( nullptr ).TopLeft();
120 aRect
= tools::Rectangle( aTopLeft
, aRect
.GetSize() );
126 bool AccessibleIconChoiceCtrlEntry::IsAlive_Impl() const
128 return ( !rBHelper
.bDisposed
&& !rBHelper
.bInDispose
&& m_pIconCtrl
);
131 bool AccessibleIconChoiceCtrlEntry::IsShowing_Impl() const
133 bool bShowing
= false;
134 Reference
< XAccessibleContext
> xParentContext
=
135 m_xParent
.is() ? m_xParent
->getAccessibleContext() : Reference
< XAccessibleContext
>();
136 if( xParentContext
.is() )
138 Reference
< XAccessibleComponent
> xParentComp( xParentContext
, uno::UNO_QUERY
);
139 if( xParentComp
.is() )
140 bShowing
= GetBoundingBox_Impl().Overlaps( VCLRectangle( xParentComp
->getBounds() ) );
146 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBox()
148 SolarMutexGuard aSolarGuard
;
149 ::osl::MutexGuard
aGuard( m_aMutex
);
152 return GetBoundingBox_Impl();
155 tools::Rectangle
AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen()
157 SolarMutexGuard aSolarGuard
;
158 ::osl::MutexGuard
aGuard( m_aMutex
);
161 return GetBoundingBoxOnScreen_Impl();
164 void AccessibleIconChoiceCtrlEntry::EnsureIsAlive() const
166 if ( !IsAlive_Impl() )
167 throw lang::DisposedException();
170 OUString
AccessibleIconChoiceCtrlEntry::implGetText()
173 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
175 sRet
= pEntry
->GetDisplayText();
179 Locale
AccessibleIconChoiceCtrlEntry::implGetLocale()
181 return Application::GetSettings().GetUILanguageTag().getLocale();
183 void AccessibleIconChoiceCtrlEntry::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
192 Sequence
< sal_Int8
> AccessibleIconChoiceCtrlEntry::getImplementationId()
194 return css::uno::Sequence
<sal_Int8
>();
199 void SAL_CALL
AccessibleIconChoiceCtrlEntry::disposing()
201 ::osl::MutexGuard
aGuard( m_aMutex
);
203 // Send a disposing to all listeners.
206 sal_uInt32 nId
= m_nClientId
;
208 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId
, *this );
211 Reference
< XComponent
> xComp( m_xParent
, UNO_QUERY
);
213 xComp
->removeEventListener( this );
215 m_pIconCtrl
= nullptr;
221 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getImplementationName()
223 return "com.sun.star.comp.svtools.AccessibleIconChoiceControlEntry";
226 Sequence
< OUString
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getSupportedServiceNames()
228 return {"com.sun.star.accessibility.AccessibleContext",
229 "com.sun.star.accessibility.AccessibleComponent",
230 "com.sun.star.awt.AccessibleIconChoiceControlEntry"};
233 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::supportsService( const OUString
& _rServiceName
)
235 return cppu::supportsService(this, _rServiceName
);
240 Reference
< XAccessibleContext
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleContext( )
246 // XAccessibleContext
248 sal_Int64 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChildCount( )
250 return 0; // no children
253 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleChild( sal_Int64
)
255 throw IndexOutOfBoundsException();
258 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleParent( )
260 ::osl::MutexGuard
aGuard( m_aMutex
);
266 sal_Int64 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleIndexInParent( )
268 ::osl::MutexGuard
aGuard( m_aMutex
);
273 sal_Int16 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRole( )
275 //return AccessibleRole::LABEL;
276 return AccessibleRole::LIST_ITEM
;
279 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleDescription( )
281 // no description for every item
285 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleName( )
287 ::osl::MutexGuard
aGuard( m_aMutex
);
290 return implGetText();
293 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleRelationSet( )
295 return new utl::AccessibleRelationSetHelper
;
298 sal_Int64 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleStateSet( )
300 SolarMutexGuard aSolarGuard
;
301 ::osl::MutexGuard
aGuard( m_aMutex
);
303 sal_Int64 nStateSet
= 0;
305 if ( IsAlive_Impl() )
307 nStateSet
|= AccessibleStateType::TRANSIENT
;
308 nStateSet
|= AccessibleStateType::SELECTABLE
;
309 nStateSet
|= AccessibleStateType::ENABLED
;
310 nStateSet
|= AccessibleStateType::SENSITIVE
;
311 if ( IsShowing_Impl() )
313 nStateSet
|= AccessibleStateType::SHOWING
;
314 nStateSet
|= AccessibleStateType::VISIBLE
;
317 if ( m_pIconCtrl
&& m_pIconCtrl
->GetCursor() == m_pIconCtrl
->GetEntry( m_nIndex
) )
318 nStateSet
|= AccessibleStateType::SELECTED
;
321 nStateSet
|= AccessibleStateType::DEFUNC
;
326 Locale SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocale( )
328 SolarMutexGuard aSolarGuard
;
329 ::osl::MutexGuard
aGuard( m_aMutex
);
331 return implGetLocale();
334 // XAccessibleComponent
336 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::containsPoint( const awt::Point
& rPoint
)
338 return tools::Rectangle( Point(), GetBoundingBox().GetSize() ).Contains( VCLPoint( rPoint
) );
341 Reference
< XAccessible
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleAtPoint( const awt::Point
& )
343 return Reference
< XAccessible
>();
346 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getBounds( )
348 return AWTRectangle( GetBoundingBox() );
351 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocation( )
353 return AWTPoint( GetBoundingBox().TopLeft() );
356 awt::Point SAL_CALL
AccessibleIconChoiceCtrlEntry::getLocationOnScreen( )
358 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
361 awt::Size SAL_CALL
AccessibleIconChoiceCtrlEntry::getSize( )
363 return AWTSize( GetBoundingBox().GetSize() );
366 void SAL_CALL
AccessibleIconChoiceCtrlEntry::grabFocus( )
368 // do nothing, because no focus for each item
371 sal_Int32
AccessibleIconChoiceCtrlEntry::getForeground( )
373 SolarMutexGuard aSolarGuard
;
374 ::osl::MutexGuard
aGuard( m_aMutex
);
376 sal_Int32 nColor
= 0;
377 Reference
< XAccessible
> xParent
= getAccessibleParent();
380 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
381 if ( xParentComp
.is() )
382 nColor
= xParentComp
->getForeground();
388 sal_Int32
AccessibleIconChoiceCtrlEntry::getBackground( )
390 SolarMutexGuard aSolarGuard
;
391 ::osl::MutexGuard
aGuard( m_aMutex
);
393 sal_Int32 nColor
= 0;
394 Reference
< XAccessible
> xParent
= getAccessibleParent();
397 Reference
< XAccessibleComponent
> xParentComp( xParent
->getAccessibleContext(), UNO_QUERY
);
398 if ( xParentComp
.is() )
399 nColor
= xParentComp
->getBackground();
408 awt::Rectangle SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterBounds( sal_Int32 _nIndex
)
410 SolarMutexGuard aSolarGuard
;
411 ::osl::MutexGuard
aGuard( m_aMutex
);
413 if ( ( 0 > _nIndex
) || ( implGetText().getLength() <= _nIndex
) )
414 throw IndexOutOfBoundsException();
416 awt::Rectangle
aBounds( 0, 0, 0, 0 );
419 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
420 tools::Rectangle aCharRect
= m_pIconCtrl
->GetEntryCharacterBounds( m_nIndex
, _nIndex
);
421 aCharRect
.Move( -aItemRect
.Left(), -aItemRect
.Top() );
422 aBounds
= AWTRectangle( aCharRect
);
428 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getIndexAtPoint( const awt::Point
& aPoint
)
430 SolarMutexGuard aSolarGuard
;
431 ::osl::MutexGuard
aGuard( m_aMutex
);
433 sal_Int32 nIndex
= -1;
436 vcl::ControlLayoutData aLayoutData
;
437 tools::Rectangle aItemRect
= GetBoundingBox_Impl();
438 m_pIconCtrl
->RecordLayoutData( &aLayoutData
, aItemRect
);
439 Point
aPnt( VCLPoint( aPoint
) );
440 aPnt
+= aItemRect
.TopLeft();
441 nIndex
= aLayoutData
.GetIndexForPoint( aPnt
);
443 tools::Long nLen
= aLayoutData
.m_aUnicodeBoundRects
.size();
444 for ( tools::Long i
= 0; i
< nLen
; ++i
)
446 tools::Rectangle aRect
= aLayoutData
.GetCharacterBounds(i
);
447 bool bInside
= aRect
.Contains( aPnt
);
457 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
459 SolarMutexGuard aSolarGuard
;
460 ::osl::MutexGuard
aGuard( m_aMutex
);
463 OUString sText
= implGetText();
464 if ( ( 0 > nStartIndex
) || ( sText
.getLength() <= nStartIndex
)
465 || ( 0 > nEndIndex
) || ( sText
.getLength() <= nEndIndex
) )
466 throw IndexOutOfBoundsException();
468 sal_Int32 nLen
= nEndIndex
- nStartIndex
+ 1;
469 ::svt::OStringTransfer::CopyString( sText
.copy( nStartIndex
, nLen
), m_pIconCtrl
);
474 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::scrollSubstringTo( sal_Int32
, sal_Int32
, AccessibleScrollType
)
479 // XAccessibleEventBroadcaster
481 void SAL_CALL
AccessibleIconChoiceCtrlEntry::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
485 ::osl::MutexGuard
aGuard( m_aMutex
);
487 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
488 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, xListener
);
492 void SAL_CALL
AccessibleIconChoiceCtrlEntry::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
497 ::osl::MutexGuard
aGuard( m_aMutex
);
499 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, xListener
);
500 if ( !nListenerCount
)
502 // no listeners anymore
503 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
504 // and at least to us not firing any events anymore, in case somebody calls
505 // NotifyAccessibleEvent, again
506 sal_Int32 nId
= m_nClientId
;
508 comphelper::AccessibleEventNotifier::revokeClient( nId
);
512 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCaretPosition( )
516 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setCaretPosition ( sal_Int32 nIndex
)
518 SolarMutexGuard aSolarGuard
;
519 ::osl::MutexGuard
aGuard( m_aMutex
);
522 if ( !implIsValidRange( nIndex
, nIndex
, implGetText().getLength() ) )
523 throw IndexOutOfBoundsException();
527 sal_Unicode SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacter( sal_Int32 nIndex
)
529 SolarMutexGuard aSolarGuard
;
530 ::osl::MutexGuard
aGuard( m_aMutex
);
532 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex
);
534 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterAttributes( sal_Int32 nIndex
, const css::uno::Sequence
< OUString
>& )
536 SolarMutexGuard aSolarGuard
;
537 ::osl::MutexGuard
aGuard( m_aMutex
);
540 OUString
sText( implGetText() );
542 if ( !implIsValidIndex( nIndex
, sText
.getLength() ) )
543 throw IndexOutOfBoundsException();
545 return css::uno::Sequence
< css::beans::PropertyValue
>();
547 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getCharacterCount( )
549 SolarMutexGuard aSolarGuard
;
550 ::osl::MutexGuard
aGuard( m_aMutex
);
552 return implGetText().getLength();
555 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectedText( )
557 SolarMutexGuard aSolarGuard
;
558 ::osl::MutexGuard
aGuard( m_aMutex
);
562 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionStart( )
564 SolarMutexGuard aSolarGuard
;
565 ::osl::MutexGuard
aGuard( m_aMutex
);
569 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getSelectionEnd( )
571 SolarMutexGuard aSolarGuard
;
572 ::osl::MutexGuard
aGuard( m_aMutex
);
576 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
578 SolarMutexGuard aSolarGuard
;
579 ::osl::MutexGuard
aGuard( m_aMutex
);
582 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
583 throw IndexOutOfBoundsException();
587 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getText( )
589 SolarMutexGuard aSolarGuard
;
590 ::osl::MutexGuard
aGuard( m_aMutex
);
592 return implGetText( );
594 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
596 SolarMutexGuard aSolarGuard
;
597 ::osl::MutexGuard
aGuard( m_aMutex
);
599 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex
, nEndIndex
);
601 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
603 SolarMutexGuard aSolarGuard
;
604 ::osl::MutexGuard
aGuard( m_aMutex
);
606 return OCommonAccessibleText::getTextAtIndex( nIndex
,aTextType
);
608 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
610 SolarMutexGuard aSolarGuard
;
611 ::osl::MutexGuard
aGuard( m_aMutex
);
613 return OCommonAccessibleText::getTextBeforeIndex( nIndex
,aTextType
);
615 css::accessibility::TextSegment SAL_CALL
AccessibleIconChoiceCtrlEntry::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
617 SolarMutexGuard aSolarGuard
;
618 ::osl::MutexGuard
aGuard( m_aMutex
);
621 return OCommonAccessibleText::getTextBehindIndex( nIndex
,aTextType
);
627 sal_Int32 SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionCount( )
629 // three actions supported
630 return ACCESSIBLE_ACTION_COUNT
;
633 sal_Bool SAL_CALL
AccessibleIconChoiceCtrlEntry::doAccessibleAction( sal_Int32 nIndex
)
635 SolarMutexGuard aSolarGuard
;
636 ::osl::MutexGuard
aGuard( m_aMutex
);
639 checkActionIndex_Impl( nIndex
);
642 SvxIconChoiceCtrlEntry
* pEntry
= m_pIconCtrl
->GetEntry( m_nIndex
);
643 if ( pEntry
&& !pEntry
->IsSelected() )
645 m_pIconCtrl
->SetNoSelection();
646 m_pIconCtrl
->SetCursor( pEntry
);
653 OUString SAL_CALL
AccessibleIconChoiceCtrlEntry::getAccessibleActionDescription( sal_Int32 nIndex
)
655 SolarMutexGuard aSolarGuard
;
656 ::osl::MutexGuard
aGuard( m_aMutex
);
658 checkActionIndex_Impl( nIndex
);
664 Reference
< XAccessibleKeyBinding
> AccessibleIconChoiceCtrlEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex
)
666 Reference
< XAccessibleKeyBinding
> xRet
;
667 checkActionIndex_Impl( nIndex
);
672 }// namespace accessibility
675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */