src/network/newgrf_download.cpp
author Tero Marttila <terom@fixme.fi>
Fri, 18 Jul 2008 22:41:08 +0300
changeset 11177 6d9a43c48924
parent 11176 874f8008e6e5
child 11178 aa617a8b4f34
permissions -rw-r--r--
set the GRFConfig's next ptr to NULL
/* $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);
}