summaryrefslogtreecommitdiff
path: root/src/newgrf_gui.cpp
diff options
context:
space:
mode:
authoralberth <alberth@openttd.org>2010-05-16 18:58:13 +0000
committeralberth <alberth@openttd.org>2010-05-16 18:58:13 +0000
commitb7a8497ccdca2dd6f8a36b580187d7db5f90dcf8 (patch)
tree681658f85c4581ad59c2296bab0d7c540eafc6df /src/newgrf_gui.cpp
parent219ae56f8aac67b9e8111500a34700c082eea2fd (diff)
downloadopenttd-b7a8497ccdca2dd6f8a36b580187d7db5f90dcf8.tar.xz
(svn r19837) -Change: Display list of available (non-active) grfs in the NewGRF window.
Diffstat (limited to 'src/newgrf_gui.cpp')
-rw-r--r--src/newgrf_gui.cpp182
1 files changed, 166 insertions, 16 deletions
diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp
index b7bcd99da..32b4cfbf9 100644
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -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);
}
@@ -562,6 +584,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();
}
}