changeset 19710:426ee8a3f9cd draft

(svn r24631) -Feature: Add buttons to expand/collapse all to advanced settings GUI.
author frosch <frosch@openttd.org>
date Sat, 27 Oct 2012 15:25:57 +0000
parents 015427c7777c
children 817b521c2b1a
files src/lang/english.txt src/settings_gui.cpp src/widgets/settings_widget.h
diffstat 3 files changed, 143 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1103,6 +1103,8 @@
 
 # Advanced settings window
 STR_CONFIG_SETTING_CAPTION                                      :{WHITE}Advanced Settings
+STR_CONFIG_SETTING_EXPAND_ALL                                   :{BLACK}Expand all
+STR_CONFIG_SETTING_COLLAPSE_ALL                                 :{BLACK}Collapse all
 STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT            :(no explanation available)
 STR_CONFIG_SETTING_DEFAULT_VALUE                                :{LTBLUE}Default value: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_TYPE                                         :{LTBLUE}Setting type: {ORANGE}{STRING}
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -1005,9 +1005,12 @@
 
 	void Init(byte level, bool last_field);
 	void FoldAll();
+	void UnFoldAll();
 	void SetButtons(byte new_val);
 
 	uint Length() const;
+	void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
+	bool IsVisible(const SettingEntry *item) const;
 	SettingEntry *FindEntry(uint row, uint *cur_row);
 	uint GetMaxHelpHeight(int maxw);
 
@@ -1036,8 +1039,11 @@
 
 	void Init(byte level = 0);
 	void FoldAll();
+	void UnFoldAll();
 
 	uint Length() const;
+	void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
+	bool IsVisible(const SettingEntry *item) const;
 	SettingEntry *FindEntry(uint row, uint *cur_row) const;
 	uint GetMaxHelpHeight(int maxw);
 
@@ -1112,6 +1118,66 @@
 	}
 }
 
+/** Recursively open all folds of sub-pages */
+void SettingEntry::UnFoldAll()
+{
+	switch (this->flags & SEF_KIND_MASK) {
+		case SEF_SETTING_KIND:
+			break;
+
+		case SEF_SUBTREE_KIND:
+			this->d.sub.folded = false;
+			this->d.sub.page->UnFoldAll();
+			break;
+
+		default: NOT_REACHED();
+	}
+}
+
+/**
+ * Recursively accumulate the folding state of the tree.
+ * @param[in,out] all_folded Set to false, if one entry is not folded.
+ * @param[in,out] all_unfolded Set to false, if one entry is folded.
+ */
+void SettingEntry::GetFoldingState(bool &all_folded, bool &all_unfolded) const
+{
+	switch (this->flags & SEF_KIND_MASK) {
+		case SEF_SETTING_KIND:
+			break;
+
+		case SEF_SUBTREE_KIND:
+			if (this->d.sub.folded) {
+				all_unfolded = false;
+			} else {
+				all_folded = false;
+			}
+			this->d.sub.page->GetFoldingState(all_folded, all_unfolded);
+			break;
+
+		default: NOT_REACHED();
+	}
+}
+
+/**
+ * Check whether an entry is visible and not folded away.
+ * Note: This does not consider the scrolling range; it might still require scrolling ot make the setting really visible.
+ * @param item Entry to search for.
+ * @return true if entry is visible.
+ */
+bool SettingEntry::IsVisible(const SettingEntry *item) const
+{
+	if (this == item) return true;
+
+	switch (this->flags & SEF_KIND_MASK) {
+		case SEF_SETTING_KIND:
+			return false;
+
+		case SEF_SUBTREE_KIND:
+			return !this->d.sub.folded && this->d.sub.page->IsVisible(item);
+
+		default: NOT_REACHED();
+	}
+}
 
 /**
  * Set the button-depressed flags (#SEF_LEFT_DEPRESSED and #SEF_RIGHT_DEPRESSED) to a specified value
@@ -1365,6 +1431,40 @@
 	}
 }
 
+/** Recursively open all folds of sub-pages */
+void SettingsPage::UnFoldAll()
+{
+	for (uint field = 0; field < this->num; field++) {
+		this->entries[field].UnFoldAll();
+	}
+}
+
+/**
+ * Recursively accumulate the folding state of the tree.
+ * @param[in,out] all_folded Set to false, if one entry is not folded.
+ * @param[in,out] all_unfolded Set to false, if one entry is folded.
+ */
+void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
+{
+	for (uint field = 0; field < this->num; field++) {
+		this->entries[field].GetFoldingState(all_folded, all_unfolded);
+	}
+}
+
+/**
+ * Check whether an entry is visible and not folded away.
+ * Note: This does not consider the scrolling range; it might still require scrolling ot make the setting really visible.
+ * @param item Entry to search for.
+ * @return true if entry is visible.
+ */
+bool SettingsPage::IsVisible(const SettingEntry *item) const
+{
+	for (uint field = 0; field < this->num; field++) {
+		if (this->entries[field].IsVisible(item)) return true;
+	}
+	return false;
+}
+
 /** Return number of rows needed to display the whole page */
 uint SettingsPage::Length() const
 {
@@ -1729,7 +1829,7 @@
 		this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
 		this->FinishInitNested(desc, WN_GAME_OPTIONS_GAME_SETTINGS);
 
-		this->vscroll->SetCount(_settings_main_page.Length());
+		this->InvalidateData();
 	}
 
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
@@ -1822,6 +1922,18 @@
 
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
+		switch (widget) {
+			case WID_GS_EXPAND_ALL:
+				_settings_main_page.UnFoldAll();
+				this->InvalidateData();
+				break;
+
+			case WID_GS_COLLAPSE_ALL:
+				_settings_main_page.FoldAll();
+				this->InvalidateData();
+				break;
+		}
+
 		if (widget != WID_GS_OPTIONSPANEL) return;
 
 		uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
@@ -1839,8 +1951,7 @@
 			this->SetDisplayedHelpText(NULL);
 			pe->d.sub.folded = !pe->d.sub.folded; // Flip 'folded'-ness of the sub-page
 
-			this->vscroll->SetCount(_settings_main_page.Length());
-			this->SetDirty();
+			this->InvalidateData();
 			return;
 		}
 
@@ -2032,6 +2143,23 @@
 		this->SetDirty();
 	}
 
+	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
+	{
+		if (!gui_scope) return;
+
+		this->vscroll->SetCount(_settings_main_page.Length());
+
+		if (this->last_clicked != NULL && !_settings_main_page.IsVisible(this->last_clicked)) {
+			this->SetDisplayedHelpText(NULL);
+		}
+
+		bool all_folded = true;
+		bool all_unfolded = true;
+		_settings_main_page.GetFoldingState(all_folded, all_unfolded);
+		this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
+		this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
+	}
+
 	virtual void OnResize()
 	{
 		this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
@@ -2055,7 +2183,13 @@
 		NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
 				SetPadding(WD_FRAMETEXT_TOP, WD_FRAMETEXT_RIGHT, WD_FRAMETEXT_BOTTOM, WD_FRAMETEXT_LEFT),
 		NWidget(NWID_HORIZONTAL),
-			NWidget(NWID_SPACER, INVALID_COLOUR), SetFill(1, 1), SetResize(1, 0),
+			NWidget(WWT_PANEL, COLOUR_MAUVE),
+				NWidget(NWID_HORIZONTAL),
+					NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
+					NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
+					NWidget(NWID_SPACER, INVALID_COLOUR), SetFill(1, 1), SetResize(1, 0),
+				EndContainer(),
+			EndContainer(),
 			NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
 		EndContainer(),
 	EndContainer(),
@@ -2064,7 +2198,7 @@
 static const WindowDesc _settings_selection_desc(
 	WDP_CENTER, 510, 450,
 	WC_GAME_OPTIONS, WC_NONE,
-	0,
+	WDF_UNCLICK_BUTTONS,
 	_nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
 );
 
--- a/src/widgets/settings_widget.h
+++ b/src/widgets/settings_widget.h
@@ -55,6 +55,8 @@
 	WID_GS_OPTIONSPANEL, ///< Panel widget containing the option lists.
 	WID_GS_SCROLLBAR,    ///< Scrollbar.
 	WID_GS_HELP_TEXT,    ///< Information area to display help text of the selected option.
+	WID_GS_EXPAND_ALL,   ///< Expand all button.
+	WID_GS_COLLAPSE_ALL, ///< Collapse all button.
 };
 
 /** Widgets of the #CustomCurrencyWindow class. */