// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . // #if defined(__GNUG__) && !defined(__APPLE__) #pragma implementation "ProjectListCtrl.h" #endif #include "stdwx.h" #include "BOINCGUIApp.h" #include "BOINCWizards.h" #include "ProjectListCtrl.h" ////@begin XPM images #include "res/externalweblink.xpm" ////@end XPM images #if wxUSE_ACCESSIBILITY // Gets the name of the specified object. wxAccStatus CProjectListCtrlAccessible::GetName(int childId, wxString* name) { if (childId == wxACC_SELF) { *name = wxT("Project List"); } else { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl) { *name = pCtrl->GetItem(childId - 1)->GetTitle().c_str(); } } return wxACC_OK; } // Can return either a child object, or an integer // representing the child element, starting from 1. wxAccStatus CProjectListCtrlAccessible::HitTest(const wxPoint& pt, int* childId, wxAccessible** /*childObject*/) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl) { *childId = pCtrl->HitTest(pt); return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Returns the rectangle for this object (id = 0) or a child element (id > 0). wxAccStatus CProjectListCtrlAccessible::GetLocation(wxRect& rect, int elementId) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl && (0 != elementId)) { wxSize cCtrlSize = pCtrl->GetClientSize(); int iItemWidth = cCtrlSize.GetWidth(); int iItemHeight = pCtrl->GetTotalClientHeight() / (int)pCtrl->GetItemCount(); // Set the initial control postition to the absolute coords of the upper // left hand position of the control rect.SetPosition(pCtrl->GetScreenPosition()); rect.width = iItemWidth - 1; rect.height = iItemHeight - 1; if (1 == elementId) { // First child } else { // Other children rect.SetTop(rect.GetTop() + ((elementId - 1) * iItemHeight) + 1); rect.height -= 1; } return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Navigates from fromId to toId/toObject. wxAccStatus CProjectListCtrlAccessible::Navigate( wxNavDir navDir, int fromId, int* toId, wxAccessible** toObject ) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); *toObject = NULL; if (0 != fromId) { switch (navDir) { case wxNAVDIR_PREVIOUS: case wxNAVDIR_UP: if (1 == fromId) { return wxACC_FALSE; } else { *toId = fromId - 1; return wxACC_OK; } break; case wxNAVDIR_NEXT: case wxNAVDIR_DOWN: if ((int)pCtrl->GetItemCount() == fromId) { return wxACC_FALSE; } else { *toId = fromId + 1; return wxACC_OK; } return wxACC_FALSE; break; case wxNAVDIR_LEFT: return wxACC_FALSE; break; case wxNAVDIR_RIGHT: return wxACC_FALSE; break; case wxNAVDIR_FIRSTCHILD: if (1 == fromId) { return wxACC_FALSE; } else { *toId = 1; return wxACC_OK; } break; case wxNAVDIR_LASTCHILD: if ((int)pCtrl->GetItemCount() == fromId) { return wxACC_FALSE; } else { *toId = (int)pCtrl->GetItemCount(); return wxACC_OK; } break; } } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Gets the number of children. wxAccStatus CProjectListCtrlAccessible::GetChildCount(int* childCount) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl) { *childCount = (int)pCtrl->GetItemCount(); return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Performs the default action. childId is 0 (the action for this object) // or > 0 (the action for a child). // Return wxACC_NOT_SUPPORTED if there is no default action for this // window (e.g. an edit control). wxAccStatus CProjectListCtrlAccessible::DoDefaultAction(int childId) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl && (childId != wxACC_SELF)) { // Zero-based array index int iRealChildId = childId - 1; pCtrl->SetSelection(iRealChildId); // Fire Event ProjectListCtrlEvent evt( wxEVT_PROJECTLIST_ITEM_CHANGE, pCtrl->GetItem(iRealChildId)->GetTitle(), pCtrl->GetItem(iRealChildId)->GetURL(), true ); evt.SetEventObject(this); pCtrl->GetParent()->AddPendingEvent( evt ); return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Gets the default action for this object (0) or > 0 (the action for a child). // Return wxACC_OK even if there is no action. actionName is the action, or the empty // string if there is no action. // The retrieved string describes the action that is performed on an object, // not what the object does as a result. For example, a toolbar button that prints // a document has a default action of "Press" rather than "Prints the current document." wxAccStatus CProjectListCtrlAccessible::GetDefaultAction(int childId, wxString* actionName) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl && (childId != wxACC_SELF)) { *actionName = _("Click"); return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Returns the description for this object or a child. wxAccStatus CProjectListCtrlAccessible::GetDescription(int childId, wxString* description) { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl && (childId != wxACC_SELF)) { *description = pCtrl->GetItem(childId - 1)->GetDescription().c_str(); return wxACC_OK; } // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Returns a role constant. wxAccStatus CProjectListCtrlAccessible::GetRole(int childId, wxAccRole* role) { if (childId == wxACC_SELF) { *role = wxROLE_SYSTEM_LIST; } else { *role = wxROLE_SYSTEM_LISTITEM; } return wxACC_OK; } // Returns a role constant. wxAccStatus CProjectListCtrlAccessible::GetState(int childId, long* state) { if (childId == wxACC_SELF) { *state = wxACC_STATE_SYSTEM_DEFAULT; } else { CProjectListCtrl* pCtrl = wxDynamicCast(GetWindow(), CProjectListCtrl); if (pCtrl && (pCtrl->IsSelected(childId - 1))) { *state = wxACC_STATE_SYSTEM_SELECTED | wxACC_STATE_SYSTEM_FOCUSED; } else if (pCtrl && (pCtrl->IsVisible(childId - 1))) { *state = wxACC_STATE_SYSTEM_SELECTABLE; } else { *state = wxACC_STATE_SYSTEM_SELECTABLE | wxACC_STATE_SYSTEM_INVISIBLE; } } return wxACC_OK; } // Selects the object or child. wxAccStatus CProjectListCtrlAccessible::Select(int childId, wxAccSelectionFlags selectFlags) { // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } // Gets a variant representing the selected children // of this object. // Acceptable values: // - a null variant (IsNull() returns true) // - a list variant (GetType() == wxT("list")) // - an integer representing the selected child element, // or 0 if this object is selected (GetType() == wxT("long")) // - a "void*" pointer to a wxAccessible child object wxAccStatus CProjectListCtrlAccessible::GetSelections(wxVariant* selections) { // Let the framework handle the other cases. return wxACC_NOT_IMPLEMENTED; } #endif /*! * CProjectListItem type definition */ IMPLEMENT_DYNAMIC_CLASS( CProjectListItem, wxObject ) /*! * CProjectListCtrl event definitions */ DEFINE_EVENT_TYPE( wxEVT_PROJECTLIST_ITEM_CHANGE ) DEFINE_EVENT_TYPE( wxEVT_PROJECTLIST_ITEM_DISPLAY ) /*! * CProjectListCtrl type definition */ IMPLEMENT_DYNAMIC_CLASS( CProjectListCtrl, wxHtmlListBox ) IMPLEMENT_DYNAMIC_CLASS( ProjectListCtrlEvent, wxNotifyEvent ) /*! * CProjectListCtrl event table definition */ BEGIN_EVENT_TABLE( CProjectListCtrl, wxHtmlListBox ) ////@begin CProjectListCtrl event table entries EVT_LISTBOX(ID_PROJECTLISTCTRL, CProjectListCtrl::OnSelected) EVT_HTML_CELL_CLICKED( ID_PROJECTLISTCTRL, CProjectListCtrl::OnClicked ) EVT_LISTBOX_DCLICK(ID_PROJECTLISTCTRL, CProjectListCtrl::OnDClicked) EVT_HTML_LINK_CLICKED( ID_PROJECTLISTCTRL, CProjectListCtrl::OnLinkClicked ) EVT_HTML_CELL_HOVER( ID_PROJECTLISTCTRL, CProjectListCtrl::OnHover ) ////@end CProjectListCtrl event table entries END_EVENT_TABLE() /*! * CProjectListCtrl constructors */ CProjectListCtrl::CProjectListCtrl( ) { } CProjectListCtrl::CProjectListCtrl( wxWindow* parent ) { Create( parent ); } /*! * CProjectList creator */ bool CProjectListCtrl::Create( wxWindow* parent ) { ////@begin CProjectListCtrl member initialisation ////@end CProjectListCtrl member initialisation ////@begin CProjectListCtrl creation wxHtmlListBox::Create( parent, ID_PROJECTLISTCTRL, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER | wxTAB_TRAVERSAL ); #if wxUSE_ACCESSIBILITY SetAccessible(new CProjectListCtrlAccessible(this)); #endif wxMemoryFSHandler::AddFile(wxT("webexternallink.xpm"), wxBitmap(externalweblink_xpm), wxBITMAP_TYPE_XPM); ////@end CProjectListCtrl creation return TRUE; } void CProjectListCtrl::OnSelected( wxCommandEvent& event ) { // Fire Event ProjectListCtrlEvent evt( wxEVT_PROJECTLIST_ITEM_CHANGE, m_Items[event.GetInt()]->GetTitle(), m_Items[event.GetInt()]->GetURL(), m_Items[event.GetInt()]->IsPlatformSupported() ); evt.SetEventObject(this); GetParent()->AddPendingEvent( evt ); } void CProjectListCtrl::OnClicked( wxHtmlCellEvent& event ) { event.Skip(); } void CProjectListCtrl::OnDClicked( wxCommandEvent& event ) { event.Skip(); } void CProjectListCtrl::OnLinkClicked( wxHtmlLinkEvent& event ) { // Fire Event ProjectListCtrlEvent evt( wxEVT_PROJECTLIST_ITEM_DISPLAY, wxEmptyString, event.GetLinkInfo().GetHref(), true ); evt.SetEventObject(this); GetParent()->AddPendingEvent( evt ); } void CProjectListCtrl::OnHover( wxHtmlCellEvent& event ) { event.Skip(); } wxString CProjectListCtrl::OnGetItem(size_t i) const { wxString buf = wxEmptyString; buf.Printf( wxT(" ") wxT(" ") wxT(" ") wxT(" ") wxT(" ") wxT("
%s
"), m_Items[i]->GetTitle().c_str(), m_Items[i]->GetURL().c_str() ); return buf; } /*! * Append a new entry to the project list. */ bool CProjectListCtrl::Append( wxString strURL, wxString strTitle, wxString strDescription, bool bSupported ) { CProjectListItem* pItem = new CProjectListItem(); pItem->SetURL( strURL ); pItem->SetTitle( strTitle ); pItem->SetDescription( strDescription ); pItem->SetPlatformSupported( bSupported ); m_Items.push_back(pItem); SetItemCount(m_Items.size()); return true; } /*! * Return the project list entry at a given index. */ CProjectListItem* CProjectListCtrl::GetItem( int iIndex ) { return m_Items[iIndex]; } /*! * Return the total height of all the client items. */ wxCoord CProjectListCtrl::GetTotalClientHeight() { return EstimateTotalHeight(); }