terom@11174: /* $Id$ */ terom@11174: terom@11174: /** @file newgrf_download.cpp GUI to download NewGRFs. */ terom@11174: #include "../stdafx.h" terom@11174: #include "../openttd.h" terom@11174: #include "../strings_func.h" terom@11174: #include "../date_func.h" terom@11174: #include "../gui.h" terom@11174: #include "../window_gui.h" terom@11174: #include "../textbuf_gui.h" terom@11174: #include "../variables.h" terom@11174: #include "../newgrf.h" terom@11174: #include "newgrf_download.h" terom@11174: #include "../functions.h" terom@11174: #include "../window_func.h" terom@11174: #include "../core/alloc_func.hpp" terom@11174: #include "../string_func.h" terom@11174: #include "../gfx_func.h" terom@11174: #include "../querystring_gui.h" terom@11174: #include "../sortlist_type.h" terom@11174: terom@11174: #include "table/strings.h" terom@11174: #include "../table/sprites.h" terom@11174: terom@11174: // XXX: copy-pasted from newgrf_gui.cpp terom@11174: static void ShowDownloadNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, uint bottom, bool show_params) terom@11174: { terom@11174: char buff[256]; terom@11174: terom@11174: if (c->error != NULL) { terom@11174: char message[512]; terom@11174: if (c->error->custom_message == NULL) { terom@11174: SetDParamStr(0, c->filename); terom@11174: SetDParamStr(1, c->error->data); terom@11174: for (uint i = 0; i < c->error->num_params; i++) { terom@11174: uint32 param = 0; terom@11174: byte param_number = c->error->param_number[i]; terom@11174: terom@11174: if (param_number < c->num_params) param = c->param[param_number]; terom@11174: terom@11174: SetDParam(2 + i, param); terom@11174: } terom@11174: terom@11174: GetString(message, c->error->message, lastof(message)); terom@11174: } else { terom@11174: SetDParamStr(0, c->error->custom_message); terom@11174: GetString(message, STR_JUST_RAW_STRING, lastof(message)); terom@11174: } terom@11174: terom@11174: SetDParamStr(0, message); terom@11174: y += DrawStringMultiLine(x, y, c->error->severity, w, bottom - y); terom@11174: } terom@11174: terom@11174: /* Draw filename or not if it is not known (GRF sent over internet) */ terom@11174: if (c->filename != NULL) { terom@11174: SetDParamStr(0, c->filename); terom@11174: y += DrawStringMultiLine(x, y, STR_NEWGRF_FILENAME, w, bottom - y); terom@11174: } terom@11174: terom@11174: /* Prepare and draw GRF ID */ terom@11174: snprintf(buff, lengthof(buff), "%08X", BSWAP32(c->grfid)); terom@11174: SetDParamStr(0, buff); terom@11174: y += DrawStringMultiLine(x, y, STR_NEWGRF_GRF_ID, w, bottom - y); terom@11174: terom@11174: /* Prepare and draw MD5 sum */ terom@11174: md5sumToString(buff, lastof(buff), c->md5sum); terom@11174: SetDParamStr(0, buff); terom@11174: y += DrawStringMultiLine(x, y, STR_NEWGRF_MD5SUM, w, bottom - y); terom@11174: terom@11174: /* Show GRF parameter list */ terom@11174: if (show_params) { terom@11174: if (c->num_params > 0) { terom@11174: GRFBuildParamList(buff, c, lastof(buff)); terom@11174: SetDParam(0, STR_JUST_RAW_STRING); terom@11174: SetDParamStr(1, buff); terom@11174: } else { terom@11174: SetDParam(0, STR_01A9_NONE); terom@11174: } terom@11174: y += DrawStringMultiLine(x, y, STR_NEWGRF_PARAMETER, w, bottom - y); terom@11174: } terom@11174: terom@11174: /* Show flags */ terom@11174: if (c->status == GCS_NOT_FOUND) y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w, bottom - y); terom@11174: if (c->status == GCS_DISABLED) y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w, bottom - y); terom@11174: if (HasBit(c->flags, GCF_COMPATIBLE)) y += DrawStringMultiLine(x, y, STR_NEWGRF_COMPATIBLE_LOADED, w, bottom - y); terom@11174: terom@11174: /* Draw GRF info if it exists */ terom@11174: if (c->info != NULL && !StrEmpty(c->info)) { terom@11174: SetDParam(0, STR_JUST_RAW_STRING); terom@11174: SetDParamStr(1, c->info); terom@11174: y += DrawStringMultiLine(x, y, STR_02BD, w, bottom - y); terom@11174: } else { terom@11174: y += DrawStringMultiLine(x, y, STR_NEWGRF_NO_INFO, w, bottom - y); terom@11174: } terom@11174: } terom@11174: terom@11174: /** terom@11174: * Window for downloading NewGRF files terom@11174: */ terom@11174: struct NewGRFDownloadWindow : public Window { terom@11174: /* Names of the add a newgrf window widgets */ terom@11174: enum DownloadNewGRFWindowWidgets { terom@11174: DNGRFS_CLOSEBOX = 0, terom@11174: DNGRFS_CAPTION, terom@11174: DNGRFS_BACKGROUND, terom@11174: DNGRFS_FILE_LIST, terom@11174: DNGRFS_SCROLLBAR, terom@11174: DNGRFS_NEWGRF_INFO, terom@11174: DNGRFS_CHECK_AVAILABLE, terom@11174: DNGRFS_DOWNLOAD_AVAILABLE, terom@11174: DNGRFS_RESIZE, terom@11174: }; terom@11174: terom@11174: // XXX: do we need a temp. copy? I think not terom@11174: GRFConfig *list; ///< temporary grf list to which changes are made terom@11174: const GRFConfig *sel; terom@11174: terom@11176: NewGRFDownloadWindow(const WindowDesc *desc, GRFConfig *list) : Window(desc, 0) terom@11174: { terom@11174: // resize magic terom@11174: this->resize.step_height = 14; terom@11174: terom@11174: // the list of GRFs terom@11176: this->list = list; terom@11174: terom@11174: // display window? terom@11174: this->FindWindowPlacementAndResize(desc); terom@11174: terom@11174: // set up our own state terom@11174: this->SetupDownloadNewGRFWindow(); terom@11174: } terom@11174: terom@11174: ~NewGRFDownloadWindow() terom@11174: { terom@11174: /* Remove the temporary copy of grf-list used in window */ terom@11174: ClearGRFConfigList(&this->list); terom@11174: } terom@11174: terom@11174: void SetupDownloadNewGRFWindow() terom@11174: { terom@11174: const GRFConfig *c; terom@11174: int i; terom@11174: terom@11174: // count how many NewGRFs in our list terom@11174: for (c = this->list, i = 0; c != NULL; c = c->next, i++) {} terom@11174: terom@11174: // something to do with vertical scrolling... terom@11174: this->vscroll.cap = (this->widget[DNGRFS_FILE_LIST].bottom - this->widget[DNGRFS_FILE_LIST].top) / 14 + 1; terom@11174: SetVScrollCount(this, i); terom@11174: terom@11174: // disable the "Check Available" button if there are no incompatible NewGRFs terom@11174: this->SetWidgetDisabledState(DNGRFS_CHECK_AVAILABLE, (i == 0)); terom@11174: terom@11174: // disable the "Download Available" button until we've checked for available NewGRFs terom@11174: this->SetWidgetDisabledState(DNGRFS_DOWNLOAD_AVAILABLE, 1); terom@11174: } terom@11174: terom@11174: virtual void OnPaint() terom@11174: { terom@11174: // superclass widget-drawing terom@11174: this->DrawWidgets(); terom@11174: terom@11174: /* Draw the NewGRF file list */ terom@11174: terom@11174: int y = this->widget[DNGRFS_FILE_LIST].top; terom@11174: int i = 0; terom@11174: terom@11174: // for each GRF... terom@11174: for (const GRFConfig *c = this->list; c != NULL; c = c->next, i++) { terom@11174: terom@11174: // is scrolled into view terom@11174: if (i >= this->vscroll.pos && i < this->vscroll.pos + this->vscroll.cap) { terom@11174: terom@11174: SpriteID pal; terom@11174: byte txtoffset; terom@11174: terom@11174: // the NewGRF name terom@11174: const char *text = (c->name != NULL && !StrEmpty(c->name)) ? c->name : c->filename; terom@11174: terom@11175: /* terom@11175: * Pick a colour terom@11175: * terom@11175: * orange - server has it, we don't, haven't checked availablity yet terom@11175: * red - not available terom@11175: * green - available terom@11175: * blue - downloaded terom@11175: */ terom@11174: switch (c->status) { terom@11174: case GCS_NOT_FOUND: terom@11175: pal = PALETTE_TO_ORANGE; terom@11175: break; terom@11175: terom@11174: case GCS_DISABLED: terom@11174: pal = PALETTE_TO_RED; terom@11174: break; terom@11174: terom@11175: case GCS_AVAILABLE: terom@11174: pal = PALETTE_TO_GREEN; terom@11174: break; terom@11174: terom@11175: default: // GCS_INITIALIZED or GCS_ACTIVATED terom@11174: pal = PALETTE_TO_BLUE; terom@11174: break; terom@11174: } terom@11175: terom@11175: /* terom@11175: XXX: flags? terom@11174: if (pal != PALETTE_TO_RED) { terom@11174: if (HasBit(c->flags, GCF_STATIC)) { terom@11174: pal = PALETTE_TO_GREY; terom@11174: terom@11174: } else if (HasBit(c->flags, GCF_COMPATIBLE)) { terom@11174: pal = PALETTE_TO_ORANGE; terom@11174: terom@11174: } terom@11174: } terom@11175: */ terom@11175: terom@11174: // draw the square in the chosen colour terom@11174: DrawSprite(SPR_SQUARE, pal, 5, y + 2); terom@11174: terom@11174: // XXX: hmm... use for download errors? terom@11174: if (c->error != NULL) DrawSprite(SPR_WARNING_SIGN, 0, 20, y + 2); terom@11174: terom@11174: // where to draw the text terom@11174: txtoffset = c->error != NULL ? 35 : 25; terom@11174: terom@11174: // draw the chosen text (GRF name/filename) terom@11174: DoDrawStringTruncated(text, txtoffset, y + 3, this->sel == c ? TC_WHITE : TC_BLACK, this->width - txtoffset - 10); terom@11174: terom@11174: // advance on to the next row terom@11174: y += 14; terom@11174: } terom@11174: } terom@11174: terom@11174: if (this->sel != NULL) { terom@11174: /* Draw NewGRF file info */ terom@11174: const Widget *wi = &this->widget[DNGRFS_NEWGRF_INFO]; terom@11174: terom@11174: ShowDownloadNewGRFInfo(this->sel, wi->left + 2, wi->top + 2, wi->right - wi->left - 2, wi->bottom, false); terom@11174: } terom@11174: } terom@11174: terom@11174: virtual void OnClick(Point pt, int widget) terom@11174: { terom@11174: switch (widget) { terom@11174: case DNGRFS_CHECK_AVAILABLE: terom@11174: // XXX: implement terom@11174: terom@11174: break; terom@11174: terom@11174: case DNGRFS_DOWNLOAD_AVAILABLE: terom@11174: // XXX: implement terom@11174: terom@11174: break; terom@11174: terom@11174: case DNGRFS_FILE_LIST: { // Select a GRF terom@11174: GRFConfig *c; terom@11174: uint i = (pt.y - this->widget[DNGRFS_FILE_LIST].top) / 14 + this->vscroll.pos; terom@11174: terom@11174: for (c = this->list; c != NULL && i > 0; c = c->next, i--) {} terom@11174: this->sel = c; terom@11174: terom@11174: this->SetDirty(); terom@11174: break; terom@11174: } terom@11174: } terom@11174: } terom@11174: terom@11174: virtual void OnResize(Point new_size, Point delta) terom@11174: { terom@11174: if (delta.x != 0) { terom@11174: ResizeButtons(this, DNGRFS_CHECK_AVAILABLE, DNGRFS_DOWNLOAD_AVAILABLE); terom@11174: } terom@11174: terom@11174: this->vscroll.cap += delta.y / 14; terom@11174: this->widget[DNGRFS_FILE_LIST].data = (this->vscroll.cap << 8) + 1; terom@11174: terom@11174: this->SetupDownloadNewGRFWindow(); terom@11174: } terom@11174: terom@11174: virtual void OnInvalidateData(int data = 0) terom@11174: { terom@11174: this->SetupDownloadNewGRFWindow(); terom@11174: } terom@11174: }; terom@11174: terom@11174: /* Widget definition of the download newgrfs window */ terom@11174: static const Widget _newgrf_download_widgets[] = { terom@11174: { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, // DNGRFS_CLOSEBOX terom@11174: { WWT_CAPTION, RESIZE_RIGHT, 10, 11, 299, 0, 13, STR_NEWGRF_SETTINGS_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS }, // DNGRFS_CAPTION terom@11174: { WWT_PANEL, RESIZE_RIGHT, 10, 0, 299, 14, 29, STR_NULL, STR_NULL }, // DNGRFS_BACKGROUND terom@11174: terom@11174: /* terom@11174: { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 10, 79, 16, 27, STR_NEWGRF_ADD, STR_NEWGRF_ADD_TIP }, // SNGRFS_ADD terom@11174: { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 80, 149, 16, 27, STR_NEWGRF_REMOVE, STR_NEWGRF_REMOVE_TIP }, // SNGRFS_REMOVE terom@11174: { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 150, 219, 16, 27, STR_NEWGRF_MOVEUP, STR_NEWGRF_MOVEUP_TIP }, // SNGRFS_MOVE_UP terom@11174: { WWT_PUSHTXTBTN, RESIZE_RIGHT, 3, 220, 289, 16, 27, STR_NEWGRF_MOVEDOWN, STR_NEWGRF_MOVEDOWN_TIP }, // SNGRFS_MOVE_DOWN terom@11174: */ terom@11174: terom@11174: { WWT_MATRIX, RESIZE_RB, 10, 0, 287, 30, 99, 0x501, STR_NEWGRF_DOWNLOAD_LIST_TIP }, // DNGRFS_FILE_LIST terom@11174: { WWT_SCROLLBAR, RESIZE_LRB, 10, 288, 299, 30, 99, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST }, // DNGRFS_SCROLLBAR terom@11174: { WWT_PANEL, RESIZE_RTB, 10, 0, 299, 100, 212, STR_NULL, STR_NULL }, // DNGRFS_NEWGRF_INFO terom@11174: { WWT_PUSHTXTBTN, RESIZE_TB, 10, 0, 143, 213, 224, STR_NEWGRF_CHECK_AVAILABLE, STR_NULL }, // DNGRFS_CHECK_AVILABLE terom@11174: { WWT_PUSHTXTBTN, RESIZE_RTB, 10, 144, 287, 213, 224, STR_NEWGRF_DOWNLOAD_AVAILABLE, STR_NULL }, // DNGRFS_DOWNLOAD_AVAILABLE terom@11174: { WWT_RESIZEBOX, RESIZE_LRTB, 10, 288, 299, 213, 224, 0x0, STR_RESIZE_BUTTON }, // DNGRFS_RESIZE terom@11174: { WIDGETS_END }, terom@11174: }; terom@11174: terom@11174: /* Window definition of the manage newgrfs window */ terom@11174: static const WindowDesc _newgrf_download_desc = { terom@11174: WDP_CENTER, WDP_CENTER, 300, 225, 300, 225, terom@11174: WC_GAME_OPTIONS, WC_NONE, terom@11174: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, terom@11174: _newgrf_download_widgets, terom@11174: }; terom@11174: terom@11174: terom@11174: /** Setup the NewGRF download gui terom@11174: * @param config pointer to a linked-list of grfconfig's needed */ terom@11174: void ShowNewGRFDownload(GRFConfig **config) terom@11174: { terom@11176: // filter out those that we don't need to download terom@11176: GRFConfig *head = NULL, **item = &head; terom@11176: const GRFConfig *src; terom@11176: terom@11176: for (src = *config; src != NULL; src = src->next) { terom@11176: if (src->status == GCS_NOT_FOUND || HasBit(src->flags, GCF_COMPATIBLE)) { terom@11176: // copy-past from newgrf_config.cpp CopyGRFConfigList terom@11176: GRFConfig *c = CallocT(1); terom@11176: *c = *src; terom@11176: if (src->filename != NULL) c->filename = strdup(src->filename); terom@11176: if (src->name != NULL) c->name = strdup(src->name); terom@11176: if (src->info != NULL) c->info = strdup(src->info); terom@11176: if (src->error != NULL) { terom@11176: c->error = CallocT(1); terom@11176: memcpy(c->error, src->error, sizeof(GRFError)); terom@11176: if (src->error->data != NULL) c->error->data = strdup(src->error->data); terom@11176: if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message); terom@11176: } terom@11176: terom@11176: *item = c; terom@11176: item = &c->next; terom@11176: } terom@11176: } terom@11176: terom@11174: DeleteWindowByClass(WC_GAME_OPTIONS); terom@11176: new NewGRFDownloadWindow(&_newgrf_download_desc, head); terom@11174: } terom@11174: