From 5a036ee882b46fc77aadfb621ff44d8edeec8b21 Mon Sep 17 00:00:00 2001 From: Norbert Thiebaud Date: Sat, 1 Oct 2011 23:10:45 -0500 Subject: accessibility changes for tree list boxes --- .../accessibility/extended/accessiblelistbox.hxx | 12 ++- .../extended/accessiblelistboxentry.hxx | 4 + .../extended/accessibletablistbox.hxx | 1 + .../extended/accessibletablistboxtable.hxx | 1 + .../source/extended/accessiblelistbox.cxx | 119 +++++++++++++++++++-- .../source/extended/accessiblelistboxentry.cxx | 14 +++ .../source/extended/accessibletablistboxtable.cxx | 56 ++++++++++ svtools/source/contnr/svtreebx.cxx | 5 +- vcl/inc/vcl/vclevent.hxx | 5 +- 9 files changed, 203 insertions(+), 14 deletions(-) diff --git a/accessibility/inc/accessibility/extended/accessiblelistbox.hxx b/accessibility/inc/accessibility/extended/accessiblelistbox.hxx index 9e81e7eed7d4..df10540d38f9 100644 --- a/accessibility/inc/accessibility/extended/accessiblelistbox.hxx +++ b/accessibility/inc/accessibility/extended/accessiblelistbox.hxx @@ -35,10 +35,12 @@ #include #include +#include // class AccessibleListBox ----------------------------------------------- class SvTreeListBox; +class SvLBoxEntry; //........................................................................ namespace accessibility @@ -53,11 +55,13 @@ namespace accessibility class AccessibleListBox :public AccessibleListBox_BASE ,public VCLXAccessibleComponent { - protected: - - ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xParent; + private: + typedef std::map< SvLBoxEntry*, ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > > MAP_ENTRY; + MAP_ENTRY m_mapEntry; + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xFocusedChild; protected: + virtual ~AccessibleListBox(); // OComponentHelper overridables @@ -70,6 +74,8 @@ namespace accessibility virtual void FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ); SvTreeListBox* getListBox() const; + void RemoveChildEntries(SvLBoxEntry* entry); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xParent; public: /** OAccessibleBase needs a valid view diff --git a/accessibility/inc/accessibility/extended/accessiblelistboxentry.hxx b/accessibility/inc/accessibility/extended/accessiblelistboxentry.hxx index 4521c0e0d03e..d88d15a611c9 100644 --- a/accessibility/inc/accessibility/extended/accessiblelistboxentry.hxx +++ b/accessibility/inc/accessibility/extended/accessiblelistboxentry.hxx @@ -86,6 +86,7 @@ namespace accessibility /** The treelistbox control */ SvTreeListBox* m_pListBox; ::std::deque< sal_Int32 > m_aEntryPath; + SvLBoxEntry* m_pSvLBoxEntry; protected: /// client id in the AccessibleEventNotifier queue @@ -103,6 +104,8 @@ namespace accessibility Rectangle GetBoundingBox() throw ( ::com::sun::star::lang::DisposedException ); Rectangle GetBoundingBoxOnScreen() throw ( ::com::sun::star::lang::DisposedException ); void EnsureIsAlive() const throw ( ::com::sun::star::lang::DisposedException ); + void NotifyAccessibleEvent( sal_Int16 _nEventId, const ::com::sun::star::uno::Any& _aOldValue, + const ::com::sun::star::uno::Any& _aNewValue ); protected: virtual ~AccessibleListBoxEntry(); @@ -131,6 +134,7 @@ namespace accessibility AccessibleListBoxEntry( SvTreeListBox& _rListBox, SvLBoxEntry* _pEntry, const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _xParent ); + SvLBoxEntry* GetSvLBoxEntry() const { return m_pSvLBoxEntry; } protected: // XTypeProvider diff --git a/accessibility/inc/accessibility/extended/accessibletablistbox.hxx b/accessibility/inc/accessibility/extended/accessibletablistbox.hxx index 4e6f03af3c9b..f3cdcea59a38 100644 --- a/accessibility/inc/accessibility/extended/accessibletablistbox.hxx +++ b/accessibility/inc/accessibility/extended/accessibletablistbox.hxx @@ -53,6 +53,7 @@ class AccessibleTabListBox { private: SvHeaderTabListBox* m_pTabListBox; + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xCurChild; public: /** ctor() diff --git a/accessibility/inc/accessibility/extended/accessibletablistboxtable.hxx b/accessibility/inc/accessibility/extended/accessibletablistboxtable.hxx index 153dc76f2a65..2af914256bcc 100644 --- a/accessibility/inc/accessibility/extended/accessibletablistboxtable.hxx +++ b/accessibility/inc/accessibility/extended/accessibletablistboxtable.hxx @@ -47,6 +47,7 @@ class AccessibleTabListBoxTable : public AccessibleBrowseBoxTable, public Access { private: SvHeaderTabListBox* m_pTabListBox; + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > m_xCurChild; void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ); DECL_LINK( WindowEventListener, VclSimpleEvent* ); diff --git a/accessibility/source/extended/accessiblelistbox.cxx b/accessibility/source/extended/accessiblelistbox.cxx index 113041a3a7ed..7deba740b43a 100644 --- a/accessibility/source/extended/accessiblelistbox.cxx +++ b/accessibility/source/extended/accessiblelistbox.cxx @@ -117,19 +117,103 @@ namespace accessibility // 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() ); + OSL_ASSERT(0 && "Debug: Treelist shouldn't use VCLEVENT_LISTBOX_SELECT"); + } + case VCLEVENT_LISTBOX_TREESELECT: + { if ( getListBox() && getListBox()->HasFocus() ) { + AccessibleListBoxEntry* pEntry =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get()); + if (pEntry) + { + pEntry->NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); + } + } + break; + } + case VCLEVENT_LISTBOX_TREEFOCUS: + { + SvTreeListBox* pBox = getListBox(); + sal_Bool bNeedFocus = sal_False; + if (pBox) + { + /* + // MT: ImplGetAppSVData shouldn't be exported from VCL. + // In which scenario is this needed? + // If needed, we need to find an other solution + Window* pParent = ((Window*)pBox)->GetParent(); + if (pParent && pParent->GetType() == WINDOW_FLOATINGWINDOW) + { + ImplSVData* pSVData = ImplGetAppSVData(); + if (pSVData && pSVData->maWinData.mpFirstFloat == (FloatingWindow*)pParent) + bNeedFocus = sal_True; + } + */ + } + if( pBox && (pBox->HasFocus() || bNeedFocus) ) + { + uno::Any aOldValue, aNewValue; SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); if ( pEntry ) { - Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this ); - uno::Any aOldValue, aNewValue; - aNewValue <<= xChild; + AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get()); + if (pEntryFocus && pEntryFocus->GetSvLBoxEntry() == pEntry) + { + aOldValue <<= uno::Any(); + aNewValue <<= m_xFocusedChild; + NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); + return ; + } + + aOldValue <<= m_xFocusedChild; + + MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry); + if(mi != m_mapEntry.end()) + { + OSL_ASSERT(mi->second.get() != NULL); + m_xFocusedChild = mi->second; + } + else + { + AccessibleListBoxEntry *pEntNew = new AccessibleListBoxEntry( *getListBox(), pEntry, NULL ); + m_xFocusedChild = pEntNew; + m_mapEntry.insert(MAP_ENTRY::value_type(pEntry,pEntNew)); + } + + aNewValue <<= m_xFocusedChild; NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); } + else + { + aOldValue <<= uno::Any(); + aNewValue <<= AccessibleStateType::FOCUSED; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } } break; + } + case VCLEVENT_LISTBOX_ITEMREMOVED: + { + SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); + if ( pEntry ) + { + RemoveChildEntries(pEntry); + } + else + { + // NULL means Clear() + MAP_ENTRY::iterator mi = m_mapEntry.begin(); + for ( ; mi != m_mapEntry.end() ; ++mi) + { + uno::Any aNewValue; + uno::Any aOldValue; + aOldValue <<= mi->second; + NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); + } + m_mapEntry.clear(); + } + break; + } // #i92103# case VCLEVENT_ITEM_EXPANDED : @@ -155,7 +239,6 @@ namespace accessibility } break; } - } default: VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent); } @@ -169,13 +252,13 @@ namespace accessibility case VCLEVENT_WINDOW_SHOW: case VCLEVENT_WINDOW_HIDE: { + break; } - break; default: { VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent ); + break; } - break; } } @@ -186,6 +269,7 @@ namespace accessibility { ::osl::MutexGuard aGuard( m_aMutex ); + m_mapEntry.clear(); VCLXAccessibleComponent::disposing(); m_xParent = NULL; } @@ -425,6 +509,27 @@ namespace accessibility } } + void AccessibleListBox::RemoveChildEntries(SvLBoxEntry* pEntry) + { + MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry); + if ( mi != m_mapEntry.end() ) + { + uno::Any aNewValue; + uno::Any aOldValue; + aOldValue <<= mi->second; + NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); + + m_mapEntry.erase(mi); + } + + SvTreeListBox* pBox = getListBox(); + SvLBoxEntry* pEntryChild = pBox->FirstChild(pEntry); + while (pEntryChild) + { + RemoveChildEntries(pEntryChild); + pEntryChild = pBox->NextSibling(pEntryChild); + } + } //........................................................................ }// namespace accessibility diff --git a/accessibility/source/extended/accessiblelistboxentry.cxx b/accessibility/source/extended/accessiblelistboxentry.cxx index 27390c51ce1c..6bb615f0d87d 100644 --- a/accessibility/source/extended/accessiblelistboxentry.cxx +++ b/accessibility/source/extended/accessiblelistboxentry.cxx @@ -84,6 +84,7 @@ namespace accessibility AccessibleListBoxEntry_BASE ( m_aMutex ), ListBoxAccessibleBase( _rListBox ), + m_pSvLBoxEntry ( _pEntry), m_nClientId ( 0 ), m_aParent ( _xParent ) @@ -105,6 +106,19 @@ namespace accessibility } } + void AccessibleListBoxEntry::NotifyAccessibleEvent( sal_Int16 _nEventId, + const ::com::sun::star::uno::Any& _aOldValue, + const ::com::sun::star::uno::Any& _aNewValue ) + { + Reference< uno::XInterface > xSource( *this ); + AccessibleEventObject aEventObj( xSource, _nEventId, _aNewValue, _aOldValue ); + + if (m_nClientId) + { + comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEventObj ); + } + } + // ----------------------------------------------------------------------------- Rectangle AccessibleListBoxEntry::GetBoundingBox_Impl() const { diff --git a/accessibility/source/extended/accessibletablistboxtable.cxx b/accessibility/source/extended/accessibletablistboxtable.cxx index 7374cc020cf6..79695d73cbe1 100644 --- a/accessibility/source/extended/accessibletablistboxtable.cxx +++ b/accessibility/source/extended/accessibletablistboxtable.cxx @@ -148,6 +148,62 @@ namespace accessibility } break; } + case VCLEVENT_WINDOW_GETFOCUS : + { + uno::Any aOldValue, aNewValue; + aNewValue <<= AccessibleStateType::FOCUSED; + commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue ); + break; + } + case VCLEVENT_WINDOW_LOSEFOCUS : + { + uno::Any aOldValue, aNewValue; + aOldValue <<= AccessibleStateType::FOCUSED; + commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue ); + break; + } + case VCLEVENT_LISTBOX_TREESELECT: + { + SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); + if (pEntry) + { + sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry ); + Reference< XAccessible > xChild = m_pTabListBox->CreateAccessibleCell( nRow, m_pTabListBox->GetCurrColumn() ); + TriState eState = STATE_DONTKNOW; + 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 VCLEVENT_LISTBOX_TREEFOCUS: + { + if ( m_pTabListBox && m_pTabListBox->HasFocus() ) + { + uno::Any aOldValue, aNewValue; + SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( 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 VCLEVENT_CHECKBOX_TOGGLE : { diff --git a/svtools/source/contnr/svtreebx.cxx b/svtools/source/contnr/svtreebx.cxx index 1730d90bd66f..329b5ded69ef 100644 --- a/svtools/source/contnr/svtreebx.cxx +++ b/svtools/source/contnr/svtreebx.cxx @@ -760,8 +760,9 @@ void SvTreeListBox::GetFocus() SvLBoxEntry* pEntry = FirstSelected(); if ( pEntry ) - pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); - + { + pImp->CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pEntry ); + } } void SvTreeListBox::LoseFocus() diff --git a/vcl/inc/vcl/vclevent.hxx b/vcl/inc/vcl/vclevent.hxx index 9181fce7b34b..b3420c9ca952 100644 --- a/vcl/inc/vcl/vclevent.hxx +++ b/vcl/inc/vcl/vclevent.hxx @@ -159,7 +159,9 @@ namespace com { namespace sun { namespace star { #define VCLEVENT_ITEM_COLLAPSED 1175 #define VCLEVENT_DROPDOWN_PRE_OPEN 1176 #define VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED 1177 -#define VCLEVENT_LISTBOX_CLEAR 1178 +#define VCLEVENT_LISTBOX_TREEFOCUS 1178 +#define VCLEVENT_LISTBOX_TREESELECT 1179 +#define VCLEVENT_LISTBOX_FOCUSITEMCHANGED 1180 // VclMenuEvent #define VCLEVENT_MENU_ACTIVATE 1200 @@ -193,7 +195,6 @@ namespace com { namespace sun { namespace star { #define VCLEVENT_TOOLBOX_BUTTONSTATECHANGED 1223 // pData = itempos #define VCLEVENT_TABLECELL_NAMECHANGED 1224 // pData = struct(Entry, Column, oldText) #define VCLEVENT_TABLEROW_SELECT 1225 -#define VCLEVENT_LISTBOX_FOCUSITEMCHANGED 1226 class VCL_DLLPUBLIC VclSimpleEvent { -- cgit