(svn r19837) -Change: Display list of available (non-active) grfs in the NewGRF window.

This commit is contained in:
alberth 2010-05-16 18:58:13 +00:00
parent 5e24305e0d
commit 47360b029e
2 changed files with 167 additions and 16 deletions

View File

@ -2323,6 +2323,7 @@ STR_GENERATION_PREPARING_GAME :{BLACK}Preparin
STR_NEWGRF_SETTINGS_CAPTION :{WHITE}NewGRF Settings
STR_NEWGRF_SETTINGS_INFO_TITLE :{WHITE}Detailed NewGRF information
STR_NEWGRF_SETTINGS_ACTIVE_LIST :{WHITE}Active NewGRF files
STR_NEWGRF_SETTINGS_INACTIVE_LIST :{WHITE}Inactive NewGRF files
STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}Select preset:
STR_NEWGRF_SETTINGS_PRESET_LIST_TOOLTIP :{BLACK}Load the selected preset
STR_NEWGRF_SETTINGS_PRESET_SAVE :{BLACK}Save preset

View File

@ -350,7 +350,7 @@ public:
*list = c;
DeleteWindowByClass(WC_SAVELOAD);
InvalidateWindowData(WC_GAME_OPTIONS, 0, 2);
InvalidateWindowData(WC_GAME_OPTIONS, 0, 4);
}
break;
@ -506,6 +506,8 @@ enum ShowNewGRFStateWidgets {
SNGRFS_MOVE_DOWN,
SNGRFS_FILE_LIST,
SNGRFS_SCROLLBAR,
SNGRFS_AVAIL_LIST,
SNGRFS_SCROLL2BAR,
SNGRFS_NEWGRF_INFO_TITLE,
SNGRFS_NEWGRF_INFO,
SNGRFS_SET_PARAMETERS,
@ -518,17 +520,31 @@ enum ShowNewGRFStateWidgets {
* Window for showing NewGRF files
*/
struct NewGRFWindow : public Window {
GRFConfig **orig_list; ///< grf list the window is shown with
GRFConfig *actives; ///< Temporary active grf list to which changes are made.
GRFConfig *active_sel; ///< Selected active grf item.
bool editable; ///< is the window editable
bool show_params; ///< are the grf-parameters shown in the info-panel
bool execute; ///< on pressing 'apply changes' are grf changes applied immediately, or only list is updated
int query_widget; ///< widget that opened a query
int preset; ///< selected preset
typedef GUIList<const GRFConfig *> GUIGRFConfigList;
static Listing last_sorting; ///< Default sorting of #GUIGRFConfigList.
static Filtering last_filtering; ///< Default filtering of #GUIGRFConfigList.
static GUIGRFConfigList::SortFunction * const sorter_funcs[]; ///< Sort functions of the #GUIGRFConfigList.
static GUIGRFConfigList::FilterFunction * const filter_funcs[]; ///< Filter functions of the #GUIGRFConfigList.
GUIGRFConfigList avails; ///< Available (non-active) grfs.
const GRFConfig *avail_sel; ///< Currently selected available grf. \c NULL is none is selected.
int avail_pos; ///< Index of #avail_sel if existing, else \c -1.
GRFConfig *actives; ///< Temporary active grf list to which changes are made.
GRFConfig *active_sel; ///< Selected active grf item.
GRFConfig **orig_list; ///< List active grfs in the game. Used as initial value, may be updated by the window.
bool editable; ///< Is the window editable?
bool show_params; ///< Are the grf-parameters shown in the info-panel?
bool execute; ///< On pressing 'apply changes' are grf changes applied immediately, or only list is updated.
int query_widget; ///< Widget that opened the last query.
int preset; ///< Selected preset.
NewGRFWindow(const WindowDesc *desc, bool editable, bool show_params, bool execute, GRFConfig **orig_list) : Window()
{
this->avail_sel = NULL;
this->avail_pos = -1;
this->active_sel = NULL;
this->actives = NULL;
this->orig_list = orig_list;
@ -541,6 +557,12 @@ struct NewGRFWindow : public Window {
GetGRFPresetList(&_grf_preset_list);
this->InitNested(desc);
this->avails.SetListing(this->last_sorting);
this->avails.SetFiltering(this->last_filtering);
this->avails.SetSortFuncs(this->sorter_funcs);
this->avails.SetFilterFuncs(this->filter_funcs);
this->avails.ForceRebuild();
this->OnInvalidateData(2);
}
@ -561,6 +583,11 @@ struct NewGRFWindow : public Window {
{
switch (widget) {
case SNGRFS_FILE_LIST:
resize->height = max(12, FONT_HEIGHT_NORMAL + 2);
size->height = max(size->height, WD_FRAMERECT_TOP + 6 * resize->height + WD_FRAMERECT_BOTTOM);
break;
case SNGRFS_AVAIL_LIST:
resize->height = max(12, FONT_HEIGHT_NORMAL + 2);
size->height = max(size->height, WD_FRAMERECT_TOP + 8 * resize->height + WD_FRAMERECT_BOTTOM);
break;
@ -602,6 +629,7 @@ struct NewGRFWindow : public Window {
virtual void OnResize()
{
this->vscroll.SetCapacityFromWidget(this, SNGRFS_FILE_LIST);
this->vscroll2.SetCapacityFromWidget(this, SNGRFS_AVAIL_LIST);
}
virtual void SetStringParameters(int widget) const
@ -690,17 +718,41 @@ struct NewGRFWindow : public Window {
}
} break;
case SNGRFS_AVAIL_LIST: {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, 0xD7);
uint step_height = this->GetWidget<NWidgetBase>(SNGRFS_AVAIL_LIST)->resize_y;
uint y = r.top + WD_FRAMERECT_TOP;
uint min_index = this->vscroll2.GetPosition();
uint max_index = min(min_index + this->vscroll2.GetCapacity(), this->avails.Length());
for (uint i = min_index; i < max_index; i++)
{
const GRFConfig *c = this->avails[i];
bool h = (c == this->avail_sel);
const char *text = c->GetName();
if (h) GfxFillRect(r.left + 1, y, r.right - 1, y + step_height - 1, 156);
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, text, h ? TC_WHITE : TC_SILVER);
y += step_height;
}
break;
}
case SNGRFS_NEWGRF_INFO_TITLE:
/* Create the nice grayish rectangle at the details top. */
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, 157);
DrawString(r.left, r.right, (r.top + r.bottom - FONT_HEIGHT_NORMAL) / 2, STR_NEWGRF_SETTINGS_INFO_TITLE, TC_FROMSTRING, SA_CENTER);
break;
case SNGRFS_NEWGRF_INFO:
if (this->active_sel != NULL) {
ShowNewGRFInfo(this->active_sel, r.left + WD_FRAMERECT_LEFT, r.top + WD_FRAMERECT_TOP, r.right - WD_FRAMERECT_RIGHT, r.bottom - WD_FRAMERECT_BOTTOM, this->show_params);
case SNGRFS_NEWGRF_INFO: {
const GRFConfig *selected = this->active_sel;
if (selected == NULL) selected = this->avail_sel;
if (selected != NULL) {
ShowNewGRFInfo(selected, r.left + WD_FRAMERECT_LEFT, r.top + WD_FRAMERECT_TOP, r.right - WD_FRAMERECT_RIGHT, r.bottom - WD_FRAMERECT_BOTTOM, this->show_params);
}
break;
}
}
}
@ -761,6 +813,9 @@ struct NewGRFWindow : public Window {
this->active_sel = newsel;
this->preset = -1;
this->avail_pos = -1;
this->avail_sel = NULL;
this->avails.ForceRebuild();
this->InvalidateData(3);
this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window
break;
@ -804,7 +859,7 @@ struct NewGRFWindow : public Window {
break;
}
case SNGRFS_FILE_LIST: { // Select a GRF
case SNGRFS_FILE_LIST: { // Select an active GRF.
NWidgetBase *nw = this->GetWidget<NWidgetBase>(SNGRFS_FILE_LIST);
uint i = (pt.y - nw->pos_y) / nw->resize_y + this->vscroll.GetPosition();
@ -813,12 +868,27 @@ struct NewGRFWindow : public Window {
if (this->active_sel != c) this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window
this->active_sel = c;
this->avail_sel = NULL;
this->avail_pos = -1;
this->InvalidateData();
if (click_count > 1) this->OnClick(pt, SNGRFS_SET_PARAMETERS, 1);
break;
}
case SNGRFS_AVAIL_LIST: { // Select a non-active GRF.
NWidgetBase *nw = this->GetWidget<NWidgetBase>(SNGRFS_AVAIL_LIST);
uint i = (pt.y - nw->pos_y) / nw->resize_y + this->vscroll2.GetPosition();
this->active_sel = NULL;
if (i < this->avails.Length()) {
this->avail_sel = this->avails[i];
this->avail_pos = i;
}
this->InvalidateData();
this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window
break;
}
case SNGRFS_APPLY_CHANGES: // Apply changes made to GRF list
if (this->execute) {
ShowQuery(
@ -891,6 +961,7 @@ struct NewGRFWindow : public Window {
ClearGRFConfigList(&this->actives);
this->actives = c;
this->preset = index;
this->avails.ForceRebuild();
}
}
@ -919,6 +990,8 @@ struct NewGRFWindow : public Window {
break;
case SNGRFS_SET_PARAMETERS: {
if (this->active_sel == NULL) return;
/* Parse our new "int list" */
GRFConfig *c = this->active_sel;
c->num_params = ParseIntList(str, (int*)c->param, lengthof(c->param));
@ -934,6 +1007,13 @@ struct NewGRFWindow : public Window {
this->InvalidateData();
}
/** Calback to update internal data.
* - 0: (optionally) build availables, update button status.
* - 1: build availables, Add newly found grfs, update button status.
* - 2: (optionally) build availables, Reset preset, + 3
* - 3: (optionally) build availables, Update active scrollbar, update button status.
* - 4: Force a rebuild of the availables, + 2
*/
virtual void OnInvalidateData(int data = 0)
{
switch (data) {
@ -959,8 +1039,10 @@ struct NewGRFWindow : public Window {
c->info = f->info == NULL ? NULL : strdup(f->info);
c->status = GCS_UNKNOWN;
}
break;
/* Fall through. */
case 4:
this->avails.ForceRebuild();
/* Fall through. */
case 2:
this->preset = -1;
/* Fall through */
@ -970,10 +1052,15 @@ struct NewGRFWindow : public Window {
this->vscroll.SetCapacityFromWidget(this, SNGRFS_FILE_LIST);
this->vscroll.SetCount(i);
this->vscroll2.SetCapacityFromWidget(this, SNGRFS_AVAIL_LIST);
if (this->avail_pos >= 0) this->vscroll2.ScrollTowards(this->avail_pos);
break;
}
}
this->BuildAvailables();
this->SetWidgetsDisabledState(!this->editable,
SNGRFS_PRESET_LIST,
SNGRFS_ADD,
@ -1016,8 +1103,55 @@ struct NewGRFWindow : public Window {
}
this->SetWidgetDisabledState(SNGRFS_PRESET_SAVE, has_missing);
}
private:
/** Sort grfs by name. */
static int CDECL NameSorter(const GRFConfig * const *a, const GRFConfig * const *b)
{
return strcasecmp((*a)->GetName(), (*b)->GetName());
}
/** Filter grfs by tags/name */
static bool CDECL TagNameFilter(const GRFConfig * const *a, const char *filter_string)
{
if (strcasestr((*a)->GetName(), filter_string) != NULL) return true;
if ((*a)->filename != NULL && strcasestr((*a)->filename, filter_string) != NULL) return true;
if ((*a)->GetDescription() != NULL && strcasestr((*a)->GetDescription(), filter_string) != NULL) return true;
return false;
}
void BuildAvailables()
{
if (!this->avails.NeedRebuild()) return;
this->avails.Clear();
for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
bool found = false;
for (const GRFConfig *grf = this->actives; grf != NULL && !found; grf = grf->next) found = grf->ident.HasGrfIdentifier(c->ident.grfid, c->ident.md5sum);
if (!found) *this->avails.Append() = c;
}
this->avails.Compact();
this->avails.RebuildDone();
this->avails.Sort();
this->vscroll2.SetCount(this->avails.Length()); // Update the scrollbar
}
};
Listing NewGRFWindow::last_sorting = {false, 0};
Filtering NewGRFWindow::last_filtering = {false, 0};
NewGRFWindow::GUIGRFConfigList::SortFunction * const NewGRFWindow::sorter_funcs[] = {
&NameSorter,
};
NewGRFWindow::GUIGRFConfigList::FilterFunction * const NewGRFWindow::filter_funcs[] = {
&TagNameFilter,
};
/* Widget definition of the manage newgrfs window */
static const NWidgetPart _nested_newgrf_widgets[] = {
NWidget(NWID_HORIZONTAL),
@ -1069,6 +1203,21 @@ static const NWidgetPart _nested_newgrf_widgets[] = {
EndContainer(),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, WD_RESIZEBOX_WIDTH), SetResize(1, 0),
NWidget(WWT_PANEL, COLOUR_MAUVE),
NWidget(WWT_LABEL, COLOUR_MAUVE), SetDataTip(STR_NEWGRF_SETTINGS_INACTIVE_LIST, STR_NULL),
SetFill(1, 0), SetResize(1, 0), SetPadding(3, WD_FRAMETEXT_RIGHT, 0, WD_FRAMETEXT_LEFT),
/* Left side, available grfs. */
NWidget(NWID_HORIZONTAL), SetPadding(0, 2, 0, 2),
NWidget(WWT_PANEL, COLOUR_MAUVE),
NWidget(WWT_INSET, COLOUR_MAUVE, SNGRFS_AVAIL_LIST), SetMinimalSize(100, 1), SetPadding(2, 2, 2, 2),
SetFill(1, 1), SetResize(1, 1),
EndContainer(),
EndContainer(),
NWidget(WWT_SCROLL2BAR, COLOUR_MAUVE, SNGRFS_SCROLL2BAR),
EndContainer(),
EndContainer(),
EndContainer(),
NWidget(NWID_VERTICAL),
@ -1130,8 +1279,9 @@ static void NewGRFConfirmationCallback(Window *w, bool confirmed)
CopyGRFConfigList(&nw->actives, *nw->orig_list, false);
for (c = nw->actives; c != NULL && i > 0; c = c->next, i--) {}
nw->active_sel = c;
nw->avails.ForceRebuild();
w->SetDirty();
w->InvalidateData();
}
}