diff --git a/checkin_notes b/checkin_notes index 5d7e07baca..518ca36231 100644 --- a/checkin_notes +++ b/checkin_notes @@ -586,3 +586,12 @@ David 19 Jan 2010 work_fetch.cpp,h html/user/ language_select.php + +Charlie 21 Jan 2010 + - MGR: Implement Mac accessibility for Event Log. + + clientgui/ + BOINCListCtrl.h + DlgEventLogListCtrl.cpp, .h + mac/ + MacAccessiblity.cpp, .h diff --git a/clientgui/BOINCListCtrl.h b/clientgui/BOINCListCtrl.h index 13a58e9053..26dd551aac 100644 --- a/clientgui/BOINCListCtrl.h +++ b/clientgui/BOINCListCtrl.h @@ -42,6 +42,10 @@ #include "wx/generic/listctrl.h" #endif +#ifdef __WXMAC__ +#include "macAccessiblity.h" +#endif + class CBOINCBaseView; class CDrawProgressBarEvent; @@ -94,11 +98,9 @@ private: #ifdef __WXMAC__ void SetupMacAccessibilitySupport(); void RemoveMacAccessibilitySupport(); - CBOINCBaseView* GetParentView() { return m_pParentView; } - - HIViewRef m_headerView; - HIViewRef m_bodyView; + struct ListAccessData accessibilityHandlerData; + EventHandlerRef m_pHeaderAccessibilityEventHandlerRef; EventHandlerRef m_pBodyAccessibilityEventHandlerRef; #endif diff --git a/clientgui/DlgEventLogListCtrl.cpp b/clientgui/DlgEventLogListCtrl.cpp index c7eea6f822..2bbe5f910e 100644 --- a/clientgui/DlgEventLogListCtrl.cpp +++ b/clientgui/DlgEventLogListCtrl.cpp @@ -33,20 +33,32 @@ #include "DlgEventLog.h" -IMPLEMENT_DYNAMIC_CLASS(CDlgEventLogListCtrl, wxListView) +IMPLEMENT_DYNAMIC_CLASS(CDlgEventLogListCtrl, LISTCTRL_BASE) CDlgEventLogListCtrl::CDlgEventLogListCtrl() {} CDlgEventLogListCtrl::CDlgEventLogListCtrl(CDlgEventLog* pView, wxWindowID iListWindowID, wxInt32 iListWindowFlags) - :wxListView(pView, iListWindowID, wxDefaultPosition, wxSize(640,480), iListWindowFlags) + : LISTCTRL_BASE(pView, iListWindowID, wxDefaultPosition, wxSize(640,480), iListWindowFlags) { m_pParentView = pView; m_bIsSingleSelection = (iListWindowFlags & wxLC_SINGLE_SEL) ? true : false ; + +#ifdef __WXMAC__ + SetupMacAccessibilitySupport(); +#endif } +#ifdef __WXMAC__ +CDlgEventLogListCtrl::~CDlgEventLogListCtrl() +{ + RemoveMacAccessibilitySupport(); +} +#endif + + wxString CDlgEventLogListCtrl::OnGetItemText(long item, long column) const { wxASSERT(m_pParentView); wxASSERT(wxDynamicCast(m_pParentView, CDlgEventLog)); diff --git a/clientgui/DlgEventLogListCtrl.h b/clientgui/DlgEventLogListCtrl.h index 0a0c6d2709..d5d30d92bc 100644 --- a/clientgui/DlgEventLogListCtrl.h +++ b/clientgui/DlgEventLogListCtrl.h @@ -22,17 +22,29 @@ #pragma interface "DlgEventLogListCtrl.cpp" #endif +#ifdef __WXMAC__ +#include "macAccessiblity.h" +#define LISTCTRL_BASE wxGenericListCtrl +#else +#define LISTCTRL_BASE wxListView +#endif + #define DEFAULT_LIST_MULTI_SEL_FLAGS wxLC_REPORT | wxLC_VIRTUAL class CDlgEventLog; -class CDlgEventLogListCtrl : public wxListView { +class CDlgEventLogListCtrl : public LISTCTRL_BASE +{ DECLARE_DYNAMIC_CLASS(CDlgEventLogListCtrl) public: CDlgEventLogListCtrl(); CDlgEventLogListCtrl(CDlgEventLog* pView, wxWindowID iListWindowID, int iListWindowFlags); +#ifdef __WXMAC__ + ~CDlgEventLogListCtrl(); +#endif + private: virtual wxString OnGetItemText(long item, long column) const; @@ -43,6 +55,16 @@ private: bool m_bIsSingleSelection; CDlgEventLog* m_pParentView; + +#ifdef __WXMAC__ + void SetupMacAccessibilitySupport(); + void RemoveMacAccessibilitySupport(); + + struct ListAccessData accessibilityHandlerData; + + EventHandlerRef m_pHeaderAccessibilityEventHandlerRef; + EventHandlerRef m_pBodyAccessibilityEventHandlerRef; +#endif }; #endif diff --git a/clientgui/mac/MacAccessiblity.cpp b/clientgui/mac/MacAccessiblity.cpp index 79f6540b42..5611dc0246 100755 --- a/clientgui/mac/MacAccessiblity.cpp +++ b/clientgui/mac/MacAccessiblity.cpp @@ -23,9 +23,11 @@ #include "BOINCGUIApp.h" #include "BOINCBaseFrame.h" #include "BOINCBaseView.h" +#include "DlgEventLog.h" #include "MainDocument.h" #include "AdvancedFrame.h" #include "BOINCListCtrl.h" +#include "DlgEventLogListCtrl.h" #include "ProjectListCtrl.h" #include "ViewStatistics.h" #include "wxPieCtrl.h" @@ -98,20 +100,29 @@ pascal OSStatus PieCtrlAccessibilityEventHandler( EventHandlerCallRef inHandlerC void CBOINCListCtrl::SetupMacAccessibilitySupport() { #if !USE_NATIVE_LISTCONTROL - HIViewRef listControlView; - OSErr err; + HIViewRef listControlView; + HIViewRef headerView; + HIViewRef bodyView; + OSErr err; listControlView = (HIViewRef)GetHandle(); - m_headerView = HIViewGetFirstSubview(listControlView); - m_bodyView = HIViewGetNextView(m_headerView); - err = HIViewSetEnabled(m_headerView, true); - err = InstallHIObjectEventHandler((HIObjectRef)m_headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler), + headerView = HIViewGetFirstSubview(listControlView); + bodyView = HIViewGetNextView(headerView); + err = HIViewSetEnabled(headerView, true); + + accessibilityHandlerData.pList = (wxGenericListCtrl*)this; + accessibilityHandlerData.pView = m_pParentView; + accessibilityHandlerData.headerView = headerView; + accessibilityHandlerData.bodyView = bodyView; + accessibilityHandlerData.pEventLog = NULL; + + err = InstallHIObjectEventHandler((HIObjectRef)headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler), sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents, - this, &m_pHeaderAccessibilityEventHandlerRef); + &accessibilityHandlerData, &m_pHeaderAccessibilityEventHandlerRef); - err = InstallHIObjectEventHandler((HIObjectRef)m_bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler), + err = InstallHIObjectEventHandler((HIObjectRef)bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler), sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents, - this, &m_pBodyAccessibilityEventHandlerRef); + &accessibilityHandlerData, &m_pBodyAccessibilityEventHandlerRef); #endif } @@ -124,6 +135,43 @@ void CBOINCListCtrl::RemoveMacAccessibilitySupport() { } +void CDlgEventLogListCtrl::SetupMacAccessibilitySupport() { +#if !USE_NATIVE_LISTCONTROL + HIViewRef listControlView; + HIViewRef headerView; + HIViewRef bodyView; + OSErr err; + + listControlView = (HIViewRef)GetHandle(); + headerView = HIViewGetFirstSubview(listControlView); + bodyView = HIViewGetNextView(headerView); + err = HIViewSetEnabled(headerView, true); + + accessibilityHandlerData.pList = (wxGenericListCtrl*)this; + accessibilityHandlerData.pView = NULL; + accessibilityHandlerData.headerView = headerView; + accessibilityHandlerData.bodyView = bodyView; + accessibilityHandlerData.pEventLog = m_pParentView; + + err = InstallHIObjectEventHandler((HIObjectRef)headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler), + sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents, + &accessibilityHandlerData, &m_pHeaderAccessibilityEventHandlerRef); + + err = InstallHIObjectEventHandler((HIObjectRef)bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler), + sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents, + &accessibilityHandlerData, &m_pBodyAccessibilityEventHandlerRef); +#endif +} + + +void CDlgEventLogListCtrl::RemoveMacAccessibilitySupport() { +#if !USE_NATIVE_LISTCONTROL + ::RemoveEventHandler(m_pHeaderAccessibilityEventHandlerRef); + ::RemoveEventHandler(m_pBodyAccessibilityEventHandlerRef); +#endif +} + + void CProjectListCtrlAccessible::SetupMacAccessibilitySupport() { OSErr err; @@ -242,7 +290,11 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe const UInt32 eventClass = GetEventClass(inEvent); const UInt32 eventKind = GetEventKind(inEvent); OSStatus err; - CBOINCListCtrl* pList = (CBOINCListCtrl*)pData; + wxGenericListCtrl* pList = ((struct ListAccessData*)pData)->pList; + CBOINCBaseView* pView = ((struct ListAccessData*)pData)->pView; + HIViewRef headerView = ((struct ListAccessData*)pData)->headerView; + HIViewRef bodyView = ((struct ListAccessData*)pData)->bodyView; + CDlgEventLog* pEventLog = ((struct ListAccessData*)pData)->pEventLog; if (eventClass != kEventClassAccessibility) { return eventNotHandledErr; @@ -253,7 +305,6 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe UInt64 outIdentifier = 0; SInt32 row = 0; SInt32 col = 0; - CBOINCBaseView* pView = NULL; HIObjectRef obj = NULL; err = GetEventParameter (inEvent, kEventParamAccessibleObject, @@ -262,8 +313,6 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe AXUIElementGetIdentifier( element, &inIdentifier ); obj = AXUIElementGetHIObject(element); - - pView = pList->GetParentView(); if (inIdentifier) { if (! isHeader) { @@ -305,7 +354,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe } if (isHeader) { - if ((p.y > 0) || (p.y < -pList->GetHeaderHeight())) { + if ((p.y > 0) || (p.y < -pList->m_headerHeight)) { return noErr; } outIdentifier = col+1; @@ -469,7 +518,13 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe str = _("blank"); } else { str = _("list of "); - str += pView->GetViewDisplayName(); + if (pEventLog) { + str += _("events"); + } else { + if (pView) { + str += pView->GetViewDisplayName(); + } + } if (pList->GetItemCount() <= 0) { str += _(" is empty"); } @@ -484,7 +539,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe AXUIElementRef parent; HIViewRef parentView; - parentView = HIViewGetSuperview(isHeader ? pList->m_headerView : pList->m_bodyView); + parentView = HIViewGetSuperview(isHeader ? headerView : bodyView); parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0); if (parent == NULL) { return eventNotHandledErr; @@ -496,7 +551,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe } else if ( CFStringCompare( attribute, kAXSizeAttribute, 0 ) == kCFCompareEqualTo ) { HIRect r; - err = HIViewGetBounds(isHeader ? pList->m_headerView : pList->m_bodyView, &r); + err = HIViewGetBounds(isHeader ? headerView : bodyView, &r); HISize size = r.size; SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeHISize, sizeof( HISize ), &size ); @@ -506,14 +561,14 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe HIRect r; HIPoint pt; - err = HIViewGetBounds(isHeader ? pList->m_headerView : pList->m_bodyView, &r); + err = HIViewGetBounds(isHeader ? headerView : bodyView, &r); int x = r.origin.x, y = r.origin.y; // Now convert to global coordinates pList->ClientToScreen(&x, &y); pt.x = x; if (isHeader) { - pt.y = y - pList->GetHeaderHeight(); + pt.y = y - pList->m_headerHeight; } else { pt.y = y; } @@ -531,6 +586,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe if ( CFStringCompare( attribute, kAXDescriptionAttribute, 0 ) == kCFCompareEqualTo ) { wxString str, buf; int rowCount; + Boolean isCurrentSortCol = false; if (isHeader) { wxListItem headerItem; @@ -542,7 +598,12 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe pList->GetColumn(col, headerItem); buf.Printf(_("%d of %d; "), col+1, pList->GetColumnCount()); - if (col == pView->m_iSortColumn) { + if (pView) { + if (col == pView->m_iSortColumn) { + isCurrentSortCol = true; + } + } + if (isCurrentSortCol) { str = _("current sort column "); str += buf; str += (pView->m_bReverseSort ? _(" descending order ") : _(" ascending order ")); @@ -570,7 +631,11 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe } buf.Printf(_("column %d; "), col+1); str += buf; - buf = pView->FireOnListGetItemText(row, col); + if (pEventLog) { + buf = pEventLog->OnListGetItemText(row, col); + } else { + buf = pView->FireOnListGetItemText(row, col); + } if (buf.IsEmpty()) { buf = _("blank"); } @@ -586,7 +651,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe AXUIElementRef parent; HIViewRef parentView; - parentView = isHeader ? pList->m_headerView : pList->m_bodyView; + parentView = isHeader ? headerView : bodyView; parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0); if (parent == NULL) { return eventNotHandledErr; @@ -676,7 +741,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe // Return the size of this part as an HISize. size.width = pList->GetColumnWidth(col); if (isHeader) { - size.height = pList->GetHeaderHeight(); + size.height = pList->m_headerHeight; } else { // ! isHeader pList->GetItemRect(row, r); size.height = r.height; @@ -703,7 +768,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe // Now convert to global coordinates pList->ClientToScreen(&x, &y); pt.x = x; - pt.y = y - pList->GetHeaderHeight(); + pt.y = y - pList->m_headerHeight; SetEventParameter(inEvent, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(HIPoint), &pt); return noErr; @@ -859,8 +924,10 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe event.m_col = col; pList->AddPendingEvent(event); } else { - pView->ClearSelections(); - pList->SelectRow(row, true); + if (pView) { + pView->ClearSelections(); + } + pList->SetItemState(row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); } return noErr; } diff --git a/clientgui/mac/MacAccessiblity.h b/clientgui/mac/MacAccessiblity.h index e8440ce76c..bf310001c2 100644 --- a/clientgui/mac/MacAccessiblity.h +++ b/clientgui/mac/MacAccessiblity.h @@ -17,5 +17,21 @@ // macAccessiblity.h +#ifndef _MACACCESSIBILITY_H_ +#define _MACACCESSIBILITY_H_ + +#include "BOINCBaseView.h" +#include "DlgEventLog.h" +#include "wx/generic/listctrl.h" + +struct ListAccessData { + wxGenericListCtrl* pList; + CBOINCBaseView* pView; + CDlgEventLog* pEventLog; + HIViewRef headerView; + HIViewRef bodyView; +}; void AccessibilityIgnoreAllChildren(HIViewRef parent, int recursionLevel); + +#endif \ No newline at end of file