src/station_gui.cpp
branchgamebalance
changeset 9895 7bd07f43b0e3
parent 6528 b705912233fa
child 9906 6f41b8713b65
equal deleted inserted replaced
9894:70d78ac95d6c 9895:7bd07f43b0e3
    28 	STATIONLIST_WIDGET_TRAIN =6,
    28 	STATIONLIST_WIDGET_TRAIN =6,
    29 	STATIONLIST_WIDGET_TRUCK,
    29 	STATIONLIST_WIDGET_TRUCK,
    30 	STATIONLIST_WIDGET_BUS,
    30 	STATIONLIST_WIDGET_BUS,
    31 	STATIONLIST_WIDGET_AIRPLANE,
    31 	STATIONLIST_WIDGET_AIRPLANE,
    32 	STATIONLIST_WIDGET_SHIP,
    32 	STATIONLIST_WIDGET_SHIP,
    33 	STATIONLIST_WIDGET_CARGOSTART = 12,
    33 	STATIONLIST_WIDGET_CARGOSTART = 20,
    34 	STATIONLIST_WIDGET_NOCARGOWAITING = 24,
    34 	STATIONLIST_WIDGET_NOCARGOWAITING = 12,
    35 	STATIONLIST_WIDGET_FACILALL = 26,
    35 	STATIONLIST_WIDGET_FACILALL = 14,
    36 	STATIONLIST_WIDGET_CARGOALL,
    36 	STATIONLIST_WIDGET_CARGOALL,
    37 	STATIONLIST_WIDGET_SORTBY,
    37 	STATIONLIST_WIDGET_SORTBY,
    38 	STATIONLIST_WIDGET_SORTCRITERIA,
    38 	STATIONLIST_WIDGET_SORTCRITERIA,
    39 	STATIONLIST_WIDGET_SORTDROPBTN,
    39 	STATIONLIST_WIDGET_SORTDROPBTN,
    40 };
    40 };
   136 	}
   136 	}
   137 
   137 
   138 	return (_internal_sort_order & 1) ? sum2 - sum1 : sum1 - sum2;
   138 	return (_internal_sort_order & 1) ? sum2 - sum1 : sum1 - sum2;
   139 }
   139 }
   140 
   140 
       
   141 /**
       
   142  * qsort-compatible version of sorting two stations by maximum rating
       
   143  * @param a   First object to be sorted, must be of type (const Station *)
       
   144  * @param b   Second object to be sorted, must be of type (const Station *)
       
   145  * @return    The sort order
       
   146  * @retval >0 a should come before b in the list
       
   147  * @retval <0 b should come before a in the list
       
   148  */
   141 static int CDECL StationRatingMaxSorter(const void *a, const void *b)
   149 static int CDECL StationRatingMaxSorter(const void *a, const void *b)
   142 {
   150 {
   143 	const Station* st1 = *(const Station**)a;
   151 	const Station* st1 = *(const Station**)a;
   144 	const Station* st2 = *(const Station**)b;
   152 	const Station* st2 = *(const Station**)b;
   145 	byte maxr1 = 0;
   153 	byte maxr1 = 0;
   146 	byte maxr2 = 0;
   154 	byte maxr2 = 0;
   147 
   155 
   148 	for (CargoID j = 0; j < NUM_CARGO; j++) {
   156 	for (CargoID j = 0; j < NUM_CARGO; j++) {
   149 		if (st1->goods[j].waiting_acceptance & 0xfff) maxr1 = max(maxr1, st1->goods[j].rating);
   157 		if (st1->goods[j].enroute_from != INVALID_STATION) maxr1 = max(maxr1, st1->goods[j].rating);
   150 		if (st2->goods[j].waiting_acceptance & 0xfff) maxr2 = max(maxr2, st2->goods[j].rating);
   158 		if (st2->goods[j].enroute_from != INVALID_STATION) maxr2 = max(maxr2, st2->goods[j].rating);
   151 	}
   159 	}
   152 
   160 
   153 	return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2;
   161 	return (_internal_sort_order & 1) ? maxr2 - maxr1 : maxr1 - maxr2;
   154 }
   162 }
   155 
   163 
   156 typedef enum StationListFlags {
   164 enum StationListFlags {
   157 	SL_ORDER   = 0x01,
   165 	SL_ORDER   = 0x01,
   158 	SL_RESORT  = 0x02,
   166 	SL_RESORT  = 0x02,
   159 	SL_REBUILD = 0x04,
   167 	SL_REBUILD = 0x04,
   160 } StationListFlags;
   168 };
   161 
   169 
   162 DECLARE_ENUM_AS_BIT_SET(StationListFlags);
   170 DECLARE_ENUM_AS_BIT_SET(StationListFlags);
   163 
   171 
   164 typedef struct plstations_d {
   172 struct plstations_d {
   165 	const Station** sort_list;
   173 	const Station** sort_list;
   166 	uint16 list_length;
   174 	uint16 list_length;
   167 	byte sort_type;
   175 	byte sort_type;
   168 	StationListFlags flags;
   176 	StationListFlags flags;
   169 	uint16 resort_timer;  //was byte refresh_counter;
   177 	uint16 resort_timer;  //was byte refresh_counter;
   170 } plstations_d;
   178 };
   171 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d));
   179 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d));
   172 
   180 
   173 void RebuildStationLists(void)
   181 void RebuildStationLists()
   174 {
   182 {
   175 	Window* const *wz;
   183 	Window* const *wz;
   176 
   184 
   177 	FOR_ALL_WINDOWS(wz) {
   185 	FOR_ALL_WINDOWS(wz) {
   178 		Window *w = *wz;
   186 		Window *w = *wz;
   181 			SetWindowDirty(w);
   189 			SetWindowDirty(w);
   182 		}
   190 		}
   183 	}
   191 	}
   184 }
   192 }
   185 
   193 
   186 void ResortStationLists(void)
   194 void ResortStationLists()
   187 {
   195 {
   188 	Window* const *wz;
   196 	Window* const *wz;
   189 
   197 
   190 	FOR_ALL_WINDOWS(wz) {
   198 	FOR_ALL_WINDOWS(wz) {
   191 		Window *w = *wz;
   199 		Window *w = *wz;
   194 			SetWindowDirty(w);
   202 			SetWindowDirty(w);
   195 		}
   203 		}
   196 	}
   204 	}
   197 }
   205 }
   198 
   206 
   199 static void BuildStationsList(plstations_d* sl, PlayerID owner, byte facilities, uint16 cargo_filter)
   207 static void BuildStationsList(plstations_d* sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty)
   200 {
   208 {
   201 	uint n = 0;
   209 	uint n = 0;
   202 	const Station *st;
   210 	const Station *st;
   203 
   211 
   204 	if (!(sl->flags & SL_REBUILD)) return;
   212 	if (!(sl->flags & SL_REBUILD)) return;
   221 							break;
   229 							break;
   222 						}
   230 						}
   223 					}
   231 					}
   224 				}
   232 				}
   225 				//stations without waiting cargo
   233 				//stations without waiting cargo
   226 				if (num_waiting_cargo == 0 && HASBIT(cargo_filter, NUM_CARGO)) {
   234 				if (num_waiting_cargo == 0 && include_empty) {
   227 					station_sort[n++] = st;
   235 					station_sort[n++] = st;
   228 				}
   236 				}
   229 			}
   237 			}
   230 		}
   238 		}
   231 	}
   239 	}
   259 
   267 
   260 	sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   268 	sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   261 	sl->flags &= ~SL_RESORT;
   269 	sl->flags &= ~SL_RESORT;
   262 }
   270 }
   263 
   271 
       
   272 static const uint32 _cargo_filter_max = ~0;
       
   273 static uint32 _cargo_filter = _cargo_filter_max;
       
   274 
   264 static void PlayerStationsWndProc(Window *w, WindowEvent *e)
   275 static void PlayerStationsWndProc(Window *w, WindowEvent *e)
   265 {
   276 {
   266 	static const uint16 CARGO_ALL_SELECTED = 0x1FFF;
       
   267 
       
   268 	const PlayerID owner = (PlayerID)w->window_number;
   277 	const PlayerID owner = (PlayerID)w->window_number;
   269 	static byte facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
   278 	static byte facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
   270 	static uint16 cargo_filter = CARGO_ALL_SELECTED;
       
   271 	static Listing station_sort = {0, 0};
   279 	static Listing station_sort = {0, 0};
       
   280 	static bool include_empty = true;
   272 
   281 
   273 	plstations_d *sl = &WP(w, plstations_d);
   282 	plstations_d *sl = &WP(w, plstations_d);
   274 
   283 
   275 	switch (e->event) {
   284 	switch (e->event) {
   276 		case WE_CREATE: /* set up resort timer */
   285 		case WE_CREATE: /* set up resort timer */
       
   286 			if (_cargo_filter == _cargo_filter_max) _cargo_filter = _cargo_mask;
       
   287 
   277 			for (uint i = 0; i < 5; i++) {
   288 			for (uint i = 0; i < 5; i++) {
   278 				if (HASBIT(facilities, i)) LowerWindowWidget(w, i + STATIONLIST_WIDGET_TRAIN);
   289 				if (HASBIT(facilities, i)) LowerWindowWidget(w, i + STATIONLIST_WIDGET_TRAIN);
   279 			}
   290 			}
   280 			for (CargoID i = 0; i < NUM_CARGO; i++) {
       
   281 				if (HASBIT(cargo_filter, i)) LowerWindowWidget(w, i + STATIONLIST_WIDGET_CARGOSTART);
       
   282 			}
       
   283 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
   291 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_FACILALL, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
   284 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_CARGOALL, cargo_filter == CARGO_ALL_SELECTED);
   292 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
   285 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_NOCARGOWAITING, HASBIT(cargo_filter, STATIONLIST_WIDGET_NOCARGOWAITING - NUM_CARGO));
   293 			SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_NOCARGOWAITING, include_empty);
   286 
   294 
   287 			sl->sort_list = NULL;
   295 			sl->sort_list = NULL;
   288 			sl->flags = SL_REBUILD;
   296 			sl->flags = SL_REBUILD;
   289 			sl->sort_type = station_sort.criteria;
   297 			sl->sort_type = station_sort.criteria;
   290 			if (station_sort.order) sl->flags |= SL_ORDER;
   298 			if (station_sort.order) sl->flags |= SL_ORDER;
   291 			sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   299 			sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   292 			break;
   300 			break;
   293 
   301 
   294 		case WE_PAINT: {
   302 		case WE_PAINT: {
   295 			BuildStationsList(sl, owner, facilities, cargo_filter);
   303 			BuildStationsList(sl, owner, facilities, _cargo_filter, include_empty);
   296 			SortStationsList(sl);
   304 			SortStationsList(sl);
   297 
   305 
   298 			SetVScrollCount(w, sl->list_length);
   306 			SetVScrollCount(w, sl->list_length);
   299 
   307 
   300 			/* draw widgets, with player's name in the caption */
   308 			/* draw widgets, with player's name in the caption */
   312 			int cg_ofst;
   320 			int cg_ofst;
   313 			int x = 89;
   321 			int x = 89;
   314 			int y = 14;
   322 			int y = 14;
   315 			int xb = 2; // offset from left of widget
   323 			int xb = 2; // offset from left of widget
   316 
   324 
   317 			for (CargoID i = 0; i < NUM_CARGO; i++) {
   325 			uint i = 0;
   318 				const CargoSpec *cs = GetCargo(i);
   326 			for (CargoID c = 0; c < NUM_CARGO; c++) {
   319 				if (cs->IsValid()) {
   327 				const CargoSpec *cs = GetCargo(c);
   320 					cg_ofst = IsWindowWidgetLowered(w, i + STATIONLIST_WIDGET_CARGOSTART) ? 2 : 1;
   328 				if (!cs->IsValid()) continue;
   321 					GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
   329 
   322 					DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, 0x10);
   330 				cg_ofst = HASBIT(_cargo_filter, c) ? 2 : 1;
   323 				}
   331 				GfxFillRect(x + cg_ofst, y + cg_ofst, x + cg_ofst + 10 , y + cg_ofst + 7, cs->rating_colour);
       
   332 				DrawStringCentered(x + 6 + cg_ofst, y + cg_ofst, cs->abbrev, 0x10);
   324 				x += 14;
   333 				x += 14;
       
   334 				i++;
   325 			}
   335 			}
   326 
   336 
   327 			x += 6;
   337 			x += 6;
   328 			cg_ofst = IsWindowWidgetLowered(w, STATIONLIST_WIDGET_NOCARGOWAITING) ? 2 : 1;
   338 			cg_ofst = IsWindowWidgetLowered(w, STATIONLIST_WIDGET_NOCARGOWAITING) ? 2 : 1;
   329 			DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_NONE, 16);
   339 			DrawStringCentered(x + cg_ofst, y + cg_ofst, STR_ABBREV_NONE, 16);
   412 					facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
   422 					facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
   413 					sl->flags |= SL_REBUILD;
   423 					sl->flags |= SL_REBUILD;
   414 					SetWindowDirty(w);
   424 					SetWindowDirty(w);
   415 					break;
   425 					break;
   416 
   426 
   417 				case STATIONLIST_WIDGET_CARGOALL:
   427 				case STATIONLIST_WIDGET_CARGOALL: {
   418 					for (CargoID i = 0; i < NUM_CARGO; i++) {
   428 					uint i = 0;
       
   429 					for (CargoID c = 0; c < NUM_CARGO; c++) {
       
   430 						if (!GetCargo(c)->IsValid()) continue;
   419 						LowerWindowWidget(w, i + STATIONLIST_WIDGET_CARGOSTART);
   431 						LowerWindowWidget(w, i + STATIONLIST_WIDGET_CARGOSTART);
       
   432 						i++;
   420 					}
   433 					}
   421 					LowerWindowWidget(w, STATIONLIST_WIDGET_NOCARGOWAITING);
   434 					LowerWindowWidget(w, STATIONLIST_WIDGET_NOCARGOWAITING);
   422 					LowerWindowWidget(w, STATIONLIST_WIDGET_CARGOALL);
   435 					LowerWindowWidget(w, STATIONLIST_WIDGET_CARGOALL);
   423 
   436 
   424 					cargo_filter = CARGO_ALL_SELECTED;
   437 					_cargo_filter = _cargo_mask;
       
   438 					include_empty = true;
   425 					sl->flags |= SL_REBUILD;
   439 					sl->flags |= SL_REBUILD;
   426 					SetWindowDirty(w);
   440 					SetWindowDirty(w);
   427 					break;
   441 					break;
       
   442 				}
   428 
   443 
   429 				case STATIONLIST_WIDGET_SORTBY: /*flip sorting method asc/desc*/
   444 				case STATIONLIST_WIDGET_SORTBY: /*flip sorting method asc/desc*/
   430 					sl->flags ^= SL_ORDER; //DESC-flag
   445 					sl->flags ^= SL_ORDER; //DESC-flag
   431 					station_sort.order = GB(sl->flags, 0, 1);
   446 					station_sort.order = GB(sl->flags, 0, 1);
   432 					sl->flags |= SL_RESORT;
   447 					sl->flags |= SL_RESORT;
   438 				case STATIONLIST_WIDGET_SORTCRITERIA:
   453 				case STATIONLIST_WIDGET_SORTCRITERIA:
   439 				case STATIONLIST_WIDGET_SORTDROPBTN: /* select sorting criteria dropdown menu */
   454 				case STATIONLIST_WIDGET_SORTDROPBTN: /* select sorting criteria dropdown menu */
   440 					ShowDropDownMenu(w, _station_sort_listing, sl->sort_type, STATIONLIST_WIDGET_SORTDROPBTN, 0, 0);
   455 					ShowDropDownMenu(w, _station_sort_listing, sl->sort_type, STATIONLIST_WIDGET_SORTDROPBTN, 0, 0);
   441 					break;
   456 					break;
   442 
   457 
       
   458 				case STATIONLIST_WIDGET_NOCARGOWAITING:
       
   459 					if (_ctrl_pressed) {
       
   460 						include_empty = !include_empty;
       
   461 						ToggleWidgetLoweredState(w, STATIONLIST_WIDGET_NOCARGOWAITING);
       
   462 					} else {
       
   463 						for (uint i = STATIONLIST_WIDGET_CARGOSTART; i < w->widget_count; i++) {
       
   464 							RaiseWindowWidget(w, i);
       
   465 						}
       
   466 
       
   467 						_cargo_filter = 0;
       
   468 						include_empty = true;
       
   469 
       
   470 						LowerWindowWidget(w, STATIONLIST_WIDGET_NOCARGOWAITING);
       
   471 					}
       
   472 					sl->flags |= SL_REBUILD;
       
   473 					SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
       
   474 					SetWindowDirty(w);
       
   475 					break;
       
   476 
   443 				default:
   477 				default:
   444 					if (e->we.click.widget >= STATIONLIST_WIDGET_CARGOSTART && e->we.click.widget <= STATIONLIST_WIDGET_NOCARGOWAITING) { //change cargo_filter
   478 					if (e->we.click.widget >= STATIONLIST_WIDGET_CARGOSTART) { //change cargo_filter
       
   479 						/* Determine the selected cargo type */
       
   480 						CargoID c;
       
   481 						int i = 0;
       
   482 						for (c = 0; c < NUM_CARGO; c++) {
       
   483 							if (!GetCargo(c)->IsValid()) continue;
       
   484 							if (e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART == i) break;
       
   485 							i++;
       
   486 						}
       
   487 
   445 						if (_ctrl_pressed) {
   488 						if (_ctrl_pressed) {
   446 							TOGGLEBIT(cargo_filter, e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART);
   489 							TOGGLEBIT(_cargo_filter, c);
   447 							ToggleWidgetLoweredState(w, e->we.click.widget);
   490 							ToggleWidgetLoweredState(w, e->we.click.widget);
   448 						} else {
   491 						} else {
   449 							for (uint i = 0; cargo_filter != 0; i++, cargo_filter >>= 1) {
   492 							for (uint i = STATIONLIST_WIDGET_CARGOSTART; i < w->widget_count; i++) {
   450 								if (HASBIT(cargo_filter, 0)) RaiseWindowWidget(w, i + STATIONLIST_WIDGET_CARGOSTART);
   493 								RaiseWindowWidget(w, i);
   451 							}
   494 							}
   452 							SETBIT(cargo_filter, e->we.click.widget - STATIONLIST_WIDGET_CARGOSTART);
   495 							RaiseWindowWidget(w, STATIONLIST_WIDGET_NOCARGOWAITING);
       
   496 
       
   497 							_cargo_filter = 0;
       
   498 							include_empty = false;
       
   499 
       
   500 							SETBIT(_cargo_filter, c);
   453 							LowerWindowWidget(w, e->we.click.widget);
   501 							LowerWindowWidget(w, e->we.click.widget);
   454 						}
   502 						}
   455 						sl->flags |= SL_REBUILD;
   503 						sl->flags |= SL_REBUILD;
   456 						SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_CARGOALL, cargo_filter == CARGO_ALL_SELECTED);
   504 						SetWindowWidgetLoweredState(w, STATIONLIST_WIDGET_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
   457 						SetWindowDirty(w);
   505 						SetWindowDirty(w);
   458 					}
   506 					}
   459 					break;
   507 					break;
   460 			}
   508 			}
   461 			break;
   509 			break;
   503 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    28,    41,    14,    24, STR_BUS,           STR_USE_CTRL_TO_SELECT_MORE},
   551 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    28,    41,    14,    24, STR_BUS,           STR_USE_CTRL_TO_SELECT_MORE},
   504 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    42,    55,    14,    24, STR_PLANE,         STR_USE_CTRL_TO_SELECT_MORE},
   552 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    42,    55,    14,    24, STR_PLANE,         STR_USE_CTRL_TO_SELECT_MORE},
   505 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    56,    69,    14,    24, STR_SHIP,          STR_USE_CTRL_TO_SELECT_MORE},
   553 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    56,    69,    14,    24, STR_SHIP,          STR_USE_CTRL_TO_SELECT_MORE},
   506 //Index 11
   554 //Index 11
   507 {      WWT_PANEL,   RESIZE_NONE,    14,    83,    88,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   555 {      WWT_PANEL,   RESIZE_NONE,    14,    83,    88,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   508 {      WWT_PANEL,   RESIZE_NONE,    14,    89,   102,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   556 {      WWT_PANEL,   RESIZE_NONE,    14,    89,   102,    14,    24, 0x0,               STR_NO_WAITING_CARGO},
   509 {      WWT_PANEL,   RESIZE_NONE,    14,   103,   116,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   557 {      WWT_PANEL,  RESIZE_RIGHT,    14,   117,   357,    14,    24, 0x0,               STR_NULL},
   510 {      WWT_PANEL,   RESIZE_NONE,    14,   117,   130,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   558 
   511 {      WWT_PANEL,   RESIZE_NONE,    14,   131,   144,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
   559 //14
   512 {      WWT_PANEL,   RESIZE_NONE,    14,   145,   158,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   513 {      WWT_PANEL,   RESIZE_NONE,    14,   159,   172,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   514 {      WWT_PANEL,   RESIZE_NONE,    14,   173,   186,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   515 {      WWT_PANEL,   RESIZE_NONE,    14,   187,   200,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   516 {      WWT_PANEL,   RESIZE_NONE,    14,   201,   214,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   517 {      WWT_PANEL,   RESIZE_NONE,    14,   215,   228,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   518 {      WWT_PANEL,   RESIZE_NONE,    14,   229,   242,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   519 {      WWT_PANEL,   RESIZE_NONE,    14,   243,   256,    14,    24, 0x0,               STR_USE_CTRL_TO_SELECT_MORE},
       
   520 {      WWT_PANEL,   RESIZE_NONE,    14,   257,   270,    14,    24, 0x0,               STR_NO_WAITING_CARGO},
       
   521 {      WWT_PANEL,  RESIZE_RIGHT,    14,   285,   357,    14,    24, 0x0,               STR_NULL},
       
   522 
       
   523 //26
       
   524 {      WWT_PANEL,   RESIZE_NONE,    14,    70,    83,    14,    24, 0x0,               STR_SELECT_ALL_FACILITIES},
   560 {      WWT_PANEL,   RESIZE_NONE,    14,    70,    83,    14,    24, 0x0,               STR_SELECT_ALL_FACILITIES},
   525 {      WWT_PANEL,   RESIZE_NONE,    14,   271,   284,    14,    24, 0x0,               STR_SELECT_ALL_TYPES},
   561 {      WWT_PANEL,   RESIZE_NONE,    14,   103,   116,    14,    24, 0x0,               STR_SELECT_ALL_TYPES},
   526 
   562 
   527 //28
   563 //16
   528 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     0,    80,    25,    36, STR_SORT_BY,       STR_SORT_ORDER_TIP},
   564 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     0,    80,    25,    36, STR_SORT_BY,       STR_SORT_ORDER_TIP},
   529 {      WWT_PANEL,   RESIZE_NONE,    14,    81,   232,    25,    36, 0x0,               STR_SORT_CRITERIA_TIP},
   565 {      WWT_PANEL,   RESIZE_NONE,    14,    81,   232,    25,    36, 0x0,               STR_SORT_CRITERIA_TIP},
   530 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   233,   243,    25,    36, STR_0225,          STR_SORT_CRITERIA_TIP},
   566 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   233,   243,    25,    36, STR_0225,          STR_SORT_CRITERIA_TIP},
   531 {      WWT_PANEL,  RESIZE_RIGHT,    14,   244,   357,    25,    36, 0x0,               STR_NULL},
   567 {      WWT_PANEL,  RESIZE_RIGHT,    14,   244,   357,    25,    36, 0x0,               STR_NULL},
   532 {   WIDGETS_END},
   568 {   WIDGETS_END},
   550 
   586 
   551 	w->caption_color = (byte)w->window_number;
   587 	w->caption_color = (byte)w->window_number;
   552 	w->vscroll.cap = 12;
   588 	w->vscroll.cap = 12;
   553 	w->resize.step_height = 10;
   589 	w->resize.step_height = 10;
   554 	w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
   590 	w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
       
   591 
       
   592 	/* Add cargo filter buttons */
       
   593 	uint num_active = 0;
       
   594 	for (CargoID c = 0; c < NUM_CARGO; c++) {
       
   595 		if (GetCargo(c)->IsValid()) num_active++;
       
   596 	}
       
   597 
       
   598 	w->widget_count += num_active;
       
   599 	w->widget = ReallocT(w->widget, w->widget_count + 1);
       
   600 	w->widget[w->widget_count].type = WWT_LAST;
       
   601 
       
   602 	uint i = 0;
       
   603 	for (CargoID c = 0; c < NUM_CARGO; c++) {
       
   604 		if (!GetCargo(c)->IsValid()) continue;
       
   605 
       
   606 		Widget *wi = &w->widget[STATIONLIST_WIDGET_CARGOSTART + i];
       
   607 		wi->type     = WWT_PANEL;
       
   608 		wi->display_flags = RESIZE_NONE;
       
   609 		wi->color    = 14;
       
   610 		wi->left     = 89 + i * 14;
       
   611 		wi->right    = wi->left + 13;
       
   612 		wi->top      = 14;
       
   613 		wi->bottom   = 24;
       
   614 		wi->data     = 0;
       
   615 		wi->tooltips = STR_USE_CTRL_TO_SELECT_MORE;
       
   616 
       
   617 		if (HASBIT(_cargo_filter, c)) LowerWindowWidget(w, STATIONLIST_WIDGET_CARGOSTART + i);
       
   618 		i++;
       
   619 	}
       
   620 
       
   621 	w->widget[STATIONLIST_WIDGET_NOCARGOWAITING].left += num_active * 14;
       
   622 	w->widget[STATIONLIST_WIDGET_NOCARGOWAITING].right += num_active * 14;
       
   623 	w->widget[STATIONLIST_WIDGET_CARGOALL].left += num_active * 14;
       
   624 	w->widget[STATIONLIST_WIDGET_CARGOALL].right += num_active * 14;
       
   625 	w->widget[13].left += num_active * 14;
       
   626 
       
   627 	if (num_active > 15) {
       
   628 		/* Resize and fix the minimum width, if necessary */
       
   629 		ResizeWindow(w, (num_active - 15) * 14, 0);
       
   630 		w->resize.width = w->width;
       
   631 	}
   555 }
   632 }
   556 
   633 
   557 static const Widget _station_view_expanded_widgets[] = {
   634 static const Widget _station_view_expanded_widgets[] = {
   558 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,          STR_018B_CLOSE_WINDOW},
   635 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,          STR_018B_CLOSE_WINDOW},
   559 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   236,     0,    13, STR_300A_0,        STR_018C_WINDOW_TITLE_DRAG_THIS},
   636 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   236,     0,    13, STR_300A_0,        STR_018C_WINDOW_TITLE_DRAG_THIS},
   630 		SetDParam(0, str);
   707 		SetDParam(0, str);
   631 		DrawString(x, y, STR_0008_WAITING, 0);
   708 		DrawString(x, y, STR_0008_WAITING, 0);
   632 		y += 10;
   709 		y += 10;
   633 	}
   710 	}
   634 
   711 
   635 	CargoID i = 0;
   712 	for (CargoID i = 0; i != NUM_CARGO && pos > -5; i++) {
   636 	do {
       
   637 		uint waiting = GB(st->goods[i].waiting_acceptance, 0, 12);
   713 		uint waiting = GB(st->goods[i].waiting_acceptance, 0, 12);
   638 		if (waiting == 0) continue;
   714 		if (waiting == 0) continue;
   639 
   715 
   640 		num = (waiting + 5) / 10;
   716 		num = (waiting + 5) / 10;
   641 		if (num != 0) {
   717 		if (num != 0) {
   667 				SetDParam(0, st->goods[i].enroute_from);
   743 				SetDParam(0, st->goods[i].enroute_from);
   668 				DrawStringRightAligned(x + 234, y, STR_000B, 0);
   744 				DrawStringRightAligned(x + 234, y, STR_000B, 0);
   669 				y += 10;
   745 				y += 10;
   670 			}
   746 			}
   671 		}
   747 		}
   672 	} while (pos > -5 && ++i != NUM_CARGO);
   748 	}
   673 
   749 
   674 	if (IsWindowOfPrototype(w, _station_view_widgets)) {
   750 	if (IsWindowOfPrototype(w, _station_view_widgets)) {
   675 		char *b = _userstring;
   751 		char *b = _userstring;
   676 		bool first = true;
   752 		bool first = true;
   677 
   753 
   699 	} else {
   775 	} else {
   700 		DrawString(2, 67, STR_3034_LOCAL_RATING_OF_TRANSPORT, 0);
   776 		DrawString(2, 67, STR_3034_LOCAL_RATING_OF_TRANSPORT, 0);
   701 
   777 
   702 		y = 77;
   778 		y = 77;
   703 		for (CargoID i = 0; i != NUM_CARGO; i++) {
   779 		for (CargoID i = 0; i != NUM_CARGO; i++) {
   704 			if (st->goods[i].enroute_from != INVALID_STATION) {
   780 			const CargoSpec *cs = GetCargo(i);
   705 				SetDParam(0, GetCargo(i)->name);
   781 			if (!cs->IsValid()) continue;
   706 				SetDParam(2, st->goods[i].rating * 101 >> 8);
   782 
   707 				SetDParam(1, STR_3035_APPALLING + (st->goods[i].rating >> 5));
   783 			const GoodsEntry *ge = &st->goods[i];
   708 				DrawString(8, y, STR_303D, 0);
   784 			if (ge->enroute_from == INVALID_STATION) continue;
   709 				y += 10;
   785 
   710 			}
   786 			SetDParam(0, cs->name);
       
   787 			SetDParam(2, ge->rating * 101 >> 8);
       
   788 			SetDParam(1, STR_3035_APPALLING + (ge->rating >> 5));
       
   789 			DrawString(8, y, STR_303D, 0);
       
   790 			y += 10;
   711 		}
   791 		}
   712 	}
   792 	}
   713 }
   793 }
   714 
   794 
   715 
   795 
   746 					ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w, CS_ALPHANUMERAL);
   826 					ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w, CS_ALPHANUMERAL);
   747 					break;
   827 					break;
   748 
   828 
   749 				case 10: { /* Show a list of scheduled trains to this station */
   829 				case 10: { /* Show a list of scheduled trains to this station */
   750 					const Station *st = GetStation(w->window_number);
   830 					const Station *st = GetStation(w->window_number);
   751 					ShowVehicleListWindow(st->owner, VEH_Train, (StationID)w->window_number);
   831 					ShowVehicleListWindow(st->owner, VEH_TRAIN, (StationID)w->window_number);
   752 					break;
   832 					break;
   753 				}
   833 				}
   754 
   834 
   755 				case 11: { /* Show a list of scheduled road-vehicles to this station */
   835 				case 11: { /* Show a list of scheduled road-vehicles to this station */
   756 					const Station *st = GetStation(w->window_number);
   836 					const Station *st = GetStation(w->window_number);
   757 					ShowVehicleListWindow(st->owner, VEH_Road, (StationID)w->window_number);
   837 					ShowVehicleListWindow(st->owner, VEH_ROAD, (StationID)w->window_number);
   758 					break;
   838 					break;
   759 				}
   839 				}
   760 
   840 
   761 				case 12: { /* Show a list of scheduled aircraft to this station */
   841 				case 12: { /* Show a list of scheduled aircraft to this station */
   762 					const Station *st = GetStation(w->window_number);
   842 					const Station *st = GetStation(w->window_number);
   763 					/* Since oilrigs have no owners, show the scheduled aircraft of current player */
   843 					/* Since oilrigs have no owners, show the scheduled aircraft of current player */
   764 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
   844 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
   765 					ShowVehicleListWindow(owner, VEH_Aircraft, (StationID)w->window_number);
   845 					ShowVehicleListWindow(owner, VEH_AIRCRAFT, (StationID)w->window_number);
   766 					break;
   846 					break;
   767 				}
   847 				}
   768 
   848 
   769 				case 13: { /* Show a list of scheduled ships to this station */
   849 				case 13: { /* Show a list of scheduled ships to this station */
   770 					const Station *st = GetStation(w->window_number);
   850 					const Station *st = GetStation(w->window_number);
   771 					/* Since oilrigs/bouys have no owners, show the scheduled ships of current player */
   851 					/* Since oilrigs/bouys have no owners, show the scheduled ships of current player */
   772 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
   852 					PlayerID owner = (st->owner == OWNER_NONE) ? _current_player : st->owner;
   773 					ShowVehicleListWindow(owner, VEH_Ship, (StationID)w->window_number);
   853 					ShowVehicleListWindow(owner, VEH_SHIP, (StationID)w->window_number);
   774 					break;
   854 					break;
   775 				}
   855 				}
   776 			}
   856 			}
   777 			break;
   857 			break;
   778 
   858