changeset 13072:75bd67594af2 draft

(svn r17572) -Codechange: Use the Window::GetWidget() function to access nested widgets through the nested_array.
author alberth <alberth@openttd.org>
date Sat, 19 Sep 2009 11:31:12 +0000
parents f9883dc4e7e7
children 013c3a75e449
files src/ai/ai_gui.cpp src/airport_gui.cpp src/bridge_gui.cpp src/dock_gui.cpp src/industry_gui.cpp src/main_gui.cpp src/misc_gui.cpp src/music_gui.cpp src/network/network_content_gui.cpp src/newgrf_gui.cpp src/news_gui.cpp src/osk_gui.cpp src/rail_gui.cpp src/road_gui.cpp src/settings_gui.cpp src/signs_gui.cpp src/subsidy_gui.cpp src/terraform_gui.cpp src/town_gui.cpp src/transparency_gui.cpp src/waypoint_gui.cpp src/widget.cpp src/widget_type.h src/widgets/dropdown.cpp src/window.cpp src/window_gui.h
diffstat 26 files changed, 162 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -62,9 +62,9 @@
 
 		this->InitNested(desc); // Initializes 'this->line_height' as side effect.
 
-		this->vscroll.SetCapacity(this->nested_array[AIL_WIDGET_LIST]->current_y / this->line_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(AIL_WIDGET_LIST)->current_y / this->line_height);
 		this->vscroll.SetCount((int)this->ai_info_list->size() + 1);
-		this->nested_array[AIL_WIDGET_LIST]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(AIL_WIDGET_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 
 		/* Try if we can find the currently selected AI */
 		this->selected = -1;
@@ -87,7 +87,7 @@
 
 			resize->width = 1;
 			resize->height = this->line_height;
-			size->height = GB(this->nested_array[widget]->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
+			size->height = GB(this->GetWidget<NWidgetCore>(widget)->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
 		}
 	}
 
@@ -101,7 +101,7 @@
 		switch (widget) {
 			case AIL_WIDGET_LIST: {
 				/* Draw a list of all available AIs. */
-				int y = this->nested_array[AIL_WIDGET_LIST]->pos_y;
+				int y = this->GetWidget<NWidgetBase>(AIL_WIDGET_LIST)->pos_y;
 				/* First AI in the list is hardcoded to random */
 				if (this->vscroll.IsVisible(0)) {
 					DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_LEFT, y + WD_MATRIX_TOP, STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_BLACK);
@@ -160,7 +160,7 @@
 	{
 		switch (widget) {
 			case AIL_WIDGET_LIST: { // Select one of the AIs
-				int sel = (pt.y - this->nested_array[AIL_WIDGET_LIST]->pos_y) / this->line_height + this->vscroll.GetPosition() - 1;
+				int sel = (pt.y - this->GetWidget<NWidgetBase>(AIL_WIDGET_LIST)->pos_y) / this->line_height + this->vscroll.GetPosition() - 1;
 				if (sel < (int)this->ai_info_list->size()) {
 					this->selected = sel;
 					this->SetDirty();
@@ -194,7 +194,7 @@
 	{
 		switch (widget) {
 			case AIL_WIDGET_LIST: {
-				int sel = (pt.y - this->nested_array[AIL_WIDGET_LIST]->pos_y) / this->line_height + this->vscroll.GetPosition() - 1;
+				int sel = (pt.y - this->GetWidget<NWidgetBase>(AIL_WIDGET_LIST)->pos_y) / this->line_height + this->vscroll.GetPosition() - 1;
 				if (sel < (int)this->ai_info_list->size()) {
 					this->selected = sel;
 					this->ChangeAI();
@@ -208,7 +208,7 @@
 	virtual void OnResize(Point delta)
 	{
 		this->vscroll.UpdateCapacity(delta.y / this->line_height);
-		this->nested_array[AIL_WIDGET_LIST]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(AIL_WIDGET_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 	}
 };
 
@@ -279,9 +279,9 @@
 
 		this->InitNested(desc);  // Initializes 'this->line_height' as side effect.
 
-		this->vscroll.SetCapacity(this->nested_array[AIS_WIDGET_BACKGROUND]->current_y / this->line_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(AIS_WIDGET_BACKGROUND)->current_y / this->line_height);
 		this->vscroll.SetCount((int)this->ai_config->GetConfigList()->size());
-		this->nested_array[AIS_WIDGET_BACKGROUND]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(AIS_WIDGET_BACKGROUND)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 	}
 
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
@@ -291,7 +291,7 @@
 
 			resize->width = 1;
 			resize->height = this->line_height;
-			size->height = GB(this->nested_array[widget]->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
+			size->height = GB(this->GetWidget<NWidgetCore>(widget)->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
 		}
 	}
 
@@ -335,7 +335,7 @@
 	{
 		switch (widget) {
 			case AIS_WIDGET_BACKGROUND: {
-				int num = (pt.y - this->nested_array[AIS_WIDGET_BACKGROUND]->pos_y) / this->line_height + this->vscroll.GetPosition();
+				int num = (pt.y - this->GetWidget<NWidgetBase>(AIS_WIDGET_BACKGROUND)->pos_y) / this->line_height + this->vscroll.GetPosition();
 				if (num >= (int)this->ai_config->GetConfigList()->size()) break;
 
 				AIConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
@@ -404,7 +404,7 @@
 	virtual void OnResize(Point delta)
 	{
 		this->vscroll.UpdateCapacity(delta.y / this->line_height);
-		this->nested_array[AIS_WIDGET_BACKGROUND]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(AIS_WIDGET_BACKGROUND)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 	}
 
 	virtual void OnTick()
@@ -505,9 +505,9 @@
 	{
 		this->InitNested(&_ai_config_desc); // Initializes 'this->line_height' as a side effect.
 		this->selected_slot = INVALID_COMPANY;
-		this->vscroll.SetCapacity(this->nested_array[AIC_WIDGET_LIST]->current_y / this->line_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(AIC_WIDGET_LIST)->current_y / this->line_height);
 		this->vscroll.SetCount(MAX_COMPANIES);
-		this->nested_array[AIC_WIDGET_LIST]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(AIC_WIDGET_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 		this->OnInvalidateData(0);
 	}
 
@@ -521,7 +521,7 @@
 	{
 		if (widget == AIC_WIDGET_LIST) {
 			this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
-			size->height = GB(this->nested_array[widget]->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
+			size->height = GB(this->GetWidget<NWidgetCore>(widget)->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
 		}
 	}
 
@@ -582,7 +582,7 @@
 			}
 
 			case AIC_WIDGET_LIST: { // Select a slot
-				uint slot = (pt.y - this->nested_array[widget]->pos_y) / this->line_height + this->vscroll.GetPosition();
+				uint slot = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / this->line_height + this->vscroll.GetPosition();
 
 				if (slot == 0 || slot > _settings_newgame.difficulty.max_no_competitors) slot = INVALID_COMPANY;
 				this->selected_slot = (CompanyID)slot;
@@ -724,7 +724,7 @@
 		/* Paint the company icons */
 		for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
 			/* Background is grey by default, will be changed to red for dead AIs */
-			this->nested_array[i + AID_WIDGET_COMPANY_BUTTON_START]->colour = COLOUR_GREY;
+			this->GetWidget<NWidgetCore>(i + AID_WIDGET_COMPANY_BUTTON_START)->colour = COLOUR_GREY;
 
 			const Company *c = Company::GetIfValid(i);
 			if (c == NULL || !c->is_ai) {
@@ -741,7 +741,7 @@
 
 			/* Mark dead AIs by red background */
 			if (c->ai_instance->IsDead()) {
-				this->nested_array[i + AID_WIDGET_COMPANY_BUTTON_START]->colour = COLOUR_RED;
+				this->GetWidget<NWidgetCore>(i + AID_WIDGET_COMPANY_BUTTON_START)->colour = COLOUR_RED;
 			}
 
 			/* Check if we have the company marked as inactive */
@@ -754,7 +754,7 @@
 			}
 
 			byte offset = (i == ai_debug_company) ? 1 : 0;
-			DrawCompanyIcon(i, this->nested_array[AID_WIDGET_COMPANY_BUTTON_START + i]->pos_x + 11 + offset, this->nested_array[AID_WIDGET_COMPANY_BUTTON_START + i]->pos_y + 2 + offset);
+			DrawCompanyIcon(i, this->GetWidget<NWidgetBase>(AID_WIDGET_COMPANY_BUTTON_START + i)->pos_x + 11 + offset, this->GetWidget<NWidgetBase>(AID_WIDGET_COMPANY_BUTTON_START + i)->pos_y + 2 + offset);
 		}
 
 		CompanyID old_company = _current_company;
--- a/src/airport_gui.cpp
+++ b/src/airport_gui.cpp
@@ -223,8 +223,8 @@
 		const AirportFTAClass *airport = GetAirport(_selected_airport_type);
 		int rad = _settings_game.station.modified_catchment ? airport->catchment : (uint)CA_UNMODIFIED;
 
-		uint16 top = this->nested_array[BAW_BTN_DOHILIGHT]->pos_y + this->nested_array[BAW_BTN_DOHILIGHT]->current_y + WD_PAR_VSEP_NORMAL;
-		NWidgetCore *panel_nwi = this->nested_array[BAW_BOTTOMPANEL];
+		uint16 top = this->GetWidget<NWidgetBase>(BAW_BTN_DOHILIGHT)->pos_y + this->GetWidget<NWidgetBase>(BAW_BTN_DOHILIGHT)->current_y + WD_PAR_VSEP_NORMAL;
+		NWidgetBase *panel_nwi = this->GetWidget<NWidgetBase>(BAW_BOTTOMPANEL);
 		int right = panel_nwi->pos_x +  panel_nwi->current_x;
 		int bottom = panel_nwi->pos_y +  panel_nwi->current_y;
 		/* only show the station (airport) noise, if the noise option is activated */
--- a/src/bridge_gui.cpp
+++ b/src/bridge_gui.cpp
@@ -118,7 +118,7 @@
 		this->bridges->Sort();
 
 		/* Display the current sort variant */
-		this->nested_array[BBSW_DROPDOWN_CRITERIA]->widget_data = this->sorter_names[this->bridges->SortType()];
+		this->GetWidget<NWidgetCore>(BBSW_DROPDOWN_CRITERIA)->widget_data = this->sorter_names[this->bridges->SortType()];
 
 		/* Set the modified widgets dirty */
 		this->SetWidgetDirty(BBSW_DROPDOWN_CRITERIA);
@@ -134,7 +134,7 @@
 	{
 		this->CreateNestedTree(desc);
 		/* Change the data, or the caption of the gui. Set it to road or rail, accordingly. */
-		this->nested_array[BBSW_CAPTION]->widget_data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
+		this->GetWidget<NWidgetCore>(BBSW_CAPTION)->widget_data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
 		this->FinishInitNested(desc, GB(br_type, 15, 2)); // Initializes 'this->bridgetext_offset'.
 
 		this->parent = FindWindowById(WC_BUILD_TOOLBAR, GB(this->type, 15, 2));
@@ -144,7 +144,7 @@
 		this->SortBridgeList();
 
 		this->vscroll.SetCount(bl->Length());
-		this->vscroll.SetCapacity(this->nested_array[BBSW_BRIDGE_LIST]->current_y / this->resize.step_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(BBSW_BRIDGE_LIST)->current_y / this->resize.step_height);
 		if (this->last_size < this->vscroll.GetCapacity()) this->last_size = this->vscroll.GetCapacity();
 		if (this->last_size > this->vscroll.GetCount()) this->last_size = this->vscroll.GetCount();
 		/* Resize the bridge selection window if we used a bigger one the last time. */
@@ -152,7 +152,7 @@
 			ResizeWindow(this, 0, (this->last_size - this->vscroll.GetCapacity()) * this->resize.step_height);
 			this->vscroll.SetCapacity(this->last_size);
 		}
-		this->nested_array[BBSW_BRIDGE_LIST]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(BBSW_BRIDGE_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 	}
 
 	~BuildBridgeWindow()
@@ -171,7 +171,7 @@
 	{
 		switch (widget) {
 			case BBSW_DROPDOWN_ORDER: {
-				Dimension d = GetStringBoundingBox(this->nested_array[widget]->widget_data);
+				Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
 				d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the word is centered, also looks nice.
 				d.height += padding.height;
 				*size = maxdim(*size, d);
@@ -253,7 +253,7 @@
 		switch (widget) {
 			default: break;
 			case BBSW_BRIDGE_LIST: {
-				uint i = ((int)pt.y - this->nested_array[BBSW_BRIDGE_LIST]->pos_y) / this->resize.step_height;
+				uint i = ((int)pt.y - this->GetWidget<NWidgetBase>(BBSW_BRIDGE_LIST)->pos_y) / this->resize.step_height;
 				if (i < this->vscroll.GetCapacity()) {
 					i += this->vscroll.GetPosition();
 					if (i < this->bridges->Length()) {
@@ -286,7 +286,7 @@
 	virtual void OnResize(Point delta)
 	{
 		this->vscroll.UpdateCapacity(delta.y / (int)this->resize.step_height);
-		this->nested_array[BBSW_BRIDGE_LIST]->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+		this->GetWidget<NWidgetCore>(BBSW_BRIDGE_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
 
 		this->last_size = max(this->vscroll.GetCapacity(), this->last_size);
 	}
--- a/src/dock_gui.cpp
+++ b/src/dock_gui.cpp
@@ -370,8 +370,8 @@
 		}
 
 		/* strings such as 'Size' and 'Coverage Area' */
-		int top = this->nested_array[BDSW_LT_OFF]->pos_y + this->nested_array[BDSW_LT_OFF]->current_y + WD_PAR_VSEP_NORMAL;
-		NWidgetCore *back_nwi = this->nested_array[BDSW_BACKGROUND];
+		int top = this->GetWidget<NWidgetBase>(BDSW_LT_OFF)->pos_y + this->GetWidget<NWidgetBase>(BDSW_LT_OFF)->current_y + WD_PAR_VSEP_NORMAL;
+		NWidgetBase *back_nwi = this->GetWidget<NWidgetBase>(BDSW_BACKGROUND);
 		int right  = back_nwi->pos_x + back_nwi->current_x;
 		int bottom = back_nwi->pos_y + back_nwi->current_y;
 		top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, false) + WD_PAR_VSEP_NORMAL;
@@ -463,10 +463,10 @@
 	{
 		this->DrawWidgets();
 
-		DrawShipDepotSprite(this->nested_array[BDDW_X]->pos_x + 64, this->nested_array[BDDW_X]->pos_y + 18, 0);
-		DrawShipDepotSprite(this->nested_array[BDDW_X]->pos_x + 32, this->nested_array[BDDW_X]->pos_y + 34, 1);
-		DrawShipDepotSprite(this->nested_array[BDDW_Y]->pos_x + 32, this->nested_array[BDDW_Y]->pos_y + 18, 2);
-		DrawShipDepotSprite(this->nested_array[BDDW_Y]->pos_x + 64, this->nested_array[BDDW_Y]->pos_y + 34, 3);
+		DrawShipDepotSprite(this->GetWidget<NWidgetBase>(BDDW_X)->pos_x + 64, this->GetWidget<NWidgetBase>(BDDW_X)->pos_y + 18, 0);
+		DrawShipDepotSprite(this->GetWidget<NWidgetBase>(BDDW_X)->pos_x + 32, this->GetWidget<NWidgetBase>(BDDW_X)->pos_y + 34, 1);
+		DrawShipDepotSprite(this->GetWidget<NWidgetBase>(BDDW_Y)->pos_x + 32, this->GetWidget<NWidgetBase>(BDDW_Y)->pos_y + 18, 2);
+		DrawShipDepotSprite(this->GetWidget<NWidgetBase>(BDDW_Y)->pos_x + 64, this->GetWidget<NWidgetBase>(BDDW_Y)->pos_y + 34, 3);
 	}
 
 	virtual void OnClick(Point pt, int widget)
--- a/src/industry_gui.cpp
+++ b/src/industry_gui.cpp
@@ -934,7 +934,7 @@
 		this->BuildSortIndustriesList();
 
 		this->InitNested(desc, 0);
-		this->vscroll.SetCapacity(this->nested_array[IDW_INDUSTRY_LIST]->current_y / this->resize.step_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(IDW_INDUSTRY_LIST)->current_y / this->resize.step_height);
 	}
 
 	~IndustryDirectoryWindow()
@@ -980,7 +980,7 @@
 	{
 		switch (widget) {
 			case IDW_DROPDOWN_ORDER: {
-				Dimension d = GetStringBoundingBox(this->nested_array[widget]->widget_data);
+				Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
 				d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the word is centered, also looks nice.
 				d.height += padding.height;
 				*size = maxdim(*size, d);
@@ -1026,7 +1026,7 @@
 				break;
 
 			case IDW_INDUSTRY_LIST: {
-				int y = (pt.y - this->nested_array[widget]->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
+				int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
 				uint16 p;
 
 				if (!IsInsideMM(y, 0, this->vscroll.GetCapacity())) return;
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -215,7 +215,7 @@
 		this->InitNested(&_main_window_desc, 0);
 		ResizeWindow(this, _screen.width, _screen.height);
 
-		NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[MW_VIEWPORT];
+		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(MW_VIEWPORT);
 		nvp->InitializeViewport(this, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
 	}
 
@@ -386,7 +386,7 @@
 	virtual void OnResize(Point delta)
 	{
 		if (this->viewport != NULL) {
-			NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[MW_VIEWPORT];
+			NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(MW_VIEWPORT);
 			nvp->UpdateViewportCoordinates(this);
 		}
 	}
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -416,7 +416,7 @@
 		this->InitNested(&_about_desc);
 
 		this->counter = 5;
-		this->text_position = this->nested_array[AW_FRAME]->pos_y + this->nested_array[AW_FRAME]->current_y;
+		this->text_position = this->GetWidget<NWidgetBase>(AW_FRAME)->pos_y + this->GetWidget<NWidgetBase>(AW_FRAME)->current_y;
 	}
 
 	virtual void SetStringParameters(int widget) const
@@ -468,8 +468,8 @@
 			this->counter = 5;
 			this->text_position--;
 			/* If the last text has scrolled start a new from the start */
-			if (this->text_position < (int)(this->nested_array[AW_FRAME]->pos_y - lengthof(_credits) * this->line_height)) {
-				this->text_position = this->nested_array[AW_FRAME]->pos_y + this->nested_array[AW_FRAME]->current_y;
+			if (this->text_position < (int)(this->GetWidget<NWidgetBase>(AW_FRAME)->pos_y - lengthof(_credits) * this->line_height)) {
+				this->text_position = this->GetWidget<NWidgetBase>(AW_FRAME)->pos_y + this->GetWidget<NWidgetBase>(AW_FRAME)->current_y;
 			}
 			this->SetDirty();
 		}
@@ -1188,7 +1188,7 @@
 	int top;
 	int bottom;
 	if (w->widget == NULL) {
-		const NWidgetCore *wi = w->nested_array[wid];
+		const NWidgetBase *wi = w->GetWidget<NWidgetBase>(wid);
 
 		assert((wi->type & WWT_MASK) == WWT_EDITBOX);
 
--- a/src/music_gui.cpp
+++ b/src/music_gui.cpp
@@ -325,7 +325,7 @@
 	{
 		switch (widget) {
 			case MTSW_LIST_LEFT: { // add to playlist
-				int y = (pt.y - this->nested_array[widget]->pos_y) / FONT_HEIGHT_SMALL;
+				int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / FONT_HEIGHT_SMALL;
 
 				if (msf.playlist < 4) return;
 				if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
@@ -343,7 +343,7 @@
 			} break;
 
 			case MTSW_LIST_RIGHT: { // remove from playlist
-				int y = (pt.y - this->nested_array[widget]->pos_y) / FONT_HEIGHT_SMALL;
+				int y = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / FONT_HEIGHT_SMALL;
 
 				if (msf.playlist < 4) return;
 				if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
@@ -583,11 +583,11 @@
 				break;
 
 			case MW_MUSIC_VOL: case MW_EFFECT_VOL: { // volume sliders
-				int x = pt.x - this->nested_array[widget]->pos_x;
+				int x = pt.x - this->GetWidget<NWidgetBase>(widget)->pos_x;
 
 				byte *vol = (widget == MW_MUSIC_VOL) ? &msf.music_vol : &msf.effect_vol;
 
-				byte new_vol = x * 127 / this->nested_array[widget]->current_x;
+				byte new_vol = x * 127 / this->GetWidget<NWidgetBase>(widget)->current_x;
 				if (new_vol != *vol) {
 					*vol = new_vol;
 					if (widget == MW_MUSIC_VOL) MusicVolumeChanged(new_vol);
--- a/src/network/network_content_gui.cpp
+++ b/src/network/network_content_gui.cpp
@@ -180,7 +180,7 @@
 
 		/* When downloading is finished change cancel in ok */
 		if (this->downloaded_bytes == this->total_bytes) {
-			this->nested_array[NCDSWW_CANCELOK]->widget_data = STR_BUTTON_OK;
+			this->GetWidget<NWidgetCore>(NCDSWW_CANCELOK)->widget_data = STR_BUTTON_OK;
 		}
 
 		this->SetDirty();
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -265,7 +265,7 @@
 
 		this->BuildGrfList();
 		this->SetWidgetDisabledState(ANGRFW_ADD, this->sel == NULL || this->sel->IsOpenTTDBaseGRF());
-		this->vscroll.SetCapacity((this->nested_array[ANGRFW_GRF_LIST]->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / this->resize.step_height);
+		this->vscroll.SetCapacity((this->GetWidget<NWidgetBase>(ANGRFW_GRF_LIST)->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / this->resize.step_height);
 	}
 
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
@@ -335,7 +335,7 @@
 		switch (widget) {
 			case ANGRFW_GRF_LIST: {
 				/* Get row... */
-				uint i = (pt.y - this->nested_array[ANGRFW_GRF_LIST]->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height + this->vscroll.GetPosition();
+				uint i = (pt.y - this->GetWidget<NWidgetBase>(ANGRFW_GRF_LIST)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height + this->vscroll.GetPosition();
 
 				if (i < this->grfs.Length()) {
 					this->sel = this->grfs[i];
--- a/src/news_gui.cpp
+++ b/src/news_gui.cpp
@@ -296,19 +296,19 @@
 		this->CreateNestedTree(desc);
 		switch (this->ni->subtype) {
 			case NS_COMPANY_TROUBLE:
-				this->nested_array[NTW_TITLE]->widget_data = STR_NEWS_COMPANY_IN_TROUBLE_TITLE;
+				this->GetWidget<NWidgetCore>(NTW_TITLE)->widget_data = STR_NEWS_COMPANY_IN_TROUBLE_TITLE;
 				break;
 
 			case NS_COMPANY_MERGER:
-				this->nested_array[NTW_TITLE]->widget_data = STR_NEWS_COMPANY_MERGER_TITLE;
+				this->GetWidget<NWidgetCore>(NTW_TITLE)->widget_data = STR_NEWS_COMPANY_MERGER_TITLE;
 				break;
 
 			case NS_COMPANY_BANKRUPT:
-				this->nested_array[NTW_TITLE]->widget_data = STR_NEWS_COMPANY_BANKRUPT_TITLE;
+				this->GetWidget<NWidgetCore>(NTW_TITLE)->widget_data = STR_NEWS_COMPANY_BANKRUPT_TITLE;
 				break;
 
 			case NS_COMPANY_NEW:
-				this->nested_array[NTW_TITLE]->widget_data = STR_NEWS_COMPANY_LAUNCH_TITLE;
+				this->GetWidget<NWidgetCore>(NTW_TITLE)->widget_data = STR_NEWS_COMPANY_LAUNCH_TITLE;
 				break;
 
 			default:
@@ -317,7 +317,7 @@
 		this->FinishInitNested(desc, 0);
 
 		/* Initialize viewport if it exists. */
-		NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[NTW_VIEWPORT];
+		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(NTW_VIEWPORT);
 		if (nvp != NULL) {
 			nvp->InitializeViewport(this, ni->reftype1 == NR_VEHICLE ? 0x80000000 | ni->ref1 : GetReferenceTile(ni->reftype1, ni->ref1), ZOOM_LVL_NEWS);
 			if (this->ni->flags & NF_NO_TRANSPARENT) nvp->disp_flags |= ND_NO_TRANSPARENCY;
@@ -922,7 +922,7 @@
 	MessageHistoryWindow(const WindowDesc *desc) : Window()
 	{
 		this->InitNested(desc); // Initializes 'this->line_height' and 'this->date_width'.
-		this->vscroll.SetCapacity((this->nested_array[MHW_BACKGROUND]->current_y - this->top_spacing - this->bottom_spacing) / this->line_height);
+		this->vscroll.SetCapacity((this->GetWidget<NWidgetBase>(MHW_BACKGROUND)->current_y - this->top_spacing - this->bottom_spacing) / this->line_height);
 		this->OnInvalidateData(0);
 	}
 
@@ -984,7 +984,7 @@
 			NewsItem *ni = _latest_news;
 			if (ni == NULL) return;
 
-			for (int n = (pt.y - this->nested_array[MHW_BACKGROUND]->pos_y - WD_FRAMERECT_TOP) / this->line_height + this->vscroll.GetPosition(); n > 0; n--) {
+			for (int n = (pt.y - this->GetWidget<NWidgetBase>(MHW_BACKGROUND)->pos_y - WD_FRAMERECT_TOP) / this->line_height + this->vscroll.GetPosition(); n > 0; n--) {
 				ni = ni->prev;
 				if (ni == NULL) return;
 			}
@@ -1145,7 +1145,7 @@
 	virtual void OnInvalidateData(int data)
 	{
 		/* Update the dropdown value for 'set all categories'. */
-		this->nested_array[WIDGET_NEWSOPT_DROP_SUMMARY]->widget_data = this->message_opt[this->state];
+		this->GetWidget<NWidgetCore>(WIDGET_NEWSOPT_DROP_SUMMARY)->widget_data = this->message_opt[this->state];
 
 		/* Update widget to reflect the value of the #_news_ticker_sound variable. */
 		this->SetWidgetLoweredState(WIDGET_NEWSOPT_SOUNDTICKER, _news_ticker_sound);
--- a/src/osk_gui.cpp
+++ b/src/osk_gui.cpp
@@ -79,8 +79,9 @@
 			this->caption = (parent->widget[button].data != STR_NULL) ? parent->widget[button].data : parent->caption;
 		}
 		if (parent->nested_array != NULL) {
-			assert(parent->nested_array[button] != NULL);
-			this->caption = (parent->nested_array[button]->widget_data != STR_NULL) ? parent->nested_array[button]->widget_data : parent->caption;
+			NWidgetCore *par_wid = parent->GetWidget<NWidgetCore>(button);
+			assert(par_wid != NULL);
+			this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : parent->caption;
 		}
 
 		this->qs         = parent;
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -643,15 +643,15 @@
 		const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 
 		assert(railtype < RAILTYPE_END);
-		this->nested_array[RTW_CAPTION]->widget_data      = rti->strings.toolbar_caption;
-		this->nested_array[RTW_BUILD_NS]->widget_data     = rti->gui_sprites.build_ns_rail;
-		this->nested_array[RTW_BUILD_X]->widget_data      = rti->gui_sprites.build_x_rail;
-		this->nested_array[RTW_BUILD_EW]->widget_data     = rti->gui_sprites.build_ew_rail;
-		this->nested_array[RTW_BUILD_Y]->widget_data      = rti->gui_sprites.build_y_rail;
-		this->nested_array[RTW_AUTORAIL]->widget_data     = rti->gui_sprites.auto_rail;
-		this->nested_array[RTW_BUILD_DEPOT]->widget_data  = rti->gui_sprites.build_depot;
-		this->nested_array[RTW_CONVERT_RAIL]->widget_data = rti->gui_sprites.convert_rail;
-		this->nested_array[RTW_BUILD_TUNNEL]->widget_data = rti->gui_sprites.build_tunnel;
+		this->GetWidget<NWidgetCore>(RTW_CAPTION)->widget_data      = rti->strings.toolbar_caption;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_NS)->widget_data     = rti->gui_sprites.build_ns_rail;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_X)->widget_data      = rti->gui_sprites.build_x_rail;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_EW)->widget_data     = rti->gui_sprites.build_ew_rail;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_Y)->widget_data      = rti->gui_sprites.build_y_rail;
+		this->GetWidget<NWidgetCore>(RTW_AUTORAIL)->widget_data     = rti->gui_sprites.auto_rail;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_DEPOT)->widget_data  = rti->gui_sprites.build_depot;
+		this->GetWidget<NWidgetCore>(RTW_CONVERT_RAIL)->widget_data = rti->gui_sprites.convert_rail;
+		this->GetWidget<NWidgetCore>(RTW_BUILD_TUNNEL)->widget_data = rti->gui_sprites.build_tunnel;
 	}
 
 	/** Switch to another rail type.
@@ -1025,7 +1025,7 @@
 			_railstation.station_count = GetNumCustomStations(_railstation.station_class);
 
 			this->vscroll.SetCount(_railstation.station_count);
-			this->vscroll.SetCapacity(GB(this->nested_array[BRSW_NEWST_LIST]->widget_data, MAT_ROW_START, MAT_ROW_BITS));
+			this->vscroll.SetCapacity(GB(this->GetWidget<NWidgetCore>(BRSW_NEWST_LIST)->widget_data, MAT_ROW_START, MAT_ROW_BITS));
 			this->vscroll.SetPosition(Clamp(_railstation.station_type - 2, 0, this->vscroll.GetCount() - this->vscroll.GetCapacity()));
 		} else {
 			/* New stations are not available, so ensure the default station
@@ -1074,8 +1074,8 @@
 		this->DrawWidgets();
 
 		/* 'Accepts' and 'Supplies' texts. */
-		int top = this->nested_array[BRSW_HIGHLIGHT_ON]->pos_y + this->nested_array[BRSW_HIGHLIGHT_ON]->current_y + WD_PAR_VSEP_NORMAL;
-		NWidgetCore *back_nwi = this->nested_array[BRSW_BACKGROUND];
+		int top = this->GetWidget<NWidgetBase>(BRSW_HIGHLIGHT_ON)->pos_y + this->GetWidget<NWidgetBase>(BRSW_HIGHLIGHT_ON)->current_y + WD_PAR_VSEP_NORMAL;
+		NWidgetBase *back_nwi = this->GetWidget<NWidgetBase>(BRSW_BACKGROUND);
 		int right = back_nwi->pos_x +  back_nwi->current_x;
 		int bottom = back_nwi->pos_y +  back_nwi->current_y;
 		top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, false) + WD_PAR_VSEP_NORMAL;
@@ -1113,7 +1113,7 @@
 				size->width = max(size->width, d.width + padding.width);
 
 				this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
-				size->height = GB(this->nested_array[widget]->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
+				size->height = GB(this->GetWidget<NWidgetCore>(widget)->widget_data, MAT_ROW_START, MAT_ROW_BITS) * this->line_height;
 				break;
 			}
 		}
@@ -1306,7 +1306,7 @@
 
 			case BRSW_NEWST_LIST: {
 				const StationSpec *statspec;
-				int y = (pt.y - this->nested_array[BRSW_NEWST_LIST]->pos_y) / this->line_height;
+				int y = (pt.y - this->GetWidget<NWidgetBase>(BRSW_NEWST_LIST)->pos_y) / this->line_height;
 
 				if (y >= this->vscroll.GetCapacity()) return;
 				y += this->vscroll.GetPosition();
@@ -1529,9 +1529,9 @@
 	 */
 	void DrawSignalSprite(byte widget_index, SpriteID image, int8 xrel, uint8 xsize)
 	{
-		int bottom = this->nested_array[widget_index]->pos_y + this->nested_array[widget_index]->current_y - 1;
+		int bottom = this->GetWidget<NWidgetBase>(widget_index)->pos_y + this->GetWidget<NWidgetBase>(widget_index)->current_y - 1;
 		DrawSprite(image + this->IsWidgetLowered(widget_index), PAL_NONE,
-				this->nested_array[widget_index]->pos_x + this->nested_array[widget_index]->current_x / 2 - xrel - xsize / 2 + this->IsWidgetLowered(widget_index),
+				this->GetWidget<NWidgetBase>(widget_index)->pos_x + this->GetWidget<NWidgetBase>(widget_index)->current_x / 2 - xrel - xsize / 2 + this->IsWidgetLowered(widget_index),
 				bottom - 3 + this->IsWidgetLowered(widget_index));
 	}
 
@@ -1568,9 +1568,9 @@
 
 		/* Draw dragging signal density value in the BSW_DRAG_SIGNALS_DENSITY widget */
 		SetDParam(0, _settings_client.gui.drag_signals_density);
-		int right = this->nested_array[BSW_DRAG_SIGNALS_DENSITY]->pos_x + this->nested_array[BSW_DRAG_SIGNALS_DENSITY]->current_x - 1;
-		DrawString(this->nested_array[BSW_DRAG_SIGNALS_DENSITY]->pos_x, right,
-				this->nested_array[BSW_DRAG_SIGNALS_DENSITY]->pos_y + 2, STR_JUST_INT, TC_ORANGE, SA_CENTER);
+		int right = this->GetWidget<NWidgetBase>(BSW_DRAG_SIGNALS_DENSITY)->pos_x + this->GetWidget<NWidgetBase>(BSW_DRAG_SIGNALS_DENSITY)->current_x - 1;
+		DrawString(this->GetWidget<NWidgetBase>(BSW_DRAG_SIGNALS_DENSITY)->pos_x, right,
+				this->GetWidget<NWidgetBase>(BSW_DRAG_SIGNALS_DENSITY)->pos_y + 2, STR_JUST_INT, TC_ORANGE, SA_CENTER);
 	}
 
 	virtual void OnClick(Point pt, int widget)
@@ -1791,8 +1791,8 @@
 			if (this->hscroll.GetPosition() + i < this->hscroll.GetCount()) {
 				const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, this->hscroll.GetPosition() + i);
 
-				int bottom = this->nested_array[BRWW_WAYPOINT_1 + i]->pos_y + this->nested_array[BRWW_WAYPOINT_1 + i]->current_y;
-				DrawWaypointSprite(this->nested_array[BRWW_WAYPOINT_1 + i]->pos_x + TILE_PIXELS, bottom - TILE_PIXELS, this->hscroll.GetPosition() + i, _cur_railtype);
+				int bottom = this->GetWidget<NWidgetBase>(BRWW_WAYPOINT_1 + i)->pos_y + this->GetWidget<NWidgetBase>(BRWW_WAYPOINT_1 + i)->current_y;
+				DrawWaypointSprite(this->GetWidget<NWidgetBase>(BRWW_WAYPOINT_1 + i)->pos_x + TILE_PIXELS, bottom - TILE_PIXELS, this->hscroll.GetPosition() + i, _cur_railtype);
 
 				if (statspec != NULL &&
 						HasBit(statspec->callback_mask, CBM_STATION_AVAIL) &&
--- a/src/road_gui.cpp
+++ b/src/road_gui.cpp
@@ -774,8 +774,8 @@
 
 		this->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE);
 		if ( _cur_roadtype == ROADTYPE_TRAM) {
-			this->nested_array[BRDW_CAPTION]->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
-			for (int i = BRDW_DEPOT_NE; i <= BRDW_DEPOT_NW; i++) this->nested_array[i]->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
+			this->GetWidget<NWidgetCore>(BRDW_CAPTION)->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
+			for (int i = BRDW_DEPOT_NE; i <= BRDW_DEPOT_NW; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
 		}
 
 		this->FinishInitNested(desc, TRANSPORT_ROAD);
@@ -887,8 +887,8 @@
 			BRSW_STATION_NW,
 			WIDGET_LIST_END);
 
-		this->nested_array[BRSW_CAPTION]->widget_data = _road_type_infos[_cur_roadtype].picker_title[rs];
-		for (uint i = BRSW_STATION_NE; i < BRSW_LT_OFF; i++) this->nested_array[i]->tool_tip = _road_type_infos[_cur_roadtype].picker_tooltip[rs];
+		this->GetWidget<NWidgetCore>(BRSW_CAPTION)->widget_data = _road_type_infos[_cur_roadtype].picker_title[rs];
+		for (uint i = BRSW_STATION_NE; i < BRSW_LT_OFF; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = _road_type_infos[_cur_roadtype].picker_tooltip[rs];
 
 		this->LowerWidget(_road_station_picker_orientation + BRSW_STATION_NE);
 		this->LowerWidget(_settings_client.gui.station_show_coverage + BRSW_LT_OFF);
@@ -916,8 +916,8 @@
 
 		/* 'Accepts' and 'Supplies' texts. */
 		StationCoverageType sct = (this->window_class == WC_BUS_STATION) ? SCT_PASSENGERS_ONLY : SCT_NON_PASSENGERS_ONLY;
-		int top = this->nested_array[BRSW_LT_ON]->pos_y + this->nested_array[BRSW_LT_ON]->current_y + WD_PAR_VSEP_NORMAL;
-		NWidgetCore *back_nwi = this->nested_array[BRSW_BACKGROUND];
+		int top = this->GetWidget<NWidgetBase>(BRSW_LT_ON)->pos_y + this->GetWidget<NWidgetBase>(BRSW_LT_ON)->current_y + WD_PAR_VSEP_NORMAL;
+		NWidgetBase *back_nwi = this->GetWidget<NWidgetBase>(BRSW_BACKGROUND);
 		int right = back_nwi->pos_x +  back_nwi->current_x;
 		int bottom = back_nwi->pos_y +  back_nwi->current_y;
 		top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, sct, rad, false) + WD_PAR_VSEP_NORMAL;
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -426,7 +426,7 @@
 		this->SetWidgetLoweredState(GOW_FULLSCREEN_BUTTON, _fullscreen);
 
 		bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
-		this->nested_array[GOW_BASE_GRF_STATUS]->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
+		this->GetWidget<NWidgetCore>(GOW_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
 	}
 };
 
--- a/src/signs_gui.cpp
+++ b/src/signs_gui.cpp
@@ -95,7 +95,7 @@
 	{
 		this->InitNested(desc, window_number);
 
-		this->vscroll.SetCapacity((this->nested_array[SLW_LIST]->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / this->resize.step_height);
+		this->vscroll.SetCapacity((this->GetWidget<NWidgetBase>(SLW_LIST)->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / this->resize.step_height);
 
 		/* Create initial list. */
 		this->signs.ForceRebuild();
@@ -144,7 +144,7 @@
 	virtual void OnClick(Point pt, int widget)
 	{
 		if (widget == SLW_LIST) {
-			uint id_v = (pt.y - this->nested_array[SLW_LIST]->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
+			uint id_v = (pt.y - this->GetWidget<NWidgetBase>(SLW_LIST)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
 
 			if (id_v >= this->vscroll.GetCapacity()) return;
 			id_v += this->vscroll.GetPosition();
--- a/src/subsidy_gui.cpp
+++ b/src/subsidy_gui.cpp
@@ -41,14 +41,14 @@
 	{
 		this->InitNested(desc, window_number);
 		this->OnInvalidateData(0);
-		this->vscroll.SetCapacity(this->nested_array[SLW_PANEL]->current_y / this->resize.step_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(SLW_PANEL)->current_y / this->resize.step_height);
 	}
 
 	virtual void OnClick(Point pt, int widget)
 	{
 		if (widget != SLW_PANEL) return;
 
-		int y = (pt.y - this->nested_array[SLW_PANEL]->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
+		int y = (pt.y - this->GetWidget<NWidgetBase>(SLW_PANEL)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
 		if (!IsInsideMM(y, 0, this->vscroll.GetCapacity())) return;
 
 		y += this->vscroll.GetPosition();
--- a/src/terraform_gui.cpp
+++ b/src/terraform_gui.cpp
@@ -657,7 +657,7 @@
 	ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
 	{
 		this->InitNested(desc, window_number);
-		this->nested_array[ETTW_PLACE_DESERT_LIGHTHOUSE]->tool_tip = (_settings_game.game_creation.landscape == LT_TROPIC) ? STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA : STR_TERRAFORM_TOOLTIP_PLACE_LIGHTHOUSE;
+		this->GetWidget<NWidgetCore>(ETTW_PLACE_DESERT_LIGHTHOUSE)->tool_tip = (_settings_game.game_creation.landscape == LT_TROPIC) ? STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA : STR_TERRAFORM_TOOLTIP_PLACE_LIGHTHOUSE;
 	}
 
 	virtual void OnPaint() {
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -271,12 +271,12 @@
 		this->CreateNestedTree(desc);
 
 		this->town = Town::Get(window_number);
-		if (this->town->larger_town) this->nested_array[TVW_CAPTION]->widget_data = STR_TOWN_VIEW_CITY_CAPTION;
+		if (this->town->larger_town) this->GetWidget<NWidgetCore>(TVW_CAPTION)->widget_data = STR_TOWN_VIEW_CITY_CAPTION;
 
 		this->FinishInitNested(desc, window_number);
 
 		this->flags4 |= WF_DISABLE_VP_SCROLL;
-		NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[TVW_VIEWPORT];
+		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(TVW_VIEWPORT);
 		nvp->InitializeViewport(this, this->town->xy, ZOOM_LVL_NEWS);
 
 		this->ResizeWindowAsNeeded();
@@ -422,7 +422,7 @@
 
 		if (_settings_game.economy.station_noise_level) aimed_height += FONT_HEIGHT_NORMAL;
 
-		NWidgetCore *nwid_info = this->nested_array[TVW_INFOPANEL];
+		NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(TVW_INFOPANEL);
 		if (aimed_height > nwid_info->current_y || (aimed_height < nwid_info->current_y && nwid_info->current_y > nwid_info->smallest_y)) {
 			ResizeWindow(this, 0, aimed_height - nwid_info->current_y);
 		}
@@ -431,7 +431,7 @@
 	virtual void OnResize(Point delta)
 	{
 		if (this->viewport != NULL) {
-			NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[TVW_VIEWPORT];
+			NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(TVW_VIEWPORT);
 			nvp->UpdateViewportCoordinates(this);
 		}
 	}
@@ -621,7 +621,7 @@
 		this->BuildSortTownList();
 
 		this->InitNested(desc, 0);
-		this->vscroll.SetCapacity(this->nested_array[TDW_CENTERTOWN]->current_y / (int)this->resize.step_height);
+		this->vscroll.SetCapacity(this->GetWidget<NWidgetBase>(TDW_CENTERTOWN)->current_y / (int)this->resize.step_height);
 	}
 
 	~TownDirectoryWindow()
@@ -679,7 +679,7 @@
 		switch (widget) {
 			case TDW_SORTNAME:
 			case TDW_SORTPOPULATION: {
-				Dimension d = GetStringBoundingBox(this->nested_array[widget]->widget_data);
+				Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
 				d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the word is centered, also looks nice.
 				d.height += padding.height;
 				*size = maxdim(*size, d);
@@ -737,7 +737,7 @@
 				break;
 
 			case TDW_CENTERTOWN: { // Click on Town Matrix
-				uint16 id_v = (pt.y - this->nested_array[widget]->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
+				uint16 id_v = (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height;
 
 				if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds
 
--- a/src/transparency_gui.cpp
+++ b/src/transparency_gui.cpp
@@ -80,7 +80,7 @@
 				for (uint i = TTW_WIDGET_BEGIN; i < TTW_WIDGET_END; i++) {
 					if (i == TTW_WIDGET_LOADING) continue; // Do not draw button for invisible loading indicators.
 
-					const NWidgetCore *wi = this->nested_array[i];
+					const NWidgetBase *wi = this->GetWidget<NWidgetBase>(i);
 					DrawFrameRect(wi->pos_x + 1, r.top + 2, wi->pos_x + wi->current_x - 2, r.bottom - 2, COLOUR_PALE_GREEN,
 							HasBit(_invisibility_opt, i - TTW_WIDGET_BEGIN) ? FR_LOWERED : FR_NONE);
 				}
@@ -104,7 +104,7 @@
 		} else if (widget == TTW_WIDGET_BUTTONS) {
 			uint i;
 			for (i = TTW_WIDGET_BEGIN; i < TTW_WIDGET_END; i++) {
-				const NWidgetCore *nwid = this->nested_array[i];
+				const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(i);
 				if (IsInsideBS(pt.x, nwid->pos_x, nwid->current_x))
 					break;
 			}
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -52,14 +52,14 @@
 
 		this->CreateNestedTree(desc);
 		if (this->vt == VEH_TRAIN) {
-			this->nested_array[WAYPVW_SHOW_VEHICLES]->SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP);
-			this->nested_array[WAYPVW_CENTERVIEW]->tool_tip = STR_WAYPOINT_VIEW_CENTER_TOOLTIP;
-			this->nested_array[WAYPVW_RENAME]->tool_tip = STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME;
+			this->GetWidget<NWidgetCore>(WAYPVW_SHOW_VEHICLES)->SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP);
+			this->GetWidget<NWidgetCore>(WAYPVW_CENTERVIEW)->tool_tip = STR_WAYPOINT_VIEW_CENTER_TOOLTIP;
+			this->GetWidget<NWidgetCore>(WAYPVW_RENAME)->tool_tip = STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME;
 		}
 		this->FinishInitNested(desc, window_number);
 
 		this->flags4 |= WF_DISABLE_VP_SCROLL;
-		NWidgetViewport *nvp = (NWidgetViewport *)this->nested_array[WAYPVW_VIEWPORT];
+		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WAYPVW_VIEWPORT);
 		nvp->InitializeViewport(this, this->wp->xy, ZOOM_LVL_MIN);
 
 		this->OnInvalidateData(0);
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -834,8 +834,9 @@
 		top = this->widget[widget].top;
 	} else {
 		assert(this->nested_array != NULL);
-		base = offset + this->nested_array[widget]->pos_x + (_dynlang.text_dir == TD_LTR ? this->nested_array[widget]->current_x - WD_SORTBUTTON_ARROW_WIDTH : 0);
-		top = this->nested_array[widget]->pos_y;
+		NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
+		base = offset + nwid->pos_x + (_dynlang.text_dir == TD_LTR ? nwid->current_x - WD_SORTBUTTON_ARROW_WIDTH : 0);
+		top = nwid->pos_y;
 	}
 	DrawString(base, base + WD_SORTBUTTON_ARROW_WIDTH, top + 1 + offset, state == SBS_DOWN ? DOWNARROW : UPARROW, TC_BLACK, SA_CENTER);
 }
@@ -937,7 +938,7 @@
  */
 
 /**
- * @fn void FillNestedArray(NWidgetCore **array, uint length)
+ * @fn void FillNestedArray(NWidgetBase **array, uint length)
  * Fill the Window::nested_array array with pointers to nested widgets in the tree.
  * @param array Base pointer of the array.
  * @param length Length of the array.
@@ -1104,7 +1105,7 @@
 	this->tool_tip = tool_tip;
 }
 
-void NWidgetCore::FillNestedArray(NWidgetCore **array, uint length)
+void NWidgetCore::FillNestedArray(NWidgetBase **array, uint length)
 {
 	if (this->index >= 0 && (uint)(this->index) < length) array[this->index] = this;
 }
@@ -1211,7 +1212,7 @@
 	}
 }
 
-void NWidgetContainer::FillNestedArray(NWidgetCore **array, uint length)
+void NWidgetContainer::FillNestedArray(NWidgetBase **array, uint length)
 {
 	for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
 		child_wid->FillNestedArray(array, length);
@@ -1640,7 +1641,7 @@
 	this->smallest_y = this->min_y;
 }
 
-void NWidgetSpacer::FillNestedArray(NWidgetCore **array, uint length)
+void NWidgetSpacer::FillNestedArray(NWidgetBase **array, uint length)
 {
 }
 
@@ -1772,7 +1773,7 @@
 	if (this->child != NULL) this->child->StoreWidgets(widgets, length, left_moving, top_moving, rtl);
 }
 
-void NWidgetBackground::FillNestedArray(NWidgetCore **array, uint length)
+void NWidgetBackground::FillNestedArray(NWidgetBase **array, uint length)
 {
 	if (this->index >= 0 && (uint)(this->index) < length) array[this->index] = this;
 	if (this->child != NULL) this->child->FillNestedArray(array, length);
@@ -1832,7 +1833,7 @@
 Scrollbar *NWidgetBackground::FindScrollbar(Window *w, bool allow_next)
 {
 	if (this->index > 0 && allow_next && this->child == NULL && (uint)(this->index) + 1 < w->nested_array_size) {
-		NWidgetCore *next_wid = w->nested_array[this->index + 1];
+		NWidgetCore *next_wid = w->GetWidget<NWidgetCore>(this->index + 1);
 		if (next_wid != NULL) return next_wid->FindScrollbar(w, false);
 	}
 	return NULL;
@@ -2278,7 +2279,7 @@
 	if (this->type == WWT_SCROLL2BAR) return &w->vscroll2;
 
 	if (this->index > 0 && allow_next && (uint)(this->index) + 1 < w->nested_array_size) {
-		NWidgetCore *next_wid = w->nested_array[this->index + 1];
+		NWidgetCore *next_wid = w->GetWidget<NWidgetCore>(this->index + 1);
 		if (next_wid != NULL) return next_wid->FindScrollbar(w, false);
 	}
 	return NULL;
--- a/src/widget_type.h
+++ b/src/widget_type.h
@@ -185,7 +185,7 @@
 	virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool allow_resize_x, bool allow_resize_y, bool rtl) = 0;
 
 	virtual void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl) = 0;
-	virtual void FillNestedArray(NWidgetCore **array, uint length) = 0;
+	virtual void FillNestedArray(NWidgetBase **array, uint length) = 0;
 
 	virtual NWidgetCore *GetWidgetFromPos(int x, int y) = 0;
 	virtual NWidgetBase *GetWidgetOfType(WidgetType tp);
@@ -307,7 +307,7 @@
 	inline bool IsDisabled();
 
 	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
-	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
+	/* virtual */ void FillNestedArray(NWidgetBase **array, uint length);
 	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
 
 	virtual Scrollbar *FindScrollbar(Window *w, bool allow_next = true) = 0;
@@ -358,7 +358,7 @@
 	~NWidgetContainer();
 
 	void Add(NWidgetBase *wid);
-	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
+	/* virtual */ void FillNestedArray(NWidgetBase **array, uint length);
 
 	/** Return whether the container is empty. */
 	inline bool IsEmpty() { return head == NULL; };
@@ -455,7 +455,7 @@
 
 	void SetupSmallestSize(Window *w, bool init_array);
 	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
-	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
+	/* virtual */ void FillNestedArray(NWidgetBase **array, uint length);
 
 	/* virtual */ void Draw(const Window *w);
 	/* virtual */ void SetDirty(const Window *w) const;
@@ -476,7 +476,7 @@
 	void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool allow_resize_x, bool allow_resize_y, bool rtl);
 
 	void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl);
-	/* virtual */ void FillNestedArray(NWidgetCore **array, uint length);
+	/* virtual */ void FillNestedArray(NWidgetBase **array, uint length);
 
 	/* virtual */ void Draw(const Window *w);
 	/* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y);
--- a/src/widgets/dropdown.cpp
+++ b/src/widgets/dropdown.cpp
@@ -259,7 +259,7 @@
 	Rect wi_rect;
 	Colours wi_colour;
 	if (w->nested_array != NULL) {
-		const NWidgetCore *nwi = w->nested_array[button];
+		const NWidgetCore *nwi = w->GetWidget<NWidgetCore>(button);
 		wi_rect.left   = nwi->pos_x;
 		wi_rect.right  = nwi->pos_x + nwi->current_x - 1;
 		wi_rect.top    = nwi->pos_y;
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -164,12 +164,12 @@
 
 		assert(this->nested_array[widget_index] != NULL); // Setting focus to a non-existing widget is a bad idea.
 		if (this->nested_focus != NULL) {
-			if (this->nested_array[widget_index] == this->nested_focus) return false;
+			if (this->GetWidget<NWidgetCore>(widget_index) == this->nested_focus) return false;
 
 			/* Repaint the widget that lost focus. A focused edit box may else leave the caret on the screen. */
 			this->nested_focus->SetDirty(this);
 		}
-		this->nested_focus = this->nested_array[widget_index];
+		this->nested_focus = this->GetWidget<NWidgetCore>(widget_index);
 		return true;
 	}
 	NOT_REACHED();
@@ -486,7 +486,7 @@
 		}
 	}
 
-	if (w->nested_array != NULL && (uint)widget < w->nested_array_size) sb = w->nested_array[widget]->FindScrollbar(w);
+	if (w->nested_array != NULL && (uint)widget < w->nested_array_size) sb = w->GetWidget<NWidgetCore>(widget)->FindScrollbar(w);
 
 	if (sb != NULL && sb->GetCount() > sb->GetCapacity()) {
 		sb->UpdatePosition(wheel);
@@ -912,7 +912,7 @@
 	/* If available, initialize nested widget tree. */
 	if (widget == NULL) {
 		if (this->nested_array == NULL) {
-			this->nested_array = CallocT<NWidgetCore *>(this->nested_array_size);
+			this->nested_array = CallocT<NWidgetBase *>(this->nested_array_size);
 			this->nested_root->SetupSmallestSize(this, true);
 		} else {
 			this->nested_root->SetupSmallestSize(this, false);
@@ -1339,7 +1339,7 @@
 	this->nested_array_size = (uint)(biggest_index + 1);
 
 	if (fill_nested) {
-		this->nested_array = CallocT<NWidgetCore *>(this->nested_array_size);
+		this->nested_array = CallocT<NWidgetBase *>(this->nested_array_size);
 		this->nested_root->FillNestedArray(this->nested_array, this->nested_array_size);
 	}
 }
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -391,13 +391,17 @@
 	const Widget *focused_widget;    ///< Currently focused widget, or \c NULL if no widget has focus.
 	const NWidgetCore *nested_focus; ///< Currently focused nested widget, or \c NULL if no nested widget has focus.
 	NWidgetBase *nested_root;        ///< Root of the nested tree.
-	NWidgetCore **nested_array;      ///< Array of pointers into the tree.
+	NWidgetBase **nested_array;      ///< Array of pointers into the tree. Do not access directly, use #Window::GetWidget() instead.
 	uint nested_array_size;          ///< Size of the nested array.
 
 	Window *parent;                  ///< Parent window.
 	Window *z_front;                 ///< The window in front of us in z-order.
 	Window *z_back;                  ///< The window behind us in z-order.
 
+	template <class NWID = NWidgetBase>
+	inline NWID *GetWidget(uint widnum) const;
+
+
 	void InitNested(const WindowDesc *desc, WindowNumber number = 0);
 	void CreateNestedTree(const WindowDesc *desc, bool fill_nested = true);
 	void FinishInitNested(const WindowDesc *desc, WindowNumber window_number);
@@ -417,7 +421,7 @@
 		}
 		if (this->nested_array != NULL) {
 			assert(widget_index < this->nested_array_size);
-			if (this->nested_array[widget_index] != NULL) this->nested_array[widget_index]->SetDisabled(disab_stat);
+			if (this->nested_array[widget_index] != NULL) this->GetWidget<NWidgetCore>(widget_index)->SetDisabled(disab_stat);
 		}
 	}
 
@@ -448,7 +452,7 @@
 	{
 		if (this->nested_array != NULL) {
 			assert(widget_index < this->nested_array_size);
-			return this->nested_array[widget_index]->IsDisabled();
+			return this->GetWidget<NWidgetCore>(widget_index)->IsDisabled();
 		}
 		assert(widget_index < this->widget_count);
 		return HasBit(this->widget[widget_index].display_flags, WIDG_DISABLED);
@@ -531,7 +535,7 @@
 		}
 		if (this->nested_array != NULL) {
 			assert(widget_index < this->nested_array_size);
-			this->nested_array[widget_index]->SetLowered(lowered_stat);
+			this->GetWidget<NWidgetCore>(widget_index)->SetLowered(lowered_stat);
 		}
 	}
 
@@ -547,8 +551,8 @@
 		}
 		if (this->nested_array != NULL) {
 			assert(widget_index < this->nested_array_size);
-			bool lowered_state = this->nested_array[widget_index]->IsLowered();
-			this->nested_array[widget_index]->SetLowered(!lowered_state);
+			bool lowered_state = this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
+			this->GetWidget<NWidgetCore>(widget_index)->SetLowered(!lowered_state);
 		}
 	}
 
@@ -579,7 +583,7 @@
 	{
 		if (this->nested_array != NULL) {
 			assert(widget_index < this->nested_array_size);
-			return this->nested_array[widget_index]->IsLowered();
+			return this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
 		}
 		assert(widget_index < this->widget_count);
 		return HasBit(this->widget[widget_index].display_flags, WIDG_LOWERED);
@@ -838,6 +842,29 @@
 	/*** End of the event handling ***/
 };
 
+/** Get the nested widget with number \a widnum from the nested widget tree.
+ * @tparam NWID Type of the nested widget.
+ * @param widnum Widget number of the widget to retrieve.
+ * @return The requested widget if it is instantiated, \c NULL otherwise.
+ */
+template <class NWID>
+inline NWID *Window::GetWidget(uint widnum) const
+{
+	if (widnum >= this->nested_array_size || this->nested_array[widnum] == NULL) return NULL;
+	NWID *nwid = dynamic_cast<NWID *>(this->nested_array[widnum]);
+	assert(nwid != NULL);
+	return nwid;
+}
+
+/** Specialized case of #Window::GetWidget for the nested widget base class. */
+template <>
+inline NWidgetBase *Window::GetWidget<NWidgetBase>(uint widnum) const
+{
+	if (widnum >= this->nested_array_size) return NULL;
+	return this->nested_array[widnum];
+}
+
+
 /**
  * Base class for windows opened from a toolbar.
  */