// 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 "BOINCBaseView.h"
#endif
#include "stdwx.h"
#include "BOINCGUIApp.h"
#include "MainDocument.h"
#include "BOINCBaseView.h"
#include "BOINCTaskCtrl.h"
#include "BOINCListCtrl.h"
#include "Events.h"
#include "res/boinc.xpm"
#include "res/sortascending.xpm"
#include "res/sortdescending.xpm"
IMPLEMENT_DYNAMIC_CLASS(CBOINCBaseView, wxPanel)
CBOINCBaseView::CBOINCBaseView() {}
CBOINCBaseView::CBOINCBaseView(wxNotebook* pNotebook) :
wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
{
m_bProcessingTaskRenderEvent = false;
m_bProcessingListRenderEvent = false;
m_bForceUpdateSelection = true;
m_bIgnoreUIEvents = false;
m_bNeedSort = false;
m_iPreviousSelectionCount = 0;
m_lPreviousFirstSelection = -1;
//
// Setup View
//
m_pTaskPane = NULL;
m_pListPane = NULL;
m_iProgressColumn = -1;
m_iSortColumnID = -1;
m_SortArrows = NULL;
m_aStdColNameOrder = NULL;
m_iDefaultShownColumns = NULL;
m_iNumDefaultShownColumns = 0;
SetName(GetViewName());
SetAutoLayout(TRUE);
}
CBOINCBaseView::CBOINCBaseView(wxNotebook* pNotebook, wxWindowID iTaskWindowID, int iTaskWindowFlags, wxWindowID iListWindowID, int iListWindowFlags) :
wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
{
m_bProcessingTaskRenderEvent = false;
m_bProcessingListRenderEvent = false;
m_bForceUpdateSelection = true;
m_bIgnoreUIEvents = false;
m_iPreviousSelectionCount = 0;
m_lPreviousFirstSelection = -1;
//
// Setup View
//
m_pTaskPane = NULL;
m_pListPane = NULL;
SetName(GetViewName());
SetAutoLayout(TRUE);
wxFlexGridSizer* itemFlexGridSizer = new wxFlexGridSizer(2, 0, 0);
wxASSERT(itemFlexGridSizer);
itemFlexGridSizer->AddGrowableRow(0);
itemFlexGridSizer->AddGrowableCol(1);
m_pTaskPane = new CBOINCTaskCtrl(this, iTaskWindowID, iTaskWindowFlags);
wxASSERT(m_pTaskPane);
m_pListPane = new CBOINCListCtrl(this, iListWindowID, iListWindowFlags);
wxASSERT(m_pListPane);
itemFlexGridSizer->Add(m_pTaskPane, 1, wxGROW|wxALL, 1);
itemFlexGridSizer->Add(m_pListPane, 1, wxGROW|wxALL, 1);
SetSizer(itemFlexGridSizer);
UpdateSelection();
#if USE_NATIVE_LISTCONTROL
m_pListPane->PushEventHandler(new MyEvtHandler(m_pListPane));
#else
m_pListPane->SaveEventHandler((m_pListPane->GetMainWin())->GetEventHandler());
(m_pListPane->GetMainWin())->PushEventHandler(new MyEvtHandler(m_pListPane));
#endif
m_iProgressColumn = -1;
m_iSortColumnID = -1;
m_bReverseSort = false;
m_SortArrows = new wxImageList(16, 16, true);
m_SortArrows->Add( wxIcon( sortascending_xpm ) );
m_SortArrows->Add( wxIcon( sortdescending_xpm ) );
m_pListPane->SetImageList(m_SortArrows, wxIMAGE_LIST_SMALL);
m_aStdColNameOrder = NULL;
m_iDefaultShownColumns = NULL;
m_iNumDefaultShownColumns = 0;
}
CBOINCBaseView::~CBOINCBaseView() {
if (m_pListPane) {
#if USE_NATIVE_LISTCONTROL
m_pListPane->PopEventHandler(true);
#else
(m_pListPane->GetMainWin())->PopEventHandler(true);
#endif
}
if (m_SortArrows) {
delete m_SortArrows;
}
m_arrSelectedKeys1.Clear();
m_arrSelectedKeys2.Clear();
m_iSortedIndexes.Clear();
if (m_aStdColNameOrder) {
delete m_aStdColNameOrder;
}
}
// The name of the view.
// If it has not been defined by the view "Undefined" is returned.
//
wxString& CBOINCBaseView::GetViewName() {
static wxString strViewName(wxT("Undefined"));
return strViewName;
}
// The user friendly name of the view.
// If it has not been defined by the view "Undefined" is returned.
//
wxString& CBOINCBaseView::GetViewDisplayName() {
static wxString strViewName(wxT("Undefined"));
return strViewName;
}
// The user friendly icon of the view.
// If it has not been defined by the view the BOINC icon is returned.
//
const char** CBOINCBaseView::GetViewIcon() {
wxASSERT(boinc_xpm);
return boinc_xpm;
}
// The rate at which the view is refreshed.
// If it has not been defined by the view 1 second is retrned.
//
int CBOINCBaseView::GetViewRefreshRate() {
return 1;
}
// Get bit mask of current view(s).
//
int CBOINCBaseView::GetViewCurrentViewPage() {
return 0;
}
wxString CBOINCBaseView::GetKeyValue1(int) {
return wxEmptyString;
}
wxString CBOINCBaseView::GetKeyValue2(int) {
return wxEmptyString;
}
int CBOINCBaseView::FindRowIndexByKeyValues(wxString&, wxString&) {
return -1;
}
bool CBOINCBaseView::FireOnSaveState(wxConfigBase* pConfig) {
return OnSaveState(pConfig);
}
bool CBOINCBaseView::FireOnRestoreState(wxConfigBase* pConfig) {
return OnRestoreState(pConfig);
}
int CBOINCBaseView::GetListRowCount() {
wxASSERT(m_pListPane);
return m_pListPane->GetItemCount();
}
void CBOINCBaseView::FireOnListRender(wxTimerEvent& event) {
OnListRender(event);
}
void CBOINCBaseView::FireOnListSelected(wxListEvent& event) {
OnListSelected(event);
}
void CBOINCBaseView::FireOnListDeselected(wxListEvent& event) {
OnListDeselected(event);
}
wxString CBOINCBaseView::FireOnListGetItemText(long item, long column) const {
return OnListGetItemText(item, column);
}
int CBOINCBaseView::FireOnListGetItemImage(long item) const {
return OnListGetItemImage(item);
}
void CBOINCBaseView::OnListRender(wxTimerEvent& event) {
if (!m_bProcessingListRenderEvent) {
m_bProcessingListRenderEvent = true;
wxASSERT(m_pListPane);
// Remember the key values of currently selected items
SaveSelections();
int iDocCount = GetDocCount();
int iCacheCount = GetCacheCount();
if (iDocCount != iCacheCount) {
if (0 >= iDocCount) {
EmptyCache();
m_pListPane->DeleteAllItems();
} else {
int iIndex = 0;
int iReturnValue = -1;
if (iDocCount > iCacheCount) {
for (iIndex = 0; iIndex < (iDocCount - iCacheCount); iIndex++) {
iReturnValue = AddCacheElement();
wxASSERT(!iReturnValue);
}
wxASSERT(GetDocCount() == GetCacheCount());
m_pListPane->SetItemCount(iDocCount);
m_bNeedSort = true;
} else {
// The virtual ListCtrl keeps a separate its list of selected rows;
// make sure it does not reference any rows beyond the new last row.
// We can ClearSelections() because we called SaveSelections() above.
ClearSelections();
m_pListPane->SetItemCount(iDocCount);
for (iIndex = (iCacheCount - 1); iIndex >= iDocCount; --iIndex) {
iReturnValue = RemoveCacheElement();
wxASSERT(!iReturnValue);
}
wxASSERT(GetDocCount() == GetCacheCount());
//fprintf(stderr, "CBOINCBaseView::OnListRender(): m_pListPane->RefreshItems(0, %d)\n", iDocCount - 1);
m_pListPane->RefreshItems(0, iDocCount - 1);
#ifdef __WXGTK__
// Work around an apparent bug in wxWidgets 3.0
// which drew blank lines at the top and failed
// to draw the bottom items. This could happen
// if the list was scrolled near the bottom and
// the user selected "Show active tasks."
m_pListPane->EnsureVisible(iDocCount - 1);
#endif
m_bNeedSort = true;
}
}
}
if (iDocCount > 0) {
SynchronizeCache();
if (iDocCount > 1) {
if (_EnsureLastItemVisible() && (iDocCount != iCacheCount)) {
m_pListPane->EnsureVisible(iDocCount - 1);
}
}
}
// Find the previously selected items by their key values and reselect them
RestoreSelections();
UpdateSelection();
m_bProcessingListRenderEvent = false;
}
event.Skip();
}
bool CBOINCBaseView::OnSaveState(wxConfigBase* pConfig) {
bool bReturnValue = true;
wxASSERT(pConfig);
wxASSERT(m_pTaskPane);
wxASSERT(m_pListPane);
if (!m_pTaskPane->OnSaveState(pConfig)) {
bReturnValue = false;
}
if (!m_pListPane->OnSaveState(pConfig)) {
bReturnValue = false;
}
return bReturnValue;
}
bool CBOINCBaseView::OnRestoreState(wxConfigBase* pConfig) {
wxASSERT(pConfig);
wxASSERT(m_pTaskPane);
wxASSERT(m_pListPane);
if (!m_pTaskPane->OnRestoreState(pConfig)) {
return false;
}
if (!m_pListPane->OnRestoreState(pConfig)) {
return false;
}
return true;
}
// We don't use this because multiple selection virtual
// wxListCtrl does not generate selection events for
// shift-click; see OnCheckSelectionChanged() below.
void CBOINCBaseView::OnListSelected(wxListEvent& event) {
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseView::OnListSelected - Function Begin"));
if (!m_bIgnoreUIEvents) {
m_bForceUpdateSelection = true;
UpdateSelection();
event.Skip();
}
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseView::OnListSelected - Function End"));
}
// We don't use this because multiple selection virtual
// wxListCtrl does generates deselection events only for
// control-click; see OnCheckSelectionChanged() below.
void CBOINCBaseView::OnListDeselected(wxListEvent& event) {
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseView::OnListDeselected - Function Begin"));
if (!m_bIgnoreUIEvents) {
m_bForceUpdateSelection = true;
UpdateSelection();
event.Skip();
}
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseView::OnListDeselected - Function End"));
}
void CBOINCBaseView::OnCheckSelectionChanged(CCheckSelectionChangedEvent& ) {
CheckSelectionChanged();
}
void CBOINCBaseView::OnCacheHint(wxListEvent& ) {
CheckSelectionChanged();
}
// Work around features in multiple selection virtual wxListCtrl:
// * It does not send deselection events (except ctrl-click).
// * It does not send selection events if you add to selection
// using Shift_Click.
//
// We currently handle all selections and deselections here.
// On the Mac, this is called due to an event posted by CBOINCListCtrl::OnMouseDown().
// On Windows, it is called due to a EVT_LIST_CACHE_HINT from wxListCtrl.
void CBOINCBaseView::CheckSelectionChanged() {
int newSelectionCount = m_pListPane->GetSelectedItemCount();
long currentSelection = m_pListPane->GetFirstSelected();
if ((newSelectionCount != m_iPreviousSelectionCount) ||
(currentSelection != m_lPreviousFirstSelection)
) {
if (!m_bIgnoreUIEvents) {
m_bForceUpdateSelection = true;
UpdateSelection();
}
}
m_iPreviousSelectionCount = newSelectionCount;
m_lPreviousFirstSelection = currentSelection;
}
wxString CBOINCBaseView::OnListGetItemText(long WXUNUSED(item), long WXUNUSED(column)) const {
return wxString(wxT("Undefined"));
}
int CBOINCBaseView::OnListGetItemImage(long WXUNUSED(item)) const {
return -1;
}
int CBOINCBaseView::GetDocCount() {
return 0;
}
wxString CBOINCBaseView::OnDocGetItemImage(long WXUNUSED(item)) const {
return wxString(wxT("Undefined"));
}
wxString CBOINCBaseView::OnDocGetItemAttr(long WXUNUSED(item)) const {
return wxString(wxT("Undefined"));
}
int CBOINCBaseView::AddCacheElement() {
return -1;
}
int CBOINCBaseView::EmptyCache() {
return -1;
}
int CBOINCBaseView::GetCacheCount() {
return -1;
}
int CBOINCBaseView::RemoveCacheElement() {
return -1;
}
int CBOINCBaseView::SynchronizeCache() {
int iRowIndex = 0;
int iRowTotal = 0;
int iColumnIndex = 0;
int iColumnTotal = 0;
bool bNeedRefreshData = false;
iRowTotal = GetDocCount();
iColumnTotal = m_pListPane->GetColumnCount();
for (iRowIndex = 0; iRowIndex < iRowTotal; iRowIndex++) {
bNeedRefreshData = false;
for (iColumnIndex = 0; iColumnIndex < iColumnTotal; iColumnIndex++) {
if (SynchronizeCacheItem(iRowIndex, iColumnIndex)) {
#ifdef __WXMAC__
bNeedRefreshData = true;
#else
// To reduce flicker, refresh only changed columns
m_pListPane->RefreshCell(iRowIndex, iColumnIndex);
#endif
if (iColumnIndex >= 0) {
if (m_iColumnIndexToColumnID[iColumnIndex] == m_iSortColumnID) {
m_bNeedSort = true;
}
}
}
}
// Mac is double-buffered to avoid flicker, so this is more efficient
if (bNeedRefreshData) {
m_pListPane->RefreshItem(iRowIndex);
}
}
if (m_bNeedSort) {
sortData(); // Will mark moved items as needing refresh
m_bNeedSort = false;
}
return 0;
}
bool CBOINCBaseView::SynchronizeCacheItem(wxInt32 WXUNUSED(iRowIndex), wxInt32 WXUNUSED(iColumnIndex)) {
return false;
}
void CBOINCBaseView::OnColClick(wxListEvent& event) {
wxListItem item;
int newSortColIndex = event.GetColumn();
int oldSortColIndex = -1;
if (newSortColIndex < 0) return; // Clicked past last column
if (m_iSortColumnID >= 0) {
oldSortColIndex = m_iColumnIDToColumnIndex[m_iSortColumnID];
}
item.SetMask(wxLIST_MASK_IMAGE);
if (newSortColIndex == oldSortColIndex) {
m_bReverseSort = !m_bReverseSort;
SetSortColumn(newSortColIndex);
} else {
// Remove sort arrow from old sort column
if (oldSortColIndex >= 0) {
item.SetImage(-1);
m_pListPane->SetColumn(oldSortColIndex, item);
}
m_iSortColumnID = m_iColumnIndexToColumnID[newSortColIndex];
m_bReverseSort = false;
SetSortColumn(newSortColIndex);
}
// Write the change to the registry
// Do this here because SetListColumnOrder() can call SetSortColumn()
// even when neither m_iSortColumnID nor m_bReverseSort changes
wxConfigBase* pConfig = wxConfigBase::Get(false);
pConfig->SetPath(wxT("/") + GetViewName());
m_pListPane->OnSaveState(pConfig);
}
void CBOINCBaseView::SetSortColumn(int newSortColIndex) {
wxListItem item;
int i, j, m;
wxArrayInt selections;
item.SetImage(m_bReverseSort ? 0 : 1);
m_pListPane->SetColumn(newSortColIndex, item);
Freeze(); // To reduce flicker
// Remember which cache elements are selected and deselect them
m_bIgnoreUIEvents = true;
i = -1;
while (1) {
i = m_pListPane->GetNextSelected(i);
if (i < 0) break;
selections.Add(m_iSortedIndexes[i]);
m_pListPane->SelectRow(i, false);
}
sortData();
// Reselect previously selected cache elements in the sorted list
m = (int)selections.GetCount();
for (i=0; i= 0) {
j = m_iSortedIndexes.Index(selections[i]);
m_pListPane->SelectRow(j, true);
}
}
m_bIgnoreUIEvents = false;
Thaw();
}
void CBOINCBaseView::InitSort() {
wxListItem item;
if (m_iSortColumnID < 0) return;
int newSortColIndex = m_iColumnIDToColumnIndex[m_iSortColumnID];
if (newSortColIndex < 0) return;
item.SetMask(wxLIST_MASK_IMAGE);
item.SetImage(m_bReverseSort ? 0 : 1);
m_pListPane->SetColumn(newSortColIndex, item);
Freeze(); // To reduce flicker
sortData();
Thaw();
}
void CBOINCBaseView::sortData() {
if (m_iSortColumnID < 0) return;
if (m_iColumnIDToColumnIndex[m_iSortColumnID] < 0) return;
wxArrayInt oldSortedIndexes(m_iSortedIndexes);
int i, n = (int)m_iSortedIndexes.GetCount();
std::stable_sort(m_iSortedIndexes.begin(), m_iSortedIndexes.end(), m_funcSortCompare);
// Refresh rows which have moved
for (i=0; iRefreshItem(i);
}
}
}
void CBOINCBaseView::EmptyTasks() {
unsigned int i;
unsigned int j;
for (i=0; im_Tasks.size(); j++) {
delete m_TaskGroups[i]->m_Tasks[j];
}
m_TaskGroups[i]->m_Tasks.clear();
delete m_TaskGroups[i];
}
m_TaskGroups.clear();
}
void CBOINCBaseView::ClearSavedSelections() {
m_arrSelectedKeys1.Clear();
m_arrSelectedKeys2.Clear();
}
// Save the key values of the currently selected rows for later restore
void CBOINCBaseView::SaveSelections() {
if (!_IsSelectionManagementNeeded()) {
return;
}
m_arrSelectedKeys1.Clear();
m_arrSelectedKeys2.Clear();
m_bIgnoreUIEvents = true;
int i = -1;
while (1) {
i = m_pListPane->GetNextSelected(i);
if (i < 0) break;
m_arrSelectedKeys1.Add(GetKeyValue1(i));
m_arrSelectedKeys2.Add(GetKeyValue2(i));
}
m_bIgnoreUIEvents = false;
}
// Select all rows with formerly selected data based on key values
//
// Each RPC may add (insert) or delete items from the list, so
// the selected row numbers may now point to different data.
// We called SaveSelections() before updating the underlying
// data; this routine finds the data corresponding to each
// previous selection and makes any adjustments to ensure that
// the rows containing the originally selected data are selected.
void CBOINCBaseView::RestoreSelections() {
if (!_IsSelectionManagementNeeded()) {
return;
}
// To minimize flicker, this method selects or deselects only
// those rows which actually need their selection status changed.
// First, get a list of which rows should be selected
int i, j, m = 0, newCount = 0, oldCount = (int)m_arrSelectedKeys1.size();
bool found;
wxArrayInt arrSelRows;
for(i=0; i< oldCount; ++i) {
int index = FindRowIndexByKeyValues(m_arrSelectedKeys1[i], m_arrSelectedKeys2[i]);
if(index >= 0) {
arrSelRows.Add(index);
}
}
newCount = (int)arrSelRows.GetCount();
// Step through the currently selected row numbers and for each one determine
// whether it should remain selected.
m_bIgnoreUIEvents = true;
i = -1;
while (1) {
found = false;
i = m_pListPane->GetNextSelected(i);
if (i < 0) break;
m = (int)arrSelRows.GetCount();
for (j=0; jSelectRow(i, false); // This row should no longer be selected
}
}
// Now select those rows which were not previously selected but should now be
m = (int)arrSelRows.GetCount();
for (j=0; jSelectRow(arrSelRows[j], true);
}
m_bIgnoreUIEvents = false;
if (oldCount != newCount) {
m_bForceUpdateSelection = true; // OnListRender() will call UpdateSelection()
}
}
void CBOINCBaseView::ClearSelections() {
if (!m_pListPane) return;
m_bIgnoreUIEvents = true;
int i = -1;
while (1) {
i = m_pListPane->GetNextSelected(i);
if (i < 0) break;
m_pListPane->SelectRow(i, false);
}
m_bIgnoreUIEvents = false;
}
void CBOINCBaseView::PreUpdateSelection(){
}
void CBOINCBaseView::UpdateSelection(){
}
void CBOINCBaseView::PostUpdateSelection(){
wxASSERT(m_pTaskPane);
if (m_pTaskPane->UpdateControls()) {
// Under wxWidgets 2.9.4, Layout() causes ListCtrl
// to repaint, so call only when actually needed.
Layout();
}
}
void CBOINCBaseView::UpdateWebsiteSelection(long lControlGroup, PROJECT* project){
unsigned int i;
CTaskItemGroup* pGroup = NULL;
CTaskItem* pItem = NULL;
wxASSERT(m_pTaskPane);
wxASSERT(m_pListPane);
if (m_bForceUpdateSelection) {
// Update the websites list
//
if (m_TaskGroups.size() > 1) {
// Delete task group, objects, and controls.
pGroup = m_TaskGroups[lControlGroup];
m_pTaskPane->DeleteTaskGroupAndTasks(pGroup);
for (i=0; im_Tasks.size(); i++) {
delete pGroup->m_Tasks[i];
}
pGroup->m_Tasks.clear();
delete pGroup;
pGroup = NULL;
m_TaskGroups.erase( m_TaskGroups.begin() + 1 );
}
// If something is selected create the tasks and controls
//
if (m_pListPane->GetSelectedItemCount()) {
if (project) {
// Create the web sites task group
pGroup = new CTaskItemGroup( _("Project web pages") );
m_TaskGroups.push_back( pGroup );
// Default project url
pItem = new CTaskItem(
wxString("Home page", wxConvUTF8),
wxString(project->project_name.c_str(), wxConvUTF8) + wxT(" web site"),
wxString(project->master_url, wxConvUTF8),
ID_TASK_PROJECT_WEB_PROJDEF_MIN
);
pGroup->m_Tasks.push_back(pItem);
// Project defined urls
for (i=0;(igui_urls.size())&&(i<=ID_TASK_PROJECT_WEB_PROJDEF_MAX);i++) {
pItem = new CTaskItem(
wxGetTranslation(wxString(project->gui_urls[i].name.c_str(), wxConvUTF8)),
wxGetTranslation(wxString(project->gui_urls[i].description.c_str(), wxConvUTF8)),
wxString(project->gui_urls[i].url.c_str(), wxConvUTF8),
ID_TASK_PROJECT_WEB_PROJDEF_MIN + 1 + i
);
pGroup->m_Tasks.push_back(pItem);
}
}
}
m_pTaskPane->FitInside();
m_bForceUpdateSelection = false;
}
}
// Make sure task pane background is properly erased
void CBOINCBaseView::RefreshTaskPane() {
if (m_pTaskPane) {
m_pTaskPane->Refresh(true);
}
}
#ifdef __WXMAC__
// Fix Keyboard navigation on Mac
//
// NOTE: to select an item in wxListCtrl when none
// has yet been selected, press tab and then space.
#define SHIFT_MASK (1<<17)
void CBOINCBaseView::OnKeyPressed(wxKeyEvent &event) {
wxWindow next;
CTaskItemGroup* pGroup = NULL;
CTaskItem* pItem = NULL;
int i, j;
bool focusOK = false;
if (m_pTaskPane) {
int keyCode = event.GetKeyCode();
wxUint32 keyFlags = event.GetRawKeyFlags();
if (keyCode == WXK_TAB) {
wxWindow* focused = wxWindow::FindFocus();
if (!m_pTaskPane->IsDescendant(focused)) {
if (keyFlags & SHIFT_MASK) {
for (i=m_TaskGroups.size()-1; i>=0; --i) {
pGroup = m_TaskGroups[i];
for (j=pGroup->m_Tasks.size()-1; j>=0; --j) {
pItem = pGroup->m_Tasks[j];
if (pItem->m_pButton) {
if (pItem->m_pButton->CanAcceptFocus()) {
focusOK = true;
break;
}
}
}
if (focusOK) break;
}
} else {
for (i=0; im_Tasks.size(); ++j) {
pItem = pGroup->m_Tasks[j];
if (pItem->m_pButton) {
if (pItem->m_pButton->CanAcceptFocus()) {
focusOK = true;
break;
}
}
}
if (focusOK) break;
}
}
if (focusOK) {
pItem->m_pButton->SetFocus();
return;
}
}
wxNavigationKeyEvent evt;
evt.SetDirection((keyFlags & SHIFT_MASK) == 0);
evt.SetFromTab(true);
m_pTaskPane->GetEventHandler()->AddPendingEvent(evt);
return;
}
}
event.Skip();
}
#endif
bool CBOINCBaseView::_IsSelectionManagementNeeded() {
return IsSelectionManagementNeeded();
}
bool CBOINCBaseView::IsSelectionManagementNeeded() {
return false;
}
bool CBOINCBaseView::_EnsureLastItemVisible() {
return EnsureLastItemVisible();
}
bool CBOINCBaseView::EnsureLastItemVisible() {
return false;
}
double CBOINCBaseView::GetProgressValue(long) {
return 0.0;
}
wxString CBOINCBaseView::GetProgressText( long ) {
return wxEmptyString;
}
void CBOINCBaseView::AppendColumn(int){
}
void CBOINCBaseView::append_to_status(wxString& existing, const wxChar* additional) {
if (existing.size() == 0) {
existing = additional;
} else {
existing = existing + wxT(", ") + additional;
}
}
// HTML Entity Conversion:
// http://www.webreference.com/html/reference/character/
// Completed: The ISO Latin 1 Character Set
//
wxString CBOINCBaseView::HtmlEntityEncode(wxString strRaw) {
wxString strEncodedHtml(strRaw);
#ifdef __WXMSW__
strEncodedHtml.Replace(wxT("&"), wxT("&"), true);
strEncodedHtml.Replace(wxT("\""), wxT("""), true);
strEncodedHtml.Replace(wxT("<"), wxT("<"), true);
strEncodedHtml.Replace(wxT(">"), wxT(">"), true);
strEncodedHtml.Replace(wxT("‚"), wxT("‚"), true);
strEncodedHtml.Replace(wxT("ƒ"), wxT("ƒ"), true);
strEncodedHtml.Replace(wxT("„"), wxT("„"), true);
strEncodedHtml.Replace(wxT("…"), wxT("…"), true);
strEncodedHtml.Replace(wxT("†"), wxT("†"), true);
strEncodedHtml.Replace(wxT("‡"), wxT("‡"), true);
strEncodedHtml.Replace(wxT("Š"), wxT("Š"), true);
strEncodedHtml.Replace(wxT("Œ"), wxT("Œ"), true);
strEncodedHtml.Replace(wxT("‘"), wxT("‘"), true);
strEncodedHtml.Replace(wxT("’"), wxT("’"), true);
strEncodedHtml.Replace(wxT("“"), wxT("“"), true);
strEncodedHtml.Replace(wxT("”"), wxT("”"), true);
strEncodedHtml.Replace(wxT("•"), wxT("•"), true);
strEncodedHtml.Replace(wxT("–"), wxT("–"), true);
strEncodedHtml.Replace(wxT("—"), wxT("—"), true);
strEncodedHtml.Replace(wxT("˜˜~"), wxT("˜"), true);
strEncodedHtml.Replace(wxT("™"), wxT("™"), true);
strEncodedHtml.Replace(wxT("š"), wxT("š"), true);
strEncodedHtml.Replace(wxT("œ"), wxT("œ"), true);
strEncodedHtml.Replace(wxT("Ÿ"), wxT("Ÿ"), true);
strEncodedHtml.Replace(wxT("¡"), wxT("¡"), true);
strEncodedHtml.Replace(wxT("¢"), wxT("¢"), true);
strEncodedHtml.Replace(wxT("£"), wxT("£"), true);
strEncodedHtml.Replace(wxT("¤"), wxT("¤"), true);
strEncodedHtml.Replace(wxT("¥"), wxT("¥"), true);
strEncodedHtml.Replace(wxT("¦"), wxT("¦"), true);
strEncodedHtml.Replace(wxT("§"), wxT("§"), true);
strEncodedHtml.Replace(wxT("¨"), wxT("¨"), true);
strEncodedHtml.Replace(wxT("©"), wxT("©"), true);
strEncodedHtml.Replace(wxT("ª"), wxT("ª"), true);
strEncodedHtml.Replace(wxT("«"), wxT("«"), true);
strEncodedHtml.Replace(wxT("¬"), wxT("¬"), true);
strEncodedHtml.Replace(wxT("®"), wxT("®"), true);
strEncodedHtml.Replace(wxT("¯"), wxT("¯"), true);
strEncodedHtml.Replace(wxT("°"), wxT("°"), true);
strEncodedHtml.Replace(wxT("±"), wxT("±"), true);
strEncodedHtml.Replace(wxT("²"), wxT("²"), true);
strEncodedHtml.Replace(wxT("³"), wxT("³"), true);
strEncodedHtml.Replace(wxT("´"), wxT("´"), true);
strEncodedHtml.Replace(wxT("µ"), wxT("µ"), true);
strEncodedHtml.Replace(wxT("¶"), wxT("¶"), true);
strEncodedHtml.Replace(wxT("·"), wxT("·"), true);
strEncodedHtml.Replace(wxT("¸"), wxT("¸"), true);
strEncodedHtml.Replace(wxT("¹"), wxT("¹"), true);
strEncodedHtml.Replace(wxT("º"), wxT("º"), true);
strEncodedHtml.Replace(wxT("»"), wxT("»"), true);
strEncodedHtml.Replace(wxT("¼"), wxT("¼"), true);
strEncodedHtml.Replace(wxT("½"), wxT("½"), true);
strEncodedHtml.Replace(wxT("¾"), wxT("¾"), true);
strEncodedHtml.Replace(wxT("¿"), wxT("¿"), true);
strEncodedHtml.Replace(wxT("À"), wxT("À"), true);
strEncodedHtml.Replace(wxT("Á"), wxT("Á"), true);
strEncodedHtml.Replace(wxT("Â"), wxT("Â"), true);
strEncodedHtml.Replace(wxT("Ã"), wxT("Ã"), true);
strEncodedHtml.Replace(wxT("Ä"), wxT("Ä"), true);
strEncodedHtml.Replace(wxT("Å"), wxT("Å"), true);
strEncodedHtml.Replace(wxT("Æ"), wxT("Æ"), true);
strEncodedHtml.Replace(wxT("Ç"), wxT("Ç"), true);
strEncodedHtml.Replace(wxT("È"), wxT("È"), true);
strEncodedHtml.Replace(wxT("É"), wxT("É"), true);
strEncodedHtml.Replace(wxT("Ê"), wxT("Ê"), true);
strEncodedHtml.Replace(wxT("Ë"), wxT("Ë"), true);
strEncodedHtml.Replace(wxT("Ì"), wxT("Ì"), true);
strEncodedHtml.Replace(wxT("Í"), wxT("Í"), true);
strEncodedHtml.Replace(wxT("Î"), wxT("Î"), true);
strEncodedHtml.Replace(wxT("Ï"), wxT("Ï"), true);
strEncodedHtml.Replace(wxT("Ð"), wxT("Ð"), true);
strEncodedHtml.Replace(wxT("Ñ"), wxT("Ñ"), true);
strEncodedHtml.Replace(wxT("Ò"), wxT("Ò"), true);
strEncodedHtml.Replace(wxT("Ó"), wxT("Ó"), true);
strEncodedHtml.Replace(wxT("Ô"), wxT("Ô"), true);
strEncodedHtml.Replace(wxT("Õ"), wxT("Õ"), true);
strEncodedHtml.Replace(wxT("Ö"), wxT("Ö"), true);
strEncodedHtml.Replace(wxT("×"), wxT("×"), true);
strEncodedHtml.Replace(wxT("Ø"), wxT("Ø"), true);
strEncodedHtml.Replace(wxT("Ù"), wxT("Ù"), true);
strEncodedHtml.Replace(wxT("Ú"), wxT("Ú"), true);
strEncodedHtml.Replace(wxT("Û"), wxT("Û"), true);
strEncodedHtml.Replace(wxT("Ü"), wxT("Ü"), true);
strEncodedHtml.Replace(wxT("Ý"), wxT("Ý"), true);
strEncodedHtml.Replace(wxT("Þ"), wxT("Þ"), true);
strEncodedHtml.Replace(wxT("ß"), wxT("ß"), true);
strEncodedHtml.Replace(wxT("à"), wxT("à"), true);
strEncodedHtml.Replace(wxT("á"), wxT("á"), true);
strEncodedHtml.Replace(wxT("â"), wxT("â"), true);
strEncodedHtml.Replace(wxT("ã"), wxT("ã"), true);
strEncodedHtml.Replace(wxT("ä"), wxT("ä"), true);
strEncodedHtml.Replace(wxT("å"), wxT("å"), true);
strEncodedHtml.Replace(wxT("æ"), wxT("æ"), true);
strEncodedHtml.Replace(wxT("ç"), wxT("ç"), true);
strEncodedHtml.Replace(wxT("è"), wxT("è"), true);
strEncodedHtml.Replace(wxT("é"), wxT("é"), true);
strEncodedHtml.Replace(wxT("ê"), wxT("ê"), true);
strEncodedHtml.Replace(wxT("ë"), wxT("ë"), true);
strEncodedHtml.Replace(wxT("ì"), wxT("ì"), true);
strEncodedHtml.Replace(wxT("í"), wxT("í"), true);
strEncodedHtml.Replace(wxT("î"), wxT("î"), true);
strEncodedHtml.Replace(wxT("ï"), wxT("ï"), true);
strEncodedHtml.Replace(wxT("ð"), wxT("ð"), true);
strEncodedHtml.Replace(wxT("ñ"), wxT("ñ"), true);
strEncodedHtml.Replace(wxT("ò"), wxT("ò"), true);
strEncodedHtml.Replace(wxT("ó"), wxT("ó"), true);
strEncodedHtml.Replace(wxT("ô"), wxT("ô"), true);
strEncodedHtml.Replace(wxT("õ"), wxT("õ"), true);
strEncodedHtml.Replace(wxT("ö"), wxT("ö"), true);
strEncodedHtml.Replace(wxT("÷"), wxT("÷"), true);
strEncodedHtml.Replace(wxT("ø"), wxT("ø"), true);
strEncodedHtml.Replace(wxT("ù"), wxT("ù"), true);
strEncodedHtml.Replace(wxT("ú"), wxT("ú"), true);
strEncodedHtml.Replace(wxT("û"), wxT("û"), true);
strEncodedHtml.Replace(wxT("ü"), wxT("ü"), true);
strEncodedHtml.Replace(wxT("ý"), wxT("ý"), true);
strEncodedHtml.Replace(wxT("þ"), wxT("þ"), true);
strEncodedHtml.Replace(wxT("ÿ"), wxT("ÿ"), true);
#endif
return strEncodedHtml;
}
wxString CBOINCBaseView::HtmlEntityDecode(wxString strRaw) {
wxString strDecodedHtml(strRaw);
if (0 <= strDecodedHtml.Find(wxT("&"))) {
#ifdef __WXMSW__
strDecodedHtml.Replace(wxT("&"), wxT("&"), true);
strDecodedHtml.Replace(wxT("""), wxT("\""), true);
strDecodedHtml.Replace(wxT("<"), wxT("<"), true);
strDecodedHtml.Replace(wxT(">"), wxT(">"), true);
strDecodedHtml.Replace(wxT("‚"), wxT("‚"), true);
strDecodedHtml.Replace(wxT("ƒ"), wxT("ƒ"), true);
strDecodedHtml.Replace(wxT("„"), wxT("„"), true);
strDecodedHtml.Replace(wxT("…"), wxT("…"), true);
strDecodedHtml.Replace(wxT("†"), wxT("†"), true);
strDecodedHtml.Replace(wxT("‡"), wxT("‡"), true);
strDecodedHtml.Replace(wxT("Š"), wxT("Š"), true);
strDecodedHtml.Replace(wxT("Œ"), wxT("Œ"), true);
strDecodedHtml.Replace(wxT("‘"), wxT("‘"), true);
strDecodedHtml.Replace(wxT("’"), wxT("’"), true);
strDecodedHtml.Replace(wxT("“"), wxT("“"), true);
strDecodedHtml.Replace(wxT("”"), wxT("”"), true);
strDecodedHtml.Replace(wxT("•"), wxT("•"), true);
strDecodedHtml.Replace(wxT("–"), wxT("–"), true);
strDecodedHtml.Replace(wxT("—"), wxT("—"), true);
strDecodedHtml.Replace(wxT("˜"), wxT("˜˜~"), true);
strDecodedHtml.Replace(wxT("™"), wxT("™"), true);
strDecodedHtml.Replace(wxT("š"), wxT("š"), true);
strDecodedHtml.Replace(wxT("œ"), wxT("œ"), true);
strDecodedHtml.Replace(wxT("Ÿ"), wxT("Ÿ"), true);
strDecodedHtml.Replace(wxT("¡"), wxT("¡"), true);
strDecodedHtml.Replace(wxT("¢"), wxT("¢"), true);
strDecodedHtml.Replace(wxT("£"), wxT("£"), true);
strDecodedHtml.Replace(wxT("¤"), wxT("¤"), true);
strDecodedHtml.Replace(wxT("¥"), wxT("¥"), true);
strDecodedHtml.Replace(wxT("¦"), wxT("¦"), true);
strDecodedHtml.Replace(wxT("§"), wxT("§"), true);
strDecodedHtml.Replace(wxT("¨"), wxT("¨"), true);
strDecodedHtml.Replace(wxT("©"), wxT("©"), true);
strDecodedHtml.Replace(wxT("ª"), wxT("ª"), true);
strDecodedHtml.Replace(wxT("«"), wxT("«"), true);
strDecodedHtml.Replace(wxT("¬"), wxT("¬"), true);
strDecodedHtml.Replace(wxT("®"), wxT("®"), true);
strDecodedHtml.Replace(wxT("¯"), wxT("¯"), true);
strDecodedHtml.Replace(wxT("°"), wxT("°"), true);
strDecodedHtml.Replace(wxT("±"), wxT("±"), true);
strDecodedHtml.Replace(wxT("²"), wxT("²"), true);
strDecodedHtml.Replace(wxT("³"), wxT("³"), true);
strDecodedHtml.Replace(wxT("´"), wxT("´"), true);
strDecodedHtml.Replace(wxT("µ"), wxT("µ"), true);
strDecodedHtml.Replace(wxT("¶"), wxT("¶"), true);
strDecodedHtml.Replace(wxT("·"), wxT("·"), true);
strDecodedHtml.Replace(wxT("¸"), wxT("¸"), true);
strDecodedHtml.Replace(wxT("¹"), wxT("¹"), true);
strDecodedHtml.Replace(wxT("º"), wxT("º"), true);
strDecodedHtml.Replace(wxT("»"), wxT("»"), true);
strDecodedHtml.Replace(wxT("¼"), wxT("¼"), true);
strDecodedHtml.Replace(wxT("½"), wxT("½"), true);
strDecodedHtml.Replace(wxT("¾"), wxT("¾"), true);
strDecodedHtml.Replace(wxT("¿"), wxT("¿"), true);
strDecodedHtml.Replace(wxT("À"), wxT("À"), true);
strDecodedHtml.Replace(wxT("Á"), wxT("Á"), true);
strDecodedHtml.Replace(wxT("Â"), wxT("Â"), true);
strDecodedHtml.Replace(wxT("Ã"), wxT("Ã"), true);
strDecodedHtml.Replace(wxT("Ä"), wxT("Ä"), true);
strDecodedHtml.Replace(wxT("Å"), wxT("Å"), true);
strDecodedHtml.Replace(wxT("Æ"), wxT("Æ"), true);
strDecodedHtml.Replace(wxT("Ç"), wxT("Ç"), true);
strDecodedHtml.Replace(wxT("È"), wxT("È"), true);
strDecodedHtml.Replace(wxT("É"), wxT("É"), true);
strDecodedHtml.Replace(wxT("Ê"), wxT("Ê"), true);
strDecodedHtml.Replace(wxT("Ë"), wxT("Ë"), true);
strDecodedHtml.Replace(wxT("Ì"), wxT("Ì"), true);
strDecodedHtml.Replace(wxT("Í"), wxT("Í"), true);
strDecodedHtml.Replace(wxT("Î"), wxT("Î"), true);
strDecodedHtml.Replace(wxT("Ï"), wxT("Ï"), true);
strDecodedHtml.Replace(wxT("Ð"), wxT("Ð"), true);
strDecodedHtml.Replace(wxT("Ñ"), wxT("Ñ"), true);
strDecodedHtml.Replace(wxT("Ò"), wxT("Ò"), true);
strDecodedHtml.Replace(wxT("Ó"), wxT("Ó"), true);
strDecodedHtml.Replace(wxT("Ô"), wxT("Ô"), true);
strDecodedHtml.Replace(wxT("Õ"), wxT("Õ"), true);
strDecodedHtml.Replace(wxT("Ö"), wxT("Ö"), true);
strDecodedHtml.Replace(wxT("×"), wxT("×"), true);
strDecodedHtml.Replace(wxT("Ø"), wxT("Ø"), true);
strDecodedHtml.Replace(wxT("Ù"), wxT("Ù"), true);
strDecodedHtml.Replace(wxT("Ú"), wxT("Ú"), true);
strDecodedHtml.Replace(wxT("Û"), wxT("Û"), true);
strDecodedHtml.Replace(wxT("Ü"), wxT("Ü"), true);
strDecodedHtml.Replace(wxT("Ý"), wxT("Ý"), true);
strDecodedHtml.Replace(wxT("Þ"), wxT("Þ"), true);
strDecodedHtml.Replace(wxT("ß"), wxT("ß"), true);
strDecodedHtml.Replace(wxT("à"), wxT("à"), true);
strDecodedHtml.Replace(wxT("á"), wxT("á"), true);
strDecodedHtml.Replace(wxT("â"), wxT("â"), true);
strDecodedHtml.Replace(wxT("ã"), wxT("ã"), true);
strDecodedHtml.Replace(wxT("ä"), wxT("ä"), true);
strDecodedHtml.Replace(wxT("å"), wxT("å"), true);
strDecodedHtml.Replace(wxT("æ"), wxT("æ"), true);
strDecodedHtml.Replace(wxT("ç"), wxT("ç"), true);
strDecodedHtml.Replace(wxT("è"), wxT("è"), true);
strDecodedHtml.Replace(wxT("é"), wxT("é"), true);
strDecodedHtml.Replace(wxT("ê"), wxT("ê"), true);
strDecodedHtml.Replace(wxT("ë"), wxT("ë"), true);
strDecodedHtml.Replace(wxT("ì"), wxT("ì"), true);
strDecodedHtml.Replace(wxT("í"), wxT("í"), true);
strDecodedHtml.Replace(wxT("î"), wxT("î"), true);
strDecodedHtml.Replace(wxT("ï"), wxT("ï"), true);
strDecodedHtml.Replace(wxT("ð"), wxT("ð"), true);
strDecodedHtml.Replace(wxT("ñ"), wxT("ñ"), true);
strDecodedHtml.Replace(wxT("ò"), wxT("ò"), true);
strDecodedHtml.Replace(wxT("ó"), wxT("ó"), true);
strDecodedHtml.Replace(wxT("ô"), wxT("ô"), true);
strDecodedHtml.Replace(wxT("õ"), wxT("õ"), true);
strDecodedHtml.Replace(wxT("ö"), wxT("ö"), true);
strDecodedHtml.Replace(wxT("÷"), wxT("÷"), true);
strDecodedHtml.Replace(wxT("ø"), wxT("ø"), true);
strDecodedHtml.Replace(wxT("ù"), wxT("ù"), true);
strDecodedHtml.Replace(wxT("ú"), wxT("ú"), true);
strDecodedHtml.Replace(wxT("û"), wxT("û"), true);
strDecodedHtml.Replace(wxT("ü"), wxT("ü"), true);
strDecodedHtml.Replace(wxT("ý"), wxT("ý"), true);
strDecodedHtml.Replace(wxT("þ"), wxT("þ"), true);
strDecodedHtml.Replace(wxT("ÿ"), wxT("ÿ"), true);
#endif
}
return strDecodedHtml;
}