summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/network/network_content_gui.cpp142
1 files changed, 129 insertions, 13 deletions
diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp
index bac705886..d25fde042 100644
--- a/src/network/network_content_gui.cpp
+++ b/src/network/network_content_gui.cpp
@@ -13,6 +13,7 @@
#include "../core/smallvec_type.hpp"
#include "../ai/ai.hpp"
#include "../gfxinit.h"
+#include "../sortlist_type.h"
#include "network_content.h"
#include "table/strings.h"
@@ -136,8 +137,8 @@ public:
virtual void OnClick(Point pt, int widget)
{
- if (widget == NCDSWW_CANCELOK && this->downloaded_bytes != this->total_bytes) {
- _network_content_client.Close();
+ if (widget == NCDSWW_CANCELOK) {
+ if (this->downloaded_bytes != this->total_bytes) _network_content_client.Close();
delete this;
}
}
@@ -158,6 +159,8 @@ public:
/** Window that lists the content that's at the content server */
class NetworkContentListWindow : public Window, ContentCallback {
+ typedef GUIList<const ContentInfo*> GUIContentList;
+
/** All widgets used */
enum Widgets {
NCLWW_CLOSE, ///< Close 'X' button
@@ -182,9 +185,76 @@ class NetworkContentListWindow : public Window, ContentCallback {
NCLWW_RESIZE, ///< Resize button
};
+ /** Runtime saved values */
+ static Listing last_sorting;
+ /** The sorter functions */
+ static GUIContentList::SortFunction * const sorter_funcs[];
+ GUIContentList content; ///< List with content
+
const ContentInfo *selected; ///< The selected content info
int list_pos; ///< Our position in the list
+ /**
+ * (Re)build the network game list as its amount has changed because
+ * an item has been added or deleted for example
+ */
+ void BuildContentList()
+ {
+ if (!this->content.NeedRebuild()) return;
+
+ /* Create temporary array of games to use for listing */
+ this->content.Clear();
+
+ for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
+ *this->content.Append() = *iter;
+ }
+
+ this->content.Compact();
+ this->content.RebuildDone();
+ }
+
+ /** Sort content by name. */
+ static int CDECL NameSorter(const ContentInfo * const *a, const ContentInfo * const *b)
+ {
+ return strcasecmp((*a)->name, (*b)->name);
+ }
+
+ /** Sort content by type. */
+ static int CDECL TypeSorter(const ContentInfo * const *a, const ContentInfo * const *b)
+ {
+ int r = 0;
+ if ((*a)->type != (*b)->type) {
+ char a_str[64];
+ char b_str[64];
+ GetString(a_str, STR_CONTENT_TYPE_BASE_GRAPHICS + (*a)->type - CONTENT_TYPE_BASE_GRAPHICS, lastof(a_str));
+ GetString(b_str, STR_CONTENT_TYPE_BASE_GRAPHICS + (*b)->type - CONTENT_TYPE_BASE_GRAPHICS, lastof(b_str));
+ r = strcasecmp(a_str, b_str);
+ }
+ if (r == 0) r = NameSorter(a, b);
+ return r;
+ }
+
+ /** Sort content by state. */
+ static int CDECL StateSorter(const ContentInfo * const *a, const ContentInfo * const *b)
+ {
+ int r = (*a)->state - (*b)->state;
+ if (r == 0) r = TypeSorter(a, b);
+ return r;
+ }
+
+ /** Sort the content list */
+ void SortContentList()
+ {
+ if (!this->content.Sort()) return;
+
+ for (ConstContentIterator iter = this->content.Begin(); iter != this->content.End(); iter++) {
+ if (*iter == this->selected) {
+ this->list_pos = iter - this->content.Begin();
+ break;
+ }
+ }
+ }
+
/** Make sure that the currently selected content info is within the visible part of the matrix */
void ScrollToSelected()
{
@@ -213,7 +283,12 @@ public:
_network_content_client.AddCallback(this);
this->HideWidget(select_all ? NCLWW_SELECT_UPDATE : NCLWW_SELECT_ALL);
- SetVScrollCount(this, _network_content_client.Length());
+ this->content.SetListing(this->last_sorting);
+ this->content.SetSortFuncs(this->sorter_funcs);
+ this->content.ForceRebuild();
+ this->SortContentList();
+
+ SetVScrollCount(this, this->content.Length());
this->FindWindowPlacementAndResize(desc);
}
@@ -225,11 +300,19 @@ public:
virtual void OnPaint()
{
+ const SortButtonState arrow = this->content.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
+
+ if (this->content.NeedRebuild()) {
+ this->BuildContentList();
+ SetVScrollCount(this, this->content.Length());
+ }
+ this->SortContentList();
+
/* To sum all the bytes we intend to download */
uint filesize = 0;
bool show_select_all = false;
bool show_select_upgrade = false;
- for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
+ for (ConstContentIterator iter = this->content.Begin(); iter != this->content.End(); iter++) {
const ContentInfo *ci = *iter;
switch (ci->state) {
case ContentInfo::SELECTED:
@@ -254,10 +337,16 @@ public:
this->DrawWidgets();
+ switch (this->content.SortType()) {
+ case NCLWW_CHECKBOX - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_CHECKBOX, arrow); break;
+ case NCLWW_TYPE - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_TYPE, arrow); break;
+ case NCLWW_NAME - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_NAME, arrow); break;
+ }
+
/* Fill the matrix with the information */
uint y = this->widget[NCLWW_MATRIX].top + 3;
int cnt = 0;
- for (ConstContentIterator iter = _network_content_client.Get(this->vscroll.pos); iter != _network_content_client.End() && cnt < this->vscroll.cap; iter++, cnt++) {
+ for (ConstContentIterator iter = this->content.Get(this->vscroll.pos); iter != this->content.End() && cnt < this->vscroll.cap; iter++, cnt++) {
const ContentInfo *ci = *iter;
if (ci == this->selected) GfxFillRect(this->widget[NCLWW_CHECKBOX].left + 1, y - 2, this->widget[NCLWW_NAME].right - 1, y + 9, 10);
@@ -402,14 +491,32 @@ public:
if (id_v >= _network_content_client.Length()) return; // click out of bounds
- this->selected = *_network_content_client.Get(id_v);
+ this->selected = *this->content.Get(id_v);
this->list_pos = id_v;
- if (pt.x <= this->widget[NCLWW_CHECKBOX].right) _network_content_client.ToggleSelectedState(this->selected);
+ if (pt.x <= this->widget[NCLWW_CHECKBOX].right) {
+ _network_content_client.ToggleSelectedState(this->selected);
+ this->content.ForceResort();
+ }
this->SetDirty();
} break;
+ case NCLWW_CHECKBOX:
+ case NCLWW_TYPE:
+ case NCLWW_NAME:
+ if (this->content.SortType() == widget - NCLWW_CHECKBOX) {
+ this->content.ToggleSortOrder();
+ this->list_pos = this->content.Length() - this->list_pos - 1;
+ } else {
+ this->content.SetSortType(widget - NCLWW_CHECKBOX);
+ this->content.ForceResort();
+ this->SortContentList();
+ }
+ this->ScrollToSelected();
+ this->SetDirty();
+ break;
+
case NCLWW_SELECT_ALL:
_network_content_client.SelectAll();
this->SetDirty();
@@ -445,7 +552,7 @@ public:
break;
case WKC_DOWN:
/* scroll down by one */
- if (this->list_pos < (int)_network_content_client.Length() - 1) this->list_pos++;
+ if (this->list_pos < (int)this->content.Length() - 1) this->list_pos++;
break;
case WKC_PAGEUP:
/* scroll up a page */
@@ -453,7 +560,7 @@ public:
break;
case WKC_PAGEDOWN:
/* scroll down a page */
- this->list_pos = min(this->list_pos + this->vscroll.cap, (int)_network_content_client.Length() - 1);
+ this->list_pos = min(this->list_pos + this->vscroll.cap, (int)this->content.Length() - 1);
break;
case WKC_HOME:
/* jump to beginning */
@@ -461,18 +568,19 @@ public:
break;
case WKC_END:
/* jump to end */
- this->list_pos = _network_content_client.Length() - 1;
+ this->list_pos = this->content.Length() - 1;
break;
case WKC_SPACE:
_network_content_client.ToggleSelectedState(this->selected);
+ this->content.ForceResort();
this->SetDirty();
return ES_HANDLED;
default: return ES_NOT_HANDLED;
}
- this->selected = *_network_content_client.Get(this->list_pos);
+ this->selected = *this->content.Get(this->list_pos);
/* scroll to the new server if it is outside the current range */
this->ScrollToSelected();
@@ -488,7 +596,7 @@ public:
this->widget[NCLWW_MATRIX].data = (this->vscroll.cap << 8) + 1;
- SetVScrollCount(this, _network_content_client.Length());
+ SetVScrollCount(this, this->content.Length());
/* Make the matrix and details section grow both bigger (or smaller) */
delta.x /= 2;
@@ -501,12 +609,13 @@ public:
virtual void OnReceiveContentInfo(const ContentInfo *rci)
{
- SetVScrollCount(this, _network_content_client.Length());
+ this->content.ForceRebuild();
this->SetDirty();
}
virtual void OnDownloadComplete(ContentID cid)
{
+ this->content.ForceResort();
this->SetDirty();
}
@@ -521,6 +630,13 @@ public:
}
};
+Listing NetworkContentListWindow::last_sorting = {false, 1};
+NetworkContentListWindow::GUIContentList::SortFunction * const NetworkContentListWindow::sorter_funcs[] = {
+ &StateSorter,
+ &TypeSorter,
+ &NameSorter,
+};
+
/** Widgets used for the content list */
static const Widget _network_content_list_widgets[] = {
/* TOP */