- MGR: My first attempt to handle the project list control was turning

into a mess and becoming very complicated, as my former mentor used
        to say "if you are having to try too hard, you are doing it wrong."
        
        Reimplement the project list control as a wxHtmlListBox which handles
        keyboard navigation correctly and allows us to have variable height
        list items.  Another perk is the ability to detect when different
        HTML elements are clicked on which might be useful for anonymous
        attach at some point in time in the future.
        
    clientgui/
        AccountManagerInfoPage.cpp
        AdvancedFrame.cpp
        BOINCGUIApp.cpp
        BOINCWizards.h
        ProjectInfoPage.cpp
        ProjectListCtrl.cpp, .h
        stdwx.h

svn path=/trunk/boinc/; revision=18509
This commit is contained in:
Rom Walton 2009-06-30 02:05:46 +00:00
parent eb033ea5ff
commit 0e57669b18
9 changed files with 486 additions and 710 deletions

View File

@ -6053,3 +6053,23 @@ David 27 June 2009
db/
schema.sql
Rom 29 June 2009
- MGR: My first attempt to handle the project list control was turning
into a mess and becoming very complicated, as my former mentor used
to say "if you are having to try too hard, you are doing it wrong."
Reimplement the project list control as a wxHtmlListBox which handles
keyboard navigation correctly and allows us to have variable height
list items. Another perk is the ability to detect when different
HTML elements are clicked on which might be useful for anonymous
attach at some point in time in the future.
clientgui/
AccountManagerInfoPage.cpp
AdvancedFrame.cpp
BOINCGUIApp.cpp
BOINCWizards.h
ProjectInfoPage.cpp
ProjectListCtrl.cpp, .h
stdwx.h

View File

@ -263,8 +263,9 @@ void CAccountManagerInfoPage::OnPageChanged( wxWizardExEvent& event ) {
);
m_pProjectListCtrl->Append(
wxString(pl.account_managers[i]->name.c_str(), wxConvUTF8),
wxString(pl.account_managers[i]->url.c_str(), wxConvUTF8),
wxString(pl.account_managers[i]->name.c_str(), wxConvUTF8),
wxString(pl.account_managers[i]->description.c_str(), wxConvUTF8),
true
);
}

View File

@ -54,18 +54,12 @@
#include "BOINCWizards.h"
#include "BOINCBaseWizard.h"
#include "WizardAttachProject.h"
//#include "WizardAccountManager.h"
#include "DlgAdvPreferences.h"
#include "res/connect.xpm"
#include "res/disconnect.xpm"
// Which of the view sets should we display.
//
//#define VIEW_LIST 2
enum STATUSBARFIELDS {
STATUS_TEXT,
STATUS_CONNECTION_STATUS

View File

@ -312,6 +312,7 @@ bool CBOINCGUIApp::OnInit() {
wxInitAllImageHandlers();
// Enable additional file system type handlers
wxFileSystem::AddHandler(new wxMemoryFSHandler);
#if wxUSE_FS_INET && wxUSE_STREAMS && wxUSE_SOCKETS
wxFileSystem::AddHandler(new wxInternetFSHandler);
#endif

View File

@ -71,10 +71,9 @@
#define ID_WELCOMECHANGEAPPS 11102
// Project Info/Account Manager Info Controls
#define ID_PROJECTSELECTIONCTRL 11200
#define ID_PROJECTLISTCTRL 11200
#define ID_PROJECTURLSTATICCTRL 11201
#define ID_PROJECTURLDESCRIPTIONSTATICCTRL 11202
#define ID_PROJECTURLCTRL 11203
#define ID_PROJECTURLCTRL 11202
// Terms Of Use Controls
#define ID_TERMSOFUSECTRL 11300

View File

@ -286,11 +286,19 @@ void CProjectInfoPage::OnPageChanged( wxWizardExEvent& event ) {
);
m_pProjectListCtrl->Append(
wxString(pl.projects[i]->name.c_str(), wxConvUTF8),
wxString(pl.projects[i]->url.c_str(), wxConvUTF8),
wxString(pl.projects[i]->name.c_str(), wxConvUTF8),
wxString(pl.projects[i]->description.c_str(), wxConvUTF8),
bSupportedPlatformFound
);
}
// Pre select the first element
m_pProjectListCtrl->SetSelection(0);
m_strProjectURL = m_pProjectListCtrl->GetItem(0)->GetURL();
m_bProjectSupported = m_pProjectListCtrl->GetItem(0)->IsPlatformSupported();
TransferDataToWindow();
m_bProjectListPopulated = true;
}

View File

@ -21,6 +21,7 @@
#include "stdwx.h"
#include "BOINCGUIApp.h"
#include "BOINCWizards.h"
#include "ProjectListCtrl.h"
////@begin XPM images
@ -28,30 +29,325 @@
////@end XPM images
#ifdef 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, wxScrolledWindow )
IMPLEMENT_DYNAMIC_CLASS( CProjectListCtrl, wxHtmlListBox )
IMPLEMENT_DYNAMIC_CLASS( ProjectListCtrlEvent, wxNotifyEvent )
/*!
* CProjectListCtrl event table definition
*/
BEGIN_EVENT_TABLE( CProjectListCtrl, wxScrolledWindow )
BEGIN_EVENT_TABLE( CProjectListCtrl, wxHtmlListBox )
////@begin CProjectListCtrl event table entries
EVT_SET_FOCUS( CProjectListCtrl::OnFocusChanged )
EVT_KILL_FOCUS( CProjectListCtrl::OnFocusChanged )
EVT_KEY_DOWN( CProjectListCtrl::OnKeyPressed )
EVT_KEY_UP( CProjectListCtrl::OnKeyPressed )
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()
@ -76,203 +372,86 @@ CProjectListCtrl::CProjectListCtrl( wxWindow* parent )
bool CProjectListCtrl::Create( wxWindow* parent )
{
////@begin CProjectListCtrl member initialisation
m_pMainSizer = NULL;
////@end CProjectListCtrl member initialisation
m_pCurrentSelection = NULL;
////@begin CProjectListCtrl creation
wxScrolledWindow::Create( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSUNKEN_BORDER | wxVSCROLL | wxTAB_TRAVERSAL );
wxHtmlListBox::Create( parent, ID_PROJECTLISTCTRL, wxDefaultPosition, wxDefaultSize,
wxSUNKEN_BORDER | wxTAB_TRAVERSAL );
SetMinSize(GetSize());
#ifdef wxUSE_ACCESSIBILITY
SetAccessible(new CProjectListCtrlAccessible(this));
#endif
CreateControls();
SetBackgroundColour( wxT("WHITE") );
SetScrollRate( 0, 25 );
GetSizer()->Fit(this);
wxMemoryFSHandler::AddFile(wxT("webexternallink.xpm"), wxBitmap(externalweblink_xpm), wxBITMAP_TYPE_XPM);
////@end CProjectListCtrl creation
return TRUE;
}
/*!
* Control creation for ProjectListCtrl
*/
void CProjectListCtrl::CreateControls()
{
////@begin CProjectListCtrl content construction
wxFlexGridSizer* itemFlexGridSizer5 = new wxFlexGridSizer(0, 1, 0, 0);
itemFlexGridSizer5->AddGrowableCol(0);
wxFlexGridSizer* itemFlexGridSizer6 = new wxFlexGridSizer(1, 1, 0, 0);
itemFlexGridSizer6->AddGrowableRow(0);
itemFlexGridSizer6->AddGrowableCol(0);
itemFlexGridSizer5->Add(itemFlexGridSizer6, 0, wxGROW|wxGROW|wxALL, 0);
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);
m_pMainSizer = new wxBoxSizer(wxVERTICAL);
itemFlexGridSizer6->Add(m_pMainSizer, 0, wxGROW|wxGROW|wxALL, 5);
SetSizer(itemFlexGridSizer5);
////@end CProjectListCtrl content construction
GetParent()->AddPendingEvent( evt );
}
/*!
* event handler for window
*/
void CProjectListCtrl::OnItemChange( CProjectListItemCtrl* pSelectedItem ) {
// Fire an event for the parent window notifing it of the new selection.
if (pSelectedItem) {
// Store so we know where we are
m_pCurrentSelection = pSelectedItem;
// Fire Event
ProjectListCtrlEvent evt(
wxEVT_PROJECTLIST_ITEM_CHANGE,
pSelectedItem->GetTitle(),
pSelectedItem->GetURL(),
pSelectedItem->IsSupported()
);
evt.SetEventObject(this);
GetParent()->AddPendingEvent( evt );
}
}
/*!
* event handler for window
*/
void CProjectListCtrl::OnItemDisplay( wxCommandEvent& event ) {
// Fire an event for the parent window notifing it to display more information.
CProjectListItemCtrl* pItem = wxDynamicCast(event.GetEventObject(), CProjectListItemCtrl);
if (pItem) {
// Fire Event
ProjectListCtrlEvent evt(
wxEVT_PROJECTLIST_ITEM_DISPLAY,
pItem->GetTitle(),
pItem->GetURL(),
pItem->IsSupported()
);
evt.SetEventObject(this);
GetParent()->AddPendingEvent( evt );
}
}
/*!
* event handler for window
*/
void CProjectListCtrl::OnItemFocusChange( CProjectListItemCtrl* pSelectedItem ) {
// Reset the background color back to the default
wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
while (current) {
wxWindow* child = current->GetData();
child->SetBackgroundColour( wxNullColour );
child->Refresh();
current = current->GetNext();
}
// Set the background color of the window that threw the event to the
// default background color of a selected control.
if (pSelectedItem) {
pSelectedItem->SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) );
pSelectedItem->Refresh();
OnItemChange( pSelectedItem );
}
}
/*!
* wxEVT_SET_FOCUS, wxEVT_KILL_FOCUS event handler for window
*/
void CProjectListCtrl::OnFocusChanged( wxFocusEvent& event ) {
if ( wxEVT_SET_FOCUS == event.GetEventType() ) {
// Control has focus
if (!m_pCurrentSelection) {
// Set the focus to the first child
GetChildren().GetFirst()->GetData()->SetFocus();
}
}
void CProjectListCtrl::OnClicked( wxHtmlCellEvent& event )
{
event.Skip();
}
/*!
* wxEVT_KEY_DOWN, wxEVT_KEY_UP event handler for window
*/
void CProjectListCtrl::OnDClicked( wxCommandEvent& event )
{
event.Skip();
}
void CProjectListCtrl::OnKeyPressed( wxKeyEvent& event ) {
wxWindowList list;
list = GetChildren();
if ( (wxEVT_KEY_DOWN == event.GetEventType()) && (WXK_DOWN == event.GetKeyCode()) ) {
void CProjectListCtrl::OnLinkClicked( wxHtmlLinkEvent& event )
{
// Fire Event
ProjectListCtrlEvent evt(
wxEVT_PROJECTLIST_ITEM_DISPLAY,
wxEmptyString,
event.GetLinkInfo().GetHref(),
true
);
evt.SetEventObject(this);
wxWindowList::compatibility_iterator iter = GetChildren().GetLast();
while (iter) {
wxWindow* pCurentWindow = iter->GetData();
if (pCurentWindow == m_pCurrentSelection) {
wxWindowListNode* pNextNode = iter->GetNext();
if (pNextNode) {
wxWindow* pNextWindow = pNextNode->GetData();
if (pNextWindow) {
pNextWindow->SetFocus();
}
}
}
iter = iter->GetPrevious();
}
GetParent()->AddPendingEvent( evt );
}
} else if ( (wxEVT_KEY_DOWN == event.GetEventType()) && (WXK_UP == event.GetKeyCode()) ) {
wxWindowList::compatibility_iterator iter = GetChildren().GetFirst();
while (iter) {
wxWindow* pCurentWindow = iter->GetData();
if (pCurentWindow == m_pCurrentSelection) {
wxWindowListNode* pPreviousNode = iter->GetPrevious();
if (pPreviousNode) {
wxWindow* pPreviousWindow = pPreviousNode->GetData();
if (pPreviousWindow) {
pPreviousWindow->SetFocus();
}
}
}
iter = iter->GetNext();
}
void CProjectListCtrl::OnHover( wxHtmlCellEvent& event )
{
event.Skip();
}
} else if ( (wxEVT_KEY_DOWN == event.GetEventType()) && (WXK_TAB == event.GetKeyCode()) ) {
if (wxMOD_SHIFT == event.GetModifiers()) {
Navigate( wxNavigationKeyEvent::IsBackward & wxNavigationKeyEvent::WinChange );
} else {
Navigate( wxNavigationKeyEvent::IsForward & wxNavigationKeyEvent::WinChange );
}
wxString CProjectListCtrl::OnGetItem(size_t i) const
{
wxString buf = wxEmptyString;
} else {
event.Skip();
}
buf.Printf(
wxT(" <table cellpadding=0 cellspacing=1>")
wxT(" <tr>")
wxT(" <td width=100%%>%s</td>")
wxT(" <td><a href=\"%s\"><img src=\"memory:webexternallink.xpm\"></a></td>")
wxT(" </tr>")
wxT(" </table>"),
m_Items[i]->GetTitle().c_str(),
m_Items[i]->GetURL().c_str()
);
return buf;
}
@ -281,367 +460,44 @@ void CProjectListCtrl::OnKeyPressed( wxKeyEvent& event ) {
*/
bool CProjectListCtrl::Append(
wxString strTitle,
wxString strURL,
wxString strTitle,
wxString strDescription,
bool bSupported
)
{
CProjectListItemCtrl* pItem = new CProjectListItemCtrl();
pItem->Create( this );
pItem->SetTitle( strTitle );
CProjectListItem* pItem = new CProjectListItem();
pItem->SetURL( strURL );
pItem->SetSupportedStatus( bSupported );
pItem->SetTitle( strTitle );
pItem->SetDescription( strDescription );
pItem->SetPlatformSupported( bSupported );
m_pMainSizer->Add( pItem, 0, wxEXPAND );
FitInside();
m_Items.push_back(pItem);
SetItemCount(m_Items.size());
return true;
}
/*!
* CProjectListItemCtrl type definition
* Return the project list entry at a given index.
*/
IMPLEMENT_DYNAMIC_CLASS( CProjectListItemCtrl, wxPanel )
/*!
* CProjectListItemCtrl event table definition
*/
BEGIN_EVENT_TABLE( CProjectListItemCtrl, wxPanel )
////@begin CProjectListItemCtrl event table entries
EVT_ENTER_WINDOW( CProjectListItemCtrl::OnMouseEnterLeave )
EVT_LEAVE_WINDOW( CProjectListItemCtrl::OnMouseEnterLeave )
EVT_LEFT_DOWN( CProjectListItemCtrl::OnMouseClick )
EVT_LEFT_UP( CProjectListItemCtrl::OnMouseClick )
EVT_KEY_DOWN( CProjectListItemCtrl::OnKeyPressed )
EVT_KEY_UP( CProjectListItemCtrl::OnKeyPressed )
EVT_BUTTON( ID_WEBSITEBUTTON, CProjectListItemCtrl::OnWebsiteButtonClick )
////@end CProjectListItemCtrl event table entries
END_EVENT_TABLE()
/*!
* CProjectListItemCtrl constructors
*/
CProjectListItemCtrl::CProjectListItemCtrl( )
{
}
CProjectListItemCtrl::CProjectListItemCtrl( wxWindow* parent )
{
Create( parent );
}
/*!
* CProjectListItemCtrl creator
*/
bool CProjectListItemCtrl::Create( wxWindow* parent )
{
////@begin CProjectListItemCtrl member initialisation
m_pTitleStaticCtrl = NULL;
m_pWebsiteButtonCtrl = NULL;
m_strTitle = wxEmptyString;
m_strURL = wxEmptyString;
m_bSupported = false;
////@end CProjectListItemCtrl member initialisation
////@begin CProjectListItemCtrl creation
wxPanel::Create( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxNO_BORDER | wxWANTS_CHARS | wxTAB_TRAVERSAL );
CreateControls();
GetSizer()->Fit(this);
////@end CProjectListItemCtrl creation
return TRUE;
}
/*!
* Control creation for CProjectListItemCtrl
*/
void CProjectListItemCtrl::CreateControls()
{
////@begin CProjectListItemCtrl content construction
wxBoxSizer* itemBoxSizer7 = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* itemFlexGridSizer8 = new wxFlexGridSizer(1, 2, 0, 0);
itemFlexGridSizer8->AddGrowableRow(0);
itemFlexGridSizer8->AddGrowableCol(0);
itemBoxSizer7->Add(itemFlexGridSizer8, 0, wxGROW|wxALL, 0);
m_pTitleStaticCtrl = new CProjectListItemStaticCtrl;
m_pTitleStaticCtrl->Create( this, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer8->Add(m_pTitleStaticCtrl, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 0);
m_pWebsiteButtonCtrl = new CProjectListItemBitmapCtrl;
m_pWebsiteButtonCtrl->Create( this, ID_WEBSITEBUTTON, wxBitmap(externalweblink_xpm), wxDefaultPosition, wxSize(12,12), wxNO_BORDER );
itemFlexGridSizer8->Add(m_pWebsiteButtonCtrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 0);
SetSizer(itemBoxSizer7);
////@end CProjectListItemCtrl content construction
}
/*!
* wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
*/
void CProjectListItemCtrl::OnMouseEnterLeave( wxMouseEvent& event ) {
m_bLeftButtonDownDetected = false;
event.Skip();
}
/*!
* wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
*/
void CProjectListItemCtrl::OnMouseClick( wxMouseEvent& event ) {
if ( event.LeftDown() ) {
m_bLeftButtonDownDetected = true;
} else {
if ( m_bLeftButtonDownDetected ) {
CProjectListCtrl* pParent = wxDynamicCast(GetParent(), CProjectListCtrl);
if (pParent) {
pParent->OnItemFocusChange( this );
}
}
}
event.Skip();
}
/*!
* wxEVT_KEY_DOWN, wxEVT_KEY_UP event handler for window
*/
void CProjectListItemCtrl::OnKeyPressed( wxKeyEvent& event ) {
CProjectListCtrl* pParent = wxDynamicCast(GetParent(), CProjectListCtrl);
if (pParent) {
pParent->OnKeyPressed( event );
}
}
/*!
* wxEVT_COMMAND_BUTTON_CLICKED event handler for window
*/
void CProjectListItemCtrl::OnWebsiteButtonClick( wxCommandEvent& event ) {
if (!m_strURL.IsEmpty()) {
// We now have focus, report that to the parent
CProjectListCtrl* pParent = wxDynamicCast(GetParent(), CProjectListCtrl);
if (pParent) {
pParent->OnItemDisplay( event );
}
}
}
bool CProjectListItemCtrl::SetTitle( wxString strTitle ) {
if (m_pTitleStaticCtrl) m_pTitleStaticCtrl->SetLabel( strTitle );
m_strTitle = strTitle;
return true;
}
bool CProjectListItemCtrl::SetURL( wxString strURL ) {
if (m_pWebsiteButtonCtrl) {
wxString strBuffer = wxEmptyString;
strBuffer.Printf(
_("Click here to go to %s's website."),
m_strTitle.c_str()
);
m_pWebsiteButtonCtrl->SetToolTip(strBuffer);
}
m_strURL = strURL;
return true;
}
bool CProjectListItemCtrl::SetSupportedStatus( bool bSupported ) {
if (m_pTitleStaticCtrl) {
m_pTitleStaticCtrl->Enable( bSupported );
}
m_bSupported = bSupported;
return true;
}
/*!
* CProjectListItemStaticCtrl type definition
*/
IMPLEMENT_DYNAMIC_CLASS( CProjectListItemStaticCtrl, wxStaticText )
/*!
* CProjectListItemStaticCtrl event table definition
*/
BEGIN_EVENT_TABLE( CProjectListItemStaticCtrl, wxStaticText )
////@begin CProjectListItemStaticCtrl event table entries
EVT_ENTER_WINDOW( CProjectListItemStaticCtrl::OnMouseEnterLeave )
EVT_LEAVE_WINDOW( CProjectListItemStaticCtrl::OnMouseEnterLeave )
EVT_LEFT_DOWN( CProjectListItemStaticCtrl::OnMouseClick )
EVT_LEFT_UP( CProjectListItemStaticCtrl::OnMouseClick )
////@end CProjectListItemStaticCtrl event table entries
END_EVENT_TABLE()
/*!
* CProjectListItemStaticCtrl constructors
*/
CProjectListItemStaticCtrl::CProjectListItemStaticCtrl( )
{
}
CProjectListItemStaticCtrl::CProjectListItemStaticCtrl(
wxWindow *parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxString& name
CProjectListItem* CProjectListCtrl::GetItem(
int iIndex
)
{
Create (parent, id, label, pos, size, style, name);
return m_Items[iIndex];
}
/*!
* CProjectListItemStaticCtrl creator
* Return the total height of all the client items.
*/
bool CProjectListItemStaticCtrl::Create(
wxWindow *parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxString& name
)
wxCoord CProjectListCtrl::GetTotalClientHeight()
{
bool retval = false;
retval = wxStaticText::Create (parent, id, label, pos, size, style, name);
return retval;
}
/*!
* wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
*/
void CProjectListItemStaticCtrl::OnMouseEnterLeave( wxMouseEvent& event ) {
CProjectListItemCtrl* pParent = wxDynamicCast(GetParent(), CProjectListItemCtrl);
if (pParent) {
pParent->OnMouseEnterLeave( event );
}
}
/*!
* wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
*/
void CProjectListItemStaticCtrl::OnMouseClick( wxMouseEvent& event ) {
CProjectListItemCtrl* pParent = wxDynamicCast(GetParent(), CProjectListItemCtrl);
if (pParent) {
pParent->OnMouseClick( event );
}
}
/*!
* CProjectListItemBitmapCtrl type definition
*/
IMPLEMENT_DYNAMIC_CLASS( CProjectListItemBitmapCtrl, wxStaticBitmap )
/*!
* CProjectListItemBitmapCtrl event table definition
*/
BEGIN_EVENT_TABLE( CProjectListItemBitmapCtrl, wxStaticBitmap )
////@begin CProjectListItemBitmapCtrl event table entries
EVT_ENTER_WINDOW( CProjectListItemBitmapCtrl::OnMouseEnterLeave )
EVT_LEAVE_WINDOW( CProjectListItemBitmapCtrl::OnMouseEnterLeave )
EVT_LEFT_DOWN( CProjectListItemBitmapCtrl::OnMouseClick )
EVT_LEFT_UP( CProjectListItemBitmapCtrl::OnMouseClick )
////@end CProjectListItemBitmapCtrl event table entries
END_EVENT_TABLE()
/*!
* CProjectListItemBitmapCtrl constructors
*/
CProjectListItemBitmapCtrl::CProjectListItemBitmapCtrl( )
{
}
CProjectListItemBitmapCtrl::CProjectListItemBitmapCtrl(
wxWindow *parent, wxWindowID id, const wxBitmap& bitmap, const wxPoint& pos, const wxSize& size, long style, const wxString& name
)
{
Create (parent, id, bitmap, pos, size, style, name);
}
/*!
* CProjectListItemBitmapCtrl creator
*/
bool CProjectListItemBitmapCtrl::Create(
wxWindow *parent, wxWindowID id, const wxBitmap& bitmap, const wxPoint& pos, const wxSize& size, long style, const wxString& name
)
{
bool retval = false;
retval = wxStaticBitmap::Create (parent, id, bitmap, pos, size, style, name);
return retval;
}
/*!
* wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
*/
void CProjectListItemBitmapCtrl::OnMouseEnterLeave( wxMouseEvent& event ) {
m_bLeftButtonDownDetected = false;
event.Skip();
}
/*!
* wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
*/
void CProjectListItemBitmapCtrl::OnMouseClick( wxMouseEvent& event ) {
if ( event.LeftDown() ) {
m_bLeftButtonDownDetected = true;
} else {
if ( m_bLeftButtonDownDetected ) {
// The control that reported the down event is also
// the one reporting the up event, so it is a valid
// click event.
wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED);
evt.SetId( ID_WEBSITEBUTTON );
evt.SetEventObject(this);
GetParent()->AddPendingEvent( evt );
}
}
event.Skip();
return EstimateTotalHeight();
}

View File

@ -23,22 +23,72 @@
#endif
class CProjectListItemCtrl;
class CProjectListItemStaticCtrl;
class CProjectListItemBitmapCtrl;
class ProjectListCtrlEvent;
/*!
* CProjectListItem class declaration
*/
class CProjectListItem: public wxObject
{
DECLARE_DYNAMIC_CLASS( CProjectListItem )
public:
wxString GetURL() const { return m_strURL ; }
void SetURL(wxString value) { m_strURL = value ; }
wxString GetTitle() const { return m_strTitle ; }
void SetTitle(wxString value) { m_strTitle = value ; }
wxString GetOrganization() const { return m_strOrganization ; }
void SetOrganization(wxString value) { m_strOrganization = value ; }
wxString GetDescription() const { return m_strDescription ; }
void SetDescription(wxString value) { m_strDescription = value ; }
wxString GetCategory() const { return m_strCategory ; }
void SetCategory(wxString value) { m_strCategory = value ; }
bool IsPlatformSupported() const { return m_bSupported ; }
void SetPlatformSupported(bool value) { m_bSupported = value ; }
private:
wxString m_strURL;
wxString m_strTitle;
wxString m_strOrganization;
wxString m_strDescription;
wxString m_strCategory;
bool m_bSupported;
};
////@begin control identifiers
#define ID_WEBSITEBUTTON 10001
////@end control identifiers
#ifdef wxUSE_ACCESSIBILITY
class CProjectListCtrlAccessible: public wxWindowAccessible
{
public:
CProjectListCtrlAccessible(wxWindow* win): wxWindowAccessible(win) {}
virtual wxAccStatus GetName(int childId, wxString* name);
virtual wxAccStatus HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject);
virtual wxAccStatus GetLocation(wxRect& rect, int elementId);
virtual wxAccStatus Navigate(wxNavDir navDir, int fromId, int* toId, wxAccessible** toObject);
virtual wxAccStatus GetChildCount(int* childCount);
virtual wxAccStatus DoDefaultAction(int childId);
virtual wxAccStatus GetDefaultAction(int childId, wxString* actionName);
virtual wxAccStatus GetDescription(int childId, wxString* description);
virtual wxAccStatus GetRole(int childId, wxAccRole* role);
virtual wxAccStatus GetState(int childId, long* state);
virtual wxAccStatus Select(int childId, wxAccSelectionFlags selectFlags);
virtual wxAccStatus GetSelections(wxVariant* selections);
};
#endif
/*!
* CProjectListCtrl class declaration
*/
class CProjectListCtrl: public wxScrolledWindow
class CProjectListCtrl: public wxHtmlListBox
{
DECLARE_DYNAMIC_CLASS( CProjectListCtrl )
DECLARE_EVENT_TABLE()
@ -52,38 +102,34 @@ public:
/// Creation
bool Create( wxWindow* parent );
/// Creates the controls and sizers
void CreateControls();
////@begin CProjectListCtrl event handler declarations
/// event handler for window
void OnItemChange( CProjectListItemCtrl* pSelectedItem );
/// event handler for window
void OnItemDisplay( wxCommandEvent& event );
/// event handler for window
void OnItemFocusChange( CProjectListItemCtrl* pSelectedItem );
/// wxEVT_SET_FOCUS, wxEVT_KILL_FOCUS event handler for window
void OnFocusChanged( wxFocusEvent& event );
/// wxEVT_KEY_DOWN, wxEVT_KEY_UP event handler for window
void OnKeyPressed( wxKeyEvent& event );
void OnSelected( wxCommandEvent& event );
void OnClicked( wxHtmlCellEvent& event );
void OnDClicked( wxCommandEvent& event );
void OnLinkClicked( wxHtmlLinkEvent& event );
void OnHover( wxHtmlCellEvent& event );
////@end CProjectListCtrl event handler declarations
virtual wxString OnGetItem(size_t i) const;
/// Methods
bool Append(
wxString strTitle,
wxString strURL,
wxString strTitle,
wxString strDescription,
bool bSupported
);
CProjectListItem* GetItem(
int iIndex
);
wxCoord GetTotalClientHeight();
private:
wxWindow* m_pCurrentSelection;
wxBoxSizer* m_pMainSizer;
std::vector<CProjectListItem*> m_Items;
};
@ -137,155 +183,4 @@ typedef void (wxEvtHandler::*ProjectListCtrlEventFunction)(ProjectListCtrlEvent&
#define EVT_PROJECTLIST_ITEM_DISPLAY(fn) wx__DECLARE_PROJECTLISTEVT(ITEM_DISPLAY, fn)
/*!
* CProjectListItemCtrl class declaration
*/
class CProjectListItemCtrl: public wxPanel
{
DECLARE_DYNAMIC_CLASS( CProjectListItemCtrl )
DECLARE_EVENT_TABLE()
public:
/// Constructors
CProjectListItemCtrl( );
CProjectListItemCtrl( wxWindow* parent );
/// Creation
bool Create( wxWindow* parent );
/// Creates the controls and sizers
void CreateControls();
////@begin CProjectListItemCtrl event handler declarations
/// wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
void OnMouseEnterLeave( wxMouseEvent& event );
/// wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
void OnMouseClick( wxMouseEvent& event );
/// wxEVT_KEY_DOWN, wxEVT_KEY_UP event handler for window
void OnKeyPressed( wxKeyEvent& event );
/// wxEVT_COMMAND_BUTTON_CLICKED event handler for window
void OnWebsiteButtonClick( wxCommandEvent& event );
////@end CProjectListItemCtrl event handler declarations
/// Methods
wxString GetTitle() { return m_strTitle; };
wxString GetURL() { return m_strURL; };
bool IsSupported() { return m_bSupported; };
bool SetTitle( wxString strTitle );
bool SetURL( wxString strURL );
bool SetSupportedStatus( bool bSupported );
private:
CProjectListItemStaticCtrl* m_pTitleStaticCtrl;
CProjectListItemBitmapCtrl* m_pWebsiteButtonCtrl;
wxString m_strTitle;
wxString m_strURL;
bool m_bSupported;
bool m_bLeftButtonDownDetected;
};
/*!
* CProjectListItemStaticCtrl class declaration
*/
class CProjectListItemStaticCtrl: public wxStaticText
{
DECLARE_DYNAMIC_CLASS( CProjectListItemStaticCtrl )
DECLARE_EVENT_TABLE()
public:
/// Constructors
CProjectListItemStaticCtrl();
CProjectListItemStaticCtrl(
wxWindow *parent,
wxWindowID id,
const wxString &label = wxEmptyString,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,
const wxString &name = _T("ProjectListItemStaticCtrl")
);
/// Creation
bool Create (
wxWindow *parent,
wxWindowID id,
const wxString &label = wxEmptyString,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,
const wxString &name = _T("ProjectListItemStaticCtrl")
);
////@begin CProjectListItemStaticCtrl event handler declarations
/// wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
void OnMouseEnterLeave( wxMouseEvent& event );
/// wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
void OnMouseClick( wxMouseEvent& event );
////@end CProjectListItemStaticCtrl event handler declarations
};
/*!
* CProjectListItemBitmapCtrl class declaration
*/
class CProjectListItemBitmapCtrl: public wxStaticBitmap
{
DECLARE_DYNAMIC_CLASS( CProjectListItemBitmapCtrl )
DECLARE_EVENT_TABLE()
public:
/// Constructors
CProjectListItemBitmapCtrl();
CProjectListItemBitmapCtrl(
wxWindow *parent,
wxWindowID id,
const wxBitmap& bitmap,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,
const wxString &name = _T("ProjectListItemBitmapCtrl")
);
/// Creation
bool Create (
wxWindow *parent,
wxWindowID id,
const wxBitmap& bitmap,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,
const wxString &name = _T("ProjectListItemBitmapCtrl")
);
////@begin CProjectListItemBitmapCtrl event handler declarations
/// wxEVT_ENTER_WINDOW, wxEVT_LEAVE_WINDOW event handler for window
void OnMouseEnterLeave( wxMouseEvent& event );
/// wxEVT_LEFT_DOWN, wxEVT_LEFT_UP event handler for window
void OnMouseClick( wxMouseEvent& event );
////@end CProjectListItemBitmapCtrl event handler declarations
bool m_bLeftButtonDownDetected;
};
#endif // _WIZ_PROJECTLISTCTRL_H_

View File

@ -112,7 +112,9 @@
#include <wx/html/htmlwin.h>
#include <wx/html/htmlproc.h>
#include <wx/fs_inet.h>
#include <wx/fs_mem.h>
#include <wx/dnd.h>
#include <wx/htmllbox.h>
#ifdef _WIN32