changeset 19415:899f24660723 draft

(svn r24318) -Feature: Add dropdowns to NewGRF configurations, if all values have labels.
author frosch <frosch@openttd.org>
date Fri, 01 Jun 2012 15:20:18 +0000
parents 7fcb23b6305e
children 9d323a730452
files src/newgrf_config.cpp src/newgrf_config.h src/newgrf_gui.cpp
diffstat 3 files changed, 103 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_config.cpp
+++ b/src/newgrf_config.cpp
@@ -164,6 +164,17 @@
 	SB(this->palette, GRFP_USE_BIT, 1, pal == PAL_WINDOWS ? GRFP_USE_WINDOWS : GRFP_USE_DOS);
 }
 
+/**
+ * Finalize Action 14 info after file scan is finished.
+ */
+void GRFConfig::FinalizeParameterInfo()
+{
+	for (GRFParameterInfo **info = this->param_info.Begin(); info != this->param_info.End(); ++info) {
+		if (*info == NULL) continue;
+		(*info)->Finalize();
+	}
+}
+
 GRFConfig *_all_grfs;
 GRFConfig *_grfconfig;
 GRFConfig *_grfconfig_newgame;
@@ -232,7 +243,8 @@
 	def_value(info.def_value),
 	param_nr(info.param_nr),
 	first_bit(info.first_bit),
-	num_bit(info.num_bit)
+	num_bit(info.num_bit),
+	complete_labels(info.complete_labels)
 {
 	for (uint i = 0; i < info.value_names.Length(); i++) {
 		SmallPair<uint32, GRFText *> *data = info.value_names.Get(i);
@@ -281,6 +293,20 @@
 }
 
 /**
+ * Finalize Action 14 info after file scan is finished.
+ */
+void GRFParameterInfo::Finalize()
+{
+	this->complete_labels = true;
+	for (uint32 value = this->min_value; value <= this->max_value; value++) {
+		if (!this->value_names.Contains(value)) {
+			this->complete_labels = false;
+			break;
+		}
+	}
+}
+
+/**
  * Update the palettes of the graphics from the config file.
  * Called when changing the default palette in advanced settings.
  * @param p1 Unused.
@@ -367,6 +393,7 @@
 	/* Find and load the Action 8 information */
 	LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN, subdir);
 	config->SetSuitablePalette();
+	config->FinalizeParameterInfo();
 
 	/* Skip if the grfid is 0 (not read) or 0xFFFFFFFF (ttdp system grf) */
 	if (config->ident.grfid == 0 || config->ident.grfid == 0xFFFFFFFF || config->IsOpenTTDBaseGRF()) return false;
--- a/src/newgrf_config.h
+++ b/src/newgrf_config.h
@@ -133,9 +133,11 @@
 	byte first_bit;        ///< First bit to use in the GRF parameter
 	byte num_bit;          ///< Number of bits to use for this parameter
 	SmallMap<uint32, struct GRFText *, 8> value_names; ///< Names for each value.
+	bool complete_labels;  ///< True if all values have a label.
 
 	uint32 GetValue(struct GRFConfig *config) const;
 	void SetValue(struct GRFConfig *config, uint32 value);
+	void Finalize();
 };
 
 /** Reference counted wrapper around a GRFText pointer. */
@@ -183,6 +185,7 @@
 
 	void SetParameterDefaults();
 	void SetSuitablePalette();
+	void FinalizeParameterInfo();
 };
 
 /** Method to find GRFs using FindGRFConfig */
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -19,6 +19,7 @@
 #include "settings_type.h"
 #include "settings_func.h"
 #include "widgets/dropdown_type.h"
+#include "widgets/dropdown_func.h"
 #include "network/network.h"
 #include "network/network_content.h"
 #include "sortlist_type.h"
@@ -143,6 +144,8 @@
 	GRFConfig *grf_config; ///< Set the parameters of this GRFConfig.
 	uint clicked_button;   ///< The row in which a button was clicked or UINT_MAX.
 	bool clicked_increase; ///< True if the increase button was clicked, false for the decrease button.
+	bool clicked_dropdown; ///< Whether the dropdown is open.
+	bool closing_dropdown; ///< True, if the dropdown list is currently closing.
 	int timeout;           ///< How long before we unpress the last-pressed button?
 	uint clicked_row;      ///< The selected parameter
 	int line_height;       ///< Height of a row in the matrix widget.
@@ -153,6 +156,8 @@
 	NewGRFParametersWindow(const WindowDesc *desc, GRFConfig *c, bool editable) : Window(),
 		grf_config(c),
 		clicked_button(UINT_MAX),
+		clicked_dropdown(false),
+		closing_dropdown(false),
 		timeout(0),
 		clicked_row(UINT_MAX),
 		editable(editable)
@@ -263,7 +268,11 @@
 				DrawBoolButton(buttons_left, y + button_y_offset, current_value != 0, this->editable);
 				SetDParam(2, par_info->GetValue(this->grf_config) == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
 			} else if (par_info->type == PTYPE_UINT_ENUM) {
-				DrawArrowButtons(buttons_left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, this->editable && current_value > par_info->min_value, this->editable && current_value < par_info->max_value);
+				if (par_info->complete_labels) {
+					DrawDropDownButton(buttons_left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && this->clicked_dropdown, this->editable);
+				} else {
+					DrawArrowButtons(buttons_left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, this->editable && current_value > par_info->min_value, this->editable && current_value < par_info->max_value);
+				}
 				SetDParam(2, STR_JUST_INT);
 				SetDParam(3, current_value);
 				if (par_info->value_names.Contains(current_value)) {
@@ -289,6 +298,15 @@
 		}
 	}
 
+	virtual void OnPaint()
+	{
+		if (this->closing_dropdown) {
+			this->closing_dropdown = false;
+			this->clicked_dropdown = false;
+		}
+		this->DrawWidgets();
+	}
+
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
 		switch (widget) {
@@ -316,7 +334,9 @@
 				if (num >= this->vscroll->GetCount()) break;
 				if (this->clicked_row != num) {
 					DeleteChildWindows(WC_QUERY_STRING);
+					HideDropDownMenu(this);
 					this->clicked_row = num;
+					this->clicked_dropdown = false;
 				}
 
 				const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_NP_BACKGROUND);
@@ -329,7 +349,36 @@
 
 				/* One of the arrows is clicked */
 				uint32 old_val = par_info->GetValue(this->grf_config);
-				if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
+				if (par_info->type != PTYPE_BOOL && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && par_info->complete_labels) {
+					if (this->clicked_dropdown) {
+						/* unclick the dropdown */
+						HideDropDownMenu(this);
+						this->clicked_dropdown = false;
+						this->closing_dropdown = false;
+					} else {
+						const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_NP_BACKGROUND);
+						int rel_y = (pt.y - (int)wid->pos_y) % this->line_height;
+
+						Rect wi_rect;
+						wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);;
+						wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
+						wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
+						wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
+
+						/* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
+						if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
+							this->clicked_dropdown = true;
+							this->closing_dropdown = false;
+
+							DropDownList *list = new DropDownList();
+							for (uint32 i = par_info->min_value; i <= par_info->max_value; i++) {
+								list->push_back(new DropDownListCharStringItem(GetGRFStringFromGRFText(par_info->value_names.Find(i)->second), i, false));
+							}
+
+							ShowDropDownListAt(this, list, old_val, -1, wi_rect, COLOUR_ORANGE, true);
+						}
+					}
+				} else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
 					uint32 val = old_val;
 					if (par_info->type == PTYPE_BOOL) {
 						val = !val;
@@ -350,7 +399,7 @@
 						this->clicked_button = num;
 						this->timeout = 5;
 					}
-				} else if (par_info->type == PTYPE_UINT_ENUM && click_count >= 2) {
+				} else if (par_info->type == PTYPE_UINT_ENUM && !par_info->complete_labels && click_count >= 2) {
 					/* Display a query box so users can enter a custom value. */
 					SetDParam(0, old_val);
 					ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_NONE);
@@ -383,6 +432,26 @@
 		this->SetDirty();
 	}
 
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		assert(this->clicked_dropdown);
+		GRFParameterInfo *par_info = ((uint)this->clicked_row < this->grf_config->param_info.Length()) ? this->grf_config->param_info[this->clicked_row] : NULL;
+		if (par_info == NULL) par_info = GetDummyParameterInfo(this->clicked_row);
+		par_info->SetValue(this->grf_config, index);
+		this->SetDirty();
+	}
+
+	virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
+	{
+		/* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
+		 * the same dropdown button was clicked again, and then not open the dropdown again.
+		 * So, we only remember that it was closed, and process it on the next OnPaint, which is
+		 * after OnClick. */
+		assert(this->clicked_dropdown);
+		this->closing_dropdown = true;
+		this->SetDirty();
+	}
+
 	virtual void OnResize()
 	{
 		NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_NP_BACKGROUND);