CppunitTest_sc_tiledrendering2: move to tiledrendering folder
[LibreOffice.git] / accessibility / source / standard / accessiblemenubasecomponent.cxx
blob5c9e1e47b637d920e1f502c209293ff3682e3dd8
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 <standard/accessiblemenubasecomponent.hxx>
21 #include <standard/vclxaccessiblemenu.hxx>
22 #include <standard/vclxaccessiblemenuitem.hxx>
23 #include <standard/vclxaccessiblemenuseparator.hxx>
24 #include <toolkit/helper/vclunohelper.hxx>
26 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
27 #include <com/sun/star/accessibility/AccessibleRole.hpp>
28 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
29 #include <comphelper/accessiblecontexthelper.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <o3tl/safeint.hxx>
32 #include <vcl/menu.hxx>
33 #include <vcl/vclevent.hxx>
35 #include <array>
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::lang;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::accessibility;
41 using namespace ::comphelper;
44 // OAccessibleMenuBaseComponent
47 OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
48 :m_pMenu( pMenu )
49 ,m_bEnabled( false )
50 ,m_bFocused( false )
51 ,m_bVisible( false )
52 ,m_bSelected( false )
53 ,m_bChecked( false )
55 if ( m_pMenu )
57 m_aAccessibleChildren.assign( m_pMenu->GetItemCount(), rtl::Reference< OAccessibleMenuItemComponent >() );
58 m_pMenu->AddEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
63 OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
65 if ( m_pMenu )
66 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
70 bool OAccessibleMenuBaseComponent::IsEnabled()
72 return false;
76 bool OAccessibleMenuBaseComponent::IsFocused()
78 return false;
82 bool OAccessibleMenuBaseComponent::IsVisible()
84 return false;
88 bool OAccessibleMenuBaseComponent::IsSelected()
90 return false;
94 bool OAccessibleMenuBaseComponent::IsChecked()
96 return false;
100 void OAccessibleMenuBaseComponent::SetStates()
102 m_bEnabled = IsEnabled();
103 m_bFocused = IsFocused();
104 m_bVisible = IsVisible();
105 m_bSelected = IsSelected();
106 m_bChecked = IsChecked();
110 void OAccessibleMenuBaseComponent::SetEnabled( bool bEnabled )
112 if ( m_bEnabled == bEnabled )
113 return;
115 sal_Int64 nStateType=AccessibleStateType::ENABLED;
116 if (IsMenuHideDisabledEntries())
118 nStateType = AccessibleStateType::VISIBLE;
120 std::array<Any, 2> aOldValue, aNewValue;
121 if ( m_bEnabled )
123 aOldValue[0] <<= AccessibleStateType::SENSITIVE;
124 aOldValue[1] <<= nStateType;
126 else
128 aNewValue[0] <<= nStateType;
129 aNewValue[1] <<= AccessibleStateType::SENSITIVE;
131 m_bEnabled = bEnabled;
132 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
133 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
137 void OAccessibleMenuBaseComponent::SetFocused( bool bFocused )
139 if ( m_bFocused != bFocused )
141 Any aOldValue, aNewValue;
142 if ( m_bFocused )
143 aOldValue <<= AccessibleStateType::FOCUSED;
144 else
145 aNewValue <<= AccessibleStateType::FOCUSED;
146 m_bFocused = bFocused;
147 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
152 void OAccessibleMenuBaseComponent::SetVisible( bool bVisible )
154 if ( m_bVisible != bVisible )
156 Any aOldValue, aNewValue;
157 if ( m_bVisible )
158 aOldValue <<= AccessibleStateType::VISIBLE;
159 else
160 aNewValue <<= AccessibleStateType::VISIBLE;
161 m_bVisible = bVisible;
162 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
167 void OAccessibleMenuBaseComponent::SetSelected( bool bSelected )
169 if ( m_bSelected != bSelected )
171 Any aOldValue, aNewValue;
172 if ( m_bSelected )
173 aOldValue <<= AccessibleStateType::SELECTED;
174 else
175 aNewValue <<= AccessibleStateType::SELECTED;
176 m_bSelected = bSelected;
177 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
182 void OAccessibleMenuBaseComponent::SetChecked( bool bChecked )
184 if ( m_bChecked != bChecked )
186 Any aOldValue, aNewValue;
187 if ( m_bChecked )
188 aOldValue <<= AccessibleStateType::CHECKED;
189 else
190 aNewValue <<= AccessibleStateType::CHECKED;
191 m_bChecked = bChecked;
192 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
197 void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, bool bEnabled )
199 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
201 rtl::Reference< OAccessibleMenuBaseComponent > xChild( m_aAccessibleChildren[i] );
202 if ( xChild.is() )
203 xChild->SetEnabled( bEnabled );
208 void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, bool bFocused )
210 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
212 rtl::Reference< OAccessibleMenuBaseComponent > xChild( m_aAccessibleChildren[i] );
213 if ( xChild.is() )
214 xChild->SetFocused( bFocused );
219 void OAccessibleMenuBaseComponent::UpdateVisible()
221 SetVisible( IsVisible() );
222 for (const rtl::Reference<OAccessibleMenuItemComponent>& xChild : m_aAccessibleChildren)
224 if ( xChild.is() )
225 xChild->SetVisible( xChild->IsVisible() );
230 void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, bool bSelected )
232 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
234 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
236 rtl::Reference< OAccessibleMenuBaseComponent > xChild( m_aAccessibleChildren[i] );
237 if ( xChild.is() )
238 xChild->SetSelected( bSelected );
243 void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, bool bChecked )
245 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
247 rtl::Reference< OAccessibleMenuBaseComponent > xChild( m_aAccessibleChildren[i] );
248 if ( xChild.is() )
249 xChild->SetChecked( bChecked );
254 void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
256 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
258 rtl::Reference< OAccessibleMenuBaseComponent > xChild( m_aAccessibleChildren[i] );
259 if ( xChild.is() )
261 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
262 if ( pComp )
263 pComp->SetAccessibleName( pComp->GetAccessibleName() );
268 void OAccessibleMenuBaseComponent::UpdateItemRole(sal_Int32 i)
270 if (i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size())
271 return;
273 rtl::Reference<OAccessibleMenuItemComponent> xChild(m_aAccessibleChildren[i]);
274 if (!xChild.is())
275 return;
277 xChild->NotifyAccessibleEvent(AccessibleEventId::ROLE_CHANGED, Any(), Any());
280 void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
282 if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
284 rtl::Reference< OAccessibleMenuItemComponent > xChild( m_aAccessibleChildren[i] );
285 if ( xChild.is() )
286 xChild->SetItemText( xChild->GetItemText() );
291 sal_Int64 OAccessibleMenuBaseComponent::GetChildCount() const
293 return m_aAccessibleChildren.size();
297 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int64 i )
299 rtl::Reference< OAccessibleMenuItemComponent > xChild = m_aAccessibleChildren[i];
300 if ( !xChild.is() )
302 if ( m_pMenu )
304 // create a new child
305 if ( m_pMenu->GetItemType( static_cast<sal_uInt16>(i) ) == MenuItemType::SEPARATOR )
307 xChild = new VCLXAccessibleMenuSeparator(m_pMenu, static_cast<sal_uInt16>(i));
309 else
311 PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( static_cast<sal_uInt16>(i) ) );
312 if ( pPopupMenu )
314 xChild = new VCLXAccessibleMenu(m_pMenu, static_cast<sal_uInt16>(i), pPopupMenu);
315 pPopupMenu->SetAccessible(xChild);
317 else
319 xChild = new VCLXAccessibleMenuItem(m_pMenu, static_cast<sal_uInt16>(i));
323 // set states
324 xChild->SetStates();
326 // insert into menu item list
327 m_aAccessibleChildren[i] = xChild;
331 return xChild;
335 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
337 for ( sal_Int64 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
339 Reference< XAccessible > xAcc = getAccessibleChild( i );
340 if ( xAcc.is() )
342 Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
343 if ( xComp.is() )
345 tools::Rectangle aRect = VCLUnoHelper::ConvertToVCLRect(xComp->getBounds());
346 Point aPos = VCLUnoHelper::ConvertToVCLPoint(rPoint);
347 if ( aRect.Contains( aPos ) )
349 return xAcc;
355 return nullptr;
359 void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
361 if ( i < 0 )
362 return;
364 if ( o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
365 i = m_aAccessibleChildren.size();
367 // insert entry in child list
368 m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, rtl::Reference< OAccessibleMenuItemComponent >() );
370 // update item position of accessible children
371 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
373 rtl::Reference< OAccessibleMenuItemComponent > xAcc( m_aAccessibleChildren[j] );
374 if ( xAcc.is() )
375 xAcc->SetItemPos( static_cast<sal_uInt16>(j) );
378 // send accessible child event
379 Reference< XAccessible > xChild( GetChild( i ) );
380 if ( xChild.is() )
382 Any aOldValue, aNewValue;
383 aNewValue <<= xChild;
384 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
389 void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
391 if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
392 return;
394 // keep the accessible of the removed item
395 rtl::Reference< OAccessibleMenuItemComponent > xChild( m_aAccessibleChildren[i] );
397 // remove entry in child list
398 m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
400 // update item position of accessible children
401 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
403 rtl::Reference< OAccessibleMenuItemComponent > xAcc( m_aAccessibleChildren[j] );
404 if ( xAcc.is() )
405 xAcc->SetItemPos( static_cast<sal_uInt16>(j) );
408 // send accessible child event
409 if ( xChild.is() )
411 Any aOldValue, aNewValue;
412 aOldValue <<= uno::Reference<XAccessible>(xChild);
413 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
415 xChild->dispose();
420 bool OAccessibleMenuBaseComponent::IsHighlighted()
422 return false;
426 bool OAccessibleMenuBaseComponent::IsChildHighlighted()
428 bool bChildHighlighted = false;
430 for (const rtl::Reference<OAccessibleMenuItemComponent>& xChild : m_aAccessibleChildren)
432 if ( xChild.is() && xChild->IsHighlighted() )
434 bChildHighlighted = true;
435 break;
439 return bChildHighlighted;
443 void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
445 // open the menu
446 if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
447 Click();
449 // highlight the child
450 if ( m_pMenu )
451 m_pMenu->HighlightItem( static_cast<sal_uInt16>(i) );
455 void OAccessibleMenuBaseComponent::DeSelectAll()
457 if ( m_pMenu )
458 m_pMenu->DeHighlight();
462 bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
464 bool bSelected = false;
466 if ( m_pMenu && m_pMenu->IsHighlighted( static_cast<sal_uInt16>(i) ) )
467 bSelected = true;
469 return bSelected;
473 void OAccessibleMenuBaseComponent::Click()
478 bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
480 return false;
484 IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclMenuEvent&, rEvent, void )
486 OSL_ENSURE( rEvent.GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
487 ProcessMenuEvent( rEvent );
491 void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
493 sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
495 switch ( rVclMenuEvent.GetId() )
497 case VclEventId::MenuShow:
498 case VclEventId::MenuHide:
500 UpdateVisible();
502 break;
503 case VclEventId::MenuHighlight:
505 SetFocused( false );
506 UpdateFocused( nItemPos, true );
507 UpdateSelected( nItemPos, true );
509 break;
510 case VclEventId::MenuDehighlight:
512 UpdateFocused( nItemPos, false );
513 UpdateSelected( nItemPos, false );
515 break;
516 case VclEventId::MenuSubmenuActivate:
519 break;
520 case VclEventId::MenuSubmenuDeactivate:
522 UpdateFocused( nItemPos, true );
524 break;
525 case VclEventId::MenuEnable:
527 UpdateEnabled( nItemPos, true );
529 break;
530 case VclEventId::MenuDisable:
532 UpdateEnabled( nItemPos, false );
534 break;
535 case VclEventId::MenuSubmenuChanged:
537 RemoveChild( nItemPos );
538 InsertChild( nItemPos );
540 break;
541 case VclEventId::MenuInsertItem:
543 InsertChild( nItemPos );
545 break;
546 case VclEventId::MenuRemoveItem:
548 RemoveChild( nItemPos );
550 break;
551 case VclEventId::MenuAccessibleNameChanged:
553 UpdateAccessibleName( nItemPos );
555 break;
556 case VclEventId::MenuItemRoleChanged:
558 UpdateItemRole(nItemPos);
560 break;
561 case VclEventId::MenuItemTextChanged:
563 UpdateAccessibleName( nItemPos );
564 UpdateItemText( nItemPos );
566 break;
567 case VclEventId::MenuItemChecked:
569 UpdateChecked( nItemPos, true );
571 break;
572 case VclEventId::MenuItemUnchecked:
574 UpdateChecked( nItemPos, false );
576 break;
577 case VclEventId::ObjectDying:
579 if ( m_pMenu )
581 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
583 m_pMenu = nullptr;
585 // dispose all menu items
586 for (const rtl::Reference<OAccessibleMenuItemComponent>& xComponent : m_aAccessibleChildren)
588 if ( xComponent.is() )
589 xComponent->dispose();
591 m_aAccessibleChildren.clear();
594 break;
595 default:
598 break;
603 // XComponent
606 void OAccessibleMenuBaseComponent::disposing()
608 OAccessibleExtendedComponentHelper::disposing();
610 if ( !m_pMenu )
611 return;
613 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
615 m_pMenu = nullptr;
617 // dispose all menu items
618 for (const rtl::Reference<OAccessibleMenuItemComponent>& xComponent : m_aAccessibleChildren)
620 if ( xComponent.is() )
621 xComponent->dispose();
623 m_aAccessibleChildren.clear();
627 // XServiceInfo
630 sal_Bool OAccessibleMenuBaseComponent::supportsService( const OUString& rServiceName )
632 return cppu::supportsService(this, rServiceName);
636 // XAccessible
639 Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext( )
641 OExternalLockGuard aGuard( this );
643 return this;
647 // XAccessibleContext
650 sal_Int64 OAccessibleMenuBaseComponent::getAccessibleStateSet( )
652 OExternalLockGuard aGuard( this );
654 sal_Int64 nStateSet = 0;
656 if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
658 FillAccessibleStateSet( nStateSet );
660 else
662 nStateSet |= AccessibleStateType::DEFUNC;
665 return nStateSet;
669 bool OAccessibleMenuBaseComponent::IsMenuHideDisabledEntries()
671 return false;
674 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */