src/station_gui.cpp
branchcpp_gui
changeset 6298 c30fe89622df
parent 6285 187e3ef04cc9
child 6303 84c215fc8eb8
--- a/src/station_gui.cpp	Sat Mar 10 11:07:13 2007 +0000
+++ b/src/station_gui.cpp	Sun Mar 11 16:31:18 2007 +0000
@@ -30,9 +30,9 @@
 	STATIONLIST_WIDGET_BUS,
 	STATIONLIST_WIDGET_AIRPLANE,
 	STATIONLIST_WIDGET_SHIP,
-	STATIONLIST_WIDGET_CARGOSTART = 12,
-	STATIONLIST_WIDGET_NOCARGOWAITING = 24,
-	STATIONLIST_WIDGET_FACILALL = 26,
+	STATIONLIST_WIDGET_CARGOSTART = 20,
+	STATIONLIST_WIDGET_NOCARGOWAITING = 12,
+	STATIONLIST_WIDGET_FACILALL = 14,
 	STATIONLIST_WIDGET_CARGOALL,
 	STATIONLIST_WIDGET_SORTBY,
 	STATIONLIST_WIDGET_SORTCRITERIA,
@@ -138,6 +138,14 @@
 	return (_internal_sort_order & 1) ? sum2 - sum1 : sum1 - sum2;
 }
 
+/**
+ * qsort-compatible version of sorting two stations by maximum rating
+ * @param a   First object to be sorted, must be of type (const Station *)
+ * @param b   Second object to be sorted, must be of type (const Station *)
+ * @return    The sort order
+ * @retval >0 a should come before b in the list
+ * @retval <0 b should come before a in the list
+ */
 static int CDECL StationRatingMaxSorter(const void *a, const void *b)
 {
 	const Station* st1 = *(const Station**)a;
@@ -146,31 +154,31 @@
 	byte maxr2 = 0;
 
 	for (CargoID j = 0; j < NUM_CARGO; j++) {
-		if (st1->goods[j].waiting_acceptance & 0xfff) maxr1 = max(maxr1, st1->goods[j].rating);
-		if (st2->goods[j].waiting_acceptance & 0xfff) maxr2 = max(maxr2, st2->goods[j].rating);
+		if (st1->goods[j].enroute_from != INVALID_STATION) maxr1 = max(maxr1, st1->goods[j].rating);
+		if (st2->goods[j].enroute_from != INVALID_STATION) maxr2 = max(maxr2, st2->goods[j].rating);
 	}
 
 	return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2;
 }
 
-typedef enum StationListFlags {
+enum StationListFlags {
 	SL_ORDER   = 0x01,
 	SL_RESORT  = 0x02,
 	SL_REBUILD = 0x04,
-} StationListFlags;
+};
 
 DECLARE_ENUM_AS_BIT_SET(StationListFlags);
 
-typedef struct plstations_d {
+struct plstations_d {
 	const Station** sort_list;
 	uint16 list_length;
 	byte sort_type;
 	StationListFlags flags;
 	uint16 resort_timer;  //was byte refresh_counter;
-} plstations_d;
+};
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d));
 
-void RebuildStationLists(void)
+void RebuildStationLists()
 {
 	BaseWindow *w = NULL;
 
@@ -182,7 +190,7 @@
 	}
 }
 
-void ResortStationLists(void)
+void ResortStationLists()
 {
 	BaseWindow *w = NULL;
 
@@ -194,7 +202,7 @@
 	}
 }
 
-static void BuildStationsList(plstations_d* sl, PlayerID owner, byte facilities, uint16 cargo_filter)
+static void BuildStationsList(plstations_d* sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty)
 {
 	uint n = 0;
 	const Station *st;
@@ -221,7 +229,7 @@
 					}
 				}
 				//stations without waiting cargo
-				if (num_waiting_cargo == 0 && HASBIT(cargo_filter, NUM_CARGO)) {
+				if (num_waiting_cargo == 0 && include_empty) {
 					station_sort[n++] = st;
 				}
 			}
@@ -259,28 +267,28 @@
 	sl->flags &= ~SL_RESORT;
 }
 
+static uint32 _cargo_filter = std::numeric_limits<uint32>::max();
+
 static void PlayerStationsWndProc(BaseWindow *w, WindowEvent *e)
 {
-	static const uint16 CARGO_ALL_SELECTED = 0x1FFF;
-
 	const PlayerID owner = (PlayerID)w->window_number;
 	static byte facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
-	static uint16 cargo_filter = CARGO_ALL_SELECTED;
 	static Listing station_sort = {0, 0};
+	static bool include_empty = true;
 
 	plstations_d *sl = &WP(w, plstations_d);
 
 	switch (e->event) {
 		case WE_CREATE: /* set up resort timer */
+			if (_cargo_filter == std::numeric_limits<uint32>::max()) _cargo_filter = _cargo_mask;
+
 			for (uint i = 0; i < 5; i++) {
 				if (HASBIT(facilities, i)) w->LowerWidget(i + STATIONLIST_WIDGET_TRAIN);
 			}
-			for (CargoID i = 0; i < NUM_CARGO; i++) {
-				if (HASBIT(cargo_filter, i)) w->LowerWidget(i + STATIONLIST_WIDGET_CARGOSTART);
-			}
+
 			w->SetWidgetLoweredState(STATIONLIST_WIDGET_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
-			w->SetWidgetLoweredState(STATIONLIST_WIDGET_CARGOALL, cargo_filter == CARGO_ALL_SELECTED);
-			w->SetWidgetLoweredState(STATIONLIST_WIDGET_NOCARGOWAITING, HASBIT(cargo_filter, STATIONLIST_WIDGET_NOCARGOWAITING - NUM_CARGO));
+			w->SetWidgetLoweredState(STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
+			w->SetWidgetLoweredState(STATIONLIST_WIDGET_NOCARGOWAITING, include_empty);
 
 			sl->sort_list = NULL;
 			sl->flags = SL_REBUILD;
@@ -290,7 +298,7 @@
 			break;
 
 		case WE_PAINT: {
-			BuildStationsList(sl, owner, facilities, cargo_filter);
+			BuildStationsList(sl, owner, facilities, _cargo_filter, include_empty);
 			SortStationsList(sl);
 
 			SetVScrollCount(w, sl->list_length);
@@ -312,14 +320,16 @@
 			int y = 14;
 			int xb = 2; // offset from left of widget
 
-			for (CargoID i = 0; i < NUM_CARGO; i++) {
-				const CargoSpec *cs = GetCargo(i);
-				if (cs->IsValid()) {
-					cg_ofst = w->IsWidgetLowered(i + STATIONLIST_WIDGET_CARGOSTART) ? 2 : 1;
-					GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
-					DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, 0x10);
-				}
+			uint i = 0;
+			for (CargoID c = 0; c < NUM_CARGO; c++) {
+				const CargoSpec *cs = GetCargo(c);
+				if (!cs->IsValid()) continue;
+
+				cg_ofst = HASBIT(_cargo_filter, c) ? 2 : 1;
+				GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
+				DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, 0x10);
 				x += 14;
+				i++;
 			}
 
 			x += 6;
@@ -412,17 +422,22 @@
 					w->SetDirty();
 					break;
 
-				case STATIONLIST_WIDGET_CARGOALL:
-					for (CargoID i = 0; i < NUM_CARGO; i++) {
+				case STATIONLIST_WIDGET_CARGOALL: {
+					uint i = 0;
+					for (CargoID c = 0; c < NUM_CARGO; c++) {
+						if (!GetCargo(c)->IsValid()) continue;
 						w->LowerWidget(i + STATIONLIST_WIDGET_CARGOSTART);
+						i++;
 					}
 					w->LowerWidget(STATIONLIST_WIDGET_NOCARGOWAITING);
 					w->LowerWidget(STATIONLIST_WIDGET_CARGOALL);
 
-					cargo_filter = CARGO_ALL_SELECTED;
+					_cargo_filter = _cargo_mask;
+					include_empty = true;
 					sl->flags |= SL_REBUILD;
 					w->SetDirty();
 					break;
+				}
 
 				case STATIONLIST_WIDGET_SORTBY: /*flip sorting method asc/desc*/
 					sl->flags ^= SL_ORDER; //DESC-flag
@@ -438,20 +453,53 @@
 					w->ShowDropDownMenu(_station_sort_listing, sl->sort_type, STATIONLIST_WIDGET_SORTDROPBTN, 0, 0);
 					break;
 
+				case STATIONLIST_WIDGET_NOCARGOWAITING:
+					if (_ctrl_pressed) {
+						include_empty = !include_empty;
+						w->ToggleWidgetLoweredState(STATIONLIST_WIDGET_NOCARGOWAITING);
+					} else {
+						for (uint i = STATIONLIST_WIDGET_CARGOSTART; i < w->widget_count; i++) {
+							w->RaiseWidget(i);
+						}
+
+						_cargo_filter = 0;
+						include_empty = true;
+
+						w->LowerWidget(STATIONLIST_WIDGET_NOCARGOWAITING);
+					}
+					sl->flags |= SL_REBUILD;
+					w->SetWidgetLoweredState(STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
+					w->SetDirty();
+					break;
+
 				default:
-					if (e->we.click.widget >= STATIONLIST_WIDGET_CARGOSTART && e->we.click.widget <= STATIONLIST_WIDGET_NOCARGOWAITING) { //change cargo_filter
+					if (e->we.click.widget >= STATIONLIST_WIDGET_CARGOSTART) { //change cargo_filter
+						/* Determine the selected cargo type */
+						CargoID c;
+						int i = 0;
+						for (c = 0; c < NUM_CARGO; c++) {
+							if (!GetCargo(c)->IsValid()) continue;
+							if (e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART == i) break;
+							i++;
+						}
+
 						if (_ctrl_pressed) {
-							TOGGLEBIT(cargo_filter, e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART);
+							TOGGLEBIT(_cargo_filter, c);
 							w->ToggleWidgetLoweredState(e->we.click.widget);
 						} else {
-							for (uint i = 0; cargo_filter != 0; i++, cargo_filter >>= 1) {
-								if (HASBIT(cargo_filter, 0)) w->RaiseWidget(i + STATIONLIST_WIDGET_CARGOSTART);
+							for (uint i = STATIONLIST_WIDGET_CARGOSTART; i < w->widget_count; i++) {
+								w->RaiseWidget(i);
 							}
-							SETBIT(cargo_filter, e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART);
+							w->RaiseWidget(STATIONLIST_WIDGET_NOCARGOWAITING);
+
+							_cargo_filter = 0;
+							include_empty = false;
+
+							SETBIT(_cargo_filter, c);
 							w->LowerWidget(e->we.click.widget);
 						}
 						sl->flags |= SL_REBUILD;
-						w->SetWidgetLoweredState(STATIONLIST_WIDGET_CARGOALL, cargo_filter == CARGO_ALL_SELECTED);
+						w->SetWidgetLoweredState(STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
 						w->SetDirty();
 					}
 					break;
@@ -503,26 +551,14 @@
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    56,    69,    14,    24, STR_SHIP,          STR_USE_CTRL_TO_SELECT_MORE},
 //Index 11
 {      WWT_PANEL,   RESIZE_NONE,    14,    83,    88,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,    89,   102,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   103,   116,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   117,   130,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   131,   144,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   145,   158,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   159,   172,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   173,   186,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   187,   200,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   201,   214,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   215,   228,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   229,   242,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   243,   256,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
-{      WWT_PANEL,   RESIZE_NONE,    14,   257,   270,    14,    24, 0x0,               STR_NO_WAITING_CARGO},
-{      WWT_PANEL,  RESIZE_RIGHT,    14,   285,   357,    14,    24, 0x0,               STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,    14,    89,   102,    14,    24, 0x0,               STR_NO_WAITING_CARGO},
+{      WWT_PANEL,  RESIZE_RIGHT,    14,   117,   357,    14,    24, 0x0,               STR_NULL},
 
-//26
+//14
 {      WWT_PANEL,   RESIZE_NONE,    14,    70,    83,    14,    24, 0x0,               STR_SELECT_ALL_FACILITIES},
-{      WWT_PANEL,   RESIZE_NONE,    14,   271,   284,    14,    24, 0x0,               STR_SELECT_ALL_TYPES},
+{      WWT_PANEL,   RESIZE_NONE,    14,   103,   116,    14,    24, 0x0,               STR_SELECT_ALL_TYPES},
 
-//28
+//16
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     0,    80,    25,    36, STR_SORT_BY,       STR_SORT_ORDER_TIP},
 {      WWT_PANEL,   RESIZE_NONE,    14,    81,   232,    25,    36, 0x0,               STR_SORT_CRITERIA_TIP},
 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   233,   243,    25,    36, STR_0225,          STR_SORT_CRITERIA_TIP},
@@ -550,6 +586,47 @@
 	w->vscroll.cap = 12;
 	w->resize.step_height = 10;
 	w->resize.height = w->Height() - 10 * 7; // minimum if 5 in the list
+
+	/* Add cargo filter buttons */
+	uint num_active = 0;
+	for (CargoID c = 0; c < NUM_CARGO; c++) {
+		if (GetCargo(c)->IsValid()) num_active++;
+	}
+
+	w->widget_count += num_active;
+	w->widget = ReallocT(w->widget, w->widget_count + 1);
+	w->widget[w->widget_count].type = WWT_LAST;
+
+	uint i = 0;
+	for (CargoID c = 0; c < NUM_CARGO; c++) {
+		if (!GetCargo(c)->IsValid()) continue;
+
+		OldWidget *wi = &w->widget[STATIONLIST_WIDGET_CARGOSTART + i];
+		wi->type     = WWT_PANEL;
+		wi->m_display_flags = RESIZE_NONE;
+		wi->color    = 14;
+		wi->left     = 89 + i * 14;
+		wi->right    = wi->left + 13;
+		wi->top      = 14;
+		wi->bottom   = 24;
+		wi->data     = 0;
+		wi->tooltips = STR_USE_CTRL_TO_SELECT_MORE;
+
+		if (HASBIT(_cargo_filter, c)) w->LowerWidget(STATIONLIST_WIDGET_CARGOSTART + i);
+		i++;
+	}
+
+	w->widget[STATIONLIST_WIDGET_NOCARGOWAITING].left += num_active * 14;
+	w->widget[STATIONLIST_WIDGET_NOCARGOWAITING].right += num_active * 14;
+	w->widget[STATIONLIST_WIDGET_CARGOALL].left += num_active * 14;
+	w->widget[STATIONLIST_WIDGET_CARGOALL].right += num_active * 14;
+	w->widget[13].left += num_active * 14;
+
+	if (num_active > 15) {
+		/* Resize and fix the minimum width, if necessary */
+		w->Resize((num_active - 15) * 14, 0);
+		w->resize.width = w->Width();
+	}
 }
 
 static const OldWidget _station_view_expanded_widgets[] = {
@@ -630,8 +707,7 @@
 		y += 10;
 	}
 
-	CargoID i = 0;
-	do {
+	for (CargoID i = 0; i != NUM_CARGO && pos > -5; i++) {
 		uint waiting = GB(st->goods[i].waiting_acceptance, 0, 12);
 		if (waiting == 0) continue;
 
@@ -667,7 +743,7 @@
 				y += 10;
 			}
 		}
-	} while (pos > -5 && ++i != NUM_CARGO);
+	}
 
 	if (w->IsOfPrototype(_station_view_widgets)) {
 		char *b = _userstring;
@@ -746,13 +822,13 @@
 
 				case 10: { /* Show a list of scheduled trains to this station */
 					const Station *st = GetStation(w->window_number);
-					ShowVehicleListWindow(st->owner, VEH_Train, (StationID)w->window_number);
+					ShowVehicleListWindow(st->owner, VEH_TRAIN, (StationID)w->window_number);
 					break;
 				}
 
 				case 11: { /* Show a list of scheduled road-vehicles to this station */
 					const Station *st = GetStation(w->window_number);
-					ShowVehicleListWindow(st->owner, VEH_Road, (StationID)w->window_number);
+					ShowVehicleListWindow(st->owner, VEH_ROAD, (StationID)w->window_number);
 					break;
 				}
 
@@ -760,7 +836,7 @@
 					const Station *st = GetStation(w->window_number);
 					/* Since oilrigs have no owners, show the scheduled aircraft of current player */
 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
-					ShowVehicleListWindow(owner, VEH_Aircraft, (StationID)w->window_number);
+					ShowVehicleListWindow(owner, VEH_AIRCRAFT, (StationID)w->window_number);
 					break;
 				}
 
@@ -768,7 +844,7 @@
 					const Station *st = GetStation(w->window_number);
 					/* Since oilrigs/bouys have no owners, show the scheduled ships of current player */
 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
-					ShowVehicleListWindow(owner, VEH_Ship, (StationID)w->window_number);
+					ShowVehicleListWindow(owner, VEH_SHIP, (StationID)w->window_number);
 					break;
 				}
 			}