00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #if defined(ENABLE_NETWORK)
00013 #include "../stdafx.h"
00014 #include "../strings_func.h"
00015 #include "../gfx_func.h"
00016 #include "../window_func.h"
00017 #include "../gui.h"
00018 #include "../ai/ai.hpp"
00019 #include "../base_media_base.h"
00020 #include "../sortlist_type.h"
00021 #include "../querystring_gui.h"
00022 #include "network_content.h"
00023
00024 #include "table/strings.h"
00025 #include "../table/sprites.h"
00026
00028 enum DownloadStatusWindowWidgets {
00029 NCDSWW_BACKGROUND,
00030 NCDSWW_CANCELOK,
00031 };
00032
00034 static const NWidgetPart _nested_network_content_download_status_window_widgets[] = {
00035 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00036 NWidget(WWT_PANEL, COLOUR_GREY, NCDSWW_BACKGROUND),
00037 NWidget(NWID_SPACER), SetMinimalSize(350, 0), SetMinimalTextLines(3, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 30),
00038 NWidget(NWID_HORIZONTAL),
00039 NWidget(NWID_SPACER), SetMinimalSize(125, 0),
00040 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCDSWW_CANCELOK), SetMinimalSize(101, 12), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
00041 NWidget(NWID_SPACER), SetFill(1, 0),
00042 EndContainer(),
00043 NWidget(NWID_SPACER), SetMinimalSize(0, 4),
00044 EndContainer(),
00045 };
00046
00048 static const WindowDesc _network_content_download_status_window_desc(
00049 WDP_CENTER, 0, 0,
00050 WC_NETWORK_STATUS_WINDOW, WC_NONE,
00051 WDF_MODAL,
00052 _nested_network_content_download_status_window_widgets, lengthof(_nested_network_content_download_status_window_widgets)
00053 );
00054
00056 struct NetworkContentDownloadStatusWindow : public Window, ContentCallback {
00057 private:
00058 ClientNetworkContentSocketHandler *connection;
00059 SmallVector<ContentType, 4> receivedTypes;
00060
00061 uint total_files;
00062 uint downloaded_files;
00063 uint total_bytes;
00064 uint downloaded_bytes;
00065
00066 uint32 cur_id;
00067 char name[48];
00068
00069 public:
00075 NetworkContentDownloadStatusWindow() :
00076 cur_id(UINT32_MAX)
00077 {
00078 this->parent = FindWindowById(WC_NETWORK_WINDOW, 1);
00079
00080 _network_content_client.AddCallback(this);
00081 _network_content_client.DownloadSelectedContent(this->total_files, this->total_bytes);
00082
00083 this->InitNested(&_network_content_download_status_window_desc, 0);
00084 }
00085
00087 ~NetworkContentDownloadStatusWindow()
00088 {
00089
00090 for (ContentType *iter = this->receivedTypes.Begin(); iter != this->receivedTypes.End(); iter++) {
00091 switch (*iter) {
00092 case CONTENT_TYPE_AI:
00093 case CONTENT_TYPE_AI_LIBRARY:
00094 AI::Rescan();
00095 SetWindowClassesDirty(WC_AI_DEBUG);
00096 break;
00097
00098 case CONTENT_TYPE_BASE_GRAPHICS:
00099 BaseGraphics::FindSets();
00100 SetWindowDirty(WC_GAME_OPTIONS, 0);
00101 break;
00102
00103 case CONTENT_TYPE_BASE_SOUNDS:
00104 BaseSounds::FindSets();
00105 SetWindowDirty(WC_GAME_OPTIONS, 0);
00106 break;
00107
00108 case CONTENT_TYPE_NEWGRF:
00109 ScanNewGRFFiles();
00110
00111 InvalidateWindowClassesData(WC_SAVELOAD);
00112 InvalidateWindowData(WC_GAME_OPTIONS, 0, 1);
00113 break;
00114
00115 case CONTENT_TYPE_SCENARIO:
00116 case CONTENT_TYPE_HEIGHTMAP:
00117 extern void ScanScenarios();
00118 ScanScenarios();
00119 InvalidateWindowData(WC_SAVELOAD, 0, 0);
00120 break;
00121
00122 default:
00123 break;
00124 }
00125 }
00126
00127
00128 InvalidateWindowData(WC_NETWORK_WINDOW, 1, 2);
00129 _network_content_client.RemoveCallback(this);
00130 }
00131
00132 virtual void OnPaint()
00133 {
00134 this->DrawWidgets();
00135 }
00136
00137 virtual void DrawWidget(const Rect &r, int widget) const
00138 {
00139 if (widget != NCDSWW_BACKGROUND) return;
00140
00141
00142 DrawFrameRect(r.left + 20, r.top + 4, r.left + 20 + (int)((this->width - 40LL) * this->downloaded_bytes / this->total_bytes), r.top + 14, COLOUR_MAUVE, FR_NONE);
00143
00144 int y = r.top + 20;
00145 SetDParam(0, this->downloaded_bytes);
00146 SetDParam(1, this->total_bytes);
00147 SetDParam(2, this->downloaded_bytes * 100LL / this->total_bytes);
00148 DrawString(r.left + 2, r.right - 2, y, STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, TC_FROMSTRING, SA_CENTER);
00149
00150 StringID str;
00151 if (this->downloaded_bytes == this->total_bytes) {
00152 str = STR_CONTENT_DOWNLOAD_COMPLETE;
00153 } else if (!StrEmpty(this->name)) {
00154 SetDParamStr(0, this->name);
00155 SetDParam(1, this->downloaded_files);
00156 SetDParam(2, this->total_files);
00157 str = STR_CONTENT_DOWNLOAD_FILE;
00158 } else {
00159 str = STR_CONTENT_DOWNLOAD_INITIALISE;
00160 }
00161
00162 y += FONT_HEIGHT_NORMAL + 5;
00163 DrawStringMultiLine(r.left + 2, r.right - 2, y, y + FONT_HEIGHT_NORMAL * 2, str, TC_FROMSTRING, SA_CENTER);
00164 }
00165
00166 virtual void OnClick(Point pt, int widget)
00167 {
00168 if (widget == NCDSWW_CANCELOK) {
00169 if (this->downloaded_bytes != this->total_bytes) _network_content_client.Close();
00170 delete this;
00171 }
00172 }
00173
00174 virtual void OnDownloadProgress(const ContentInfo *ci, uint bytes)
00175 {
00176 if (ci->id != this->cur_id) {
00177 strecpy(this->name, ci->filename, lastof(this->name));
00178 this->cur_id = ci->id;
00179 this->downloaded_files++;
00180 this->receivedTypes.Include(ci->type);
00181 }
00182 this->downloaded_bytes += bytes;
00183
00184
00185 if (this->downloaded_bytes == this->total_bytes) {
00186 this->GetWidget<NWidgetCore>(NCDSWW_CANCELOK)->widget_data = STR_BUTTON_OK;
00187 }
00188
00189 this->SetDirty();
00190 }
00191 };
00192
00194 enum NetworkContentListWindowWidgets {
00195 NCLWW_BACKGROUND,
00196
00197 NCLWW_FILTER_CAPT,
00198 NCLWW_FILTER,
00199
00200 NCLWW_CHECKBOX,
00201 NCLWW_TYPE,
00202 NCLWW_NAME,
00203
00204 NCLWW_MATRIX,
00205 NCLWW_SCROLLBAR,
00206
00207 NCLWW_DETAILS,
00208
00209 NCLWW_SELECT_ALL,
00210 NCLWW_SELECT_UPDATE,
00211 NCLWW_UNSELECT,
00212 NCLWW_CANCEL,
00213 NCLWW_DOWNLOAD,
00214
00215 NCLWW_SEL_ALL_UPDATE,
00216 };
00217
00219 class NetworkContentListWindow : public QueryStringBaseWindow, ContentCallback {
00220 typedef GUIList<const ContentInfo*> GUIContentList;
00221
00222 enum {
00223 EDITBOX_MAX_SIZE = 50,
00224 EDITBOX_MAX_LENGTH = 300,
00225 };
00226
00228 static Listing last_sorting;
00229 static Filtering last_filtering;
00231 static GUIContentList::SortFunction * const sorter_funcs[];
00232 static GUIContentList::FilterFunction * const filter_funcs[];
00233 GUIContentList content;
00234
00235 const ContentInfo *selected;
00236 int list_pos;
00237 uint filesize_sum;
00238
00243 void BuildContentList()
00244 {
00245 if (!this->content.NeedRebuild()) return;
00246
00247
00248 this->content.Clear();
00249
00250 for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
00251 *this->content.Append() = *iter;
00252 }
00253
00254 this->FilterContentList();
00255 this->content.Compact();
00256 this->content.RebuildDone();
00257 this->SortContentList();
00258
00259 this->vscroll.SetCount(this->content.Length());
00260 this->ScrollToSelected();
00261 }
00262
00264 static int CDECL NameSorter(const ContentInfo * const *a, const ContentInfo * const *b)
00265 {
00266 return strcasecmp((*a)->name, (*b)->name);
00267 }
00268
00270 static int CDECL TypeSorter(const ContentInfo * const *a, const ContentInfo * const *b)
00271 {
00272 int r = 0;
00273 if ((*a)->type != (*b)->type) {
00274 char a_str[64];
00275 char b_str[64];
00276 GetString(a_str, STR_CONTENT_TYPE_BASE_GRAPHICS + (*a)->type - CONTENT_TYPE_BASE_GRAPHICS, lastof(a_str));
00277 GetString(b_str, STR_CONTENT_TYPE_BASE_GRAPHICS + (*b)->type - CONTENT_TYPE_BASE_GRAPHICS, lastof(b_str));
00278 r = strcasecmp(a_str, b_str);
00279 }
00280 if (r == 0) r = NameSorter(a, b);
00281 return r;
00282 }
00283
00285 static int CDECL StateSorter(const ContentInfo * const *a, const ContentInfo * const *b)
00286 {
00287 int r = (*a)->state - (*b)->state;
00288 if (r == 0) r = TypeSorter(a, b);
00289 return r;
00290 }
00291
00293 void SortContentList()
00294 {
00295 if (!this->content.Sort()) return;
00296
00297 for (ConstContentIterator iter = this->content.Begin(); iter != this->content.End(); iter++) {
00298 if (*iter == this->selected) {
00299 this->list_pos = iter - this->content.Begin();
00300 break;
00301 }
00302 }
00303 }
00304
00306 static bool CDECL TagNameFilter(const ContentInfo * const *a, const char *filter_string)
00307 {
00308 for (int i = 0; i < (*a)->tag_count; i++) {
00309 if (strcasestr((*a)->tags[i], filter_string) != NULL) return true;
00310 }
00311 return strcasestr((*a)->name, filter_string) != NULL;
00312 }
00313
00315 void FilterContentList()
00316 {
00317 if (!this->content.Filter(this->edit_str_buf)) return;
00318
00319
00320 for (ConstContentIterator iter = this->content.Begin(); iter != this->content.End(); iter++) {
00321 if (*iter == this->selected) {
00322 this->list_pos = iter - this->content.Begin();
00323 return;
00324 }
00325 }
00326
00327
00328 this->selected = NULL;
00329 this->list_pos = 0;
00330 }
00331
00333 void ScrollToSelected()
00334 {
00335 if (this->selected == NULL) return;
00336
00337 this->vscroll.ScrollTowards(this->list_pos);
00338 }
00339
00340 public:
00345 NetworkContentListWindow(const WindowDesc *desc, bool select_all) :
00346 QueryStringBaseWindow(EDITBOX_MAX_SIZE),
00347 selected(NULL),
00348 list_pos(0)
00349 {
00350 this->InitNested(desc, 1);
00351
00352 this->GetWidget<NWidgetStacked>(NCLWW_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all);
00353
00354 this->afilter = CS_ALPHANUMERAL;
00355 InitializeTextBuffer(&this->text, this->edit_str_buf, this->edit_str_size, EDITBOX_MAX_LENGTH);
00356 this->SetFocusedWidget(NCLWW_FILTER);
00357
00358 _network_content_client.AddCallback(this);
00359 this->content.SetListing(this->last_sorting);
00360 this->content.SetFiltering(this->last_filtering);
00361 this->content.SetSortFuncs(this->sorter_funcs);
00362 this->content.SetFilterFuncs(this->filter_funcs);
00363 this->content.ForceRebuild();
00364 this->FilterContentList();
00365 this->SortContentList();
00366 this->InvalidateData();
00367 }
00368
00370 ~NetworkContentListWindow()
00371 {
00372 _network_content_client.RemoveCallback(this);
00373 }
00374
00375 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00376 {
00377 switch (widget) {
00378 case NCLWW_FILTER_CAPT:
00379 *size = maxdim(*size, GetStringBoundingBox(STR_CONTENT_FILTER_TITLE));
00380 break;
00381
00382 case NCLWW_TYPE: {
00383 Dimension d = *size;
00384 for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
00385 d = maxdim(d, GetStringBoundingBox(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS));
00386 }
00387 size->width = d.width + WD_MATRIX_RIGHT + WD_MATRIX_LEFT;
00388 break;
00389 }
00390
00391 case NCLWW_MATRIX:
00392 resize->height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
00393 size->height = 10 * resize->height;
00394 break;
00395 }
00396 }
00397
00398
00399 virtual void DrawWidget(const Rect &r, int widget) const
00400 {
00401 switch (widget) {
00402 case NCLWW_FILTER_CAPT:
00403 DrawString(r.left, r.right, r.top, STR_CONTENT_FILTER_TITLE, TC_FROMSTRING, SA_RIGHT);
00404 break;
00405
00406 case NCLWW_DETAILS:
00407 this->DrawDetails(r);
00408 break;
00409
00410 case NCLWW_MATRIX:
00411 this->DrawMatrix(r);
00412 break;
00413 }
00414 }
00415
00416 virtual void OnPaint()
00417 {
00418 const SortButtonState arrow = this->content.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
00419
00420 if (this->content.NeedRebuild()) {
00421 this->BuildContentList();
00422 }
00423
00424 this->DrawWidgets();
00425
00426
00427 this->DrawEditBox(NCLWW_FILTER);
00428
00429 switch (this->content.SortType()) {
00430 case NCLWW_CHECKBOX - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_CHECKBOX, arrow); break;
00431 case NCLWW_TYPE - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_TYPE, arrow); break;
00432 case NCLWW_NAME - NCLWW_CHECKBOX: this->DrawSortButtonState(NCLWW_NAME, arrow); break;
00433 }
00434 }
00435
00436 void DrawMatrix(const Rect &r) const
00437 {
00438
00439 if (this->content.Length() == 0) return;
00440
00441 const NWidgetBase *nwi_checkbox = this->GetWidget<NWidgetBase>(NCLWW_CHECKBOX);
00442 const NWidgetBase *nwi_name = this->GetWidget<NWidgetBase>(NCLWW_NAME);
00443 const NWidgetBase *nwi_type = this->GetWidget<NWidgetBase>(NCLWW_TYPE);
00444
00445
00446
00447 int sprite_y_offset = WD_MATRIX_TOP + (FONT_HEIGHT_NORMAL - 10) / 2;
00448 uint y = r.top;
00449 int cnt = 0;
00450 for (ConstContentIterator iter = this->content.Get(this->vscroll.GetPosition()); iter != this->content.End() && cnt < this->vscroll.GetCapacity(); iter++, cnt++) {
00451 const ContentInfo *ci = *iter;
00452
00453 if (ci == this->selected) GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 1, 10);
00454
00455 SpriteID sprite;
00456 SpriteID pal = PAL_NONE;
00457 switch (ci->state) {
00458 case ContentInfo::UNSELECTED: sprite = SPR_BOX_EMPTY; break;
00459 case ContentInfo::SELECTED: sprite = SPR_BOX_CHECKED; break;
00460 case ContentInfo::AUTOSELECTED: sprite = SPR_BOX_CHECKED; break;
00461 case ContentInfo::ALREADY_HERE: sprite = SPR_BLOT; pal = PALETTE_TO_GREEN; break;
00462 case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
00463 default: NOT_REACHED();
00464 }
00465 DrawSprite(sprite, pal, nwi_checkbox->pos_x + (pal == PAL_NONE ? 2 : 3), y + sprite_y_offset + (pal == PAL_NONE ? 1 : 0));
00466
00467 StringID str = STR_CONTENT_TYPE_BASE_GRAPHICS + ci->type - CONTENT_TYPE_BASE_GRAPHICS;
00468 DrawString(nwi_type->pos_x, nwi_type->pos_x + nwi_type->current_x - 1, y + WD_MATRIX_TOP, str, TC_BLACK, SA_CENTER);
00469
00470 DrawString(nwi_name->pos_x + WD_FRAMERECT_LEFT, nwi_name->pos_x + nwi_name->current_x - WD_FRAMERECT_RIGHT, y + WD_MATRIX_TOP, ci->name, TC_BLACK);
00471 y += this->resize.step_height;
00472 }
00473 }
00474
00479 void DrawDetails(const Rect &r) const
00480 {
00481 static const int DETAIL_LEFT = 5;
00482 static const int DETAIL_RIGHT = 5;
00483 static const int DETAIL_TOP = 5;
00484
00485
00486 int DETAIL_TITLE_HEIGHT = 5 * FONT_HEIGHT_NORMAL;
00487
00488
00489 GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + DETAIL_TITLE_HEIGHT, 157);
00490 DrawString(r.left + WD_INSET_LEFT, r.right - WD_INSET_RIGHT, r.top + FONT_HEIGHT_NORMAL + WD_INSET_TOP, STR_CONTENT_DETAIL_TITLE, TC_FROMSTRING, SA_CENTER);
00491
00492
00493 SetDParam(0, this->filesize_sum);
00494 DrawString(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_NORMAL, STR_CONTENT_TOTAL_DOWNLOAD_SIZE);
00495
00496 if (this->selected == NULL) return;
00497
00498
00499 DrawStringMultiLine(r.left + WD_INSET_LEFT, r.right - WD_INSET_RIGHT, r.top + DETAIL_TITLE_HEIGHT / 2, r.top + DETAIL_TITLE_HEIGHT, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
00500
00501
00502 const uint max_y = r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_WIDE;
00503 int y = r.top + DETAIL_TITLE_HEIGHT + DETAIL_TOP;
00504
00505 if (this->selected->upgrade) {
00506 SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
00507 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_UPDATE);
00508 y += WD_PAR_VSEP_WIDE;
00509 }
00510
00511 SetDParamStr(0, this->selected->name);
00512 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_NAME);
00513
00514 if (!StrEmpty(this->selected->version)) {
00515 SetDParamStr(0, this->selected->version);
00516 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_VERSION);
00517 }
00518
00519 if (!StrEmpty(this->selected->description)) {
00520 SetDParamStr(0, this->selected->description);
00521 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DESCRIPTION);
00522 }
00523
00524 if (!StrEmpty(this->selected->url)) {
00525 SetDParamStr(0, this->selected->url);
00526 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL);
00527 }
00528
00529 SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
00530 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TYPE);
00531
00532 y += WD_PAR_VSEP_WIDE;
00533 SetDParam(0, this->selected->filesize);
00534 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_FILESIZE);
00535
00536 if (this->selected->dependency_count != 0) {
00537
00538 char buf[DRAW_STRING_BUFFER] = "";
00539 char *p = buf;
00540 for (uint i = 0; i < this->selected->dependency_count; i++) {
00541 ContentID cid = this->selected->dependencies[i];
00542
00543
00544 ConstContentIterator iter = _network_content_client.Begin();
00545 for (; iter != _network_content_client.End(); iter++) {
00546 const ContentInfo *ci = *iter;
00547 if (ci->id != cid) continue;
00548
00549 p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name);
00550 break;
00551 }
00552 }
00553 SetDParamStr(0, buf);
00554 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES);
00555 }
00556
00557 if (this->selected->tag_count != 0) {
00558
00559 char buf[DRAW_STRING_BUFFER] = "";
00560 char *p = buf;
00561 for (uint i = 0; i < this->selected->tag_count; i++) {
00562 p += seprintf(p, lastof(buf), i == 0 ? "%s" : ", %s", this->selected->tags[i]);
00563 }
00564 SetDParamStr(0, buf);
00565 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS);
00566 }
00567
00568 if (this->selected->IsSelected()) {
00569
00570 ConstContentVector tree;
00571 _network_content_client.ReverseLookupTreeDependency(tree, this->selected);
00572
00573 char buf[DRAW_STRING_BUFFER] = "";
00574 char *p = buf;
00575 for (ConstContentIterator iter = tree.Begin(); iter != tree.End(); iter++) {
00576 const ContentInfo *ci = *iter;
00577 if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
00578
00579 p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name);
00580 }
00581 if (p != buf) {
00582 SetDParamStr(0, buf);
00583 y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF);
00584 }
00585 }
00586 }
00587
00588 virtual void OnDoubleClick(Point pt, int widget)
00589 {
00590
00591 if (widget != NCLWW_MATRIX) return;
00592
00593 pt.x = this->GetWidget<NWidgetBase>(NCLWW_CHECKBOX)->pos_x;
00594 this->OnClick(pt, widget);
00595 }
00596
00597 virtual void OnClick(Point pt, int widget)
00598 {
00599 switch (widget) {
00600 case NCLWW_MATRIX: {
00601 uint32 id_v = (pt.y - this->GetWidget<NWidgetBase>(NCLWW_MATRIX)->pos_y) / this->resize.step_height;
00602
00603 if (id_v >= this->vscroll.GetCapacity()) return;
00604 id_v += this->vscroll.GetPosition();
00605
00606 if (id_v >= this->content.Length()) return;
00607
00608 this->selected = *this->content.Get(id_v);
00609 this->list_pos = id_v;
00610
00611 if (pt.x <= (int)(this->GetWidget<NWidgetBase>(NCLWW_CHECKBOX)->pos_y + this->GetWidget<NWidgetBase>(NCLWW_CHECKBOX)->current_y)) {
00612 _network_content_client.ToggleSelectedState(this->selected);
00613 this->content.ForceResort();
00614 }
00615
00616 this->InvalidateData();
00617 } break;
00618
00619 case NCLWW_CHECKBOX:
00620 case NCLWW_TYPE:
00621 case NCLWW_NAME:
00622 if (this->content.SortType() == widget - NCLWW_CHECKBOX) {
00623 this->content.ToggleSortOrder();
00624 this->list_pos = this->content.Length() - this->list_pos - 1;
00625 } else {
00626 this->content.SetSortType(widget - NCLWW_CHECKBOX);
00627 this->content.ForceResort();
00628 this->SortContentList();
00629 }
00630 this->ScrollToSelected();
00631 this->InvalidateData();
00632 break;
00633
00634 case NCLWW_SELECT_ALL:
00635 _network_content_client.SelectAll();
00636 this->InvalidateData();
00637 break;
00638
00639 case NCLWW_SELECT_UPDATE:
00640 _network_content_client.SelectUpgrade();
00641 this->InvalidateData();
00642 break;
00643
00644 case NCLWW_UNSELECT:
00645 _network_content_client.UnselectAll();
00646 this->InvalidateData();
00647 break;
00648
00649 case NCLWW_CANCEL:
00650 delete this;
00651 break;
00652
00653 case NCLWW_DOWNLOAD:
00654 if (BringWindowToFrontById(WC_NETWORK_STATUS_WINDOW, 0) == NULL) new NetworkContentDownloadStatusWindow();
00655 break;
00656 }
00657 }
00658
00659 virtual void OnMouseLoop()
00660 {
00661 this->HandleEditBox(NCLWW_FILTER);
00662 }
00663
00664 virtual EventState OnKeyPress(uint16 key, uint16 keycode)
00665 {
00666 switch (keycode) {
00667 case WKC_UP:
00668
00669 if (this->list_pos > 0) this->list_pos--;
00670 break;
00671 case WKC_DOWN:
00672
00673 if (this->list_pos < (int)this->content.Length() - 1) this->list_pos++;
00674 break;
00675 case WKC_PAGEUP:
00676
00677 this->list_pos = (this->list_pos < this->vscroll.GetCapacity()) ? 0 : this->list_pos - this->vscroll.GetCapacity();
00678 break;
00679 case WKC_PAGEDOWN:
00680
00681 this->list_pos = min(this->list_pos + this->vscroll.GetCapacity(), (int)this->content.Length() - 1);
00682 break;
00683 case WKC_HOME:
00684
00685 this->list_pos = 0;
00686 break;
00687 case WKC_END:
00688
00689 this->list_pos = this->content.Length() - 1;
00690 break;
00691
00692 case WKC_SPACE:
00693 case WKC_RETURN:
00694 if (keycode == WKC_RETURN || !IsWidgetFocused(NCLWW_FILTER)) {
00695 if (this->selected != NULL) {
00696 _network_content_client.ToggleSelectedState(this->selected);
00697 this->content.ForceResort();
00698 this->InvalidateData();
00699 }
00700 return ES_HANDLED;
00701 }
00702
00703
00704 default: {
00705
00706 EventState state = ES_NOT_HANDLED;
00707 if (this->HandleEditBoxKey(NCLWW_FILTER, key, keycode, state) == HEBR_EDITING) {
00708 this->OnOSKInput(NCLWW_FILTER);
00709 }
00710
00711 return state;
00712 }
00713 }
00714
00715 if (_network_content_client.Length() == 0) return ES_HANDLED;
00716
00717 this->selected = *this->content.Get(this->list_pos);
00718
00719
00720 this->ScrollToSelected();
00721
00722
00723 this->InvalidateData();
00724 return ES_HANDLED;
00725 }
00726
00727 virtual void OnOSKInput(int wid)
00728 {
00729 this->content.SetFilterState(!StrEmpty(this->edit_str_buf));
00730 this->content.ForceRebuild();
00731 this->InvalidateData();
00732 }
00733
00734 virtual void OnResize()
00735 {
00736 this->vscroll.SetCapacityFromWidget(this, NCLWW_MATRIX);
00737 this->GetWidget<NWidgetCore>(NCLWW_MATRIX)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
00738 }
00739
00740 virtual void OnReceiveContentInfo(const ContentInfo *rci)
00741 {
00742 this->content.ForceRebuild();
00743 this->InvalidateData();
00744 }
00745
00746 virtual void OnDownloadComplete(ContentID cid)
00747 {
00748 this->content.ForceResort();
00749 this->InvalidateData();
00750 }
00751
00752 virtual void OnConnect(bool success)
00753 {
00754 if (!success) {
00755 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, 0, 0);
00756 delete this;
00757 return;
00758 }
00759
00760 this->InvalidateData();
00761 }
00762
00763 virtual void OnInvalidateData(int data)
00764 {
00765 if (this->content.NeedRebuild()) this->BuildContentList();
00766
00767
00768 this->filesize_sum = 0;
00769 bool show_select_all = false;
00770 bool show_select_upgrade = false;
00771 for (ConstContentIterator iter = this->content.Begin(); iter != this->content.End(); iter++) {
00772 const ContentInfo *ci = *iter;
00773 switch (ci->state) {
00774 case ContentInfo::SELECTED:
00775 case ContentInfo::AUTOSELECTED:
00776 this->filesize_sum += ci->filesize;
00777 break;
00778
00779 case ContentInfo::UNSELECTED:
00780 show_select_all = true;
00781 show_select_upgrade |= ci->upgrade;
00782 break;
00783
00784 default:
00785 break;
00786 }
00787 }
00788
00789
00790 this->SetWidgetDisabledState(NCLWW_DOWNLOAD, this->filesize_sum == 0 || (FindWindowById(WC_NETWORK_STATUS_WINDOW, 0) != NULL && data != 2));
00791 this->SetWidgetDisabledState(NCLWW_UNSELECT, this->filesize_sum == 0);
00792 this->SetWidgetDisabledState(NCLWW_SELECT_ALL, !show_select_all);
00793 this->SetWidgetDisabledState(NCLWW_SELECT_UPDATE, !show_select_upgrade);
00794
00795 this->GetWidget<NWidgetCore>(NCLWW_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL;
00796 }
00797 };
00798
00799 Listing NetworkContentListWindow::last_sorting = {false, 1};
00800 Filtering NetworkContentListWindow::last_filtering = {false, 0};
00801
00802 NetworkContentListWindow::GUIContentList::SortFunction * const NetworkContentListWindow::sorter_funcs[] = {
00803 &StateSorter,
00804 &TypeSorter,
00805 &NameSorter,
00806 };
00807
00808 NetworkContentListWindow::GUIContentList::FilterFunction * const NetworkContentListWindow::filter_funcs[] = {
00809 &TagNameFilter,
00810 };
00811
00812 static const NWidgetPart _nested_network_content_list_widgets[] = {
00813 NWidget(NWID_HORIZONTAL),
00814 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
00815 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_CONTENT_TITLE, STR_NULL),
00816 EndContainer(),
00817 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, NCLWW_BACKGROUND),
00818 NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
00819 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
00820
00821 NWidget(WWT_EMPTY, COLOUR_LIGHT_BLUE, NCLWW_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0),
00822 NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, NCLWW_FILTER), SetFill(1, 0), SetResize(1, 0),
00823 SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
00824 EndContainer(),
00825 NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
00826 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
00827
00828 NWidget(NWID_VERTICAL),
00829 NWidget(NWID_HORIZONTAL),
00830 NWidget(NWID_VERTICAL),
00831 NWidget(NWID_HORIZONTAL),
00832 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_CHECKBOX), SetMinimalSize(13, 1), SetDataTip(STR_EMPTY, STR_NULL),
00833 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_TYPE),
00834 SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
00835 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_NAME), SetResize(1, 0), SetFill(1, 0),
00836 SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
00837 EndContainer(),
00838 NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, NCLWW_MATRIX), SetResize(1, 14), SetFill(1, 1),
00839 EndContainer(),
00840 NWidget(WWT_SCROLLBAR, COLOUR_LIGHT_BLUE, NCLWW_SCROLLBAR),
00841 EndContainer(),
00842 EndContainer(),
00843
00844 NWidget(NWID_VERTICAL),
00845 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, NCLWW_DETAILS), SetResize(1, 1), SetFill(1, 1), EndContainer(),
00846 EndContainer(),
00847 EndContainer(),
00848 NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
00849
00850 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
00851 NWidget(NWID_SELECTION, INVALID_COLOUR, NCLWW_SEL_ALL_UPDATE), SetResize(1, 0), SetFill(1, 0),
00852 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
00853 SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
00854 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
00855 SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
00856 EndContainer(),
00857 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_UNSELECT), SetResize(1, 0), SetFill(1, 0),
00858 SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
00859 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_CANCEL), SetResize(1, 0), SetFill(1, 0),
00860 SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
00861 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, NCLWW_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
00862 SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
00863 EndContainer(),
00864 NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetResize(1, 0),
00865
00866 NWidget(NWID_HORIZONTAL),
00867 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
00868 NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
00869 EndContainer(),
00870 EndContainer(),
00871 };
00872
00874 static const WindowDesc _network_content_list_desc(
00875 WDP_CENTER, 630, 460,
00876 WC_NETWORK_WINDOW, WC_NONE,
00877 WDF_UNCLICK_BUTTONS,
00878 _nested_network_content_list_widgets, lengthof(_nested_network_content_list_widgets)
00879 );
00880
00886 void ShowNetworkContentListWindow(ContentVector *cv, ContentType type)
00887 {
00888 #if defined(WITH_ZLIB)
00889 _network_content_client.Clear();
00890 if (cv == NULL) {
00891 _network_content_client.RequestContentList(type);
00892 } else {
00893 _network_content_client.RequestContentList(cv, true);
00894 }
00895
00896 DeleteWindowById(WC_NETWORK_WINDOW, 1);
00897 new NetworkContentListWindow(&_network_content_list_desc, cv != NULL);
00898 #else
00899 ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, 0, 0);
00900
00901 if (cv != NULL) {
00902 for (ContentIterator iter = cv->Begin(); iter != cv->End(); iter++) delete *iter;
00903 }
00904 #endif
00905 }
00906
00907 #endif