From 8ef066baeeb965a0067c687f9e0e2d26d4728418 Mon Sep 17 00:00:00 2001 From: rubidium Date: Thu, 22 Jan 2009 14:15:52 +0000 Subject: (svn r15207) -Add: sorting to the content list. --- src/network/network_content_gui.cpp | 142 ++++++++++++++++++++++++++++++++---- 1 file 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 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 */ -- cgit v1.2.3-54-g00ecf