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