summaryrefslogtreecommitdiffstats
path: root/accessibility/source
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /accessibility/source
parentInitial commit. (diff)
downloadlibreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.tar.xz
libreoffice-cb75148ebd0135178ff46f89a30139c44f8d2040.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'accessibility/source')
-rw-r--r--accessibility/source/extended/AccessibleBrowseBox.cxx314
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxBase.cxx561
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxCheckBoxCell.cxx162
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxHeaderBar.cxx362
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxHeaderCell.cxx159
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxTable.cxx229
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxTableBase.cxx292
-rw-r--r--accessibility/source/extended/AccessibleBrowseBoxTableCell.cxx338
-rw-r--r--accessibility/source/extended/AccessibleGridControl.cxx354
-rw-r--r--accessibility/source/extended/AccessibleGridControlBase.cxx465
-rw-r--r--accessibility/source/extended/AccessibleGridControlHeader.cxx231
-rw-r--r--accessibility/source/extended/AccessibleGridControlHeaderCell.cxx167
-rw-r--r--accessibility/source/extended/AccessibleGridControlTable.cxx388
-rw-r--r--accessibility/source/extended/AccessibleGridControlTableBase.cxx240
-rw-r--r--accessibility/source/extended/AccessibleGridControlTableCell.cxx355
-rw-r--r--accessibility/source/extended/AccessibleIconView.cxx53
-rw-r--r--accessibility/source/extended/accessiblebrowseboxcell.cxx69
-rw-r--r--accessibility/source/extended/accessibleeditbrowseboxcell.cxx240
-rw-r--r--accessibility/source/extended/accessibleiconchoicectrl.cxx340
-rw-r--r--accessibility/source/extended/accessibleiconchoicectrlentry.cxx680
-rw-r--r--accessibility/source/extended/accessiblelistbox.cxx530
-rw-r--r--accessibility/source/extended/accessiblelistboxentry.cxx1194
-rw-r--r--accessibility/source/extended/accessibletabbar.cxx507
-rw-r--r--accessibility/source/extended/accessibletabbarbase.cxx96
-rw-r--r--accessibility/source/extended/accessibletabbarpage.cxx427
-rw-r--r--accessibility/source/extended/accessibletabbarpagelist.cxx692
-rw-r--r--accessibility/source/extended/accessibletablistbox.cxx112
-rw-r--r--accessibility/source/extended/accessibletablistboxtable.cxx347
-rw-r--r--accessibility/source/extended/textwindowaccessibility.cxx2271
-rw-r--r--accessibility/source/helper/IComboListBoxHelper.cxx17
-rw-r--r--accessibility/source/helper/acc_factory.cxx500
-rw-r--r--accessibility/source/helper/accresmgr.cxx24
-rw-r--r--accessibility/source/helper/characterattributeshelper.cxx78
-rw-r--r--accessibility/source/inc/floatingwindowaccessible.hxx32
-rw-r--r--accessibility/source/standard/accessiblemenubasecomponent.cxx716
-rw-r--r--accessibility/source/standard/accessiblemenucomponent.cxx423
-rw-r--r--accessibility/source/standard/accessiblemenuitemcomponent.cxx472
-rw-r--r--accessibility/source/standard/floatingwindowaccessible.cxx45
-rw-r--r--accessibility/source/standard/svtaccessiblenumericfield.cxx105
-rw-r--r--accessibility/source/standard/vclxaccessiblebox.cxx525
-rw-r--r--accessibility/source/standard/vclxaccessiblebutton.cxx310
-rw-r--r--accessibility/source/standard/vclxaccessiblecheckbox.cxx342
-rw-r--r--accessibility/source/standard/vclxaccessiblecombobox.cxx54
-rw-r--r--accessibility/source/standard/vclxaccessibledropdowncombobox.cxx73
-rw-r--r--accessibility/source/standard/vclxaccessibledropdownlistbox.cxx51
-rw-r--r--accessibility/source/standard/vclxaccessibleedit.cxx608
-rw-r--r--accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx38
-rw-r--r--accessibility/source/standard/vclxaccessiblefixedtext.cxx54
-rw-r--r--accessibility/source/standard/vclxaccessibleheaderbar.cxx130
-rw-r--r--accessibility/source/standard/vclxaccessibleheaderbaritem.cxx265
-rw-r--r--accessibility/source/standard/vclxaccessiblelist.cxx942
-rw-r--r--accessibility/source/standard/vclxaccessiblelistbox.cxx53
-rw-r--r--accessibility/source/standard/vclxaccessiblelistitem.cxx617
-rw-r--r--accessibility/source/standard/vclxaccessiblemenu.cxx233
-rw-r--r--accessibility/source/standard/vclxaccessiblemenubar.cxx187
-rw-r--r--accessibility/source/standard/vclxaccessiblemenuitem.cxx579
-rw-r--r--accessibility/source/standard/vclxaccessiblemenuseparator.cxx50
-rw-r--r--accessibility/source/standard/vclxaccessiblepopupmenu.cxx84
-rw-r--r--accessibility/source/standard/vclxaccessibleradiobutton.cxx281
-rw-r--r--accessibility/source/standard/vclxaccessiblescrollbar.cxx272
-rw-r--r--accessibility/source/standard/vclxaccessiblestatusbar.cxx335
-rw-r--r--accessibility/source/standard/vclxaccessiblestatusbaritem.cxx587
-rw-r--r--accessibility/source/standard/vclxaccessibletabcontrol.cxx488
-rw-r--r--accessibility/source/standard/vclxaccessibletabpage.cxx675
-rw-r--r--accessibility/source/standard/vclxaccessibletabpagewindow.cxx133
-rw-r--r--accessibility/source/standard/vclxaccessibletextcomponent.cxx376
-rw-r--r--accessibility/source/standard/vclxaccessibletextfield.cxx107
-rw-r--r--accessibility/source/standard/vclxaccessibletoolbox.cxx866
-rw-r--r--accessibility/source/standard/vclxaccessibletoolboxitem.cxx734
69 files changed, 24636 insertions, 0 deletions
diff --git a/accessibility/source/extended/AccessibleBrowseBox.cxx b/accessibility/source/extended/AccessibleBrowseBox.cxx
new file mode 100644
index 000000000..6bc4865c6
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBox.cxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBox.hxx>
+#include <extended/AccessibleBrowseBoxTable.hxx>
+#include <extended/AccessibleBrowseBoxHeaderBar.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <utility>
+#include <vcl/accessibletableprovider.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sal/types.h>
+
+
+namespace accessibility
+{
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+// Ctor/Dtor/disposing
+
+AccessibleBrowseBox::AccessibleBrowseBox(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator,
+ ::vcl::IAccessibleTableProvider& _rBrowseBox )
+ : AccessibleBrowseBoxBase( _rxParent, _rBrowseBox,nullptr, AccessibleBrowseBoxObjType::BrowseBox ),
+ m_aCreator(_rxCreator)
+{
+ m_xFocusWindow = VCLUnoHelper::GetInterface(mpBrowseBox->GetWindowInstance());
+}
+
+void AccessibleBrowseBox::setCreator( const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator )
+{
+#if OSL_DEBUG_LEVEL > 0
+ css::uno::Reference< css::accessibility::XAccessible > xCreator(m_aCreator);
+ OSL_ENSURE( !xCreator.is(), "extended/AccessibleBrowseBox::setCreator: creator already set!" );
+#endif
+ m_aCreator = _rxCreator;
+}
+
+
+AccessibleBrowseBox::~AccessibleBrowseBox()
+{
+}
+
+
+void SAL_CALL AccessibleBrowseBox::disposing()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ m_aCreator.clear();
+
+ if ( mxTable.is() )
+ {
+ mxTable->dispose();
+ mxTable.clear();
+ }
+ if ( mxRowHeaderBar.is() )
+ {
+ mxRowHeaderBar->dispose();
+ mxRowHeaderBar.clear();
+ }
+ if ( mxColumnHeaderBar.is() )
+ {
+ mxColumnHeaderBar->dispose();
+ mxColumnHeaderBar.clear();
+ }
+
+ AccessibleBrowseBoxBase::disposing();
+}
+
+
+// css::accessibility::XAccessibleContext
+
+sal_Int32 SAL_CALL AccessibleBrowseBox::getAccessibleChildCount()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return vcl::BBINDEX_FIRSTCONTROL + mpBrowseBox->GetAccessibleControlCount();
+}
+
+
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+AccessibleBrowseBox::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ css::uno::Reference< css::accessibility::XAccessible > xRet;
+ if( nChildIndex >= 0 )
+ {
+ if( nChildIndex < vcl::BBINDEX_FIRSTCONTROL )
+ xRet = implGetFixedChild( nChildIndex );
+ else
+ {
+ // additional controls
+ nChildIndex -= vcl::BBINDEX_FIRSTCONTROL;
+ if( nChildIndex < mpBrowseBox->GetAccessibleControlCount() )
+ xRet = mpBrowseBox->CreateAccessibleControl( nChildIndex );
+ }
+ }
+
+ if( !xRet.is() )
+ throw lang::IndexOutOfBoundsException();
+ return xRet;
+}
+
+// css::accessibility::XAccessibleComponent
+
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+AccessibleBrowseBox::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ css::uno::Reference< css::accessibility::XAccessible > xChild;
+ sal_Int32 nIndex = 0;
+ if( mpBrowseBox->ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
+ xChild = mpBrowseBox->CreateAccessibleControl( nIndex );
+ else
+ {
+ // try whether point is in one of the fixed children
+ // (table, header bars, corner control)
+ Point aPoint( VCLPoint( rPoint ) );
+ for( nIndex = 0; (nIndex < vcl::BBINDEX_FIRSTCONTROL) && !xChild.is(); ++nIndex )
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
+ css::uno::Reference< css::accessibility::XAccessibleComponent >
+ xCurrChildComp( xCurrChild, uno::UNO_QUERY );
+
+ if( xCurrChildComp.is() &&
+ VCLRectangle( xCurrChildComp->getBounds() ).Contains( aPoint ) )
+ xChild = xCurrChild;
+ }
+ }
+ return xChild;
+}
+
+
+void SAL_CALL AccessibleBrowseBox::grabFocus()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ mpBrowseBox->GrabFocus();
+}
+
+// XServiceInfo
+
+OUString SAL_CALL AccessibleBrowseBox::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleBrowseBox";
+}
+
+
+// internal virtual methods
+
+tools::Rectangle AccessibleBrowseBox::implGetBoundingBox()
+{
+ vcl::Window* pParent = mpBrowseBox->GetAccessibleParentWindow();
+ OSL_ENSURE( pParent, "implGetBoundingBox - missing parent window" );
+ return mpBrowseBox->GetWindowExtentsRelative( pParent );
+}
+
+
+tools::Rectangle AccessibleBrowseBox::implGetBoundingBoxOnScreen()
+{
+ return mpBrowseBox->GetWindowExtentsRelative( nullptr );
+}
+
+// internal helper methods
+css::uno::Reference< css::accessibility::XAccessible > AccessibleBrowseBox::implGetTable()
+{
+ if( !mxTable.is() )
+ {
+ mxTable = createAccessibleTable();
+
+ }
+ return mxTable;
+}
+
+css::uno::Reference< css::accessibility::XAccessible >
+AccessibleBrowseBox::implGetHeaderBar(AccessibleBrowseBoxObjType eObjType)
+{
+ css::uno::Reference< css::accessibility::XAccessible > xRet;
+ rtl::Reference< AccessibleBrowseBoxHeaderBar >* pxMember = nullptr;
+
+ if( eObjType == AccessibleBrowseBoxObjType::RowHeaderBar )
+ pxMember = &mxRowHeaderBar;
+ else if( eObjType == AccessibleBrowseBoxObjType::ColumnHeaderBar )
+ pxMember = &mxColumnHeaderBar;
+
+ if( pxMember )
+ {
+ if( !pxMember->is() )
+ {
+ rtl::Reference<AccessibleBrowseBoxHeaderBar> pHeaderBar = new AccessibleBrowseBoxHeaderBar(
+ m_aCreator, *mpBrowseBox, eObjType );
+ *pxMember = pHeaderBar;
+ }
+ xRet = pxMember->get();
+ }
+ return xRet;
+}
+
+css::uno::Reference< css::accessibility::XAccessible >
+AccessibleBrowseBox::implGetFixedChild( sal_Int32 nChildIndex )
+{
+ css::uno::Reference< css::accessibility::XAccessible > xRet;
+ switch( nChildIndex )
+ {
+ case vcl::BBINDEX_COLUMNHEADERBAR:
+ xRet = implGetHeaderBar( AccessibleBrowseBoxObjType::ColumnHeaderBar );
+ break;
+ case vcl::BBINDEX_ROWHEADERBAR:
+ xRet = implGetHeaderBar( AccessibleBrowseBoxObjType::RowHeaderBar );
+ break;
+ case vcl::BBINDEX_TABLE:
+ xRet = implGetTable();
+ break;
+ }
+ return xRet;
+}
+
+rtl::Reference<AccessibleBrowseBoxTable> AccessibleBrowseBox::createAccessibleTable()
+{
+ css::uno::Reference< css::accessibility::XAccessible > xCreator(m_aCreator);
+ OSL_ENSURE( xCreator.is(), "extended/AccessibleBrowseBox::createAccessibleTable: my creator died - how this?" );
+ return new AccessibleBrowseBoxTable( xCreator, *mpBrowseBox );
+}
+
+void AccessibleBrowseBox::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
+{
+ if ( mxTable.is() )
+ {
+ mxTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
+ }
+}
+
+void AccessibleBrowseBox::commitHeaderBarEvent( sal_Int16 _nEventId,
+ const Any& _rNewValue,
+ const Any& _rOldValue,bool _bColumnHeaderBar)
+{
+ rtl::Reference< AccessibleBrowseBoxHeaderBar >& xHeaderBar = _bColumnHeaderBar ? mxColumnHeaderBar : mxRowHeaderBar;
+ if ( xHeaderBar.is() )
+ xHeaderBar->commitEvent(_nEventId,_rNewValue,_rOldValue);
+}
+
+
+// = AccessibleBrowseBoxAccess
+
+AccessibleBrowseBoxAccess::AccessibleBrowseBoxAccess( css::uno::Reference< css::accessibility::XAccessible > _xParent, ::vcl::IAccessibleTableProvider& _rBrowseBox )
+ :m_xParent(std::move( _xParent ))
+ ,m_rBrowseBox( _rBrowseBox )
+{
+}
+
+
+AccessibleBrowseBoxAccess::~AccessibleBrowseBoxAccess()
+{
+}
+
+
+void AccessibleBrowseBoxAccess::dispose()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if (m_xContext.is())
+ {
+ m_xContext->dispose();
+ m_xContext.clear();
+ }
+}
+
+
+css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL AccessibleBrowseBoxAccess::getAccessibleContext()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ // if the context died meanwhile (there is no listener, so it won't tell us explicitly when this happens),
+ // then reset and re-create.
+ if ( m_xContext.is() && !m_xContext->isAlive() )
+ m_xContext = nullptr;
+
+ if ( !m_xContext.is() )
+ m_xContext = new AccessibleBrowseBox( m_xParent, this, m_rBrowseBox );
+
+ return m_xContext;
+}
+
+
+
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxBase.cxx b/accessibility/source/extended/AccessibleBrowseBoxBase.cxx
new file mode 100644
index 000000000..4b16293e5
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxBase.cxx
@@ -0,0 +1,561 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBoxBase.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <utility>
+#include <vcl/accessibletableprovider.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+namespace accessibility {
+
+using namespace com::sun::star::accessibility::AccessibleStateType;
+
+
+// Ctor/Dtor/disposing
+
+AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
+ css::uno::Reference< css::accessibility::XAccessible > xParent,
+ ::vcl::IAccessibleTableProvider& rBrowseBox,
+ css::uno::Reference< css::awt::XWindow > _xFocusWindow,
+ AccessibleBrowseBoxObjType eObjType ) :
+ AccessibleBrowseBoxImplHelper( m_aMutex ),
+ mxParent(std::move( xParent )),
+ mpBrowseBox( &rBrowseBox ),
+ m_xFocusWindow(std::move(_xFocusWindow)),
+ maName( rBrowseBox.GetAccessibleObjectName( eObjType ) ),
+ maDescription( rBrowseBox.GetAccessibleObjectDescription( eObjType ) ),
+ meObjType( eObjType ),
+ m_aClientId(0)
+{
+ if ( m_xFocusWindow.is() )
+ m_xFocusWindow->addFocusListener( this );
+}
+
+AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
+ css::uno::Reference< css::accessibility::XAccessible > rxParent,
+ ::vcl::IAccessibleTableProvider& rBrowseBox,
+ css::uno::Reference< css::awt::XWindow > _xFocusWindow,
+ AccessibleBrowseBoxObjType eObjType,
+ OUString rName,
+ OUString rDescription ) :
+ AccessibleBrowseBoxImplHelper( m_aMutex ),
+ mxParent(std::move( rxParent )),
+ mpBrowseBox( &rBrowseBox ),
+ m_xFocusWindow(std::move(_xFocusWindow)),
+ maName(std::move( rName )),
+ maDescription(std::move( rDescription )),
+ meObjType( eObjType ),
+ m_aClientId(0)
+{
+ if ( m_xFocusWindow.is() )
+ m_xFocusWindow->addFocusListener( this );
+}
+
+AccessibleBrowseBoxBase::~AccessibleBrowseBoxBase()
+{
+ if( isAlive() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+}
+
+void SAL_CALL AccessibleBrowseBoxBase::disposing()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( m_xFocusWindow.is() )
+ {
+ SolarMutexGuard aSolarGuard;
+ m_xFocusWindow->removeFocusListener( this );
+ }
+
+ if ( getClientId( ) )
+ {
+ AccessibleEventNotifier::TClientId nId( getClientId( ) );
+ setClientId( 0 );
+ AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+ }
+
+ mxParent = nullptr;
+ mpBrowseBox = nullptr;
+}
+
+// css::accessibility::XAccessibleContext
+
+Reference< css::accessibility::XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleParent()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return mxParent;
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getAccessibleIndexInParent()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+
+ // -1 for child not found/no parent (according to specification)
+ sal_Int32 nRet = -1;
+
+ css::uno::Reference< uno::XInterface > xMeMyselfAndI( static_cast< css::accessibility::XAccessibleContext* >( this ), uno::UNO_QUERY );
+
+ // iterate over parent's children and search for this object
+ if( mxParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ xParentContext( mxParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ {
+ css::uno::Reference< uno::XInterface > xChild;
+
+ sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
+ for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild )
+ {
+ xChild.set(xParentContext->getAccessibleChild( nChild ), css::uno::UNO_QUERY);
+
+ if ( xMeMyselfAndI.get() == xChild.get() )
+ {
+ nRet = nChild;
+ break;
+ }
+ }
+ }
+ }
+ return nRet;
+}
+
+OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleDescription()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return maDescription;
+}
+
+OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleName()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return maName;
+}
+
+Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL
+AccessibleBrowseBoxBase::getAccessibleRelationSet()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ // BrowseBox does not have relations.
+ return new utl::AccessibleRelationSetHelper;
+}
+
+Reference< css::accessibility::XAccessibleStateSet > SAL_CALL
+AccessibleBrowseBoxBase::getAccessibleStateSet()
+{
+ SolarMethodGuard aGuard( getMutex() );
+ // don't check whether alive -> StateSet may contain DEFUNC
+ return implCreateStateSetHelper();
+}
+
+lang::Locale SAL_CALL AccessibleBrowseBoxBase::getLocale()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ if( mxParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ xParentContext( mxParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ return xParentContext->getLocale();
+ }
+ throw IllegalAccessibleComponentStateException();
+}
+
+// css::accessibility::XAccessibleComponent
+
+sal_Bool SAL_CALL AccessibleBrowseBoxBase::containsPoint( const css::awt::Point& rPoint )
+{
+ return tools::Rectangle( Point(), getBoundingBox().GetSize() ).Contains( VCLPoint( rPoint ) );
+}
+
+awt::Rectangle SAL_CALL AccessibleBrowseBoxBase::getBounds()
+{
+ return AWTRectangle( getBoundingBox() );
+}
+
+awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocation()
+{
+ return AWTPoint( getBoundingBox().TopLeft() );
+}
+
+awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocationOnScreen()
+{
+ return AWTPoint( getBoundingBoxOnScreen().TopLeft() );
+}
+
+awt::Size SAL_CALL AccessibleBrowseBoxBase::getSize()
+{
+ return AWTSize( getBoundingBox().GetSize() );
+}
+
+void SAL_CALL AccessibleBrowseBoxBase::focusGained( const css::awt::FocusEvent& )
+{
+ com::sun::star::uno::Any aFocused;
+ com::sun::star::uno::Any aEmpty;
+ aFocused <<= FOCUSED;
+
+ commitEvent(AccessibleEventId::STATE_CHANGED,aFocused,aEmpty);
+}
+
+
+void SAL_CALL AccessibleBrowseBoxBase::focusLost( const css::awt::FocusEvent& )
+{
+ com::sun::star::uno::Any aFocused;
+ com::sun::star::uno::Any aEmpty;
+ aFocused <<= FOCUSED;
+
+ commitEvent(AccessibleEventId::STATE_CHANGED,aEmpty,aFocused);
+}
+// css::accessibility::XAccessibleEventBroadcaster
+
+void SAL_CALL AccessibleBrowseBoxBase::addAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
+{
+ if ( _rxListener.is() )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ if ( !getClientId( ) )
+ setClientId( AccessibleEventNotifier::registerClient( ) );
+
+ AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener );
+ }
+}
+
+void SAL_CALL AccessibleBrowseBoxBase::removeAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
+{
+ if( !(_rxListener.is() && getClientId( )) )
+ return;
+
+ ::osl::MutexGuard aGuard( getMutex() );
+ sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+
+ AccessibleEventNotifier::TClientId nId( getClientId( ) );
+ setClientId( 0 );
+ AccessibleEventNotifier::revokeClient( nId );
+ }
+}
+
+// XTypeProvider
+
+Sequence< sal_Int8 > SAL_CALL AccessibleBrowseBoxBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XServiceInfo
+
+sal_Bool SAL_CALL AccessibleBrowseBoxBase::supportsService(
+ const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SAL_CALL AccessibleBrowseBoxBase::getSupportedServiceNames()
+{
+ return { "com.sun.star.accessibility.AccessibleContext" };
+}
+
+// other public methods
+
+void AccessibleBrowseBoxBase::setAccessibleName( const OUString& rName )
+{
+ ::osl::ClearableMutexGuard aGuard( getMutex() );
+ Any aOld;
+ aOld <<= maName;
+ maName = rName;
+
+ aGuard.clear();
+
+ commitEvent(
+ AccessibleEventId::NAME_CHANGED,
+ uno::Any( maName ),
+ aOld );
+}
+
+void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString& rDescription )
+{
+ ::osl::ClearableMutexGuard aGuard( getMutex() );
+ Any aOld;
+ aOld <<= maDescription;
+ maDescription = rDescription;
+
+ aGuard.clear();
+
+ commitEvent(
+ AccessibleEventId::DESCRIPTION_CHANGED,
+ uno::Any( maDescription ),
+ aOld );
+}
+
+// internal virtual methods
+
+bool AccessibleBrowseBoxBase::implIsShowing()
+{
+ bool bShowing = false;
+ if( mxParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleComponent >
+ xParentComp( mxParent->getAccessibleContext(), uno::UNO_QUERY );
+ if( xParentComp.is() )
+ bShowing = implGetBoundingBox().Overlaps(
+ VCLRectangle( xParentComp->getBounds() ) );
+ }
+ return bShowing;
+}
+
+rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleBrowseBoxBase::implCreateStateSetHelper()
+{
+ rtl::Reference<::utl::AccessibleStateSetHelper>
+ pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with mxParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ // BrowseBox fills StateSet with states depending on object type
+ mpBrowseBox->FillAccessibleStateSet( *pStateSetHelper, getType() );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+// internal helper methods
+
+bool AccessibleBrowseBoxBase::isAlive() const
+{
+ return !rBHelper.bDisposed && !rBHelper.bInDispose && mpBrowseBox;
+}
+
+void AccessibleBrowseBoxBase::ensureIsAlive() const
+{
+ if( !isAlive() )
+ throw lang::DisposedException();
+}
+
+tools::Rectangle AccessibleBrowseBoxBase::getBoundingBox()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ tools::Rectangle aRect = implGetBoundingBox();
+ if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
+ {
+ SAL_WARN( "accessibility", "rectangle doesn't exist" );
+ }
+ return aRect;
+}
+
+tools::Rectangle AccessibleBrowseBoxBase::getBoundingBoxOnScreen()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ tools::Rectangle aRect = implGetBoundingBoxOnScreen();
+ if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
+ {
+ SAL_WARN( "accessibility", "rectangle doesn't exist" );
+ }
+ return aRect;
+}
+
+void AccessibleBrowseBoxBase::commitEvent(
+ sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
+{
+ osl::MutexGuard aGuard( getMutex() );
+ if ( !getClientId( ) )
+ // if we don't have a client id for the notifier, then we don't have listeners, then
+ // we don't need to notify anything
+ return;
+
+ // build an event object
+ AccessibleEventObject aEvent;
+ aEvent.Source = *this;
+ aEvent.EventId = _nEventId;
+ aEvent.OldValue = _rOldValue;
+ aEvent.NewValue = _rNewValue;
+
+ // let the notifier handle this event
+
+ AccessibleEventNotifier::addEvent( getClientId( ), aEvent );
+}
+
+sal_Int16 SAL_CALL AccessibleBrowseBoxBase::getAccessibleRole()
+{
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ sal_Int16 nRole = AccessibleRole::UNKNOWN;
+ switch ( meObjType )
+ {
+ case AccessibleBrowseBoxObjType::RowHeaderCell:
+ nRole = AccessibleRole::ROW_HEADER;
+ break;
+ case AccessibleBrowseBoxObjType::ColumnHeaderCell:
+ nRole = AccessibleRole::COLUMN_HEADER;
+ break;
+ case AccessibleBrowseBoxObjType::ColumnHeaderBar:
+ case AccessibleBrowseBoxObjType::RowHeaderBar:
+ case AccessibleBrowseBoxObjType::Table:
+ nRole = AccessibleRole::TABLE;
+ break;
+ case AccessibleBrowseBoxObjType::TableCell:
+ nRole = AccessibleRole::TABLE_CELL;
+ break;
+ case AccessibleBrowseBoxObjType::BrowseBox:
+ nRole = AccessibleRole::PANEL;
+ break;
+ case AccessibleBrowseBoxObjType::CheckBoxCell:
+ nRole = AccessibleRole::CHECK_BOX;
+ break;
+ }
+ return nRole;
+}
+
+Reference<XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleAtPoint( const css::awt::Point& )
+{
+ return nullptr;
+}
+
+void SAL_CALL AccessibleBrowseBoxBase::disposing( const css::lang::EventObject& )
+{
+ m_xFocusWindow = nullptr;
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getForeground( )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Color nColor;
+ vcl::Window* pInst = mpBrowseBox->GetWindowInstance();
+ if ( pInst )
+ {
+ if ( pInst->IsControlForeground() )
+ nColor = pInst->GetControlForeground();
+ else
+ {
+ vcl::Font aFont;
+ if ( pInst->IsControlFont() )
+ aFont = pInst->GetControlFont();
+ else
+ aFont = pInst->GetFont();
+ nColor = aFont.GetColor();
+ }
+ }
+
+ return sal_Int32(nColor);
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getBackground( )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Color nColor;
+ vcl::Window* pInst = mpBrowseBox->GetWindowInstance();
+ if ( pInst )
+ {
+ if ( pInst->IsControlBackground() )
+ nColor = pInst->GetControlBackground();
+ else
+ nColor = pInst->GetBackground().GetColor();
+ }
+
+ return sal_Int32(nColor);
+}
+
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base )
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base )
+
+// css::accessibility::XAccessible
+
+Reference< css::accessibility::XAccessibleContext > SAL_CALL BrowseBoxAccessibleElement::getAccessibleContext()
+{
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return this;
+}
+
+
+BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference< css::accessibility::XAccessible >& rxParent, ::vcl::IAccessibleTableProvider& rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType )
+ :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType )
+{
+}
+
+
+BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference< css::accessibility::XAccessible >& rxParent, ::vcl::IAccessibleTableProvider& rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType,
+ const OUString& rName, const OUString& rDescription )
+ :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType, rName, rDescription )
+{
+}
+
+
+BrowseBoxAccessibleElement::~BrowseBoxAccessibleElement( )
+{
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxCheckBoxCell.cxx b/accessibility/source/extended/AccessibleBrowseBoxCheckBoxCell.cxx
new file mode 100644
index 000000000..2b29547ba
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxCheckBoxCell.cxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBoxCheckBoxCell.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <vcl/accessibletableprovider.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+namespace accessibility
+{
+ using namespace com::sun::star::accessibility;
+ using namespace com::sun::star::uno;
+ using namespace com::sun::star::accessibility::AccessibleEventId;
+
+ AccessibleCheckBoxCell::AccessibleCheckBoxCell(const Reference<XAccessible >& _rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos
+ ,const TriState& _eState,
+ bool _bIsTriState)
+ :AccessibleBrowseBoxCell(_rxParent, _rBrowseBox, _xFocusWindow, _nRowPos, _nColPos, AccessibleBrowseBoxObjType::CheckBoxCell)
+ ,m_eState(_eState)
+ ,m_bIsTriState(_bIsTriState)
+ {
+ }
+ IMPLEMENT_FORWARD_XINTERFACE2( AccessibleCheckBoxCell, AccessibleBrowseBoxCell, AccessibleCheckBoxCell_BASE )
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleCheckBoxCell, AccessibleBrowseBoxCell, AccessibleCheckBoxCell_BASE )
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleCheckBoxCell::getAccessibleContext( )
+ {
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return this;
+ }
+
+ rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleCheckBoxCell::implCreateStateSetHelper()
+ {
+ rtl::Reference<::utl::AccessibleStateSetHelper> pStateSetHelper =
+ AccessibleBrowseBoxCell::implCreateStateSetHelper();
+ if( isAlive() )
+ {
+ mpBrowseBox->FillAccessibleStateSetForCell(
+ *pStateSetHelper, getRowPos(), static_cast< sal_uInt16 >( getColumnPos() ) );
+ if ( m_eState == TRISTATE_TRUE )
+ pStateSetHelper->AddState( AccessibleStateType::CHECKED );
+ }
+ return pStateSetHelper;
+ }
+
+ // XAccessibleValue
+
+ Any SAL_CALL AccessibleCheckBoxCell::getCurrentValue( )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ sal_Int32 nValue = 0;
+ switch( m_eState )
+ {
+ case TRISTATE_FALSE:
+ nValue = 0;
+ break;
+ case TRISTATE_TRUE:
+ nValue = 1;
+ break;
+ case TRISTATE_INDET:
+ nValue = 2;
+ break;
+ }
+ return Any(nValue);
+ }
+
+ sal_Bool SAL_CALL AccessibleCheckBoxCell::setCurrentValue( const Any& )
+ {
+ return false;
+ }
+
+ Any SAL_CALL AccessibleCheckBoxCell::getMaximumValue( )
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ Any aValue;
+
+ if ( m_bIsTriState )
+ aValue <<= sal_Int32(2);
+ else
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+ }
+
+ Any SAL_CALL AccessibleCheckBoxCell::getMinimumValue( )
+ {
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+ }
+
+ Any SAL_CALL AccessibleCheckBoxCell::getMinimumIncrement( )
+ {
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+ }
+
+ // XAccessibleContext
+ sal_Int32 SAL_CALL AccessibleCheckBoxCell::getAccessibleChildCount( )
+ {
+ return 0;
+ }
+
+ css::uno::Reference< css::accessibility::XAccessible > SAL_CALL AccessibleCheckBoxCell::getAccessibleChild( sal_Int32 )
+ {
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+ OUString SAL_CALL AccessibleCheckBoxCell::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.TableCheckBoxCell";
+ }
+
+ sal_Int32 SAL_CALL AccessibleCheckBoxCell::getAccessibleIndexInParent()
+ {
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+
+ return ( getRowPos() * mpBrowseBox->GetColumnCount() ) + getColumnPos();
+ }
+
+ void AccessibleCheckBoxCell::SetChecked( bool _bChecked )
+ {
+ m_eState = _bChecked ? TRISTATE_TRUE : TRISTATE_FALSE;
+ Any aOldValue, aNewValue;
+ if ( _bChecked )
+ aNewValue <<= AccessibleStateType::CHECKED;
+ else
+ aOldValue <<= AccessibleStateType::CHECKED;
+ commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxHeaderBar.cxx b/accessibility/source/extended/AccessibleBrowseBoxHeaderBar.cxx
new file mode 100644
index 000000000..3d3541e4a
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxHeaderBar.cxx
@@ -0,0 +1,362 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBoxHeaderBar.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletableprovider.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+
+namespace accessibility {
+
+
+// Ctor/Dtor/disposing --------------------------------------------------------
+
+AccessibleBrowseBoxHeaderBar::AccessibleBrowseBoxHeaderBar(
+ const Reference< XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& rBrowseBox,
+ AccessibleBrowseBoxObjType eObjType ) :
+ AccessibleBrowseBoxTableBase( rxParent, rBrowseBox,eObjType )
+{
+ OSL_ENSURE( isRowBar() || isColumnBar(),
+ "extended/AccessibleBrowseBoxHeaderBar - invalid object type" );
+}
+
+AccessibleBrowseBoxHeaderBar::~AccessibleBrowseBoxHeaderBar()
+{
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleBrowseBoxHeaderBar::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidHeaderIndex( nChildIndex );
+ return implGetChild( nChildIndex, implToVCLColumnPos( nChildIndex ) );
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleIndexInParent()
+{
+ return isRowBar() ? vcl::BBINDEX_ROWHEADERBAR : vcl::BBINDEX_COLUMNHEADERBAR;
+}
+
+// XAccessibleComponent -------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleBrowseBoxHeaderBar::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ sal_Int32 nRow = 0;
+ sal_uInt16 nColumnPos = 0;
+ bool bConverted = isRowBar() ?
+ mpBrowseBox->ConvertPointToRowHeader( nRow, VCLPoint( rPoint ) ) :
+ mpBrowseBox->ConvertPointToColumnHeader( nColumnPos, VCLPoint( rPoint ) );
+
+ return bConverted ? implGetChild( nRow, nColumnPos ) : Reference< XAccessible >();
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::grabFocus()
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ // focus on header not supported
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+OUString SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleRowDescription( sal_Int32 nRow )
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ return OUString(); // no headers in headers
+}
+
+OUString SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleColumnDescription( sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ ensureIsValidColumn( nColumn );
+ return OUString(); // no headers in headers
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleRowHeaders()
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ return nullptr; // no headers in headers
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleColumnHeaders()
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ return nullptr; // no headers in headers
+}
+
+Sequence< sal_Int32 > SAL_CALL AccessibleBrowseBoxHeaderBar::getSelectedAccessibleRows()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Sequence< sal_Int32 > aSelSeq;
+ // row of column header bar not selectable
+ if( isRowBar() )
+ implGetSelectedRows( aSelSeq );
+ return aSelSeq;
+}
+
+Sequence< sal_Int32 > SAL_CALL AccessibleBrowseBoxHeaderBar::getSelectedAccessibleColumns()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Sequence< sal_Int32 > aSelSeq;
+ // column of row header bar ("handle column") not selectable
+ if( isColumnBar() )
+ implGetSelectedColumns( aSelSeq );
+ return aSelSeq;
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxHeaderBar::isAccessibleRowSelected( sal_Int32 nRow )
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ return isRowBar() && implIsRowSelected( nRow );
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxHeaderBar::isAccessibleColumnSelected( sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ ensureIsValidColumn( nColumn );
+ return isColumnBar() && implIsColumnSelected( nColumn );
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBrowseBoxHeaderBar::getAccessibleCellAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+
+ return implGetChild( nRow, implToVCLColumnPos( nColumn ) );
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxHeaderBar::isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidAddress( nRow, nColumn );
+ return isRowBar() ? implIsRowSelected( nRow ) : implIsColumnSelected( nColumn );
+}
+
+// XAccessibleSelection -------------------------------------------------------
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidHeaderIndex( nChildIndex );
+ if( isRowBar() )
+ implSelectRow( nChildIndex, true );
+ else
+ implSelectColumn( implToVCLColumnPos( nChildIndex ), true );
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxHeaderBar::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ // using interface methods - no mutex
+ return isRowBar() ?
+ isAccessibleRowSelected( nChildIndex ) :
+ isAccessibleColumnSelected( nChildIndex );
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::clearAccessibleSelection()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ mpBrowseBox->SetNoSelection();
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::selectAllAccessibleChildren()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ // no multiselection of columns possible
+ if( isRowBar() )
+ mpBrowseBox->SelectAll();
+ else
+ implSelectColumn( implToVCLColumnPos( 0 ), true );
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxHeaderBar::getSelectedAccessibleChildCount()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return isRowBar() ? implGetSelectedRowCount() : implGetSelectedColumnCount();
+}
+
+Reference< XAccessible > SAL_CALL
+AccessibleBrowseBoxHeaderBar::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ // method may throw lang::IndexOutOfBoundsException
+ sal_Int32 nIndex = implGetChildIndexFromSelectedIndex( nSelectedChildIndex );
+ return implGetChild( nIndex, implToVCLColumnPos( nIndex ) );
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::deselectAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ // method may throw lang::IndexOutOfBoundsException
+ if ( isAccessibleChildSelected(nSelectedChildIndex) )
+ {
+ if( isRowBar() )
+ implSelectRow( nSelectedChildIndex, false );
+ else
+ implSelectColumn( implToVCLColumnPos( nSelectedChildIndex ), false );
+ }
+}
+
+// XInterface -----------------------------------------------------------------
+
+Any SAL_CALL AccessibleBrowseBoxHeaderBar::queryInterface( const uno::Type& rType )
+{
+ Any aAny( AccessibleBrowseBoxTableBase::queryInterface( rType ) );
+ return aAny.hasValue() ?
+ aAny : AccessibleBrowseBoxHeaderBarImplHelper::queryInterface( rType );
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::acquire() noexcept
+{
+ AccessibleBrowseBoxTableBase::acquire();
+}
+
+void SAL_CALL AccessibleBrowseBoxHeaderBar::release() noexcept
+{
+ AccessibleBrowseBoxTableBase::release();
+}
+
+// XServiceInfo ---------------------------------------------------------------
+
+OUString SAL_CALL AccessibleBrowseBoxHeaderBar::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderBar";
+}
+
+Sequence< sal_Int8 > SAL_CALL AccessibleBrowseBoxHeaderBar::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// internal virtual methods ---------------------------------------------------
+
+tools::Rectangle AccessibleBrowseBoxHeaderBar::implGetBoundingBox()
+{
+ return mpBrowseBox->calcHeaderRect(isColumnBar(), false);
+}
+
+tools::Rectangle AccessibleBrowseBoxHeaderBar::implGetBoundingBoxOnScreen()
+{
+ return mpBrowseBox->calcHeaderRect(isColumnBar());
+}
+
+sal_Int32 AccessibleBrowseBoxHeaderBar::implGetRowCount() const
+{
+ // column header bar: only 1 row
+ return isRowBar() ? AccessibleBrowseBoxTableBase::implGetRowCount() : 1;
+}
+
+sal_Int32 AccessibleBrowseBoxHeaderBar::implGetColumnCount() const
+{
+ // row header bar ("handle column"): only 1 column
+ return isColumnBar() ? AccessibleBrowseBoxTableBase::implGetColumnCount() : 1;
+}
+
+// internal helper methods ----------------------------------------------------
+
+Reference< XAccessible > AccessibleBrowseBoxHeaderBar::implGetChild(
+ sal_Int32 nRow, sal_uInt16 nColumnPos )
+{
+ return isRowBar() ?
+ mpBrowseBox->CreateAccessibleRowHeader( nRow ) :
+ mpBrowseBox->CreateAccessibleColumnHeader( nColumnPos );
+}
+
+sal_Int32 AccessibleBrowseBoxHeaderBar::implGetChildIndexFromSelectedIndex(
+ sal_Int32 nSelectedChildIndex )
+{
+ Sequence< sal_Int32 > aSelSeq;
+ if( isRowBar() )
+ implGetSelectedRows( aSelSeq );
+ else
+ implGetSelectedColumns( aSelSeq );
+
+ if( (nSelectedChildIndex < 0) || (nSelectedChildIndex >= aSelSeq.getLength()) )
+ throw lang::IndexOutOfBoundsException();
+
+ return aSelSeq.getConstArray()[ nSelectedChildIndex ];
+}
+
+void AccessibleBrowseBoxHeaderBar::ensureIsValidHeaderIndex( sal_Int32 nIndex )
+{
+ if( isRowBar() )
+ ensureIsValidRow( nIndex );
+ else
+ ensureIsValidColumn( nIndex );
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxHeaderCell.cxx b/accessibility/source/extended/AccessibleBrowseBoxHeaderCell.cxx
new file mode 100644
index 000000000..81b3bfa4e
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxHeaderCell.cxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <extended/AccessibleBrowseBoxHeaderCell.hxx>
+#include <vcl/accessibletableprovider.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+namespace accessibility
+{
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::uno;
+
+AccessibleBrowseBoxHeaderCell::AccessibleBrowseBoxHeaderCell(sal_Int32 _nColumnRowId,
+ const Reference< XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ AccessibleBrowseBoxObjType eObjType)
+: BrowseBoxAccessibleElement(rxParent,
+ rBrowseBox,
+ _xFocusWindow,
+ eObjType,
+ rBrowseBox.GetAccessibleObjectName( eObjType ,_nColumnRowId),
+ rBrowseBox.GetAccessibleObjectDescription( eObjType ,_nColumnRowId))
+, m_nColumnRowId(_nColumnRowId)
+{
+}
+/** Creates a new AccessibleStateSetHelper and fills it with states of the
+ current object.
+ @return
+ A filled AccessibleStateSetHelper.
+*/
+rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleBrowseBoxHeaderCell::implCreateStateSetHelper()
+{
+ SolarMethodGuard aGuard( getMutex() );
+
+ rtl::Reference<::utl::AccessibleStateSetHelper>
+ pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with mxParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+
+ mpBrowseBox->FillAccessibleStateSet( *pStateSetHelper, getType() );
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+
+ bool bSelected = isRowBarCell() ? mpBrowseBox->IsRowSelected(m_nColumnRowId) : mpBrowseBox->IsColumnSelected(m_nColumnRowId);
+ if ( bSelected )
+ pStateSetHelper->AddState( AccessibleStateType::SELECTED );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+/** @return
+ The count of visible children.
+*/
+sal_Int32 SAL_CALL AccessibleBrowseBoxHeaderCell::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+/** @return
+ The XAccessible interface of the specified child.
+*/
+Reference<XAccessible > SAL_CALL AccessibleBrowseBoxHeaderCell::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+/** Grabs the focus to the column header. */
+void SAL_CALL AccessibleBrowseBoxHeaderCell::grabFocus()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ if ( isRowBarCell() )
+ mpBrowseBox->SelectRow(m_nColumnRowId);
+ else
+ mpBrowseBox->SelectColumn(static_cast<sal_uInt16>(m_nColumnRowId)); //!!!
+}
+
+/** @return
+ The name of this class.
+*/
+OUString SAL_CALL AccessibleBrowseBoxHeaderCell::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleBrowseBoxHeaderCell";
+}
+
+namespace
+{
+ tools::Rectangle getRectangle(vcl::IAccessibleTableProvider* _pBrowseBox,sal_Int32 _nRowColIndex, bool _bOnScreen,bool _bRowBar)
+ {
+ sal_Int32 nRow = 0;
+ sal_uInt16 nCol = static_cast<sal_uInt16>(_nRowColIndex);
+ if ( _bRowBar )
+ {
+ nRow = _nRowColIndex + 1;
+ nCol = 0;
+ }
+
+ tools::Rectangle aRet(_pBrowseBox->GetFieldRectPixelAbs( nRow , nCol, true, _bOnScreen));
+ return tools::Rectangle(aRet.TopLeft() - Point(0,aRet.GetHeight()),aRet.GetSize());
+ }
+}
+
+tools::Rectangle AccessibleBrowseBoxHeaderCell::implGetBoundingBox()
+{
+ return getRectangle(mpBrowseBox,m_nColumnRowId,false,isRowBarCell());
+}
+
+
+tools::Rectangle AccessibleBrowseBoxHeaderCell::implGetBoundingBoxOnScreen()
+{
+ return getRectangle(mpBrowseBox,m_nColumnRowId,true,isRowBarCell());
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxHeaderCell::getAccessibleIndexInParent()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ sal_Int32 nIndex = m_nColumnRowId;
+ if ( mpBrowseBox->HasRowHeader() )
+ --nIndex;
+ return nIndex;
+}
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxTable.cxx b/accessibility/source/extended/AccessibleBrowseBoxTable.cxx
new file mode 100644
index 000000000..d245c5155
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxTable.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBoxTable.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletableprovider.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+
+namespace accessibility {
+
+
+// Ctor/Dtor/disposing --------------------------------------------------------
+
+AccessibleBrowseBoxTable::AccessibleBrowseBoxTable(
+ const Reference< XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& rBrowseBox ) :
+ AccessibleBrowseBoxTableBase( rxParent, rBrowseBox, AccessibleBrowseBoxObjType::Table )
+{
+}
+
+AccessibleBrowseBoxTable::~AccessibleBrowseBoxTable()
+{
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleBrowseBoxTable::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidIndex( nChildIndex );
+ return mpBrowseBox->CreateAccessibleCell(
+ implGetRow( nChildIndex ), static_cast<sal_Int16>(implGetColumn( nChildIndex )) );
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTable::getAccessibleIndexInParent()
+{
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return vcl::BBINDEX_TABLE;
+}
+
+// XAccessibleComponent -------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleBrowseBoxTable::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Reference< XAccessible > xChild;
+ sal_Int32 nRow = 0;
+ sal_uInt16 nColumnPos = 0;
+ if( mpBrowseBox->ConvertPointToCellAddress( nRow, nColumnPos, VCLPoint( rPoint ) ) )
+ xChild = mpBrowseBox->CreateAccessibleCell( nRow, nColumnPos );
+
+ return xChild;
+}
+
+void SAL_CALL AccessibleBrowseBoxTable::grabFocus()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ mpBrowseBox->GrabTableFocus();
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+OUString SAL_CALL AccessibleBrowseBoxTable::getAccessibleRowDescription( sal_Int32 nRow )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ return mpBrowseBox->GetRowDescription( nRow );
+}
+
+OUString SAL_CALL AccessibleBrowseBoxTable::getAccessibleColumnDescription( sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidColumn( nColumn );
+ return mpBrowseBox->GetColumnDescription( static_cast<sal_uInt16>(nColumn) );
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleBrowseBoxTable::getAccessibleRowHeaders()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return implGetHeaderBar( vcl::BBINDEX_ROWHEADERBAR );
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleBrowseBoxTable::getAccessibleColumnHeaders()
+{
+ ::osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return implGetHeaderBar( vcl::BBINDEX_COLUMNHEADERBAR );
+}
+
+Sequence< sal_Int32 > SAL_CALL AccessibleBrowseBoxTable::getSelectedAccessibleRows()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Sequence< sal_Int32 > aSelSeq;
+ implGetSelectedRows( aSelSeq );
+ return aSelSeq;
+}
+
+Sequence< sal_Int32 > SAL_CALL AccessibleBrowseBoxTable::getSelectedAccessibleColumns()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ Sequence< sal_Int32 > aSelSeq;
+ implGetSelectedColumns( aSelSeq );
+ return aSelSeq;
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxTable::isAccessibleRowSelected( sal_Int32 nRow )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidRow( nRow );
+ return implIsRowSelected( nRow );
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxTable::isAccessibleColumnSelected( sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidColumn( nColumn );
+ return implIsColumnSelected( nColumn );
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBrowseBoxTable::getAccessibleCellAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidAddress( nRow, nColumn );
+ return mpBrowseBox->CreateAccessibleCell( nRow, static_cast<sal_Int16>(nColumn) );
+}
+
+sal_Bool SAL_CALL AccessibleBrowseBoxTable::isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ ensureIsValidAddress( nRow, nColumn );
+ return implIsRowSelected( nRow ) || implIsColumnSelected( nColumn );
+}
+
+// XServiceInfo ---------------------------------------------------------------
+
+OUString SAL_CALL AccessibleBrowseBoxTable::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleBrowseBoxTable";
+}
+
+// internal virtual methods ---------------------------------------------------
+
+tools::Rectangle AccessibleBrowseBoxTable::implGetBoundingBox()
+{
+ return mpBrowseBox->calcTableRect(false);
+}
+
+tools::Rectangle AccessibleBrowseBoxTable::implGetBoundingBoxOnScreen()
+{
+ return mpBrowseBox->calcTableRect();
+}
+
+// internal helper methods ----------------------------------------------------
+
+Reference< XAccessibleTable > AccessibleBrowseBoxTable::implGetHeaderBar(
+ sal_Int32 nChildIndex )
+{
+ Reference< XAccessible > xRet;
+ Reference< XAccessibleContext > xContext( mxParent, uno::UNO_QUERY );
+ if( xContext.is() )
+ {
+ try
+ {
+ xRet = xContext->getAccessibleChild( nChildIndex );
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ OSL_FAIL( "implGetHeaderBar - wrong child index" );
+ }
+ // RuntimeException goes to caller
+ }
+ return Reference< XAccessibleTable >( xRet, uno::UNO_QUERY );
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxTableBase.cxx b/accessibility/source/extended/AccessibleBrowseBoxTableBase.cxx
new file mode 100644
index 000000000..ebb6e06e0
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxTableBase.cxx
@@ -0,0 +1,292 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleBrowseBoxTableBase.hxx>
+#include <vcl/accessibletableprovider.hxx>
+#include <comphelper/sequence.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+
+using css::uno::Reference;
+using css::uno::Sequence;
+using css::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+
+namespace accessibility {
+
+
+// Ctor/Dtor/disposing --------------------------------------------------------
+
+AccessibleBrowseBoxTableBase::AccessibleBrowseBoxTableBase(
+ const Reference< XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& rBrowseBox,
+ AccessibleBrowseBoxObjType eObjType ) :
+ BrowseBoxAccessibleElement( rxParent, rBrowseBox,nullptr, eObjType )
+{
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleChildCount()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ return implGetChildCount();
+}
+
+sal_Int16 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleRole()
+{
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return AccessibleRole::TABLE;
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleRowCount()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ return implGetRowCount();
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleColumnCount()
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ return implGetColumnCount();
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return 1; // merged cells not supported
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return 1; // merged cells not supported
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleCaption()
+{
+ ensureIsAlive();
+ return nullptr; // not supported
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleSummary()
+{
+ ensureIsAlive();
+ return nullptr; // not supported
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return nRow * implGetColumnCount() + nColumn;
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleRow( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ return implGetRow( nChildIndex );
+}
+
+sal_Int32 SAL_CALL AccessibleBrowseBoxTableBase::getAccessibleColumn( sal_Int32 nChildIndex )
+{
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ return implGetColumn( nChildIndex );
+}
+
+// XInterface -----------------------------------------------------------------
+
+Any SAL_CALL AccessibleBrowseBoxTableBase::queryInterface( const uno::Type& rType )
+{
+ Any aAny( BrowseBoxAccessibleElement::queryInterface( rType ) );
+ return aAny.hasValue() ?
+ aAny : AccessibleBrowseBoxTableImplHelper::queryInterface( rType );
+}
+
+void SAL_CALL AccessibleBrowseBoxTableBase::acquire() noexcept
+{
+ BrowseBoxAccessibleElement::acquire();
+}
+
+void SAL_CALL AccessibleBrowseBoxTableBase::release() noexcept
+{
+ BrowseBoxAccessibleElement::release();
+}
+
+// XTypeProvider --------------------------------------------------------------
+
+Sequence< uno::Type > SAL_CALL AccessibleBrowseBoxTableBase::getTypes()
+{
+ return ::comphelper::concatSequences(
+ BrowseBoxAccessibleElement::getTypes(),
+ AccessibleBrowseBoxTableImplHelper::getTypes() );
+}
+
+Sequence< sal_Int8 > SAL_CALL AccessibleBrowseBoxTableBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// internal virtual methods ---------------------------------------------------
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetRowCount() const
+{
+ return mpBrowseBox->GetRowCount();
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetColumnCount() const
+{
+ sal_uInt16 nColumns = mpBrowseBox->GetColumnCount();
+ // do not count the "handle column"
+ if( nColumns && implHasHandleColumn() )
+ --nColumns;
+ return nColumns;
+}
+
+// internal helper methods ----------------------------------------------------
+
+bool AccessibleBrowseBoxTableBase::implHasHandleColumn() const
+{
+ return mpBrowseBox->HasRowHeader();
+}
+
+sal_uInt16 AccessibleBrowseBoxTableBase::implToVCLColumnPos( sal_Int32 nColumn ) const
+{
+ sal_uInt16 nVCLPos = 0;
+ if( (0 <= nColumn) && (nColumn < implGetColumnCount()) )
+ {
+ // regard "handle column"
+ if( implHasHandleColumn() )
+ ++nColumn;
+ nVCLPos = static_cast< sal_uInt16 >( nColumn );
+ }
+ return nVCLPos;
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetChildCount() const
+{
+ return implGetRowCount() * implGetColumnCount();
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetRow( sal_Int32 nChildIndex ) const
+{
+ sal_Int32 nColumns = implGetColumnCount();
+ return nColumns ? (nChildIndex / nColumns) : 0;
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetColumn( sal_Int32 nChildIndex ) const
+{
+ sal_Int32 nColumns = implGetColumnCount();
+ return nColumns ? (nChildIndex % nColumns) : 0;
+}
+
+bool AccessibleBrowseBoxTableBase::implIsRowSelected( sal_Int32 nRow ) const
+{
+ return mpBrowseBox->IsRowSelected( nRow );
+}
+
+bool AccessibleBrowseBoxTableBase::implIsColumnSelected( sal_Int32 nColumn ) const
+{
+ if( implHasHandleColumn() )
+ --nColumn;
+ return mpBrowseBox->IsColumnSelected( nColumn );
+}
+
+void AccessibleBrowseBoxTableBase::implSelectRow( sal_Int32 nRow, bool bSelect )
+{
+ mpBrowseBox->SelectRow( nRow, bSelect );
+}
+
+void AccessibleBrowseBoxTableBase::implSelectColumn( sal_Int32 nColumnPos, bool bSelect )
+{
+ mpBrowseBox->SelectColumn( static_cast<sal_uInt16>(nColumnPos), bSelect );
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetSelectedRowCount() const
+{
+ return mpBrowseBox->GetSelectedRowCount();
+}
+
+sal_Int32 AccessibleBrowseBoxTableBase::implGetSelectedColumnCount() const
+{
+ return mpBrowseBox->GetSelectedColumnCount();
+}
+
+void AccessibleBrowseBoxTableBase::implGetSelectedRows( Sequence< sal_Int32 >& rSeq )
+{
+ mpBrowseBox->GetAllSelectedRows( rSeq );
+}
+
+void AccessibleBrowseBoxTableBase::implGetSelectedColumns( Sequence< sal_Int32 >& rSeq )
+{
+ mpBrowseBox->GetAllSelectedColumns( rSeq );
+}
+
+void AccessibleBrowseBoxTableBase::ensureIsValidRow( sal_Int32 nRow )
+{
+ if( nRow >= implGetRowCount() )
+ throw lang::IndexOutOfBoundsException( "row index is invalid", *this );
+}
+
+void AccessibleBrowseBoxTableBase::ensureIsValidColumn( sal_Int32 nColumn )
+{
+ if( nColumn >= implGetColumnCount() )
+ throw lang::IndexOutOfBoundsException( "column index is invalid", *this );
+}
+
+void AccessibleBrowseBoxTableBase::ensureIsValidAddress(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ ensureIsValidRow( nRow );
+ ensureIsValidColumn( nColumn );
+}
+
+void AccessibleBrowseBoxTableBase::ensureIsValidIndex( sal_Int32 nChildIndex )
+{
+ if( nChildIndex >= implGetChildCount() )
+ throw lang::IndexOutOfBoundsException( "child index is invalid", *this );
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleBrowseBoxTableCell.cxx b/accessibility/source/extended/AccessibleBrowseBoxTableCell.cxx
new file mode 100644
index 000000000..13cdb63e2
--- /dev/null
+++ b/accessibility/source/extended/AccessibleBrowseBoxTableCell.cxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <extended/AccessibleBrowseBoxTableCell.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletableprovider.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+namespace accessibility
+{
+ namespace
+ {
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkIndex_Impl( sal_Int32 _nIndex, const OUString& _sText )
+ {
+ if ( _nIndex >= _sText.getLength() )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+ sal_Int32 getIndex_Impl( sal_Int32 _nRow, sal_uInt16 _nColumn, sal_uInt16 _nColumnCount )
+ {
+ return _nRow * _nColumnCount + _nColumn;
+ }
+ }
+ using namespace ::com::sun::star::lang;
+ using namespace utl;
+ using namespace comphelper;
+ using namespace ::com::sun::star::uno;
+ using ::com::sun::star::accessibility::XAccessible;
+ using namespace ::com::sun::star::accessibility;
+
+
+ // implementation of a table cell
+ OUString AccessibleBrowseBoxTableCell::implGetText()
+ {
+ return mpBrowseBox->GetAccessibleCellText( getRowPos(), static_cast< sal_uInt16 >( getColumnPos() ) );
+ }
+
+ css::lang::Locale AccessibleBrowseBoxTableCell::implGetLocale()
+ {
+ return mpBrowseBox->GetAccessible()->getAccessibleContext()->getLocale();
+ }
+
+ void AccessibleBrowseBoxTableCell::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+ {
+ nStartIndex = 0;
+ nEndIndex = 0;
+ }
+
+ AccessibleBrowseBoxTableCell::AccessibleBrowseBoxTableCell(const Reference<XAccessible >& _rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos,
+ sal_Int32 _nOffset )
+ :AccessibleBrowseBoxCell( _rxParent, _rBrowseBox, _xFocusWindow, _nRowPos, _nColPos )
+ {
+ m_nOffset = ( _nOffset == OFFSET_DEFAULT ) ? sal_Int32(vcl::BBINDEX_FIRSTCONTROL) : _nOffset;
+ sal_Int32 nIndex = getIndex_Impl( _nRowPos, _nColPos, _rBrowseBox.GetColumnCount() );
+ setAccessibleName( _rBrowseBox.GetAccessibleObjectName( AccessibleBrowseBoxObjType::TableCell, nIndex ) );
+ setAccessibleDescription( _rBrowseBox.GetAccessibleObjectDescription( AccessibleBrowseBoxObjType::TableCell, nIndex ) );
+ // Need to register as event listener
+ Reference< XComponent > xComponent(_rxParent, UNO_QUERY);
+ if( xComponent.is() )
+ xComponent->addEventListener(static_cast< XEventListener *> (this));
+ }
+
+ // XInterface -------------------------------------------------------------
+
+ /** Queries for a new interface. */
+ css::uno::Any SAL_CALL AccessibleBrowseBoxTableCell::queryInterface( const css::uno::Type& rType )
+ {
+ Any aRet = AccessibleBrowseBoxCell::queryInterface(rType);
+ if ( !aRet.hasValue() )
+ aRet = AccessibleTextHelper_BASE::queryInterface(rType);
+ return aRet;
+ }
+
+ /** Acquires the object (calls acquire() on base class). */
+ void SAL_CALL AccessibleBrowseBoxTableCell::acquire() noexcept
+ {
+ AccessibleBrowseBoxCell::acquire();
+ }
+
+ /** Releases the object (calls release() on base class). */
+ void SAL_CALL AccessibleBrowseBoxTableCell::release() noexcept
+ {
+ AccessibleBrowseBoxCell::release();
+ }
+
+ css::awt::Rectangle SAL_CALL AccessibleBrowseBoxTableCell::getCharacterBounds( sal_Int32 nIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ css::awt::Rectangle aRect;
+
+ if ( mpBrowseBox )
+ {
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ aRect = AWTRectangle( mpBrowseBox->GetFieldCharacterBounds( getRowPos(), getColumnPos(), nIndex ) );
+ }
+
+ return aRect;
+ }
+
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getIndexAtPoint( const css::awt::Point& _aPoint )
+ {
+ //! TODO CTL bidi
+ // OSL_FAIL("Need to be done by base class!");
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return mpBrowseBox->GetFieldIndexAtPoint( getRowPos(), getColumnPos(), VCLPoint( _aPoint ) );
+ }
+
+ /** @return
+ The name of this class.
+ */
+ OUString SAL_CALL AccessibleBrowseBoxTableCell::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleBrowseBoxTableCell";
+ }
+
+ /** @return The count of visible children. */
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getAccessibleChildCount()
+ {
+ return 0;
+ }
+
+ /** @return The XAccessible interface of the specified child. */
+ css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ AccessibleBrowseBoxTableCell::getAccessibleChild( sal_Int32 )
+ {
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+ /** Creates a new AccessibleStateSetHelper and fills it with states of the
+ current object.
+ @return
+ A filled AccessibleStateSetHelper.
+ */
+ rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleBrowseBoxTableCell::implCreateStateSetHelper()
+ {
+ SolarMethodGuard aGuard(getMutex());
+
+ rtl::Reference<::utl::AccessibleStateSetHelper> pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with mxParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+
+ mpBrowseBox->FillAccessibleStateSetForCell( *pStateSetHelper, getRowPos(), static_cast< sal_uInt16 >( getColumnPos() ) );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+ }
+
+
+ // XAccessible ------------------------------------------------------------
+
+ /** @return The XAccessibleContext interface of this object. */
+ Reference< XAccessibleContext > SAL_CALL AccessibleBrowseBoxTableCell::getAccessibleContext()
+ {
+ osl::MutexGuard aGuard( getMutex() );
+ ensureIsAlive();
+ return this;
+ }
+
+ // XAccessibleContext -----------------------------------------------------
+
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getAccessibleIndexInParent()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return /*vcl::BBINDEX_FIRSTCONTROL*/ m_nOffset + ( getRowPos() * mpBrowseBox->GetColumnCount() ) + getColumnPos();
+ }
+
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getCaretPosition( )
+ {
+ return -1;
+ }
+
+ sal_Bool SAL_CALL AccessibleBrowseBoxTableCell::setCaretPosition ( sal_Int32 nIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ sal_Unicode SAL_CALL AccessibleBrowseBoxTableCell::getCharacter( sal_Int32 nIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+ }
+ css::uno::Sequence< css::beans::PropertyValue > SAL_CALL AccessibleBrowseBoxTableCell::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return css::uno::Sequence< css::beans::PropertyValue >();
+ }
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getCharacterCount( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return implGetText().getLength();
+ }
+
+ OUString SAL_CALL AccessibleBrowseBoxTableCell::getSelectedText( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getSelectedText( );
+ }
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getSelectionStart( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getSelectionStart( );
+ }
+ sal_Int32 SAL_CALL AccessibleBrowseBoxTableCell::getSelectionEnd( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getSelectionEnd( );
+ }
+ sal_Bool SAL_CALL AccessibleBrowseBoxTableCell::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ OUString SAL_CALL AccessibleBrowseBoxTableCell::getText( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return implGetText( );
+ }
+ OUString SAL_CALL AccessibleBrowseBoxTableCell::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleBrowseBoxTableCell::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleBrowseBoxTableCell::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleBrowseBoxTableCell::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
+ }
+ sal_Bool SAL_CALL AccessibleBrowseBoxTableCell::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ OUString sText = implGetText();
+ checkIndex_Impl( nStartIndex, sText );
+ checkIndex_Impl( nEndIndex, sText );
+
+ //!!! don't know how to put a string into the clipboard
+ return false;
+ }
+ sal_Bool SAL_CALL AccessibleBrowseBoxTableCell::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+ {
+ return false;
+ }
+ void AccessibleBrowseBoxTableCell::disposing( const EventObject& _rSource )
+ {
+ if ( _rSource.Source == mxParent )
+ {
+ dispose();
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControl.cxx b/accessibility/source/extended/AccessibleGridControl.cxx
new file mode 100644
index 000000000..a3d016194
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControl.cxx
@@ -0,0 +1,354 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleGridControl.hxx>
+#include <extended/AccessibleGridControlTable.hxx>
+#include <extended/AccessibleGridControlHeader.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <toolkit/helper/convert.hxx>
+#include <utility>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+
+namespace accessibility
+{
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+AccessibleGridControl::AccessibleGridControl(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator,
+ ::vcl::table::IAccessibleTable& _rTable )
+ : AccessibleGridControlBase( _rxParent, _rTable, TCTYPE_GRIDCONTROL ),
+ m_aCreator(_rxCreator)
+{
+}
+
+
+void SAL_CALL AccessibleGridControl::disposing()
+{
+ SolarMutexGuard g;
+
+ m_aCreator.clear();
+
+ if ( m_xTable.is() )
+ {
+ m_xTable->dispose();
+ m_xTable.clear();
+ }
+ if ( m_xRowHeaderBar.is() )
+ {
+ m_xRowHeaderBar->dispose();
+ m_xRowHeaderBar.clear();
+ }
+ if ( m_xColumnHeaderBar.is() )
+ {
+ m_xColumnHeaderBar->dispose();
+ m_xColumnHeaderBar.clear();
+ }
+ AccessibleGridControlBase::disposing();
+}
+
+sal_Int32 AccessibleGridControl::implGetAccessibleChildCount()
+{
+ return m_aTable.GetAccessibleControlCount();
+}
+
+// css::accessibility::XAccessibleContext ---------------------------------------------------------
+
+
+sal_Int32 SAL_CALL AccessibleGridControl::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ensureIsAlive();
+ return implGetAccessibleChildCount();
+}
+
+
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+AccessibleGridControl::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ if (nChildIndex<0 || nChildIndex>=implGetAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ css::uno::Reference< css::accessibility::XAccessible > xChild;
+ if (isAlive())
+ {
+ if(nChildIndex == 0 && m_aTable.HasColHeader())
+ {
+ if(!m_xColumnHeaderBar.is())
+ {
+ m_xColumnHeaderBar = new AccessibleGridControlHeader(m_aCreator, m_aTable, vcl::table::TCTYPE_COLUMNHEADERBAR);
+ }
+ xChild = m_xColumnHeaderBar.get();
+ }
+ else if(m_aTable.HasRowHeader() && (nChildIndex == 1 || nChildIndex == 0))
+ {
+ if(!m_xRowHeaderBar.is())
+ {
+ m_xRowHeaderBar = new AccessibleGridControlHeader(m_aCreator, m_aTable, vcl::table::TCTYPE_ROWHEADERBAR);
+ }
+ xChild = m_xRowHeaderBar.get();
+ }
+ else
+ {
+ if(!m_xTable.is())
+ {
+ m_xTable = new AccessibleGridControlTable(m_aCreator, m_aTable);
+ }
+ xChild = m_xTable.get();
+ }
+ }
+ return xChild;
+}
+
+
+sal_Int16 SAL_CALL AccessibleGridControl::getAccessibleRole()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return AccessibleRole::PANEL;
+}
+
+
+// css::accessibility::XAccessibleComponent -------------------------------------------------------
+
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+AccessibleGridControl::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMutexGuard aSolarGuard;
+ ensureIsAlive();
+
+ css::uno::Reference< css::accessibility::XAccessible > xChild;
+ sal_Int32 nIndex = 0;
+ if( m_aTable.ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
+ xChild = m_aTable.CreateAccessibleControl( nIndex );
+ else
+ {
+ // try whether point is in one of the fixed children
+ // (table, header bars, corner control)
+ Point aPoint( VCLPoint( rPoint ) );
+ for( nIndex = 0; (nIndex < 3) && !xChild.is(); ++nIndex )
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
+ css::uno::Reference< css::accessibility::XAccessibleComponent >
+ xCurrChildComp( xCurrChild, uno::UNO_QUERY );
+
+ if( xCurrChildComp.is() &&
+ VCLRectangle( xCurrChildComp->getBounds() ).Contains( aPoint ) )
+ xChild = xCurrChild;
+ }
+ }
+ return xChild;
+}
+
+
+void SAL_CALL AccessibleGridControl::grabFocus()
+{
+ SolarMutexGuard aSolarGuard;
+ ensureIsAlive();
+ m_aTable.GrabFocus();
+}
+
+// XServiceInfo ---------------------------------------------------------------
+
+OUString SAL_CALL AccessibleGridControl::getImplementationName()
+{
+ return "com.sun.star.accessibility.AccessibleGridControl";
+}
+
+
+// internal virtual methods ---------------------------------------------------
+
+tools::Rectangle AccessibleGridControl::implGetBoundingBox()
+{
+ vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
+ OSL_ENSURE( pParent, "implGetBoundingBox - missing parent window" );
+ return m_aTable.GetWindowExtentsRelative( pParent );
+}
+
+
+tools::Rectangle AccessibleGridControl::implGetBoundingBoxOnScreen()
+{
+ return m_aTable.GetWindowExtentsRelative( nullptr );
+}
+// internal helper methods ----------------------------------------------------
+
+css::uno::Reference< css::accessibility::XAccessible > AccessibleGridControl::implGetTable()
+{
+ if( !m_xTable.is() )
+ {
+ m_xTable = createAccessibleTable();
+ }
+ return m_xTable;
+}
+
+
+css::uno::Reference< css::accessibility::XAccessible >
+AccessibleGridControl::implGetHeaderBar( AccessibleTableControlObjType eObjType )
+{
+ css::uno::Reference< css::accessibility::XAccessible > xRet;
+ rtl::Reference< AccessibleGridControlHeader >* pxMember = nullptr;
+
+ if( eObjType == TCTYPE_ROWHEADERBAR )
+ pxMember = &m_xRowHeaderBar;
+ else if( eObjType == TCTYPE_COLUMNHEADERBAR )
+ pxMember = &m_xColumnHeaderBar;
+
+ if( pxMember )
+ {
+ if( !pxMember->is() )
+ {
+ *pxMember = new AccessibleGridControlHeader(
+ m_aCreator, m_aTable, eObjType );
+ }
+ xRet = pxMember->get();
+ }
+ return xRet;
+}
+
+css::uno::Reference< css::accessibility::XAccessible >
+AccessibleGridControl::implGetFixedChild( sal_Int32 nChildIndex )
+{
+ css::uno::Reference< css::accessibility::XAccessible > xRet;
+ switch( nChildIndex )
+ {
+ /** Child index of the column header bar (first row). */
+ case 0:
+ xRet = implGetHeaderBar( TCTYPE_COLUMNHEADERBAR );
+ break;
+ /** Child index of the row header bar ("handle column"). */
+ case 1:
+ xRet = implGetHeaderBar( TCTYPE_ROWHEADERBAR );
+ break;
+ /** Child index of the data table. */
+ case 2:
+ xRet = implGetTable();
+ break;
+ }
+ return xRet;
+}
+
+rtl::Reference<AccessibleGridControlTable> AccessibleGridControl::createAccessibleTable()
+{
+ css::uno::Reference< css::accessibility::XAccessible > xCreator(m_aCreator);
+ OSL_ENSURE( xCreator.is(), "extended/AccessibleGridControl::createAccessibleTable: my creator died - how this?" );
+ return new AccessibleGridControlTable( xCreator, m_aTable );
+}
+
+void AccessibleGridControl::commitCellEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
+{
+ sal_Int32 nChildCount = implGetAccessibleChildCount();
+ if(nChildCount != 0)
+ {
+ for(sal_Int32 i=0;i<nChildCount;i++)
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xAccessible = getAccessibleChild(i);
+ if(css::uno::Reference< css::accessibility::XAccessible >(m_xTable) == xAccessible)
+ {
+ Reference<XAccessible> xCell = m_xTable->getAccessibleCellAt(
+ m_aTable.GetCurrentRow(), m_aTable.GetCurrentColumn());
+ AccessibleGridControlTableCell* pCell = static_cast<AccessibleGridControlTableCell*>(xCell.get());
+ pCell->commitEvent(_nEventId, _rNewValue, _rOldValue);
+ }
+ }
+ }
+ else
+ {
+ if ( m_xTable.is() )
+ m_xTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
+ }
+}
+
+void AccessibleGridControl::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
+{
+ if ( !m_xTable.is() )
+ return;
+
+ if(_nEventId == AccessibleEventId::ACTIVE_DESCENDANT_CHANGED)
+ {
+ const sal_Int32 nCurrentRow = m_aTable.GetCurrentRow();
+ const sal_Int32 nCurrentCol = m_aTable.GetCurrentColumn();
+ css::uno::Reference< css::accessibility::XAccessible > xChild;
+ if (nCurrentRow > -1 && nCurrentCol > -1)
+ xChild = m_xTable->getAccessibleCellAt(nCurrentRow, nCurrentCol);
+
+ m_xTable->commitEvent(_nEventId, Any(xChild),_rOldValue);
+ }
+ else
+ m_xTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
+}
+
+// = AccessibleGridControlAccess
+
+
+AccessibleGridControlAccess::AccessibleGridControlAccess(
+ css::uno::Reference< css::accessibility::XAccessible > xParent, ::vcl::table::IAccessibleTable& rTable )
+ : m_xParent(std::move( xParent ))
+ , m_pTable( & rTable )
+{
+}
+
+
+AccessibleGridControlAccess::~AccessibleGridControlAccess()
+{
+}
+
+
+void AccessibleGridControlAccess::DisposeAccessImpl()
+{
+ SolarMutexGuard g;
+
+ m_pTable = nullptr;
+ if (m_xContext.is())
+ {
+ m_xContext->dispose();
+ m_xContext.clear();
+ }
+}
+
+
+css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL AccessibleGridControlAccess::getAccessibleContext()
+{
+ SolarMutexGuard g;
+
+ // if the context died meanwhile (we're no listener, so it won't tell us explicitly when this happens),
+ // then reset and re-create.
+ if ( m_xContext.is() && !m_xContext->isAlive() )
+ m_xContext = nullptr;
+
+ if (!m_xContext.is() && m_pTable)
+ m_xContext = new AccessibleGridControl(m_xParent, this, *m_pTable);
+
+ return m_xContext;
+}
+
+
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlBase.cxx b/accessibility/source/extended/AccessibleGridControlBase.cxx
new file mode 100644
index 000000000..6b7ce3fad
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlBase.cxx
@@ -0,0 +1,465 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleGridControlBase.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <utility>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/types.h>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <sal/log.hxx>
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+
+namespace accessibility {
+
+using namespace com::sun::star::accessibility::AccessibleStateType;
+
+
+AccessibleGridControlBase::AccessibleGridControlBase(
+ css::uno::Reference< css::accessibility::XAccessible > xParent,
+ ::vcl::table::IAccessibleTable& rTable,
+ ::vcl::table::AccessibleTableControlObjType eObjType ) :
+ AccessibleGridControlImplHelper( m_aMutex ),
+ m_xParent(std::move( xParent )),
+ m_aTable( rTable),
+ m_eObjType( eObjType ),
+ m_aClientId(0)
+{
+}
+
+AccessibleGridControlBase::~AccessibleGridControlBase()
+{
+ if( isAlive() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+}
+
+void SAL_CALL AccessibleGridControlBase::disposing()
+{
+ SolarMutexGuard g;
+
+ if ( getClientId( ) )
+ {
+ AccessibleEventNotifier::TClientId nId( getClientId( ) );
+ setClientId( 0 );
+ AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+ }
+
+ m_xParent = nullptr;
+ //m_aTable = NULL;
+}
+
+// css::accessibility::XAccessibleContext
+
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL AccessibleGridControlBase::getAccessibleParent()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return m_xParent;
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlBase::getAccessibleIndexInParent()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+
+ // -1 for child not found/no parent (according to specification)
+ sal_Int32 nRet = -1;
+
+ css::uno::Reference< uno::XInterface > xMeMyselfAndI( static_cast< css::accessibility::XAccessibleContext* >( this ), uno::UNO_QUERY );
+
+ // iterate over parent's children and search for this object
+ if( m_xParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ xParentContext( m_xParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ {
+ css::uno::Reference< uno::XInterface > xChild;
+
+ sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
+ for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild )
+ {
+ xChild.set(xParentContext->getAccessibleChild( nChild ), css::uno::UNO_QUERY);
+ if ( xMeMyselfAndI.get() == xChild.get() )
+ {
+ nRet = nChild;
+ break;
+ }
+ }
+ }
+ }
+ return nRet;
+}
+
+OUString SAL_CALL AccessibleGridControlBase::getAccessibleDescription()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return m_aTable.GetAccessibleObjectDescription(m_eObjType);
+}
+
+OUString SAL_CALL AccessibleGridControlBase::getAccessibleName()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return m_aTable.GetAccessibleObjectName(m_eObjType, 0, 0);
+}
+
+css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL
+AccessibleGridControlBase::getAccessibleRelationSet()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ // GridControl does not have relations.
+ return new utl::AccessibleRelationSetHelper;
+}
+
+css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL
+AccessibleGridControlBase::getAccessibleStateSet()
+{
+ SolarMutexGuard aSolarGuard;
+
+ // don't check whether alive -> StateSet may contain DEFUNC
+ return implCreateStateSetHelper();
+}
+
+lang::Locale SAL_CALL AccessibleGridControlBase::getLocale()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ if( m_xParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ xParentContext( m_xParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ return xParentContext->getLocale();
+ }
+ throw IllegalAccessibleComponentStateException();
+}
+
+// css::accessibility::XAccessibleComponent
+
+sal_Bool SAL_CALL AccessibleGridControlBase::containsPoint( const awt::Point& rPoint )
+{
+ return tools::Rectangle( Point(), getBoundingBox().GetSize() ).Contains( VCLPoint( rPoint ) );
+}
+
+awt::Rectangle SAL_CALL AccessibleGridControlBase::getBounds()
+{
+ return AWTRectangle( getBoundingBox() );
+}
+
+awt::Point SAL_CALL AccessibleGridControlBase::getLocation()
+{
+ return AWTPoint( getBoundingBox().TopLeft() );
+}
+
+awt::Point SAL_CALL AccessibleGridControlBase::getLocationOnScreen()
+{
+ return AWTPoint( getBoundingBoxOnScreen().TopLeft() );
+}
+
+awt::Size SAL_CALL AccessibleGridControlBase::getSize()
+{
+ return AWTSize( getBoundingBox().GetSize() );
+}
+
+// css::accessibility::XAccessibleEventBroadcaster
+
+void SAL_CALL AccessibleGridControlBase::addAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
+{
+ if ( _rxListener.is() )
+ {
+ SolarMutexGuard g;
+
+ if ( !getClientId( ) )
+ setClientId( AccessibleEventNotifier::registerClient( ) );
+
+ AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener );
+ }
+}
+
+void SAL_CALL AccessibleGridControlBase::removeAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
+{
+ if( !(_rxListener.is() && getClientId( )) )
+ return;
+
+ SolarMutexGuard g;
+
+ sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ AccessibleEventNotifier::TClientId nId( getClientId( ) );
+ setClientId( 0 );
+ AccessibleEventNotifier::revokeClient( nId );
+ }
+}
+
+// XTypeProvider
+
+Sequence< sal_Int8 > SAL_CALL AccessibleGridControlBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XServiceInfo
+
+sal_Bool SAL_CALL AccessibleGridControlBase::supportsService(
+ const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > SAL_CALL AccessibleGridControlBase::getSupportedServiceNames()
+{
+ return { "com.sun.star.accessibility.AccessibleContext" };
+}
+// internal virtual methods
+
+bool AccessibleGridControlBase::implIsShowing()
+{
+ bool bShowing = false;
+ if( m_xParent.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleComponent >
+ xParentComp( m_xParent->getAccessibleContext(), uno::UNO_QUERY );
+ if( xParentComp.is() )
+ bShowing = implGetBoundingBox().Overlaps(
+ VCLRectangle( xParentComp->getBounds() ) );
+ }
+ return bShowing;
+}
+
+rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleGridControlBase::implCreateStateSetHelper()
+{
+ rtl::Reference<::utl::AccessibleStateSetHelper>
+ pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with m_xParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ // GridControl fills StateSet with states depending on object type
+ m_aTable.FillAccessibleStateSet( *pStateSetHelper, getType() );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ return pStateSetHelper;
+}
+
+// internal helper methods
+
+bool AccessibleGridControlBase::isAlive() const
+{
+ ::osl::MutexGuard g(m_aMutex); // guards rBHelper members
+ return !rBHelper.bDisposed && !rBHelper.bInDispose;
+}
+
+void AccessibleGridControlBase::ensureIsAlive() const
+{
+ if( !isAlive() )
+ throw lang::DisposedException();
+}
+
+tools::Rectangle AccessibleGridControlBase::getBoundingBox()
+{
+ SolarMutexGuard aSolarGuard;
+ ensureIsAlive();
+ tools::Rectangle aRect = implGetBoundingBox();
+ if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
+ {
+ SAL_WARN( "accessibility", "rectangle doesn't exist" );
+ }
+ return aRect;
+}
+
+tools::Rectangle AccessibleGridControlBase::getBoundingBoxOnScreen()
+{
+ SolarMutexGuard aSolarGuard;
+ ensureIsAlive();
+ tools::Rectangle aRect = implGetBoundingBoxOnScreen();
+ if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
+ {
+ SAL_WARN( "accessibility", "rectangle doesn't exist" );
+ }
+ return aRect;
+}
+
+void AccessibleGridControlBase::commitEvent(
+ sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
+{
+ SolarMutexGuard g;
+
+ if ( !getClientId( ) )
+ // if we don't have a client id for the notifier, then we don't have listeners, then
+ // we don't need to notify anything
+ return;
+
+ // build an event object
+ AccessibleEventObject aEvent;
+ aEvent.Source = *this;
+ aEvent.EventId = _nEventId;
+ aEvent.OldValue = _rOldValue;
+ aEvent.NewValue = _rNewValue;
+
+ // let the notifier handle this event
+
+ AccessibleEventNotifier::addEvent( getClientId( ), aEvent );
+}
+
+sal_Int16 SAL_CALL AccessibleGridControlBase::getAccessibleRole()
+{
+ ensureIsAlive();
+ sal_Int16 nRole = AccessibleRole::UNKNOWN;
+ switch ( m_eObjType )
+ {
+ case TCTYPE_ROWHEADERCELL:
+ nRole = AccessibleRole::ROW_HEADER;
+ break;
+ case TCTYPE_COLUMNHEADERCELL:
+ nRole = AccessibleRole::COLUMN_HEADER;
+ break;
+ case TCTYPE_COLUMNHEADERBAR:
+ case TCTYPE_ROWHEADERBAR:
+ case TCTYPE_TABLE:
+ nRole = AccessibleRole::TABLE;
+ break;
+ case TCTYPE_TABLECELL:
+ nRole = AccessibleRole::TABLE_CELL;
+ break;
+ case TCTYPE_GRIDCONTROL:
+ nRole = AccessibleRole::PANEL;
+ break;
+ }
+ return nRole;
+}
+
+css::uno::Reference<css::accessibility::XAccessible > SAL_CALL AccessibleGridControlBase::getAccessibleAtPoint( const css::awt::Point& )
+{
+ return nullptr;
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlBase::getForeground( )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+
+ Color nColor;
+ vcl::Window* pInst = m_aTable.GetWindowInstance();
+ if ( pInst )
+ {
+ if ( pInst->IsControlForeground() )
+ nColor = pInst->GetControlForeground();
+ else
+ {
+ vcl::Font aFont;
+ if ( pInst->IsControlFont() )
+ aFont = pInst->GetControlFont();
+ else
+ aFont = pInst->GetFont();
+ nColor = aFont.GetColor();
+ }
+ }
+ return sal_Int32(nColor);
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlBase::getBackground( )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ Color nColor;
+ vcl::Window* pInst = m_aTable.GetWindowInstance();
+ if ( pInst )
+ {
+ if ( pInst->IsControlBackground() )
+ nColor = pInst->GetControlBackground();
+ else
+ nColor = pInst->GetBackground().GetColor();
+ }
+ return sal_Int32(nColor);
+}
+
+
+GridControlAccessibleElement::GridControlAccessibleElement( const css::uno::Reference< css::accessibility::XAccessible >& rxParent,
+ ::vcl::table::IAccessibleTable& rTable,
+ ::vcl::table::AccessibleTableControlObjType eObjType )
+ :AccessibleGridControlBase( rxParent, rTable, eObjType )
+{
+}
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base)
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base )
+
+// css::accessibility::XAccessible
+
+css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL GridControlAccessibleElement::getAccessibleContext()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return this;
+}
+
+GridControlAccessibleElement::~GridControlAccessibleElement( )
+{
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlHeader.cxx b/accessibility/source/extended/AccessibleGridControlHeader.cxx
new file mode 100644
index 000000000..d88b34218
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlHeader.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <extended/AccessibleGridControlHeader.hxx>
+#include <extended/AccessibleGridControlHeaderCell.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+
+namespace accessibility {
+
+
+AccessibleGridControlHeader::AccessibleGridControlHeader(
+ const Reference< XAccessible >& rxParent,
+ ::vcl::table::IAccessibleTable& rTable,
+ ::vcl::table::AccessibleTableControlObjType eObjType):
+ AccessibleGridControlTableBase( rxParent, rTable, eObjType )
+{
+ OSL_ENSURE( isRowBar() || isColumnBar(),
+ "extended/AccessibleGridControlHeaderBar - invalid object type" );
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleGridControlHeader::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ if (nChildIndex<0 || nChildIndex>=getAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+ ensureIsAlive();
+ Reference< XAccessible > xChild;
+ if(m_eObjType == vcl::table::TCTYPE_COLUMNHEADERBAR)
+ {
+ rtl::Reference<AccessibleGridControlHeaderCell> pColHeaderCell = new AccessibleGridControlHeaderCell(nChildIndex, this, m_aTable, vcl::table::TCTYPE_COLUMNHEADERCELL);
+ xChild = pColHeaderCell;
+ }
+ else if(m_eObjType == vcl::table::TCTYPE_ROWHEADERBAR)
+ {
+ rtl::Reference<AccessibleGridControlHeaderCell> pRowHeaderCell = new AccessibleGridControlHeaderCell(nChildIndex, this, m_aTable, vcl::table::TCTYPE_ROWHEADERCELL);
+ xChild = pRowHeaderCell;
+ }
+ return xChild;
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlHeader::getAccessibleIndexInParent()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ if(m_eObjType == vcl::table::TCTYPE_ROWHEADERBAR && m_aTable.HasColHeader())
+ return 1;
+ else
+ return 0;
+}
+
+// XAccessibleComponent -------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleGridControlHeader::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumnPos = 0;
+ bool bConverted = m_aTable.ConvertPointToCellAddress(nRow, nColumnPos, VCLPoint(rPoint));
+ return bConverted ? implGetChild( nRow, nColumnPos ) : Reference< XAccessible >();
+}
+
+void SAL_CALL AccessibleGridControlHeader::grabFocus()
+{
+ ensureIsAlive();
+ // focus on header not supported
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+OUString SAL_CALL AccessibleGridControlHeader::getAccessibleRowDescription( sal_Int32 nRow )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ return OUString(); // no headers in headers
+}
+
+OUString SAL_CALL AccessibleGridControlHeader::getAccessibleColumnDescription( sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidColumn( nColumn );
+ return OUString(); // no headers in headers
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleGridControlHeader::getAccessibleRowHeaders()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return nullptr; // no headers in headers
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleGridControlHeader::getAccessibleColumnHeaders()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return nullptr; // no headers in headers
+}
+//not selectable
+Sequence< sal_Int32 > SAL_CALL AccessibleGridControlHeader::getSelectedAccessibleRows()
+{
+ return {};
+}
+//columns aren't selectable
+Sequence< sal_Int32 > SAL_CALL AccessibleGridControlHeader::getSelectedAccessibleColumns()
+{
+ return {};
+}
+//row headers not selectable
+sal_Bool SAL_CALL AccessibleGridControlHeader::isAccessibleRowSelected( sal_Int32 /*nRow*/ )
+{
+ return false;
+}
+//columns aren't selectable
+sal_Bool SAL_CALL AccessibleGridControlHeader::isAccessibleColumnSelected( sal_Int32 )
+{
+ return false;
+}
+//not implemented
+Reference< XAccessible > SAL_CALL AccessibleGridControlHeader::getAccessibleCellAt(
+ sal_Int32 /*nRow*/, sal_Int32 /*nColumn*/ )
+{
+ return nullptr;
+}
+// not selectable
+sal_Bool SAL_CALL AccessibleGridControlHeader::isAccessibleSelected(
+ sal_Int32 /*nRow*/, sal_Int32 /*nColumn */)
+{
+ return false;
+}
+
+// XServiceInfo ---------------------------------------------------------------
+
+OUString SAL_CALL AccessibleGridControlHeader::getImplementationName()
+{
+ return "com.sun.star.accessibility.AccessibleGridControlHeader";
+}
+
+Sequence< sal_Int8 > SAL_CALL AccessibleGridControlHeader::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// internal virtual methods ---------------------------------------------------
+
+tools::Rectangle AccessibleGridControlHeader::implGetBoundingBox()
+{
+ vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( pParent ) );
+ tools::Rectangle aHeaderRect (m_aTable.calcHeaderRect(isColumnBar()));
+ if(isColumnBar())
+ return tools::Rectangle(aGridRect.TopLeft(), Size(aGridRect.getWidth(),aHeaderRect.getHeight()));
+ else
+ return tools::Rectangle(aGridRect.TopLeft(), Size(aHeaderRect.getWidth(),aGridRect.getHeight()));
+
+}
+
+tools::Rectangle AccessibleGridControlHeader::implGetBoundingBoxOnScreen()
+{
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( nullptr ) );
+ tools::Rectangle aHeaderRect (m_aTable.calcHeaderRect(isColumnBar()));
+ if(isColumnBar())
+ return tools::Rectangle(aGridRect.TopLeft(), Size(aGridRect.getWidth(),aHeaderRect.getHeight()));
+ else
+ return tools::Rectangle(aGridRect.TopLeft(), Size(aHeaderRect.getWidth(),aGridRect.getHeight()));
+}
+
+// internal helper methods ----------------------------------------------------
+Reference< XAccessible > AccessibleGridControlHeader::implGetChild(
+ sal_Int32 nRow, sal_uInt32 nColumnPos )
+{
+ Reference< XAccessible > xChild;
+ if(m_eObjType == vcl::table::TCTYPE_COLUMNHEADERBAR)
+ {
+ rtl::Reference<AccessibleGridControlHeaderCell> pColHeaderCell = new AccessibleGridControlHeaderCell(nColumnPos, this, m_aTable, vcl::table::TCTYPE_COLUMNHEADERCELL);
+ xChild = pColHeaderCell;
+ }
+ else if(m_eObjType == vcl::table::TCTYPE_ROWHEADERBAR)
+ {
+ rtl::Reference<AccessibleGridControlHeaderCell> pRowHeaderCell = new AccessibleGridControlHeaderCell(nRow, this, m_aTable, vcl::table::TCTYPE_ROWHEADERCELL);
+ xChild = pRowHeaderCell;
+ }
+ return xChild;
+}
+
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlHeaderCell.cxx b/accessibility/source/extended/AccessibleGridControlHeaderCell.cxx
new file mode 100644
index 000000000..72333d340
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlHeaderCell.cxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <extended/AccessibleGridControlHeaderCell.hxx>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+
+namespace accessibility
+{
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::uno;
+ using namespace ::vcl;
+ using namespace ::vcl::table;
+
+AccessibleGridControlHeaderCell::AccessibleGridControlHeaderCell(sal_Int32 _nColumnRowId,
+ const Reference< XAccessible >& rxParent,
+ IAccessibleTable& rTable,
+ AccessibleTableControlObjType eObjType)
+: AccessibleGridControlCell( rxParent, rTable, _nColumnRowId, 0, eObjType)
+, m_nColumnRowId(_nColumnRowId)
+{
+}
+/** Creates a new AccessibleStateSetHelper and fills it with states of the
+ current object.
+ @return
+ A filled AccessibleStateSetHelper.
+*/
+rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleGridControlHeaderCell::implCreateStateSetHelper()
+{
+ rtl::Reference<::utl::AccessibleStateSetHelper>
+ pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with mxParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+
+ if ( m_aTable.IsRowSelected(m_nColumnRowId) )
+ pStateSetHelper->AddState( AccessibleStateType::SELECTED );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+/** @return
+ The count of visible children.
+*/
+sal_Int32 SAL_CALL AccessibleGridControlHeaderCell::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+/** @return
+ The XAccessible interface of the specified child.
+*/
+Reference<XAccessible > SAL_CALL AccessibleGridControlHeaderCell::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+// XInterface -------------------------------------------------------------
+
+ /** Queries for a new interface. */
+ css::uno::Any SAL_CALL AccessibleGridControlHeaderCell::queryInterface( const css::uno::Type& rType )
+ {
+ Any aRet = AccessibleGridControlCell::queryInterface(rType);
+ return aRet;
+ }
+
+ /** Acquires the object (calls acquire() on base class). */
+ void SAL_CALL AccessibleGridControlHeaderCell::acquire() noexcept
+ {
+ AccessibleGridControlCell::acquire();
+ }
+
+ /** Releases the object (calls release() on base class). */
+ void SAL_CALL AccessibleGridControlHeaderCell::release() noexcept
+ {
+ AccessibleGridControlCell::release();
+ }
+ /** @return The XAccessibleContext interface of this object. */
+ Reference< css::accessibility::XAccessibleContext > SAL_CALL AccessibleGridControlHeaderCell::getAccessibleContext()
+ {
+ ensureIsAlive();
+ return this;
+ }
+
+
+/** Grabs the focus to the column header. */
+void SAL_CALL AccessibleGridControlHeaderCell::grabFocus()
+{
+}
+
+/** @return
+ The name of this class.
+*/
+OUString SAL_CALL AccessibleGridControlHeaderCell::getImplementationName()
+{
+ return "com.sun.star.accessibility.AccessibleGridControlHeaderCell";
+}
+
+tools::Rectangle AccessibleGridControlHeaderCell::implGetBoundingBox()
+{
+ vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( pParent ) );
+ sal_Int32 nIndex = getAccessibleIndexInParent();
+ tools::Rectangle aCellRect;
+ if(m_eObjType == TCTYPE_COLUMNHEADERCELL)
+ aCellRect = m_aTable.calcHeaderCellRect(true, nIndex);
+ else
+ aCellRect = m_aTable.calcHeaderCellRect(false, nIndex);
+ return tools::Rectangle(Point(aGridRect.Left()+aCellRect.Left(),aGridRect.Top()+aCellRect.Top()), aCellRect.GetSize());
+}
+
+
+tools::Rectangle AccessibleGridControlHeaderCell::implGetBoundingBoxOnScreen()
+{
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( nullptr ) );
+ sal_Int32 nIndex = getAccessibleIndexInParent();
+ tools::Rectangle aCellRect;
+ if(m_eObjType == TCTYPE_COLUMNHEADERCELL)
+ aCellRect = m_aTable.calcHeaderCellRect(true, nIndex);
+ else
+ aCellRect = m_aTable.calcHeaderCellRect(false, nIndex);
+ return tools::Rectangle(Point(aGridRect.Left()+aCellRect.Left(),aGridRect.Top()+aCellRect.Top()), aCellRect.GetSize());
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlHeaderCell::getAccessibleIndexInParent()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ sal_Int32 nIndex = m_nColumnRowId;
+ return nIndex;
+}
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlTable.cxx b/accessibility/source/extended/AccessibleGridControlTable.cxx
new file mode 100644
index 000000000..00788cdf2
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlTable.cxx
@@ -0,0 +1,388 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <extended/AccessibleGridControlTable.hxx>
+#include <extended/AccessibleGridControlTableCell.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/debug.hxx>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+
+namespace accessibility {
+
+
+AccessibleGridControlTable::AccessibleGridControlTable(
+ const Reference< XAccessible >& rxParent,
+ IAccessibleTable& rTable) :
+ AccessibleGridControlTableBase( rxParent, rTable, TCTYPE_TABLE )
+{
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleGridControlTable::getAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ sal_Int32 nCount = getAccessibleChildCount();
+ if(m_aCellVector.empty() || m_aCellVector.size() != static_cast<unsigned>(nCount))
+ {
+ m_aCellVector.resize(nCount);
+ }
+ if(!m_aCellVector[nChildIndex].is())
+ {
+ rtl::Reference<AccessibleGridControlTableCell> pCell = new AccessibleGridControlTableCell(this, m_aTable, nChildIndex/m_aTable.GetColumnCount(), nChildIndex%m_aTable.GetColumnCount());
+ m_aCellVector[nChildIndex] = pCell;
+ }
+ return m_aCellVector[nChildIndex];
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTable::getAccessibleIndexInParent()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ if(m_aTable.HasRowHeader() && m_aTable.HasColHeader())
+ return 0;
+ else if((!m_aTable.HasRowHeader() && m_aTable.HasColHeader()) || (m_aTable.HasRowHeader() && !m_aTable.HasColHeader()) )
+ return 1;
+ else
+ return 2;
+}
+
+// XAccessibleComponent -------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL
+AccessibleGridControlTable::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+
+ Reference< XAccessible > xChild;
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumnPos = 0;
+ if( m_aTable.ConvertPointToCellAddress( nRow, nColumnPos, VCLPoint( rPoint ) ) )
+ xChild = new AccessibleGridControlTableCell(this, m_aTable, nRow, nColumnPos);
+ return xChild;
+}
+
+void SAL_CALL AccessibleGridControlTable::grabFocus()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ m_aTable.GrabFocus();
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+OUString SAL_CALL AccessibleGridControlTable::getAccessibleRowDescription( sal_Int32 nRow )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ return "row description";
+}
+
+OUString SAL_CALL AccessibleGridControlTable::getAccessibleColumnDescription( sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidColumn( nColumn );
+ return "col description";
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleGridControlTable::getAccessibleRowHeaders()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ if(m_aTable.HasColHeader())
+ return implGetHeaderBar( 1 );
+ else
+ return implGetHeaderBar( 0 );
+}
+
+Reference< XAccessibleTable > SAL_CALL AccessibleGridControlTable::getAccessibleColumnHeaders()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return implGetHeaderBar( 0 );
+}
+
+Sequence< sal_Int32 > SAL_CALL AccessibleGridControlTable::getSelectedAccessibleRows()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ Sequence< sal_Int32 > aSelSeq;
+ implGetSelectedRows( aSelSeq );
+ return aSelSeq;
+}
+
+//columns aren't selectable
+Sequence< sal_Int32 > SAL_CALL AccessibleGridControlTable::getSelectedAccessibleColumns()
+{
+ return {};
+}
+
+sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleRowSelected( sal_Int32 nRow )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidRow( nRow );
+ Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
+ return comphelper::findValue(selectedRows, nRow) != -1;
+}
+
+//columns aren't selectable
+sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleColumnSelected( sal_Int32 )
+{
+ return false;
+}
+
+Reference< XAccessible > SAL_CALL AccessibleGridControlTable::getAccessibleCellAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ sal_Int32 nChildIndex = nRow*m_aTable.GetColumnCount() + nColumn;
+ return getAccessibleChild(nChildIndex);
+}
+
+sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ //selection of single cells not possible, so if row is selected, the cell will be selected too
+ return isAccessibleRowSelected(nRow);
+}
+void SAL_CALL AccessibleGridControlTable::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ sal_Int32 nColumns = m_aTable.GetColumnCount();
+ sal_Int32 nRow = nChildIndex / nColumns;
+ m_aTable.SelectRow( nRow, true );
+}
+sal_Bool SAL_CALL AccessibleGridControlTable::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ sal_Int32 nColumns = m_aTable.GetColumnCount();
+ sal_Int32 nRow = nChildIndex / nColumns;
+ return isAccessibleRowSelected(nRow);
+}
+void SAL_CALL AccessibleGridControlTable::clearAccessibleSelection()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ m_aTable.SelectAllRows( false );
+}
+void SAL_CALL AccessibleGridControlTable::selectAllAccessibleChildren()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
+ auto selectedRowsRange = asNonConstRange(selectedRows);
+ for(tools::Long i=0; i<m_aTable.GetRowCount(); i++)
+ selectedRowsRange[i]=i;
+}
+sal_Int32 SAL_CALL AccessibleGridControlTable::getSelectedAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ Sequence< sal_Int32 > selectedRows = getSelectedAccessibleRows();
+ sal_Int32 nColumns = m_aTable.GetColumnCount();
+ return selectedRows.getLength()*nColumns;
+}
+Reference< XAccessible > SAL_CALL
+AccessibleGridControlTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ if(isAccessibleChildSelected(nSelectedChildIndex))
+ return getAccessibleChild(nSelectedChildIndex);
+ else
+ return nullptr;
+}
+//not implemented yet, because only row selection possible
+void SAL_CALL AccessibleGridControlTable::deselectAccessibleChild(
+ sal_Int32 )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+}
+// XInterface -----------------------------------------------------------------
+
+Any SAL_CALL AccessibleGridControlTable::queryInterface( const uno::Type& rType )
+{
+ Any aAny( AccessibleGridControlTableBase::queryInterface( rType ) );
+ return aAny.hasValue() ?
+ aAny : AccessibleGridControlTableSelectionImplHelper::queryInterface( rType );
+}
+
+void SAL_CALL AccessibleGridControlTable::acquire() noexcept
+{
+ AccessibleGridControlTableBase::acquire();
+}
+
+void SAL_CALL AccessibleGridControlTable::release() noexcept
+{
+ AccessibleGridControlTableBase::release();
+}
+// XServiceInfo ---------------------------------------------------------------
+
+OUString SAL_CALL AccessibleGridControlTable::getImplementationName()
+{
+ return "com.sun.star.accessibility.AccessibleGridControlTable";
+}
+
+void AccessibleGridControlTable::dispose()
+{
+ for (rtl::Reference<AccessibleGridControlTableCell>& rxCell : m_aCellVector)
+ {
+ if (rxCell.is())
+ {
+ rxCell->dispose();
+ rxCell.clear();
+ }
+ }
+
+ AccessibleGridControlTableBase::dispose();
+}
+
+void AccessibleGridControlTable::commitEvent(sal_Int16 nEventId, const css::uno::Any& rNewValue,
+ const css::uno::Any& rOldValue)
+{
+ if (nEventId == AccessibleEventId::TABLE_MODEL_CHANGED)
+ {
+ AccessibleTableModelChange aChange;
+ if (rNewValue >>= aChange)
+ {
+ assert(aChange.Type != AccessibleTableModelChangeType::COLUMNS_REMOVED);
+
+ if (aChange.Type == AccessibleTableModelChangeType::ROWS_REMOVED)
+ {
+ int nColCount = m_aTable.GetColumnCount();
+ // check valid index - entries are inserted lazily
+ size_t const nStart = nColCount * aChange.FirstRow;
+ size_t const nEnd = nColCount * aChange.LastRow;
+ if (nStart < m_aCellVector.size())
+ {
+ m_aCellVector.erase(
+ m_aCellVector.begin() + nStart,
+ m_aCellVector.begin() + std::min(m_aCellVector.size(), nEnd));
+ }
+ }
+ }
+ }
+
+ AccessibleGridControlBase::commitEvent(nEventId, rNewValue, rOldValue);
+}
+
+// internal virtual methods ---------------------------------------------------
+
+tools::Rectangle AccessibleGridControlTable::implGetBoundingBox()
+{
+ vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( pParent ));
+ tools::Rectangle aTableRect( m_aTable.calcTableRect() );
+ tools::Long nX = aGridRect.Left() + aTableRect.Left();
+ tools::Long nY = aGridRect.Top() + aTableRect.Top();
+ tools::Long nWidth = aGridRect.GetSize().Width()-aTableRect.Left();
+ tools::Long nHeight = aGridRect.GetSize().Height()-aTableRect.Top();
+ tools::Rectangle aTable( Point( nX, nY ), Size( nWidth, nHeight ));
+ return aTable;
+}
+
+tools::Rectangle AccessibleGridControlTable::implGetBoundingBoxOnScreen()
+{
+ tools::Rectangle aGridRect( m_aTable.GetWindowExtentsRelative( nullptr ));
+ tools::Rectangle aTableRect( m_aTable.calcTableRect() );
+ tools::Long nX = aGridRect.Left() + aTableRect.Left();
+ tools::Long nY = aGridRect.Top() + aTableRect.Top();
+ tools::Long nWidth = aGridRect.GetSize().Width()-aTableRect.Left();
+ tools::Long nHeight = aGridRect.GetSize().Height()-aTableRect.Top();
+ tools::Rectangle aTable( Point( nX, nY ), Size( nWidth, nHeight ));
+ return aTable;
+}
+// internal helper methods ----------------------------------------------------
+Reference< XAccessibleTable > AccessibleGridControlTable::implGetHeaderBar(
+ sal_Int32 nChildIndex )
+{
+ Reference< XAccessible > xRet;
+ Reference< XAccessibleContext > xContext( m_xParent, uno::UNO_QUERY );
+ if( xContext.is() )
+ {
+ try
+ {
+ xRet = xContext->getAccessibleChild( nChildIndex );
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ OSL_FAIL( "implGetHeaderBar - wrong child index" );
+ }
+ // RuntimeException goes to caller
+ }
+ return Reference< XAccessibleTable >( xRet, uno::UNO_QUERY );
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlTableBase.cxx b/accessibility/source/extended/AccessibleGridControlTableBase.cxx
new file mode 100644
index 000000000..7ed42bc6b
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlTableBase.cxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <extended/AccessibleGridControlTableBase.hxx>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/sequence.hxx>
+
+using css::uno::Reference;
+using css::uno::Sequence;
+using css::uno::Any;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+
+namespace accessibility {
+
+
+AccessibleGridControlTableBase::AccessibleGridControlTableBase(
+ const Reference< XAccessible >& rxParent,
+ IAccessibleTable& rTable,
+ AccessibleTableControlObjType eObjType ) :
+ GridControlAccessibleElement( rxParent, rTable, eObjType )
+{
+}
+
+// XAccessibleContext ---------------------------------------------------------
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ sal_Int32 nChildren = 0;
+ if(m_eObjType == TCTYPE_ROWHEADERBAR)
+ nChildren = m_aTable.GetRowCount();
+ else if(m_eObjType == TCTYPE_TABLE)
+ nChildren = m_aTable.GetRowCount()*m_aTable.GetColumnCount();
+ else if(m_eObjType == TCTYPE_COLUMNHEADERBAR)
+ nChildren = m_aTable.GetColumnCount();
+ return nChildren;
+}
+
+sal_Int16 SAL_CALL AccessibleGridControlTableBase::getAccessibleRole()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return AccessibleRole::TABLE;
+}
+
+// XAccessibleTable -----------------------------------------------------------
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleRowCount()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ return m_aTable.GetRowCount();
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleColumnCount()
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ return m_aTable.GetColumnCount();
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return 1; // merged cells not supported
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return 1; // merged cells not supported
+}
+
+Reference< XAccessible > SAL_CALL AccessibleGridControlTableBase::getAccessibleCaption()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return nullptr; // not supported
+}
+
+Reference< XAccessible > SAL_CALL AccessibleGridControlTableBase::getAccessibleSummary()
+{
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return nullptr; // not supported
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidAddress( nRow, nColumn );
+ return nRow * m_aTable.GetColumnCount() + nColumn;
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleRow( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ return implGetRow( nChildIndex );
+}
+
+sal_Int32 SAL_CALL AccessibleGridControlTableBase::getAccessibleColumn( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ ensureIsValidIndex( nChildIndex );
+ return implGetColumn( nChildIndex );
+}
+
+// XInterface -----------------------------------------------------------------
+
+Any SAL_CALL AccessibleGridControlTableBase::queryInterface( const uno::Type& rType )
+{
+ Any aAny( GridControlAccessibleElement::queryInterface( rType ) );
+ return aAny.hasValue() ?
+ aAny : AccessibleGridControlTableImplHelper::queryInterface( rType );
+}
+
+void SAL_CALL AccessibleGridControlTableBase::acquire() noexcept
+{
+ GridControlAccessibleElement::acquire();
+}
+
+void SAL_CALL AccessibleGridControlTableBase::release() noexcept
+{
+ GridControlAccessibleElement::release();
+}
+
+// XTypeProvider --------------------------------------------------------------
+
+Sequence< uno::Type > SAL_CALL AccessibleGridControlTableBase::getTypes()
+{
+ return ::comphelper::concatSequences(
+ GridControlAccessibleElement::getTypes(),
+ AccessibleGridControlTableImplHelper::getTypes() );
+}
+
+Sequence< sal_Int8 > SAL_CALL AccessibleGridControlTableBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// internal helper methods ----------------------------------------------------
+
+sal_Int32 AccessibleGridControlTableBase::implGetRow( sal_Int32 nChildIndex ) const
+{
+ sal_Int32 nColumns = m_aTable.GetColumnCount();
+ return nColumns ? (nChildIndex / nColumns) : 0;
+}
+
+sal_Int32 AccessibleGridControlTableBase::implGetColumn( sal_Int32 nChildIndex ) const
+{
+ sal_Int32 nColumns = m_aTable.GetColumnCount();
+ return nColumns ? (nChildIndex % nColumns) : 0;
+}
+
+void AccessibleGridControlTableBase::implGetSelectedRows( Sequence< sal_Int32 >& rSeq )
+{
+ sal_Int32 const selectionCount( m_aTable.GetSelectedRowCount() );
+ rSeq.realloc( selectionCount );
+ auto pSeq = rSeq.getArray();
+ for ( sal_Int32 i=0; i<selectionCount; ++i )
+ pSeq[i] = m_aTable.GetSelectedRowIndex(i);
+}
+
+void AccessibleGridControlTableBase::ensureIsValidRow( sal_Int32 nRow )
+{
+ if( nRow >= m_aTable.GetRowCount() )
+ throw lang::IndexOutOfBoundsException( "row index is invalid", *this );
+}
+
+void AccessibleGridControlTableBase::ensureIsValidColumn( sal_Int32 nColumn )
+{
+ if( nColumn >= m_aTable.GetColumnCount() )
+ throw lang::IndexOutOfBoundsException( "column index is invalid", *this );
+}
+
+void AccessibleGridControlTableBase::ensureIsValidAddress(
+ sal_Int32 nRow, sal_Int32 nColumn )
+{
+ ensureIsValidRow( nRow );
+ ensureIsValidColumn( nColumn );
+}
+
+void AccessibleGridControlTableBase::ensureIsValidIndex( sal_Int32 nChildIndex )
+{
+ if( nChildIndex >= m_aTable.GetRowCount()*m_aTable.GetColumnCount() )
+ throw lang::IndexOutOfBoundsException( "child index is invalid", *this );
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleGridControlTableCell.cxx b/accessibility/source/extended/AccessibleGridControlTableCell.cxx
new file mode 100644
index 000000000..20bf37698
--- /dev/null
+++ b/accessibility/source/extended/AccessibleGridControlTableCell.cxx
@@ -0,0 +1,355 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/AccessibleGridControlTableCell.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/accessibletable.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/gen.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+namespace accessibility
+{
+ namespace
+ {
+ // FIXME this is a copy'n'paste from
+ // source/extended/AccessibleBrowseBoxTableCell.cxx, get rid of that...
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkIndex_Impl( sal_Int32 _nIndex, const OUString& _sText )
+ {
+ if ( _nIndex >= _sText.getLength() )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+ }
+ using namespace ::com::sun::star::lang;
+ using namespace utl;
+ using namespace comphelper;
+ using namespace ::com::sun::star::uno;
+ using ::com::sun::star::accessibility::XAccessible;
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::vcl;
+ using namespace ::vcl::table;
+
+
+ // = AccessibleGridControlCell
+
+
+ AccessibleGridControlCell::AccessibleGridControlCell(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, ::vcl::table::IAccessibleTable& _rTable,
+ sal_Int32 _nRowPos, sal_uInt16 _nColPos, ::vcl::table::AccessibleTableControlObjType _eType )
+ :AccessibleGridControlBase( _rxParent, _rTable, _eType )
+ ,m_nRowPos( _nRowPos )
+ ,m_nColPos( _nColPos )
+ {
+ }
+
+ void SAL_CALL AccessibleGridControlCell::grabFocus()
+ {
+ SolarMutexGuard aSolarGuard;
+
+ m_aTable.GoToCell( m_nColPos, m_nRowPos );
+ }
+
+ OUString SAL_CALL AccessibleGridControlCell::getAccessibleName()
+ {
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+
+ OUString sAccName;
+ if (m_eObjType == TCTYPE_TABLECELL)
+ sAccName = m_aTable.GetAccessibleObjectName(TCTYPE_TABLECELL, m_nRowPos, m_nColPos);
+ else if (m_eObjType == TCTYPE_ROWHEADERCELL)
+ sAccName = m_aTable.GetAccessibleObjectName(TCTYPE_ROWHEADERCELL, m_nRowPos, 0);
+ else if (m_eObjType == TCTYPE_COLUMNHEADERCELL)
+ sAccName = m_aTable.GetAccessibleObjectName(TCTYPE_COLUMNHEADERCELL, 0, m_nRowPos);
+ else
+ assert(false && "Unhandled table cell type");
+ return sAccName;
+ }
+
+ // implementation of a table cell
+ OUString AccessibleGridControlTableCell::implGetText()
+ {
+ ensureIsAlive();
+ return m_aTable.GetAccessibleCellText( getRowPos(), getColumnPos() );
+ }
+
+ css::lang::Locale AccessibleGridControlTableCell::implGetLocale()
+ {
+ ensureIsAlive();
+ return m_aTable.GetAccessible()->getAccessibleContext()->getLocale();
+ }
+
+ void AccessibleGridControlTableCell::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+ {
+ nStartIndex = 0;
+ nEndIndex = 0;
+ }
+
+ AccessibleGridControlTableCell::AccessibleGridControlTableCell(const css::uno::Reference<XAccessible >& _rxParent,
+ ::vcl::table::IAccessibleTable& _rTable,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos)
+ :AccessibleGridControlCell( _rxParent, _rTable, _nRowPos, _nColPos, TCTYPE_TABLECELL )
+ {
+ }
+
+ // XInterface
+
+ /** Queries for a new interface. */
+ css::uno::Any SAL_CALL AccessibleGridControlTableCell::queryInterface(
+ const css::uno::Type& rType )
+ {
+ Any aRet = AccessibleGridControlCell::queryInterface(rType);
+ if ( !aRet.hasValue() )
+ aRet = AccessibleTextHelper_BASE::queryInterface(rType);
+ return aRet;
+ }
+
+ /** Acquires the object (calls acquire() on base class). */
+ void SAL_CALL AccessibleGridControlTableCell::acquire() noexcept
+ {
+ AccessibleGridControlCell::acquire();
+ }
+
+ /** Releases the object (calls release() on base class). */
+ void SAL_CALL AccessibleGridControlTableCell::release() noexcept
+ {
+ AccessibleGridControlCell::release();
+ }
+
+ css::awt::Rectangle SAL_CALL AccessibleGridControlTableCell::getCharacterBounds( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return AWTRectangle( m_aTable.GetFieldCharacterBounds( getRowPos(), getColumnPos(), nIndex ) );
+ }
+
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getIndexAtPoint( const css::awt::Point& _aPoint )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+
+ return m_aTable.GetFieldIndexAtPoint( getRowPos(), getColumnPos(), VCLPoint( _aPoint ) );
+ }
+
+ /** @return
+ The name of this class.
+ */
+ OUString SAL_CALL AccessibleGridControlTableCell::getImplementationName()
+ {
+ return "com.sun.star.accessibility.AccessibleGridControlTableCell";
+ }
+
+ /** @return The count of visible children. */
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getAccessibleChildCount()
+ {
+ return 0;
+ }
+
+ /** @return The css::accessibility::XAccessible interface of the specified child. */
+ css::uno::Reference< css::accessibility::XAccessible > SAL_CALL AccessibleGridControlTableCell::getAccessibleChild( sal_Int32 )
+ {
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+ /** Creates a new AccessibleStateSetHelper and fills it with states of the
+ current object.
+ @return
+ A filled AccessibleStateSetHelper.
+ */
+ rtl::Reference<::utl::AccessibleStateSetHelper> AccessibleGridControlTableCell::implCreateStateSetHelper()
+ {
+ rtl::Reference<::utl::AccessibleStateSetHelper> pStateSetHelper = new ::utl::AccessibleStateSetHelper;
+
+ if( isAlive() )
+ {
+ // SHOWING done with mxParent
+ if( implIsShowing() )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+
+ m_aTable.FillAccessibleStateSetForCell( *pStateSetHelper, getRowPos(), static_cast< sal_uInt16 >( getColumnPos() ) );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+ }
+
+
+ // css::accessibility::XAccessible
+
+ /** @return The css::accessibility::XAccessibleContext interface of this object. */
+ css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL AccessibleGridControlTableCell::getAccessibleContext()
+ {
+ SolarMutexGuard g;
+
+ ensureIsAlive();
+ return this;
+ }
+
+ // css::accessibility::XAccessibleContext
+
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getAccessibleIndexInParent()
+ {
+ SolarMutexGuard aSolarGuard;
+
+ ensureIsAlive();
+
+ return ( getRowPos() * m_aTable.GetColumnCount() ) + getColumnPos();
+ }
+
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getCaretPosition( )
+ {
+ return -1;
+ }
+ sal_Bool SAL_CALL AccessibleGridControlTableCell::setCaretPosition ( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ sal_Unicode SAL_CALL AccessibleGridControlTableCell::getCharacter( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+ }
+ css::uno::Sequence< css::beans::PropertyValue > SAL_CALL AccessibleGridControlTableCell::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return css::uno::Sequence< css::beans::PropertyValue >();
+ }
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getCharacterCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return implGetText().getLength();
+ }
+
+ OUString SAL_CALL AccessibleGridControlTableCell::getSelectedText( )
+ {
+ return OUString();
+ }
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getSelectionStart( )
+ {
+ return 0;
+ }
+ sal_Int32 SAL_CALL AccessibleGridControlTableCell::getSelectionEnd( )
+ {
+ return 0;
+ }
+ sal_Bool SAL_CALL AccessibleGridControlTableCell::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ OUString SAL_CALL AccessibleGridControlTableCell::getText( )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return implGetText( );
+ }
+ OUString SAL_CALL AccessibleGridControlTableCell::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleGridControlTableCell::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleGridControlTableCell::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleGridControlTableCell::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
+ }
+ sal_Bool SAL_CALL AccessibleGridControlTableCell::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+
+ OUString sText = implGetText();
+ checkIndex_Impl( nStartIndex, sText );
+ checkIndex_Impl( nEndIndex, sText );
+
+ //!!! don't know how to put a string into the clipboard
+ return false;
+ }
+ sal_Bool SAL_CALL AccessibleGridControlTableCell::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+ {
+ return false;
+ }
+
+ tools::Rectangle AccessibleGridControlTableCell::implGetBoundingBox()
+ {
+ vcl::Window* pParent = m_aTable.GetAccessibleParentWindow();
+ DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" );
+ tools::Rectangle aGridRect = m_aTable.GetWindowExtentsRelative( pParent );
+ sal_Int32 nIndex = getAccessibleIndexInParent();
+ tools::Rectangle aCellRect = m_aTable.calcCellRect(nIndex%m_aTable.GetColumnCount(), nIndex/m_aTable.GetColumnCount());
+ tools::Long nX = aGridRect.Left() + aCellRect.Left();
+ tools::Long nY = aGridRect.Top() + aCellRect.Top();
+ tools::Rectangle aCell( Point( nX, nY ), aCellRect.GetSize());
+ return aCell;
+ }
+
+ tools::Rectangle AccessibleGridControlTableCell::implGetBoundingBoxOnScreen()
+ {
+ tools::Rectangle aGridRect = m_aTable.GetWindowExtentsRelative( nullptr );
+ sal_Int32 nIndex = getAccessibleIndexInParent();
+ tools::Rectangle aCellRect = m_aTable.calcCellRect(nIndex%m_aTable.GetColumnCount(), nIndex/m_aTable.GetColumnCount());
+ tools::Long nX = aGridRect.Left() + aCellRect.Left();
+ tools::Long nY = aGridRect.Top() + aCellRect.Top();
+ tools::Rectangle aCell( Point( nX, nY ), aCellRect.GetSize());
+ return aCell;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/AccessibleIconView.cxx b/accessibility/source/extended/AccessibleIconView.cxx
new file mode 100644
index 000000000..6bc5c99e9
--- /dev/null
+++ b/accessibility/source/extended/AccessibleIconView.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+
+#include <toolkit/helper/convert.hxx>
+#include <vcl/event.hxx>
+
+#include <extended/AccessibleIconView.hxx>
+
+namespace accessibility
+{
+AccessibleIconView::AccessibleIconView(
+ SvTreeListBox const& _rListBox,
+ const css::uno::Reference<css::accessibility::XAccessible>& _xParent)
+ : AccessibleListBox(_rListBox, _xParent)
+{
+}
+
+void AccessibleIconView::ProcessWindowEvent(const VclWindowEvent& rVclWindowEvent)
+{
+ if (!isAlive())
+ return;
+
+ switch (rVclWindowEvent.GetId())
+ {
+ case VclEventId::WindowMouseMove:
+ if (MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData()))
+ {
+ if (auto xChild = getAccessibleAtPoint(AWTPoint(pMouseEvt->GetPosPixel())))
+ {
+ // Allow announcing the element on mouse hover
+ css::uno::Any aNew(xChild);
+ NotifyAccessibleEvent(
+ css::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, {}, aNew);
+ }
+ }
+ break;
+ default:
+ AccessibleListBox::ProcessWindowEvent(rVclWindowEvent);
+ }
+}
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/accessibility/source/extended/accessiblebrowseboxcell.cxx b/accessibility/source/extended/accessiblebrowseboxcell.cxx
new file mode 100644
index 000000000..4996b7eed
--- /dev/null
+++ b/accessibility/source/extended/accessiblebrowseboxcell.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <vcl/accessibletableprovider.hxx>
+#include <extended/accessiblebrowseboxcell.hxx>
+
+namespace accessibility
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::accessibility;
+
+ // AccessibleBrowseBoxCell
+ AccessibleBrowseBoxCell::AccessibleBrowseBoxCell(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, ::vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowPos, sal_uInt16 _nColPos, AccessibleBrowseBoxObjType _eType )
+ :AccessibleBrowseBoxBase( _rxParent, _rBrowseBox, _xFocusWindow, _eType )
+ ,m_nRowPos( _nRowPos )
+ ,m_nColPos( _nColPos )
+ {
+ // set accessible name here, because for that we need the position of the cell
+ // and so the base class isn't capable of doing this
+ sal_Int32 nPos = _nRowPos * _rBrowseBox.GetColumnCount() + _nColPos;
+ OUString aAccName = _rBrowseBox.GetAccessibleObjectName( AccessibleBrowseBoxObjType::TableCell, nPos );
+ implSetName( aAccName );
+ }
+
+ AccessibleBrowseBoxCell::~AccessibleBrowseBoxCell()
+ {
+ }
+
+ void SAL_CALL AccessibleBrowseBoxCell::grabFocus()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ mpBrowseBox->GoToCell( m_nRowPos, m_nColPos );
+ }
+
+ ::tools::Rectangle AccessibleBrowseBoxCell::implGetBoundingBox()
+ {
+ return mpBrowseBox->GetFieldRectPixelAbs( m_nRowPos, m_nColPos, false, false );
+ }
+
+ ::tools::Rectangle AccessibleBrowseBoxCell::implGetBoundingBoxOnScreen()
+ {
+ return mpBrowseBox->GetFieldRectPixelAbs( m_nRowPos, m_nColPos, false );
+ }
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibleeditbrowseboxcell.cxx b/accessibility/source/extended/accessibleeditbrowseboxcell.cxx
new file mode 100644
index 000000000..54f069673
--- /dev/null
+++ b/accessibility/source/extended/accessibleeditbrowseboxcell.cxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <extended/accessibleeditbrowseboxcell.hxx>
+#include <comphelper/processfactory.hxx>
+#include <utility>
+#include <tools/diagnose_ex.h>
+
+namespace accessibility
+{
+ using namespace com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::awt;
+ using namespace ::comphelper;
+
+ EditBrowseBoxTableCell::EditBrowseBoxTableCell(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxOwningAccessible,
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& _xControlChild,
+ ::vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos)
+ :AccessibleBrowseBoxCell( _rxParent, _rBrowseBox, _xFocusWindow, _nRowPos, _nColPos )
+ ,OAccessibleContextWrapperHelper( ::comphelper::getProcessComponentContext(), rBHelper, _xControlChild, _rxOwningAccessible, _rxParent )
+ {
+ aggregateProxy( m_refCount, *this );
+ }
+
+ EditBrowseBoxTableCell::~EditBrowseBoxTableCell()
+ {
+ if ( !rBHelper.bDisposed )
+ {
+ acquire(); // to prevent duplicate dtor calls
+ dispose();
+ }
+ }
+
+ OUString SAL_CALL EditBrowseBoxTableCell::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.TableCellProxy";
+ }
+
+ IMPLEMENT_FORWARD_XINTERFACE2( EditBrowseBoxTableCell, AccessibleBrowseBoxCell, OAccessibleContextWrapperHelper )
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( EditBrowseBoxTableCell, AccessibleBrowseBoxCell, OAccessibleContextWrapperHelper )
+
+ void EditBrowseBoxTableCell::notifyTranslatedEvent( const AccessibleEventObject& _rEvent )
+ {
+ commitEvent( _rEvent.EventId, _rEvent.NewValue, _rEvent.OldValue );
+ }
+
+ // css::accessibility::XAccessibleComponent
+ sal_Int32 SAL_CALL EditBrowseBoxTableCell::getForeground( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ css::uno::Reference< css::accessibility::XAccessibleComponent > xAccComp( m_xInnerContext, UNO_QUERY );
+ if ( xAccComp.is() )
+ return xAccComp->getForeground();
+ return 0;
+ }
+
+ sal_Int32 SAL_CALL EditBrowseBoxTableCell::getBackground( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ css::uno::Reference< css::accessibility::XAccessibleComponent > xAccComp( m_xInnerContext, UNO_QUERY );
+ if ( xAccComp.is() )
+ return xAccComp->getBackground();
+ return 0;
+ }
+
+ css::uno::Reference< css::accessibility::XAccessible > SAL_CALL EditBrowseBoxTableCell::getAccessibleParent( )
+ {
+ return m_xParentAccessible;
+ }
+
+ OUString SAL_CALL EditBrowseBoxTableCell::getAccessibleDescription()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return m_xInnerContext->getAccessibleDescription();
+ }
+
+ OUString SAL_CALL EditBrowseBoxTableCell::getAccessibleName()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return AccResId(RID_STR_ACC_COLUMN_NUM).replaceAll("%COLUMNNUMBER", OUString::number(getColumnPos()-1)) + ", "
+ + AccResId(RID_STR_ACC_ROW_NUM).replaceAll("%ROWNUMBER", OUString::number(getRowPos()));
+ }
+
+ css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL EditBrowseBoxTableCell::getAccessibleRelationSet()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return baseGetAccessibleRelationSet( );
+ }
+
+ css::uno::Reference<css::accessibility::XAccessibleStateSet > SAL_CALL EditBrowseBoxTableCell::getAccessibleStateSet()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return m_xInnerContext->getAccessibleStateSet();
+ // TODO: shouldn't we add an ACTIVE here? Isn't the EditBrowseBoxTableCell always ACTIVE?
+ }
+
+ sal_Int32 SAL_CALL EditBrowseBoxTableCell::getAccessibleChildCount( )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return baseGetAccessibleChildCount();
+ }
+
+ css::uno::Reference< css::accessibility::XAccessible > SAL_CALL EditBrowseBoxTableCell::getAccessibleChild( sal_Int32 i )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return baseGetAccessibleChild( i );
+ }
+
+ sal_Int16 SAL_CALL EditBrowseBoxTableCell::getAccessibleRole()
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ return m_xInnerContext->getAccessibleRole( );
+ }
+
+ void SAL_CALL EditBrowseBoxTableCell::dispose()
+ {
+ // simply disambiguate. Note that the OComponentHelper base in AccessibleBrowseBoxCell
+ // will call our "disposing()", which will call "dispose()" on the OAccessibleContextWrapperHelper
+ // so there is no need to do this here.
+ AccessibleBrowseBoxCell::dispose();
+ }
+
+ void SAL_CALL EditBrowseBoxTableCell::disposing( const css::lang::EventObject& _rSource )
+ {
+ AccessibleBrowseBoxCell::disposing( _rSource );
+ OAccessibleContextWrapperHelper::disposing( _rSource );
+ }
+
+ void SAL_CALL EditBrowseBoxTableCell::disposing()
+ {
+ SolarMethodGuard aGuard(getMutex());
+
+ OAccessibleContextWrapperHelper::dispose();
+ // TODO: do we need to dispose our inner object? The base class does this, but is it a good idea?
+ AccessibleBrowseBoxCell::disposing();
+ }
+
+ // EditBrowseBoxTableCell
+ EditBrowseBoxTableCellAccess::EditBrowseBoxTableCellAccess(
+ css::uno::Reference< css::accessibility::XAccessible > _xParent, css::uno::Reference< css::accessibility::XAccessible > _xControlAccessible,
+ css::uno::Reference< css::awt::XWindow > _xFocusWindow,
+ ::vcl::IAccessibleTableProvider& _rBrowseBox, sal_Int32 _nRowPos, sal_uInt16 _nColPos )
+ :m_xParent(std::move( _xParent ))
+ ,m_xControlAccessible(std::move( _xControlAccessible ))
+ ,m_xFocusWindow(std::move( _xFocusWindow ))
+ ,m_pBrowseBox( &_rBrowseBox )
+ ,m_nRowPos( _nRowPos )
+ ,m_nColPos( _nColPos )
+ {
+ }
+
+ EditBrowseBoxTableCellAccess::~EditBrowseBoxTableCellAccess( )
+ {
+ }
+
+ css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL EditBrowseBoxTableCellAccess::getAccessibleContext( )
+ {
+ if ( !m_pBrowseBox || !m_xControlAccessible.is() )
+ throw DisposedException();
+ css::uno::Reference< css::accessibility::XAccessibleContext > xMyContext( m_aContext );
+ if ( !xMyContext.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext > xInnerContext = m_xControlAccessible->getAccessibleContext();
+ css::uno::Reference< css::accessibility::XAccessible > xMe( this );
+
+ xMyContext = new EditBrowseBoxTableCell( xMe, m_xParent, xInnerContext, *m_pBrowseBox, m_xFocusWindow, m_nRowPos, m_nColPos );
+ m_aContext = xMyContext;
+ }
+ return xMyContext;
+ }
+
+ void EditBrowseBoxTableCellAccess::disposing(std::unique_lock<std::mutex>&)
+ {
+ // dispose our context, if it still alive
+ css::uno::Reference< XComponent > xMyContext( m_aContext.get(), UNO_QUERY );
+ if ( xMyContext.is() )
+ {
+ try
+ {
+ xMyContext->dispose();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "accessibility", "EditBrowseBoxTableCellAccess::disposing: caught an exception while disposing the context!" );
+ }
+ }
+
+ m_pBrowseBox = nullptr;
+ m_xControlAccessible.clear();
+ m_aContext.clear();
+ // NO dispose of the inner object there: it is the css::accessibility::XAccessible of a window, and disposing
+ // it would delete the respective VCL window
+ }
+} // namespace accessibility
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibleiconchoicectrl.cxx b/accessibility/source/extended/accessibleiconchoicectrl.cxx
new file mode 100644
index 000000000..9ad90c387
--- /dev/null
+++ b/accessibility/source/extended/accessibleiconchoicectrl.cxx
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibleiconchoicectrl.hxx>
+#include <extended/accessibleiconchoicectrlentry.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/toolkit/ivctrl.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+
+namespace accessibility
+{
+
+
+ // class AccessibleIconChoiceCtrl ----------------------------------------------
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleIconChoiceCtrl::AccessibleIconChoiceCtrl( SvtIconChoiceCtrl const & _rIconCtrl, const Reference< XAccessible >& _xParent ) :
+ VCLXAccessibleComponent( _rIconCtrl.GetWindowPeer() ),
+ m_xParent ( _xParent )
+ {
+ }
+
+ IMPLEMENT_FORWARD_XINTERFACE2(AccessibleIconChoiceCtrl, VCLXAccessibleComponent, AccessibleIconChoiceCtrl_BASE)
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleIconChoiceCtrl, VCLXAccessibleComponent, AccessibleIconChoiceCtrl_BASE)
+
+ void AccessibleIconChoiceCtrl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ if ( !isAlive() )
+ return;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ListboxSelect :
+ {
+ // First send an event that tells the listeners of a
+ // modified selection. The active descendant event is
+ // send after that so that the receiving AT has time to
+ // read the text or name of the active child.
+// NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+
+ if ( getCtrl() && getCtrl()->HasFocus() )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = static_cast< SvxIconChoiceCtrlEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ sal_Int32 nPos = getCtrl()->GetEntryListPos( pEntry );
+ Reference< XAccessible > xChild = new AccessibleIconChoiceCtrlEntry( *getCtrl(), nPos, this );
+ uno::Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
+
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOldValue, aNewValue );
+
+ }
+ }
+ break;
+ }
+ case VclEventId::WindowGetFocus :
+ {
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ if ( pCtrl && pCtrl->HasFocus() )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = static_cast< SvxIconChoiceCtrlEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry == nullptr )
+ {
+ pEntry = getCtrl()->GetSelectedEntry();
+ }
+ if ( pEntry )
+ {
+ sal_Int32 nPos = pCtrl->GetEntryListPos( pEntry );
+ Reference< XAccessible > xChild = new AccessibleIconChoiceCtrlEntry( *pCtrl, nPos, this );
+ uno::Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ break;
+ }
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
+ }
+ }
+
+ // XComponent
+
+ void SAL_CALL AccessibleIconChoiceCtrl::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ m_xParent = nullptr;
+ }
+
+ // XServiceInfo
+
+ OUString SAL_CALL AccessibleIconChoiceCtrl::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleIconChoiceControl";
+ }
+
+ Sequence< OUString > SAL_CALL AccessibleIconChoiceCtrl::getSupportedServiceNames()
+ {
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.awt.AccessibleIconChoiceControl"};
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrl::supportsService( const OUString& _rServiceName )
+ {
+ return cppu::supportsService(this, _rServiceName);
+ }
+
+ // XAccessible
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleContext( )
+ {
+ ensureAlive();
+ return this;
+ }
+
+ // XAccessibleContext
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrl::getAccessibleChildCount( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ return getCtrl()->GetEntryCount();
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleChild( sal_Int32 i )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry(i);
+ if ( !pEntry )
+ throw RuntimeException("getAccessibleChild: Entry "
+ + OUString::number(i) + " not found",
+ static_cast<css::lang::XTypeProvider*>(
+ static_cast<VCLXAccessibleComponent_BASE*>(this)));
+
+ return new AccessibleIconChoiceCtrlEntry( *pCtrl, i, this );
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getAccessibleParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ensureAlive();
+ return m_xParent;
+ }
+
+ sal_Int16 SAL_CALL AccessibleIconChoiceCtrl::getAccessibleRole( )
+ {
+ //return AccessibleRole::TREE;
+ return AccessibleRole::LIST;
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrl::getAccessibleDescription( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ return getCtrl()->GetAccessibleDescription();
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrl::getAccessibleName( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ OUString sName = getCtrl()->GetAccessibleName();
+ if ( sName.isEmpty() )
+ sName = "IconChoiceControl";
+ return sName;
+ }
+
+ // XAccessibleSelection
+
+ void SAL_CALL AccessibleIconChoiceCtrl::selectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( nChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ pCtrl->SetCursor( pEntry );
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrl::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( nChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ return ( pCtrl->GetCursor() == pEntry );
+ }
+
+ void SAL_CALL AccessibleIconChoiceCtrl::clearAccessibleSelection( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+ getCtrl()->SetNoSelection();
+ }
+
+ void SAL_CALL AccessibleIconChoiceCtrl::selectAllAccessibleChildren( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ sal_Int32 nCount = pCtrl->GetEntryCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
+ if ( pCtrl->GetCursor() != pEntry )
+ pCtrl->SetCursor( pEntry );
+ }
+ }
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrl::getSelectedAccessibleChildCount( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ sal_Int32 nSelCount = 0;
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ sal_Int32 nCount = pCtrl->GetEntryCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
+ if ( pCtrl->GetCursor() == pEntry )
+ ++nSelCount;
+ }
+
+ return nSelCount;
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ sal_Int32 nSelCount = 0;
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ sal_Int32 nCount = pCtrl->GetEntryCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
+ if ( pCtrl->GetCursor() == pEntry )
+ ++nSelCount;
+
+ if ( nSelCount == ( nSelectedChildIndex + 1 ) )
+ {
+ xChild = new AccessibleIconChoiceCtrlEntry( *pCtrl, i, this );
+ break;
+ }
+ }
+
+ return xChild;
+ }
+
+ void SAL_CALL AccessibleIconChoiceCtrl::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nSelCount = 0;
+ VclPtr<SvtIconChoiceCtrl> pCtrl = getCtrl();
+ sal_Int32 nCount = pCtrl->GetEntryCount();
+ bool bFound = false;
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvxIconChoiceCtrlEntry* pEntry = pCtrl->GetEntry( i );
+ if ( pEntry->IsSelected() )
+ {
+ ++nSelCount;
+ if ( i == nSelectedChildIndex )
+ bFound = true;
+ }
+ }
+
+ // if only one entry is selected and its index is chosen to deselect -> no selection anymore
+ if ( nSelCount == 1 && bFound )
+ pCtrl->SetNoSelection();
+ }
+
+ void AccessibleIconChoiceCtrl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+ {
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+ if ( isAlive() )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+ }
+ }
+
+ VclPtr< SvtIconChoiceCtrl > AccessibleIconChoiceCtrl::getCtrl() const
+ {
+ return GetAs<SvtIconChoiceCtrl >();
+ }
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibleiconchoicectrlentry.cxx b/accessibility/source/extended/accessibleiconchoicectrlentry.cxx
new file mode 100644
index 000000000..5a995a94f
--- /dev/null
+++ b/accessibility/source/extended/accessibleiconchoicectrlentry.cxx
@@ -0,0 +1,680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibleiconchoicectrlentry.hxx>
+#include <vcl/toolkit/ivctrl.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svtools/stringtransfer.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#define ACCESSIBLE_ACTION_COUNT 1
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkActionIndex_Impl( sal_Int32 _nIndex )
+ {
+ if ( _nIndex < 0 || _nIndex >= ACCESSIBLE_ACTION_COUNT )
+ // only three actions
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+
+namespace accessibility
+{
+
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleIconChoiceCtrlEntry::AccessibleIconChoiceCtrlEntry( SvtIconChoiceCtrl& _rIconCtrl,
+ sal_Int32 _nPos,
+ const Reference< XAccessible >& _xParent ) :
+
+ AccessibleIconChoiceCtrlEntry_BASE ( m_aMutex ),
+
+ m_pIconCtrl ( &_rIconCtrl ),
+ m_nIndex ( _nPos ),
+ m_nClientId ( 0 ),
+ m_xParent ( _xParent )
+
+ {
+ osl_atomic_increment( &m_refCount );
+ {
+ Reference< XComponent > xComp( m_xParent, UNO_QUERY );
+ if ( xComp.is() )
+ xComp->addEventListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ void AccessibleIconChoiceCtrlEntry::disposing( const css::lang::EventObject& _rSource )
+ {
+ if ( _rSource.Source == m_xParent )
+ {
+ dispose();
+ OSL_ENSURE( !m_xParent.is() && ( m_pIconCtrl == nullptr ), "" );
+ }
+ }
+
+ AccessibleIconChoiceCtrlEntry::~AccessibleIconChoiceCtrlEntry()
+ {
+ if ( IsAlive_Impl() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ }
+
+ tools::Rectangle AccessibleIconChoiceCtrlEntry::GetBoundingBox_Impl() const
+ {
+ tools::Rectangle aRect;
+ SvxIconChoiceCtrlEntry* pEntry = m_pIconCtrl->GetEntry( m_nIndex );
+ if ( pEntry )
+ aRect = m_pIconCtrl->GetBoundingBox( pEntry );
+
+ return aRect;
+ }
+
+ tools::Rectangle AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen_Impl() const
+ {
+ tools::Rectangle aRect;
+ SvxIconChoiceCtrlEntry* pEntry = m_pIconCtrl->GetEntry( m_nIndex );
+ if ( pEntry )
+ {
+ aRect = m_pIconCtrl->GetBoundingBox( pEntry );
+ Point aTopLeft = aRect.TopLeft();
+ aTopLeft += m_pIconCtrl->GetWindowExtentsRelative( nullptr ).TopLeft();
+ aRect = tools::Rectangle( aTopLeft, aRect.GetSize() );
+ }
+
+ return aRect;
+ }
+
+ bool AccessibleIconChoiceCtrlEntry::IsAlive_Impl() const
+ {
+ return ( !rBHelper.bDisposed && !rBHelper.bInDispose && m_pIconCtrl );
+ }
+
+ bool AccessibleIconChoiceCtrlEntry::IsShowing_Impl() const
+ {
+ bool bShowing = false;
+ Reference< XAccessibleContext > xParentContext =
+ m_xParent.is() ? m_xParent->getAccessibleContext() : Reference< XAccessibleContext >();
+ if( xParentContext.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParentContext, uno::UNO_QUERY );
+ if( xParentComp.is() )
+ bShowing = GetBoundingBox_Impl().Overlaps( VCLRectangle( xParentComp->getBounds() ) );
+ }
+
+ return bShowing;
+ }
+
+ tools::Rectangle AccessibleIconChoiceCtrlEntry::GetBoundingBox()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return GetBoundingBox_Impl();
+ }
+
+ tools::Rectangle AccessibleIconChoiceCtrlEntry::GetBoundingBoxOnScreen()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return GetBoundingBoxOnScreen_Impl();
+ }
+
+ void AccessibleIconChoiceCtrlEntry::EnsureIsAlive() const
+ {
+ if ( !IsAlive_Impl() )
+ throw lang::DisposedException();
+ }
+
+ OUString AccessibleIconChoiceCtrlEntry::implGetText()
+ {
+ OUString sRet;
+ SvxIconChoiceCtrlEntry* pEntry = m_pIconCtrl->GetEntry( m_nIndex );
+ if ( pEntry )
+ sRet = pEntry->GetDisplayText();
+ return sRet;
+ }
+
+ Locale AccessibleIconChoiceCtrlEntry::implGetLocale()
+ {
+ return Application::GetSettings().GetUILanguageTag().getLocale();
+ }
+ void AccessibleIconChoiceCtrlEntry::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+ {
+ nStartIndex = 0;
+ nEndIndex = 0;
+ }
+
+ // XTypeProvider
+
+
+ Sequence< sal_Int8 > AccessibleIconChoiceCtrlEntry::getImplementationId()
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ // XComponent
+
+ void SAL_CALL AccessibleIconChoiceCtrlEntry::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // Send a disposing to all listeners.
+ if ( m_nClientId )
+ {
+ sal_uInt32 nId = m_nClientId;
+ m_nClientId = 0;
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+ }
+
+ Reference< XComponent > xComp( m_xParent, UNO_QUERY );
+ if ( xComp.is() )
+ xComp->removeEventListener( this );
+
+ m_pIconCtrl = nullptr;
+ m_xParent = nullptr;
+ }
+
+ // XServiceInfo
+
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleIconChoiceControlEntry";
+ }
+
+ Sequence< OUString > SAL_CALL AccessibleIconChoiceCtrlEntry::getSupportedServiceNames()
+ {
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.awt.AccessibleIconChoiceControlEntry"};
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::supportsService( const OUString& _rServiceName )
+ {
+ return cppu::supportsService(this, _rServiceName);
+ }
+
+ // XAccessible
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleContext( )
+ {
+ EnsureIsAlive();
+ return this;
+ }
+
+ // XAccessibleContext
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleChildCount( )
+ {
+ return 0; // no children
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleChild( sal_Int32 )
+ {
+ throw IndexOutOfBoundsException();
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return m_xParent;
+ }
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_nIndex;
+ }
+
+ sal_Int16 SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleRole( )
+ {
+ //return AccessibleRole::LABEL;
+ return AccessibleRole::LIST_ITEM;
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleDescription( )
+ {
+ // no description for every item
+ return OUString();
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleName( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return implGetText();
+ }
+
+ Reference< XAccessibleRelationSet > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleRelationSet( )
+ {
+ return new utl::AccessibleRelationSetHelper;
+ }
+
+ Reference< XAccessibleStateSet > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleStateSet( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( IsAlive_Impl() )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
+ if ( IsShowing_Impl() )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ }
+
+ if ( m_pIconCtrl && m_pIconCtrl->GetCursor() == m_pIconCtrl->GetEntry( m_nIndex ) )
+ pStateSetHelper->AddState( AccessibleStateType::SELECTED );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+ }
+
+ Locale SAL_CALL AccessibleIconChoiceCtrlEntry::getLocale( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return implGetLocale();
+ }
+
+ // XAccessibleComponent
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::containsPoint( const awt::Point& rPoint )
+ {
+ return tools::Rectangle( Point(), GetBoundingBox().GetSize() ).Contains( VCLPoint( rPoint ) );
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleAtPoint( const awt::Point& )
+ {
+ return Reference< XAccessible >();
+ }
+
+ awt::Rectangle SAL_CALL AccessibleIconChoiceCtrlEntry::getBounds( )
+ {
+ return AWTRectangle( GetBoundingBox() );
+ }
+
+ awt::Point SAL_CALL AccessibleIconChoiceCtrlEntry::getLocation( )
+ {
+ return AWTPoint( GetBoundingBox().TopLeft() );
+ }
+
+ awt::Point SAL_CALL AccessibleIconChoiceCtrlEntry::getLocationOnScreen( )
+ {
+ return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
+ }
+
+ awt::Size SAL_CALL AccessibleIconChoiceCtrlEntry::getSize( )
+ {
+ return AWTSize( GetBoundingBox().GetSize() );
+ }
+
+ void SAL_CALL AccessibleIconChoiceCtrlEntry::grabFocus( )
+ {
+ // do nothing, because no focus for each item
+ }
+
+ sal_Int32 AccessibleIconChoiceCtrlEntry::getForeground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+ }
+
+ sal_Int32 AccessibleIconChoiceCtrlEntry::getBackground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+ }
+
+ // XAccessibleText
+
+
+ awt::Rectangle SAL_CALL AccessibleIconChoiceCtrlEntry::getCharacterBounds( sal_Int32 _nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( ( 0 > _nIndex ) || ( implGetText().getLength() <= _nIndex ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pIconCtrl )
+ {
+ tools::Rectangle aItemRect = GetBoundingBox_Impl();
+ tools::Rectangle aCharRect = m_pIconCtrl->GetEntryCharacterBounds( m_nIndex, _nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+ }
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getIndexAtPoint( const awt::Point& aPoint )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pIconCtrl )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = GetBoundingBox_Impl();
+ m_pIconCtrl->RecordLayoutData( &aLayoutData, aItemRect );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ nIndex = aLayoutData.GetIndexForPoint( aPnt );
+
+ tools::Long nLen = aLayoutData.m_aUnicodeBoundRects.size();
+ for ( tools::Long i = 0; i < nLen; ++i )
+ {
+ tools::Rectangle aRect = aLayoutData.GetCharacterBounds(i);
+ bool bInside = aRect.Contains( aPnt );
+
+ if ( bInside )
+ break;
+ }
+ }
+
+ return nIndex;
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ OUString sText = implGetText();
+ if ( ( 0 > nStartIndex ) || ( sText.getLength() <= nStartIndex )
+ || ( 0 > nEndIndex ) || ( sText.getLength() <= nEndIndex ) )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nLen = nEndIndex - nStartIndex + 1;
+ ::svt::OStringTransfer::CopyString( sText.copy( nStartIndex, nLen ), m_pIconCtrl );
+
+ return true;
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+ {
+ return false;
+ }
+
+ // XAccessibleEventBroadcaster
+
+ void SAL_CALL AccessibleIconChoiceCtrlEntry::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+ {
+ if (xListener.is())
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (!m_nClientId)
+ m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
+ }
+ }
+
+ void SAL_CALL AccessibleIconChoiceCtrlEntry::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+ {
+ if (!xListener.is())
+ return;
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ sal_Int32 nId = m_nClientId;
+ m_nClientId = 0;
+ comphelper::AccessibleEventNotifier::revokeClient( nId );
+ }
+ }
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getCaretPosition( )
+ {
+ return -1;
+ }
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::setCaretPosition ( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ sal_Unicode SAL_CALL AccessibleIconChoiceCtrlEntry::getCharacter( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+ }
+ css::uno::Sequence< css::beans::PropertyValue > SAL_CALL AccessibleIconChoiceCtrlEntry::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return css::uno::Sequence< css::beans::PropertyValue >();
+ }
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getCharacterCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return implGetText().getLength();
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getSelectedText( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OUString();
+ }
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getSelectionStart( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return 0;
+ }
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getSelectionEnd( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return 0;
+ }
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getText( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return implGetText( );
+ }
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleIconChoiceCtrlEntry::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleIconChoiceCtrlEntry::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleIconChoiceCtrlEntry::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
+ }
+
+
+ // XAccessibleAction
+
+ sal_Int32 SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleActionCount( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // three actions supported
+ return ACCESSIBLE_ACTION_COUNT;
+ }
+
+ sal_Bool SAL_CALL AccessibleIconChoiceCtrlEntry::doAccessibleAction( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bRet = false;
+ checkActionIndex_Impl( nIndex );
+ EnsureIsAlive();
+
+ SvxIconChoiceCtrlEntry* pEntry = m_pIconCtrl->GetEntry( m_nIndex );
+ if ( pEntry && !pEntry->IsSelected() )
+ {
+ m_pIconCtrl->SetNoSelection();
+ m_pIconCtrl->SetCursor( pEntry );
+ bRet = true;
+ }
+
+ return bRet;
+ }
+
+ OUString SAL_CALL AccessibleIconChoiceCtrlEntry::getAccessibleActionDescription( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ checkActionIndex_Impl( nIndex );
+ EnsureIsAlive();
+
+ return "Select";
+ }
+
+ Reference< XAccessibleKeyBinding > AccessibleIconChoiceCtrlEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XAccessibleKeyBinding > xRet;
+ checkActionIndex_Impl( nIndex );
+ // ... which key?
+ return xRet;
+ }
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessiblelistbox.cxx b/accessibility/source/extended/accessiblelistbox.cxx
new file mode 100644
index 000000000..462f28664
--- /dev/null
+++ b/accessibility/source/extended/accessiblelistbox.cxx
@@ -0,0 +1,530 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessiblelistbox.hxx>
+#include <extended/accessiblelistboxentry.hxx>
+#include <vcl/toolkit/treelistbox.hxx>
+#include <vcl/toolkit/treelistentry.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+
+
+namespace accessibility
+{
+
+
+ // class AccessibleListBox -----------------------------------------------------
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleListBox::AccessibleListBox( SvTreeListBox const & _rListBox, const Reference< XAccessible >& _xParent ) :
+
+ VCLXAccessibleComponent( _rListBox.GetWindowPeer() ),
+ m_xParent( _xParent )
+ {
+ }
+
+ AccessibleListBox::~AccessibleListBox()
+ {
+ if ( isAlive() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ }
+ IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox, VCLXAccessibleComponent, ImplHelper2)
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleListBox, VCLXAccessibleComponent, ImplHelper2)
+
+ void AccessibleListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ if ( !isAlive() )
+ return;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::CheckboxToggle :
+ {
+ if ( !getListBox() || !getListBox()->HasFocus() )
+ {
+ return;
+ }
+ AccessibleListBoxEntry* pCurOpEntry = GetCurEventEntry(rVclWindowEvent);
+ if(!pCurOpEntry)
+ {
+ return ;
+ }
+ uno::Any aValue;
+ aValue <<= AccessibleStateType::CHECKED;
+
+ if ( getListBox()->GetCheckButtonState( pCurOpEntry->GetSvLBoxEntry() ) == SvButtonState::Checked )
+ {
+ pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), aValue );
+ }
+ else
+ {
+ pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aValue,uno::Any() );
+ }
+ break;
+ }
+
+ case VclEventId::ListboxSelect :
+ {
+ OSL_FAIL("Debug: Treelist shouldn't use VclEventId::ListboxSelect");
+ break;
+ }
+
+ case VclEventId::ListboxTreeSelect:
+ {
+ if ( getListBox() && getListBox()->HasFocus() )
+ {
+ AccessibleListBoxEntry* pEntry =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
+ if (pEntry)
+ {
+ pEntry->NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ }
+ break;
+ case VclEventId::ListboxTreeFocus:
+ {
+ VclPtr<SvTreeListBox> pBox = getListBox();
+ if( pBox && pBox->HasFocus() )
+ {
+ uno::Any aNewValue;
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
+ if (pEntryFocus && pEntryFocus->GetSvLBoxEntry() == pEntry)
+ {
+ aNewValue <<= m_xFocusedChild;
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, uno::Any(), aNewValue );
+ return ;
+ }
+
+ uno::Any aOldValue;
+ aOldValue <<= m_xFocusedChild;
+
+ m_xFocusedChild.set(implGetAccessible(*pEntry));
+
+ aNewValue <<= m_xFocusedChild;
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
+ }
+ else
+ {
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::ListboxItemRemoved:
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ RemoveChildEntries(pEntry);
+ }
+ else
+ {
+ // NULL means Clear()
+ for (auto const& entry : m_mapEntry)
+ {
+ uno::Any aNewValue;
+ uno::Any aOldValue;
+ aOldValue <<= uno::Reference<XAccessible>(entry.second);
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ for (auto const& entry : m_mapEntry)
+ { // release references ...
+ entry.second->dispose();
+ }
+ m_mapEntry.clear();
+ }
+ }
+ break;
+
+ // #i92103#
+ case VclEventId::ItemExpanded :
+ case VclEventId::ItemCollapsed :
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ Reference<XAccessible> const xChild(implGetAccessible(*pEntry));
+ const short nAccEvent =
+ ( rVclWindowEvent.GetId() == VclEventId::ItemExpanded )
+ ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED
+ : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED;
+ uno::Any aListBoxEntry;
+ aListBoxEntry <<= xChild;
+ NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry );
+ if ( getListBox() && getListBox()->HasFocus() )
+ {
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry );
+ }
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ }
+ }
+
+ AccessibleListBoxEntry* AccessibleListBox::GetCurEventEntry( const VclWindowEvent& rVclWindowEvent )
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( !pEntry )
+ pEntry = getListBox()->GetCurEntry();
+
+ AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
+ if (pEntryFocus && pEntry && pEntry != pEntryFocus->GetSvLBoxEntry())
+ {
+ AccessibleListBoxEntry *const pAccCurOptionEntry = implGetAccessible(*pEntry).get();
+ uno::Any aNewValue;
+ aNewValue <<= uno::Reference<XAccessible>(pAccCurOptionEntry);
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, uno::Any(), aNewValue );//Add
+
+ return pAccCurOptionEntry;
+ }
+ else
+ {
+ return pEntryFocus;
+ }
+ }
+
+ void AccessibleListBox::RemoveChildEntries(SvTreeListEntry* pEntry)
+ {
+ MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry);
+ if ( mi != m_mapEntry.end() )
+ {
+ uno::Any aNewValue;
+ uno::Any aOldValue;
+ aOldValue <<= uno::Reference<XAccessible>(mi->second);
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ m_mapEntry.erase(mi);
+ }
+
+ VclPtr<SvTreeListBox> pBox = getListBox();
+ SvTreeListEntry* pEntryChild = pBox->FirstChild(pEntry);
+ while (pEntryChild)
+ {
+ RemoveChildEntries(pEntryChild);
+ pEntryChild = pEntryChild->NextSibling();
+ }
+ }
+
+
+ void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow:
+ case VclEventId::WindowHide:
+ {
+ }
+ break;
+ default:
+ {
+ VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
+ }
+ break;
+ }
+ }
+
+
+ // XComponent
+
+ void SAL_CALL AccessibleListBox::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ m_mapEntry.clear();
+ VCLXAccessibleComponent::disposing();
+ m_xParent = nullptr;
+ }
+
+ // XServiceInfo
+
+ OUString SAL_CALL AccessibleListBox::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTreeListBox";
+ }
+
+ Sequence< OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames()
+ {
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.awt.AccessibleTreeListBox"};
+ }
+
+ sal_Bool SAL_CALL AccessibleListBox::supportsService( const OUString& _rServiceName )
+ {
+ return cppu::supportsService(this, _rServiceName);
+ }
+
+ // XAccessible
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext( )
+ {
+ ensureAlive();
+ return this;
+ }
+
+ // XAccessibleContext
+
+ sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ sal_Int32 nCount = 0;
+ VclPtr<SvTreeListBox> pSvTreeListBox = getListBox();
+ if ( pSvTreeListBox )
+ nCount = pSvTreeListBox->GetLevelChildCount( nullptr );
+
+ return nCount;
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ SvTreeListEntry* pEntry = getListBox()->GetEntry(i);
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ // Solution: Set the parameter of the parent to null to let entry determine the parent by itself
+ //return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
+ //return new AccessibleListBoxEntry( *getListBox(), pEntry, nullptr );
+ return implGetAccessible(*pEntry);
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ensureAlive();
+ return m_xParent;
+ }
+
+ sal_Int32 AccessibleListBox::GetRoleType() const
+ {
+ sal_Int32 nCase = 0;
+ SvTreeListEntry* pEntry = getListBox()->GetEntry(0);
+ if ( pEntry )
+ {
+ if( pEntry->HasChildrenOnDemand() || getListBox()->GetChildCount(pEntry) > 0 )
+ {
+ nCase = 1;
+ return nCase;
+ }
+ }
+
+ bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
+ if( !(getListBox()->GetTreeFlags() & SvTreeFlags::CHKBTN) )
+ {
+ if( bHasButtons )
+ nCase = 1;
+ }
+ else
+ {
+ if( bHasButtons )
+ nCase = 2;
+ else
+ nCase = 3;
+ }
+ return nCase;
+ }
+
+ sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole()
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ //o is: return AccessibleRole::TREE;
+ bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
+ if(!bHasButtons && (getListBox()->GetTreeFlags() & SvTreeFlags::CHKBTN))
+ return AccessibleRole::LIST;
+ else
+ if (GetRoleType() == 0)
+ return AccessibleRole::LIST;
+ else
+ return AccessibleRole::TREE;
+ }
+
+ OUString SAL_CALL AccessibleListBox::getAccessibleDescription( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ return getListBox()->GetAccessibleDescription();
+ }
+
+ OUString SAL_CALL AccessibleListBox::getAccessibleName( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ return getListBox()->GetAccessibleName();
+ }
+
+ // XAccessibleSelection
+
+ void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( nChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ getListBox()->Select( pEntry );
+ }
+
+ sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( nChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ return getListBox()->IsSelected( pEntry );
+ }
+
+ void SAL_CALL AccessibleListBox::clearAccessibleSelection( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
+ if ( getListBox()->IsSelected( pEntry ) )
+ getListBox()->Select( pEntry, false );
+ }
+ }
+
+ void SAL_CALL AccessibleListBox::selectAllAccessibleChildren( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
+ if ( !getListBox()->IsSelected( pEntry ) )
+ getListBox()->Select( pEntry );
+ }
+ }
+
+ sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount( )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ return getListBox()->GetSelectionCount();
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ sal_Int32 nSelCount= 0;
+ sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
+ if ( getListBox()->IsSelected( pEntry ) )
+ ++nSelCount;
+
+ if ( nSelCount == ( nSelectedChildIndex + 1 ) )
+ {
+ // Solution: Set the parameter of the parent to null to let entry determine the parent by itself
+ //xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
+ //xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, nullptr );
+ xChild = implGetAccessible(*pEntry).get();
+ break;
+ }
+ }
+
+ return xChild;
+ }
+
+ void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ ::comphelper::OExternalLockGuard aGuard( this );
+
+ SvTreeListEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ getListBox()->Select( pEntry, false );
+ }
+
+ void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+ {
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+ if ( getListBox() && isAlive() )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
+ if ( getListBox()->GetSelectionMode() == SelectionMode::Multiple )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+ }
+ }
+
+ rtl::Reference<AccessibleListBoxEntry> AccessibleListBox::implGetAccessible(SvTreeListEntry & rEntry)
+ {
+ rtl::Reference<AccessibleListBoxEntry> pAccessible;
+ auto const it = m_mapEntry.find(&rEntry);
+ if (it != m_mapEntry.end())
+ {
+ pAccessible = it->second;
+ }
+ else
+ {
+ pAccessible = new AccessibleListBoxEntry(*getListBox(), rEntry, *this);
+ m_mapEntry.emplace(&rEntry, pAccessible);
+ }
+ assert(pAccessible.is());
+ return pAccessible;
+ }
+
+ VclPtr< SvTreeListBox > AccessibleListBox::getListBox() const
+ {
+ return GetAs< SvTreeListBox >();
+ }
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessiblelistboxentry.cxx b/accessibility/source/extended/accessiblelistboxentry.cxx
new file mode 100644
index 000000000..2fff77b03
--- /dev/null
+++ b/accessibility/source/extended/accessiblelistboxentry.cxx
@@ -0,0 +1,1194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessiblelistboxentry.hxx>
+#include <extended/accessiblelistbox.hxx>
+#include <vcl/toolkit/treelistbox.hxx>
+#include <svtools/stringtransfer.hxx>
+#include <vcl/toolkit/svlbitm.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#define ACCESSIBLE_ACTION_COUNT 1
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkActionIndex_Impl( sal_Int32 _nIndex )
+ {
+ if ( _nIndex < 0 || _nIndex >= ACCESSIBLE_ACTION_COUNT )
+ // only three actions
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+
+namespace accessibility
+{
+ // class AccessibleListBoxEntry -----------------------------------------------------
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+ using namespace ::comphelper;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleListBoxEntry::AccessibleListBoxEntry( SvTreeListBox& _rListBox,
+ SvTreeListEntry& rEntry,
+ AccessibleListBox & rListBox)
+ : AccessibleListBoxEntry_BASE( m_aMutex )
+
+ , m_pTreeListBox( &_rListBox )
+ , m_pSvLBoxEntry(&rEntry)
+ , m_nClientId( 0 )
+ , m_wListBox(&rListBox)
+ , m_rListBox(rListBox)
+ {
+ m_pTreeListBox->AddEventListener( LINK( this, AccessibleListBoxEntry, WindowEventListener ) );
+ _rListBox.FillEntryPath( m_pSvLBoxEntry, m_aEntryPath );
+ }
+
+ AccessibleListBoxEntry::~AccessibleListBoxEntry()
+ {
+ if ( IsAlive_Impl() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ }
+
+ IMPL_LINK( AccessibleListBoxEntry, WindowEventListener, VclWindowEvent&, rEvent, void )
+ {
+ OSL_ENSURE( rEvent.GetWindow() , "AccessibleListBoxEntry::WindowEventListener: no event window!" );
+ OSL_ENSURE( rEvent.GetWindow() == m_pTreeListBox, "AccessibleListBoxEntry::WindowEventListener: where did this come from?" );
+
+ if ( m_pTreeListBox == nullptr )
+ return;
+
+ switch ( rEvent.GetId() )
+ {
+ case VclEventId::ObjectDying :
+ {
+ if ( m_pTreeListBox )
+ m_pTreeListBox->RemoveEventListener( LINK( this, AccessibleListBoxEntry, WindowEventListener ) );
+ m_pTreeListBox = nullptr;
+ dispose();
+ break;
+ }
+ default: break;
+ }
+ }
+
+ void AccessibleListBoxEntry::NotifyAccessibleEvent( sal_Int16 _nEventId,
+ const css::uno::Any& _aOldValue,
+ const css::uno::Any& _aNewValue )
+ {
+ Reference< uno::XInterface > xSource( *this );
+ AccessibleEventObject aEventObj( xSource, _nEventId, _aNewValue, _aOldValue );
+
+ if (m_nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEventObj );
+ }
+
+
+ tools::Rectangle AccessibleListBoxEntry::GetBoundingBox_Impl() const
+ {
+ tools::Rectangle aRect;
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ aRect = m_pTreeListBox->GetBoundingRect( pEntry );
+ SvTreeListEntry* pParent = m_pTreeListBox->GetParent( pEntry );
+ if ( pParent )
+ {
+ // position relative to parent entry
+ Point aTopLeft = aRect.TopLeft();
+ aTopLeft -= m_pTreeListBox->GetBoundingRect( pParent ).TopLeft();
+ aRect = tools::Rectangle( aTopLeft, aRect.GetSize() );
+ }
+ }
+
+ return aRect;
+ }
+
+ tools::Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen_Impl() const
+ {
+ tools::Rectangle aRect;
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ aRect = m_pTreeListBox->GetBoundingRect( pEntry );
+ Point aTopLeft = aRect.TopLeft();
+ aTopLeft += m_pTreeListBox->GetWindowExtentsRelative( nullptr ).TopLeft();
+ aRect = tools::Rectangle( aTopLeft, aRect.GetSize() );
+ }
+
+ return aRect;
+ }
+
+ bool AccessibleListBoxEntry::IsAlive_Impl() const
+ {
+ return !rBHelper.bDisposed && !rBHelper.bInDispose && (m_pTreeListBox != nullptr);
+ }
+
+ bool AccessibleListBoxEntry::IsShowing_Impl() const
+ {
+ Reference< XAccessible > xParent = implGetParentAccessible( );
+
+ bool bShowing = false;
+ Reference< XAccessibleContext > xParentContext =
+ xParent.is() ? xParent->getAccessibleContext() : Reference< XAccessibleContext >();
+ if( xParentContext.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParentContext, uno::UNO_QUERY );
+ if( xParentComp.is() )
+ bShowing = GetBoundingBox_Impl().Overlaps( VCLRectangle( xParentComp->getBounds() ) );
+ }
+
+ return bShowing;
+ }
+
+ tools::Rectangle AccessibleListBoxEntry::GetBoundingBox()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return GetBoundingBox_Impl();
+ }
+
+ tools::Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ return GetBoundingBoxOnScreen_Impl();
+ }
+
+ void AccessibleListBoxEntry::EnsureIsAlive() const
+ {
+ if ( !IsAlive_Impl() )
+ throw lang::DisposedException();
+ }
+
+ OUString AccessibleListBoxEntry::implGetText()
+ {
+ OUString sRet;
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ sRet = SvTreeListBox::SearchEntryTextWithHeadTitle( pEntry );
+ return sRet;
+ }
+
+ Locale AccessibleListBoxEntry::implGetLocale()
+ {
+ return Application::GetSettings().GetUILanguageTag().getLocale();
+ }
+ void AccessibleListBoxEntry::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+ {
+ nStartIndex = 0;
+ nEndIndex = 0;
+ }
+
+ // XTypeProvider
+
+
+ Sequence< sal_Int8 > AccessibleListBoxEntry::getImplementationId()
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+
+ // XComponent
+
+ void SAL_CALL AccessibleListBoxEntry::disposing()
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XAccessible > xKeepAlive( this );
+
+ // Send a disposing to all listeners.
+ if ( m_nClientId )
+ {
+ ::comphelper::AccessibleEventNotifier::TClientId nId = m_nClientId;
+ m_nClientId = 0;
+ ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+ }
+
+ // clean up
+ m_wListBox.clear();
+
+ if ( m_pTreeListBox )
+ m_pTreeListBox->RemoveEventListener( LINK( this, AccessibleListBoxEntry, WindowEventListener ) );
+ m_pTreeListBox = nullptr;
+ }
+
+ // XServiceInfo
+
+ OUString SAL_CALL AccessibleListBoxEntry::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTreeListBoxEntry";
+ }
+
+ Sequence< OUString > SAL_CALL AccessibleListBoxEntry::getSupportedServiceNames()
+ {
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.awt.AccessibleTreeListBoxEntry"};
+ }
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::supportsService( const OUString& _rServiceName )
+ {
+ return cppu::supportsService(this, _rServiceName);
+ }
+
+ // XAccessible
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleListBoxEntry::getAccessibleContext( )
+ {
+ EnsureIsAlive();
+ return this;
+ }
+
+ // XAccessibleContext
+
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleChildCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ sal_Int32 nCount = 0;
+ if ( pEntry )
+ nCount = m_pTreeListBox->GetLevelChildCount( pEntry );
+
+ return nCount;
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleChild( sal_Int32 i )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ SvTreeListEntry* pEntry = GetRealChild(i);
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ uno::Reference<XAccessible> xListBox(m_wListBox);
+ assert(xListBox.is());
+
+ return m_rListBox.implGetAccessible(*pEntry);
+ }
+
+ Reference< XAccessible > AccessibleListBoxEntry::implGetParentAccessible( ) const
+ {
+ Reference< XAccessible > xParent;
+ if ( !xParent.is() )
+ {
+ OSL_ENSURE( m_aEntryPath.size(), "AccessibleListBoxEntry::getAccessibleParent: invalid path!" );
+ if ( m_aEntryPath.size() == 1 )
+ { // we're a top level entry
+ // -> our parent is the tree listbox itself
+ if ( m_pTreeListBox )
+ xParent = m_pTreeListBox->GetAccessible( );
+ }
+ else
+ { // we have an entry as parent -> get its accessible
+
+ // shorten our access path by one
+ std::deque< sal_Int32 > aParentPath( m_aEntryPath );
+ aParentPath.pop_back();
+
+ // get the entry for this shortened access path
+ SvTreeListEntry* pParentEntry = m_pTreeListBox->GetEntryFromPath( aParentPath );
+ OSL_ENSURE( pParentEntry, "AccessibleListBoxEntry::implGetParentAccessible: could not obtain a parent entry!" );
+
+ if ( pParentEntry )
+ pParentEntry = m_pTreeListBox->GetParent(pParentEntry);
+ if ( pParentEntry )
+ {
+ uno::Reference<XAccessible> xListBox(m_wListBox);
+ assert(xListBox.is());
+ return m_rListBox.implGetAccessible(*pParentEntry);
+ // the AccessibleListBoxEntry class will create its parent
+ // when needed
+ }
+ }
+ }
+
+ return xParent;
+ }
+
+
+ Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleParent( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ return implGetParentAccessible( );
+ }
+
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( !m_aEntryPath.empty(), "empty path" );
+ return m_aEntryPath.empty() ? -1 : m_aEntryPath.back();
+ }
+
+ sal_Int32 AccessibleListBoxEntry::GetRoleType() const
+ {
+ sal_Int32 nCase = 0;
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry(0);
+ if ( pEntry )
+ {
+ if( pEntry->HasChildrenOnDemand() || m_pTreeListBox->GetChildCount(pEntry) > 0 )
+ {
+ nCase = 1;
+ return nCase;
+ }
+ }
+
+ bool bHasButtons = (m_pTreeListBox->GetStyle() & WB_HASBUTTONS)!=0;
+ if( !(m_pTreeListBox->GetTreeFlags() & SvTreeFlags::CHKBTN) )
+ {
+ if( bHasButtons )
+ nCase = 1;
+ }
+ else
+ {
+ if( bHasButtons )
+ nCase = 2;
+ else
+ nCase = 3;
+ }
+ return nCase;
+ }
+
+ sal_Int16 SAL_CALL AccessibleListBoxEntry::getAccessibleRole( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ SvTreeListBox* pBox = m_pTreeListBox;
+ if(!pBox)
+ return AccessibleRole::UNKNOWN;
+
+ SvTreeFlags treeFlag = pBox->GetTreeFlags();
+ if(treeFlag & SvTreeFlags::CHKBTN )
+ {
+ SvTreeListEntry* pEntry = pBox->GetEntryFromPath( m_aEntryPath );
+ SvButtonState eState = pBox->GetCheckButtonState( pEntry );
+ switch( eState )
+ {
+ case SvButtonState::Checked:
+ case SvButtonState::Unchecked:
+ return AccessibleRole::CHECK_BOX;
+ case SvButtonState::Tristate:
+ default:
+ return AccessibleRole::LABEL;
+ }
+ }
+ if (GetRoleType() == 0)
+ return AccessibleRole::LIST_ITEM;
+ else
+ //o is: return AccessibleRole::LABEL;
+ return AccessibleRole::TREE_ITEM;
+ }
+
+ OUString SAL_CALL AccessibleListBoxEntry::getAccessibleDescription( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if( getAccessibleRole() == AccessibleRole::TREE_ITEM )
+ {
+ return OUString();
+ }
+ return m_pTreeListBox->GetEntryAccessibleDescription(
+ m_pTreeListBox->GetEntryFromPath(m_aEntryPath));
+ }
+
+ OUString SAL_CALL AccessibleListBoxEntry::getAccessibleName( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ return implGetText();
+ }
+
+ Reference< XAccessibleRelationSet > SAL_CALL AccessibleListBoxEntry::getAccessibleRelationSet( )
+ {
+ Reference< XAccessibleRelationSet > xRelSet;
+ Reference< XAccessible > xParent;
+ if ( m_aEntryPath.size() > 1 ) // not a root entry
+ xParent = implGetParentAccessible();
+ if ( xParent.is() )
+ {
+ rtl::Reference<utl::AccessibleRelationSetHelper> pRelationSetHelper = new utl::AccessibleRelationSetHelper;
+ Sequence< Reference< XInterface > > aSequence { xParent };
+ pRelationSetHelper->AddRelation(
+ AccessibleRelation( AccessibleRelationType::NODE_CHILD_OF, aSequence ) );
+ xRelSet = pRelationSetHelper;
+ }
+ return xRelSet;
+ }
+
+ Reference< XAccessibleStateSet > SAL_CALL AccessibleListBoxEntry::getAccessibleStateSet( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( IsAlive_Impl() )
+ {
+ switch(getAccessibleRole())
+ {
+ case AccessibleRole::LABEL:
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ if (m_pTreeListBox->IsInplaceEditingEnabled())
+ pStateSetHelper->AddState( AccessibleStateType::EDITABLE );
+ if (IsShowing_Impl())
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ break;
+ case AccessibleRole::CHECK_BOX:
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ if (IsShowing_Impl())
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ break;
+ }
+ SvTreeListEntry *pEntry = m_pTreeListBox->GetEntryFromPath(m_aEntryPath);
+ if (pEntry)
+ m_pTreeListBox->FillAccessibleEntryStateSet(pEntry, *pStateSetHelper);
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+ }
+
+ Locale SAL_CALL AccessibleListBoxEntry::getLocale( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return implGetLocale();
+ }
+
+ // XAccessibleComponent
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::containsPoint( const awt::Point& rPoint )
+ {
+ return tools::Rectangle( Point(), GetBoundingBox().GetSize() ).Contains( VCLPoint( rPoint ) );
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleAtPoint( const awt::Point& _aPoint )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( VCLPoint( _aPoint ) );
+ if ( !pEntry )
+ throw RuntimeException("AccessibleListBoxEntry::getAccessibleAtPoint - pEntry cannot be empty!");
+
+ Reference< XAccessible > xAcc;
+ uno::Reference<XAccessible> xListBox(m_wListBox);
+ assert(xListBox.is());
+ auto pAccEntry = m_rListBox.implGetAccessible(*pEntry);
+ tools::Rectangle aRect = pAccEntry->GetBoundingBox_Impl();
+ if ( aRect.Contains( VCLPoint( _aPoint ) ) )
+ xAcc = pAccEntry.get();
+ return xAcc;
+ }
+
+ awt::Rectangle SAL_CALL AccessibleListBoxEntry::getBounds( )
+ {
+ return AWTRectangle( GetBoundingBox() );
+ }
+
+ awt::Point SAL_CALL AccessibleListBoxEntry::getLocation( )
+ {
+ return AWTPoint( GetBoundingBox().TopLeft() );
+ }
+
+ awt::Point SAL_CALL AccessibleListBoxEntry::getLocationOnScreen( )
+ {
+ return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
+ }
+
+ awt::Size SAL_CALL AccessibleListBoxEntry::getSize( )
+ {
+ return AWTSize( GetBoundingBox().GetSize() );
+ }
+
+ void SAL_CALL AccessibleListBoxEntry::grabFocus( )
+ {
+ // do nothing, because no focus for each item
+ }
+
+ sal_Int32 AccessibleListBoxEntry::getForeground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+ }
+
+ sal_Int32 AccessibleListBoxEntry::getBackground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+ }
+
+ // XAccessibleText
+
+
+ awt::Rectangle SAL_CALL AccessibleListBoxEntry::getCharacterBounds( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = GetBoundingBox();
+ m_pTreeListBox->RecordLayoutData( &aLayoutData, aItemRect );
+ tools::Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+ }
+
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getIndexAtPoint( const awt::Point& aPoint )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ if(aPoint.X==0 && aPoint.Y==0) return 0;
+
+ sal_Int32 nIndex = -1;
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = GetBoundingBox();
+ m_pTreeListBox->RecordLayoutData( &aLayoutData, aItemRect );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ nIndex = aLayoutData.GetIndexForPoint( aPnt );
+ }
+
+ return nIndex;
+ }
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ OUString sText = implGetText();
+ if ( ( 0 > nStartIndex ) || ( sText.getLength() <= nStartIndex )
+ || ( 0 > nEndIndex ) || ( sText.getLength() <= nEndIndex ) )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nLen = nEndIndex - nStartIndex + 1;
+ ::svt::OStringTransfer::CopyString( sText.copy( nStartIndex, nLen ), m_pTreeListBox );
+
+ return true;
+ }
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+ {
+ return false;
+ }
+
+ // XAccessibleEventBroadcaster
+
+ void SAL_CALL AccessibleListBoxEntry::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+ {
+ if (xListener.is())
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (!m_nClientId)
+ m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
+ }
+ }
+
+ void SAL_CALL AccessibleListBoxEntry::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+ {
+ if (!xListener.is())
+ return;
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ sal_Int32 nId = m_nClientId;
+ m_nClientId = 0;
+ comphelper::AccessibleEventNotifier::revokeClient( nId );
+
+ }
+ }
+
+ // XAccessibleAction
+
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleActionCount( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // three actions supported
+ SvTreeFlags treeFlag = m_pTreeListBox->GetTreeFlags();
+ bool bHasButtons = (m_pTreeListBox->GetStyle() & WB_HASBUTTONS)!=0;
+ if( (treeFlag & SvTreeFlags::CHKBTN) && !bHasButtons)
+ {
+ sal_Int16 role = getAccessibleRole();
+ if ( role == AccessibleRole::CHECK_BOX )
+ return 2;
+ else if ( role == AccessibleRole::LABEL )
+ return 0;
+ }
+ else
+ return ACCESSIBLE_ACTION_COUNT;
+ return 0;
+ }
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::doAccessibleAction( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bRet = false;
+ checkActionIndex_Impl( nIndex );
+ EnsureIsAlive();
+
+ SvTreeFlags treeFlag = m_pTreeListBox->GetTreeFlags();
+ if( nIndex == 0 && (treeFlag & SvTreeFlags::CHKBTN) )
+ {
+ if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ SvButtonState state = m_pTreeListBox->GetCheckButtonState( pEntry );
+ if ( state == SvButtonState::Checked )
+ m_pTreeListBox->SetCheckButtonState(pEntry, SvButtonState::Unchecked);
+ else if (state == SvButtonState::Unchecked)
+ m_pTreeListBox->SetCheckButtonState(pEntry, SvButtonState::Checked);
+ }
+ }
+ else if( (nIndex == 1 && (treeFlag & SvTreeFlags::CHKBTN) ) || (nIndex == 0) )
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ if ( m_pTreeListBox->IsExpanded( pEntry ) )
+ m_pTreeListBox->Collapse( pEntry );
+ else
+ m_pTreeListBox->Expand( pEntry );
+ bRet = true;
+ }
+ }
+
+ return bRet;
+ }
+
+ OUString SAL_CALL AccessibleListBoxEntry::getAccessibleActionDescription( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ checkActionIndex_Impl( nIndex );
+ EnsureIsAlive();
+
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ SvButtonState state = m_pTreeListBox->GetCheckButtonState( pEntry );
+ SvTreeFlags treeFlag = m_pTreeListBox->GetTreeFlags();
+ if(nIndex == 0 && (treeFlag & SvTreeFlags::CHKBTN))
+ {
+ if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
+ {
+ if ( state == SvButtonState::Checked )
+ return "UnCheck";
+ else if (state == SvButtonState::Unchecked)
+ return "Check";
+ }
+ else
+ {
+ //Sometimes, a List or Tree may have both checkbox and label at the same time
+ return OUString();
+ }
+ }else if( (nIndex == 1 && (treeFlag & SvTreeFlags::CHKBTN)) || nIndex == 0 )
+ {
+ if( pEntry->HasChildren() || pEntry->HasChildrenOnDemand() )
+ return m_pTreeListBox->IsExpanded( pEntry ) ?
+ AccResId(STR_SVT_ACC_ACTION_COLLAPSE) :
+ AccResId(STR_SVT_ACC_ACTION_EXPAND);
+ return OUString();
+
+ }
+ throw IndexOutOfBoundsException();
+ }
+
+ Reference< XAccessibleKeyBinding > AccessibleListBoxEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XAccessibleKeyBinding > xRet;
+ checkActionIndex_Impl( nIndex );
+ // ... which key?
+ return xRet;
+ }
+
+ // XAccessibleSelection
+
+ void SAL_CALL AccessibleListBoxEntry::selectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ SvTreeListEntry* pEntry = GetRealChild(nChildIndex);
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ m_pTreeListBox->Select( pEntry );
+ }
+
+ sal_Bool SAL_CALL AccessibleListBoxEntry::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, nChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ return m_pTreeListBox->IsSelected( pEntry );
+ }
+
+ void SAL_CALL AccessibleListBoxEntry::clearAccessibleSelection( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( !pParent )
+ throw RuntimeException("AccessibleListBoxEntry::clearAccessibleSelection - pParent cannot be empty!");
+ sal_Int32 nCount = m_pTreeListBox->GetLevelChildCount( pParent );
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, i );
+ if ( m_pTreeListBox->IsSelected( pEntry ) )
+ m_pTreeListBox->Select( pEntry, false );
+ }
+ }
+
+ void SAL_CALL AccessibleListBoxEntry::selectAllAccessibleChildren( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( !pParent )
+ throw RuntimeException("AccessibleListBoxEntry::selectAllAccessibleChildren - pParent cannot be empty!");
+ sal_Int32 nCount = m_pTreeListBox->GetLevelChildCount( pParent );
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, i );
+ if ( !m_pTreeListBox->IsSelected( pEntry ) )
+ m_pTreeListBox->Select( pEntry );
+ }
+ }
+
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChildCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ sal_Int32 i, nSelCount = 0, nCount = 0;
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( !pParent )
+ throw RuntimeException("AccessibleListBoxEntry::getSelectedAccessibleChildCount - pParent cannot be empty!");
+ nCount = m_pTreeListBox->GetLevelChildCount( pParent );
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, i );
+ if ( m_pTreeListBox->IsSelected( pEntry ) )
+ ++nSelCount;
+ }
+
+ return nSelCount;
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ sal_Int32 i, nSelCount = 0, nCount = 0;
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if ( !pParent )
+ throw RuntimeException("AccessibleListBoxEntry::getSelectedAccessibleChild - pParent cannot be empty!");
+ nCount = m_pTreeListBox->GetLevelChildCount( pParent );
+ for ( i = 0; i < nCount; ++i )
+ {
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, i );
+ if ( m_pTreeListBox->IsSelected( pEntry ) )
+ ++nSelCount;
+
+ if ( nSelCount == ( nSelectedChildIndex + 1 ) )
+ {
+ uno::Reference<XAccessible> xListBox(m_wListBox);
+ assert(xListBox.is());
+ xChild = m_rListBox.implGetAccessible(*pEntry).get();
+ break;
+ }
+ }
+
+ return xChild;
+ }
+
+ void SAL_CALL AccessibleListBoxEntry::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ EnsureIsAlive();
+
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ SvTreeListEntry* pEntry = m_pTreeListBox->GetEntry( pParent, nSelectedChildIndex );
+ if ( !pEntry )
+ throw IndexOutOfBoundsException();
+
+ m_pTreeListBox->Select( pEntry, false );
+ }
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getCaretPosition( )
+ {
+ return -1;
+ }
+ sal_Bool SAL_CALL AccessibleListBoxEntry::setCaretPosition ( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ sal_Unicode SAL_CALL AccessibleListBoxEntry::getCharacter( sal_Int32 nIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+ }
+ css::uno::Sequence< css::beans::PropertyValue > SAL_CALL AccessibleListBoxEntry::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return css::uno::Sequence< css::beans::PropertyValue >();
+ }
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getCharacterCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return implGetText().getLength();
+ }
+
+ OUString SAL_CALL AccessibleListBoxEntry::getSelectedText( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OUString();
+ }
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionStart( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return 0;
+ }
+ sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionEnd( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return 0;
+ }
+ sal_Bool SAL_CALL AccessibleListBoxEntry::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+ }
+ OUString SAL_CALL AccessibleListBoxEntry::getText( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return implGetText( );
+ }
+ OUString SAL_CALL AccessibleListBoxEntry::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
+ }
+ css::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+ EnsureIsAlive();
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
+ }
+
+ // XAccessibleValue
+
+
+ Any AccessibleListBoxEntry::getCurrentValue( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Any aValue;
+ sal_Int32 level = static_cast<sal_Int32>(m_aEntryPath.size()) - 1;
+ level = level < 0 ? 0: level;
+ aValue <<= level;
+ return aValue;
+ }
+
+
+ sal_Bool AccessibleListBoxEntry::setCurrentValue( const Any& aNumber )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+
+ bool bReturn = false;
+ SvTreeListBox* pBox = m_pTreeListBox;
+ if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
+ {
+ SvTreeListEntry* pEntry = pBox->GetEntryFromPath( m_aEntryPath );
+ if ( pEntry )
+ {
+ sal_Int32 nValue(0), nValueMin(0), nValueMax(0);
+ aNumber >>= nValue;
+ getMinimumValue() >>= nValueMin;
+ getMaximumValue() >>= nValueMax;
+
+ if ( nValue < nValueMin )
+ nValue = nValueMin;
+ else if ( nValue > nValueMax )
+ nValue = nValueMax;
+
+ pBox->SetCheckButtonState(pEntry, static_cast<SvButtonState>(nValue) );
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+ }
+
+
+ Any AccessibleListBoxEntry::getMaximumValue( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Any aValue;
+ // SvTreeListBox* pBox = m_pTreeListBox;
+ switch(getAccessibleRole())
+ {
+ case AccessibleRole::CHECK_BOX:
+ aValue <<= sal_Int32(1);
+ break;
+ case AccessibleRole::LABEL:
+ default:
+ break;
+ }
+
+ return aValue;
+ }
+
+
+ Any AccessibleListBoxEntry::getMinimumValue( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Any aValue;
+ // SvTreeListBox* pBox = m_pTreeListBox;
+ switch(getAccessibleRole())
+ {
+ case AccessibleRole::CHECK_BOX:
+ aValue <<= sal_Int32(0);
+ break;
+ case AccessibleRole::LABEL:
+ default:
+ break;
+ }
+
+ return aValue;
+ }
+
+ Any AccessibleListBoxEntry::getMinimumIncrement( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Any aValue;
+ switch(getAccessibleRole())
+ {
+ case AccessibleRole::CHECK_BOX:
+ aValue <<= sal_Int32(1);
+ break;
+ case AccessibleRole::LABEL:
+ default:
+ break;
+ }
+
+ return aValue;
+ }
+
+ SvTreeListEntry* AccessibleListBoxEntry::GetRealChild(sal_Int32 nIndex)
+ {
+ SvTreeListEntry* pEntry = nullptr;
+ SvTreeListEntry* pParent = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
+ if (pParent)
+ {
+ pEntry = m_pTreeListBox->GetEntry( pParent, nIndex );
+ if ( !pEntry && getAccessibleChildCount() > 0 )
+ {
+ m_pTreeListBox->RequestingChildren(pParent);
+ pEntry = m_pTreeListBox->GetEntry( pParent, nIndex );
+ }
+ }
+ return pEntry;
+ }
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletabbar.cxx b/accessibility/source/extended/accessibletabbar.cxx
new file mode 100644
index 000000000..8bf2d7add
--- /dev/null
+++ b/accessibility/source/extended/accessibletabbar.cxx
@@ -0,0 +1,507 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletabbar.hxx>
+#include <svtools/tabbar.hxx>
+#include <extended/accessibletabbarpagelist.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/awt/vclxfont.hxx>
+#include <toolkit/helper/convert.hxx>
+
+
+namespace accessibility
+{
+
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::comphelper;
+
+
+
+
+ AccessibleTabBar::AccessibleTabBar( TabBar* pTabBar )
+ :AccessibleTabBarBase( pTabBar )
+ {
+ if ( m_pTabBar )
+ m_aAccessibleChildren.assign( m_pTabBar->GetAccessibleChildWindowCount() + 1, Reference< XAccessible >() );
+ }
+
+
+ void AccessibleTabBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ Any aOldValue, aNewValue;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowEnabled:
+ {
+ aNewValue <<= AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ aNewValue <<= AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowDisabled:
+ {
+ aOldValue <<= AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ aOldValue <<= AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowGetFocus:
+ {
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowLoseFocus:
+ {
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowShow:
+ {
+ aNewValue <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowHide:
+ {
+ aOldValue <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ default:
+ {
+ AccessibleTabBarBase::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ }
+ }
+
+
+ void AccessibleTabBar::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+ {
+ if ( !m_pTabBar )
+ return;
+
+ if ( m_pTabBar->IsEnabled() )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( m_pTabBar->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if ( m_pTabBar->IsVisible() )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ if ( m_pTabBar->GetStyle() & WB_SIZEABLE )
+ rStateSet.AddState( AccessibleStateType::RESIZABLE );
+ }
+
+
+ // OCommonAccessibleComponent
+
+
+ awt::Rectangle AccessibleTabBar::implGetBounds()
+ {
+ awt::Rectangle aBounds;
+ if ( m_pTabBar )
+ aBounds = AWTRectangle( tools::Rectangle( m_pTabBar->GetPosPixel(), m_pTabBar->GetSizePixel() ) );
+
+ return aBounds;
+ }
+
+
+ // XInterface
+
+
+ IMPLEMENT_FORWARD_XINTERFACE2( AccessibleTabBar, OAccessibleExtendedComponentHelper, AccessibleTabBar_BASE )
+
+
+ // XTypeProvider
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleTabBar, OAccessibleExtendedComponentHelper, AccessibleTabBar_BASE )
+
+
+ // XComponent
+
+
+ void AccessibleTabBar::disposing()
+ {
+ AccessibleTabBarBase::disposing();
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+
+ // XServiceInfo
+
+
+ OUString AccessibleTabBar::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTabBar";
+ }
+
+
+ sal_Bool AccessibleTabBar::supportsService( const OUString& rServiceName )
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+
+ Sequence< OUString > AccessibleTabBar::getSupportedServiceNames()
+ {
+ return { "com.sun.star.awt.AccessibleTabBar" };
+ }
+
+
+ // XAccessible
+
+
+ Reference< XAccessibleContext > AccessibleTabBar::getAccessibleContext( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return this;
+ }
+
+
+ // XAccessibleContext
+
+
+ sal_Int32 AccessibleTabBar::getAccessibleChildCount()
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+ }
+
+
+ Reference< XAccessible > AccessibleTabBar::getAccessibleChild( sal_Int32 i )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pTabBar )
+ {
+ sal_Int32 nCount = m_pTabBar->GetAccessibleChildWindowCount();
+
+ if ( i < nCount )
+ {
+ vcl::Window* pChild = m_pTabBar->GetAccessibleChildWindow( static_cast<sal_uInt16>(i) );
+ if ( pChild )
+ xChild = pChild->GetAccessible();
+ }
+ else if ( i == nCount )
+ {
+ xChild = new AccessibleTabBarPageList( m_pTabBar, i );
+ }
+
+ // insert into child list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+ }
+
+
+ Reference< XAccessible > AccessibleTabBar::getAccessibleParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabBar )
+ {
+ vcl::Window* pParent = m_pTabBar->GetAccessibleParentWindow();
+ if ( pParent )
+ xParent = pParent->GetAccessible();
+ }
+
+ return xParent;
+ }
+
+
+ sal_Int32 AccessibleTabBar::getAccessibleIndexInParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pTabBar )
+ {
+ vcl::Window* pParent = m_pTabBar->GetAccessibleParentWindow();
+ if ( pParent )
+ {
+ for ( sal_uInt16 i = 0, nCount = pParent->GetAccessibleChildWindowCount(); i < nCount; ++i )
+ {
+ vcl::Window* pChild = pParent->GetAccessibleChildWindow( i );
+ if ( pChild == static_cast< vcl::Window* >( m_pTabBar ) )
+ {
+ nIndexInParent = i;
+ break;
+ }
+ }
+ }
+ }
+
+ return nIndexInParent;
+ }
+
+
+ sal_Int16 AccessibleTabBar::getAccessibleRole( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::PANEL;
+ }
+
+
+ OUString AccessibleTabBar::getAccessibleDescription( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pTabBar )
+ sDescription = m_pTabBar->GetAccessibleDescription();
+
+ return sDescription;
+ }
+
+
+ OUString AccessibleTabBar::getAccessibleName( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ OUString sName;
+ if ( m_pTabBar )
+ sName = m_pTabBar->GetAccessibleName();
+
+ return sName;
+ }
+
+
+ Reference< XAccessibleRelationSet > AccessibleTabBar::getAccessibleRelationSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+ }
+
+
+ Reference< XAccessibleStateSet > AccessibleTabBar::getAccessibleStateSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+ }
+
+
+ Locale AccessibleTabBar::getLocale( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+ }
+
+
+ // XAccessibleComponent
+
+
+ Reference< XAccessible > AccessibleTabBar::getAccessibleAtPoint( const awt::Point& rPoint )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ for ( size_t i = 0; i < m_aAccessibleChildren.size(); ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+ }
+
+
+ void AccessibleTabBar::grabFocus( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pTabBar )
+ m_pTabBar->GrabFocus();
+ }
+
+
+ sal_Int32 AccessibleTabBar::getForeground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pTabBar )
+ {
+ if ( m_pTabBar->IsControlForeground() )
+ nColor = m_pTabBar->GetControlForeground();
+ else
+ {
+ vcl::Font aFont;
+ if ( m_pTabBar->IsControlFont() )
+ aFont = m_pTabBar->GetControlFont();
+ else
+ aFont = m_pTabBar->GetFont();
+ nColor = aFont.GetColor();
+ }
+ }
+
+ return sal_Int32(nColor);
+ }
+
+
+ sal_Int32 AccessibleTabBar::getBackground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pTabBar )
+ {
+ if ( m_pTabBar->IsControlBackground() )
+ nColor = m_pTabBar->GetControlBackground();
+ else
+ nColor = m_pTabBar->GetBackground().GetColor();
+ }
+
+ return sal_Int32(nColor);
+ }
+
+
+ // XAccessibleExtendedComponent
+
+
+ Reference< awt::XFont > AccessibleTabBar::getFont( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ if ( m_pTabBar )
+ {
+ Reference< awt::XDevice > xDev( m_pTabBar->GetComponentInterface(), UNO_QUERY );
+ if ( xDev.is() )
+ {
+ vcl::Font aFont;
+ if ( m_pTabBar->IsControlFont() )
+ aFont = m_pTabBar->GetControlFont();
+ else
+ aFont = m_pTabBar->GetFont();
+ rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont;
+ pVCLXFont->Init( *xDev, aFont );
+ xFont = pVCLXFont;
+ }
+ }
+
+ return xFont;
+ }
+
+
+ OUString AccessibleTabBar::getTitledBorderText( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ OUString sText;
+ if ( m_pTabBar )
+ sText = m_pTabBar->GetText();
+
+ return sText;
+ }
+
+
+ OUString AccessibleTabBar::getToolTipText( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ OUString sText;
+ if ( m_pTabBar )
+ sText = m_pTabBar->GetQuickHelpText();
+
+ return sText;
+ }
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletabbarbase.cxx b/accessibility/source/extended/accessibletabbarbase.cxx
new file mode 100644
index 000000000..1e213f071
--- /dev/null
+++ b/accessibility/source/extended/accessibletabbarbase.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletabbarbase.hxx>
+#ifndef ACCESSIBILITY_EXT_ACCESSIBLETABBARPAGELIST
+#include <extended/accessibletabbarpagelist.hxx>
+#endif
+#include <svtools/tabbar.hxx>
+#include <vcl/vclevent.hxx>
+
+
+namespace accessibility
+{
+
+
+AccessibleTabBarBase::AccessibleTabBarBase( TabBar* pTabBar ) :
+ m_pTabBar( nullptr )
+{
+ SetTabBarPointer( pTabBar );
+}
+
+AccessibleTabBarBase::~AccessibleTabBarBase()
+{
+ ClearTabBarPointer();
+}
+
+IMPL_LINK( AccessibleTabBarBase, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ vcl::Window* pEventWindow = rEvent.GetWindow();
+ OSL_ENSURE( pEventWindow, "AccessibleTabBarBase::WindowEventListener: no window!" );
+
+ if( ( rEvent.GetId() == VclEventId::TabbarPageRemoved ) &&
+ ( static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rEvent.GetData())) == TabBar::PAGE_NOT_FOUND ) &&
+ (dynamic_cast<AccessibleTabBarPageList *>(this) == nullptr))
+ {
+ return;
+ }
+
+ if ( !pEventWindow->IsAccessibilityEventsSuppressed() || (rEvent.GetId() == VclEventId::ObjectDying) )
+ ProcessWindowEvent( rEvent );
+}
+
+void AccessibleTabBarBase::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ if( rVclWindowEvent.GetId() == VclEventId::ObjectDying )
+ ClearTabBarPointer();
+}
+
+// XComponent
+
+void AccessibleTabBarBase::disposing()
+{
+ OAccessibleExtendedComponentHelper::disposing();
+ ClearTabBarPointer();
+}
+
+// private
+
+void AccessibleTabBarBase::SetTabBarPointer( TabBar* pTabBar )
+{
+ OSL_ENSURE( !m_pTabBar, "AccessibleTabBarBase::SetTabBarPointer - multiple call" );
+ m_pTabBar = pTabBar;
+ if( m_pTabBar )
+ m_pTabBar->AddEventListener( LINK( this, AccessibleTabBarBase, WindowEventListener ) );
+}
+
+void AccessibleTabBarBase::ClearTabBarPointer()
+{
+ if( m_pTabBar )
+ {
+ m_pTabBar->RemoveEventListener( LINK( this, AccessibleTabBarBase, WindowEventListener ) );
+ m_pTabBar = nullptr;
+ }
+}
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletabbarpage.cxx b/accessibility/source/extended/accessibletabbarpage.cxx
new file mode 100644
index 000000000..197ad78d9
--- /dev/null
+++ b/accessibility/source/extended/accessibletabbarpage.cxx
@@ -0,0 +1,427 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletabbarpage.hxx>
+#include <svtools/tabbar.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+
+namespace accessibility
+{
+
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+ using namespace ::comphelper;
+
+
+
+
+ AccessibleTabBarPage::AccessibleTabBarPage( TabBar* pTabBar, sal_uInt16 nPageId, const Reference< XAccessible >& rxParent )
+ :AccessibleTabBarBase( pTabBar )
+ ,m_nPageId( nPageId )
+ ,m_xParent( rxParent )
+ {
+ m_bShowing = IsShowing();
+ m_bSelected = IsSelected();
+
+ if ( m_pTabBar )
+ m_sPageText = m_pTabBar->GetPageText( m_nPageId );
+ }
+
+
+ bool AccessibleTabBarPage::IsEnabled()
+ {
+ OExternalLockGuard aGuard( this );
+
+ bool bEnabled = false;
+ if ( m_pTabBar )
+ bEnabled = m_pTabBar->IsPageEnabled( m_nPageId );
+
+ return bEnabled;
+ }
+
+
+ bool AccessibleTabBarPage::IsShowing() const
+ {
+ bool bShowing = false;
+
+ if ( m_pTabBar && m_pTabBar->IsVisible() )
+ bShowing = true;
+
+ return bShowing;
+ }
+
+
+ bool AccessibleTabBarPage::IsSelected() const
+ {
+ bool bSelected = false;
+
+ if ( m_pTabBar && m_pTabBar->GetCurPageId() == m_nPageId )
+ bSelected = true;
+
+ return bSelected;
+ }
+
+
+ void AccessibleTabBarPage::SetShowing( bool bShowing )
+ {
+ if ( m_bShowing != bShowing )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bShowing )
+ aOldValue <<= AccessibleStateType::SHOWING;
+ else
+ aNewValue <<= AccessibleStateType::SHOWING;
+ m_bShowing = bShowing;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+
+
+ void AccessibleTabBarPage::SetSelected( bool bSelected )
+ {
+ if ( m_bSelected != bSelected )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+
+
+ void AccessibleTabBarPage::SetPageText( const OUString& sPageText )
+ {
+ if ( m_sPageText != sPageText )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sPageText;
+ aNewValue <<= sPageText;
+ m_sPageText = sPageText;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+ }
+
+
+ void AccessibleTabBarPage::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+ {
+ if ( IsEnabled() )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if ( IsShowing() )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ if ( IsSelected() )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+ }
+
+
+ // OCommonAccessibleComponent
+
+
+ awt::Rectangle AccessibleTabBarPage::implGetBounds()
+ {
+ awt::Rectangle aBounds;
+ if ( m_pTabBar )
+ {
+ // get bounding rectangle relative to the AccessibleTabBar
+ aBounds = AWTRectangle( m_pTabBar->GetPageRect( m_nPageId ) );
+
+ // get position of the AccessibleTabBarPageList relative to the AccessibleTabBar
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentLoc = xParentComponent->getLocation();
+
+ // calculate bounding rectangle relative to the AccessibleTabBarPageList
+ aBounds.X -= aParentLoc.X;
+ aBounds.Y -= aParentLoc.Y;
+ }
+ }
+ }
+
+ return aBounds;
+ }
+
+
+ // XInterface
+
+
+ IMPLEMENT_FORWARD_XINTERFACE2( AccessibleTabBarPage, OAccessibleExtendedComponentHelper, AccessibleTabBarPage_BASE )
+
+
+ // XTypeProvider
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleTabBarPage, OAccessibleExtendedComponentHelper, AccessibleTabBarPage_BASE )
+
+
+ // XComponent
+
+
+ void AccessibleTabBarPage::disposing()
+ {
+ AccessibleTabBarBase::disposing();
+ m_sPageText.clear();
+ }
+
+
+ // XServiceInfo
+
+
+ OUString AccessibleTabBarPage::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTabBarPage";
+ }
+
+
+ sal_Bool AccessibleTabBarPage::supportsService( const OUString& rServiceName )
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+
+ Sequence< OUString > AccessibleTabBarPage::getSupportedServiceNames()
+ {
+ return { "com.sun.star.awt.AccessibleTabBarPage" };
+ }
+
+
+ // XAccessible
+
+
+ Reference< XAccessibleContext > AccessibleTabBarPage::getAccessibleContext( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return this;
+ }
+
+
+ // XAccessibleContext
+
+
+ sal_Int32 AccessibleTabBarPage::getAccessibleChildCount()
+ {
+ return 0;
+ }
+
+
+ Reference< XAccessible > AccessibleTabBarPage::getAccessibleChild( sal_Int32 )
+ {
+ OExternalLockGuard aGuard( this );
+
+ throw IndexOutOfBoundsException();
+ }
+
+
+ Reference< XAccessible > AccessibleTabBarPage::getAccessibleParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_xParent;
+ }
+
+
+ sal_Int32 AccessibleTabBarPage::getAccessibleIndexInParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pTabBar )
+ nIndexInParent = m_pTabBar->GetPagePos( m_nPageId );
+
+ return nIndexInParent;
+ }
+
+
+ sal_Int16 AccessibleTabBarPage::getAccessibleRole( )
+ {
+ return AccessibleRole::PAGE_TAB;
+ }
+
+
+ OUString AccessibleTabBarPage::getAccessibleDescription( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pTabBar )
+ sDescription = m_pTabBar->GetHelpText( m_nPageId );
+
+ return sDescription;
+ }
+
+
+ OUString AccessibleTabBarPage::getAccessibleName( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_sPageText;
+ }
+
+
+ Reference< XAccessibleRelationSet > AccessibleTabBarPage::getAccessibleRelationSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+ }
+
+
+ Reference< XAccessibleStateSet > AccessibleTabBarPage::getAccessibleStateSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+ }
+
+
+ Locale AccessibleTabBarPage::getLocale( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+ }
+
+
+ // XAccessibleComponent
+
+
+ Reference< XAccessible > AccessibleTabBarPage::getAccessibleAtPoint( const awt::Point& )
+ {
+ return Reference< XAccessible >();
+ }
+
+
+ void AccessibleTabBarPage::grabFocus( )
+ {
+ // no focus
+ }
+
+
+ sal_Int32 AccessibleTabBarPage::getForeground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+ }
+
+
+ sal_Int32 AccessibleTabBarPage::getBackground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+ }
+
+
+ // XAccessibleExtendedComponent
+
+
+ Reference< awt::XFont > AccessibleTabBarPage::getFont( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+ }
+
+
+ OUString AccessibleTabBarPage::getTitledBorderText( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_sPageText;
+ }
+
+
+ OUString AccessibleTabBarPage::getToolTipText( )
+ {
+ return OUString();
+ }
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletabbarpagelist.cxx b/accessibility/source/extended/accessibletabbarpagelist.cxx
new file mode 100644
index 000000000..a65750fbd
--- /dev/null
+++ b/accessibility/source/extended/accessibletabbarpagelist.cxx
@@ -0,0 +1,692 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletabbarpagelist.hxx>
+#include <svtools/tabbar.hxx>
+#include <extended/accessibletabbarpage.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+
+namespace accessibility
+{
+
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+ using namespace ::comphelper;
+
+
+
+
+ AccessibleTabBarPageList::AccessibleTabBarPageList( TabBar* pTabBar, sal_Int32 nIndexInParent )
+ :AccessibleTabBarBase( pTabBar )
+ ,m_nIndexInParent( nIndexInParent )
+ {
+ if ( m_pTabBar )
+ m_aAccessibleChildren.assign( m_pTabBar->GetPageCount(), Reference< XAccessible >() );
+ }
+
+
+ void AccessibleTabBarPageList::UpdateShowing( bool bShowing )
+ {
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ AccessibleTabBarPage* pAccessibleTabBarPage = static_cast< AccessibleTabBarPage* >( xChild.get() );
+ if ( pAccessibleTabBarPage )
+ pAccessibleTabBarPage->SetShowing( bShowing );
+ }
+ }
+ }
+
+
+ void AccessibleTabBarPageList::UpdateSelected( sal_Int32 i, bool bSelected )
+ {
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ AccessibleTabBarPage* pAccessibleTabBarPage = static_cast< AccessibleTabBarPage* >( xChild.get() );
+ if ( pAccessibleTabBarPage )
+ pAccessibleTabBarPage->SetSelected( bSelected );
+ }
+ }
+ }
+
+
+ void AccessibleTabBarPageList::UpdatePageText( sal_Int32 i )
+ {
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ AccessibleTabBarPage* pAccessibleTabBarPage = static_cast< AccessibleTabBarPage* >( xChild.get() );
+ if ( pAccessibleTabBarPage && m_pTabBar )
+ {
+ OUString sPageText = m_pTabBar->GetPageText( m_pTabBar->GetPageId( static_cast<sal_uInt16>(i) ) );
+ pAccessibleTabBarPage->SetPageText( sPageText );
+ }
+ }
+ }
+
+
+ void AccessibleTabBarPageList::InsertChild( sal_Int32 i )
+ {
+ if ( i < 0 || o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ return;
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // send accessible child event
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ }
+
+
+ void AccessibleTabBarPageList::RemoveChild( sal_Int32 i )
+ {
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // get the accessible of the removed page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ }
+
+
+ void AccessibleTabBarPageList::MoveChild( sal_Int32 i, sal_Int32 j )
+ {
+ if ( !(i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() &&
+ j >= 0 && o3tl::make_unsigned(j) <= m_aAccessibleChildren.size()) )
+ return;
+
+ if ( i < j )
+ --j;
+
+ // get the accessible of the moved page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list at old position
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // insert entry in child list at new position
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + j, xChild );
+ }
+
+
+ void AccessibleTabBarPageList::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowEnabled:
+ {
+ Any aNewValue;
+ aNewValue <<= AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), aNewValue );
+ aNewValue <<= AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), aNewValue );
+ }
+ break;
+ case VclEventId::WindowDisabled:
+ {
+ Any aOldValue;
+ aOldValue <<= AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, Any() );
+ aOldValue <<= AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, Any() );
+ }
+ break;
+ case VclEventId::WindowShow:
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ UpdateShowing( true );
+ }
+ break;
+ case VclEventId::WindowHide:
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ UpdateShowing( false );
+ }
+ break;
+ case VclEventId::TabbarPageSelected:
+ {
+ // do nothing
+ }
+ break;
+ case VclEventId::TabbarPageActivated:
+ {
+ if ( m_pTabBar )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabBar->GetPagePos( nPageId );
+ UpdateSelected( nPagePos, true );
+ }
+ }
+ break;
+ case VclEventId::TabbarPageDeactivated:
+ {
+ if ( m_pTabBar )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabBar->GetPagePos( nPageId );
+ UpdateSelected( nPagePos, false );
+ }
+ }
+ break;
+ case VclEventId::TabbarPageInserted:
+ {
+ if ( m_pTabBar )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabBar->GetPagePos( nPageId );
+ InsertChild( nPagePos );
+ }
+ }
+ break;
+ case VclEventId::TabbarPageRemoved:
+ {
+ if ( m_pTabBar )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+
+ if ( nPageId == TabBar::PAGE_NOT_FOUND )
+ {
+ for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
+ RemoveChild( i );
+ }
+ else
+ {
+ for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ AccessibleTabBarPage* pAccessibleTabBarPage = static_cast< AccessibleTabBarPage* >( xChild.get() );
+ if ( pAccessibleTabBarPage && pAccessibleTabBarPage->GetPageId() == nPageId )
+ {
+ RemoveChild( i );
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::TabbarPageMoved:
+ {
+ Pair* pPair = static_cast<Pair*>(rVclWindowEvent.GetData());
+ if ( pPair )
+ MoveChild( pPair->A(), pPair->B() );
+ }
+ break;
+ case VclEventId::TabbarPageTextChanged:
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabBar->GetPagePos( nPageId );
+ UpdatePageText( nPagePos );
+ }
+ break;
+ default:
+ {
+ AccessibleTabBarBase::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ }
+ }
+
+
+ void AccessibleTabBarPageList::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+ {
+ if ( !m_pTabBar )
+ return;
+
+ if ( m_pTabBar->IsEnabled() )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if ( m_pTabBar->IsVisible() )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ }
+
+
+ // OCommonAccessibleComponent
+
+
+ awt::Rectangle AccessibleTabBarPageList::implGetBounds()
+ {
+ awt::Rectangle aBounds;
+ if ( m_pTabBar )
+ aBounds = AWTRectangle( m_pTabBar->GetPageArea() );
+
+ return aBounds;
+ }
+
+
+ // XInterface
+
+
+ IMPLEMENT_FORWARD_XINTERFACE2( AccessibleTabBarPageList, OAccessibleExtendedComponentHelper, AccessibleTabBarPageList_BASE )
+
+
+ // XTypeProvider
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleTabBarPageList, OAccessibleExtendedComponentHelper, AccessibleTabBarPageList_BASE )
+
+
+ // XComponent
+
+
+ void AccessibleTabBarPageList::disposing()
+ {
+ AccessibleTabBarBase::disposing();
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+
+ // XServiceInfo
+
+
+ OUString AccessibleTabBarPageList::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTabBarPageList";
+ }
+
+
+ sal_Bool AccessibleTabBarPageList::supportsService( const OUString& rServiceName )
+ {
+ return cppu::supportsService(this, rServiceName);
+ }
+
+
+ Sequence< OUString > AccessibleTabBarPageList::getSupportedServiceNames()
+ {
+ return { "com.sun.star.awt.AccessibleTabBarPageList" };
+ }
+
+
+ // XAccessible
+
+
+ Reference< XAccessibleContext > AccessibleTabBarPageList::getAccessibleContext( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return this;
+ }
+
+
+ // XAccessibleContext
+
+
+ sal_Int32 AccessibleTabBarPageList::getAccessibleChildCount()
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+ }
+
+
+ Reference< XAccessible > AccessibleTabBarPageList::getAccessibleChild( sal_Int32 i )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pTabBar )
+ {
+ sal_uInt16 nPageId = m_pTabBar->GetPageId( static_cast<sal_uInt16>(i) );
+
+ xChild = new AccessibleTabBarPage( m_pTabBar, nPageId, this );
+
+ // insert into child list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+ }
+
+
+ Reference< XAccessible > AccessibleTabBarPageList::getAccessibleParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabBar )
+ xParent = m_pTabBar->GetAccessible();
+
+ return xParent;
+ }
+
+
+ sal_Int32 AccessibleTabBarPageList::getAccessibleIndexInParent( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return m_nIndexInParent;
+ }
+
+
+ sal_Int16 AccessibleTabBarPageList::getAccessibleRole( )
+ {
+ return AccessibleRole::PAGE_TAB_LIST;
+ }
+
+
+ OUString AccessibleTabBarPageList::getAccessibleDescription( )
+ {
+ return OUString();
+ }
+
+
+ OUString AccessibleTabBarPageList::getAccessibleName( )
+ {
+ return OUString();
+ }
+
+
+ Reference< XAccessibleRelationSet > AccessibleTabBarPageList::getAccessibleRelationSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+ }
+
+
+ Reference< XAccessibleStateSet > AccessibleTabBarPageList::getAccessibleStateSet( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+ }
+
+
+ Locale AccessibleTabBarPageList::getLocale( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+ }
+
+
+ // XAccessibleComponent
+
+
+ Reference< XAccessible > AccessibleTabBarPageList::getAccessibleAtPoint( const awt::Point& rPoint )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ for ( size_t i = 0; i < m_aAccessibleChildren.size(); ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+ }
+
+
+ void AccessibleTabBarPageList::grabFocus( )
+ {
+ // no focus
+ }
+
+
+ sal_Int32 AccessibleTabBarPageList::getForeground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+ }
+
+
+ sal_Int32 AccessibleTabBarPageList::getBackground( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+ }
+
+
+ // XAccessibleExtendedComponent
+
+
+ Reference< awt::XFont > AccessibleTabBarPageList::getFont( )
+ {
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+ }
+
+
+ OUString AccessibleTabBarPageList::getTitledBorderText( )
+ {
+ return OUString();
+ }
+
+
+ OUString AccessibleTabBarPageList::getToolTipText( )
+ {
+ return OUString();
+ }
+
+
+ // XAccessibleSelection
+
+
+ void AccessibleTabBarPageList::selectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pTabBar )
+ {
+ m_pTabBar->SetCurPageId( m_pTabBar->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) );
+ m_pTabBar->PaintImmediately();
+ m_pTabBar->ActivatePage();
+ m_pTabBar->Select();
+ }
+ }
+
+
+ sal_Bool AccessibleTabBarPageList::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ bool bSelected = false;
+ if ( m_pTabBar && m_pTabBar->GetCurPageId() == m_pTabBar->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) )
+ bSelected = true;
+
+ return bSelected;
+ }
+
+
+ void AccessibleTabBarPageList::clearAccessibleSelection( )
+ {
+ // This method makes no sense in a TabBar, and so does nothing.
+ }
+
+
+ void AccessibleTabBarPageList::selectAllAccessibleChildren( )
+ {
+ selectAccessibleChild( 0 );
+ }
+
+
+ sal_Int32 AccessibleTabBarPageList::getSelectedAccessibleChildCount( )
+ {
+ return 1;
+ }
+
+
+ Reference< XAccessible > AccessibleTabBarPageList::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
+ {
+ if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
+ {
+ xChild = getAccessibleChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+ }
+
+
+ void AccessibleTabBarPageList::deselectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ // This method makes no sense in a TabBar, and so does nothing.
+ }
+
+
+} // namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletablistbox.cxx b/accessibility/source/extended/accessibletablistbox.cxx
new file mode 100644
index 000000000..e34f1896f
--- /dev/null
+++ b/accessibility/source/extended/accessibletablistbox.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletablistbox.hxx>
+#include <extended/accessibletablistboxtable.hxx>
+#include <vcl/toolkit/svtabbx.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+namespace accessibility
+{
+
+
+ // class AccessibleTabListBox -----------------------------------------------------
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleTabListBox::AccessibleTabListBox( const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox )
+ :AccessibleBrowseBox( rxParent, nullptr, rBox )
+ ,m_pTabListBox( &rBox )
+ {
+ osl_atomic_increment( &m_refCount );
+ {
+ setCreator( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+
+ AccessibleTabListBox::~AccessibleTabListBox()
+ {
+ if ( isAlive() )
+ {
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ }
+
+ rtl::Reference<AccessibleBrowseBoxTable> AccessibleTabListBox::createAccessibleTable()
+ {
+ return new AccessibleTabListBoxTable( this, *m_pTabListBox );
+ }
+
+ // XInterface -----------------------------------------------------------------
+ IMPLEMENT_FORWARD_XINTERFACE2( AccessibleTabListBox, AccessibleBrowseBox, AccessibleTabListBox_Base )
+
+ // XTypeProvider --------------------------------------------------------------
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleTabListBox, AccessibleBrowseBox, AccessibleTabListBox_Base )
+
+ // XAccessibleContext ---------------------------------------------------------
+
+ sal_Int32 SAL_CALL AccessibleTabListBox::getAccessibleChildCount()
+ {
+ return 2; // header and table
+ }
+
+ Reference< XAccessibleContext > SAL_CALL AccessibleTabListBox::getAccessibleContext()
+ {
+ return this;
+ }
+
+ Reference< XAccessible > SAL_CALL
+ AccessibleTabListBox::getAccessibleChild( sal_Int32 nChildIndex )
+ {
+ SolarMethodGuard aGuard(getMutex());
+ ensureIsAlive();
+
+ if ( nChildIndex < 0 || nChildIndex > 1 )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xRet;
+ if (nChildIndex == 0)
+ {
+ //! so far the actual implementation object only supports column headers
+ xRet = implGetHeaderBar( AccessibleBrowseBoxObjType::ColumnHeaderBar );
+ }
+ else if (nChildIndex == 1)
+ xRet = implGetTable();
+
+ if ( !xRet.is() )
+ throw RuntimeException();
+
+ return xRet;
+ }
+
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/accessibletablistboxtable.cxx b/accessibility/source/extended/accessibletablistboxtable.cxx
new file mode 100644
index 000000000..14d48bcad
--- /dev/null
+++ b/accessibility/source/extended/accessibletablistboxtable.cxx
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <extended/accessibletablistboxtable.hxx>
+#include <extended/AccessibleBrowseBoxTableCell.hxx>
+#include <extended/AccessibleBrowseBoxCheckBoxCell.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/toolkit/svtabbx.hxx>
+
+namespace accessibility
+{
+
+
+ // class AccessibleTabListBoxTable ---------------------------------------------
+
+ using namespace ::com::sun::star::accessibility;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star;
+
+
+ // Ctor() and Dtor()
+
+ AccessibleTabListBoxTable::AccessibleTabListBoxTable( const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox ) :
+
+ AccessibleBrowseBoxTable( rxParent, rBox ),
+
+ m_pTabListBox ( &rBox )
+
+ {
+ m_pTabListBox->AddEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
+ }
+
+ AccessibleTabListBoxTable::~AccessibleTabListBoxTable()
+ {
+ if ( isAlive() )
+ {
+ m_pTabListBox = nullptr;
+
+ // increment ref count to prevent double call of Dtor
+ osl_atomic_increment( &m_refCount );
+ dispose();
+ }
+ }
+
+ void AccessibleTabListBoxTable::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+ {
+ if ( !isAlive() )
+ return;
+
+ switch ( VclEventId nEventId = rVclWindowEvent.GetId(); nEventId )
+ {
+ case VclEventId::ObjectDying :
+ {
+ m_pTabListBox->RemoveEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) );
+ m_pTabListBox = nullptr;
+ break;
+ }
+
+ case VclEventId::ControlGetFocus :
+ case VclEventId::ControlLoseFocus :
+ {
+ uno::Any aOldValue, aNewValue;
+ if ( nEventId == VclEventId::ControlGetFocus )
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ else
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
+ break;
+ }
+
+ case VclEventId::ListboxSelect :
+ {
+ // First send an event that tells the listeners of a
+ // modified selection. The active descendant event is
+ // send after that so that the receiving AT has time to
+ // read the text or name of the active child.
+ commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ if ( m_pTabListBox && m_pTabListBox->HasFocus() )
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
+ sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
+ Reference< XAccessible > xChild =
+ m_pTabListBox->CreateAccessibleCell( nRow, nCol );
+ uno::Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue, aOldValue );
+ }
+ }
+ break;
+ }
+ case VclEventId::WindowGetFocus :
+ {
+ uno::Any aOldValue, aNewValue;
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
+ break;
+
+ }
+ case VclEventId::WindowLoseFocus :
+ {
+ uno::Any aOldValue, aNewValue;
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue );
+ break;
+ }
+ case VclEventId::ListboxTreeSelect:
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if (pEntry)
+ {
+ sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
+ Reference< XAccessible > xChild = m_pTabListBox->CreateAccessibleCell( nRow, m_pTabListBox->GetCurrColumn() );
+ TriState eState = TRISTATE_INDET;
+ if ( m_pTabListBox->IsCellCheckBox( nRow, m_pTabListBox->GetCurrColumn(), eState ) )
+ {
+ AccessibleCheckBoxCell* pCell = static_cast< AccessibleCheckBoxCell* >( xChild.get() );
+ pCell->commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ }
+ else
+ {
+ AccessibleBrowseBoxTableCell* pCell = static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() );
+ pCell->commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ }
+ break;
+ case VclEventId::ListboxTreeFocus:
+ {
+ if ( m_pTabListBox && m_pTabListBox->HasFocus() )
+ {
+ uno::Any aOldValue, aNewValue;
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
+ m_xCurChild = m_pTabListBox->CreateAccessibleCell( nRow, m_pTabListBox->GetCurrColumn() );
+ aNewValue <<= m_xCurChild;
+ commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue ,aOldValue);
+ }
+ else
+ {
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue ,aOldValue);
+ }
+ }
+ }
+ break;
+
+ case VclEventId::CheckboxToggle :
+ {
+ if ( m_pTabListBox && m_pTabListBox->HasFocus() )
+ {
+ SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
+ if ( pEntry )
+ {
+ sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry );
+ sal_uInt16 nCol = m_pTabListBox->GetCurrColumn();
+ TriState eState = TRISTATE_INDET;
+ if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) )
+ {
+ Reference< XAccessible > xChild =
+ m_pTabListBox->CreateAccessibleCell( nRow, nCol );
+ AccessibleCheckBoxCell* pCell =
+ static_cast< AccessibleCheckBoxCell* >( xChild.get() );
+ pCell->SetChecked( SvHeaderTabListBox::IsItemChecked( pEntry, nCol ) );
+ }
+ }
+ }
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ IMPL_LINK( AccessibleTabListBoxTable, WindowEventListener, VclWindowEvent&, rEvent, void )
+ {
+ OSL_ENSURE( rEvent.GetWindow() && m_pTabListBox, "no event window" );
+ ProcessWindowEvent( rEvent );
+ }
+ // helpers --------------------------------------------------------------------
+
+ void AccessibleTabListBoxTable::ensureValidIndex( sal_Int32 _nIndex ) const
+ {
+ if ( ( _nIndex < 0 ) || ( _nIndex >= (implGetRowCount() * implGetColumnCount()) ) )
+ throw IndexOutOfBoundsException();
+ }
+
+ void AccessibleTabListBoxTable::implSelectRow( sal_Int32 _nRow, bool _bSelect )
+ {
+ if ( m_pTabListBox )
+ m_pTabListBox->Select( m_pTabListBox->GetEntry( _nRow ), _bSelect );
+ }
+
+ sal_Int32 AccessibleTabListBoxTable::implGetRowCount() const
+ {
+ return m_pTabListBox ? m_pTabListBox->GetEntryCount() : 0;
+ }
+
+ sal_Int32 AccessibleTabListBoxTable::implGetColumnCount() const
+ {
+ return m_pTabListBox ? m_pTabListBox->GetColumnCount() : 0;
+ }
+
+ sal_Int32 AccessibleTabListBoxTable::implGetSelRowCount() const
+ {
+ return m_pTabListBox ? m_pTabListBox->GetSelectionCount() : 0;
+ }
+
+ sal_Int32 AccessibleTabListBoxTable::implGetSelRow( sal_Int32 nSelRow ) const
+ {
+ if ( m_pTabListBox )
+ {
+ sal_Int32 nRow = 0;
+ SvTreeListEntry* pEntry = m_pTabListBox->FirstSelected();
+ while ( pEntry )
+ {
+ ++nRow;
+ if ( nRow == nSelRow )
+ return m_pTabListBox->GetEntryPos( pEntry );
+ pEntry = m_pTabListBox->NextSelected( pEntry );
+ }
+ }
+
+ return 0;
+ }
+
+ // XInterface & XTypeProvider
+
+ IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper)
+
+ // XServiceInfo
+
+ OUString AccessibleTabListBoxTable::getImplementationName()
+ {
+ return "com.sun.star.comp.svtools.AccessibleTabListBoxTable";
+ }
+
+ // XAccessibleSelection
+
+ void SAL_CALL AccessibleTabListBoxTable::selectAccessibleChild( sal_Int32 nChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+ ensureValidIndex( nChildIndex );
+
+ implSelectRow( implGetRow( nChildIndex ), true );
+ }
+
+ sal_Bool SAL_CALL AccessibleTabListBoxTable::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+ ensureValidIndex( nChildIndex );
+
+ return m_pTabListBox && m_pTabListBox->IsSelected( m_pTabListBox->GetEntry( implGetRow( nChildIndex ) ) );
+ }
+
+ void SAL_CALL AccessibleTabListBoxTable::clearAccessibleSelection( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+
+ m_pTabListBox->SetNoSelection();
+ }
+
+ void SAL_CALL AccessibleTabListBoxTable::selectAllAccessibleChildren( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+
+ m_pTabListBox->SelectAll();
+ }
+
+ sal_Int32 SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChildCount( )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+
+ return implGetColumnCount() * implGetSelRowCount();
+ }
+
+ Reference< XAccessible > SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+
+ sal_Int32 nRows = implGetSelRowCount();
+ if ( nRows == 0 )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nRow = implGetSelRow( nSelectedChildIndex % nRows );
+ sal_Int32 nColumn = nSelectedChildIndex / nRows;
+ return getAccessibleCellAt( nRow, nColumn );
+ }
+
+ void SAL_CALL AccessibleTabListBoxTable::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( getMutex() );
+
+ ensureIsAlive();
+ ensureValidIndex( nSelectedChildIndex );
+
+ implSelectRow( implGetRow( nSelectedChildIndex ), false );
+ }
+
+
+}// namespace accessibility
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/extended/textwindowaccessibility.cxx b/accessibility/source/extended/textwindowaccessibility.cxx
new file mode 100644
index 000000000..218ba33e6
--- /dev/null
+++ b/accessibility/source/extended/textwindowaccessibility.cxx
@@ -0,0 +1,2271 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/i18n/Boundary.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <extended/textwindowaccessibility.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/txtattr.hxx>
+#include <vcl/window.hxx>
+#include <tools/diagnose_ex.h>
+#include <toolkit/helper/convert.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <algorithm>
+#include <memory>
+#include <numeric>
+#include <vector>
+
+namespace accessibility
+{
+void SfxListenerGuard::startListening(::SfxBroadcaster & rNotifier)
+{
+ assert(m_pNotifier == nullptr && "called more than once");
+ m_pNotifier = &rNotifier;
+ m_rListener.StartListening(*m_pNotifier, DuplicateHandling::Prevent);
+}
+
+void SfxListenerGuard::endListening()
+{
+ if (m_pNotifier != nullptr)
+ {
+ m_rListener.EndListening(*m_pNotifier);
+ m_pNotifier = nullptr;
+ }
+}
+
+void WindowListenerGuard::startListening(vcl::Window & rNotifier)
+{
+ assert(m_pNotifier == nullptr && "called more than once");
+ m_pNotifier = &rNotifier;
+ m_pNotifier->AddEventListener(m_aListener);
+}
+
+void WindowListenerGuard::endListening()
+{
+ if (m_pNotifier)
+ {
+ m_pNotifier->RemoveEventListener(m_aListener);
+ m_pNotifier = nullptr;
+ }
+}
+
+Paragraph::Paragraph(::rtl::Reference< Document > xDocument,
+ Paragraphs::size_type nNumber):
+ ParagraphBase(m_aMutex),
+ m_xDocument(std::move(xDocument)),
+ m_nNumber(nNumber),
+ m_nClientId(0)
+{
+ m_aParagraphText = m_xDocument->retrieveParagraphText(this);
+}
+
+void
+Paragraph::numberChanged(bool bIncremented)
+{
+ if (bIncremented)
+ ++m_nNumber;
+ else
+ --m_nNumber;
+}
+
+void Paragraph::textChanged()
+{
+ OUString aParagraphText = implGetText();
+ css::uno::Any aOldValue, aNewValue;
+ if ( implInitTextChangedEvent( m_aParagraphText, aParagraphText, aOldValue, aNewValue ) )
+ {
+ m_aParagraphText = aParagraphText;
+ notifyEvent(css::accessibility::AccessibleEventId::
+ TEXT_CHANGED,
+ aOldValue, aNewValue);
+ }
+}
+
+void Paragraph::notifyEvent(::sal_Int16 nEventId,
+ css::uno::Any const & rOldValue,
+ css::uno::Any const & rNewValue)
+{
+ if (m_nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( m_nClientId, css::accessibility::AccessibleEventObject(
+ static_cast< ::cppu::OWeakObject * >(this),
+ nEventId, rNewValue, rOldValue) );
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL
+Paragraph::getAccessibleContext()
+{
+ checkDisposed();
+ return this;
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getAccessibleChildCount()
+{
+ checkDisposed();
+ return 0;
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+Paragraph::getAccessibleChild(::sal_Int32)
+{
+ checkDisposed();
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Paragraph::getAccessibleChild",
+ static_cast< css::uno::XWeak * >(this));
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+Paragraph::getAccessibleParent()
+{
+ checkDisposed();
+ return m_xDocument->getAccessible();
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getAccessibleIndexInParent()
+{
+ checkDisposed();
+ return m_xDocument->retrieveParagraphIndex(this);
+}
+
+// virtual
+::sal_Int16 SAL_CALL Paragraph::getAccessibleRole()
+{
+ checkDisposed();
+ return css::accessibility::AccessibleRole::PARAGRAPH;
+}
+
+// virtual
+OUString SAL_CALL Paragraph::getAccessibleDescription()
+{
+ checkDisposed();
+ return OUString();
+}
+
+// virtual
+OUString SAL_CALL Paragraph::getAccessibleName()
+{
+ checkDisposed();
+ return OUString();
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessibleRelationSet >
+SAL_CALL Paragraph::getAccessibleRelationSet()
+{
+ checkDisposed();
+ return m_xDocument->retrieveParagraphRelationSet( this );
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessibleStateSet >
+SAL_CALL Paragraph::getAccessibleStateSet()
+{
+ checkDisposed();
+
+ // FIXME Notification of changes (STATE_CHANGED) missing when
+ // m_rView.IsReadOnly() changes:
+ return new ::utl::AccessibleStateSetHelper(
+ m_xDocument->retrieveParagraphState(this));
+}
+
+// virtual
+css::lang::Locale SAL_CALL Paragraph::getLocale()
+{
+ checkDisposed();
+ return m_xDocument->retrieveLocale();
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::containsPoint(css::awt::Point const & rPoint)
+{
+ checkDisposed();
+ css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
+ false));
+ return rPoint.X >= 0 && rPoint.X < aRect.Width
+ && rPoint.Y >= 0 && rPoint.Y < aRect.Height;
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+Paragraph::getAccessibleAtPoint(css::awt::Point const &)
+{
+ checkDisposed();
+ return nullptr;
+}
+
+// virtual
+css::awt::Rectangle SAL_CALL Paragraph::getBounds()
+{
+ checkDisposed();
+ return m_xDocument->retrieveParagraphBounds(this, false);
+}
+
+// virtual
+css::awt::Point SAL_CALL Paragraph::getLocation()
+{
+ checkDisposed();
+ css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
+ false));
+ return css::awt::Point(aRect.X, aRect.Y);
+}
+
+// virtual
+css::awt::Point SAL_CALL Paragraph::getLocationOnScreen()
+{
+ checkDisposed();
+ css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
+ true));
+ return css::awt::Point(aRect.X, aRect.Y);
+}
+
+// virtual
+css::awt::Size SAL_CALL Paragraph::getSize()
+{
+ checkDisposed();
+ css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
+ false));
+ return css::awt::Size(aRect.Width, aRect.Height);
+}
+
+// virtual
+void SAL_CALL Paragraph::grabFocus()
+{
+ checkDisposed();
+ VclPtr<vcl::Window> pWindow = m_xDocument->GetWindow();
+ if ( pWindow )
+ {
+ pWindow->GrabFocus();
+ }
+ try
+ {
+ m_xDocument->changeParagraphSelection(this, 0, 0);
+ }
+ catch (const css::lang::IndexOutOfBoundsException &)
+ {
+ TOOLS_INFO_EXCEPTION("accessibility", "Paragraph::grabFocus: caught unexpected");
+ }
+}
+
+// virtual
+sal_Int32 SAL_CALL Paragraph::getForeground()
+{
+ return 0; // TODO
+}
+
+// virtual
+sal_Int32 SAL_CALL Paragraph::getBackground()
+{
+ return 0; // TODO
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getCaretPosition()
+{
+ checkDisposed();
+ return m_xDocument->retrieveParagraphCaretPosition(this);
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::setCaretPosition(::sal_Int32 nIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphSelection(this, nIndex, nIndex);
+ return true;
+}
+
+// virtual
+::sal_Unicode SAL_CALL Paragraph::getCharacter(::sal_Int32 nIndex)
+{
+ checkDisposed();
+ return OCommonAccessibleText::implGetCharacter(implGetText(), nIndex);
+}
+
+// virtual
+css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
+Paragraph::getCharacterAttributes(::sal_Int32 nIndex, const css::uno::Sequence< OUString >& aRequestedAttributes)
+{
+ checkDisposed();
+ return m_xDocument->retrieveCharacterAttributes( this, nIndex, aRequestedAttributes );
+}
+
+// virtual
+css::awt::Rectangle SAL_CALL
+Paragraph::getCharacterBounds(::sal_Int32 nIndex)
+{
+ checkDisposed();
+ css::awt::Rectangle aBounds(m_xDocument->retrieveCharacterBounds(this, nIndex));
+ css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
+ aBounds.X -= aParaBounds.X;
+ aBounds.Y -= aParaBounds.Y;
+ return aBounds;
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getCharacterCount()
+{
+ checkDisposed();
+ return implGetText().getLength();
+}
+
+// virtual
+::sal_Int32 SAL_CALL
+Paragraph::getIndexAtPoint(css::awt::Point const & rPoint)
+{
+ checkDisposed();
+ css::awt::Point aPoint(rPoint);
+ css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
+ aPoint.X += aParaBounds.X;
+ aPoint.Y += aParaBounds.Y;
+ return m_xDocument->retrieveCharacterIndex(this, aPoint);
+}
+
+// virtual
+OUString SAL_CALL Paragraph::getSelectedText()
+{
+ checkDisposed();
+
+ return OCommonAccessibleText::getSelectedText();
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getSelectionStart()
+{
+ checkDisposed();
+ return OCommonAccessibleText::getSelectionStart();
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getSelectionEnd()
+{
+ checkDisposed();
+ return OCommonAccessibleText::getSelectionEnd();
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::setSelection(::sal_Int32 nStartIndex,
+ ::sal_Int32 nEndIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphSelection(this, nStartIndex, nEndIndex);
+ return true;
+}
+
+// virtual
+OUString SAL_CALL Paragraph::getText()
+{
+ checkDisposed();
+ return implGetText();
+}
+
+// virtual
+OUString SAL_CALL Paragraph::getTextRange(::sal_Int32 nStartIndex,
+ ::sal_Int32 nEndIndex)
+{
+ checkDisposed();
+ return OCommonAccessibleText::implGetTextRange(implGetText(), nStartIndex, nEndIndex);
+}
+
+// virtual
+css::accessibility::TextSegment SAL_CALL Paragraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ checkDisposed();
+ return OCommonAccessibleText::getTextAtIndex(nIndex, aTextType);
+}
+
+// virtual
+css::accessibility::TextSegment SAL_CALL Paragraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ checkDisposed();
+ return OCommonAccessibleText::getTextBeforeIndex(nIndex, aTextType);
+}
+
+// virtual
+css::accessibility::TextSegment SAL_CALL Paragraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ checkDisposed();
+ return OCommonAccessibleText::getTextBehindIndex(nIndex, aTextType);
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::copyText(::sal_Int32 nStartIndex,
+ ::sal_Int32 nEndIndex)
+{
+ checkDisposed();
+ m_xDocument->copyParagraphText(this, nStartIndex, nEndIndex);
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::scrollSubstringTo( sal_Int32, sal_Int32, css::accessibility::AccessibleScrollType )
+{
+ return false;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::cutText(::sal_Int32 nStartIndex,
+ ::sal_Int32 nEndIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, true, false,
+ OUString());
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::pasteText(::sal_Int32 nIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, nIndex, nIndex, false, true,
+ OUString());
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::deleteText(::sal_Int32 nStartIndex,
+ ::sal_Int32 nEndIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
+ OUString());
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::insertText(OUString const & rText,
+ ::sal_Int32 nIndex)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, nIndex, nIndex, false, false, rText);
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL
+Paragraph::replaceText(::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
+ OUString const & rReplacement)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
+ rReplacement);
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::setAttributes(
+ ::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
+ css::uno::Sequence< css::beans::PropertyValue > const & rAttributeSet)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphAttributes(this, nStartIndex, nEndIndex,
+ rAttributeSet);
+ return true;
+}
+
+// virtual
+sal_Bool SAL_CALL Paragraph::setText(OUString const & rText)
+{
+ checkDisposed();
+ m_xDocument->changeParagraphText(this, rText);
+ return true;
+}
+
+// virtual
+css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
+Paragraph::getDefaultAttributes(const css::uno::Sequence< OUString >&)
+{
+ checkDisposed();
+ return {}; // default attributes are not supported by text engine
+}
+
+// virtual
+css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
+Paragraph::getRunAttributes(::sal_Int32 Index, const css::uno::Sequence< OUString >& RequestedAttributes)
+{
+ checkDisposed();
+ return m_xDocument->retrieveRunAttributes( this, Index, RequestedAttributes );
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getLineNumberAtIndex( ::sal_Int32 nIndex )
+{
+ checkDisposed();
+
+ ::sal_Int32 nLineNo = -1;
+ m_xDocument->retrieveParagraphLineBoundary( this, nIndex, &nLineNo );
+
+ return nLineNo;
+}
+
+// virtual
+css::accessibility::TextSegment SAL_CALL Paragraph::getTextAtLineNumber( ::sal_Int32 nLineNo )
+{
+ checkDisposed();
+
+ css::i18n::Boundary aBoundary =
+ m_xDocument->retrieveParagraphBoundaryOfLine( this, nLineNo );
+
+ return css::accessibility::TextSegment( getTextRange(aBoundary.startPos, aBoundary.endPos),
+ aBoundary.startPos, aBoundary.endPos);
+}
+
+// virtual
+css::accessibility::TextSegment SAL_CALL Paragraph::getTextAtLineWithCaret( )
+{
+ checkDisposed();
+
+ sal_Int32 nLineNo = getNumberOfLineWithCaret();
+
+ try {
+ return ( nLineNo >= 0 ) ?
+ getTextAtLineNumber( nLineNo ) :
+ css::accessibility::TextSegment();
+ } catch (const css::lang::IndexOutOfBoundsException&) {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "textwindowaccessibility.cxx:"
+ " Paragraph::getTextAtLineWithCaret",
+ static_cast< css::uno::XWeak * >( this ), anyEx );
+ }
+}
+
+// virtual
+::sal_Int32 SAL_CALL Paragraph::getNumberOfLineWithCaret( )
+{
+ checkDisposed();
+ return m_xDocument->retrieveParagraphLineWithCursor(this);
+}
+
+
+// virtual
+void SAL_CALL Paragraph::addAccessibleEventListener(
+ css::uno::Reference<
+ css::accessibility::XAccessibleEventListener > const & rListener)
+{
+ if (!rListener.is())
+ return;
+
+ ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ rListener->disposing(css::lang::EventObject(
+ static_cast< ::cppu::OWeakObject * >(this)));
+ }
+ else
+ {
+ if (!m_nClientId)
+ m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, rListener );
+ }
+}
+
+// virtual
+void SAL_CALL Paragraph::removeAccessibleEventListener(
+ css::uno::Reference<
+ css::accessibility::XAccessibleEventListener > const & rListener)
+{
+ comphelper::AccessibleEventNotifier::TClientId nId = 0;
+ {
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+ if (rListener.is() && m_nClientId != 0
+ && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, rListener ) == 0)
+ {
+ nId = m_nClientId;
+ m_nClientId = 0;
+ }
+ }
+ if (nId != 0)
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ comphelper::AccessibleEventNotifier::revokeClient(nId);
+ }
+}
+
+// virtual
+void SAL_CALL Paragraph::disposing()
+{
+ comphelper::AccessibleEventNotifier::TClientId nId = 0;
+ {
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+ nId = m_nClientId;
+ m_nClientId = 0;
+ }
+ if (nId != 0)
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId, *this);
+}
+
+// virtual
+OUString Paragraph::implGetText()
+{
+ return m_xDocument->retrieveParagraphText(this);
+}
+
+// virtual
+css::lang::Locale Paragraph::implGetLocale()
+{
+ return m_xDocument->retrieveLocale();
+}
+
+// virtual
+void Paragraph::implGetSelection(::sal_Int32 & rStartIndex,
+ ::sal_Int32 & rEndIndex)
+{
+ m_xDocument->retrieveParagraphSelection(this, &rStartIndex, &rEndIndex);
+}
+
+// virtual
+void Paragraph::implGetParagraphBoundary( const OUString& rText,
+ css::i18n::Boundary& rBoundary,
+ ::sal_Int32 nIndex )
+{
+ ::sal_Int32 nLength = rText.getLength();
+
+ if ( implIsValidIndex( nIndex, nLength ) )
+ {
+ rBoundary.startPos = 0;
+ rBoundary.endPos = nLength;
+ }
+ else
+ {
+ rBoundary.startPos = nIndex;
+ rBoundary.endPos = nIndex;
+ }
+}
+
+// virtual
+void Paragraph::implGetLineBoundary( const OUString& rText,
+ css::i18n::Boundary& rBoundary,
+ ::sal_Int32 nIndex )
+{
+ ::sal_Int32 nLength = rText.getLength();
+
+ if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
+ {
+ css::i18n::Boundary aBoundary =
+ m_xDocument->retrieveParagraphLineBoundary( this, nIndex, nullptr );
+ rBoundary.startPos = aBoundary.startPos;
+ rBoundary.endPos = aBoundary.endPos;
+ }
+ else
+ {
+ rBoundary.startPos = nIndex;
+ rBoundary.endPos = nIndex;
+ }
+}
+
+
+void Paragraph::checkDisposed()
+{
+ ::osl::MutexGuard aGuard(rBHelper.rMutex);
+ if (!(rBHelper.bDisposed || rBHelper.bInDispose))
+ return;
+ throw css::lang::DisposedException(
+ OUString(), static_cast< css::uno::XWeak * >(this));
+}
+
+Document::Document(::VCLXWindow * pVclXWindow, ::TextEngine & rEngine,
+ ::TextView & rView):
+ VCLXAccessibleComponent(pVclXWindow),
+ m_xAccessible(pVclXWindow),
+ m_rEngine(rEngine),
+ m_rView(rView),
+ m_aEngineListener(*this),
+ m_aViewListener(LINK(this, Document, WindowEventHandler)),
+ m_nViewOffset(0),
+ m_nViewHeight(0),
+ m_nVisibleBeginOffset(0),
+ m_nSelectionFirstPara(-1),
+ m_nSelectionFirstPos(-1),
+ m_nSelectionLastPara(-1),
+ m_nSelectionLastPos(-1),
+ m_bSelectionChangedNotification(false)
+{}
+
+css::lang::Locale Document::retrieveLocale()
+{
+ SolarMutexGuard aGuard;
+ return m_rEngine.GetLocale();
+}
+
+::sal_Int32 Document::retrieveParagraphIndex(Paragraph const * pParagraph)
+{
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+
+ // If a client holds on to a Paragraph that is no longer visible, it can
+ // happen that this Paragraph lies outside the range from m_aVisibleBegin
+ // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
+ Paragraphs::iterator aPara(m_xParagraphs->begin()
+ + pParagraph->getNumber());
+ return aPara < m_aVisibleBegin || aPara >= m_aVisibleEnd
+ ? -1 : static_cast< ::sal_Int32 >(aPara - m_aVisibleBegin);
+ // XXX numeric overflow
+}
+
+::sal_Int64 Document::retrieveParagraphState(Paragraph const * pParagraph)
+{
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+
+ // If a client holds on to a Paragraph that is no longer visible, it can
+ // happen that this Paragraph lies outside the range from m_aVisibleBegin
+ // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
+ ::sal_Int64 nState
+ = (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::ENABLED)
+ | (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::SENSITIVE)
+ | (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::FOCUSABLE)
+ | (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::MULTI_LINE);
+ if (!m_rView.IsReadOnly())
+ nState |= (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::EDITABLE);
+ Paragraphs::iterator aPara(m_xParagraphs->begin()
+ + pParagraph->getNumber());
+ if (aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd)
+ {
+ nState
+ |= (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::VISIBLE)
+ | (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::SHOWING);
+ if (aPara == m_aFocused)
+ nState |= (static_cast< ::sal_Int64 >(1)
+ << css::accessibility::AccessibleStateType::FOCUSED);
+ }
+ return nState;
+};
+
+css::awt::Rectangle
+Document::retrieveParagraphBounds(Paragraph const * pParagraph,
+ bool bAbsolute)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+
+ // If a client holds on to a Paragraph that is no longer visible (as it
+ // scrolled out the top of the view), it can happen that this Paragraph
+ // lies before m_aVisibleBegin. In that case, calculate the vertical
+ // position of the Paragraph starting at paragraph 0, otherwise optimize
+ // and start at m_aVisibleBegin:
+ Paragraphs::iterator aPara(m_xParagraphs->begin()
+ + pParagraph->getNumber());
+ auto lAddHeight = [](const sal_Int32& rSum, const ParagraphInfo& rParagraph) {
+ return rSum + rParagraph.getHeight(); };
+ ::sal_Int32 nPos;
+ if (aPara < m_aVisibleBegin)
+ nPos = std::accumulate(m_xParagraphs->begin(), aPara, sal_Int32(0), lAddHeight);
+ else
+ nPos = std::accumulate(m_aVisibleBegin, aPara, m_nViewOffset - m_nVisibleBeginOffset, lAddHeight);
+
+ Point aOrig(0, 0);
+ if (bAbsolute)
+ aOrig = m_rView.GetWindow()->OutputToAbsoluteScreenPixel(aOrig);
+
+ return css::awt::Rectangle(
+ static_cast< ::sal_Int32 >(aOrig.X()),
+ static_cast< ::sal_Int32 >(aOrig.Y()) + nPos - m_nViewOffset,
+ m_rView.GetWindow()->GetOutputSizePixel().Width(), aPara->getHeight());
+ // XXX numeric overflow (3x)
+}
+
+OUString
+Document::retrieveParagraphText(Paragraph const * pParagraph)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ return m_rEngine.GetText(static_cast< ::sal_uInt32 >(pParagraph->getNumber()));
+ // numeric overflow cannot happen here
+}
+
+void Document::retrieveParagraphSelection(Paragraph const * pParagraph,
+ ::sal_Int32 * pBegin,
+ ::sal_Int32 * pEnd)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::TextSelection const & rSelection = m_rView.GetSelection();
+ Paragraphs::size_type nNumber = pParagraph->getNumber();
+ TextPaM aStartPaM( rSelection.GetStart() );
+ TextPaM aEndPaM( rSelection.GetEnd() );
+ TextPaM aMinPaM( std::min( aStartPaM, aEndPaM ) );
+ TextPaM aMaxPaM( std::max( aStartPaM, aEndPaM ) );
+
+ if ( nNumber >= aMinPaM.GetPara() && nNumber <= aMaxPaM.GetPara() )
+ {
+ *pBegin = nNumber > aMinPaM.GetPara() ? 0 : aMinPaM.GetIndex();
+ // XXX numeric overflow
+ *pEnd = nNumber < aMaxPaM.GetPara()
+ ? m_rEngine.GetText(static_cast< ::sal_uInt32 >(nNumber)).getLength()
+ : aMaxPaM.GetIndex();
+ // XXX numeric overflow (3x)
+
+ if ( aStartPaM > aEndPaM )
+ std::swap( *pBegin, *pEnd );
+ }
+ else
+ {
+ *pBegin = 0;
+ *pEnd = 0;
+ }
+}
+
+::sal_Int32 Document::retrieveParagraphCaretPosition(Paragraph const * pParagraph)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::TextSelection const & rSelection = m_rView.GetSelection();
+ Paragraphs::size_type nNumber = pParagraph->getNumber();
+ TextPaM aEndPaM( rSelection.GetEnd() );
+
+ return aEndPaM.GetPara() == nNumber ? aEndPaM.GetIndex() : -1;
+}
+
+css::awt::Rectangle
+Document::retrieveCharacterBounds(Paragraph const * pParagraph,
+ ::sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ sal_Int32 nLength = m_rEngine.GetText(nNumber).getLength();
+ // XXX numeric overflow
+ if (nIndex < 0 || nIndex > nLength)
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::retrieveCharacterAttributes",
+ static_cast< css::uno::XWeak * >(this));
+ css::awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( nIndex == nLength )
+ {
+ aBounds = AWTRectangle(
+ m_rEngine.PaMtoEditCursor(::TextPaM(nNumber, nIndex)));
+ }
+ else
+ {
+ ::tools::Rectangle aLeft(
+ m_rEngine.PaMtoEditCursor(::TextPaM(nNumber, nIndex)));
+ // XXX numeric overflow
+ ::tools::Rectangle aRight(
+ m_rEngine.PaMtoEditCursor(::TextPaM(nNumber, nIndex + 1)));
+ // XXX numeric overflow (2x)
+ // FIXME If the vertical extends of the two cursors do not match, assume
+ // nIndex is the last character on the line; the bounding box will then
+ // extend to m_rEngine.GetMaxTextWidth():
+ ::sal_Int32 nWidth = (aLeft.Top() == aRight.Top()
+ && aLeft.Bottom() == aRight.Bottom())
+ ? static_cast< ::sal_Int32 >(aRight.Left() - aLeft.Left())
+ : static_cast< ::sal_Int32 >(m_rEngine.GetMaxTextWidth()
+ - aLeft.Left());
+ // XXX numeric overflow (4x)
+ aBounds = css::awt::Rectangle(static_cast< ::sal_Int32 >(aLeft.Left()),
+ static_cast< ::sal_Int32 >(aLeft.Top() - m_nViewOffset),
+ nWidth,
+ static_cast< ::sal_Int32 >(aLeft.Bottom()
+ - aLeft.Top()));
+ // XXX numeric overflow (4x)
+ }
+ return aBounds;
+}
+
+::sal_Int32 Document::retrieveCharacterIndex(Paragraph const * pParagraph,
+ css::awt::Point const & rPoint)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ ::TextPaM aPaM(m_rEngine.GetPaM(::Point(static_cast< tools::Long >(rPoint.X),
+ static_cast< tools::Long >(rPoint.Y))));
+ // XXX numeric overflow (2x)
+ return aPaM.GetPara() == nNumber ? aPaM.GetIndex() : -1;
+ // XXX numeric overflow
+}
+
+css::uno::Sequence< css::beans::PropertyValue >
+Document::retrieveCharacterAttributes(
+ Paragraph const * pParagraph, ::sal_Int32 nIndex,
+ const css::uno::Sequence< OUString >& aRequestedAttributes)
+{
+ SolarMutexGuard aGuard;
+
+ vcl::Font aFont = m_rEngine.GetFont();
+ const sal_Int32 AttributeCount = 9;
+ std::vector< css::beans::PropertyValue > aAttribs;
+ aAttribs.reserve(AttributeCount);
+
+ css::beans::PropertyValue aAttrib;
+ aAttrib.Handle = -1;
+ aAttrib.State = css::beans::PropertyState_DIRECT_VALUE;
+
+ //character background color
+ aAttrib.Name = "CharBackColor";
+ aAttrib.Value = mapFontColor( aFont.GetFillColor() );
+ aAttribs.push_back(aAttrib);
+
+ //character color
+ aAttrib.Name = "CharColor";
+ //aAttrib.Value = mapFontColor( aFont.GetColor() );
+ aAttrib.Value = mapFontColor( m_rEngine.GetTextColor() );
+ aAttribs.push_back(aAttrib);
+
+ //character font name
+ aAttrib.Name = "CharFontName";
+ aAttrib.Value <<= aFont.GetFamilyName();
+ aAttribs.push_back(aAttrib);
+
+ //character height
+ aAttrib.Name = "CharHeight";
+ aAttrib.Value <<= static_cast<sal_Int16>(aFont.GetFontHeight());
+ aAttribs.push_back(aAttrib);
+
+ //character posture
+ aAttrib.Name = "CharPosture";
+ aAttrib.Value <<= static_cast<sal_Int16>(aFont.GetItalic());
+ aAttribs.push_back(aAttrib);
+
+ //character relief
+ /*
+ aAttrib.Name = "CharRelief";
+ aAttrib.Value = css::uno::Any( (sal_Int16)aFont.GetRelief() );
+ aAttribs.push_back(aAttrib);
+ */
+
+ //character strikeout
+ aAttrib.Name = "CharStrikeout";
+ aAttrib.Value <<= static_cast<sal_Int16>(aFont.GetStrikeout());
+ aAttribs.push_back(aAttrib);
+
+ //character underline
+ aAttrib.Name = "CharUnderline";
+ aAttrib.Value <<= static_cast<sal_Int16>(aFont.GetUnderline());
+ aAttribs.push_back(aAttrib);
+
+ //character weight
+ aAttrib.Name = "CharWeight";
+ aAttrib.Value <<= static_cast<float>(aFont.GetWeight());
+ aAttribs.push_back(aAttrib);
+
+ //character alignment
+ aAttrib.Name = "ParaAdjust";
+ aAttrib.Value <<= static_cast<sal_Int16>(m_rEngine.GetTextAlign());
+ aAttribs.push_back(aAttrib);
+
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ // nIndex can be equal to getLength();
+ if (nIndex < 0 || nIndex > m_rEngine.GetText(nNumber).getLength())
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::retrieveCharacterAttributes",
+ static_cast< css::uno::XWeak * >(this));
+
+
+ // retrieve run attributes
+ tPropValMap aCharAttrSeq;
+ retrieveRunAttributesImpl( pParagraph, nIndex, aRequestedAttributes, aCharAttrSeq );
+
+ for (const css::beans::PropertyValue& rAttrib : aAttribs)
+ {
+ aCharAttrSeq[ rAttrib.Name ] = rAttrib;
+ }
+
+ const css::uno::Sequence< css::beans::PropertyValue > aRes = comphelper::mapValuesToSequence( aCharAttrSeq );
+
+ // sort the attributes
+ auto nLength = static_cast<size_t>(aRes.getLength());
+ std::unique_ptr<sal_Int32[]> pIndices( new sal_Int32[nLength] );
+ std::iota(&pIndices[0], &pIndices[nLength], 0);
+ std::sort(&pIndices[0], &pIndices[nLength],
+ [&aRes](sal_Int32 a, sal_Int32 b) { return aRes[a].Name < aRes[b].Name; });
+
+ // create sorted sequences according to index array
+ std::vector<css::beans::PropertyValue> aNewValues;
+ aNewValues.reserve(nLength);
+ std::transform(&pIndices[0], &pIndices[nLength], std::back_inserter(aNewValues),
+ [&aRes](const sal_Int32 nIdx) { return aRes[nIdx]; });
+
+ return comphelper::containerToSequence(aNewValues);
+}
+
+void Document::retrieveRunAttributesImpl(
+ Paragraph const * pParagraph, ::sal_Int32 Index,
+ const css::uno::Sequence< OUString >& RequestedAttributes,
+ tPropValMap& rRunAttrSeq)
+{
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >( pParagraph->getNumber() );
+ ::TextPaM aPaM( nNumber, Index );
+ // XXX numeric overflow
+ ::TextAttribFontColor const * pColor
+ = static_cast< ::TextAttribFontColor const * >(
+ m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTCOLOR ) );
+ ::TextAttribFontWeight const * pWeight
+ = static_cast< ::TextAttribFontWeight const * >(
+ m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTWEIGHT ) );
+ tPropValMap aRunAttrSeq;
+ if ( pColor )
+ {
+ css::beans::PropertyValue aPropVal;
+ aPropVal.Name = "CharColor";
+ aPropVal.Handle = -1;
+ aPropVal.Value = mapFontColor( pColor->GetColor() );
+ aPropVal.State = css::beans::PropertyState_DIRECT_VALUE;
+ aRunAttrSeq[ aPropVal.Name ] = aPropVal;
+ }
+ if ( pWeight )
+ {
+ css::beans::PropertyValue aPropVal;
+ aPropVal.Name = "CharWeight";
+ aPropVal.Handle = -1;
+ aPropVal.Value = mapFontWeight( pWeight->getFontWeight() );
+ aPropVal.State = css::beans::PropertyState_DIRECT_VALUE;
+ aRunAttrSeq[ aPropVal.Name ] = aPropVal;
+ }
+ if ( !RequestedAttributes.hasElements() )
+ {
+ rRunAttrSeq = aRunAttrSeq;
+ }
+ else
+ {
+ for ( const OUString& rReqAttr : RequestedAttributes )
+ {
+ tPropValMap::iterator aIter = aRunAttrSeq.find( rReqAttr );
+ if ( aIter != aRunAttrSeq.end() )
+ {
+ rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
+ }
+ }
+ }
+}
+
+css::uno::Sequence< css::beans::PropertyValue >
+Document::retrieveRunAttributes(
+ Paragraph const * pParagraph, ::sal_Int32 Index,
+ const css::uno::Sequence< OUString >& RequestedAttributes)
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard( GetMutex() );
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >( pParagraph->getNumber() );
+ // XXX numeric overflow
+ if ( Index < 0 || Index >= m_rEngine.GetText(nNumber).getLength() )
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::retrieveRunAttributes",
+ static_cast< css::uno::XWeak * >( this ) );
+
+ tPropValMap aRunAttrSeq;
+ retrieveRunAttributesImpl( pParagraph, Index, RequestedAttributes, aRunAttrSeq );
+ return comphelper::mapValuesToSequence( aRunAttrSeq );
+}
+
+void Document::changeParagraphText(Paragraph const * pParagraph,
+ OUString const & rText)
+{
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ changeParagraphText(nNumber, 0, m_rEngine.GetTextLen(nNumber), false,
+ false, rText);
+ }
+}
+
+void Document::changeParagraphText(Paragraph const * pParagraph,
+ ::sal_Int32 nBegin, ::sal_Int32 nEnd,
+ bool bCut, bool bPaste,
+ OUString const & rText)
+{
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ if (nBegin < 0 || nBegin > nEnd
+ || nEnd > m_rEngine.GetText(nNumber).getLength())
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::changeParagraphText",
+ static_cast< css::uno::XWeak * >(this));
+ changeParagraphText(nNumber, static_cast< ::sal_uInt16 >(nBegin),
+ static_cast< ::sal_uInt16 >(nEnd), bCut, bPaste, rText);
+ // XXX numeric overflow (2x)
+ }
+}
+
+void Document::copyParagraphText(Paragraph const * pParagraph,
+ ::sal_Int32 nBegin, ::sal_Int32 nEnd)
+{
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ if (nBegin < 0 || nBegin > nEnd
+ || nEnd > m_rEngine.GetText(nNumber).getLength())
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::copyParagraphText",
+ static_cast< css::uno::XWeak * >(this));
+ m_rView.SetSelection(
+ ::TextSelection(::TextPaM(nNumber, nBegin),
+ ::TextPaM(nNumber, nEnd)));
+ // XXX numeric overflow (2x)
+ m_rView.Copy();
+ }
+}
+
+void Document::changeParagraphAttributes(
+ Paragraph const * pParagraph, ::sal_Int32 nBegin, ::sal_Int32 nEnd,
+ css::uno::Sequence< css::beans::PropertyValue > const & rAttributeSet)
+{
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ if (nBegin < 0 || nBegin > nEnd
+ || nEnd > m_rEngine.GetText(nNumber).getLength())
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::changeParagraphAttributes",
+ static_cast< css::uno::XWeak * >(this));
+
+ // FIXME The new attributes are added to any attributes already set,
+ // they do not replace the old attributes as required by
+ // XAccessibleEditableText.setAttributes:
+ for (const auto& rAttr : rAttributeSet)
+ if ( rAttr.Name == "CharColor" )
+ m_rEngine.SetAttrib(::TextAttribFontColor(
+ mapFontColor(rAttr.Value)),
+ nNumber, nBegin, nEnd);
+ // XXX numeric overflow (2x)
+ else if ( rAttr.Name == "CharWeight" )
+ m_rEngine.SetAttrib(::TextAttribFontWeight(
+ mapFontWeight(rAttr.Value)),
+ nNumber, nBegin, nEnd);
+ // XXX numeric overflow (2x)
+ }
+}
+
+void Document::changeParagraphSelection(Paragraph const * pParagraph,
+ ::sal_Int32 nBegin, ::sal_Int32 nEnd)
+{
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >(pParagraph->getNumber());
+ // XXX numeric overflow
+ if (nBegin < 0 || nBegin > nEnd
+ || nEnd > m_rEngine.GetText(nNumber).getLength())
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::changeParagraphSelection",
+ static_cast< css::uno::XWeak * >(this));
+ m_rView.SetSelection(
+ ::TextSelection(::TextPaM(nNumber, nBegin),
+ ::TextPaM(nNumber, nEnd)));
+ // XXX numeric overflow (2x)
+ }
+}
+
+css::i18n::Boundary
+Document::retrieveParagraphLineBoundary( Paragraph const * pParagraph,
+ ::sal_Int32 nIndex, ::sal_Int32 *pLineNo )
+{
+ css::i18n::Boundary aBoundary;
+ aBoundary.startPos = nIndex;
+ aBoundary.endPos = nIndex;
+
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard( GetMutex() );
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >( pParagraph->getNumber() );
+ if ( nIndex < 0 || nIndex > m_rEngine.GetText( nNumber ).getLength() )
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::retrieveParagraphLineBoundary",
+ static_cast< css::uno::XWeak * >( this ) );
+ ::sal_Int32 nLineStart = 0;
+ ::sal_Int32 nLineEnd = 0;
+ ::sal_uInt16 nLineCount = m_rEngine.GetLineCount( nNumber );
+ for ( ::sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ nLineStart = nLineEnd;
+ nLineEnd += m_rEngine.GetLineLen( nNumber, nLine );
+ if ( nIndex >= nLineStart && ( ( nLine == nLineCount - 1 ) ? nIndex <= nLineEnd : nIndex < nLineEnd ) )
+ {
+ aBoundary.startPos = nLineStart;
+ aBoundary.endPos = nLineEnd;
+ if( pLineNo )
+ pLineNo[0] = nLine;
+ break;
+ }
+ }
+ }
+
+ return aBoundary;
+}
+
+css::i18n::Boundary
+Document::retrieveParagraphBoundaryOfLine( Paragraph const * pParagraph,
+ ::sal_Int32 nLineNo )
+{
+ css::i18n::Boundary aBoundary;
+ aBoundary.startPos = 0;
+ aBoundary.endPos = 0;
+
+ SolarMutexGuard aGuard;
+ {
+ ::osl::MutexGuard aInternalGuard( GetMutex() );
+ ::sal_uInt32 nNumber = static_cast< ::sal_uInt32 >( pParagraph->getNumber() );
+ if ( nLineNo >= m_rEngine.GetLineCount( nNumber ) )
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::retrieveParagraphBoundaryOfLine",
+ static_cast< css::uno::XWeak * >( this ) );
+ ::sal_Int32 nLineStart = 0;
+ ::sal_Int32 nLineEnd = 0;
+ for ( ::sal_Int32 nLine = 0; nLine <= nLineNo; ++nLine )
+ {
+ nLineStart = nLineEnd;
+ nLineEnd += m_rEngine.GetLineLen( nNumber, nLine );
+ }
+
+ aBoundary.startPos = nLineStart;
+ aBoundary.endPos = nLineEnd;
+ }
+
+ return aBoundary;
+}
+
+sal_Int32 Document::retrieveParagraphLineWithCursor( Paragraph const * pParagraph )
+{
+ SolarMutexGuard aGuard;
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ ::TextSelection const & rSelection = m_rView.GetSelection();
+ Paragraphs::size_type nNumber = pParagraph->getNumber();
+ TextPaM aEndPaM( rSelection.GetEnd() );
+
+ return aEndPaM.GetPara() == nNumber
+ ? m_rView.GetLineNumberOfCursorInSelection() : -1;
+}
+
+
+css::uno::Reference< css::accessibility::XAccessibleRelationSet >
+Document::retrieveParagraphRelationSet( Paragraph const * pParagraph )
+{
+ ::osl::MutexGuard aInternalGuard( GetMutex() );
+
+ rtl::Reference<::utl::AccessibleRelationSetHelper> pRelationSetHelper = new ::utl::AccessibleRelationSetHelper();
+
+ Paragraphs::iterator aPara( m_xParagraphs->begin() + pParagraph->getNumber() );
+
+ if ( aPara > m_aVisibleBegin && aPara < m_aVisibleEnd )
+ {
+ css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence { getAccessibleChild( aPara - 1 ) };
+ css::accessibility::AccessibleRelation aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM, aSequence );
+ pRelationSetHelper->AddRelation( aRelation );
+ }
+
+ if ( aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd -1 )
+ {
+ css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence { getAccessibleChild( aPara + 1 ) };
+ css::accessibility::AccessibleRelation aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO, aSequence );
+ pRelationSetHelper->AddRelation( aRelation );
+ }
+
+ return pRelationSetHelper;
+}
+
+// virtual
+::sal_Int32 SAL_CALL Document::getAccessibleChildCount()
+{
+ ::comphelper::OExternalLockGuard aGuard(this);
+ init();
+ return m_aVisibleEnd - m_aVisibleBegin;
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+Document::getAccessibleChild(::sal_Int32 i)
+{
+ ::comphelper::OExternalLockGuard aGuard(this);
+ init();
+ if (i < 0 || i >= m_aVisibleEnd - m_aVisibleBegin)
+ throw css::lang::IndexOutOfBoundsException(
+ "textwindowaccessibility.cxx:"
+ " Document::getAccessibleChild",
+ static_cast< css::uno::XWeak * >(this));
+ return getAccessibleChild(m_aVisibleBegin
+ + static_cast< Paragraphs::size_type >(i));
+}
+
+// virtual
+::sal_Int16 SAL_CALL Document::getAccessibleRole()
+{
+ return css::accessibility::AccessibleRole::TEXT_FRAME;
+}
+
+// virtual
+css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+Document::getAccessibleAtPoint(css::awt::Point const & rPoint)
+{
+ ::comphelper::OExternalLockGuard aGuard(this);
+ init();
+ if (rPoint.X >= 0
+ && rPoint.X < m_rView.GetWindow()->GetOutputSizePixel().Width()
+ && rPoint.Y >= 0 && rPoint.Y < m_nViewHeight)
+ {
+ ::sal_Int32 nOffset = m_nViewOffset + rPoint.Y; // XXX numeric overflow
+ ::sal_Int32 nPos = m_nViewOffset - m_nVisibleBeginOffset;
+ for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
+ ++aIt)
+ {
+ nPos += aIt->getHeight(); // XXX numeric overflow
+ if (nOffset < nPos)
+ return getAccessibleChild(aIt);
+ }
+ }
+ return nullptr;
+}
+void Document::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+ if (!m_rView.IsReadOnly())
+ rStateSet.AddState( css::accessibility::AccessibleStateType::EDITABLE );
+}
+
+void Document::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ if( getAccessibleParent()->getAccessibleContext()->getAccessibleRole() == css::accessibility::AccessibleRole::SCROLL_PANE )
+ {
+ css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence { getAccessibleParent() };
+ rRelationSet.AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
+ }
+ else
+ {
+ VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
+ }
+}
+// virtual
+void SAL_CALL Document::disposing()
+{
+ m_aEngineListener.endListening();
+ m_aViewListener.endListening();
+ if (m_xParagraphs != nullptr)
+ disposeParagraphs();
+ VCLXAccessibleComponent::disposing();
+}
+
+// virtual
+void Document::Notify(::SfxBroadcaster &, ::SfxHint const & rHint)
+{
+ const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
+ if (!pTextHint)
+ return;
+
+ ::TextHint const & rTextHint = *pTextHint;
+ switch (rTextHint.GetId())
+ {
+ case SfxHintId::TextParaInserted:
+ case SfxHintId::TextParaRemoved:
+ // SfxHintId::TextParaInserted and SfxHintId::TextParaRemoved are sent at
+ // "unsafe" times (when the text engine has not yet re-formatted its
+ // content), so that for example calling ::TextEngine::GetTextHeight
+ // from within the code that handles SfxHintId::TextParaInserted causes
+ // trouble within the text engine. Therefore, these hints are just
+ // buffered until a following ::TextEngine::FormatDoc causes a
+ // SfxHintId::TextFormatted to come in:
+ case SfxHintId::TextFormatPara:
+ // ::TextEngine::FormatDoc sends a sequence of
+ // SfxHintId::TextFormatParas, followed by an optional
+ // SfxHintId::TextHeightChanged, followed in all cases by one
+ // SfxHintId::TextFormatted. Only the SfxHintId::TextFormatParas contain
+ // the numbers of the affected paragraphs, but they are sent
+ // before the changes are applied. Therefore, SfxHintId::TextFormatParas
+ // are just buffered until another hint comes in:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+
+ m_aParagraphNotifications.push(rTextHint);
+ break;
+ }
+ case SfxHintId::TextFormatted:
+ case SfxHintId::TextHeightChanged:
+ case SfxHintId::TextModified:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+ handleParagraphNotifications();
+ break;
+ }
+ case SfxHintId::TextViewScrolled:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+ handleParagraphNotifications();
+
+ ::sal_Int32 nOffset = static_cast< ::sal_Int32 >(
+ m_rView.GetStartDocPos().Y());
+ // XXX numeric overflow
+ if (nOffset != m_nViewOffset)
+ {
+ m_nViewOffset = nOffset;
+
+ Paragraphs::iterator aOldVisibleBegin(
+ m_aVisibleBegin);
+ Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
+
+ determineVisibleRange();
+
+ notifyVisibleRangeChanges(aOldVisibleBegin,
+ aOldVisibleEnd,
+ m_xParagraphs->end());
+ }
+ break;
+ }
+ case SfxHintId::TextViewSelectionChanged:
+ case SfxHintId::TextViewCaretChanged:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+
+ if (m_aParagraphNotifications.empty())
+ {
+ handleSelectionChangeNotification();
+ }
+ else
+ {
+ // SfxHintId::TextViewSelectionChanged is sometimes sent at
+ // "unsafe" times (when the text engine has not yet re-
+ // formatted its content), so that for example calling
+ // ::TextEngine::GetTextHeight from within the code that
+ // handles a previous SfxHintId::TextParaInserted causes
+ // trouble within the text engine. Therefore, these
+ // hints are just buffered (along with
+ // SfxHintId::TextParaInserted/REMOVED/FORMATPARA) until a
+ // following ::TextEngine::FormatDoc causes a
+ // SfxHintId::TextFormatted to come in:
+ m_bSelectionChangedNotification = true;
+ }
+ break;
+ }
+ default: break;
+ }
+}
+
+IMPL_LINK(Document, WindowEventHandler, ::VclWindowEvent&, rEvent, void)
+{
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowResize:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+
+ ::sal_Int32 nHeight = static_cast< ::sal_Int32 >(
+ m_rView.GetWindow()->GetOutputSizePixel().Height());
+ // XXX numeric overflow
+ if (nHeight != m_nViewHeight)
+ {
+ m_nViewHeight = nHeight;
+
+ Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
+ Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
+
+ determineVisibleRange();
+
+ notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
+ m_xParagraphs->end());
+ }
+ break;
+ }
+ case VclEventId::WindowGetFocus:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+ //to enable the PARAGRAPH to get focus for multiline edit
+ ::sal_Int32 count = getAccessibleChildCount();
+ bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
+ if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
+ {
+ Paragraphs::iterator aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(aTemp));
+ if (xParagraph.is())
+ {
+ xParagraph->notifyEvent(
+ css::accessibility::AccessibleEventId::
+ STATE_CHANGED,
+ css::uno::Any(),
+ css::uno::Any(
+ css::accessibility::AccessibleStateType::
+ FOCUSED));
+ }
+ }
+ break;
+ }
+ case VclEventId::WindowLoseFocus:
+ {
+ ::osl::MutexGuard aInternalGuard(GetMutex());
+ if (!isAlive())
+ break;
+ //to enable the PARAGRAPH to get focus for multiline edit
+ ::sal_Int32 count = getAccessibleChildCount();
+ bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
+ if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
+ {
+ Paragraphs::iterator aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(aTemp));
+ if (xParagraph.is())
+ xParagraph->notifyEvent(
+ css::accessibility::AccessibleEventId::
+ STATE_CHANGED,
+ css::uno::Any(
+ css::accessibility::AccessibleStateType::
+ FOCUSED),
+ css::uno::Any());
+ }
+ break;
+ }
+ default: break;
+ }
+}
+
+void Document::init()
+{
+ if (m_xParagraphs != nullptr)
+ return;
+
+ const ::sal_uInt32 nCount = m_rEngine.GetParagraphCount();
+ m_xParagraphs.reset(new Paragraphs);
+ m_xParagraphs->reserve(static_cast< Paragraphs::size_type >(nCount));
+ // numeric overflow is harmless here
+ for (::sal_uInt32 i = 0; i < nCount; ++i)
+ m_xParagraphs->push_back(ParagraphInfo(static_cast< ::sal_Int32 >(
+ m_rEngine.GetTextHeight(i))));
+ // XXX numeric overflow
+ m_nViewOffset = static_cast< ::sal_Int32 >(
+ m_rView.GetStartDocPos().Y()); // XXX numeric overflow
+ m_nViewHeight = static_cast< ::sal_Int32 >(
+ m_rView.GetWindow()->GetOutputSizePixel().Height());
+ // XXX numeric overflow
+ determineVisibleRange();
+ m_nSelectionFirstPara = -1;
+ m_nSelectionFirstPos = -1;
+ m_nSelectionLastPara = -1;
+ m_nSelectionLastPos = -1;
+ m_aFocused = m_xParagraphs->end();
+ m_bSelectionChangedNotification = false;
+ m_aEngineListener.startListening(m_rEngine);
+ m_aViewListener.startListening(*m_rView.GetWindow());
+}
+
+::rtl::Reference< Paragraph >
+Document::getParagraph(Paragraphs::iterator const & rIt)
+{
+ return static_cast< Paragraph * >(
+ css::uno::Reference< css::accessibility::XAccessible >(
+ rIt->getParagraph()).get());
+}
+
+css::uno::Reference< css::accessibility::XAccessible >
+Document::getAccessibleChild(Paragraphs::iterator const & rIt)
+{
+ css::uno::Reference< css::accessibility::XAccessible > xParagraph(
+ rIt->getParagraph());
+ if (!xParagraph.is())
+ {
+ xParagraph = new Paragraph(this, rIt - m_xParagraphs->begin());
+ rIt->setParagraph(xParagraph);
+ }
+ return xParagraph;
+}
+
+void Document::determineVisibleRange()
+{
+ Paragraphs::iterator const aEnd = m_xParagraphs->end();
+
+ m_aVisibleBegin = aEnd;
+ m_aVisibleEnd = aEnd;
+ m_nVisibleBeginOffset = 0;
+
+ ::sal_Int32 nPos = 0;
+ for (Paragraphs::iterator aIt = m_xParagraphs->begin(); m_aVisibleEnd == aEnd && aIt != aEnd; ++aIt)
+ {
+ ::sal_Int32 const nOldPos = nPos;
+ nPos += aIt->getHeight(); // XXX numeric overflow
+ if (m_aVisibleBegin == aEnd)
+ {
+ if (nPos >= m_nViewOffset)
+ {
+ m_aVisibleBegin = aIt;
+ m_nVisibleBeginOffset = m_nViewOffset - nOldPos;
+ }
+ }
+ else
+ {
+ if (nPos >= m_nViewOffset + m_nViewHeight) // XXX numeric overflow
+ {
+ m_aVisibleEnd = aIt;
+ }
+ }
+ }
+
+ SAL_WARN_IF(
+ !((m_aVisibleBegin == m_xParagraphs->end() && m_aVisibleEnd == m_xParagraphs->end() && m_nVisibleBeginOffset == 0)
+ || (m_aVisibleBegin < m_aVisibleEnd && m_nVisibleBeginOffset >= 0)),
+ "accessibility",
+ "invalid visible range");
+}
+
+void Document::notifyVisibleRangeChanges(
+ Paragraphs::iterator const & rOldVisibleBegin,
+ Paragraphs::iterator const & rOldVisibleEnd,
+ Paragraphs::iterator const & rInserted)
+{
+ // XXX Replace this code that determines which paragraphs have changed from
+ // invisible to visible or vice versa with a better algorithm.
+ for (Paragraphs::iterator aIt(rOldVisibleBegin); aIt != rOldVisibleEnd;
+ ++aIt)
+ {
+ if (aIt != rInserted
+ && (aIt < m_aVisibleBegin || aIt >= m_aVisibleEnd))
+ NotifyAccessibleEvent(
+ css::accessibility::AccessibleEventId::
+ CHILD,
+ css::uno::Any(getAccessibleChild(aIt)),
+ css::uno::Any());
+ }
+ for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
+ ++aIt)
+ {
+ if (aIt == rInserted
+ || aIt < rOldVisibleBegin || aIt >= rOldVisibleEnd)
+ NotifyAccessibleEvent(
+ css::accessibility::AccessibleEventId::
+ CHILD,
+ css::uno::Any(),
+ css::uno::Any(getAccessibleChild(aIt)));
+ }
+}
+
+void
+Document::changeParagraphText(::sal_uInt32 nNumber, ::sal_uInt16 nBegin, ::sal_uInt16 nEnd,
+ bool bCut, bool bPaste,
+ OUString const & rText)
+{
+ m_rView.SetSelection(::TextSelection(::TextPaM(nNumber, nBegin),
+ ::TextPaM(nNumber, nEnd)));
+ if (bCut)
+ m_rView.Cut();
+ else if (nBegin != nEnd)
+ m_rView.DeleteSelected();
+ if (bPaste)
+ m_rView.Paste();
+ else if (!rText.isEmpty())
+ m_rView.InsertText(rText);
+}
+
+void Document::handleParagraphNotifications()
+{
+ while (!m_aParagraphNotifications.empty())
+ {
+ ::TextHint aHint(m_aParagraphNotifications.front());
+ m_aParagraphNotifications.pop();
+ switch (aHint.GetId())
+ {
+ case SfxHintId::TextParaInserted:
+ {
+ ::sal_uInt32 n = static_cast< ::sal_uInt32 >( aHint.GetValue() );
+ assert(n <= m_xParagraphs->size() && "bad SfxHintId::TextParaInserted event");
+
+ // Save the values of old iterators (the iterators themselves
+ // will get invalidated), and adjust the old values so that they
+ // reflect the insertion of the new paragraph:
+ Paragraphs::size_type nOldVisibleBegin
+ = m_aVisibleBegin - m_xParagraphs->begin();
+ Paragraphs::size_type nOldVisibleEnd
+ = m_aVisibleEnd - m_xParagraphs->begin();
+ Paragraphs::size_type nOldFocused
+ = m_aFocused - m_xParagraphs->begin();
+ if (n <= nOldVisibleBegin)
+ ++nOldVisibleBegin; // XXX numeric overflow
+ if (n <= nOldVisibleEnd)
+ ++nOldVisibleEnd; // XXX numeric overflow
+ if (n <= nOldFocused)
+ ++nOldFocused; // XXX numeric overflow
+ if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionFirstPara)
+ ++m_nSelectionFirstPara; // XXX numeric overflow
+ if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionLastPara)
+ ++m_nSelectionLastPara; // XXX numeric overflow
+
+ Paragraphs::iterator aIns(
+ m_xParagraphs->insert(
+ m_xParagraphs->begin() + n,
+ ParagraphInfo(static_cast< ::sal_Int32 >(
+ m_rEngine.GetTextHeight(n)))));
+ // XXX numeric overflow (2x)
+
+ determineVisibleRange();
+ m_aFocused = m_xParagraphs->begin() + nOldFocused;
+
+ for (Paragraphs::iterator aIt(aIns);;)
+ {
+ ++aIt;
+ if (aIt == m_xParagraphs->end())
+ break;
+ ::rtl::Reference< Paragraph > xParagraph(
+ getParagraph(aIt));
+ if (xParagraph.is())
+ xParagraph->numberChanged(true);
+ }
+
+ notifyVisibleRangeChanges(
+ m_xParagraphs->begin() + nOldVisibleBegin,
+ m_xParagraphs->begin() + nOldVisibleEnd, aIns);
+ break;
+ }
+ case SfxHintId::TextParaRemoved:
+ {
+ ::sal_uInt32 n = static_cast< ::sal_uInt32 >( aHint.GetValue() );
+ if (n == TEXT_PARA_ALL)
+ {
+ for (Paragraphs::iterator aIt(m_aVisibleBegin);
+ aIt != m_aVisibleEnd; ++aIt)
+ {
+ NotifyAccessibleEvent(
+ css::accessibility::AccessibleEventId::
+ CHILD,
+ css::uno::Any(getAccessibleChild(aIt)),
+ css::uno::Any());
+ }
+ disposeParagraphs();
+ m_xParagraphs->clear();
+ determineVisibleRange();
+ m_nSelectionFirstPara = -1;
+ m_nSelectionFirstPos = -1;
+ m_nSelectionLastPara = -1;
+ m_nSelectionLastPos = -1;
+ m_aFocused = m_xParagraphs->end();
+ }
+ else
+ {
+ assert(n < m_xParagraphs->size() && "Bad SfxHintId::TextParaRemoved event");
+
+ Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
+ // numeric overflow cannot occur
+
+ // Save the values of old iterators (the iterators
+ // themselves will get invalidated), and adjust the old
+ // values so that they reflect the removal of the paragraph:
+ Paragraphs::size_type nOldVisibleBegin
+ = m_aVisibleBegin - m_xParagraphs->begin();
+ Paragraphs::size_type nOldVisibleEnd
+ = m_aVisibleEnd - m_xParagraphs->begin();
+ bool bWasVisible
+ = nOldVisibleBegin <= n && n < nOldVisibleEnd;
+ Paragraphs::size_type nOldFocused
+ = m_aFocused - m_xParagraphs->begin();
+ bool bWasFocused = aIt == m_aFocused;
+ if (n < nOldVisibleBegin)
+ --nOldVisibleBegin;
+ if (n < nOldVisibleEnd)
+ --nOldVisibleEnd;
+ if (n < nOldFocused)
+ --nOldFocused;
+ if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionFirstPara)
+ --m_nSelectionFirstPara;
+ else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionFirstPara)
+ {
+ if (m_nSelectionFirstPara == m_nSelectionLastPara)
+ {
+ m_nSelectionFirstPara = -1;
+ m_nSelectionFirstPos = -1;
+ m_nSelectionLastPara = -1;
+ m_nSelectionLastPos = -1;
+ }
+ else
+ {
+ ++m_nSelectionFirstPara;
+ m_nSelectionFirstPos = 0;
+ }
+ }
+ if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionLastPara)
+ --m_nSelectionLastPara;
+ else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionLastPara)
+ {
+ assert(m_nSelectionFirstPara < m_nSelectionLastPara && "logic error");
+ --m_nSelectionLastPara;
+ m_nSelectionLastPos = 0x7FFFFFFF;
+ }
+
+ css::uno::Reference< css::accessibility::XAccessible >
+ xStrong;
+ if (bWasVisible)
+ xStrong = getAccessibleChild(aIt);
+ css::uno::WeakReference<
+ css::accessibility::XAccessible > xWeak(
+ aIt->getParagraph());
+ aIt = m_xParagraphs->erase(aIt);
+
+ determineVisibleRange();
+ m_aFocused = bWasFocused ? m_xParagraphs->end()
+ : m_xParagraphs->begin() + nOldFocused;
+
+ for (; aIt != m_xParagraphs->end(); ++aIt)
+ {
+ ::rtl::Reference< Paragraph > xParagraph(
+ getParagraph(aIt));
+ if (xParagraph.is())
+ xParagraph->numberChanged(false);
+ }
+
+ if (bWasVisible)
+ NotifyAccessibleEvent(
+ css::accessibility::AccessibleEventId::
+ CHILD,
+ css::uno::Any(xStrong),
+ css::uno::Any());
+
+ css::uno::Reference< css::lang::XComponent > xComponent(
+ xWeak.get(), css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+
+ notifyVisibleRangeChanges(
+ m_xParagraphs->begin() + nOldVisibleBegin,
+ m_xParagraphs->begin() + nOldVisibleEnd,
+ m_xParagraphs->end());
+ }
+ break;
+ }
+ case SfxHintId::TextFormatPara:
+ {
+ ::sal_uInt32 n = static_cast< ::sal_uInt32 >( aHint.GetValue() );
+ assert(n < m_xParagraphs->size() && "Bad SfxHintId::TextFormatPara event");
+
+ (*m_xParagraphs)[static_cast< Paragraphs::size_type >(n)].
+ changeHeight(static_cast< ::sal_Int32 >(
+ m_rEngine.GetTextHeight(n)));
+ // XXX numeric overflow
+ Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
+ Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
+ determineVisibleRange();
+ notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
+ m_xParagraphs->end());
+
+ if (n < m_xParagraphs->size())
+ {
+ Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
+ if (xParagraph.is())
+ xParagraph->textChanged();
+ }
+ break;
+ }
+ default:
+ SAL_WARN("accessibility", "bad buffered hint");
+ break;
+ }
+ }
+ if (m_bSelectionChangedNotification)
+ {
+ m_bSelectionChangedNotification = false;
+ handleSelectionChangeNotification();
+ }
+}
+
+namespace
+{
+
+enum class SelChangeType
+{
+ None, // no change, or invalid
+ CaretMove, // neither old nor new have selection, and they are different
+ NoSelToSel, // old has no selection but new has selection
+ SelToNoSel, // old has selection but new has no selection
+ // both old and new have selections
+ NoParaChange, // only end index changed inside end para
+ EndParaNoMoreBehind, // end para was behind start, but now is same or ahead
+ AddedFollowingPara, // selection extended to following paragraph(s)
+ ExcludedPreviousPara, // selection shrunk excluding previous paragraph(s)
+ ExcludedFollowingPara, // selection shrunk excluding following paragraph(s)
+ AddedPreviousPara, // selection extended to previous paragraph(s)
+ EndParaBecameBehind // end para was ahead of start, but now is behind
+};
+
+SelChangeType getSelChangeType(const TextPaM& Os, const TextPaM& Oe,
+ const TextPaM& Ns, const TextPaM& Ne)
+{
+ if (Os == Oe) // no old selection
+ {
+ if (Ns == Ne) // no new selection: only caret moves
+ return Os != Ns ? SelChangeType::CaretMove : SelChangeType::None;
+ else // old has no selection but new has selection
+ return SelChangeType::NoSelToSel;
+ }
+ else if (Ns == Ne) // old has selection; no new selection
+ {
+ return SelChangeType::SelToNoSel;
+ }
+ else if (Os == Ns) // both old and new have selections, and their starts are same
+ {
+ const sal_Int32 Osp = Os.GetPara(), Oep = Oe.GetPara();
+ const sal_Int32 Nsp = Ns.GetPara(), Nep = Ne.GetPara();
+ if (Oep == Nep) // end of selection stays in the same paragraph
+ {
+ //Send text_selection_change event on Nep
+ return Oe.GetIndex() != Ne.GetIndex() ? SelChangeType::NoParaChange
+ : SelChangeType::None;
+ }
+ else if (Oep < Nep) // end of selection moved to a following paragraph
+ {
+ //all the following examples like 1,2->1,3 means that old start select para is 1, old end select para is 2,
+ // then press shift up, the new start select para is 1, new end select para is 3;
+ //for example, 1, 2 -> 1, 3; 4,1 -> 4, 7; 4,1 -> 4, 2; 4,4->4,5
+ if (Nep >= Nsp) // new end para not behind start
+ {
+ // 1, 2 -> 1, 3; 4, 1 -> 4, 7; 4,4->4,5;
+ if (Oep < Osp) // old end was behind start
+ {
+ // 4,1 -> 4,7; 4,1 -> 4,4
+ return SelChangeType::EndParaNoMoreBehind;
+ }
+ else // old end para wasn't behind start
+ {
+ // 1, 2 -> 1, 3; 4,4->4,5;
+ return SelChangeType::AddedFollowingPara;
+ }
+ }
+ else // new end para is still behind start
+ {
+ // 4,1 -> 4,2,
+ return SelChangeType::ExcludedPreviousPara;
+ }
+ }
+ else // Oep > Nep => end of selection moved to a previous paragraph
+ {
+ // 3,2 -> 3,1; 4,7 -> 4,1; 4, 7 -> 4,6; 4,4 -> 4,3
+ if (Nep >= Nsp) // new end para is still not behind of start
+ {
+ // 4,7 ->4,6
+ return SelChangeType::ExcludedFollowingPara;
+ }
+ else // new end para is behind start
+ {
+ // 3,2 -> 3,1, 4,7 -> 4,1; 4,4->4,3
+ if (Oep <= Osp) // it was not ahead already
+ {
+ // 3,2 -> 3,1; 4,4->4,3
+ return SelChangeType::AddedPreviousPara;
+ }
+ else // it was ahead previously
+ {
+ // 4,7 -> 4,1
+ return SelChangeType::EndParaBecameBehind;
+ }
+ }
+ }
+ }
+ return SelChangeType::None;
+}
+
+} // namespace
+
+void Document::sendEvent(::sal_Int32 start, ::sal_Int32 end, ::sal_Int16 nEventId)
+{
+ size_t nAvailDistance = std::distance(m_xParagraphs->begin(), m_aVisibleEnd);
+
+ Paragraphs::iterator aEnd(m_xParagraphs->begin());
+ size_t nEndDistance = std::min<size_t>(end + 1, nAvailDistance);
+ std::advance(aEnd, nEndDistance);
+
+ Paragraphs::iterator aIt(m_xParagraphs->begin());
+ size_t nStartDistance = std::min<size_t>(start, nAvailDistance);
+ std::advance(aIt, nStartDistance);
+
+ while (aIt < aEnd)
+ {
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
+ if (xParagraph.is())
+ xParagraph->notifyEvent(
+ nEventId,
+ css::uno::Any(), css::uno::Any());
+ ++aIt;
+ }
+}
+
+void Document::handleSelectionChangeNotification()
+{
+ ::TextSelection const & rSelection = m_rView.GetSelection();
+ assert(rSelection.GetStart().GetPara() < m_xParagraphs->size() &&
+ rSelection.GetEnd().GetPara() < m_xParagraphs->size() &&
+ "bad SfxHintId::TextViewSelectionChanged event");
+ ::sal_Int32 nNewFirstPara
+ = static_cast< ::sal_Int32 >(rSelection.GetStart().GetPara());
+ ::sal_Int32 nNewFirstPos = rSelection.GetStart().GetIndex();
+ // XXX numeric overflow
+ ::sal_Int32 nNewLastPara
+ = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetPara());
+ ::sal_Int32 nNewLastPos = rSelection.GetEnd().GetIndex();
+ // XXX numeric overflow
+
+ // Lose focus:
+ Paragraphs::iterator aIt(m_xParagraphs->begin() + nNewLastPara);
+ if (m_aFocused != m_xParagraphs->end() && m_aFocused != aIt
+ && m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
+ {
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(m_aFocused));
+ if (xParagraph.is())
+ xParagraph->notifyEvent(
+ css::accessibility::AccessibleEventId::
+ STATE_CHANGED,
+ css::uno::Any(
+ css::accessibility::AccessibleStateType::FOCUSED),
+ css::uno::Any());
+ }
+
+ // Gain focus and update cursor position:
+ if (aIt >= m_aVisibleBegin && aIt < m_aVisibleEnd
+ && (aIt != m_aFocused
+ || nNewLastPara != m_nSelectionLastPara
+ || nNewLastPos != m_nSelectionLastPos))
+ {
+ ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
+ if (xParagraph.is())
+ {
+ //disable the first event when user types in empty field.
+ ::sal_Int32 count = getAccessibleChildCount();
+ bool bEmpty = count > 1;
+ //if (aIt != m_aFocused)
+ if (aIt != m_aFocused && bEmpty)
+ xParagraph->notifyEvent(
+ css::accessibility::AccessibleEventId::
+ STATE_CHANGED,
+ css::uno::Any(),
+ css::uno::Any(
+ css::accessibility::AccessibleStateType::FOCUSED));
+ if (nNewLastPara != m_nSelectionLastPara
+ || nNewLastPos != m_nSelectionLastPos)
+ xParagraph->notifyEvent(
+ css::accessibility::AccessibleEventId::
+ CARET_CHANGED,
+ css::uno::Any( ::sal_Int32 (
+ nNewLastPara == m_nSelectionLastPara
+ ? m_nSelectionLastPos : 0)),
+ css::uno::Any(nNewLastPos));
+ }
+ }
+ m_aFocused = aIt;
+
+ if (m_nSelectionFirstPara != -1)
+ {
+ sal_Int32 nMin;
+ sal_Int32 nMax;
+ SelChangeType ret = getSelChangeType(TextPaM(m_nSelectionFirstPara, m_nSelectionFirstPos),
+ TextPaM(m_nSelectionLastPara, m_nSelectionLastPos),
+ rSelection.GetStart(), rSelection.GetEnd());
+ switch (ret)
+ {
+ case SelChangeType::None:
+ //no event
+ break;
+ case SelChangeType::CaretMove:
+ //only caret moved, already handled in above
+ break;
+ case SelChangeType::NoSelToSel:
+ //old has no selection but new has selection
+ nMin = std::min(nNewFirstPara, nNewLastPara);
+ nMax = std::max(nNewFirstPara, nNewLastPara);
+ sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+ sendEvent(nMin, nMax,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::SelToNoSel:
+ //old has selection but new has no selection.
+ nMin = std::min(m_nSelectionFirstPara, m_nSelectionLastPara);
+ nMax = std::max(m_nSelectionFirstPara, m_nSelectionLastPara);
+ sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+ sendEvent(nMin, nMax,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::NoParaChange:
+ //Send text_selection_change event on Nep
+ sendEvent(nNewLastPara, nNewLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::EndParaNoMoreBehind:
+ // 4, 1 -> 4, 7; 4,1 -> 4,4
+ sendEvent(m_nSelectionLastPara, m_nSelectionFirstPara - 1,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+ sendEvent(nNewFirstPara + 1, nNewLastPara,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(m_nSelectionLastPara, nNewLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::AddedFollowingPara:
+ // 1, 2 -> 1, 4; 4,4->4,5;
+ sendEvent(m_nSelectionLastPara + 1, nNewLastPara,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(m_nSelectionLastPara, nNewLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::ExcludedPreviousPara:
+ // 4,1 -> 4,3,
+ sendEvent(m_nSelectionLastPara + 1, nNewLastPara,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(m_nSelectionLastPara, nNewLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::ExcludedFollowingPara:
+ // 4,7 ->4,5;
+ sendEvent(nNewLastPara + 1, m_nSelectionLastPara,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(nNewLastPara, m_nSelectionLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::AddedPreviousPara:
+ // 3,2 -> 3,1; 4,4->4,3
+ sendEvent(nNewLastPara, m_nSelectionLastPara - 1,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(nNewLastPara, m_nSelectionLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ case SelChangeType::EndParaBecameBehind:
+ // 4,7 -> 4,1
+ sendEvent(m_nSelectionFirstPara + 1, m_nSelectionLastPara,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+ sendEvent(nNewLastPara, nNewFirstPara - 1,
+ css::accessibility::AccessibleEventId::SELECTION_CHANGED);
+
+ sendEvent(nNewLastPara, m_nSelectionLastPara,
+ css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
+ break;
+ }
+ }
+
+ m_nSelectionFirstPara = nNewFirstPara;
+ m_nSelectionFirstPos = nNewFirstPos;
+ m_nSelectionLastPara = nNewLastPara;
+ m_nSelectionLastPos = nNewLastPos;
+}
+
+void Document::disposeParagraphs()
+{
+ for (auto const& paragraph : *m_xParagraphs)
+ {
+ css::uno::Reference< css::lang::XComponent > xComponent(
+ paragraph.getParagraph().get(), css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+}
+
+// static
+css::uno::Any Document::mapFontColor(::Color const & rColor)
+{
+ return css::uno::Any(rColor.GetRGBColor());
+ // FIXME keep transparency?
+}
+
+// static
+::Color Document::mapFontColor(css::uno::Any const & rColor)
+{
+ ::Color nColor;
+ rColor >>= nColor;
+ return nColor;
+}
+
+// static
+css::uno::Any Document::mapFontWeight(::FontWeight nWeight)
+{
+ // Map from ::FontWeight to css::awt::FontWeight, depends on order of
+ // elements in ::FontWeight (vcl/vclenum.hxx):
+ static float const aWeight[]
+ = { css::awt::FontWeight::DONTKNOW, // WEIGHT_DONTKNOW
+ css::awt::FontWeight::THIN, // WEIGHT_THIN
+ css::awt::FontWeight::ULTRALIGHT, // WEIGHT_ULTRALIGHT
+ css::awt::FontWeight::LIGHT, // WEIGHT_LIGHT
+ css::awt::FontWeight::SEMILIGHT, // WEIGHT_SEMILIGHT
+ css::awt::FontWeight::NORMAL, // WEIGHT_NORMAL
+ css::awt::FontWeight::NORMAL, // WEIGHT_MEDIUM
+ css::awt::FontWeight::SEMIBOLD, // WEIGHT_SEMIBOLD
+ css::awt::FontWeight::BOLD, // WEIGHT_BOLD
+ css::awt::FontWeight::ULTRABOLD, // WEIGHT_ULTRABOLD
+ css::awt::FontWeight::BLACK }; // WEIGHT_BLACK
+ return css::uno::Any(aWeight[nWeight]);
+}
+
+// static
+::FontWeight Document::mapFontWeight(css::uno::Any const & rWeight)
+{
+ float nWeight = css::awt::FontWeight::NORMAL;
+ rWeight >>= nWeight;
+ return nWeight <= css::awt::FontWeight::DONTKNOW ? WEIGHT_DONTKNOW
+ : nWeight <= css::awt::FontWeight::THIN ? WEIGHT_THIN
+ : nWeight <= css::awt::FontWeight::ULTRALIGHT ? WEIGHT_ULTRALIGHT
+ : nWeight <= css::awt::FontWeight::LIGHT ? WEIGHT_LIGHT
+ : nWeight <= css::awt::FontWeight::SEMILIGHT ? WEIGHT_SEMILIGHT
+ : nWeight <= css::awt::FontWeight::NORMAL ? WEIGHT_NORMAL
+ : nWeight <= css::awt::FontWeight::SEMIBOLD ? WEIGHT_SEMIBOLD
+ : nWeight <= css::awt::FontWeight::BOLD ? WEIGHT_BOLD
+ : nWeight <= css::awt::FontWeight::ULTRABOLD ? WEIGHT_ULTRABOLD
+ : WEIGHT_BLACK;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/helper/IComboListBoxHelper.cxx b/accessibility/source/helper/IComboListBoxHelper.cxx
new file mode 100644
index 000000000..f4830815f
--- /dev/null
+++ b/accessibility/source/helper/IComboListBoxHelper.cxx
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <helper/IComboListBoxHelper.hxx>
+
+namespace accessibility
+{
+IComboListBoxHelper::~IComboListBoxHelper() {}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/helper/acc_factory.cxx b/accessibility/source/helper/acc_factory.cxx
new file mode 100644
index 000000000..10cc27f00
--- /dev/null
+++ b/accessibility/source/helper/acc_factory.cxx
@@ -0,0 +1,500 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_feature_desktop.h>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/helper/accessiblefactory.hxx>
+#include <vcl/accessiblefactory.hxx>
+#include <standard/svtaccessiblenumericfield.hxx>
+#include <standard/vclxaccessiblebutton.hxx>
+#include <standard/vclxaccessiblecheckbox.hxx>
+#include <standard/vclxaccessibledropdowncombobox.hxx>
+#include <standard/vclxaccessiblecombobox.hxx>
+#include <standard/vclxaccessibledropdownlistbox.hxx>
+#include <standard/vclxaccessibleedit.hxx>
+#include <standard/vclxaccessiblefixedhyperlink.hxx>
+#include <standard/vclxaccessiblefixedtext.hxx>
+#include <standard/vclxaccessibleheaderbar.hxx>
+#include <standard/vclxaccessiblelistbox.hxx>
+#include <standard/vclxaccessibleradiobutton.hxx>
+#include <standard/vclxaccessiblescrollbar.hxx>
+#include <standard/vclxaccessibletoolbox.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <standard/vclxaccessiblestatusbar.hxx>
+#include <standard/vclxaccessibletabcontrol.hxx>
+#include <standard/vclxaccessibletabpagewindow.hxx>
+#include <standard/vclxaccessiblemenubar.hxx>
+#include <standard/vclxaccessiblepopupmenu.hxx>
+#include <extended/accessibletablistbox.hxx>
+#include <extended/AccessibleBrowseBox.hxx>
+#include <extended/accessibleiconchoicectrl.hxx>
+#include <extended/AccessibleIconView.hxx>
+#include <extended/accessibletabbar.hxx>
+#include <extended/accessiblelistbox.hxx>
+#include <extended/AccessibleBrowseBoxHeaderBar.hxx>
+#include <extended/textwindowaccessibility.hxx>
+#include <extended/AccessibleBrowseBoxTableCell.hxx>
+#include <extended/AccessibleBrowseBoxHeaderCell.hxx>
+#include <extended/AccessibleBrowseBoxCheckBoxCell.hxx>
+#include <extended/accessibleeditbrowseboxcell.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/toolkit/lstbox.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <extended/AccessibleGridControl.hxx>
+#include <vcl/accessibletable.hxx>
+
+#include <floatingwindowaccessible.hxx>
+
+using namespace ::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::accessibility;
+using namespace ::vcl;
+using namespace ::vcl::table;
+
+namespace {
+
+bool hasFloatingChild(vcl::Window *pWindow)
+{
+ vcl::Window * pChild = pWindow->GetAccessibleChildWindow(0);
+ return pChild && pChild->GetType() == WindowType::FLOATINGWINDOW;
+}
+
+// IAccessibleFactory
+class AccessibleFactory :public ::toolkit::IAccessibleFactory
+ ,public ::vcl::IAccessibleFactory
+{
+public:
+ AccessibleFactory();
+
+ // ::toolkit::IAccessibleFactory
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXButton* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXCheckBox* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXRadioButton* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXListBox* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXFixedText* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXFixedHyperlink* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXScrollBar* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXEdit* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXComboBox* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXToolBox* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXHeaderBar* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( SVTXNumericField* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXWindow* _pXWindow ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessible( Menu* _pMenu, bool _bIsMenuBar ) override;
+
+ // ::vcl::IAccessibleFactory
+ virtual vcl::IAccessibleTabListBox*
+ createAccessibleTabListBox(
+ const css::uno::Reference< css::accessibility::XAccessible >& rxParent,
+ SvHeaderTabListBox& rBox
+ ) const override;
+
+ virtual vcl::IAccessibleBrowseBox*
+ createAccessibleBrowseBox(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox
+ ) const override;
+
+ virtual IAccessibleTableControl*
+ createAccessibleTableControl(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ IAccessibleTable& _rTable
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleIconChoiceCtrl(
+ SvtIconChoiceCtrl& _rIconCtrl,
+ const css::uno::Reference< css::accessibility::XAccessible >& _xParent
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleTabBar(
+ TabBar& _rTabBar
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleTextWindowContext(
+ VCLXWindow* pVclXWindow, TextEngine& rEngine, TextView& rView
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleTreeListBox(
+ SvTreeListBox& _rListBox,
+ const css::uno::Reference< css::accessibility::XAccessible >& _xParent
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleIconView(
+ SvTreeListBox& _rListBox,
+ const css::uno::Reference< css::accessibility::XAccessible >& _xParent
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleBrowseBoxHeaderBar(
+ const css::uno::Reference< css::accessibility::XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& _rOwningTable,
+ AccessibleBrowseBoxObjType _eObjType
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleBrowseBoxTableCell(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowId,
+ sal_uInt16 _nColId,
+ sal_Int32 _nOffset
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleBrowseBoxHeaderCell(
+ sal_Int32 _nColumnRowId,
+ const css::uno::Reference< css::accessibility::XAccessible >& rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ AccessibleBrowseBoxObjType _eObjType
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createAccessibleCheckBoxCell(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ const css::uno::Reference< css::awt::XWindow >& _xFocusWindow,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos,
+ const TriState& _eState,
+ bool _bIsTriState
+ ) const override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ createEditBrowseBoxTableCellAccess(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxControlAccessible,
+ const css::uno::Reference< css::awt::XWindow >& _rxFocusWindow,
+ vcl::IAccessibleTableProvider& _rBrowseBox,
+ sal_Int32 _nRowPos,
+ sal_uInt16 _nColPos
+ ) const override;
+
+protected:
+ virtual ~AccessibleFactory() override;
+};
+
+AccessibleFactory::AccessibleFactory()
+{
+}
+
+AccessibleFactory::~AccessibleFactory()
+{
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessible( Menu* _pMenu, bool _bIsMenuBar )
+{
+ rtl::Reference<OAccessibleMenuBaseComponent> pAccessible;
+ if ( _bIsMenuBar )
+ pAccessible = new VCLXAccessibleMenuBar( _pMenu );
+ else
+ pAccessible = new VCLXAccessiblePopupMenu( _pMenu );
+ pAccessible->SetStates();
+ return pAccessible;
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXButton* _pXWindow )
+{
+ return new VCLXAccessibleButton( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXCheckBox* _pXWindow )
+{
+ return new VCLXAccessibleCheckBox( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXRadioButton* _pXWindow )
+{
+ return new VCLXAccessibleRadioButton( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXListBox* _pXWindow )
+{
+ bool bIsDropDownBox = false;
+ VclPtr< ListBox > pBox = _pXWindow->GetAs< ListBox >();
+ if ( pBox )
+ bIsDropDownBox = ( ( pBox->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN );
+
+ if ( bIsDropDownBox )
+ return new VCLXAccessibleDropDownListBox( _pXWindow );
+ else
+ return new VCLXAccessibleListBox( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXFixedText* _pXWindow )
+{
+ return new VCLXAccessibleFixedText( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXFixedHyperlink* _pXWindow )
+{
+ return new VCLXAccessibleFixedHyperlink( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXScrollBar* _pXWindow )
+{
+ return new VCLXAccessibleScrollBar( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXEdit* _pXWindow )
+{
+ return new VCLXAccessibleEdit( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXComboBox* _pXWindow )
+{
+ bool bIsDropDownBox = false;
+ VclPtr< ComboBox > pBox = _pXWindow->GetAs< ComboBox >();
+ if ( pBox )
+ bIsDropDownBox = ( ( pBox->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN );
+
+ if ( bIsDropDownBox )
+ return new VCLXAccessibleDropDownComboBox( _pXWindow );
+ else
+ return new VCLXAccessibleComboBox( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXWindow* _pXWindow )
+{
+ Reference< XAccessibleContext > xContext;
+
+ VclPtr<vcl::Window> pWindow = _pXWindow->GetWindow();
+ if ( pWindow )
+ {
+ WindowType nType = pWindow->GetType();
+
+ if ( nType == WindowType::MENUBARWINDOW || pWindow->IsMenuFloatingWindow() || pWindow->IsToolbarFloatingWindow() )
+ {
+ Reference< XAccessible > xAcc( pWindow->GetAccessible() );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleContext > xCont( xAcc->getAccessibleContext() );
+ if ( pWindow->GetType() == WindowType::MENUBARWINDOW ||
+ ( xCont.is() && xCont->getAccessibleRole() == AccessibleRole::POPUP_MENU ) )
+ {
+ xContext = xCont;
+ }
+ }
+ }
+
+ else if ( nType == WindowType::STATUSBAR )
+ {
+ xContext = new VCLXAccessibleStatusBar(_pXWindow);
+ }
+
+ else if ( nType == WindowType::TABCONTROL )
+ {
+ xContext = new VCLXAccessibleTabControl(_pXWindow);
+ }
+
+ else if ( nType == WindowType::TABPAGE && pWindow->GetAccessibleParentWindow() && pWindow->GetAccessibleParentWindow()->GetType() == WindowType::TABCONTROL )
+ {
+ xContext = new VCLXAccessibleTabPageWindow( _pXWindow );
+ }
+
+ else if ( nType == WindowType::FLOATINGWINDOW )
+ {
+ xContext = new FloatingWindowAccessible( _pXWindow );
+ }
+
+ else if ( nType == WindowType::BORDERWINDOW && hasFloatingChild( pWindow ) )
+ {
+ xContext = new FloatingWindowAccessible( _pXWindow );
+ }
+
+ else if ( ( nType == WindowType::HELPTEXTWINDOW ) || ( nType == WindowType::FIXEDLINE ) )
+ {
+ xContext = new VCLXAccessibleFixedText(_pXWindow);
+ }
+ else
+ {
+ xContext = new VCLXAccessibleComponent(_pXWindow);
+ }
+ }
+ return xContext;
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXToolBox* _pXWindow )
+{
+ return new VCLXAccessibleToolBox( _pXWindow );
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( VCLXHeaderBar* _pXWindow )
+{
+ return new VCLXAccessibleHeaderBar(_pXWindow);
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleContext( SVTXNumericField* _pXWindow )
+{
+ return new SVTXAccessibleNumericField( _pXWindow );
+}
+
+vcl::IAccessibleTabListBox* AccessibleFactory::createAccessibleTabListBox(
+ const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox ) const
+{
+ return new AccessibleTabListBox( rxParent, rBox );
+}
+
+vcl::IAccessibleBrowseBox* AccessibleFactory::createAccessibleBrowseBox(
+ const Reference< XAccessible >& _rxParent, vcl::IAccessibleTableProvider& _rBrowseBox ) const
+{
+ return new AccessibleBrowseBoxAccess( _rxParent, _rBrowseBox );
+}
+
+IAccessibleTableControl* AccessibleFactory::createAccessibleTableControl(
+ const Reference< XAccessible >& _rxParent, IAccessibleTable& _rTable ) const
+{
+ return new AccessibleGridControlAccess( _rxParent, _rTable );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleIconChoiceCtrl(
+ SvtIconChoiceCtrl& _rIconCtrl, const Reference< XAccessible >& _xParent ) const
+{
+ return new AccessibleIconChoiceCtrl( _rIconCtrl, _xParent );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleTabBar( TabBar& _rTabBar ) const
+{
+#if HAVE_FEATURE_SCRIPTING
+ return new AccessibleTabBar( &_rTabBar );
+#else
+ (void)_rTabBar;
+ return nullptr;
+#endif
+}
+
+Reference< XAccessibleContext > AccessibleFactory::createAccessibleTextWindowContext(
+ VCLXWindow* pVclXWindow, TextEngine& rEngine, TextView& rView ) const
+{
+ return new Document( pVclXWindow, rEngine, rView );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleTreeListBox(
+ SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) const
+{
+ return new AccessibleListBox( _rListBox, _xParent );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleIconView(
+ SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) const
+{
+ return new AccessibleIconView( _rListBox, _xParent );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleBrowseBoxHeaderBar(
+ const Reference< XAccessible >& rxParent, vcl::IAccessibleTableProvider& _rOwningTable,
+ AccessibleBrowseBoxObjType _eObjType ) const
+{
+ return new AccessibleBrowseBoxHeaderBar( rxParent, _rOwningTable, _eObjType );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleBrowseBoxTableCell(
+ const Reference< XAccessible >& _rxParent, vcl::IAccessibleTableProvider& _rBrowseBox,
+ const Reference< XWindow >& _xFocusWindow, sal_Int32 _nRowId, sal_uInt16 _nColId, sal_Int32 _nOffset ) const
+{
+ return new AccessibleBrowseBoxTableCell( _rxParent, _rBrowseBox, _xFocusWindow,
+ _nRowId, _nColId, _nOffset );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleBrowseBoxHeaderCell(
+ sal_Int32 _nColumnRowId, const Reference< XAccessible >& rxParent, vcl::IAccessibleTableProvider& _rBrowseBox,
+ const Reference< XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType _eObjType ) const
+{
+ return new AccessibleBrowseBoxHeaderCell( _nColumnRowId, rxParent, _rBrowseBox,
+ _xFocusWindow, _eObjType );
+}
+
+Reference< XAccessible > AccessibleFactory::createAccessibleCheckBoxCell(
+ const Reference< XAccessible >& _rxParent, vcl::IAccessibleTableProvider& _rBrowseBox,
+ const Reference< XWindow >& _xFocusWindow, sal_Int32 _nRowPos, sal_uInt16 _nColPos,
+ const TriState& _eState, bool _bIsTriState ) const
+{
+ return new AccessibleCheckBoxCell( _rxParent, _rBrowseBox, _xFocusWindow,
+ _nRowPos, _nColPos, _eState, _bIsTriState );
+}
+
+Reference< XAccessible > AccessibleFactory::createEditBrowseBoxTableCellAccess(
+ const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxControlAccessible,
+ const Reference< XWindow >& _rxFocusWindow, vcl::IAccessibleTableProvider& _rBrowseBox,
+ sal_Int32 _nRowPos, sal_uInt16 _nColPos ) const
+{
+ return new EditBrowseBoxTableCellAccess( _rxParent, _rxControlAccessible,
+ _rxFocusWindow, _rBrowseBox, _nRowPos, _nColPos );
+}
+
+} // anonymous namespace
+
+#if HAVE_FEATURE_DESKTOP
+/* this is the entry point to retrieve a factory for the toolkit-level Accessible/Contexts supplied
+ by this library
+
+ This function implements the factory function needed in toolkit
+ (of type GetStandardAccComponentFactory).
+*/
+extern "C"
+{
+ SAL_DLLPUBLIC_EXPORT void* getStandardAccessibleFactory()
+ {
+ ::toolkit::IAccessibleFactory* pFactory = new AccessibleFactory;
+ pFactory->acquire();
+ return pFactory;
+ }
+}
+
+/** this is the entry point to retrieve a factory for the svtools-level Accessible/Contexts supplied
+ by this library
+
+ This function implements the factory function needed in svtools
+ (of type GetSvtAccessibilityComponentFactory).
+*/
+extern "C"
+{
+ SAL_DLLPUBLIC_EXPORT void* getSvtAccessibilityComponentFactory()
+ {
+ ::vcl::IAccessibleFactory* pFactory = new AccessibleFactory;
+ pFactory->acquire();
+ return pFactory;
+ }
+}
+#endif // HAVE_FEATURE_DESKTOP
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/helper/accresmgr.cxx b/accessibility/source/helper/accresmgr.cxx
new file mode 100644
index 000000000..f120dcb26
--- /dev/null
+++ b/accessibility/source/helper/accresmgr.cxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <helper/accresmgr.hxx>
+
+OUString AccResId(TranslateId aId) { return Translate::get(aId, Translate::Create("acc")); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/helper/characterattributeshelper.cxx b/accessibility/source/helper/characterattributeshelper.cxx
new file mode 100644
index 000000000..9cbeaaee8
--- /dev/null
+++ b/accessibility/source/helper/characterattributeshelper.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <helper/characterattributeshelper.hxx>
+#include <tools/gen.hxx>
+#include <comphelper/sequence.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+
+CharacterAttributesHelper::CharacterAttributesHelper( const vcl::Font& rFont, sal_Int32 nBackColor, sal_Int32 nColor )
+{
+ m_aAttributeMap.emplace( OUString( "CharBackColor" ), Any( nBackColor ) );
+ m_aAttributeMap.emplace( OUString( "CharColor" ), Any( nColor ) );
+ m_aAttributeMap.emplace( OUString( "CharFontCharSet" ), Any( static_cast<sal_Int16>(rFont.GetCharSet()) ) );
+ m_aAttributeMap.emplace( OUString( "CharFontFamily" ), Any( static_cast<sal_Int16>(rFont.GetFamilyType()) ) );
+ m_aAttributeMap.emplace( OUString( "CharFontName" ), Any( rFont.GetFamilyName() ) );
+ m_aAttributeMap.emplace( OUString( "CharFontPitch" ), Any( static_cast<sal_Int16>(rFont.GetPitch()) ) );
+ m_aAttributeMap.emplace( OUString( "CharFontStyleName" ), Any( rFont.GetStyleName() ) );
+ m_aAttributeMap.emplace( OUString( "CharHeight" ), Any( static_cast<sal_Int16>(rFont.GetFontSize().Height()) ) );
+ m_aAttributeMap.emplace( OUString( "CharScaleWidth" ), Any( static_cast<sal_Int16>(rFont.GetFontSize().Width()) ) );
+ m_aAttributeMap.emplace( OUString( "CharStrikeout" ), Any( static_cast<sal_Int16>(rFont.GetStrikeout()) ) );
+ m_aAttributeMap.emplace( OUString( "CharUnderline" ), Any( static_cast<sal_Int16>(rFont.GetUnderline()) ) );
+ m_aAttributeMap.emplace( OUString( "CharWeight" ), Any( static_cast<float>(rFont.GetWeight()) ) );
+ m_aAttributeMap.emplace( OUString( "CharPosture" ), Any( static_cast<sal_Int16>(rFont.GetItalic()) ) );
+}
+
+
+std::vector< PropertyValue > CharacterAttributesHelper::GetCharacterAttributes()
+{
+ std::vector< PropertyValue > aValues;
+ aValues.reserve( m_aAttributeMap.size() );
+
+ for ( const auto& aIt : m_aAttributeMap)
+ {
+ aValues.emplace_back(aIt.first, sal_Int32(-1), aIt.second, PropertyState_DIRECT_VALUE);
+ }
+
+ return aValues;
+}
+
+
+Sequence< PropertyValue > CharacterAttributesHelper::GetCharacterAttributes( const css::uno::Sequence< OUString >& aRequestedAttributes )
+{
+ if ( !aRequestedAttributes.hasElements() )
+ return comphelper::containerToSequence(GetCharacterAttributes());
+
+ std::vector< PropertyValue > aValues;
+
+ for ( const auto& aRequestedAttribute: aRequestedAttributes)
+ {
+ AttributeMap::iterator aFound = m_aAttributeMap.find( aRequestedAttribute );
+ if ( aFound != m_aAttributeMap.end() )
+ aValues.emplace_back(aFound->first, sal_Int32(-1), aFound->second, PropertyState_DIRECT_VALUE);
+ }
+
+ return comphelper::containerToSequence(aValues);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/inc/floatingwindowaccessible.hxx b/accessibility/source/inc/floatingwindowaccessible.hxx
new file mode 100644
index 000000000..c36e86236
--- /dev/null
+++ b/accessibility/source/inc/floatingwindowaccessible.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+
+class FloatingWindowAccessible final : public VCLXAccessibleComponent
+{
+public:
+ using VCLXAccessibleComponent::VCLXAccessibleComponent;
+
+ virtual void FillAccessibleRelationSet(utl::AccessibleRelationSetHelper& rRelationSet) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/accessiblemenubasecomponent.cxx b/accessibility/source/standard/accessiblemenubasecomponent.cxx
new file mode 100644
index 000000000..f28bf8ad0
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenubasecomponent.cxx
@@ -0,0 +1,716 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/accessiblemenubasecomponent.hxx>
+#include <standard/vclxaccessiblemenu.hxx>
+#include <standard/vclxaccessiblemenuitem.hxx>
+#include <standard/vclxaccessiblemenuseparator.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/vclevent.hxx>
+
+#include <array>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// OAccessibleMenuBaseComponent
+
+
+OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
+ :m_pMenu( pMenu )
+ ,m_bEnabled( false )
+ ,m_bFocused( false )
+ ,m_bVisible( false )
+ ,m_bSelected( false )
+ ,m_bChecked( false )
+{
+ if ( m_pMenu )
+ {
+ m_aAccessibleChildren.assign( m_pMenu->GetItemCount(), Reference< XAccessible >() );
+ m_pMenu->AddEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+ }
+}
+
+
+OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
+{
+ if ( m_pMenu )
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+}
+
+
+bool OAccessibleMenuBaseComponent::IsEnabled()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsFocused()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsVisible()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsSelected()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChecked()
+{
+ return false;
+}
+
+
+void OAccessibleMenuBaseComponent::SetStates()
+{
+ m_bEnabled = IsEnabled();
+ m_bFocused = IsFocused();
+ m_bVisible = IsVisible();
+ m_bSelected = IsSelected();
+ m_bChecked = IsChecked();
+}
+
+
+void OAccessibleMenuBaseComponent::SetEnabled( bool bEnabled )
+{
+ if ( m_bEnabled == bEnabled )
+ return;
+
+ sal_Int16 nStateType=AccessibleStateType::ENABLED;
+ if (IsMenuHideDisabledEntries())
+ {
+ nStateType = AccessibleStateType::VISIBLE;
+ }
+ std::array<Any, 2> aOldValue, aNewValue;
+ if ( m_bEnabled )
+ {
+ aOldValue[0] <<= AccessibleStateType::SENSITIVE;
+ aOldValue[1] <<= nStateType;
+ }
+ else
+ {
+ aNewValue[0] <<= nStateType;
+ aNewValue[1] <<= AccessibleStateType::SENSITIVE;
+ }
+ m_bEnabled = bEnabled;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
+}
+
+
+void OAccessibleMenuBaseComponent::SetFocused( bool bFocused )
+{
+ if ( m_bFocused != bFocused )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bFocused )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bFocused = bFocused;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetVisible( bool bVisible )
+{
+ if ( m_bVisible != bVisible )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bVisible )
+ aOldValue <<= AccessibleStateType::VISIBLE;
+ else
+ aNewValue <<= AccessibleStateType::VISIBLE;
+ m_bVisible = bVisible;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetSelected( bool bSelected )
+{
+ if ( m_bSelected != bSelected )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetChecked( bool bChecked )
+{
+ if ( m_bChecked != bChecked )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bChecked = bChecked;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, bool bEnabled )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetEnabled( bEnabled );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, bool bFocused )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetFocused( bFocused );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateVisible()
+{
+ SetVisible( IsVisible() );
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetVisible( pComp->IsVisible() );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, bool bSelected )
+{
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetSelected( bSelected );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, bool bChecked )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetChecked( bChecked );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetAccessibleName( pComp->GetAccessibleName() );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetItemText( pComp->GetItemText() );
+ }
+ }
+}
+
+
+sal_Int32 OAccessibleMenuBaseComponent::GetChildCount() const
+{
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int32 i )
+{
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pMenu )
+ {
+ // create a new child
+ rtl::Reference<OAccessibleMenuBaseComponent> pChild;
+
+ if ( m_pMenu->GetItemType( static_cast<sal_uInt16>(i) ) == MenuItemType::SEPARATOR )
+ {
+ pChild = new VCLXAccessibleMenuSeparator( m_pMenu, static_cast<sal_uInt16>(i) );
+ }
+ else
+ {
+ PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( static_cast<sal_uInt16>(i) ) );
+ if ( pPopupMenu )
+ {
+ pChild = new VCLXAccessibleMenu( m_pMenu, static_cast<sal_uInt16>(i), pPopupMenu );
+ pPopupMenu->SetAccessible( pChild );
+ }
+ else
+ {
+ pChild = new VCLXAccessibleMenuItem( m_pMenu, static_cast<sal_uInt16>(i) );
+ }
+ }
+
+ // set states
+ pChild->SetStates();
+
+ xChild = pChild;
+
+ // insert into menu item list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
+{
+ Reference< XAccessible > xChild;
+ for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+}
+
+
+void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 )
+ return;
+
+ if ( o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ i = m_aAccessibleChildren.size();
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // update item position of accessible children
+ for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
+ {
+ Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
+ if ( xAcc.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
+ if ( pComp )
+ pComp->SetItemPos( static_cast<sal_uInt16>(j) );
+ }
+ }
+
+ // send accessible child event
+ Reference< XAccessible > xChild( GetChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // keep the accessible of the removed item
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // update item position of accessible children
+ for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
+ {
+ Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
+ if ( xAcc.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
+ if ( pComp )
+ pComp->SetItemPos( static_cast<sal_uInt16>(j) );
+ }
+ }
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+bool OAccessibleMenuBaseComponent::IsHighlighted()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChildHighlighted()
+{
+ bool bChildHighlighted = false;
+
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp && pComp->IsHighlighted() )
+ {
+ bChildHighlighted = true;
+ break;
+ }
+ }
+ }
+
+ return bChildHighlighted;
+}
+
+
+void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
+{
+ // open the menu
+ if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
+ Click();
+
+ // highlight the child
+ if ( m_pMenu )
+ m_pMenu->HighlightItem( static_cast<sal_uInt16>(i) );
+}
+
+
+void OAccessibleMenuBaseComponent::DeSelectAll()
+{
+ if ( m_pMenu )
+ m_pMenu->DeHighlight();
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
+{
+ bool bSelected = false;
+
+ if ( m_pMenu && m_pMenu->IsHighlighted( static_cast<sal_uInt16>(i) ) )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void OAccessibleMenuBaseComponent::Click()
+{
+}
+
+
+bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
+{
+ return false;
+}
+
+
+IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclMenuEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
+ ProcessMenuEvent( rEvent );
+}
+
+
+void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
+{
+ sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
+
+ switch ( rVclMenuEvent.GetId() )
+ {
+ case VclEventId::MenuShow:
+ case VclEventId::MenuHide:
+ {
+ UpdateVisible();
+ }
+ break;
+ case VclEventId::MenuHighlight:
+ {
+ SetFocused( false );
+ UpdateFocused( nItemPos, true );
+ UpdateSelected( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuDehighlight:
+ {
+ UpdateFocused( nItemPos, false );
+ UpdateSelected( nItemPos, false );
+ }
+ break;
+ case VclEventId::MenuSubmenuActivate:
+ {
+ }
+ break;
+ case VclEventId::MenuSubmenuDeactivate:
+ {
+ UpdateFocused( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuEnable:
+ {
+ UpdateEnabled( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuDisable:
+ {
+ UpdateEnabled( nItemPos, false );
+ }
+ break;
+ case VclEventId::MenuSubmenuChanged:
+ {
+ RemoveChild( nItemPos );
+ InsertChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuInsertItem:
+ {
+ InsertChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuRemoveItem:
+ {
+ RemoveChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuAccessibleNameChanged:
+ {
+ UpdateAccessibleName( nItemPos );
+ }
+ break;
+ case VclEventId::MenuItemTextChanged:
+ {
+ UpdateAccessibleName( nItemPos );
+ UpdateItemText( nItemPos );
+ }
+ break;
+ case VclEventId::MenuItemChecked:
+ {
+ UpdateChecked( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuItemUnchecked:
+ {
+ UpdateChecked( nItemPos, false );
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pMenu )
+ {
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+
+ m_pMenu = nullptr;
+
+ // dispose all menu items
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuBaseComponent, OAccessibleExtendedComponentHelper, OAccessibleMenuBaseComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuBaseComponent, OAccessibleExtendedComponentHelper, OAccessibleMenuBaseComponent_BASE )
+
+
+// XComponent
+
+
+void OAccessibleMenuBaseComponent::disposing()
+{
+ OAccessibleExtendedComponentHelper::disposing();
+
+ if ( !m_pMenu )
+ return;
+
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+
+ m_pMenu = nullptr;
+
+ // dispose all menu items
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+sal_Bool OAccessibleMenuBaseComponent::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+Reference< XAccessibleStateSet > OAccessibleMenuBaseComponent::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsMenuHideDisabledEntries()
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/accessiblemenucomponent.cxx b/accessibility/source/standard/accessiblemenucomponent.cxx
new file mode 100644
index 000000000..be9b1e6f4
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenucomponent.cxx
@@ -0,0 +1,423 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/accessiblemenucomponent.hxx>
+
+#include <toolkit/awt/vclxfont.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+bool OAccessibleMenuComponent::IsEnabled()
+{
+ return true;
+}
+
+
+bool OAccessibleMenuComponent::IsVisible()
+{
+ bool bVisible = false;
+
+ if ( m_pMenu )
+ bVisible = m_pMenu->IsMenuVisible();
+
+ return bVisible;
+}
+
+
+void OAccessibleMenuComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ if ( IsEnabled() )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ if ( IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ }
+
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle OAccessibleMenuComponent::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ // get bounding rectangle of the window in screen coordinates
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ aBounds = AWTRectangle( aRect );
+
+ // get position of the accessible parent in screen coordinates
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
+
+ // calculate position of the window relative to the accessible parent
+ aBounds.X -= aParentScreenLoc.X;
+ aBounds.Y -= aParentScreenLoc.Y;
+ }
+ }
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
+
+
+// XAccessibleContext
+
+
+sal_Int32 OAccessibleMenuComponent::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildCount();
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return GetChild( i );
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
+ if ( pParent )
+ xParent = pParent->GetAccessible();
+ }
+ }
+
+ return xParent;
+}
+
+
+sal_Int16 OAccessibleMenuComponent::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::UNKNOWN;
+}
+
+
+OUString OAccessibleMenuComponent::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ sDescription = pWindow->GetAccessibleDescription();
+ }
+
+ return sDescription;
+}
+
+
+OUString OAccessibleMenuComponent::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+Reference< XAccessibleRelationSet > OAccessibleMenuComponent::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Locale OAccessibleMenuComponent::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildAt( rPoint );
+}
+
+
+awt::Point OAccessibleMenuComponent::getLocationOnScreen( )
+{
+ OExternalLockGuard aGuard( this );
+
+ awt::Point aPos;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ aPos = AWTPoint( aRect.TopLeft() );
+ }
+ }
+
+ return aPos;
+}
+
+
+void OAccessibleMenuComponent::grabFocus( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ pWindow->GrabFocus();
+ }
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ Color nColor = rStyleSettings.GetMenuTextColor();
+
+ return sal_Int32(nColor);
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > OAccessibleMenuComponent::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY );
+ if ( xDev.is() )
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont;
+ pVCLXFont->Init( *xDev, rStyleSettings.GetMenuFont() );
+ xFont = pVCLXFont;
+ }
+ }
+ }
+
+ return xFont;
+}
+
+
+OUString OAccessibleMenuComponent::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString OAccessibleMenuComponent::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleSelection
+
+
+void OAccessibleMenuComponent::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ SelectChild( nChildIndex );
+}
+
+
+sal_Bool OAccessibleMenuComponent::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+
+void OAccessibleMenuComponent::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+
+ DeSelectAll();
+}
+
+
+void OAccessibleMenuComponent::selectAllAccessibleChildren( )
+{
+ // This method makes no sense in a menu, and so does nothing.
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nRet = 0;
+
+ for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
+ {
+ xChild = GetChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void OAccessibleMenuComponent::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ DeSelectAll();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/accessiblemenuitemcomponent.cxx b/accessibility/source/standard/accessiblemenuitemcomponent.cxx
new file mode 100644
index 000000000..e61c7452e
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenuitemcomponent.cxx
@@ -0,0 +1,472 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/accessiblemenuitemcomponent.hxx>
+
+
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <comphelper/accessibletexthelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+OAccessibleMenuItemComponent::OAccessibleMenuItemComponent( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
+ :OAccessibleMenuBaseComponent( pMenu )
+ ,m_pParent( pParent )
+ ,m_nItemPos( nItemPos )
+{
+ m_sAccessibleName = GetAccessibleName();
+ m_sItemText = GetItemText();
+}
+
+OAccessibleMenuItemComponent::~OAccessibleMenuItemComponent()
+{
+}
+
+bool OAccessibleMenuItemComponent::IsEnabled()
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bEnabled = false;
+ if ( m_pParent )
+ bEnabled = m_pParent->IsItemEnabled( m_pParent->GetItemId( m_nItemPos ) );
+
+ return bEnabled;
+}
+
+
+bool OAccessibleMenuItemComponent::IsVisible()
+{
+ bool bVisible = false;
+
+ if ( m_pParent )
+ bVisible = m_pParent->IsItemPosVisible( m_nItemPos );
+
+ return bVisible;
+}
+
+
+void OAccessibleMenuItemComponent::Select()
+{
+ // open the parent menu
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
+ if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
+ pComp->Click();
+ }
+
+ // highlight the menu item
+ if ( m_pParent )
+ m_pParent->HighlightItem( m_nItemPos );
+}
+
+
+void OAccessibleMenuItemComponent::DeSelect()
+{
+ if ( m_pParent && IsSelected() )
+ m_pParent->DeHighlight();
+}
+
+
+void OAccessibleMenuItemComponent::Click()
+{
+ // open the parent menu
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
+ if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
+ pComp->Click();
+ }
+
+ // click the menu item
+ if ( !m_pParent )
+ return;
+
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( !pWindow )
+ return;
+
+ // #102438# Menu items are not selectable
+ // Popup menus are executed asynchronously, triggered by a timer.
+ // As Menu::SelectItem only works, if the corresponding menu window is
+ // already created, we have to set the menu delay to 0, so
+ // that the popup menus are executed synchronously.
+ AllSettings aSettings = pWindow->GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+ sal_Int32 nDelay = aMouseSettings.GetMenuDelay();
+ aMouseSettings.SetMenuDelay( 0 );
+ aSettings.SetMouseSettings( aMouseSettings );
+ pWindow->SetSettings( aSettings );
+
+ m_pParent->SelectItem( m_pParent->GetItemId( m_nItemPos ) );
+
+ // meanwhile the window pointer may be invalid
+ pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ // set the menu delay back to the old value
+ aSettings = pWindow->GetSettings();
+ aMouseSettings = aSettings.GetMouseSettings();
+ aMouseSettings.SetMenuDelay( nDelay );
+ aSettings.SetMouseSettings( aMouseSettings );
+ pWindow->SetSettings( aSettings );
+ }
+}
+
+
+void OAccessibleMenuItemComponent::SetItemPos( sal_uInt16 nItemPos )
+{
+ m_nItemPos = nItemPos;
+}
+
+
+void OAccessibleMenuItemComponent::SetAccessibleName( const OUString& sAccessibleName )
+{
+ if ( m_sAccessibleName != sAccessibleName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sAccessibleName;
+ aNewValue <<= sAccessibleName;
+ m_sAccessibleName = sAccessibleName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString OAccessibleMenuItemComponent::GetAccessibleName()
+{
+ OUString sName;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ sName = m_pParent->GetAccessibleName( nItemId );
+ if ( sName.isEmpty() )
+ sName = m_pParent->GetItemText( nItemId );
+ sName = OutputDevice::GetNonMnemonicString( sName );
+#if defined(_WIN32)
+ if ( m_pParent->GetAccelKey( nItemId ).GetName().getLength() )
+ sName += "\t" + m_pParent->GetAccelKey(nItemId).GetName();
+#endif
+ }
+
+ return sName;
+}
+
+
+void OAccessibleMenuItemComponent::SetItemText( const OUString& sItemText )
+{
+ Any aOldValue, aNewValue;
+ if ( OCommonAccessibleText::implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
+ {
+ m_sItemText = sItemText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString OAccessibleMenuItemComponent::GetItemText()
+{
+ OUString sText;
+ if ( m_pParent )
+ sText = OutputDevice::GetNonMnemonicString( m_pParent->GetItemText( m_pParent->GetItemId( m_nItemPos ) ) );
+
+ return sText;
+}
+
+
+void OAccessibleMenuItemComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ bool bEnabled = IsEnabled();
+ if ( bEnabled )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ if ( IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ if( !IsMenuHideDisabledEntries() || bEnabled )
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ }
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle OAccessibleMenuItemComponent::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pParent )
+ {
+ // get bounding rectangle of the item relative to the containing window
+ aBounds = AWTRectangle( m_pParent->GetBoundingRectangle( m_nItemPos ) );
+
+ // get position of containing window in screen coordinates
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ awt::Point aWindowScreenLoc = AWTPoint( aRect.TopLeft() );
+
+ // get position of accessible parent in screen coordinates
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
+
+ // calculate bounding rectangle of the item relative to the accessible parent
+ aBounds.X += aWindowScreenLoc.X - aParentScreenLoc.X;
+ aBounds.Y += aWindowScreenLoc.Y - aParentScreenLoc.Y;
+ }
+ }
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XComponent
+
+
+void SAL_CALL OAccessibleMenuItemComponent::disposing()
+{
+ OAccessibleMenuBaseComponent::disposing();
+
+ m_pParent = nullptr;
+ m_sAccessibleName.clear();
+ m_sItemText.clear();
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 OAccessibleMenuItemComponent::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessible >();
+}
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_pParent->GetAccessible();
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_nItemPos;
+}
+
+
+sal_Int16 OAccessibleMenuItemComponent::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::UNKNOWN;
+}
+
+
+OUString OAccessibleMenuItemComponent::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pParent )
+ sDescription = m_pParent->GetAccessibleDescription( m_pParent->GetItemId( m_nItemPos ) );
+
+ return sDescription;
+}
+
+
+OUString OAccessibleMenuItemComponent::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sAccessibleName;
+}
+
+
+Reference< XAccessibleRelationSet > OAccessibleMenuItemComponent::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Locale OAccessibleMenuItemComponent::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleAtPoint( const awt::Point& )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Reference< XAccessible >();
+}
+
+
+void OAccessibleMenuItemComponent::grabFocus( )
+{
+ // no focus for items
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > OAccessibleMenuItemComponent::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString OAccessibleMenuItemComponent::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString OAccessibleMenuItemComponent::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pParent )
+ sRet = m_pParent->GetTipHelpText( m_pParent->GetItemId( m_nItemPos ) );
+
+ return sRet;
+}
+
+
+bool OAccessibleMenuItemComponent::IsMenuHideDisabledEntries()
+{
+ if (m_pParent )
+ {
+ if( m_pParent->GetMenuFlags() & MenuFlags::HideDisabledEntries)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/floatingwindowaccessible.cxx b/accessibility/source/standard/floatingwindowaccessible.cxx
new file mode 100644
index 000000000..aa5ef41f6
--- /dev/null
+++ b/accessibility/source/standard/floatingwindowaccessible.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <floatingwindowaccessible.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/window.hxx>
+
+namespace uno = ::com::sun::star::uno;
+
+using ::com::sun::star::accessibility::AccessibleRelation;
+namespace AccessibleRelationType = ::com::sun::star::accessibility::AccessibleRelationType;
+
+void FloatingWindowAccessible::FillAccessibleRelationSet(utl::AccessibleRelationSetHelper& rRelationSet)
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParentWindow = pWindow->GetParent();
+ if( pParentWindow )
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pParentWindow->GetAccessible() };
+ rRelationSet.AddRelation( AccessibleRelation( AccessibleRelationType::SUB_WINDOW_OF, aSequence ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/svtaccessiblenumericfield.cxx b/accessibility/source/standard/svtaccessiblenumericfield.cxx
new file mode 100644
index 000000000..729966eb8
--- /dev/null
+++ b/accessibility/source/standard/svtaccessiblenumericfield.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/svtaccessiblenumericfield.hxx>
+#include <toolkit/awt/vclxwindows.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+SVTXAccessibleNumericField::SVTXAccessibleNumericField(VCLXWindow* pVCLWindow)
+ : VCLXAccessibleEdit(pVCLWindow)
+{
+}
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2(SVTXAccessibleNumericField, VCLXAccessibleTextComponent,
+ SVTXAccessibleNumericField_BASE)
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(SVTXAccessibleNumericField, VCLXAccessibleTextComponent,
+ SVTXAccessibleNumericField_BASE)
+
+sal_Int16 SVTXAccessibleNumericField::getAccessibleRole() { return AccessibleRole::SPIN_BOX; }
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getCurrentValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getValue();
+
+ return css::uno::Any(dValue);
+}
+
+sal_Bool SVTXAccessibleNumericField::setCurrentValue(const css::uno::Any& aNumber)
+{
+ OExternalLockGuard aGuard(this);
+
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (!pField)
+ return false;
+
+ double dValue = 0;
+ aNumber >>= dValue;
+ pField->setValue(dValue);
+ return true;
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMaximumValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getMax();
+
+ return css::uno::Any(dValue);
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMinimumValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getMin();
+
+ return css::uno::Any(dValue);
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMinimumIncrement()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getSpinSize();
+
+ return css::uno::Any(dValue);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblebox.cxx b/accessibility/source/standard/vclxaccessiblebox.cxx
new file mode 100644
index 000000000..ce81c254c
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblebox.cxx
@@ -0,0 +1,525 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblebox.hxx>
+#include <standard/vclxaccessibletextfield.hxx>
+#include <standard/vclxaccessibleedit.hxx>
+#include <standard/vclxaccessiblelist.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+VCLXAccessibleBox::VCLXAccessibleBox (VCLXWindow* pVCLWindow, BoxType aType, bool bIsDropDownBox)
+ : VCLXAccessibleComponent (pVCLWindow),
+ m_aBoxType (aType),
+ m_bIsDropDownBox (bIsDropDownBox)
+{
+ // Set up the flags that indicate which children this object has.
+ m_bHasListChild = true;
+
+ // A text field is not present for non drop down list boxes.
+ if ((m_aBoxType==LISTBOX) && ! m_bIsDropDownBox)
+ m_bHasTextChild = false;
+ else
+ m_bHasTextChild = true;
+}
+
+void VCLXAccessibleBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ uno::Any aOldValue, aNewValue;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow:
+ case VclEventId::WindowHide:
+ {
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ // Just compare to the combo box text field. All other children
+ // are identical to this object in which case this object will
+ // be removed in a short time.
+ if (m_aBoxType==COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( ( pComboBox != nullptr ) && ( pChildWindow != nullptr ) )
+ if (pChildWindow == pComboBox->GetSubEdit())
+ {
+ if (rVclWindowEvent.GetId() == VclEventId::WindowShow)
+ {
+ // Instantiate text field.
+ getAccessibleChild (0);
+ aNewValue <<= m_xText;
+ }
+ else
+ {
+ // Release text field.
+ aOldValue <<= m_xText;
+ m_xText = nullptr;
+ }
+ // Tell the listeners about the new/removed child.
+ NotifyAccessibleEvent (
+ AccessibleEventId::CHILD,
+ aOldValue, aNewValue);
+ }
+
+ }
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
+ }
+}
+
+void VCLXAccessibleBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownSelect:
+ case VclEventId::ListboxSelect:
+ {
+ // Forward the call to the list child.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent, m_bIsDropDownBox);
+#if defined(_WIN32)
+ if (m_bIsDropDownBox)
+ {
+ NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
+ }
+#endif
+ }
+ break;
+ }
+ case VclEventId::DropdownOpen:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ pList->HandleDropOpen();
+ }
+ break;
+ }
+ case VclEventId::DropdownClose:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ }
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow && (pWindow->HasFocus() || pWindow->HasChildPathFocus()) )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ }
+ case VclEventId::ComboboxSelect:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if (pList != nullptr && m_xText.is())
+ {
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getSelectedText();
+ if ( sText.isEmpty() )
+ sText = xText->getText();
+ pList->UpdateSelection_Acc(sText, m_bIsDropDownBox);
+#if defined(_WIN32)
+ if (m_bIsDropDownBox || m_aBoxType==COMBOBOX)
+ NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
+#endif
+ }
+ }
+ break;
+ }
+ //case VclEventId::DropdownOpen:
+ //case VclEventId::DropdownClose:
+ case VclEventId::ListboxDoubleClick:
+ case VclEventId::ListboxScrolled:
+ //case VclEventId::ListboxSelect:
+ case VclEventId::ListboxItemAdded:
+ case VclEventId::ListboxItemRemoved:
+ case VclEventId::ComboboxItemAdded:
+ case VclEventId::ComboboxItemRemoved:
+ {
+ // Forward the call to the list child.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ break;
+ }
+
+ //case VclEventId::ComboboxSelect:
+ case VclEventId::ComboboxDeselect:
+ {
+ // Selection is handled by VCLXAccessibleList which operates on
+ // the same VCL object as this box does. In case of the
+ // combobox, however, we have to help by providing the list with
+ // the text of the currently selected item.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if (pList != nullptr && m_xText.is())
+ {
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getSelectedText();
+ if ( sText.isEmpty() )
+ sText = xText->getText();
+ pList->UpdateSelection (sText);
+ }
+ }
+ break;
+ }
+
+ case VclEventId::EditModify:
+ case VclEventId::EditSelectionChanged:
+ case VclEventId::EditCaretChanged:
+ // Modify/Selection events are handled by the combo box instead of
+ // directly by the edit field (Why?). Therefore, delegate this
+ // call to the edit field.
+ if (m_aBoxType==COMBOBOX)
+ {
+ if (m_xText.is())
+ {
+ Reference<XAccessibleContext> xContext = m_xText->getAccessibleContext();
+ VCLXAccessibleEdit* pEdit = static_cast<VCLXAccessibleEdit*>(xContext.get());
+ if (pEdit != nullptr)
+ pEdit->ProcessWindowEvent (rVclWindowEvent);
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
+
+//===== XAccessible =========================================================
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleBox::getAccessibleContext( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return this;
+}
+
+//===== XAccessibleContext ==================================================
+
+sal_Int32 VCLXAccessibleBox::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleBox::implGetAccessibleChildCount()
+{
+ // Usually a box has a text field and a list of items as its children.
+ // Non drop down list boxes have no text field. Additionally check
+ // whether the object is valid.
+ sal_Int32 nCount = 0;
+ if (IsValid())
+ nCount += (m_bHasTextChild?1:0) + (m_bHasListChild?1:0);
+ else
+ {
+ // Object not valid anymore. Release references to children.
+ m_bHasTextChild = false;
+ m_xText = nullptr;
+ m_bHasListChild = false;
+ m_xList = nullptr;
+ }
+
+ return nCount;
+}
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleBox::getAccessibleChild (sal_Int32 i)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if (i<0 || i>=implGetAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ if (IsValid())
+ {
+ if (i==1 || ! m_bHasTextChild)
+ {
+ // List.
+ if ( ! m_xList.is())
+ {
+ rtl::Reference<VCLXAccessibleList> pList = new VCLXAccessibleList ( GetVCLXWindow(),
+ (m_aBoxType == LISTBOX ? VCLXAccessibleList::LISTBOX : VCLXAccessibleList::COMBOBOX),
+ this);
+ pList->SetIndexInParent (i);
+ m_xList = pList;
+ }
+ xChild = m_xList;
+ }
+ else
+ {
+ // Text Field.
+ if ( ! m_xText.is())
+ {
+ if (m_aBoxType==COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox!=nullptr && pComboBox->GetSubEdit()!=nullptr)
+ //Set the edit's acc name the same as parent
+ {
+ pComboBox->GetSubEdit()->SetAccessibleName(getAccessibleName());
+ m_xText = pComboBox->GetSubEdit()->GetAccessible();
+ }
+ }
+ else if (m_bIsDropDownBox)
+ m_xText = new VCLXAccessibleTextField (GetVCLXWindow(),this);
+ }
+ xChild = m_xText;
+ }
+ }
+
+ return xChild;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleBox::getAccessibleRole()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // Return the role <const>COMBO_BOX</const> for both VCL combo boxes and
+ // VCL list boxes in DropDown-Mode else <const>PANEL</const>.
+ // This way the Java bridge has not to handle both independently.
+ //return m_bIsDropDownBox ? AccessibleRole::COMBO_BOX : AccessibleRole::PANEL;
+ if (m_bIsDropDownBox || (m_aBoxType == COMBOBOX))
+ return AccessibleRole::COMBO_BOX;
+ else
+ return AccessibleRole::PANEL;
+}
+
+//===== XAccessibleAction ===================================================
+
+sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleActionCount()
+{
+ ::osl::Guard< ::osl::Mutex> aGuard (GetMutex());
+
+ // There is one action for drop down boxes (toggle popup) and none for
+ // the other boxes.
+ return m_bIsDropDownBox ? 1 : 0;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleBox::doAccessibleAction (sal_Int32 nIndex)
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if (nIndex!=0 || !m_bIsDropDownBox)
+ throw css::lang::IndexOutOfBoundsException(
+ ("VCLXAccessibleBox::doAccessibleAction: index "
+ + OUString::number(nIndex) + " not among 0.."
+ + OUString::number(getAccessibleActionCount())),
+ static_cast<OWeakObject*>(this));
+
+ if (m_aBoxType == COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox != nullptr)
+ {
+ pComboBox->ToggleDropDown();
+ bNotify = true;
+ }
+ }
+ else if (m_aBoxType == LISTBOX)
+ {
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox != nullptr)
+ {
+ pListBox->ToggleDropDown();
+ bNotify = true;
+ }
+ }
+ }
+
+ if (bNotify)
+ NotifyAccessibleEvent (AccessibleEventId::ACTION_CHANGED, Any(), Any());
+
+ return bNotify;
+}
+
+OUString SAL_CALL VCLXAccessibleBox::getAccessibleActionDescription (sal_Int32 nIndex)
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if (nIndex!=0 || !m_bIsDropDownBox)
+ throw css::lang::IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_TOGGLEPOPUP;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ Reference< XAccessibleKeyBinding > xRet;
+
+ if (nIndex<0 || nIndex>=getAccessibleActionCount())
+ throw css::lang::IndexOutOfBoundsException();
+
+ // ... which key?
+ return xRet;
+}
+
+// ===== XAccessibleValue ===============================================
+Any VCLXAccessibleBox::getCurrentValue( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ Any aAny;
+ if( m_xList.is() && m_xText.is())
+ {
+ // VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getText();
+ aAny <<= sText;
+ }
+ }
+ if (m_aBoxType == LISTBOX && m_bIsDropDownBox && m_xList.is() )
+ {
+
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if(pList->IsInDropDown())
+ {
+ if(pList->getSelectedAccessibleChildCount()>0)
+ {
+ Reference<XAccessibleContext> xName (pList->getSelectedAccessibleChild(sal_Int32(0)), UNO_QUERY);
+ if(xName.is())
+ {
+ aAny <<= xName->getAccessibleName();
+ }
+ }
+ }
+ }
+
+ return aAny;
+}
+
+sal_Bool VCLXAccessibleBox::setCurrentValue( const Any& aNumber )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ OUString fValue;
+ bool bValid = (aNumber >>= fValue);
+ return bValid;
+
+}
+
+Any VCLXAccessibleBox::getMaximumValue( )
+{
+ Any aAny;
+ return aAny;
+}
+
+Any VCLXAccessibleBox::getMinimumValue( )
+{
+ Any aAny;
+ return aAny;
+}
+
+Any VCLXAccessibleBox::getMinimumIncrement( )
+{
+ return Any();
+}
+
+// Set the INDETERMINATE state when there is no selected item for combobox
+void VCLXAccessibleBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet(rStateSet);
+ if (m_aBoxType == COMBOBOX )
+ {
+ OUString sText;
+ sal_Int32 nEntryCount = 0;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox != nullptr)
+ {
+ Edit* pSubEdit = pComboBox->GetSubEdit();
+ if ( pSubEdit)
+ sText = pSubEdit->GetText();
+ nEntryCount = pComboBox->GetEntryCount();
+ }
+ if ( sText.isEmpty() && nEntryCount > 0 )
+ rStateSet.AddState(AccessibleStateType::INDETERMINATE);
+ }
+ else if (m_aBoxType == LISTBOX && m_bIsDropDownBox)
+ {
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox != nullptr && pListBox->GetEntryCount() > 0)
+ {
+ sal_Int32 nSelectedEntryCount = pListBox->GetSelectedEntryCount();
+ if ( nSelectedEntryCount == 0)
+ rStateSet.AddState(AccessibleStateType::INDETERMINATE);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblebutton.cxx b/accessibility/source/standard/vclxaccessiblebutton.cxx
new file mode 100644
index 000000000..d5ffb68bb
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblebutton.cxx
@@ -0,0 +1,310 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblebutton.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <strings.hxx>
+
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleButton
+
+
+void VCLXAccessibleButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::PushbuttonToggle:
+ {
+ Any aOldValue;
+ Any aNewValue;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton && pButton->GetState() == TRISTATE_TRUE )
+ aNewValue <<= AccessibleStateType::CHECKED;
+ else
+ aOldValue <<= AccessibleStateType::CHECKED;
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( !pButton )
+ return;
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( pButton->GetState() == TRISTATE_TRUE )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+
+ if ( pButton->IsPressed() )
+ rStateSet.AddState( AccessibleStateType::PRESSED );
+
+ // IA2 CWS: if the button has a popup menu, it should has the state EXPANDABLE
+ if( pButton->GetType() == WindowType::MENUBUTTON )
+ {
+ rStateSet.AddState( AccessibleStateType::EXPANDABLE );
+ }
+ if( pButton->GetStyle() & WB_DEFBUTTON )
+ {
+ rStateSet.AddState( AccessibleStateType::DEFAULT );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleButton::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleButton";
+}
+
+
+Sequence< OUString > VCLXAccessibleButton::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleButton" };
+}
+
+
+// XAccessibleContext
+
+
+OUString VCLXAccessibleButton::getAccessibleName( )
+{
+ OUString aName( VCLXAccessibleTextComponent::getAccessibleName() );
+ sal_Int32 nLength = aName.getLength();
+
+ if ( nLength >= 3 && aName.match( "...", nLength - 3 ) )
+ {
+ if ( nLength == 3 )
+ {
+ // it's a browse button
+ aName = AccResId( RID_STR_ACC_NAME_BROWSEBUTTON );
+ }
+ else
+ {
+ // remove the three trailing dots
+ aName = aName.copy( 0, nLength - 3 );
+ }
+ }
+ else if ( nLength >= 3 && aName.match( "<< ", 0 ) )
+ {
+ // remove the leading symbols
+ aName = aName.copy( 3, nLength - 3 );
+ }
+ else if ( nLength >= 3 && aName.match( " >>", nLength - 3 ) )
+ {
+ // remove the trailing symbols
+ aName = aName.copy( 0, nLength - 3 );
+ }
+
+ return aName;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleButton::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleButton::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ pButton->Click();
+
+ return true;
+}
+
+
+OUString VCLXAccessibleButton::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_CLICK;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleButton::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleButton::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ aValue <<= static_cast<sal_Int32>(pButton->IsPressed());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleButton::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ pButton->SetPressed( nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleButton::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleButton::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleButton::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblecheckbox.cxx b/accessibility/source/standard/vclxaccessiblecheckbox.cxx
new file mode 100644
index 000000000..20cf2138b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblecheckbox.cxx
@@ -0,0 +1,342 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblecheckbox.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleCheckBox
+
+
+VCLXAccessibleCheckBox::VCLXAccessibleCheckBox( VCLXWindow* pVCLWindow )
+ :VCLXAccessibleTextComponent( pVCLWindow )
+{
+ m_bChecked = IsChecked();
+ m_bIndeterminate = IsIndeterminate();
+}
+
+
+bool VCLXAccessibleCheckBox::IsChecked() const
+{
+ bool bChecked = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox && pVCLXCheckBox->getState() == sal_Int16(1) )
+ bChecked = true;
+
+ return bChecked;
+}
+
+
+bool VCLXAccessibleCheckBox::IsIndeterminate() const
+{
+ bool bIndeterminate = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox && pVCLXCheckBox->getState() == sal_Int16(2) )
+ bIndeterminate = true;
+
+ return bIndeterminate;
+}
+
+
+void VCLXAccessibleCheckBox::SetChecked( bool bChecked )
+{
+ if ( m_bChecked != bChecked )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bChecked = bChecked;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::SetIndeterminate( bool bIndeterminate )
+{
+ if ( m_bIndeterminate != bIndeterminate )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bIndeterminate )
+ aOldValue <<= AccessibleStateType::INDETERMINATE;
+ else
+ aNewValue <<= AccessibleStateType::INDETERMINATE;
+ m_bIndeterminate = bIndeterminate;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::CheckboxToggle:
+ {
+ SetChecked( IsChecked() );
+ SetIndeterminate( IsIndeterminate() );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsChecked() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+
+ if ( IsIndeterminate() )
+ rStateSet.AddState( AccessibleStateType::INDETERMINATE );
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleCheckBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleCheckBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleCheckBox::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleCheckBox" };
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleCheckBox::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleCheckBox::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pCheckBox && pVCLXCheckBox )
+ {
+ sal_Int32 nValueMax = sal_Int32(1);
+
+ if ( pCheckBox->IsTriStateEnabled() )
+ nValueMax = sal_Int32(2);
+
+ sal_Int32 nValue = static_cast<sal_Int32>(pVCLXCheckBox->getState());
+
+ ++nValue;
+
+ if ( nValue > nValueMax )
+ nValue = 0;
+
+ pVCLXCheckBox->setState( static_cast<sal_Int16>(nValue) );
+ }
+
+ return true;
+}
+
+
+OUString VCLXAccessibleCheckBox::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ if(IsChecked())
+ return AccResId( RID_STR_ACC_ACTION_UNCHECK );
+ else
+ return AccResId( RID_STR_ACC_ACTION_CHECK );
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleCheckBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleCheckBox::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox )
+ aValue <<= static_cast<sal_Int32>(pVCLXCheckBox->getState());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleCheckBox::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox )
+ {
+ sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+ nValueMax=implGetMaximumValue();
+
+ if ( nValue < nValueMin )
+ nValue = nValueMin;
+ else if ( nValue > nValueMax )
+ nValue = nValueMax;
+
+ pVCLXCheckBox->setState( static_cast<sal_Int16>(nValue) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleCheckBox::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= implGetMaximumValue();
+
+ return aValue;
+}
+
+sal_Int32 VCLXAccessibleCheckBox::implGetMaximumValue( )
+{
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox && pCheckBox->IsTriStateEnabled() )
+ return 2;
+
+ return 1;
+}
+
+Any VCLXAccessibleCheckBox::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleCheckBox::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblecombobox.cxx b/accessibility/source/standard/vclxaccessiblecombobox.cxx
new file mode 100644
index 000000000..e537f7199
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblecombobox.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblecombobox.hxx>
+#include <vcl/window.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleComboBox::VCLXAccessibleComboBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::COMBOBOX, false)
+{
+}
+
+
+bool VCLXAccessibleComboBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleComboBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleComboBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleComboBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleComboBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx b/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx
new file mode 100644
index 000000000..97fcebb04
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibledropdowncombobox.hxx>
+
+#include <toolkit/awt/vclxwindow.hxx>
+#include <vcl/vclevent.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleDropDownComboBox::VCLXAccessibleDropDownComboBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::COMBOBOX, true)
+{
+}
+
+
+bool VCLXAccessibleDropDownComboBox::IsValid() const
+{
+ return GetWindow();
+}
+
+void VCLXAccessibleDropDownComboBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownOpen:
+ case VclEventId::DropdownClose:
+ {
+ break;
+ }
+
+ default:
+ VCLXAccessibleBox::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// XServiceInfo
+
+OUString VCLXAccessibleDropDownComboBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleDropDownComboBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleDropDownComboBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleDropDownComboBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx b/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx
new file mode 100644
index 000000000..641c1bdc4
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibledropdownlistbox.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleDropDownListBox::VCLXAccessibleDropDownListBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::LISTBOX, true)
+{
+}
+
+bool VCLXAccessibleDropDownListBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+OUString VCLXAccessibleDropDownListBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleDropDownListBox";
+}
+
+Sequence< OUString > VCLXAccessibleDropDownListBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleDropDownListBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleedit.cxx b/accessibility/source/standard/vclxaccessibleedit.cxx
new file mode 100644
index 000000000..d41c29737
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleedit.cxx
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibleedit.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <comphelper/string.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/toolkit/edit.hxx>
+#include <vcl/toolkit/vclmedit.hxx>
+#include <vcl/textdata.hxx>
+#include <vcl/txtattr.hxx>
+#include <vcl/xtextedt.hxx>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleEdit
+
+
+VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow* pVCLWindow )
+ :VCLXAccessibleTextComponent( pVCLWindow )
+{
+ m_nCaretPosition = getCaretPosition();
+}
+
+
+void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::EditModify:
+ {
+ SetText( implGetText() );
+ }
+ break;
+ case VclEventId::EditCaretChanged:
+ {
+ sal_Int32 nOldCaretPosition = m_nCaretPosition;
+ m_nCaretPosition = getCaretPosition();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow && pWindow->HasChildPathFocus())
+ {
+ if (m_nCaretPosition != nOldCaretPosition)
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= nOldCaretPosition;
+ aNewValue <<= m_nCaretPosition;
+ NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::EditSelectionChanged:
+ {
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow && pWindow->HasChildPathFocus())
+ {
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ rStateSet.AddState( AccessibleStateType::SINGLE_LINE );
+ if ( pVCLXEdit->isEditable() )
+ rStateSet.AddState( AccessibleStateType::EDITABLE );
+ }
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleEdit::implGetText()
+{
+ OUString aText;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ aText = OutputDevice::GetNonMnemonicString( pEdit->GetText() );
+
+ if ( implGetAccessibleRole() == AccessibleRole::PASSWORD_TEXT )
+ {
+ sal_Unicode cEchoChar = pEdit->GetEchoChar();
+ if ( !cEchoChar )
+ cEchoChar = '*';
+ OUStringBuffer sTmp(aText.getLength());
+ aText = comphelper::string::padToLength(sTmp, aText.getLength(),
+ cEchoChar).makeStringAndClear();
+ }
+ }
+
+ return aText;
+}
+
+
+void VCLXAccessibleEdit::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ awt::Selection aSelection;
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit )
+ aSelection = pVCLXEdit->getSelection();
+
+ nStartIndex = aSelection.Min;
+ nEndIndex = aSelection.Max;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleEdit::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleEdit";
+}
+
+
+Sequence< OUString > VCLXAccessibleEdit::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleEdit" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleEdit::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleEdit::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+sal_Int16 VCLXAccessibleEdit::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetAccessibleRole();
+}
+
+sal_Int16 VCLXAccessibleEdit::implGetAccessibleRole( )
+{
+ sal_Int16 nRole;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit && ( pEdit->IsPassword() || pEdit->GetEchoChar() ) )
+ nRole = AccessibleRole::PASSWORD_TEXT;
+ else if ( pEdit && ( pEdit->GetStyle() & WB_READONLY ) )
+ nRole = AccessibleRole::STATIC;
+ else
+ nRole = AccessibleRole::TEXT;
+
+ return nRole;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleEdit::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ // There is one action: activate
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ bool bDoAction = false;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->GrabFocus();
+ bDoAction = true;
+ }
+
+ return bDoAction;
+}
+
+
+OUString VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0)
+ throw IndexOutOfBoundsException();
+
+ return "activate";
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleEdit::getCaretPosition( )
+{
+ return getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex )
+{
+ return setSelection( nIndex, nIndex );
+}
+
+
+sal_Unicode VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex )
+{
+ return VCLXAccessibleTextComponent::getCharacter( nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+ Sequence< PropertyValue > aProperties = VCLXAccessibleTextComponent::getCharacterAttributes( nIndex, aRequestedAttributes );
+ auto aNonConstRange = asNonConstRange(aProperties);
+
+ // Handle multiline edit character properties
+ VclPtr<VclMultiLineEdit> pMulitLineEdit = GetAsDynamic< VclMultiLineEdit >();
+ if ( pMulitLineEdit )
+ {
+ ExtTextEngine* pTextEngine = pMulitLineEdit->GetTextEngine();
+ TextPaM aCursor( 0, nIndex );
+ const TextAttribFontColor* pFontColor = static_cast<const TextAttribFontColor* >(pTextEngine->FindAttrib( aCursor, TEXTATTR_FONTCOLOR ));
+ if ( pFontColor )
+ {
+ for (PropertyValue& aValue : aNonConstRange )
+ {
+ if (aValue.Name == "CharColor")
+ {
+ aValue.Value <<= pFontColor->GetColor().GetRGBColor();
+ break;
+ }
+ }
+ }
+ }
+
+ // Set default character color if it is not set yet to a valid value
+ for (PropertyValue& aValue : aNonConstRange )
+ {
+ if (aValue.Name == "CharColor")
+ {
+ if ( aValue.Value == sal_Int32(-1) )
+ {
+ OutputDevice* pDev = Application::GetDefaultDevice();
+ if ( pDev )
+ {
+ aValue.Value <<= pDev->GetSettings().GetStyleSettings().GetFieldTextColor();
+ }
+ }
+ break;
+ }
+ }
+
+ return aProperties;
+}
+
+
+awt::Rectangle VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ sal_Int32 nLength = implGetText().getLength();
+
+ if ( !implIsValidRange( nIndex, nIndex, nLength ) )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ {
+ if ( nIndex == nLength )
+ {
+ // #108914# calculate virtual bounding rectangle
+ for ( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tools::Rectangle aRect = pControl->GetCharacterBounds( i );
+ sal_Int32 nHeight = aRect.GetHeight();
+ if ( aBounds.Height < nHeight )
+ {
+ aBounds.Y = aRect.Top();
+ aBounds.Height = nHeight;
+ }
+ if ( i == nLength - 1 )
+ {
+ aBounds.X = aRect.Right() + 1;
+ aBounds.Width = 1;
+ }
+ }
+ }
+ else
+ {
+ aBounds = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
+ }
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getCharacterCount( )
+{
+ return VCLXAccessibleTextComponent::getCharacterCount();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getIndexAtPoint( const awt::Point& aPoint )
+{
+ return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint );
+}
+
+
+OUString VCLXAccessibleEdit::getSelectedText( )
+{
+ return VCLXAccessibleTextComponent::getSelectedText();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getSelectionStart( )
+{
+ return VCLXAccessibleTextComponent::getSelectionStart();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getSelectionEnd( )
+{
+ return VCLXAccessibleTextComponent::getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pVCLXEdit && pEdit && pEdit->IsEnabled() )
+ {
+ pVCLXEdit->setSelection( awt::Selection( nStartIndex, nEndIndex ) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+OUString VCLXAccessibleEdit::getText( )
+{
+ return VCLXAccessibleTextComponent::getText();
+}
+
+
+OUString VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return VCLXAccessibleTextComponent::getTextRange( nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+ // Override general text component behavior: MultiLineEdit can have more text portions
+ if ( aTextType == AccessibleTextType::ATTRIBUTE_RUN )
+ {
+ VclPtr<VclMultiLineEdit> pMulitLineEdit = GetAsDynamic< VclMultiLineEdit >();
+ if ( pMulitLineEdit )
+ {
+ ExtTextEngine* pTextEngine = pMulitLineEdit->GetTextEngine();
+ TextPaM aCursor( 0, nIndex );
+ TextSegment aResult;
+ pTextEngine->GetTextPortionRange( aCursor, aResult.SegmentStart, aResult.SegmentEnd );
+ return aResult;
+ }
+ }
+
+ return VCLXAccessibleTextComponent::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return VCLXAccessibleTextComponent::copyText( nStartIndex, nEndIndex );
+}
+
+sal_Bool VCLXAccessibleEdit::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleEditableText
+
+
+sal_Bool VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return copyText( nStartIndex, nEndIndex ) && deleteText( nStartIndex, nEndIndex );
+}
+
+
+sal_Bool VCLXAccessibleEdit::pasteText( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( GetWindow() )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow()->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ Reference< datatransfer::XTransferable > xDataObj;
+ {
+ SolarMutexReleaser aReleaser;
+ xDataObj = xClipboard->getContents();
+ }
+ if ( xDataObj.is() )
+ {
+ datatransfer::DataFlavor aFlavor;
+ SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
+ if ( xDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ Any aData = xDataObj->getTransferData( aFlavor );
+ OUString sText;
+ aData >>= sText;
+ bReturn = replaceText( nIndex, nIndex, sText );
+ }
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return replaceText( nStartIndex, nEndIndex, OUString() );
+}
+
+
+sal_Bool VCLXAccessibleEdit::insertText( const OUString& sText, sal_Int32 nIndex )
+{
+ return replaceText( nIndex, nIndex, sText );
+}
+
+
+sal_Bool VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nMinIndex = std::min( nStartIndex, nEndIndex );
+ sal_Int32 nMaxIndex = std::max( nStartIndex, nEndIndex );
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit && pVCLXEdit->isEditable() )
+ {
+ pVCLXEdit->setText( sText.replaceAt( nMinIndex, nMaxIndex - nMinIndex, sReplacement ) );
+ sal_Int32 nIndex = nMinIndex + sReplacement.getLength();
+ setSelection( nIndex, nIndex );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const Sequence<PropertyValue>& )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false; // attributes cannot be set for an edit
+}
+
+
+sal_Bool VCLXAccessibleEdit::setText( const OUString& sText )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit && pVCLXEdit->isEditable() )
+ {
+ pVCLXEdit->setText( sText );
+ sal_Int32 nSize = sText.getLength();
+ pVCLXEdit->setSelection( awt::Selection( nSize, nSize ) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx b/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx
new file mode 100644
index 000000000..9e2874365
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblefixedhyperlink.hxx>
+
+using namespace ::com::sun::star;
+
+// VCLXAccessibleFixedHyperlink
+
+// XServiceInfo
+
+OUString VCLXAccessibleFixedHyperlink::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleFixedHyperlink";
+}
+
+uno::Sequence<OUString> VCLXAccessibleFixedHyperlink::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleFixedHyperlink" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblefixedtext.cxx b/accessibility/source/standard/vclxaccessiblefixedtext.cxx
new file mode 100644
index 000000000..b62faded5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblefixedtext.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblefixedtext.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/window.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+// VCLXAccessibleFixedText
+
+void VCLXAccessibleFixedText::FillAccessibleStateSet(utl::AccessibleStateSetHelper& rStateSet)
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet(rStateSet);
+
+ if (GetWindow() && GetWindow()->GetStyle() & WB_WORDBREAK)
+ rStateSet.AddState(AccessibleStateType::MULTI_LINE);
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleFixedText::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleFixedText";
+}
+
+Sequence<OUString> VCLXAccessibleFixedText::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleFixedText" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleheaderbar.cxx b/accessibility/source/standard/vclxaccessibleheaderbar.cxx
new file mode 100644
index 000000000..de5208b35
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleheaderbar.cxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibleheaderbar.hxx>
+#include <standard/vclxaccessibleheaderbaritem.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <vcl/headbar.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+VCLXAccessibleHeaderBar::VCLXAccessibleHeaderBar(VCLXWindow* pVCLWindow)
+ : VCLXAccessibleComponent(pVCLWindow)
+{
+ m_pHeadBar = GetAs<HeaderBar>();
+}
+
+VCLXAccessibleHeaderBar::~VCLXAccessibleHeaderBar() {}
+
+// XServiceInfo
+
+OUString VCLXAccessibleHeaderBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleHeaderBar";
+}
+
+Sequence<OUString> VCLXAccessibleHeaderBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleHeaderBar" };
+}
+
+// =======XAccessibleContext=======
+
+sal_Int32 SAL_CALL VCLXAccessibleHeaderBar::getAccessibleChildCount()
+{
+ SolarMutexGuard g;
+
+ sal_Int32 nCount = 0;
+ if (m_pHeadBar)
+ nCount = m_pHeadBar->GetItemCount();
+
+ return nCount;
+}
+css::uno::Reference<css::accessibility::XAccessible>
+ SAL_CALL VCLXAccessibleHeaderBar::getAccessibleChild(sal_Int32 i)
+{
+ SolarMutexGuard g;
+
+ if (i < 0 || i >= getAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ Reference<XAccessible> xChild;
+ // search for the child
+ if (o3tl::make_unsigned(i) >= m_aAccessibleChildren.size())
+ xChild = CreateChild(i);
+ else
+ {
+ xChild = m_aAccessibleChildren[i];
+ if (!xChild.is())
+ xChild = CreateChild(i);
+ }
+ return xChild;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleHeaderBar::getAccessibleRole()
+{
+ return css::accessibility::AccessibleRole::LIST;
+}
+
+void SAL_CALL VCLXAccessibleHeaderBar::disposing()
+{
+ SolarMutexGuard g;
+
+ ListItems().swap(m_aAccessibleChildren);
+ VCLXAccessibleComponent::disposing();
+}
+
+css::uno::Reference<css::accessibility::XAccessible>
+VCLXAccessibleHeaderBar::CreateChild(sal_Int32 i)
+{
+ Reference<XAccessible> xChild;
+
+ sal_uInt16 nPos = static_cast<sal_uInt16>(i);
+ if (nPos >= m_aAccessibleChildren.size())
+ {
+ m_aAccessibleChildren.resize(nPos + 1);
+
+ // insert into the container
+ xChild = new VCLXAccessibleHeaderBarItem(m_pHeadBar, i);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ else
+ {
+ xChild = m_aAccessibleChildren[nPos];
+ // check if position is empty and can be used else we have to adjust all entries behind this
+ if (!xChild.is())
+ {
+ xChild = new VCLXAccessibleHeaderBarItem(m_pHeadBar, i);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ }
+ return xChild;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx b/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx
new file mode 100644
index 000000000..5c9bf5c9a
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <standard/vclxaccessibleheaderbaritem.hxx>
+
+#include <vcl/headbar.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleHeaderBarItem::VCLXAccessibleHeaderBarItem( HeaderBar* pHeadBar, sal_Int32 _nIndexInParent )
+ :m_pHeadBar( pHeadBar )
+ ,m_nIndexInParent(_nIndexInParent + 1)
+
+{
+}
+
+VCLXAccessibleHeaderBarItem::~VCLXAccessibleHeaderBarItem()
+{
+}
+
+void VCLXAccessibleHeaderBarItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ if ( m_pHeadBar )
+ {
+ if ( m_pHeadBar->IsEnabled() )
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+
+ if ( m_pHeadBar->IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ }
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+ rStateSet.AddState( AccessibleStateType::RESIZABLE );
+ }
+}
+
+// OCommonAccessibleComponent
+awt::Rectangle VCLXAccessibleHeaderBarItem::implGetBounds()
+{
+ awt::Rectangle aBounds;
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pHeadBar )
+ aBounds = AWTRectangle( m_pHeadBar->GetItemRect( sal_uInt16( m_nIndexInParent ) ) );
+
+ return aBounds;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleHeaderBarItem, OAccessibleExtendedComponentHelper, VCLXAccessibleHeaderBarItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleHeaderBarItem, OAccessibleExtendedComponentHelper, VCLXAccessibleHeaderBarItem_BASE )
+
+
+// XServiceInfo
+OUString VCLXAccessibleHeaderBarItem::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleHeaderBarItem";
+}
+
+sal_Bool VCLXAccessibleHeaderBarItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > VCLXAccessibleHeaderBarItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleHeaderBarItem" };
+}
+
+// XAccessible
+Reference< XAccessibleContext > VCLXAccessibleHeaderBarItem::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessible >();
+}
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleParent()
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pHeadBar )
+ {
+ xParent = m_pHeadBar->GetAccessible();
+ }
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getAccessibleIndexInParent()
+{
+ OExternalLockGuard aGuard( this );
+ return m_nIndexInParent - 1;
+}
+
+
+sal_Int16 VCLXAccessibleHeaderBarItem::getAccessibleRole()
+{
+ return AccessibleRole::COLUMN_HEADER;
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getAccessibleDescription()
+{
+ return OUString();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getAccessibleName()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sName;
+ if(m_pHeadBar)
+ sName = m_pHeadBar->GetItemText( sal_uInt16( m_nIndexInParent ) );
+ return sName;
+}
+
+
+Reference< XAccessibleRelationSet > VCLXAccessibleHeaderBarItem::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleHeaderBarItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+css::lang::Locale VCLXAccessibleHeaderBarItem::getLocale()
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getForeground()
+{
+ return 0;
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getBackground()
+{
+ return 0;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleHeaderBarItem::getFont()
+{
+ return Reference< awt::XFont >();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getTitledBorderText()
+{
+ return OUString();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getToolTipText()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText;
+ if ( m_pHeadBar )
+ sText = m_pHeadBar->GetQuickHelpText();
+
+ return sText;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelist.cxx b/accessibility/source/standard/vclxaccessiblelist.cxx
new file mode 100644
index 000000000..bb81350f5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelist.cxx
@@ -0,0 +1,942 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblelist.hxx>
+#include <standard/vclxaccessiblelistitem.hxx>
+#include <helper/listboxhelper.hxx>
+
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <toolkit/helper/convert.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::accessibility;
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkSelection_Impl( sal_Int32 _nIndex, const IComboListBoxHelper& _rListBox, bool bSelected )
+ {
+ sal_Int32 nCount = bSelected ? _rListBox.GetSelectedEntryCount()
+ : _rListBox.GetEntryCount();
+ if ( _nIndex < 0 || _nIndex >= nCount )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+VCLXAccessibleList::VCLXAccessibleList (VCLXWindow* pVCLWindow, BoxType aBoxType,
+ const Reference< XAccessible >& _xParent)
+ : VCLXAccessibleComponent (pVCLWindow),
+ m_aBoxType (aBoxType),
+ m_nVisibleLineCount (0),
+ m_nIndexInParent (DEFAULT_INDEX_IN_PARENT),
+ m_nLastTopEntry ( 0 ),
+ m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
+ m_bDisableProcessEvent ( false ),
+ m_bVisible ( true ),
+ m_nCurSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
+ m_xParent ( _xParent )
+{
+ // Because combo boxes and list boxes don't have a common interface for
+ // methods with identical signature we have to write down twice the
+ // same code.
+ switch (m_aBoxType)
+ {
+ case COMBOBOX:
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ m_pListBoxHelper.reset( new VCLListBoxHelper<ComboBox> (*pBox) );
+ break;
+ }
+
+ case LISTBOX:
+ {
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ m_pListBoxHelper.reset( new VCLListBoxHelper<ListBox> (*pBox) );
+ break;
+ }
+ }
+ UpdateVisibleLineCount();
+ if(m_pListBoxHelper)
+ {
+ m_nCurSelectedPos=m_pListBoxHelper->GetSelectedEntryPos(0);
+ }
+ sal_uInt16 nCount = static_cast<sal_uInt16>(getAccessibleChildCount());
+ m_aAccessibleChildren.reserve(nCount);
+}
+
+
+void VCLXAccessibleList::SetIndexInParent (sal_Int32 nIndex)
+{
+ m_nIndexInParent = nIndex;
+}
+
+
+void SAL_CALL VCLXAccessibleList::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ // Dispose all items in the list.
+ m_aAccessibleChildren.clear();
+
+ m_pListBoxHelper.reset();
+}
+
+
+void VCLXAccessibleList::FillAccessibleStateSet (utl::AccessibleStateSetHelper& rStateSet)
+{
+ SolarMutexGuard aSolarGuard;
+
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+ // check if our list should be visible
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN
+ && !m_pListBoxHelper->IsInDropDown() )
+ {
+ rStateSet.RemoveState (AccessibleStateType::VISIBLE);
+ rStateSet.RemoveState (AccessibleStateType::SHOWING);
+ m_bVisible = false;
+ }
+
+ // Both the combo box and list box are handled identical in the
+ // following but for some reason they don't have a common interface for
+ // the methods used.
+ if ( m_pListBoxHelper )
+ {
+ if ( m_pListBoxHelper->IsMultiSelectionEnabled() )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
+ rStateSet.AddState (AccessibleStateType::FOCUSABLE);
+ // All children are transient.
+ rStateSet.AddState (AccessibleStateType::MANAGES_DESCENDANTS);
+ }
+}
+
+void VCLXAccessibleList::notifyVisibleStates(bool _bSetNew )
+{
+ m_bVisible = _bSetNew;
+ Any aOldValue, aNewValue;
+ (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+
+ ListItems::iterator aIter = m_aAccessibleChildren.begin();
+ UpdateVisibleLineCount();
+ // adjust the index inside the VCLXAccessibleListItem
+ for ( ; aIter != m_aAccessibleChildren.end(); )
+ {
+ Reference< XAccessible > xHold = *aIter;
+ if (!xHold.is())
+ {
+ aIter = m_aAccessibleChildren.erase(aIter);
+ }
+ else
+ {
+ VCLXAccessibleListItem* pItem = static_cast<VCLXAccessibleListItem*>(xHold.get());
+ const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
+ const sal_Int32 nPos = static_cast<sal_Int32>(aIter - m_aAccessibleChildren.begin());
+ bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
+ pItem->SetVisible( m_bVisible && bVisible );
+ ++aIter;
+ }
+
+ }
+}
+
+void VCLXAccessibleList::UpdateSelection_Acc (std::u16string_view /*sTextOfSelectedItem*/, bool b_IsDropDownList)
+{
+ if ( m_aBoxType != COMBOBOX )
+ return;
+
+ /* FIXME: is there something missing here? nIndex is unused. Looks like
+ * copy-paste from VCLXAccessibleList::UpdateSelection() */
+ // VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ // if ( pBox )
+ // {
+ // // Find the index of the selected item inside the VCL control...
+ // sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
+ // // ...and then find the associated accessibility object.
+ // if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
+ // nIndex = 0;
+ UpdateSelection_Impl_Acc(b_IsDropDownList);
+ // }
+}
+
+
+void VCLXAccessibleList::UpdateSelection_Impl_Acc(bool bHasDropDownList)
+{
+ uno::Any aOldValue, aNewValue;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ Reference< XAccessible > xNewAcc;
+ if ( m_pListBoxHelper )
+ {
+ sal_Int32 i=0;
+ m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
+ for ( const auto& rChild : m_aAccessibleChildren )
+ {
+ Reference< XAccessible > xHold = rChild;
+ if ( xHold.is() )
+ {
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( xHold.get() );
+ // Retrieve the item's index from the list entry.
+ bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
+ if (bNowSelected)
+ m_nCurSelectedPos = i;
+
+ if ( bNowSelected && !pItem->IsSelected() )
+ {
+ xNewAcc = rChild;
+ aNewValue <<= xNewAcc;
+ }
+ else if ( pItem->IsSelected() )
+ m_nLastSelectedPos = i;
+
+ pItem->SetSelected( bNowSelected );
+ }
+ else
+ { // it could happen that a child was not created before
+ checkEntrySelected(i,aNewValue,xNewAcc);
+ }
+ ++i;
+ }
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ if ( i < nCount ) // here we have to check the if any other listbox entry is selected
+ {
+ for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
+ ;
+ }
+ if ( xNewAcc.is() && GetWindow()->HasFocus() )
+ {
+ if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
+ aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
+ aNewValue <<= xNewAcc;
+ }
+ }
+ }
+
+ if (m_aBoxType == COMBOBOX)
+ {
+ //VCLXAccessibleDropDownComboBox
+ //when in list is dropped down, xText = NULL
+ if (bHasDropDownList && m_pListBoxHelper && m_pListBoxHelper->IsInDropDown())
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ {
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+
+ NotifyListItem(aNewValue);
+ }
+ }
+ else
+ {
+ //VCLXAccessibleComboBox
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, uno::Any(), uno::Any() );
+ }
+ }
+ else if (m_aBoxType == LISTBOX)
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ {
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+
+ NotifyListItem(aNewValue);
+ }
+ }
+}
+
+void VCLXAccessibleList::NotifyListItem(css::uno::Any const & val)
+{
+ Reference< XAccessible > xCurItem;
+ val >>= xCurItem;
+ if (xCurItem.is())
+ {
+ VCLXAccessibleListItem* pCurItem = static_cast< VCLXAccessibleListItem* >(xCurItem.get());
+ if (pCurItem)
+ {
+ pCurItem->NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED,Any(),Any());
+ }
+ }
+}
+
+void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent, bool b_IsDropDownList)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownSelect:
+ case VclEventId::ListboxSelect:
+ if ( !m_bDisableProcessEvent )
+ UpdateSelection_Impl_Acc(b_IsDropDownList);
+ break;
+ case VclEventId::WindowGetFocus:
+ break;
+ case VclEventId::ControlGetFocus:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ if (m_aBoxType == COMBOBOX && b_IsDropDownList)
+ {
+ //VCLXAccessibleDropDownComboBox
+ }
+ else if (m_aBoxType == LISTBOX && b_IsDropDownList)
+ {
+ }
+ else if ( m_aBoxType == LISTBOX && !b_IsDropDownList)
+ {
+ if ( m_pListBoxHelper )
+ {
+ uno::Any aOldValue,
+ aNewValue;
+ sal_Int32 nPos = m_nCurSelectedPos; //m_pListBoxHelper->GetSelectedEntryPos();
+
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = m_pListBoxHelper->GetTopEntry();
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ aNewValue <<= CreateChild(nPos);
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ // Create a reference to this object to prevent an early release of the
+ // listbox (VclEventId::ObjectDying).
+ Reference< XAccessible > xHoldAlive = this;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownOpen:
+ notifyVisibleStates(true);
+ break;
+ case VclEventId::DropdownClose:
+ notifyVisibleStates(false);
+ break;
+ case VclEventId::ListboxScrolled:
+ UpdateEntryRange_Impl();
+ break;
+
+ // The selection events VclEventId::ComboboxSelect and
+ // VclEventId::ComboboxDeselect are not handled here because here we
+ // have no access to the edit field. Its text is necessary to
+ // identify the currently selected item.
+
+ case VclEventId::ObjectDying:
+ {
+ dispose();
+
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ break;
+ }
+
+ case VclEventId::ListboxItemRemoved:
+ case VclEventId::ComboboxItemRemoved:
+ case VclEventId::ListboxItemAdded:
+ case VclEventId::ComboboxItemAdded:
+ HandleChangedItemList();
+ break;
+ case VclEventId::ControlGetFocus:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ // Added by IBM Symphony Acc team to handle the list item focus when List control get focus
+ bool b_IsDropDownList = true;
+ if (m_pListBoxHelper)
+ b_IsDropDownList = ((m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN);
+ if ( m_aBoxType == LISTBOX && !b_IsDropDownList )
+ {
+ if ( m_pListBoxHelper )
+ {
+ uno::Any aOldValue,
+ aNewValue;
+ sal_Int32 nPos = m_nCurSelectedPos;
+
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = m_pListBoxHelper->GetTopEntry();
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ aNewValue <<= CreateChild(nPos);
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ }
+ }
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ }
+}
+
+ void VCLXAccessibleList::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if( m_aBoxType == LISTBOX )
+ {
+ if (m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) != WB_DROPDOWN)
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pBox->GetAccessible() };
+ rRelationSet.AddRelation( com::sun::star::accessibility::AccessibleRelation( com::sun::star::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
+ }
+ }
+ else
+ {
+ VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
+ }
+}
+
+
+/** To find out which item is currently selected and to update the SELECTED
+ state of the associated accessibility objects accordingly we exploit the
+ fact that the
+*/
+void VCLXAccessibleList::UpdateSelection (std::u16string_view sTextOfSelectedItem)
+{
+ if ( m_aBoxType != COMBOBOX )
+ return;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ // Find the index of the selected item inside the VCL control...
+ sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
+ // ...and then find the associated accessibility object.
+ if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
+ nIndex = 0;
+ UpdateSelection_Impl(nIndex);
+ }
+}
+
+
+Reference<XAccessible> VCLXAccessibleList::CreateChild (sal_Int32 nPos)
+{
+ Reference<XAccessible> xChild;
+
+ if ( o3tl::make_unsigned(nPos) >= m_aAccessibleChildren.size() )
+ {
+ m_aAccessibleChildren.resize(nPos + 1);
+
+ // insert into the container
+ xChild = new VCLXAccessibleListItem(nPos, this);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ else
+ {
+ xChild = m_aAccessibleChildren[nPos];
+ // check if position is empty and can be used else we have to adjust all entries behind this
+ if (!xChild.is())
+ {
+ xChild = new VCLXAccessibleListItem(nPos, this);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ }
+
+ if ( xChild.is() )
+ {
+ // Just add the SELECTED state.
+ bool bNowSelected = false;
+ if ( m_pListBoxHelper )
+ bNowSelected = m_pListBoxHelper->IsEntryPosSelected(nPos);
+ if (bNowSelected)
+ m_nCurSelectedPos = nPos;
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >(xChild.get());
+ pItem->SetSelected( bNowSelected );
+
+ // Set the child's VISIBLE state.
+ UpdateVisibleLineCount();
+ const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
+ bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
+ pItem->SetVisible( m_bVisible && bVisible );
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleList::HandleChangedItemList()
+{
+ m_aAccessibleChildren.clear();
+ NotifyAccessibleEvent (
+ AccessibleEventId::INVALIDATE_ALL_CHILDREN,
+ Any(), Any());
+}
+
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE)
+
+// XAccessible
+
+Reference<XAccessibleContext> SAL_CALL
+ VCLXAccessibleList::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleList::implGetAccessibleChildCount()
+{
+ sal_Int32 nCount = 0;
+ if ( m_pListBoxHelper )
+ nCount = m_pListBoxHelper->GetEntryCount();
+
+ return nCount;
+}
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleList::getAccessibleChild (sal_Int32 i)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ // search for the child
+ if ( o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ xChild = CreateChild (i);
+ else
+ {
+ xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ xChild = CreateChild (i);
+ }
+ OSL_ENSURE( xChild.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
+ return xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleList::getAccessibleParent( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return m_xParent;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleIndexInParent()
+{
+ if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
+ return m_nIndexInParent;
+ else
+ return VCLXAccessibleComponent::getAccessibleIndexInParent();
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleList::getAccessibleRole()
+{
+ return AccessibleRole::LIST;
+}
+
+// XServiceInfo
+OUString VCLXAccessibleList::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleList";
+}
+
+Sequence< OUString > VCLXAccessibleList::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleList"});
+}
+
+void VCLXAccessibleList::UpdateVisibleLineCount()
+{
+ if ( m_pListBoxHelper )
+ {
+ if ( (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ m_nVisibleLineCount = m_pListBoxHelper->GetDisplayLineCount();
+ else
+ {
+ sal_uInt16 nCols = 0,
+ nLines = 0;
+ m_pListBoxHelper->GetMaxVisColumnsAndLines (nCols, nLines);
+ m_nVisibleLineCount = nLines;
+ }
+ }
+}
+
+void VCLXAccessibleList::UpdateEntryRange_Impl()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_Int32 nTop = m_nLastTopEntry;
+
+ if ( m_pListBoxHelper )
+ nTop = m_pListBoxHelper->GetTopEntry();
+ if ( nTop != m_nLastTopEntry )
+ {
+ UpdateVisibleLineCount();
+ sal_Int32 nBegin = std::min( m_nLastTopEntry, nTop );
+ sal_Int32 nEnd = std::max( m_nLastTopEntry + m_nVisibleLineCount, nTop + m_nVisibleLineCount );
+ for (sal_Int32 i = nBegin; (i <= nEnd); ++i)
+ {
+ bool bVisible = ( i >= nTop && i < ( nTop + m_nVisibleLineCount ) );
+ Reference< XAccessible > xHold;
+ if ( o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ xHold = m_aAccessibleChildren[i];
+ else if ( bVisible )
+ xHold = CreateChild(i);
+
+ if ( xHold.is() )
+ static_cast< VCLXAccessibleListItem* >( xHold.get() )->SetVisible( m_bVisible && bVisible );
+ }
+ }
+
+ m_nLastTopEntry = nTop;
+}
+
+bool VCLXAccessibleList::checkEntrySelected(sal_Int32 _nPos,Any& _rNewValue,Reference< XAccessible >& _rxNewAcc)
+{
+ OSL_ENSURE(m_pListBoxHelper,"Helper is not valid!");
+ bool bNowSelected = false;
+ if ( m_pListBoxHelper )
+ {
+ bNowSelected = m_pListBoxHelper->IsEntryPosSelected (_nPos);
+ if ( bNowSelected )
+ {
+ _rxNewAcc = CreateChild(_nPos);
+ _rNewValue <<= _rxNewAcc;
+ }
+ }
+ return bNowSelected;
+}
+
+
+void VCLXAccessibleList::UpdateSelection_Impl(sal_Int32)
+{
+ uno::Any aOldValue, aNewValue;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ Reference< XAccessible > xNewAcc;
+
+ if ( m_pListBoxHelper )
+ {
+ sal_Int32 i=0;
+ m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
+ for ( const auto& rChild : m_aAccessibleChildren )
+ {
+ Reference< XAccessible > xHold = rChild;
+ if ( xHold.is() )
+ {
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( xHold.get() );
+ // Retrieve the item's index from the list entry.
+ bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
+ if (bNowSelected)
+ m_nCurSelectedPos = i;
+
+ if ( bNowSelected && !pItem->IsSelected() )
+ {
+ xNewAcc = rChild;
+ aNewValue <<= xNewAcc;
+ }
+ else if ( pItem->IsSelected() )
+ m_nLastSelectedPos = i;
+
+ pItem->SetSelected( bNowSelected );
+ }
+ else
+ { // it could happen that a child was not created before
+ checkEntrySelected(i,aNewValue,xNewAcc);
+ }
+ ++i;
+ }
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ if ( i < nCount ) // here we have to check the if any other listbox entry is selected
+ {
+ for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
+ ;
+ }
+ if ( xNewAcc.is() && GetWindow()->HasFocus() )
+ {
+ if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
+ aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
+ aNewValue <<= xNewAcc;
+ }
+ if (m_pListBoxHelper->IsInDropDown())
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ //the SELECTION_CHANGED is not necessary
+ //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ }
+}
+
+
+// XAccessibleSelection
+
+void SAL_CALL VCLXAccessibleList::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
+
+ m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nChildIndex) );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+sal_Bool SAL_CALL VCLXAccessibleList::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ bool bRet = false;
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
+
+ bRet = m_pListBoxHelper->IsEntryPosSelected( static_cast<sal_uInt16>(nChildIndex) );
+ }
+ return bRet;
+}
+
+void SAL_CALL VCLXAccessibleList::clearAccessibleSelection( )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ m_pListBoxHelper->SetNoSelection();
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+void SAL_CALL VCLXAccessibleList::selectAllAccessibleChildren( )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ m_pListBoxHelper->SelectEntryPos( i );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getSelectedAccessibleChildCount( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_Int32 nCount = 0;
+ if ( m_pListBoxHelper )
+ nCount = m_pListBoxHelper->GetSelectedEntryCount();
+ return nCount;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleList::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,true);
+ return getAccessibleChild( m_pListBoxHelper->GetSelectedEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex) ) );
+ }
+
+ return nullptr;
+}
+
+void SAL_CALL VCLXAccessibleList::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,false);
+
+ m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex), false );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+awt::Rectangle VCLXAccessibleList::implGetBounds()
+{
+ awt::Rectangle aBounds ( 0, 0, 0, 0 );
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ {
+ if ( m_pListBoxHelper->IsInDropDown() )
+ aBounds = AWTRectangle(m_pListBoxHelper->GetDropDownPosSizePixel());
+ }
+ else
+ {
+ // a list has the same bounds as his parent but starts at (0,0)
+ aBounds = VCLXAccessibleComponent::implGetBounds();
+ aBounds.X = 0;
+ aBounds.Y = 0;
+ if ( m_aBoxType == COMBOBOX )
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ Size aSize = pBox->GetSubEdit()->GetSizePixel();
+ aBounds.Y += aSize.Height();
+ aBounds.Height -= aSize.Height();
+ }
+ }
+ }
+ return aBounds;
+}
+
+
+awt::Point VCLXAccessibleList::getLocationOnScreen( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ awt::Point aPos;
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ {
+ if ( m_pListBoxHelper->IsInDropDown() )
+ aPos = AWTPoint(m_pListBoxHelper->GetDropDownPosSizePixel().TopLeft());
+ }
+ else
+ {
+ aPos = VCLXAccessibleComponent::getLocationOnScreen();
+ if ( m_aBoxType == COMBOBOX )
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ aPos.Y += pBox->GetSubEdit()->GetSizePixel().Height();
+ }
+ }
+ }
+ return aPos;
+}
+
+
+bool VCLXAccessibleList::IsInDropDown() const
+{
+ return m_pListBoxHelper->IsInDropDown();
+}
+
+
+void VCLXAccessibleList::HandleDropOpen()
+{
+ if ( !m_bDisableProcessEvent )
+ UpdateSelection_Impl();
+ if (m_nCurSelectedPos != LISTBOX_ENTRY_NOTFOUND &&
+ m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND)
+ {
+ Reference< XAccessible > xChild = getAccessibleChild(m_nCurSelectedPos);
+ if(xChild.is())
+ {
+ uno::Any aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, uno::Any(), aNewValue );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelistbox.cxx b/accessibility/source/standard/vclxaccessiblelistbox.cxx
new file mode 100644
index 000000000..4b5ed9377
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelistbox.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblelistbox.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+VCLXAccessibleListBox::VCLXAccessibleListBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::LISTBOX, false)
+{
+}
+
+
+bool VCLXAccessibleListBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleListBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleListBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleListBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleListBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelistitem.cxx b/accessibility/source/standard/vclxaccessiblelistitem.cxx
new file mode 100644
index 000000000..81a5cd1a2
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelistitem.cxx
@@ -0,0 +1,617 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblelistitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/IComboListBoxHelper.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/settings.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkIndex_Impl( sal_Int32 _nIndex, const OUString& _sText )
+ {
+ if ( _nIndex < 0 || _nIndex > _sText.getLength() )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+// class VCLXAccessibleListItem ------------------------------------------
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+
+
+// Ctor() and Dtor()
+
+VCLXAccessibleListItem::VCLXAccessibleListItem(sal_Int32 _nIndexInParent, rtl::Reference< VCLXAccessibleList > _xParent)
+ : VCLXAccessibleListItem_BASE(m_aMutex)
+ , m_nIndexInParent(_nIndexInParent)
+ , m_bSelected(false)
+ , m_bVisible(false)
+ , m_nClientId(0)
+ , m_xParent(std::move(_xParent))
+{
+ assert(m_xParent.is());
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent->getListBoxHelper();
+ if (pListBoxHelper)
+ m_sEntryText = pListBoxHelper->GetEntry(static_cast<sal_uInt16>(_nIndexInParent));
+}
+
+void VCLXAccessibleListItem::SetSelected( bool _bSelected )
+{
+ if ( m_bSelected != _bSelected )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = _bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleListItem::SetVisible( bool _bVisible )
+{
+ if ( m_bVisible != _bVisible )
+ {
+ Any aOldValue, aNewValue;
+ m_bVisible = _bVisible;
+ (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleListItem::NotifyAccessibleEvent( sal_Int16 _nEventId,
+ const css::uno::Any& _aOldValue,
+ const css::uno::Any& _aNewValue )
+{
+ AccessibleEventObject aEvt;
+ aEvt.Source = *this;
+ aEvt.EventId = _nEventId;
+ aEvt.OldValue = _aOldValue;
+ aEvt.NewValue = _aNewValue;
+
+ if (m_nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEvt );
+}
+
+// OCommonAccessibleText
+
+OUString VCLXAccessibleListItem::implGetText()
+{
+ return m_sEntryText;
+}
+
+Locale VCLXAccessibleListItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+void VCLXAccessibleListItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+// XTypeProvider
+
+Sequence< sal_Int8 > VCLXAccessibleListItem::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XComponent
+
+void SAL_CALL VCLXAccessibleListItem::disposing()
+{
+ comphelper::AccessibleEventNotifier::TClientId nId( 0 );
+ Reference< XInterface > xEventSource;
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ VCLXAccessibleListItem_BASE::disposing();
+ m_sEntryText.clear();
+ m_xParent = nullptr;
+
+ nId = m_nClientId;
+ m_nClientId = 0;
+ if ( nId )
+ xEventSource = *this;
+ }
+
+ // Send a disposing to all listeners.
+ if ( nId )
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleListItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleListItem";
+}
+
+sal_Bool VCLXAccessibleListItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > VCLXAccessibleListItem::getSupportedServiceNames()
+{
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.accessibility.AccessibleListItem"};
+}
+
+// XAccessible
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleListItem::getAccessibleContext( )
+{
+ return this;
+}
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getAccessibleChildCount( )
+{
+ return 0;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleChild( sal_Int32 )
+{
+ return Reference< XAccessible >();
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleParent( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_xParent;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getAccessibleIndexInParent( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_nIndexInParent;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleListItem::getAccessibleRole( )
+{
+ return AccessibleRole::LIST_ITEM;
+ // return AccessibleRole::LABEL;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getAccessibleDescription( )
+{
+ // no description for every item
+ return OUString();
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getAccessibleName( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // entry text == accessible name
+ return m_sEntryText;
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL VCLXAccessibleListItem::getAccessibleRelationSet( )
+{
+ return new utl::AccessibleRelationSetHelper;
+}
+
+Reference< XAccessibleStateSet > SAL_CALL VCLXAccessibleListItem::getAccessibleStateSet( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper && pListBoxHelper->IsEnabled())
+ {
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ if ( m_bSelected )
+ pStateSetHelper->AddState( AccessibleStateType::SELECTED );
+ if ( m_bVisible )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ }
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+Locale SAL_CALL VCLXAccessibleListItem::getLocale( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return implGetLocale();
+}
+
+// XAccessibleComponent
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::containsPoint( const awt::Point& _aPoint )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bInside = false;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect(pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent)));
+ aRect.Move(-aRect.Left(), -aRect.Top());
+ bInside = aRect.Contains( VCLPoint( _aPoint ) );
+ }
+ return bInside;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleListItem::getBounds( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ awt::Rectangle aRect;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ aRect = AWTRectangle(pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent)));
+
+ return aRect;
+}
+
+awt::Point SAL_CALL VCLXAccessibleListItem::getLocation( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Point aPoint(0,0);
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ aPoint = aRect.TopLeft();
+ }
+ return AWTPoint( aPoint );
+}
+
+awt::Point SAL_CALL VCLXAccessibleListItem::getLocationOnScreen( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Point aPoint(0,0);
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect = pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent));
+ aPoint = aRect.TopLeft();
+ aPoint += pListBoxHelper->GetWindowExtentsRelative().TopLeft();
+ }
+ return AWTPoint( aPoint );
+}
+
+awt::Size SAL_CALL VCLXAccessibleListItem::getSize( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Size aSize;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ aSize = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) ).GetSize();
+
+ return AWTSize( aSize );
+}
+
+void SAL_CALL VCLXAccessibleListItem::grabFocus( )
+{
+ // no focus for each item
+}
+
+// XAccessibleText
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getCaretPosition()
+{
+ return -1;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::setCaretPosition( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidRange( nIndex, nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+sal_Unicode SAL_CALL VCLXAccessibleListItem::getCharacter( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::implGetCharacter( m_sEntryText, nIndex );
+}
+
+Sequence< PropertyValue > SAL_CALL VCLXAccessibleListItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return Sequence< PropertyValue >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleListItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aCharRect = pListBoxHelper->GetEntryCharacterBounds( m_nIndexInParent, nIndex );
+ tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getCharacterCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_sEntryText.getLength();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nIndex = -1;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
+ tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nI = pListBoxHelper->GetIndexForPoint( aPnt, nPos );
+ if ( nI != -1 && m_nIndexInParent == nPos )
+ nIndex = nI;
+ }
+ return nIndex;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getSelectedText()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OUString();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionStart()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return 0;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionEnd()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return 0;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getText()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_sEntryText;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::implGetTextRange( m_sEntryText, nStartIndex, nEndIndex );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ checkIndex_Impl( nStartIndex, m_sEntryText );
+ checkIndex_Impl( nEndIndex, m_sEntryText );
+
+ bool bRet = false;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pListBoxHelper->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( getTextRange( nStartIndex, nEndIndex ) );
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool VCLXAccessibleListItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleEventBroadcaster
+
+void SAL_CALL VCLXAccessibleListItem::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ if (xListener.is())
+ {
+ if (!m_nClientId)
+ m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
+ }
+}
+
+void SAL_CALL VCLXAccessibleListItem::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ if ( !(xListener.is() && m_nClientId) )
+ return;
+
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
+ if ( nListenerCount )
+ return;
+
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ if ( m_nClientId )
+ {
+ comphelper::AccessibleEventNotifier::TClientId nId( m_nClientId );
+ m_nClientId = 0;
+ comphelper::AccessibleEventNotifier::revokeClient( nId );
+ }
+}
+
+
+// AF (Oct. 29 2002): Return black as constant foreground color. This is an
+// initial implementation and has to be substituted by code that determines
+// the color that is actually used.
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getForeground()
+{
+ return sal_Int32(COL_BLACK);
+}
+
+// AF (Oct. 29 2002): Return white as constant background color. This is an
+// initial implementation and has to be substituted by code that determines
+// the color that is actually used.
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getBackground()
+{
+ return sal_Int32(COL_WHITE);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenu.cxx b/accessibility/source/standard/vclxaccessiblemenu.cxx
new file mode 100644
index 000000000..a7e31094b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenu.cxx
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblemenu.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/menu.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleMenu
+
+
+bool VCLXAccessibleMenu::IsFocused()
+{
+ bool bFocused = false;
+
+ if ( IsHighlighted() && !IsChildHighlighted() )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+bool VCLXAccessibleMenu::IsPopupMenuOpen()
+{
+ bool bPopupMenuOpen = false;
+
+ if ( m_pParent )
+ {
+ PopupMenu* pPopupMenu = m_pParent->GetPopupMenu( m_pParent->GetItemId( m_nItemPos ) );
+ if ( pPopupMenu && pPopupMenu->IsMenuVisible() )
+ bPopupMenuOpen = true;
+ }
+
+ return bPopupMenuOpen;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenu, VCLXAccessibleMenuItem, VCLXAccessibleMenu_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenu, VCLXAccessibleMenuItem, VCLXAccessibleMenu_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenu::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenu";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenu::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenu" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleMenu::getAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildCount();
+}
+
+
+Reference< XAccessible > VCLXAccessibleMenu::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return GetChild( i );
+}
+
+
+sal_Int16 VCLXAccessibleMenu::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::MENU;
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleMenu::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildAt( rPoint );
+}
+
+
+// XAccessibleSelection
+
+
+void VCLXAccessibleMenu::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ SelectChild( nChildIndex );
+}
+
+
+sal_Bool VCLXAccessibleMenu::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+
+void VCLXAccessibleMenu::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+
+ DeSelectAll();
+}
+
+
+void VCLXAccessibleMenu::selectAllAccessibleChildren( )
+{
+ // This method makes no sense in a menu, and so does nothing.
+}
+
+
+sal_Int32 VCLXAccessibleMenu::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetSelectedAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleMenu::implGetSelectedAccessibleChildCount( )
+{
+ sal_Int32 nRet = 0;
+
+ for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+Reference< XAccessible > VCLXAccessibleMenu::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
+ {
+ xChild = GetChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleMenu::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ DeSelectAll();
+}
+
+
+OUString VCLXAccessibleMenu::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
+ throw IndexOutOfBoundsException();
+
+ return OUString( );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenubar.cxx b/accessibility/source/standard/vclxaccessiblemenubar.cxx
new file mode 100644
index 000000000..27a02607b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenubar.cxx
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblemenubar.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleMenuBar::VCLXAccessibleMenuBar( Menu* pMenu )
+ :OAccessibleMenuComponent( pMenu )
+{
+ if ( pMenu )
+ {
+ m_pWindow = pMenu->GetWindow();
+
+ if ( m_pWindow )
+ m_pWindow->AddEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ }
+}
+
+
+VCLXAccessibleMenuBar::~VCLXAccessibleMenuBar()
+{
+ if ( m_pWindow )
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+}
+
+
+bool VCLXAccessibleMenuBar::IsFocused()
+{
+ bool bFocused = false;
+
+ if ( m_pWindow && m_pWindow->HasFocus() && !IsChildHighlighted() )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+IMPL_LINK( VCLXAccessibleMenuBar, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetWindow(), "VCLXAccessibleMenuBar::WindowEventListener: no window!" );
+ if ( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
+ {
+ ProcessWindowEvent( rEvent );
+ }
+}
+
+
+void VCLXAccessibleMenuBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowGetFocus:
+ case VclEventId::WindowLoseFocus:
+ {
+ SetFocused( rVclWindowEvent.GetId() == VclEventId::WindowGetFocus );
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pWindow )
+ {
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ m_pWindow = nullptr;
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleMenuBar::disposing()
+{
+ OAccessibleMenuComponent::disposing();
+
+ if ( m_pWindow )
+ {
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ m_pWindow = nullptr;
+ }
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenuBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenuBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuBar" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleMenuBar::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
+ if ( pParent )
+ {
+ for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; )
+ {
+ vcl::Window* pChild = pParent->GetAccessibleChildWindow( --n );
+ if ( pChild == pWindow )
+ {
+ nIndexInParent = n;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return nIndexInParent;
+}
+
+
+sal_Int16 VCLXAccessibleMenuBar::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::MENU_BAR;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+sal_Int32 VCLXAccessibleMenuBar::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return sal_Int32(Application::GetSettings().GetStyleSettings().GetMenuBarColor());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenuitem.cxx b/accessibility/source/standard/vclxaccessiblemenuitem.cxx
new file mode 100644
index 000000000..96e31c007
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenuitem.cxx
@@ -0,0 +1,579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblemenuitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/settings.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
+ :OAccessibleMenuItemComponent( pParent, nItemPos, pMenu )
+{
+}
+
+
+bool VCLXAccessibleMenuItem::IsFocused()
+{
+ return IsHighlighted();
+}
+
+
+bool VCLXAccessibleMenuItem::IsSelected()
+{
+ return IsHighlighted();
+}
+
+
+bool VCLXAccessibleMenuItem::IsChecked()
+{
+ bool bChecked = false;
+
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ if ( m_pParent->IsItemChecked( nItemId ) )
+ bChecked = true;
+ }
+
+ return bChecked;
+}
+
+
+bool VCLXAccessibleMenuItem::IsHighlighted()
+{
+ bool bHighlighted = false;
+
+ if ( m_pParent && m_pParent->IsHighlighted( m_nItemPos ) )
+ bHighlighted = true;
+
+ return bHighlighted;
+}
+
+
+void VCLXAccessibleMenuItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ if ( IsSelected() )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+
+ if ( IsChecked() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleMenuItem::implGetText()
+{
+ return m_sItemText;
+}
+
+
+Locale VCLXAccessibleMenuItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleMenuItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenuItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuItem";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenuItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuItem" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int16 VCLXAccessibleMenuItem::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+ // IA2 CWS. MT: We had the additional roles in UAA for ever, but never used them anywhere.
+ // Looks reasonable, but need to verify in Orca and VoiceOver.
+ sal_Int16 nRole = AccessibleRole::MENU_ITEM;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ MenuItemBits nItemBits = m_pParent->GetItemBits(nItemId);
+ if( nItemBits & MenuItemBits::RADIOCHECK)
+ nRole = AccessibleRole::RADIO_MENU_ITEM;
+ else if( nItemBits & MenuItemBits::CHECKABLE)
+ nRole = AccessibleRole::CHECK_MENU_ITEM;
+ }
+ return nRole;
+}
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleMenuItem::getCaretPosition()
+{
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex )
+{
+
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Unicode VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ vcl::Font aFont = Application::GetSettings().GetStyleSettings().GetMenuFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ return CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+}
+
+
+awt::Rectangle VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ tools::Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos );
+ tools::Rectangle aCharRect = m_pParent->GetCharacterBounds( nItemId, nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sItemText.getLength();
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = 0;
+ tools::Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nI = m_pParent->GetIndexForPoint( aPnt, nItemId );
+ if ( nI != -1 && m_pParent->GetItemId( m_nItemPos ) == nItemId )
+ nIndex = nI;
+ }
+
+ return nIndex;
+}
+
+
+OUString VCLXAccessibleMenuItem::getSelectedText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getSelectionStart()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getSelectionEnd()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+OUString VCLXAccessibleMenuItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sItemText;
+}
+
+
+OUString VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pParent )
+ {
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( getTextRange( nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleMenuItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleMenuItem::getAccessibleActionCount( )
+{
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Click();
+
+ return true;
+}
+
+
+OUString VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_SELECT;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ if ( m_pParent )
+ {
+ // create auto mnemonics
+ if (!(m_pParent->GetMenuFlags() & MenuFlags::NoAutoMnemonics))
+ m_pParent->CreateAutoMnemonics();
+
+ // activation key
+ KeyEvent aKeyEvent = m_pParent->GetActivationKey( m_pParent->GetItemId( m_nItemPos ) );
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ Sequence< awt::KeyStroke > aSeq1
+ {
+ {
+ 0, // Modifiers
+ static_cast< sal_Int16 >(aKeyCode.GetCode()),
+ aKeyEvent.GetCharCode(),
+ static_cast< sal_Int16 >( aKeyCode.GetFunction())
+ }
+ };
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU_BAR )
+ aSeq1.getArray()[0].Modifiers |= awt::KeyModifier::MOD2;
+ }
+ pKeyBindingHelper->AddKeyBinding( aSeq1 );
+
+ // complete menu activation key sequence
+ Sequence< awt::KeyStroke > aSeq;
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU )
+ {
+ Reference< XAccessibleAction > xAction( xParentContext, UNO_QUERY );
+ if ( xAction.is() && xAction->getAccessibleActionCount() > 0 )
+ {
+ Reference< XAccessibleKeyBinding > xKeyB( xAction->getAccessibleActionKeyBinding( 0 ) );
+ if ( xKeyB.is() && xKeyB->getAccessibleKeyBindingCount() > 1 )
+ aSeq = xKeyB->getAccessibleKeyBinding( 1 );
+ }
+ }
+ }
+ Sequence< awt::KeyStroke > aSeq2 = ::comphelper::concatSequences( aSeq, aSeq1 );
+ pKeyBindingHelper->AddKeyBinding( aSeq2 );
+
+ // accelerator key
+ vcl::KeyCode aAccelKeyCode = m_pParent->GetAccelKey( m_pParent->GetItemId( m_nItemPos ) );
+ if ( aAccelKeyCode.GetCode() != 0 )
+ {
+ Sequence< awt::KeyStroke > aSeq3
+ {
+ {
+ 0, // Modifiers
+ static_cast< sal_Int16 >(aAccelKeyCode.GetCode()),
+ aKeyEvent.GetCharCode(),
+ static_cast< sal_Int16 >(aAccelKeyCode.GetFunction())
+ }
+ };
+ if (aAccelKeyCode.GetModifier() != 0)
+ {
+ auto pSeq3 = aSeq3.getArray();
+ if ( aAccelKeyCode.IsShift() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aAccelKeyCode.IsMod1() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD1;
+ if ( aAccelKeyCode.IsMod2() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD2;
+ if ( aAccelKeyCode.IsMod3() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD3;
+ }
+ pKeyBindingHelper->AddKeyBinding( aSeq3 );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleMenuItem::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ if ( IsSelected() )
+ aValue <<= sal_Int32(1);
+ else
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue <= 0 )
+ {
+ DeSelect();
+ bReturn = true;
+ }
+ else if ( nValue >= 1 )
+ {
+ Select();
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleMenuItem::getMaximumValue( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleMenuItem::getMinimumValue( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleMenuItem::getMinimumIncrement( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenuseparator.cxx b/accessibility/source/standard/vclxaccessiblemenuseparator.cxx
new file mode 100644
index 000000000..50a70df01
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenuseparator.cxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblemenuseparator.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+VCLXAccessibleMenuSeparator::VCLXAccessibleMenuSeparator(Menu* pParent, sal_uInt16 nItemPos)
+ : OAccessibleMenuItemComponent(pParent, nItemPos, nullptr)
+{
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleMenuSeparator::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuSeparator";
+}
+
+Sequence<OUString> VCLXAccessibleMenuSeparator::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuSeparator" };
+}
+
+// XAccessibleContext
+
+sal_Int16 VCLXAccessibleMenuSeparator::getAccessibleRole() { return AccessibleRole::SEPARATOR; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblepopupmenu.cxx b/accessibility/source/standard/vclxaccessiblepopupmenu.cxx
new file mode 100644
index 000000000..ad3e7441e
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblepopupmenu.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblepopupmenu.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::comphelper;
+
+
+
+
+bool VCLXAccessiblePopupMenu::IsFocused()
+{
+ return !IsChildHighlighted();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessiblePopupMenu::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessiblePopupMenu";
+}
+
+
+Sequence< OUString > VCLXAccessiblePopupMenu::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessiblePopupMenu" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessiblePopupMenu::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Int16 VCLXAccessiblePopupMenu::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::POPUP_MENU;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+sal_Int32 VCLXAccessiblePopupMenu::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return sal_Int32(Application::GetSettings().GetStyleSettings().GetMenuColor());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleradiobutton.cxx b/accessibility/source/standard/vclxaccessibleradiobutton.cxx
new file mode 100644
index 000000000..c1a23ede2
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleradiobutton.cxx
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibleradiobutton.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/window.hxx>
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleRadioButton
+
+
+void VCLXAccessibleRadioButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::RadiobuttonToggle:
+ {
+ Any aOldValue;
+ Any aNewValue;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton && pVCLXRadioButton->getState() )
+ aNewValue <<= AccessibleStateType::CHECKED;
+ else
+ aOldValue <<= AccessibleStateType::CHECKED;
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleRadioButton::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleRelationSet( rRelationSet );
+
+ VclPtr< RadioButton > pRadioButton = GetAsDynamic< RadioButton >();
+ if ( !pRadioButton )
+ return;
+
+ std::vector< VclPtr<RadioButton> > aGroup(pRadioButton->GetRadioButtonGroup());
+ if (!aGroup.empty())
+ {
+ std::vector< Reference< XInterface > > aVec;
+ aVec.reserve(aGroup.size());
+ std::transform(aGroup.begin(), aGroup.end(), std::back_inserter(aVec),
+ [](const VclPtr<RadioButton>& rxItem) { return rxItem->GetAccessible(); });
+ rRelationSet.AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF,
+ comphelper::containerToSequence(aVec) ) );
+ }
+}
+
+
+void VCLXAccessibleRadioButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pVCLXRadioButton->getState() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleRadioButton::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleRadioButton";
+}
+
+
+Sequence< OUString > VCLXAccessibleRadioButton::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleRadioButton" };
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleRadioButton::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleRadioButton::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton && !pVCLXRadioButton->getState() )
+ pVCLXRadioButton->setState( true );
+
+ return true;
+}
+
+OUString VCLXAccessibleRadioButton::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_SELECT;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleRadioButton::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleRadioButton::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ aValue <<= static_cast<sal_Int32>(pVCLXRadioButton->getState());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleRadioButton::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ pVCLXRadioButton->setState( nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleRadioButton::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleRadioButton::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleRadioButton::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblescrollbar.cxx b/accessibility/source/standard/vclxaccessiblescrollbar.cxx
new file mode 100644
index 000000000..9ddb5e12a
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblescrollbar.cxx
@@ -0,0 +1,272 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblescrollbar.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/scrbar.hxx>
+#include <vcl/vclevent.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleScrollBar
+
+
+void VCLXAccessibleScrollBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ScrollbarScroll:
+ {
+ NotifyAccessibleEvent( AccessibleEventId::VALUE_CHANGED, Any(), Any() );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleScrollBar::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ // IA2 CWS: scroll bar should not have FOCUSABLE state.
+ // rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::HORIZONTAL )
+ rStateSet.AddState( AccessibleStateType::HORIZONTAL );
+ else if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::VERTICAL )
+ rStateSet.AddState( AccessibleStateType::VERTICAL );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleScrollBar, VCLXAccessibleComponent, VCLXAccessibleScrollBar_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleScrollBar, VCLXAccessibleComponent, VCLXAccessibleScrollBar_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleScrollBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleScrollBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleScrollBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleScrollBar" };
+}
+
+
+// XAccessibleAction
+
+constexpr sal_Int32 ACCESSIBLE_ACTION_COUNT=4;
+
+sal_Int32 VCLXAccessibleScrollBar::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return ACCESSIBLE_ACTION_COUNT;
+}
+
+
+sal_Bool VCLXAccessibleScrollBar::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ bool bReturn = false;
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ {
+ ScrollType eScrollType;
+ switch ( nIndex )
+ {
+ case 0: eScrollType = ScrollType::LineUp; break;
+ case 1: eScrollType = ScrollType::LineDown; break;
+ case 2: eScrollType = ScrollType::PageUp; break;
+ case 3: eScrollType = ScrollType::PageDown; break;
+ default: eScrollType = ScrollType::DontKnow; break;
+ }
+ if ( pScrollBar->DoScrollAction( eScrollType ) )
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+OUString VCLXAccessibleScrollBar::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ OUString sDescription;
+
+ switch ( nIndex )
+ {
+ case 0: sDescription = OUString(RID_STR_ACC_ACTION_DECLINE); break;
+ case 1: sDescription = OUString(RID_STR_ACC_ACTION_INCLINE); break;
+ case 2: sDescription = OUString(RID_STR_ACC_ACTION_DECBLOCK); break;
+ case 3: sDescription = OUString(RID_STR_ACC_ACTION_INCBLOCK); break;
+ default: break;
+ }
+
+ return sDescription;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleScrollBar::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleScrollBar::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ aValue <<= pVCLXScrollBar->getValue();
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleScrollBar::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+ OSL_VERIFY( getMinimumValue() >>= nValueMin );
+ OSL_VERIFY( getMaximumValue() >>= nValueMax );
+
+ if ( nValue < nValueMin )
+ nValue = nValueMin;
+ else if ( nValue > nValueMax )
+ nValue = nValueMax;
+
+ pVCLXScrollBar->setValue( nValue );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleScrollBar::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ aValue <<= pVCLXScrollBar->getMaximum();
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleScrollBar::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleScrollBar::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Any();
+}
+
+
+OUString VCLXAccessibleScrollBar::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString aName;
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::HORIZONTAL )
+ aName = AccResId( RID_STR_ACC_SCROLLBAR_NAME_HORIZONTAL );
+ else if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::VERTICAL )
+ aName = AccResId( RID_STR_ACC_SCROLLBAR_NAME_VERTICAL );
+ }
+ return aName;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblestatusbar.cxx b/accessibility/source/standard/vclxaccessiblestatusbar.cxx
new file mode 100644
index 000000000..d6e3e0ef5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblestatusbar.cxx
@@ -0,0 +1,335 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblestatusbar.hxx>
+#include <standard/vclxaccessiblestatusbaritem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/status.hxx>
+#include <vcl/vclevent.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleStatusBar::VCLXAccessibleStatusBar( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pStatusBar = GetAs<StatusBar>();
+
+ if ( m_pStatusBar )
+ m_aAccessibleChildren.assign( m_pStatusBar->GetItemCount(), Reference< XAccessible >() );
+}
+
+
+void VCLXAccessibleStatusBar::UpdateShowing( sal_Int32 i, bool bShowing )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ pVCLXAccessibleStatusBarItem->SetShowing( bShowing );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::UpdateItemName( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ {
+ OUString sItemName = pVCLXAccessibleStatusBarItem->GetItemName();
+ pVCLXAccessibleStatusBarItem->SetItemName( sItemName );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::UpdateItemText( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ {
+ OUString sItemText = pVCLXAccessibleStatusBarItem->GetItemText();
+ pVCLXAccessibleStatusBarItem->SetItemText( sItemText );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ return;
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // send accessible child event
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleStatusBar::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // get the accessible of the removed page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+void VCLXAccessibleStatusBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::StatusbarItemAdded:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ InsertChild( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::StatusbarItemRemoved:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem && pVCLXAccessibleStatusBarItem->GetItemId() == nItemId )
+ {
+ RemoveChild( i );
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::StatusbarAllItemsRemoved:
+ {
+ for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
+ RemoveChild( i );
+ }
+ break;
+ case VclEventId::StatusbarShowItem:
+ case VclEventId::StatusbarHideItem:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateShowing( nItemPos, rVclWindowEvent.GetId() == VclEventId::StatusbarShowItem );
+ }
+ }
+ break;
+ case VclEventId::StatusbarNameChanged:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateItemName( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::StatusbarDrawItem:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateItemText( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pStatusBar )
+ {
+ m_pStatusBar = nullptr;
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleStatusBar::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ if ( !m_pStatusBar )
+ return;
+
+ m_pStatusBar = nullptr;
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleStatusBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleStatusBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleStatusBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleStatusBar" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleStatusBar::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = m_pStatusBar->GetItemId( static_cast<sal_uInt16>(i) );
+
+ xChild = new VCLXAccessibleStatusBarItem( m_pStatusBar, nItemId );
+
+ // insert into status bar item list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = m_pStatusBar->GetItemId( VCLPoint( rPoint ) );
+ sal_Int32 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ if ( nItemPos >= 0 && o3tl::make_unsigned(nItemPos) < m_aAccessibleChildren.size() )
+ xChild = getAccessibleChild( nItemPos );
+ }
+
+ return xChild;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx b/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx
new file mode 100644
index 000000000..840674206
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx
@@ -0,0 +1,587 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessiblestatusbaritem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/status.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleStatusBarItem::VCLXAccessibleStatusBarItem( StatusBar* pStatusBar, sal_uInt16 nItemId )
+ :m_pStatusBar( pStatusBar )
+ ,m_nItemId( nItemId )
+{
+
+ m_sItemName = GetItemName();
+ m_sItemText = GetItemText();
+ m_bShowing = IsShowing();
+}
+
+
+bool VCLXAccessibleStatusBarItem::IsShowing()
+{
+ bool bShowing = false;
+
+ if ( m_pStatusBar )
+ bShowing = m_pStatusBar->IsItemVisible( m_nItemId );
+
+ return bShowing;
+}
+
+
+void VCLXAccessibleStatusBarItem::SetShowing( bool bShowing )
+{
+ if ( m_bShowing != bShowing )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bShowing )
+ aOldValue <<= AccessibleStateType::SHOWING;
+ else
+ aNewValue <<= AccessibleStateType::SHOWING;
+ m_bShowing = bShowing;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleStatusBarItem::SetItemName( const OUString& sItemName )
+{
+ if ( m_sItemName != sItemName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sItemName;
+ aNewValue <<= sItemName;
+ m_sItemName = sItemName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleStatusBarItem::GetItemName()
+{
+ OUString sName;
+ if ( m_pStatusBar )
+ sName = m_pStatusBar->GetAccessibleName( m_nItemId );
+
+ return sName;
+}
+
+
+void VCLXAccessibleStatusBarItem::SetItemText( const OUString& sItemText )
+{
+ Any aOldValue, aNewValue;
+ if ( implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
+ {
+ m_sItemText = sItemText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleStatusBarItem::GetItemText()
+{
+ OUString sText;
+ if ( m_pStatusBar )
+ sText = m_pStatusBar->GetItemText( m_nItemId );
+
+ return sText;
+}
+
+
+void VCLXAccessibleStatusBarItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if ( IsShowing() )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleStatusBarItem::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pStatusBar )
+ aBounds = AWTRectangle( m_pStatusBar->GetItemRect( m_nItemId ) );
+
+ return aBounds;
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleStatusBarItem::implGetText()
+{
+ return GetItemText();
+}
+
+
+lang::Locale VCLXAccessibleStatusBarItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleStatusBarItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleStatusBarItem, AccessibleTextHelper_BASE, VCLXAccessibleStatusBarItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleStatusBarItem, AccessibleTextHelper_BASE, VCLXAccessibleStatusBarItem_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleStatusBarItem::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+
+ m_pStatusBar = nullptr;
+ m_sItemName.clear();
+ m_sItemText.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleStatusBarItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleStatusBarItem";
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+Sequence< OUString > VCLXAccessibleStatusBarItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleStatusBarItem" };
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > VCLXAccessibleStatusBarItem::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pStatusBar )
+ xParent = m_pStatusBar->GetAccessible();
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pStatusBar )
+ nIndexInParent = m_pStatusBar->GetItemPos( m_nItemId );
+
+ return nIndexInParent;
+}
+
+
+sal_Int16 VCLXAccessibleStatusBarItem::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::LABEL;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pStatusBar )
+ sDescription = m_pStatusBar->GetHelpText( m_nItemId );
+
+ return sDescription;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemName();
+}
+
+
+Reference< XAccessibleRelationSet > VCLXAccessibleStatusBarItem::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleStatusBarItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+Locale VCLXAccessibleStatusBarItem::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleAtPoint( const awt::Point& )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Reference< XAccessible >();
+}
+
+
+void VCLXAccessibleStatusBarItem::grabFocus( )
+{
+ // no focus for status bar items
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleStatusBarItem::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText();
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleText
+
+OUString VCLXAccessibleStatusBarItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText();
+}
+
+OUString VCLXAccessibleStatusBarItem::getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange(GetItemText(), nStartIndex, nEndIndex);
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText().getLength();
+}
+
+sal_Unicode VCLXAccessibleStatusBarItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetItemText(), nIndex );
+}
+
+sal_Int32 VCLXAccessibleStatusBarItem::getCaretPosition()
+{
+ OExternalLockGuard aGuard( this );
+
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetItemText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleStatusBarItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pStatusBar )
+ {
+ vcl::Font aFont = m_pStatusBar->GetFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ aValues = CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleStatusBarItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pStatusBar )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = m_pStatusBar->GetItemRect( m_nItemId );
+ m_pStatusBar->RecordLayoutData( &aLayoutData, aItemRect );
+ tools::Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pStatusBar )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = m_pStatusBar->GetItemRect( m_nItemId );
+ m_pStatusBar->RecordLayoutData( &aLayoutData, aItemRect );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ nIndex = aLayoutData.GetIndexForPoint( aPnt );
+ }
+
+ return nIndex;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pStatusBar )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pStatusBar->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( implGetTextRange( GetItemText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabcontrol.cxx b/accessibility/source/standard/vclxaccessibletabcontrol.cxx
new file mode 100644
index 000000000..c1ede9741
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabcontrol.cxx
@@ -0,0 +1,488 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletabcontrol.hxx>
+#include <standard/vclxaccessibletabpage.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/vclevent.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabControl::VCLXAccessibleTabControl( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pTabControl = GetAs<TabControl>();
+ if (!m_pTabControl)
+ return;
+ if (m_pTabControl->isDisposed())
+ {
+ m_pTabControl.clear();
+ return;
+ }
+ m_aAccessibleChildren.assign( m_pTabControl->GetPageCount(), Reference< XAccessible >() );
+}
+
+
+void VCLXAccessibleTabControl::UpdateFocused()
+{
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetFocused( pVCLXAccessibleTabPage->IsFocused() );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdateSelected( sal_Int32 i, bool bSelected )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetSelected( bSelected );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdatePageText( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetPageText( pVCLXAccessibleTabPage->GetPageText() );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdateTabPage( sal_Int32 i, bool bNew )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->Update( bNew );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ return;
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // send accessible child event
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabControl::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // get the accessible of the removed page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+void VCLXAccessibleTabControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::TabpageActivate:
+ case VclEventId::TabpageDeactivate:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ UpdateFocused();
+ UpdateSelected( nPagePos, rVclWindowEvent.GetId() == VclEventId::TabpageActivate );
+ }
+ }
+ break;
+ case VclEventId::TabpagePageTextChanged:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ UpdatePageText( nPagePos );
+ }
+ }
+ break;
+ case VclEventId::TabpageInserted:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ InsertChild( nPagePos );
+ }
+ }
+ break;
+ case VclEventId::TabpageRemoved:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage && pVCLXAccessibleTabPage->GetPageId() == nPageId )
+ {
+ RemoveChild( i );
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::TabpageRemovedAll:
+ {
+ for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
+ RemoveChild( i );
+ }
+ break;
+ case VclEventId::WindowGetFocus:
+ case VclEventId::WindowLoseFocus:
+ {
+ UpdateFocused();
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pTabControl )
+ {
+ m_pTabControl = nullptr;
+
+ // dispose all tab pages
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleTabControl::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow:
+ case VclEventId::WindowHide:
+ {
+ if ( m_pTabControl )
+ {
+ vcl::Window* pChild = static_cast< vcl::Window* >( rVclWindowEvent.GetData() );
+ if ( pChild && pChild->GetType() == WindowType::TABPAGE )
+ {
+ for ( sal_Int32 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i )
+ {
+ sal_uInt16 nPageId = m_pTabControl->GetPageId( static_cast<sal_uInt16>(i) );
+ TabPage* pTabPage = m_pTabControl->GetTabPage( nPageId );
+ if ( pTabPage == static_cast<TabPage*>(pChild) )
+ UpdateTabPage( i, rVclWindowEvent.GetId() == VclEventId::WindowShow );
+ }
+ }
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleTabControl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ if ( m_pTabControl )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleTabControl::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ if ( !m_pTabControl )
+ return;
+
+ m_pTabControl = nullptr;
+
+ // dispose all tab pages
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleTabControl::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTabControl";
+}
+
+
+Sequence< OUString > VCLXAccessibleTabControl::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleTabControl" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleTabControl::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabControl::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ return implGetAccessibleChild( i );
+}
+
+Reference< XAccessible > VCLXAccessibleTabControl::implGetAccessibleChild( sal_Int32 i )
+{
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ sal_uInt16 nPageId = m_pTabControl ? m_pTabControl->GetPageId(static_cast<sal_uInt16>(i)) : 0;
+ if (nPageId)
+ {
+ xChild = new VCLXAccessibleTabPage( m_pTabControl, nPageId );
+
+ // insert into tab page list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+sal_Int16 VCLXAccessibleTabControl::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::PAGE_TAB_LIST;
+}
+
+
+OUString VCLXAccessibleTabControl::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleSelection
+
+
+void VCLXAccessibleTabControl::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pTabControl )
+ m_pTabControl->SelectTabPage( m_pTabControl->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) );
+}
+
+
+sal_Bool VCLXAccessibleTabControl::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ return implIsAccessibleChildSelected( nChildIndex );
+}
+
+bool VCLXAccessibleTabControl::implIsAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ bool bSelected = false;
+ if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_pTabControl->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void VCLXAccessibleTabControl::clearAccessibleSelection( )
+{
+ // This method makes no sense in a tab control, and so does nothing.
+}
+
+
+void VCLXAccessibleTabControl::selectAllAccessibleChildren( )
+{
+ selectAccessibleChild( 0 );
+}
+
+
+sal_Int32 VCLXAccessibleTabControl::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabControl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( std::size_t i = 0, nCount = m_aAccessibleChildren.size(); i < nCount; i++ )
+ {
+ if ( implIsAccessibleChildSelected( i ) )
+ {
+ xChild = implGetAccessibleChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleTabControl::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ // This method makes no sense in a tab control, and so does nothing.
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabpage.cxx b/accessibility/source/standard/vclxaccessibletabpage.cxx
new file mode 100644
index 000000000..8dd5a2419
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabpage.cxx
@@ -0,0 +1,675 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletabpage.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabPage::VCLXAccessibleTabPage( TabControl* pTabControl, sal_uInt16 nPageId )
+ :m_pTabControl( pTabControl )
+ ,m_nPageId( nPageId )
+{
+ m_bFocused = IsFocused();
+ m_bSelected = IsSelected();
+ m_sPageText = GetPageText();
+}
+
+
+VCLXAccessibleTabPage::~VCLXAccessibleTabPage()
+{
+}
+
+
+bool VCLXAccessibleTabPage::IsFocused() const
+{
+ bool bFocused = false;
+
+ if ( m_pTabControl && m_pTabControl->HasFocus() && m_pTabControl->GetCurPageId() == m_nPageId )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+bool VCLXAccessibleTabPage::IsSelected() const
+{
+ bool bSelected = false;
+
+ if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_nPageId )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void VCLXAccessibleTabPage::SetFocused( bool bFocused )
+{
+ if ( m_bFocused != bFocused )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bFocused )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bFocused = bFocused;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::SetSelected( bool bSelected )
+{
+ if ( m_bSelected != bSelected )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::SetPageText( const OUString& sPageText )
+{
+ Any aOldValue, aNewValue;
+ if ( OCommonAccessibleText::implInitTextChangedEvent( m_sPageText, sPageText, aOldValue, aNewValue ) )
+ {
+ Any aOldName, aNewName;
+ aOldName <<= m_sPageText;
+ aNewName <<= sPageText;
+ m_sPageText = sPageText;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldName, aNewName );
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleTabPage::GetPageText()
+{
+ OUString sText;
+ if ( m_pTabControl )
+ sText = OutputDevice::GetNonMnemonicString( m_pTabControl->GetPageText( m_nPageId ) );
+
+ return sText;
+}
+
+
+void VCLXAccessibleTabPage::Update( bool bNew )
+{
+ if ( !m_pTabControl )
+ return;
+
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( !pTabPage )
+ return;
+
+ Reference< XAccessible > xChild( pTabPage->GetAccessible( bNew ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ if ( bNew )
+ aNewValue <<= xChild;
+ else
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ if ( IsSelected() )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleTabPage::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pTabControl )
+ aBounds = AWTRectangle( m_pTabControl->GetTabBounds( m_nPageId ) );
+
+ return aBounds;
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleTabPage::implGetText()
+{
+ return GetPageText();
+}
+
+
+lang::Locale VCLXAccessibleTabPage::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleTabPage::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabPage, AccessibleTextHelper_BASE, VCLXAccessibleTabPage_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabPage, AccessibleTextHelper_BASE, VCLXAccessibleTabPage_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleTabPage::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+
+ m_pTabControl = nullptr;
+ m_sPageText.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleTabPage::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTabPage";
+}
+
+
+sal_Bool VCLXAccessibleTabPage::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+Sequence< OUString > VCLXAccessibleTabPage::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleTabPage" };
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > VCLXAccessibleTabPage::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleTabPage::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleTabPage::implGetAccessibleChildCount()
+{
+ sal_Int32 nCount = 0;
+ if ( m_pTabControl )
+ {
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( pTabPage && pTabPage->IsVisible() )
+ nCount = 1;
+ }
+
+ return nCount;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= implGetAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ if ( m_pTabControl )
+ {
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( pTabPage && pTabPage->IsVisible() )
+ xChild = pTabPage->GetAccessible();
+ }
+
+ return xChild;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabControl )
+ xParent = m_pTabControl->GetAccessible();
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pTabControl )
+ nIndexInParent = m_pTabControl->GetPagePos( m_nPageId );
+
+ return nIndexInParent;
+}
+
+sal_Int16 VCLXAccessibleTabPage::getAccessibleRole()
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::PAGE_TAB;
+}
+
+OUString VCLXAccessibleTabPage::getAccessibleDescription()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pTabControl )
+ sDescription = m_pTabControl->GetAccessibleDescription( m_nPageId );
+
+ return sDescription;
+}
+
+OUString VCLXAccessibleTabPage::getAccessibleName()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sName;
+ if ( m_pTabControl )
+ sName = m_pTabControl->GetAccessibleName( m_nPageId );
+
+ return sName;
+}
+
+Reference< XAccessibleRelationSet > VCLXAccessibleTabPage::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleTabPage::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+Locale VCLXAccessibleTabPage::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleTabPage::grabFocus( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pTabControl )
+ {
+ m_pTabControl->SelectTabPage( m_nPageId );
+ m_pTabControl->GrabFocus();
+ }
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleTabPage::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString VCLXAccessibleTabPage::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString VCLXAccessibleTabPage::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleText
+
+OUString VCLXAccessibleTabPage::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetPageText();
+}
+
+OUString VCLXAccessibleTabPage::getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange(GetPageText(), nStartIndex, nEndIndex);
+}
+
+sal_Unicode VCLXAccessibleTabPage::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetPageText(), nIndex );
+}
+
+sal_Int32 VCLXAccessibleTabPage::getCharacterCount()
+{
+ return GetPageText().getLength();
+}
+
+sal_Int32 VCLXAccessibleTabPage::getCaretPosition()
+{
+ OExternalLockGuard aGuard( this );
+
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleTabPage::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( GetPageText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pTabControl )
+ {
+ vcl::Font aFont = m_pTabControl->GetFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ aValues = CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleTabPage::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pTabControl )
+ {
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ tools::Rectangle aCharRect = m_pTabControl->GetCharacterBounds( m_nPageId, nIndex );
+ aCharRect.Move( -aPageRect.Left(), -aPageRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = 0;
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aPageRect.TopLeft();
+ sal_Int32 nI = m_pTabControl->GetIndexForPoint( aPnt, nPageId );
+ if ( nI != -1 && m_nPageId == nPageId )
+ nIndex = nI;
+ }
+
+ return nIndex;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pTabControl )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pTabControl->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( implGetTextRange( GetPageText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleTabPage::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabpagewindow.cxx b/accessibility/source/standard/vclxaccessibletabpagewindow.cxx
new file mode 100644
index 000000000..c8408d24b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabpagewindow.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletabpagewindow.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabPageWindow::VCLXAccessibleTabPageWindow( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pTabPage = GetAs<TabPage>();
+ m_pTabControl = nullptr;
+ m_nPageId = 0;
+ if ( !m_pTabPage )
+ return;
+
+ vcl::Window* pParent = m_pTabPage->GetAccessibleParentWindow();
+ if ( !(pParent && pParent->GetType() == WindowType::TABCONTROL) )
+ return;
+
+ m_pTabControl = static_cast< TabControl* >( pParent );
+ if ( m_pTabControl )
+ {
+ for ( sal_uInt16 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i )
+ {
+ sal_uInt16 nPageId = m_pTabControl->GetPageId( i );
+ if ( m_pTabControl->GetTabPage( nPageId ) == m_pTabPage.get() )
+ m_nPageId = nPageId;
+ }
+ }
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleTabPageWindow::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pTabControl )
+ {
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ if ( m_pTabPage )
+ {
+ tools::Rectangle aRect( m_pTabPage->GetPosPixel(), m_pTabPage->GetSizePixel() );
+ aRect.Move( -aPageRect.Left(), -aPageRect.Top() );
+ aBounds = AWTRectangle( aRect );
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleTabPageWindow::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ m_pTabControl = nullptr;
+ m_pTabPage = nullptr;
+}
+
+
+// XAccessibleContext
+
+
+Reference< XAccessible > VCLXAccessibleTabPageWindow::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabControl )
+ {
+ Reference< XAccessible > xAcc( m_pTabControl->GetAccessible() );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleContext > xCont( xAcc->getAccessibleContext() );
+ if ( xCont.is() )
+ {
+ sal_uInt16 const nPagePos(m_pTabControl->GetPagePos(m_nPageId));
+ SAL_WARN_IF(nPagePos == TAB_PAGE_NOTFOUND, "accessibility",
+ "getAccessibleParent(): no tab page");
+ if (nPagePos != TAB_PAGE_NOTFOUND)
+ {
+ xParent = xCont->getAccessibleChild(nPagePos);
+ }
+ }
+ }
+ }
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleTabPageWindow::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletextcomponent.cxx b/accessibility/source/standard/vclxaccessibletextcomponent.cxx
new file mode 100644
index 000000000..c5dba0df9
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletextcomponent.cxx
@@ -0,0 +1,376 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletextcomponent.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTextComponent::VCLXAccessibleTextComponent( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ m_sText = OutputDevice::GetNonMnemonicString( pWindow->GetText() );
+}
+
+
+void VCLXAccessibleTextComponent::SetText( const OUString& sText )
+{
+ Any aOldValue, aNewValue;
+ if ( implInitTextChangedEvent( m_sText, sText, aOldValue, aNewValue ) )
+ {
+ m_sText = sText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTextComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowFrameTitleChanged:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ SetText( implGetText() );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleTextComponent::implGetText()
+{
+ OUString aText;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ aText = OutputDevice::GetNonMnemonicString( pWindow->GetText() );
+
+ return aText;
+}
+
+
+lang::Locale VCLXAccessibleTextComponent::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleTextComponent::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleTextComponent::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ m_sText.clear();
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleTextComponent::getCaretPosition()
+{
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::setCaretPosition( sal_Int32 nIndex )
+{
+ return setSelection( nIndex, nIndex );
+}
+
+
+sal_Unicode VCLXAccessibleTextComponent::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleTextComponent::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ vcl::Font aFont = pWindow->GetControlFont();
+
+ Color nBackColor = pWindow->GetControlBackground();
+ Color nColor = pWindow->GetControlForeground();
+
+ // MT: Code with default font was introduced with the IA2 CWS, but I am not convinced that this is the correct font...
+ // Decide what to do when we have a concrete issue.
+ /*
+ Font aDefaultVCLFont;
+ OutputDevice* pDev = Application::GetDefaultDevice();
+ if ( pDev )
+ {
+ aDefaultVCLFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
+ if ( !aFont.GetName().Len() )
+ {
+ String aDefaultName = aDefaultVCLFont.GetName();
+ aFont.SetName( aDefaultName );
+ }
+ if ( !aFont.GetHeight() )
+ {
+ aFont.SetHeight( aDefaultVCLFont.GetHeight() );
+ }
+ if ( aFont.GetWeight() == WEIGHT_DONTKNOW )
+ {
+ aFont.SetWeight( aDefaultVCLFont.GetWeight() );
+ }
+
+ //if nColor is -1, it may indicate that the default color black is using.
+ if ( nColor == -1)
+ {
+ nColor = aDefaultVCLFont.GetColor().GetColor();
+ }
+ }
+ */
+
+ // MT: Adjustment stuff was introduced with the IA2 CWS, but adjustment is not a character attribute...
+ // In case we reintroduce it, use adjustment as extra parameter for the CharacterAttributesHelper...
+ /*
+ WinBits aBits = GetWindow()->GetStyle();
+ sal_Int16 nAdjust = -1;
+ if ( aBits & WB_LEFT )
+ {
+ nAdjust = style::ParagraphAdjust_LEFT;
+ }
+ else if ( aBits & WB_RIGHT )
+ {
+ nAdjust = style::ParagraphAdjust_RIGHT;
+ }
+ else if ( aBits & WB_CENTER )
+ {
+ nAdjust = style::ParagraphAdjust_CENTER;
+ }
+ */
+
+ aValues = CharacterAttributesHelper( aFont, sal_Int32(nBackColor), sal_Int32(nColor) )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleTextComponent::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aRect;
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ aRect = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
+
+ return aRect;
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetText().getLength();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ nIndex = pControl->GetIndexForPoint( VCLPoint( aPoint ) );
+
+ return nIndex;
+}
+
+
+OUString VCLXAccessibleTextComponent::getSelectedText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectedText();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getSelectionStart()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectionStart();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getSelectionEnd()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+OUString VCLXAccessibleTextComponent::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetText();
+}
+
+
+OUString VCLXAccessibleTextComponent::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleTextComponent::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletextfield.cxx b/accessibility/source/standard/vclxaccessibletextfield.cxx
new file mode 100644
index 000000000..c94e46e3d
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletextfield.cxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletextfield.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleTextField::VCLXAccessibleTextField (VCLXWindow* pVCLWindow, const Reference< XAccessible >& _xParent) :
+ VCLXAccessibleTextComponent (pVCLWindow),
+ m_xParent( _xParent )
+
+{
+}
+
+
+OUString VCLXAccessibleTextField::implGetText()
+{
+ OUString aText;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox && !pListBox->IsInDropDown())
+ aText = pListBox->GetSelectedEntry();
+
+ return aText;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleTextField, VCLXAccessibleTextComponent, VCLXAccessible_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleTextField, VCLXAccessibleTextComponent, VCLXAccessible_BASE)
+
+
+// XAccessible
+
+Reference<XAccessibleContext> SAL_CALL
+ VCLXAccessibleTextField::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleTextField::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleTextField::getAccessibleChild (sal_Int32)
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+sal_Int16 SAL_CALL VCLXAccessibleTextField::getAccessibleRole()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return AccessibleRole::TEXT;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleTextField::getAccessibleParent( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return m_xParent;
+}
+
+
+// XServiceInfo
+
+OUString VCLXAccessibleTextField::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTextField";
+}
+
+
+Sequence< OUString > VCLXAccessibleTextField::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleTextComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleTextField"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletoolbox.cxx b/accessibility/source/standard/vclxaccessibletoolbox.cxx
new file mode 100644
index 000000000..4e2059b61
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletoolbox.cxx
@@ -0,0 +1,866 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <string.h>
+
+#include <standard/vclxaccessibletoolbox.hxx>
+#include <standard/vclxaccessibletoolboxitem.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/vclevent.hxx>
+#include <comphelper/accessiblewrapper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/types.hxx>
+
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+namespace
+{
+
+ // = OToolBoxWindowItemContext
+
+ /** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
+ */
+ class OToolBoxWindowItemContext final : public OAccessibleContextWrapper
+ {
+ sal_Int32 m_nIndexInParent;
+ public:
+ OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxOwningAccessible,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
+ ) : OAccessibleContextWrapper(
+ _rxContext,
+ _rxInnerAccessibleContext,
+ _rxOwningAccessible,
+ _rxParentAccessible )
+ ,m_nIndexInParent(_nIndexInParent)
+ {
+ }
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ };
+
+
+ sal_Int32 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_nIndexInParent;
+ }
+
+
+ // = OToolBoxWindowItem
+
+ typedef ::cppu::ImplHelper1 < XUnoTunnel
+ > OToolBoxWindowItem_Base;
+
+ /** XAccessible implementation for a toolbox item which is represented by a VCL Window
+ */
+ class OToolBoxWindowItem
+ :public OAccessibleWrapper
+ ,public OToolBoxWindowItem_Base
+ {
+ private:
+ sal_Int32 m_nIndexInParent;
+
+ public:
+ sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
+ void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
+
+ static const Sequence< sal_Int8 > & getUnoTunnelId();
+
+ public:
+ OToolBoxWindowItem(sal_Int32 _nIndexInParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxInnerAccessible,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
+ ) : OAccessibleWrapper(
+ _rxContext,
+ _rxInnerAccessible,
+ _rxParentAccessible)
+ ,m_nIndexInParent(_nIndexInParent)
+ {
+ }
+
+ protected:
+ // XInterface
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+
+ // OAccessibleWrapper
+ virtual rtl::Reference<OAccessibleContextWrapper> createAccessibleContext(
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerContext
+ ) override;
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
+ };
+
+ IMPLEMENT_FORWARD_XINTERFACE2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
+
+ rtl::Reference<OAccessibleContextWrapper> OToolBoxWindowItem::createAccessibleContext(
+ const Reference< XAccessibleContext >& _rxInnerContext )
+ {
+ return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
+ }
+
+ const Sequence< sal_Int8 > & OToolBoxWindowItem::getUnoTunnelId()
+ {
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+ }
+
+ sal_Int64 SAL_CALL OToolBoxWindowItem::getSomething( const Sequence< sal_Int8 >& _rId )
+ {
+ return comphelper::getSomethingImpl(_rId, this);
+ }
+}
+
+// VCLXAccessibleToolBox
+
+VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
+
+ VCLXAccessibleComponent( pVCLXWindow )
+
+{
+}
+
+VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
+{
+}
+
+VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = nullptr;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ // returns only toolbox buttons, not windows
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
+ pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ }
+
+ return pItem;
+}
+
+void VCLXAccessibleToolBox::UpdateFocus_Impl()
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if( !pToolBox )
+ return;
+
+ // submit events only if toolbox has the focus to avoid sending events due to mouse move
+ bool bHasFocus = false;
+ if ( pToolBox->HasFocus() )
+ bHasFocus = true;
+ else
+ {
+ // check for subtoolbar, i.e. check if our parent is a toolbar
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
+ // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
+ if ( pToolBoxParent && pToolBoxParent->HasFocus() )
+ bHasFocus = true;
+ }
+
+ if ( !bHasFocus )
+ return;
+
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ sal_uInt16 nFocusCount = 0;
+ for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
+
+ if ( rxChild.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
+ if ( pItem->HasFocus() && nItemId != nHighlightItemId )
+ {
+ // reset the old focused item
+ pItem->SetFocus( false );
+ nFocusCount++;
+ }
+ if ( nItemId == nHighlightItemId )
+ {
+ // set the new focused item
+ pItem->SetFocus( true );
+ nFocusCount++;
+ }
+ }
+ // both items changed?
+ if ( nFocusCount > 1 )
+ break;
+ }
+}
+
+void VCLXAccessibleToolBox::ReleaseFocus_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
+ {
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ if ( pItem->HasFocus() )
+ pItem->SetFocus( false );
+ }
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateChecked_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBoxItemId nFocusId = pToolBox->GetItemId( _nPos );
+ VCLXAccessibleToolBoxItem* pFocusItem = nullptr;
+
+ for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
+
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
+ pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
+ if ( nItemId == nFocusId )
+ pFocusItem = pItem;
+ }
+ //Solution:If the position is not a child item,the focus should not be called
+ if ( pFocusItem && _nPos != ToolBox::ITEM_NOTFOUND )
+ pFocusItem->SetFocus( true );
+}
+
+void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBoxItemId nItemId = pToolBox->GetItemId( _nPos );
+
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ if ( pItem )
+ pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
+ }
+}
+
+void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator const & _rMapPos,
+ bool _bNotifyRemoval )
+{
+ Reference< XAccessible > xItemAcc( _rMapPos->second );
+ if ( !xItemAcc.is() )
+ return;
+
+ if ( _bNotifyRemoval )
+ {
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any( xItemAcc ), Any() );
+ }
+
+ auto pWindowItem = comphelper::getFromUnoTunnel<OToolBoxWindowItem>(xItemAcc);
+ if ( !pWindowItem )
+ {
+ static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
+ ::comphelper::disposeComponent( xItemAcc );
+ }
+ else
+ {
+ Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
+ ::comphelper::disposeComponent( xContext );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateItem_Impl( ToolBox::ImplToolItems::size_type _nPos)
+{
+ if ( _nPos < m_aAccessibleChildren.size() )
+ {
+ UpdateAllItems_Impl();
+ return;
+ }
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ // adjust the "index-in-parent"s
+ ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ while ( m_aAccessibleChildren.end() != aIndexAdjust )
+ {
+ Reference< XAccessible > xItemAcc( aIndexAdjust->second );
+
+ auto pWindowItem = comphelper::getFromUnoTunnel<OToolBoxWindowItem>(xItemAcc);
+ if ( !pWindowItem )
+ {
+ VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
+ if ( pItem )
+ {
+ sal_Int32 nIndex = pItem->getIndexInParent( );
+ nIndex++;
+ pItem->setIndexInParent( nIndex );
+ }
+ }
+ else
+ {
+ sal_Int32 nIndex = pWindowItem->getIndexInParent( );
+ nIndex++;
+ pWindowItem->setIndexInParent( nIndex );
+ }
+
+ ++aIndexAdjust;
+ }
+
+ // TODO: we should make this dependent on the existence of event listeners
+ // with the current implementation, we always create accessible object
+ Any aNewChild( getAccessibleChild( static_cast<sal_Int32>(_nPos) ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
+}
+
+void VCLXAccessibleToolBox::UpdateAllItems_Impl()
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ // deregister the old items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, true );
+ }
+ m_aAccessibleChildren.clear();
+
+ // register the new items
+ ToolBox::ImplToolItems::size_type i, nCount = pToolBox->GetItemCount();
+ for ( i = 0; i < nCount; ++i )
+ {
+ Any aNewValue;
+ aNewValue <<= getAccessibleChild( static_cast<sal_Int32>(i) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if( !(pWindow && pToolBox) )
+ return;
+
+ const ToolBoxItemId nDownItem = pToolBox->GetDownItemId();
+ if ( !nDownItem )
+ // No item is currently in down state.
+ // Moreover, calling GetItemPos with 0 will find a separator if there is any.
+ return;
+
+ Reference< XAccessible > xChild( pWindow->GetAccessible() );
+ if( xChild.is() )
+ {
+ Reference< XAccessible > xChildItem( getAccessibleChild( static_cast< sal_Int32 >( pToolBox->GetItemPos( nDownItem ) ) ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
+
+ pItem->SetChild( xChild );
+ pItem->NotifyChildEvent( xChild, bOpen );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateItemName_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
+ if ( pItem )
+ pItem->NameChanged();
+}
+
+void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
+ if ( pItem )
+ pItem->ToggleEnableState();
+}
+
+void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !(pChildWindow
+ && pToolBox
+ && pToolBox == pChildWindow->GetParent()
+ && pChildWindow->GetType() == WindowType::TOOLBOX) )
+ return;
+
+ const ToolBoxItemId nCurItemId( pToolBox->GetCurItemId() );
+ if ( !nCurItemId )
+ // No item is currently active (might happen when opening the overflow popup).
+ // Moreover, calling GetItemPos with 0 will find a separator if there is any.
+ return;
+
+ ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( nCurItemId );
+ Reference< XAccessible > xItem = getAccessibleChild( nIndex );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( xItem.is() )
+ {
+ Reference< XAccessible > xChild = pChildWindow->GetAccessible();
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
+ pItem->SetChild( xChild );
+ pItem->NotifyChildEvent( xChild, true/*_bShow*/ );
+ }
+}
+
+void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
+ if ( nIndex == ToolBox::ITEM_NOTFOUND )
+ return; // not found
+
+ Reference< XAccessible > xItem = getAccessibleChild( nIndex );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( !xItem.is() )
+ return;
+
+ Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
+ if ( pItem->GetChild() == xChild )
+ {
+ pItem->SetChild( Reference< XAccessible >() );
+ pItem->NotifyChildEvent( xChild, false );
+ }
+}
+
+void VCLXAccessibleToolBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pToolBox->IsHorizontal() )
+ rStateSet.AddState( AccessibleStateType::HORIZONTAL );
+ else
+ rStateSet.AddState( AccessibleStateType::VERTICAL );
+ }
+}
+
+void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ // to prevent an early release of the toolbox (VclEventId::ObjectDying)
+ Reference< XAccessibleContext > xHoldAlive = this;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ToolboxClick:
+ case VclEventId::ToolboxSelect:
+ {
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( rVclWindowEvent.GetData() )
+ {
+ UpdateChecked_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ }
+ else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != ToolBox::ITEM_NOTFOUND )
+ {
+ UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
+ UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
+ }
+ break;
+ }
+ case VclEventId::ToolboxDoubleClick:
+ case VclEventId::ToolboxActivate:
+ case VclEventId::ToolboxDeactivate:
+ //case VclEventId::ToolboxSelect:
+ break;
+
+ case VclEventId::ToolboxItemUpdated:
+ {
+ if ( rVclWindowEvent.GetData() )
+ {
+ UpdateChecked_Impl( ToolBox::ITEM_NOTFOUND );
+ UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ }
+ break;
+ }
+
+ case VclEventId::ToolboxHighlight:
+ UpdateFocus_Impl();
+ break;
+
+ case VclEventId::ToolboxHighlightOff:
+ ReleaseFocus_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemAdded :
+ UpdateItem_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemRemoved :
+ case VclEventId::ToolboxAllItemsChanged :
+ {
+ UpdateAllItems_Impl();
+ break;
+ }
+
+ case VclEventId::ToolboxItemWindowChanged:
+ {
+ auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( m_aAccessibleChildren.end() != aAccessiblePos )
+ {
+ implReleaseToolboxItem( aAccessiblePos, false );
+ m_aAccessibleChildren.erase (aAccessiblePos);
+ }
+
+ Any aNewValue;
+ aNewValue <<= getAccessibleChild(nPos);
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
+ break;
+ }
+ case VclEventId::ToolboxItemTextChanged :
+ UpdateItemName_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemEnabled :
+ case VclEventId::ToolboxItemDisabled :
+ {
+ UpdateItemEnabled_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+ }
+
+ case VclEventId::DropdownOpen:
+ case VclEventId::DropdownClose:
+ {
+ UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VclEventId::DropdownOpen );
+ break;
+ }
+
+ case VclEventId::ObjectDying :
+ {
+ // if this toolbox is a subtoolbox, we have to release it from its parent
+ VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
+ if ( pWin && pWin->GetParent() &&
+ pWin->GetParent()->GetType() == WindowType::TOOLBOX )
+ {
+ auto pParentAccContext = pWin->GetParent()->GetAccessible()->getAccessibleContext();
+ VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >( pParentAccContext.get() );
+ if ( pParent )
+ pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
+ }
+
+ // dispose all items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, false );
+ }
+ m_aAccessibleChildren.clear();
+
+ [[fallthrough]]; // call base class
+ }
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow: // send create on show for direct accessible children
+ {
+ Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
+ if ( xReturn.is() )
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), Any(xReturn) );
+ else
+ HandleSubToolBarEvent( rVclWindowEvent );
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
+
+ }
+}
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
+
+// XComponent
+void SAL_CALL VCLXAccessibleToolBox::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ // release the items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, false );
+ }
+ m_aAccessibleChildren.clear();
+}
+
+// XServiceInfo
+OUString VCLXAccessibleToolBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleToolBox";
+}
+
+Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleToolBox"});
+}
+
+// XAccessibleContext
+sal_Int32 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+ return implGetAccessibleChildCount();
+}
+
+ sal_Int32 VCLXAccessibleToolBox::implGetAccessibleChildCount( )
+ {
+ sal_Int32 nCount = 0;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ nCount = pToolBox->GetItemCount();
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+
+ return nCount;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int32 i )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || i < 0 || o3tl::make_unsigned(i) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ // search for the child
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
+ if ( m_aAccessibleChildren.end() == aIter )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( i );
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
+ // not found -> create a new child
+ rtl::Reference<VCLXAccessibleToolBoxItem> pChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
+ Reference< XAccessible> xParent = pChild;
+ if ( pItemWindow )
+ {
+ xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
+ pItemWindow->SetAccessible(xChild);
+ pChild->SetChild( xChild );
+ }
+ xChild = pChild;
+ if ( nHighlightItemId > ToolBoxItemId(0) && nItemId == nHighlightItemId )
+ pChild->SetFocus( true );
+ if ( pToolBox->IsItemChecked( nItemId ) )
+ pChild->SetChecked( true );
+ if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
+ pChild->SetIndeterminate( true );
+ m_aAccessibleChildren.emplace( i, xChild );
+ }
+ else
+ {
+ // found it
+ xChild = aIter->second;
+ }
+ return xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xAccessible;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ ToolBox::ImplToolItems::size_type nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
+ if ( nItemPos != ToolBox::ITEM_NOTFOUND )
+ xAccessible = getAccessibleChild( nItemPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ }
+
+ return xAccessible;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
+{
+ Reference< XAccessible > xReturn;
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pChildWindow && pToolBox )
+ {
+ ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
+ for (ToolBox::ImplToolItems::size_type i = 0 ; i < nCount && !xReturn.is() ; ++i)
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( i );
+ vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
+ if ( pItemWindow == pChildWindow )
+ xReturn = getAccessibleChild(i);
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ }
+ }
+ return xReturn;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
+{
+ Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
+
+ if ( !xReturn.is() )
+ xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
+ return xReturn;
+}
+
+// XAccessibleSelection
+void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ pToolBox->ChangeHighlight( nChildIndex );
+}
+
+sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ if ( pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nChildIndex ) )
+ return true;
+ else
+ return false;
+}
+
+void VCLXAccessibleToolBox::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ pToolBox -> LoseFocus();
+}
+
+void VCLXAccessibleToolBox::selectAllAccessibleChildren( )
+{
+ OExternalLockGuard aGuard( this );
+ // intentionally empty. makes no sense for a toolbox
+}
+
+sal_Int32 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nRet = 0;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if (pToolBox)
+ {
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ for ( size_t i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
+ {
+ if ( nHighlightItemId == pToolBox->GetItemId( i ) )
+ {
+ nRet = 1;
+ break; // a toolbox can only have (n)one selected child
+ }
+ }
+ }
+
+ return nRet;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ if ( nSelectedChildIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if (pToolBox)
+ {
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ for ( sal_Int32 i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
+ {
+ if ( nHighlightItemId == pToolBox->GetItemId( i ) )
+ {
+ xChild = getAccessibleChild( i );
+ break;
+ }
+ }
+ }
+
+ if (!xChild)
+ throw IndexOutOfBoundsException();
+
+ return xChild;
+}
+
+void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ if ( nChildIndex < 0 || nChildIndex >= implGetAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+ clearAccessibleSelection(); // a toolbox can only have (n)one selected child
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletoolboxitem.cxx b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
new file mode 100644
index 000000000..dd2a44628
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
@@ -0,0 +1,734 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <standard/vclxaccessibletoolboxitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <strings.hxx>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+#include <array>
+
+// class VCLXAccessibleToolBoxItem ------------------------------------------
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+// Ctor() and Dtor()
+
+VCLXAccessibleToolBoxItem::VCLXAccessibleToolBoxItem( ToolBox* _pToolBox, sal_Int32 _nPos ) :
+ m_pToolBox ( _pToolBox ),
+ m_nIndexInParent( _nPos ),
+ m_nRole ( AccessibleRole::PUSH_BUTTON ),
+ m_nItemId ( 0 ),
+ m_bHasFocus ( false ),
+ m_bIsChecked ( false ),
+ m_bIndeterminate( false )
+
+{
+ OSL_ENSURE( m_pToolBox, "invalid toolbox" );
+ m_nItemId = m_pToolBox->GetItemId( m_nIndexInParent );
+ m_sOldName = GetText();
+ m_bIsChecked = m_pToolBox->IsItemChecked( m_nItemId );
+ m_bIndeterminate = ( m_pToolBox->GetItemState( m_nItemId ) == TRISTATE_INDET );
+ ToolBoxItemType eType = m_pToolBox->GetItemType( m_nIndexInParent );
+ switch ( eType )
+ {
+ case ToolBoxItemType::BUTTON :
+ {
+ ToolBoxItemBits nBits = m_pToolBox->GetItemBits( m_nItemId );
+ if (
+ (( nBits & ToolBoxItemBits::DROPDOWN ) == ToolBoxItemBits::DROPDOWN) ||
+ (( nBits & ToolBoxItemBits::DROPDOWNONLY ) == ToolBoxItemBits::DROPDOWNONLY)
+ )
+ m_nRole = AccessibleRole::BUTTON_DROPDOWN;
+ else if (
+ ( ( nBits & ToolBoxItemBits::CHECKABLE ) == ToolBoxItemBits::CHECKABLE ) ||
+ ( ( nBits & ToolBoxItemBits::RADIOCHECK ) == ToolBoxItemBits::RADIOCHECK ) ||
+ ( ( nBits & ToolBoxItemBits::AUTOCHECK ) == ToolBoxItemBits::AUTOCHECK )
+ )
+ m_nRole = AccessibleRole::TOGGLE_BUTTON;
+ else if ( m_pToolBox->GetItemWindow( m_nItemId ) )
+ m_nRole = AccessibleRole::PANEL;
+ break;
+ }
+
+ case ToolBoxItemType::SPACE :
+ m_nRole = AccessibleRole::FILLER;
+ break;
+
+ case ToolBoxItemType::SEPARATOR :
+ case ToolBoxItemType::BREAK :
+ m_nRole = AccessibleRole::SEPARATOR;
+ break;
+
+ default:
+ {
+ SAL_WARN( "accessibility", "unsupported toolbox itemtype" );
+ }
+ }
+}
+
+VCLXAccessibleToolBoxItem::~VCLXAccessibleToolBoxItem()
+{
+}
+
+OUString VCLXAccessibleToolBoxItem::GetText() const
+{
+ OUString sRet;
+ // no text for separators and spaces
+ if ( m_pToolBox && m_nItemId > ToolBoxItemId(0) )
+ {
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+ if (sRet.isEmpty())
+ {
+ sRet = m_pToolBox->GetQuickHelpText( m_nItemId );
+ if (sRet.isEmpty())
+ {
+ vcl::Window* pItemWindow = m_pToolBox->GetItemWindow( m_nItemId );
+ if ( m_nRole == AccessibleRole::PANEL && pItemWindow && pItemWindow->GetAccessible().is() &&
+ pItemWindow->GetAccessible()->getAccessibleContext().is() )
+ {
+ OUString sWinText = pItemWindow->GetAccessible()->getAccessibleContext()->getAccessibleName();
+ if (!sWinText.isEmpty())
+ sRet = sWinText;
+ }
+ }
+ }
+
+ }
+ return sRet;
+}
+
+void VCLXAccessibleToolBoxItem::SetFocus( bool _bFocus )
+{
+ if ( m_bHasFocus != _bFocus )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bHasFocus )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bHasFocus = _bFocus;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetChecked( bool _bCheck )
+{
+ if( m_nRole == AccessibleRole::PANEL)
+ return;
+ if ( m_bIsChecked != _bCheck )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bIsChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bIsChecked = _bCheck;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetIndeterminate( bool _bIndeterminate )
+{
+ if ( m_bIndeterminate != _bIndeterminate )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bIndeterminate )
+ aOldValue <<= AccessibleStateType::INDETERMINATE;
+ else
+ aNewValue <<= AccessibleStateType::INDETERMINATE;
+ m_bIndeterminate = _bIndeterminate;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::NameChanged()
+{
+ OUString sNewName = implGetText();
+ if ( sNewName != m_sOldName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sOldName;
+ // save new name as old name for next change
+ m_sOldName = sNewName;
+ aNewValue <<= m_sOldName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetChild( const Reference< XAccessible >& _xChild )
+{
+ m_xChild = _xChild;
+}
+
+void VCLXAccessibleToolBoxItem::NotifyChildEvent( const Reference< XAccessible >& _xChild, bool _bShow )
+{
+ Any aOld = _bShow ? Any() : Any( _xChild );
+ Any aNew = _bShow ? Any( _xChild ) : Any();
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOld, aNew );
+}
+
+void VCLXAccessibleToolBoxItem::ToggleEnableState()
+{
+ std::array<Any, 2> aOldValue, aNewValue;
+ if ( m_pToolBox->IsItemEnabled( m_nItemId ) )
+ {
+ aNewValue[0] <<= AccessibleStateType::SENSITIVE;
+ aNewValue[1] <<= AccessibleStateType::ENABLED;
+ }
+ else
+ {
+ aOldValue[0] <<= AccessibleStateType::ENABLED;
+ aOldValue[1] <<= AccessibleStateType::SENSITIVE;
+ }
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
+}
+
+awt::Rectangle VCLXAccessibleToolBoxItem::implGetBounds( )
+{
+ awt::Rectangle aRect;
+ if ( m_pToolBox )
+ aRect = AWTRectangle( m_pToolBox->GetItemPosRect( m_nIndexInParent ) );
+
+ return aRect;
+}
+
+OUString VCLXAccessibleToolBoxItem::implGetText()
+{
+ return GetText();
+}
+
+Locale VCLXAccessibleToolBoxItem::implGetLocale()
+{
+ return Application::GetSettings().GetUILanguageTag().getLocale();
+}
+
+void VCLXAccessibleToolBoxItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+// XInterface
+
+IMPLEMENT_FORWARD_REFCOUNT( VCLXAccessibleToolBoxItem, AccessibleTextHelper_BASE )
+Any SAL_CALL VCLXAccessibleToolBoxItem::queryInterface( const Type& _rType )
+{
+ // #i33611# - toolbox buttons without text don't support XAccessibleText
+ if ( _rType == cppu::UnoType<XAccessibleText>::get()
+ && ( !m_pToolBox || m_pToolBox->GetButtonType() == ButtonType::SYMBOLONLY ) )
+ return Any();
+
+ css::uno::Any aReturn = AccessibleTextHelper_BASE::queryInterface( _rType );
+ if ( !aReturn.hasValue() )
+ aReturn = VCLXAccessibleToolBoxItem_BASE::queryInterface( _rType );
+ return aReturn;
+}
+
+// XTypeProvider
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBoxItem, AccessibleTextHelper_BASE, VCLXAccessibleToolBoxItem_BASE )
+
+// XComponent
+
+void SAL_CALL VCLXAccessibleToolBoxItem::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+ m_pToolBox = nullptr;
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleToolBoxItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleToolBoxItem";
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > VCLXAccessibleToolBoxItem::getSupportedServiceNames()
+{
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.accessibility.AccessibleExtendedComponent",
+ "com.sun.star.accessibility.AccessibleToolBoxItem"};
+}
+
+// XAccessible
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleContext( )
+{
+ return this;
+}
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleChildCount( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_xChild.is() ? 1 : 0;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleChild( sal_Int32 i )
+{
+ OContextEntryGuard aGuard( this );
+
+ // no child -> so index is out of bounds
+ if ( !m_xChild.is() || i != 0 )
+ throw IndexOutOfBoundsException();
+
+ return m_xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleParent( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_pToolBox->GetAccessible();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleIndexInParent( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_nIndexInParent;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleRole( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_nRole;
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if (m_nRole == AccessibleRole::PANEL && m_xChild.is())
+ {
+ return AccResId( RID_STR_ACC_PANEL_DESCRIPTION );
+ }
+ else
+ {
+ OUString sDescription;
+ if ( m_pToolBox )
+ sDescription = m_pToolBox->GetHelpText( m_nItemId );
+ return sDescription;
+ }
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ // entry text == accessible name
+ return GetText();
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleRelationSet( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+Reference< XAccessibleStateSet > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( m_pToolBox && !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
+ if ( m_bIsChecked && m_nRole != AccessibleRole::PANEL )
+ pStateSetHelper->AddState( AccessibleStateType::CHECKED );
+ if ( m_bIndeterminate )
+ pStateSetHelper->AddState( AccessibleStateType::INDETERMINATE );
+ if ( m_pToolBox->IsEnabled() && m_pToolBox->IsItemEnabled( m_nItemId ) )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
+ }
+ if ( m_pToolBox->IsItemVisible( m_nItemId ) )
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ if ( m_pToolBox->IsItemReallyVisible( m_nItemId ) )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ if ( m_bHasFocus )
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSED );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+// XAccessibleText
+
+OUString VCLXAccessibleToolBoxItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetText();
+}
+
+sal_Int32 VCLXAccessibleToolBoxItem::getCharacterCount()
+{
+ return GetText().getLength();
+}
+
+sal_Unicode VCLXAccessibleToolBoxItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetText(), nIndex );
+}
+
+OUString VCLXAccessibleToolBoxItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( GetText(), nStartIndex, nEndIndex );
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getCaretPosition()
+{
+ return -1;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+Sequence< PropertyValue > SAL_CALL VCLXAccessibleToolBoxItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return Sequence< PropertyValue >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleToolBoxItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pToolBox && m_pToolBox->GetButtonType() != ButtonType::SYMBOLONLY ) // symbol buttons have no character bounds
+ {
+ tools::Rectangle aCharRect = m_pToolBox->GetCharacterBounds( m_nItemId, nIndex );
+ tools::Rectangle aItemRect = m_pToolBox->GetItemRect( m_nItemId );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pToolBox && m_pToolBox->GetButtonType() != ButtonType::SYMBOLONLY ) // symbol buttons have no character bounds
+ {
+ ToolBoxItemId nItemId;
+ tools::Rectangle aItemRect = m_pToolBox->GetItemRect( m_nItemId );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nIdx = m_pToolBox->GetIndexForPoint( aPnt, nItemId );
+ if ( nIdx != -1 && nItemId == m_nItemId )
+ nIndex = nIdx;
+ }
+
+ return nIndex;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ bool bReturn = false;
+
+ if ( m_pToolBox )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pToolBox->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleComponent
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+void SAL_CALL VCLXAccessibleToolBoxItem::grabFocus( )
+{
+ Reference< XAccessible > xParent(getAccessibleParent());
+
+ if( xParent.is() )
+ {
+ Reference< XAccessibleSelection > rxAccessibleSelection(xParent->getAccessibleContext(), UNO_QUERY);
+
+ if ( rxAccessibleSelection.is() )
+ {
+ rxAccessibleSelection -> selectAccessibleChild ( getAccessibleIndexInParent() );
+ }
+ }
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pToolBox )
+ nColor = m_pToolBox->GetControlForeground();
+
+ return sal_Int32(nColor);
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pToolBox )
+ nColor = m_pToolBox->GetControlBackground();
+
+ return sal_Int32(nColor);
+}
+
+// XAccessibleExtendedComponent
+Reference< awt::XFont > SAL_CALL VCLXAccessibleToolBoxItem::getFont( )
+{
+ return uno::Reference< awt::XFont >();
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pToolBox )
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+
+ return sRet;
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pToolBox )
+ {
+ if ( Help::IsExtHelpEnabled() )
+ sRet = m_pToolBox->GetHelpText( m_nItemId );
+ else
+ sRet = m_pToolBox->GetQuickHelpText( m_nItemId );
+ if ( sRet.isEmpty() )
+ // no help text set, so use item text
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+ }
+ return sRet;
+}
+
+// XAccessibleAction
+
+sal_Int32 VCLXAccessibleToolBoxItem::getAccessibleActionCount( )
+{
+ // only one action -> "Click"
+ return 1;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pToolBox )
+ m_pToolBox->TriggerItem( m_nItemId );
+
+ return true;
+}
+
+OUString VCLXAccessibleToolBoxItem::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_CLICK;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleToolBoxItem::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OContextEntryGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+// XAccessibleValue
+
+Any VCLXAccessibleToolBoxItem::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ if ( m_pToolBox )
+ aValue <<= static_cast<sal_Int32>(m_pToolBox->IsItemChecked( m_nItemId ));
+
+ if( m_nRole == AccessibleRole::PANEL )
+ aValue <<= sal_Int32(0);
+ return aValue;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pToolBox )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ m_pToolBox->CheckItem( m_nItemId, nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+Any VCLXAccessibleToolBoxItem::getMaximumValue( )
+{
+ return Any(sal_Int32(1));
+}
+
+Any VCLXAccessibleToolBoxItem::getMinimumValue( )
+{
+ return Any(sal_Int32(0));
+}
+
+Any VCLXAccessibleToolBoxItem::getMinimumIncrement( )
+{
+ return Any(sal_Int32(1));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */