LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / accessibility / source / extended / accessiblelistbox.cxx
blob462f286640861df3388e24079c167c3f9365daa7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <extended/accessiblelistbox.hxx>
21 #include <extended/accessiblelistboxentry.hxx>
22 #include <vcl/toolkit/treelistbox.hxx>
23 #include <vcl/toolkit/treelistentry.hxx>
24 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
27 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <unotools/accessiblestatesethelper.hxx>
32 namespace accessibility
36 // class AccessibleListBox -----------------------------------------------------
38 using namespace ::com::sun::star::accessibility;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star;
44 // Ctor() and Dtor()
46 AccessibleListBox::AccessibleListBox( SvTreeListBox const & _rListBox, const Reference< XAccessible >& _xParent ) :
48 VCLXAccessibleComponent( _rListBox.GetWindowPeer() ),
49 m_xParent( _xParent )
53 AccessibleListBox::~AccessibleListBox()
55 if ( isAlive() )
57 // increment ref count to prevent double call of Dtor
58 osl_atomic_increment( &m_refCount );
59 dispose();
62 IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox, VCLXAccessibleComponent, ImplHelper2)
63 IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleListBox, VCLXAccessibleComponent, ImplHelper2)
65 void AccessibleListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
67 if ( !isAlive() )
68 return;
70 switch ( rVclWindowEvent.GetId() )
72 case VclEventId::CheckboxToggle :
74 if ( !getListBox() || !getListBox()->HasFocus() )
76 return;
78 AccessibleListBoxEntry* pCurOpEntry = GetCurEventEntry(rVclWindowEvent);
79 if(!pCurOpEntry)
81 return ;
83 uno::Any aValue;
84 aValue <<= AccessibleStateType::CHECKED;
86 if ( getListBox()->GetCheckButtonState( pCurOpEntry->GetSvLBoxEntry() ) == SvButtonState::Checked )
88 pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), aValue );
90 else
92 pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aValue,uno::Any() );
94 break;
97 case VclEventId::ListboxSelect :
99 OSL_FAIL("Debug: Treelist shouldn't use VclEventId::ListboxSelect");
100 break;
103 case VclEventId::ListboxTreeSelect:
105 if ( getListBox() && getListBox()->HasFocus() )
107 AccessibleListBoxEntry* pEntry =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
108 if (pEntry)
110 pEntry->NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
114 break;
115 case VclEventId::ListboxTreeFocus:
117 VclPtr<SvTreeListBox> pBox = getListBox();
118 if( pBox && pBox->HasFocus() )
120 uno::Any aNewValue;
121 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
122 if ( pEntry )
124 AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
125 if (pEntryFocus && pEntryFocus->GetSvLBoxEntry() == pEntry)
127 aNewValue <<= m_xFocusedChild;
128 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, uno::Any(), aNewValue );
129 return ;
132 uno::Any aOldValue;
133 aOldValue <<= m_xFocusedChild;
135 m_xFocusedChild.set(implGetAccessible(*pEntry));
137 aNewValue <<= m_xFocusedChild;
138 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
140 else
142 aNewValue <<= AccessibleStateType::FOCUSED;
143 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), aNewValue );
147 break;
148 case VclEventId::ListboxItemRemoved:
150 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
151 if ( pEntry )
153 RemoveChildEntries(pEntry);
155 else
157 // NULL means Clear()
158 for (auto const& entry : m_mapEntry)
160 uno::Any aNewValue;
161 uno::Any aOldValue;
162 aOldValue <<= uno::Reference<XAccessible>(entry.second);
163 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
165 for (auto const& entry : m_mapEntry)
166 { // release references ...
167 entry.second->dispose();
169 m_mapEntry.clear();
172 break;
174 // #i92103#
175 case VclEventId::ItemExpanded :
176 case VclEventId::ItemCollapsed :
178 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
179 if ( pEntry )
181 Reference<XAccessible> const xChild(implGetAccessible(*pEntry));
182 const short nAccEvent =
183 ( rVclWindowEvent.GetId() == VclEventId::ItemExpanded )
184 ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED
185 : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED;
186 uno::Any aListBoxEntry;
187 aListBoxEntry <<= xChild;
188 NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry );
189 if ( getListBox() && getListBox()->HasFocus() )
191 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry );
195 break;
196 default:
197 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
201 AccessibleListBoxEntry* AccessibleListBox::GetCurEventEntry( const VclWindowEvent& rVclWindowEvent )
203 SvTreeListEntry* pEntry = static_cast< SvTreeListEntry* >( rVclWindowEvent.GetData() );
204 if ( !pEntry )
205 pEntry = getListBox()->GetCurEntry();
207 AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
208 if (pEntryFocus && pEntry && pEntry != pEntryFocus->GetSvLBoxEntry())
210 AccessibleListBoxEntry *const pAccCurOptionEntry = implGetAccessible(*pEntry).get();
211 uno::Any aNewValue;
212 aNewValue <<= uno::Reference<XAccessible>(pAccCurOptionEntry);
213 NotifyAccessibleEvent( AccessibleEventId::CHILD, uno::Any(), aNewValue );//Add
215 return pAccCurOptionEntry;
217 else
219 return pEntryFocus;
223 void AccessibleListBox::RemoveChildEntries(SvTreeListEntry* pEntry)
225 MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry);
226 if ( mi != m_mapEntry.end() )
228 uno::Any aNewValue;
229 uno::Any aOldValue;
230 aOldValue <<= uno::Reference<XAccessible>(mi->second);
231 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
233 m_mapEntry.erase(mi);
236 VclPtr<SvTreeListBox> pBox = getListBox();
237 SvTreeListEntry* pEntryChild = pBox->FirstChild(pEntry);
238 while (pEntryChild)
240 RemoveChildEntries(pEntryChild);
241 pEntryChild = pEntryChild->NextSibling();
246 void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
248 switch ( rVclWindowEvent.GetId() )
250 case VclEventId::WindowShow:
251 case VclEventId::WindowHide:
254 break;
255 default:
257 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
259 break;
264 // XComponent
266 void SAL_CALL AccessibleListBox::disposing()
268 ::osl::MutexGuard aGuard( m_aMutex );
270 m_mapEntry.clear();
271 VCLXAccessibleComponent::disposing();
272 m_xParent = nullptr;
275 // XServiceInfo
277 OUString SAL_CALL AccessibleListBox::getImplementationName()
279 return "com.sun.star.comp.svtools.AccessibleTreeListBox";
282 Sequence< OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames()
284 return {"com.sun.star.accessibility.AccessibleContext",
285 "com.sun.star.accessibility.AccessibleComponent",
286 "com.sun.star.awt.AccessibleTreeListBox"};
289 sal_Bool SAL_CALL AccessibleListBox::supportsService( const OUString& _rServiceName )
291 return cppu::supportsService(this, _rServiceName);
294 // XAccessible
296 Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext( )
298 ensureAlive();
299 return this;
302 // XAccessibleContext
304 sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount( )
306 ::comphelper::OExternalLockGuard aGuard( this );
308 sal_Int32 nCount = 0;
309 VclPtr<SvTreeListBox> pSvTreeListBox = getListBox();
310 if ( pSvTreeListBox )
311 nCount = pSvTreeListBox->GetLevelChildCount( nullptr );
313 return nCount;
316 Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i )
318 ::comphelper::OExternalLockGuard aGuard( this );
320 SvTreeListEntry* pEntry = getListBox()->GetEntry(i);
321 if ( !pEntry )
322 throw IndexOutOfBoundsException();
324 // Solution: Set the parameter of the parent to null to let entry determine the parent by itself
325 //return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
326 //return new AccessibleListBoxEntry( *getListBox(), pEntry, nullptr );
327 return implGetAccessible(*pEntry);
330 Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent( )
332 ::osl::MutexGuard aGuard( m_aMutex );
334 ensureAlive();
335 return m_xParent;
338 sal_Int32 AccessibleListBox::GetRoleType() const
340 sal_Int32 nCase = 0;
341 SvTreeListEntry* pEntry = getListBox()->GetEntry(0);
342 if ( pEntry )
344 if( pEntry->HasChildrenOnDemand() || getListBox()->GetChildCount(pEntry) > 0 )
346 nCase = 1;
347 return nCase;
351 bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
352 if( !(getListBox()->GetTreeFlags() & SvTreeFlags::CHKBTN) )
354 if( bHasButtons )
355 nCase = 1;
357 else
359 if( bHasButtons )
360 nCase = 2;
361 else
362 nCase = 3;
364 return nCase;
367 sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole()
369 ::comphelper::OExternalLockGuard aGuard( this );
371 //o is: return AccessibleRole::TREE;
372 bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
373 if(!bHasButtons && (getListBox()->GetTreeFlags() & SvTreeFlags::CHKBTN))
374 return AccessibleRole::LIST;
375 else
376 if (GetRoleType() == 0)
377 return AccessibleRole::LIST;
378 else
379 return AccessibleRole::TREE;
382 OUString SAL_CALL AccessibleListBox::getAccessibleDescription( )
384 ::comphelper::OExternalLockGuard aGuard( this );
386 return getListBox()->GetAccessibleDescription();
389 OUString SAL_CALL AccessibleListBox::getAccessibleName( )
391 ::comphelper::OExternalLockGuard aGuard( this );
393 return getListBox()->GetAccessibleName();
396 // XAccessibleSelection
398 void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex )
400 ::comphelper::OExternalLockGuard aGuard( this );
402 SvTreeListEntry* pEntry = getListBox()->GetEntry( nChildIndex );
403 if ( !pEntry )
404 throw IndexOutOfBoundsException();
406 getListBox()->Select( pEntry );
409 sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex )
411 ::comphelper::OExternalLockGuard aGuard( this );
413 SvTreeListEntry* pEntry = getListBox()->GetEntry( nChildIndex );
414 if ( !pEntry )
415 throw IndexOutOfBoundsException();
417 return getListBox()->IsSelected( pEntry );
420 void SAL_CALL AccessibleListBox::clearAccessibleSelection( )
422 ::comphelper::OExternalLockGuard aGuard( this );
424 sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
425 for ( sal_Int32 i = 0; i < nCount; ++i )
427 SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
428 if ( getListBox()->IsSelected( pEntry ) )
429 getListBox()->Select( pEntry, false );
433 void SAL_CALL AccessibleListBox::selectAllAccessibleChildren( )
435 ::comphelper::OExternalLockGuard aGuard( this );
437 sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
438 for ( sal_Int32 i = 0; i < nCount; ++i )
440 SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
441 if ( !getListBox()->IsSelected( pEntry ) )
442 getListBox()->Select( pEntry );
446 sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount( )
448 ::comphelper::OExternalLockGuard aGuard( this );
450 return getListBox()->GetSelectionCount();
453 Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
455 ::comphelper::OExternalLockGuard aGuard( this );
457 if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
458 throw IndexOutOfBoundsException();
460 Reference< XAccessible > xChild;
461 sal_Int32 nSelCount= 0;
462 sal_Int32 nCount = getListBox()->GetLevelChildCount( nullptr );
463 for ( sal_Int32 i = 0; i < nCount; ++i )
465 SvTreeListEntry* pEntry = getListBox()->GetEntry( i );
466 if ( getListBox()->IsSelected( pEntry ) )
467 ++nSelCount;
469 if ( nSelCount == ( nSelectedChildIndex + 1 ) )
471 // Solution: Set the parameter of the parent to null to let entry determine the parent by itself
472 //xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
473 //xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, nullptr );
474 xChild = implGetAccessible(*pEntry).get();
475 break;
479 return xChild;
482 void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
484 ::comphelper::OExternalLockGuard aGuard( this );
486 SvTreeListEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
487 if ( !pEntry )
488 throw IndexOutOfBoundsException();
490 getListBox()->Select( pEntry, false );
493 void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
495 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
496 if ( getListBox() && isAlive() )
498 rStateSet.AddState( AccessibleStateType::FOCUSABLE );
499 rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
500 if ( getListBox()->GetSelectionMode() == SelectionMode::Multiple )
501 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
505 rtl::Reference<AccessibleListBoxEntry> AccessibleListBox::implGetAccessible(SvTreeListEntry & rEntry)
507 rtl::Reference<AccessibleListBoxEntry> pAccessible;
508 auto const it = m_mapEntry.find(&rEntry);
509 if (it != m_mapEntry.end())
511 pAccessible = it->second;
513 else
515 pAccessible = new AccessibleListBoxEntry(*getListBox(), rEntry, *this);
516 m_mapEntry.emplace(&rEntry, pAccessible);
518 assert(pAccessible.is());
519 return pAccessible;
522 VclPtr< SvTreeListBox > AccessibleListBox::getListBox() const
524 return GetAs< SvTreeListBox >();
527 }// namespace accessibility
530 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */