Merge pull request #293 from VacuumBreather/station_cargo_history

Add station cargo history
pull/295/head
Jonathan G Rennison 3 years ago committed by GitHub
commit 0f73fe765f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -90,6 +90,15 @@ struct CargoSpec {
return this - CargoSpec::array;
}
/**
* Determine CargoTypes bit of this cargospec
* @return CargoTypes bit
*/
inline CargoTypes CargoTypesBit() const
{
return static_cast<CargoTypes>(1) << this->Index();
}
/**
* Tests for validity of this cargospec
* @return is this cargospec valid?

@ -184,6 +184,7 @@ extern void CompaniesMonthlyLoop();
extern void EnginesMonthlyLoop();
extern void TownsMonthlyLoop();
extern void IndustryMonthlyLoop();
extern void StationDailyLoop();
extern void StationMonthlyLoop();
extern void SubsidyMonthlyLoop();
@ -276,6 +277,7 @@ static void OnNewDay()
DisasterDailyLoop();
IndustryDailyLoop();
StationDailyLoop();
if (!_settings_time.time_in_minutes || _settings_client.gui.date_with_time > 0) {
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);

@ -31,6 +31,7 @@
#include <math.h>
#include "safeguards.h"
#include "station_base.h"
/* Bitmasks of company and cargo indices that shouldn't be drawn. */
static CompanyMask _legend_excluded_companies;
@ -1649,3 +1650,277 @@ void InitializeGraphGui()
_legend_excluded_companies = 0;
_legend_excluded_cargo = 0;
}
/*************************/
/* STATION CARGO HISTORY */
/*************************/
struct StationCargoGraphWindow final : BaseGraphWindow {
StationID station_id;
uint line_height {}; ///< Pixel height of each cargo type row.
Scrollbar *vscroll; ///< Cargo list scrollbar.
uint legend_width {}; ///< Width of legend 'blob'.
CargoTypes legend_excluded_cargo;
CargoTypes present_cargoes;
StationCargoGraphWindow(WindowDesc *desc, WindowNumber window) :
BaseGraphWindow(desc, WID_SCG_GRAPH, STR_JUST_COMMA)
{
station_id = static_cast<uint16>(window);
this->num_on_x_axis = MAX_STATION_CARGO_HISTORY_DAYS; // Four weeks
this->num_vert_lines = MAX_STATION_CARGO_HISTORY_DAYS;
this->month = 0xFF;
this->x_values_start = 2;
this->x_values_increment = 2;
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_SCG_MATRIX_SCROLLBAR);
/* Initialise the data set */
this->FillGraphData();
this->FinishInitNested(window);
}
void OnInit() override
{
/* Width of the legend blob. */
this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5;
this->legend_excluded_cargo = 0;
}
void SetStringParameters(int widget) const override
{
if (widget == WID_SCG_CAPTION) {
SetDParam(0, this->station_id);
}
if (widget == WID_SCG_FOOTER) {
SetDParam(0, 48);
}
}
void UpdateExcludedData()
{
this->excluded_data = 0;
uint8 i = 0;
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
if (!HasBit(this->present_cargoes, cs->Index())) continue;
if (HasBit(legend_excluded_cargo, cs->Index())) SetBit(this->excluded_data, i);
i++;
}
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
{
if (widget < WID_SCG_MATRIX) {
BaseGraphWindow::UpdateWidgetSize(widget, size, padding, fill, resize);
return;
}
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
SetDParam(0, cs->name);
Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO);
d.width += this->legend_width + 4; // color field
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
*size = maxdim(d, *size);
}
this->line_height = size->height;
size->height = this->line_height * 11; /* Default number of cargo types in most climates. */
resize->width = 0;
resize->height = this->line_height;
}
void DrawWidget(const Rect &r, int widget) const override
{
if (widget < WID_SCG_MATRIX) {
BaseGraphWindow::DrawWidget(r, widget);
return;
}
const bool rtl = _current_text_dir == TD_RTL;
int x = r.left + WD_FRAMERECT_LEFT;
int y = r.top;
const uint row_height = FONT_HEIGHT_SMALL;
const int padding = ScaleFontTrad(1);
int pos = this->vscroll->GetPosition();
int max = pos + this->vscroll->GetCapacity();
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
if (!HasBit(this->present_cargoes, cs->Index())) continue;
if (pos-- > 0) continue;
if (--max < 0) break;
const bool lowered = !HasBit(legend_excluded_cargo, cs->Index());
/* Redraw box if lowered */
if (lowered) DrawFrameRect(r.left, y, r.right, y + this->line_height - 1, COLOUR_BROWN, lowered ? FR_LOWERED : FR_NONE);
const byte clk_dif = lowered ? 1 : 0;
const int rect_x = clk_dif + (rtl ? r.right - this->legend_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT);
GfxFillRect(rect_x, y + padding + clk_dif, rect_x + this->legend_width, y + row_height - 1 + clk_dif, PC_BLACK);
GfxFillRect(rect_x + 1, y + padding + 1 + clk_dif, rect_x + this->legend_width - 1, y + row_height - 2 + clk_dif, cs->legend_colour);
SetDParam(0, cs->name);
DrawString(rtl ? r.left : x + this->legend_width + 4 + clk_dif, (rtl ? r.right - this->legend_width - 4 + clk_dif : r.right), y + clk_dif, STR_GRAPH_CARGO_PAYMENT_CARGO);
y += this->line_height;
}
}
void OnClick(Point pt, int widget, int click_count) override
{
switch (widget) {
case WID_SCG_ENABLE_CARGOES:
/* Remove all cargoes from the excluded lists. */
this->legend_excluded_cargo = 0;
this->excluded_data = 0;
this->SetDirty();
break;
case WID_SCG_DISABLE_CARGOES: {
/* Add all cargoes to the excluded lists. */
this->legend_excluded_cargo = ~static_cast<CargoTypes>(0);
int i = 0;
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
if (!HasBit(this->present_cargoes, cs->Index())) continue;
SetBit(this->excluded_data, i);
i++;
}
this->SetDirty();
break;
}
case WID_SCG_MATRIX: {
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCG_MATRIX);
if (row >= this->vscroll->GetCount()) return;
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
if (!HasBit(this->present_cargoes, cs->Index())) continue;
if (row-- > 0) continue;
ToggleBit(legend_excluded_cargo, cs->Index());
this->UpdateExcludedData();
this->SetDirty();
break;
}
break;
}
}
}
void OnResize() override
{
this->vscroll->SetCapacityFromWidget(this, WID_SCG_MATRIX);
}
void OnGameTick() override
{
/* Override default OnGameTick */
}
/**
* Some data on this window has become invalid.
* @param data Information about the changed data.
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
*/
void OnInvalidateData(int data = 0, bool gui_scope = true) override
{
if (!gui_scope) return;
this->FillGraphData();
}
void FillGraphData()
{
const Station* station = Station::GetIfValid(this->station_id);
if (station == nullptr) return;
this->present_cargoes = station->station_cargo_history_cargoes;
this->vscroll->SetCount(CountBits(this->present_cargoes));
this->UpdateExcludedData();
uint8 i = 0;
const CargoSpec *cs;
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
if (!HasBit(this->present_cargoes, cs->Index())) continue;
this->colours[i] = cs->legend_colour;
const auto &history = station->station_cargo_history[CountBits(this->present_cargoes & (cs->CargoTypesBit() - 1))];
uint offset = station->station_cargo_history_offset;
for (uint j = 0; j < MAX_STATION_CARGO_HISTORY_DAYS; j++) {
this->cost[i][j] = history[offset];
offset++;
if (offset == MAX_STATION_CARGO_HISTORY_DAYS) offset = 0;
}
i++;
}
this->num_dataset = i;
this->SetDirty();
}
};
static const NWidgetPart _nested_station_cargo_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCG_CAPTION), SetDataTip(STR_GRAPH_STATION_CARGO_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
NWidget(WWT_SHADEBOX, COLOUR_GREY),
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_SCG_BACKGROUND), SetMinimalSize(568, 128),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_GREY, WID_SCG_HEADER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_STATION_CARGO_TITLE, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCG_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 0), SetResize(0, 1),
NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SCG_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SCG_DISABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_SCG_MATRIX), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_SCG_MATRIX_SCROLLBAR),
NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_SCG_MATRIX_SCROLLBAR),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1), SetResize(0, 1),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(WD_RESIZEBOX_WIDTH, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_GREY, WID_SCG_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_STATION_CARGO_X_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_SCG_RESIZE),
EndContainer(),
EndContainer(),
};
static WindowDesc _station_cargo_desc(
WDP_AUTO, "graph_station_cargo", 0, 0,
WC_STATION_CARGO, WC_NONE,
0,
_nested_station_cargo_widgets, lengthof(_nested_station_cargo_widgets)
);
void ShowStationCargo(StationID station_id)
{
AllocateWindowDescFront<StationCargoGraphWindow>(&_station_cargo_desc, station_id);
}

@ -12,6 +12,8 @@
extern uint8 _cargo_payment_x_mode;
typedef uint16 StationID;
void ShowOperatingProfitGraph();
void ShowIncomeGraph();
void ShowDeliveredCargoGraph();
@ -20,5 +22,6 @@ void ShowCompanyValueGraph();
void ShowCargoPaymentRates();
void ShowCompanyLeagueTable();
void ShowPerformanceRatingDetail();
void ShowStationCargo(StationID);
#endif /* GRAPH_GUI_H */

@ -613,6 +613,10 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Display
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Toggle graph for cargo type on/off
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
STR_GRAPH_STATION_CARGO_CAPTION :{WHITE}{STATION} - Waiting Cargo History
STR_GRAPH_STATION_CARGO_X_LABEL :{TINY_FONT}{BLACK}Development over the last {NUM} days
STR_GRAPH_STATION_CARGO_TITLE :{TINY_FONT}{BLACK}Units of cargo waiting at the station
STR_GRAPH_CARGO_DAYS_MODE :{TINY_FONT}{BLACK}Days in transit
STR_GRAPH_CARGO_SPEED_MODE :{TINY_FONT}{BLACK}Average speed
STR_GRAPH_CARGO_TOOLTIP_DAYS_MODE :{BLACK}Display days in transit on the x-axis of the graph
@ -4184,6 +4188,9 @@ STR_STATION_VIEW_GROUP_D_V_S :Destination-Via
STR_STATION_VIEW_DEPARTURES_BUTTON :{BLACK}Departures
STR_STATION_VIEW_DEPARTURES_TOOLTIP :{BLACK}Show list of scheduled departures
STR_STATION_VIEW_HISTORY_BUTTON :{BLACK}History
STR_STATION_VIEW_HISTORY_TOOLTIP :{BLACK}Show waiting cargo history
############ range for rating starts
STR_CARGO_RATING_APPALLING :Appalling
STR_CARGO_RATING_VERY_POOR :Very Poor

@ -151,6 +151,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
{ XSLFI_CUSTOM_TOWN_ZONE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "custom_town_zone", nullptr, nullptr, nullptr },
{ XSLFI_STATION_CARGO_HISTORY, XSCF_NULL, 1, 1, "station_cargo_history", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
};

@ -105,6 +105,7 @@ enum SlXvFeatureIndex {
XSLFI_WATER_FLOODING, ///< Water flooding map bit
XSLFI_MORE_HOUSES, ///< More house types
XSLFI_CUSTOM_TOWN_ZONE, ///< Custom town zones
XSLFI_STATION_CARGO_HISTORY, ///< Station waiting cargo history
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

@ -459,6 +459,7 @@ static const SaveLoad _station_desc[] = {
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES),
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
SLE_CONDNULL_X(32 * 24, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_22)),
SLE_CONDVAR_X(Station, station_cargo_history_cargoes, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATION_CARGO_HISTORY)),
SLE_END()
};
@ -547,6 +548,17 @@ static void RealSave_STNN(BaseStation *bst)
SlObjectSaveFiltered(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc); // _cargo_list_desc has no conditionals
}
}
assert(st->station_cargo_history.size() == CountBits(st->station_cargo_history_cargoes));
dumper->CheckBytes(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2);
for (const auto &history : st->station_cargo_history) {
uint i = st->station_cargo_history_offset;
do {
dumper->RawWriteUint16(history[i]);
i++;
if (i == MAX_STATION_CARGO_HISTORY_DAYS) i = 0;
} while (i != st->station_cargo_history_offset);
}
}
for (uint i = 0; i < bst->num_specs; i++) {
@ -656,6 +668,15 @@ static void Load_STNN()
}
if (SlXvIsFeatureMissing(XSLFI_ST_LAST_VEH_TYPE)) st->goods[i].last_vehicle_type = _old_last_vehicle_type;
}
st->station_cargo_history.resize(CountBits(st->station_cargo_history_cargoes));
buffer->CheckBytes(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2);
for (auto &history : st->station_cargo_history) {
for (uint16 &amount : history) {
amount = buffer->RawReadUint16();
}
}
st->station_cargo_history_offset = 0;
}
if (bst->num_specs != 0) {

@ -62,6 +62,7 @@ BaseStation::~BaseStation()
DeleteWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).Pack());
DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).Pack());
DeleteWindowById(WC_DEPARTURES_BOARD, this->index);
DeleteWindowById(WC_STATION_CARGO, this->index);
if (HasBit(_display_opt, Station::IsExpected(this) ? DO_SHOW_STATION_NAMES : DO_SHOW_WAYPOINT_NAMES) &&
!(_local_company != this->owner && this->owner != OWNER_NONE && !HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS))) {
@ -76,7 +77,9 @@ Station::Station(TileIndex tile) :
ship_station(INVALID_TILE, 0, 0),
indtype(IT_INVALID),
time_since_load(255),
time_since_unload(255)
time_since_unload(255),
station_cargo_history_cargoes(0),
station_cargo_history_offset(0)
{
/* this->random_bits is set in Station::AddFacility() */
}

@ -23,6 +23,7 @@
#include "core/endian_type.hpp"
#include <map>
#include <vector>
#include <array>
#include <iterator>
#include <functional>
#include <algorithm>
@ -808,6 +809,10 @@ public:
IndustryList industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
Industry *industry; ///< NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
CargoTypes station_cargo_history_cargoes; ///< Bitmask of cargoes in station_cargo_history
uint8 station_cargo_history_offset; ///< Start offset in station_cargo_history cargo ring buffer
std::vector<std::array<uint16, MAX_STATION_CARGO_HISTORY_DAYS>> station_cargo_history; ///< Station history of waiting cargo.
Station(TileIndex tile = INVALID_TILE);
~Station();
@ -817,6 +822,8 @@ public:
void UpdateVirtCoord() override;
void UpdateCargoHistory();
void MoveSign(TileIndex new_xy) override;
void AfterStationTileSetChange(bool adding, StationType type);

@ -404,6 +404,33 @@ void Station::GetTileArea(TileArea *ta, StationType type) const
}
}
/**
* Update the cargo history.
*/
void Station::UpdateCargoHistory()
{
uint storage_offset = 0;
bool update_window = false;
for (const CargoSpec *cs : CargoSpec::Iterate()) {
uint amount = this->goods[cs->Index()].cargo.TotalCount();
if (!HasBit(this->station_cargo_history_cargoes, cs->Index())) {
if (amount == 0) {
/* No cargo present, and no history stored for this cargo, no work to do */
continue;
} else {
if (this->station_cargo_history_cargoes == 0) update_window = true;
SetBit(this->station_cargo_history_cargoes, cs->Index());
this->station_cargo_history.emplace(this->station_cargo_history.begin() + storage_offset);
}
}
this->station_cargo_history[storage_offset][this->station_cargo_history_offset] = static_cast<uint16>(std::clamp<uint>(amount, (uint)0, (uint)UINT16_MAX));
storage_offset++;
}
this->station_cargo_history_offset++;
if (this->station_cargo_history_offset == MAX_STATION_CARGO_HISTORY_DAYS) this->station_cargo_history_offset = 0;
if (update_window) InvalidateWindowData(WC_STATION_VIEW, this->index, -1);
}
/**
* Update the virtual coords needed to draw the station sign.
*/
@ -3771,7 +3798,7 @@ bool GetNewGrfRating(const Station *st, const CargoSpec *cs, const GoodsEntry *g
{
*new_grf_rating = 0;
bool is_using_newgrf_rating = false;
/* Perform custom station rating. If it succeeds the speed, days in transit and
* waiting cargo ratings must not be executed. */
@ -3805,7 +3832,7 @@ int GetSpeedRating(const GoodsEntry *ge)
int GetWaitTimeRating(const CargoSpec *cs, const GoodsEntry *ge)
{
int rating = 0;
uint wait_time = ge->time_since_pickup;
if (_settings_game.station.cargo_class_rating_wait_time) {
@ -3878,7 +3905,7 @@ int GetTargetRating(const Station *st, const CargoSpec *cs, const GoodsEntry *ge
} else if (HasBit(cs->callback_mask, CBM_CARGO_STATION_RATING_CALC)) {
int new_grf_rating;
if (GetNewGrfRating(st, cs, ge, &new_grf_rating)) {
skip = true;
rating += new_grf_rating;
@ -4240,6 +4267,18 @@ void OnTick_Station()
}
}
/** Daily loop for stations. */
void StationDailyLoop()
{
// Only record cargo history every second day.
if (_date % 2 != 0) {
for (Station *st : Station::Iterate()) {
st->UpdateCargoHistory();
}
InvalidateWindowClassesData(WC_STATION_CARGO);
}
}
/** Monthly loop for stations. */
void StationMonthlyLoop()
{

@ -32,6 +32,7 @@
#include "linkgraph/linkgraph.h"
#include "zoom_func.h"
#include "departures_gui.h"
#include "graph_gui.h"
#include "zoning.h"
#include "newgrf_debug.h"
@ -831,6 +832,8 @@ static const NWidgetPart _nested_station_view_widgets[] = {
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_ACCEPTS_RATINGS), SetMinimalSize(46, 12), SetResize(1, 0), SetFill(1, 1),
SetDataTip(STR_STATION_VIEW_RATINGS_BUTTON, STR_STATION_VIEW_RATINGS_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_HISTORY), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1),
SetDataTip(STR_STATION_VIEW_HISTORY_BUTTON, STR_STATION_VIEW_HISTORY_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_DEPARTURES), SetMinimalSize(46, 12), SetResize(1, 0), SetFill(1, 1),
SetDataTip(STR_STATION_VIEW_DEPARTURES_BUTTON, STR_STATION_VIEW_DEPARTURES_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SV_CLOSE_AIRPORT), SetMinimalSize(45, 12), SetResize(1, 0), SetFill(1, 1),
@ -1363,6 +1366,12 @@ struct StationViewWindow : public Window {
SetViewportCatchmentStation(Station::Get(this->window_number), false);
}
void OnInit() override
{
const Station *st = Station::Get(this->window_number);
SetWidgetDisabledState(WID_SV_HISTORY, st->station_cargo_history_cargoes == 0);
}
/**
* Show a certain cargo entry characterized by source/next/dest station, cargo ID and amount of cargo at the
* right place in the cargo view. I.e. update as many rows as are expanded following that characterization.
@ -2052,6 +2061,11 @@ struct StationViewWindow : public Window {
break;
}
case WID_SV_HISTORY: {
ShowStationCargo((StationID)this->window_number);
break;
}
case WID_SV_DEPARTURES: {
ShowStationDepartures((StationID)this->window_number);
break;

@ -27,6 +27,8 @@ struct Waypoint;
static const StationID NEW_STATION = 0xFFFE;
static const StationID INVALID_STATION = 0xFFFF;
static const uint MAX_STATION_CARGO_HISTORY_DAYS = 24;
typedef SmallStack<StationID, StationID, INVALID_STATION, 8, 0xFFFD> StationIDStack;
/** Station types */

@ -53,6 +53,20 @@ enum CargoPaymentRatesWidgets {
WID_CPR_SPEED, ///< Speed mode.
};
/** Widget of the #StationCargoGraphWindow class. */
enum StationCargoWidgets {
WID_SCG_CAPTION, ///< Window title
WID_SCG_BACKGROUND, ///< Background of the window.
WID_SCG_HEADER, ///< Header.
WID_SCG_GRAPH, ///< Graph itself.
WID_SCG_RESIZE, ///< Resize button.
WID_SCG_FOOTER, ///< Footer.
WID_SCG_ENABLE_CARGOES, ///< Enable cargoes button.
WID_SCG_DISABLE_CARGOES, ///< Disable cargoes button.
WID_SCG_MATRIX, ///< Cargo list.
WID_SCG_MATRIX_SCROLLBAR, ///< Cargo list scrollbar.
};
/** Widget of the #CompanyLeagueWindow class. */
enum CompanyLeagueWidgets {
WID_CL_BACKGROUND, ///< Background of the window.

@ -30,6 +30,7 @@ enum StationViewWidgets {
WID_SV_PLANES, ///< List of scheduled planes button.
WID_SV_CATCHMENT, ///< Toggle catchment area highlight.
WID_SV_DEPARTURES, ///< Departures button.
WID_SV_HISTORY, ///< Cargo history button.
};
/** Widgets of the #CompanyStationsWindow class. */

@ -581,6 +581,12 @@ enum WindowClass {
*/
WC_PAYMENT_RATES,
/**
* Station cargo graph; %Window numbers:
* - #StationID = #StationCargoWidgets
*/
WC_STATION_CARGO,
/**
* Performance detail window; %Window numbers:
* - 0 = #PerformanceRatingDetailsWidgets

Loading…
Cancel
Save