src/bridge_gui.cpp
branchnoai
changeset 10776 07203fc29812
parent 10715 6bdf79ffb022
child 10920 e33442a2b239
--- a/src/bridge_gui.cpp	Thu May 29 12:52:24 2008 +0000
+++ b/src/bridge_gui.cpp	Thu May 29 15:56:32 2008 +0000
@@ -22,9 +22,6 @@
 
 #include "table/strings.h"
 
-/* Save the sorting during runtime */
-static Listing _bridge_sorting = {false, 0};
-
 /**
  * Carriage for the data we need if we want to build a bridge
  */
@@ -36,53 +33,6 @@
 
 typedef GUIList<BuildBridgeData> GUIBridgeList;
 
-/** Sort the bridges by their index */
-static int CDECL BridgeIndexSorter(const void *a, const void *b)
-{
-	const BuildBridgeData* ba = (BuildBridgeData*)a;
-	const BuildBridgeData* bb = (BuildBridgeData*)b;
-	int r = ba->index - bb->index;
-
-	return (_bridge_sorting.order) ? -r : r;
-}
-
-/** Sort the bridges by their price */
-static int CDECL BridgePriceSorter(const void *a, const void *b)
-{
-	const BuildBridgeData* ba = (BuildBridgeData*)a;
-	const BuildBridgeData* bb = (BuildBridgeData*)b;
-	int r = ba->cost - bb->cost;
-
-	return (_bridge_sorting.order) ? -r : r;
-}
-
-/** Sort the bridges by their maximum speed */
-static int CDECL BridgeSpeedSorter(const void *a, const void *b)
-{
-	const BuildBridgeData* ba = (BuildBridgeData*)a;
-	const BuildBridgeData* bb = (BuildBridgeData*)b;
-	int r = ba->spec->speed - bb->spec->speed;
-
-	return (_bridge_sorting.order) ? -r : r;
-}
-
-typedef int CDECL BridgeSortListingTypeFunction(const void*, const void*);
-
-/* Availible bridge sorting functions */
-static BridgeSortListingTypeFunction* const _bridge_sorter[] = {
-	&BridgeIndexSorter,
-	&BridgePriceSorter,
-	&BridgeSpeedSorter
-};
-
-/* Names of the sorting functions */
-static const StringID _bridge_sort_listing[] = {
-	STR_SORT_BY_NUMBER,
-	STR_ENGINE_SORT_COST,
-	STR_SORT_BY_MAX_SPEED,
-	INVALID_STRING_ID
-};
-
 /**
  * Callback executed after a build Bridge CMD has been called
  *
@@ -109,33 +59,51 @@
 
 class BuildBridgeWindow : public Window {
 private:
-	/* The last size of the build bridge window
-	 * is saved during runtime */
+	/* Runtime saved values */
 	static uint last_size;
+	static Listing last_sorting;
 
+	/* Constants for sorting the bridges */
+	static const StringID sorter_names[];
+	static GUIBridgeList::SortFunction *const sorter_funcs[];
+
+	/* Internal variables */
 	TileIndex start_tile;
 	TileIndex end_tile;
 	uint32 type;
 	GUIBridgeList *bridges;
 
+	/** Sort the bridges by their index */
+	static int CDECL BridgeIndexSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->index - b->index;
+	}
+
+	/** Sort the bridges by their price */
+	static int CDECL BridgePriceSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->cost - b->cost;
+	}
+
+	/** Sort the bridges by their maximum speed */
+	static int CDECL BridgeSpeedSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->spec->speed - b->spec->speed;
+	}
+
 	void BuildBridge(uint8 i)
 	{
-		DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->sort_list[i].index,
+		DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index,
 				CcBuildBridge, CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
 	}
 
 	/** Sort the builable bridges */
 	void SortBridgeList()
 	{
-		/* Skip sorting if resort bit is not set */
-		if (!(bridges->flags & VL_RESORT)) return;
-
-		qsort(this->bridges->sort_list, this->bridges->list_length, sizeof(this->bridges->sort_list[0]), _bridge_sorter[_bridge_sorting.criteria]);
+		this->bridges->Sort();
 
 		/* Display the current sort variant */
-		this->widget[BBSW_DROPDOWN_CRITERIA].data = _bridge_sort_listing[this->bridges->sort_type];
-
-		bridges->flags &= ~VL_RESORT;
+		this->widget[BBSW_DROPDOWN_CRITERIA].data = this->sorter_names[this->bridges->SortType()];
 
 		/* Set the modified widgets dirty */
 		this->InvalidateWidget(BBSW_DROPDOWN_CRITERIA);
@@ -149,13 +117,15 @@
 		type(br_type),
 		bridges(bl)
 	{
+		this->bridges->SetListing(this->last_sorting);
+		this->bridges->SetSortFuncs(this->sorter_funcs);
 		this->SortBridgeList();
 
 		/* Change the data, or the caption of the gui. Set it to road or rail, accordingly */
 		this->widget[BBSW_CAPTION].data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
 
 		this->resize.step_height = 22;
-		this->vscroll.count = bl->list_length;
+		this->vscroll.count = bl->Length();
 
 		if (this->last_size <= 4) {
 			this->vscroll.cap = 4;
@@ -171,7 +141,8 @@
 
 	~BuildBridgeWindow()
 	{
-		free(this->bridges->sort_list);
+		this->last_sorting = this->bridges->GetListing();
+
 		delete bridges;
 	}
 
@@ -183,10 +154,10 @@
 
 		uint y = this->widget[BBSW_BRIDGE_LIST].top + 2;
 
-		for (int i = this->vscroll.pos; (i < (this->vscroll.cap + this->vscroll.pos)) && (i < this->bridges->list_length); i++) {
-			const BridgeSpec *b = this->bridges->sort_list[i].spec;
+		for (int i = this->vscroll.pos; (i < (this->vscroll.cap + this->vscroll.pos)) && (i < (int)this->bridges->Length()); i++) {
+			const BridgeSpec *b = this->bridges->Get(i)->spec;
 
-			SetDParam(2, this->bridges->sort_list[i].cost);
+			SetDParam(2, this->bridges->Get(i)->cost);
 			SetDParam(1, b->speed * 10 / 16);
 			SetDParam(0, b->material);
 
@@ -200,7 +171,7 @@
 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		const uint8 i = keycode - '1';
-		if (i < 9 && i < this->bridges->list_length) {
+		if (i < 9 && i < this->bridges->Length()) {
 			/* Build the requested bridge */
 			this->BuildBridge(i);
 			delete this;
@@ -217,7 +188,7 @@
 				uint i = ((int)pt.y - this->widget[BBSW_BRIDGE_LIST].top) / this->resize.step_height;
 				if (i < this->vscroll.cap) {
 					i += this->vscroll.pos;
-					if (i < this->bridges->list_length) {
+					if (i < this->bridges->Length()) {
 						this->BuildBridge(i);
 						delete this;
 					}
@@ -225,27 +196,21 @@
 			} break;
 
 			case BBSW_DROPDOWN_ORDER:
-				/* Revers the sort order */
-				this->bridges->flags ^= VL_DESC;
-				_bridge_sorting.order = !_bridge_sorting.order;
-
-				this->bridges->flags |= VL_RESORT;
-				this->SortBridgeList();
+				this->bridges->ToggleSortOrder();
+				this->SetDirty();
 				break;
 
 			case BBSW_DROPDOWN_CRITERIA:
-				ShowDropDownMenu(this, _bridge_sort_listing, bridges->sort_type, BBSW_DROPDOWN_CRITERIA, 0, 0);
+				ShowDropDownMenu(this, this->sorter_names, this->bridges->SortType(), BBSW_DROPDOWN_CRITERIA, 0, 0);
 				break;
 		}
 	}
 
 	virtual void OnDropdownSelect(int widget, int index)
 	{
-		if (widget == BBSW_DROPDOWN_CRITERIA && this->bridges->sort_type != index) {
-			this->bridges->sort_type = index;
-			_bridge_sorting.criteria = index;
+		if (widget == BBSW_DROPDOWN_CRITERIA && this->bridges->SortType() != index) {
+			this->bridges->SetSortType(index);
 
-			this->bridges->flags |= VL_RESORT;
 			this->SortBridgeList();
 		}
 	}
@@ -254,7 +219,7 @@
 	{
 		this->vscroll.cap += delta.y / (int)this->resize.step_height;
 		this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1;
-		SetVScrollCount(this, this->bridges->list_length);
+		SetVScrollCount(this, this->bridges->Length());
 
 		this->last_size = this->vscroll.cap;
 	}
@@ -262,6 +227,23 @@
 
 /* Set the default size of the Build Bridge Window */
 uint BuildBridgeWindow::last_size = 4;
+/* Set the default sorting for the bridges */
+Listing BuildBridgeWindow::last_sorting = {false, 0};
+
+/* Availible bridge sorting functions */
+GUIBridgeList::SortFunction* const BuildBridgeWindow::sorter_funcs[] = {
+	&BridgeIndexSorter,
+	&BridgePriceSorter,
+	&BridgeSpeedSorter
+};
+
+/* Names of the sorting functions */
+const StringID BuildBridgeWindow::sorter_names[] = {
+	STR_SORT_BY_NUMBER,
+	STR_ENGINE_SORT_COST,
+	STR_SORT_BY_MAX_SPEED,
+	INVALID_STRING_ID
+};
 
 /* Widget definition for the rail bridge selection window */
 static const Widget _build_bridge_widgets[] = {
@@ -286,35 +268,6 @@
 };
 
 /**
- * Add a buildable bridge to the list.
- *  If the list is empty a new one is created.
- *
- * @param bl The list which we want to manage
- * @param item The item to add
- * @return The pointer to the list
- */
-static GUIBridgeList *PushBridgeList(GUIBridgeList *bl, BuildBridgeData item)
-{
-	if (bl == NULL) {
-		/* Create the list if needed */
-		bl = new GUIBridgeList();
-		bl->flags |= VL_RESORT;
-		if (_bridge_sorting.order) bl->flags |= VL_DESC;
-		bl->list_length = 1;
-		bl->sort_type = _bridge_sorting.criteria;
-	} else {
-		/* Resize the list */
-		bl->list_length++;
-	}
-
-	bl->sort_list = ReallocT(bl->sort_list, bl->list_length);
-
-	bl->sort_list[bl->list_length - 1] = item;
-
-	return bl;
-}
-
-/**
  * Prepare the data for the build a bridge window.
  *  If we can't build a bridge under the given conditions
  *  show an error message.
@@ -350,24 +303,26 @@
 		/* total length of bridge */
 		const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2);
 
+		bl = new GUIBridgeList();
+
 		/* loop for all bridgetypes */
 		for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
 			if (CheckBridge_Stuff(brd_type, bridge_len)) {
 				/* bridge is accepted, add to list */
-				BuildBridgeData item;
-				item.index = brd_type;
-				item.spec = GetBridgeSpec(brd_type);
+				BuildBridgeData *item = bl->Append();
+				item->index = brd_type;
+				item->spec = GetBridgeSpec(brd_type);
 				/* Add to terraforming & bulldozing costs the cost of the
 				 * bridge itself (not computed with DC_QUERY_COST) */
-				item.cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * item.spec->price) >> 8);
-				bl = PushBridgeList(bl, item);
+				item->cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * item->spec->price) >> 8);
 			}
 		}
 	}
 
-	if (bl != NULL) {
+	if (bl != NULL && bl->Length() != 0) {
 		new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl);
 	} else {
+		if (bl != NULL) delete bl;
 		ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
 	}
 }