mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-09 15:41:15 +00:00
Add: Ability to show and filter different datasets on the same graph.
This commit is contained in:
parent
598fdf04a4
commit
22035a4f2a
@ -185,6 +185,7 @@ protected:
|
|||||||
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
||||||
|
|
||||||
uint64_t excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
|
uint64_t excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
|
||||||
|
uint64_t excluded_range; ///< bitmask of ranges that should not be displayed.
|
||||||
uint8_t num_on_x_axis;
|
uint8_t num_on_x_axis;
|
||||||
uint8_t num_vert_lines;
|
uint8_t num_vert_lines;
|
||||||
|
|
||||||
@ -206,9 +207,13 @@ protected:
|
|||||||
std::array<OverflowSafeInt64, GRAPH_NUM_MONTHS> values;
|
std::array<OverflowSafeInt64, GRAPH_NUM_MONTHS> values;
|
||||||
uint8_t colour;
|
uint8_t colour;
|
||||||
uint8_t exclude_bit;
|
uint8_t exclude_bit;
|
||||||
|
uint8_t range_bit;
|
||||||
|
uint8_t dash;
|
||||||
};
|
};
|
||||||
std::vector<DataSet> data;
|
std::vector<DataSet> data;
|
||||||
|
|
||||||
|
std::span<const StringID> ranges = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get appropriate part of dataset values for the current number of horizontal points.
|
* Get appropriate part of dataset values for the current number of horizontal points.
|
||||||
* @param dataset Dataset to get values of
|
* @param dataset Dataset to get values of
|
||||||
@ -235,6 +240,7 @@ protected:
|
|||||||
|
|
||||||
for (const DataSet &dataset : this->data) {
|
for (const DataSet &dataset : this->data) {
|
||||||
if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
|
if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
|
||||||
|
if (HasBit(this->excluded_range, dataset.range_bit)) continue;
|
||||||
|
|
||||||
for (const OverflowSafeInt64 &datapoint : this->GetDataSetRange(dataset)) {
|
for (const OverflowSafeInt64 &datapoint : this->GetDataSetRange(dataset)) {
|
||||||
if (datapoint != INVALID_DATAPOINT) {
|
if (datapoint != INVALID_DATAPOINT) {
|
||||||
@ -457,6 +463,7 @@ protected:
|
|||||||
|
|
||||||
for (const DataSet &dataset : this->data) {
|
for (const DataSet &dataset : this->data) {
|
||||||
if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
|
if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
|
||||||
|
if (HasBit(this->excluded_range, dataset.range_bit)) continue;
|
||||||
|
|
||||||
/* Centre the dot between the grid lines. */
|
/* Centre the dot between the grid lines. */
|
||||||
x = r.left + (x_sep / 2);
|
x = r.left + (x_sep / 2);
|
||||||
@ -464,6 +471,7 @@ protected:
|
|||||||
uint prev_x = INVALID_DATAPOINT_POS;
|
uint prev_x = INVALID_DATAPOINT_POS;
|
||||||
uint prev_y = INVALID_DATAPOINT_POS;
|
uint prev_y = INVALID_DATAPOINT_POS;
|
||||||
|
|
||||||
|
const uint dash = ScaleGUITrad(dataset.dash);
|
||||||
for (OverflowSafeInt64 datapoint : this->GetDataSetRange(dataset)) {
|
for (OverflowSafeInt64 datapoint : this->GetDataSetRange(dataset)) {
|
||||||
if (datapoint != INVALID_DATAPOINT) {
|
if (datapoint != INVALID_DATAPOINT) {
|
||||||
/*
|
/*
|
||||||
@ -492,7 +500,7 @@ protected:
|
|||||||
GfxFillRect(x - pointoffs1, y - pointoffs1, x + pointoffs2, y + pointoffs2, dataset.colour);
|
GfxFillRect(x - pointoffs1, y - pointoffs1, x + pointoffs2, y + pointoffs2, dataset.colour);
|
||||||
|
|
||||||
/* Draw the line connected to the previous point. */
|
/* Draw the line connected to the previous point. */
|
||||||
if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, dataset.colour, linewidth);
|
if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, dataset.colour, linewidth, dash);
|
||||||
|
|
||||||
prev_x = x;
|
prev_x = x;
|
||||||
prev_y = y;
|
prev_y = y;
|
||||||
@ -533,8 +541,24 @@ protected:
|
|||||||
public:
|
public:
|
||||||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
||||||
{
|
{
|
||||||
if (widget != WID_GRAPH_GRAPH) return;
|
switch (widget) {
|
||||||
|
case WID_GRAPH_RANGE_MATRIX:
|
||||||
|
for (const StringID &str : this->ranges) {
|
||||||
|
size = maxdim(size, GetStringBoundingBox(str, FS_SMALL));
|
||||||
|
}
|
||||||
|
|
||||||
|
size.width += WidgetDimensions::scaled.framerect.Horizontal();
|
||||||
|
size.height += WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
|
||||||
|
/* Set fixed height for number of ranges. */
|
||||||
|
size.height *= static_cast<uint>(std::size(this->ranges));
|
||||||
|
|
||||||
|
resize.width = 0;
|
||||||
|
resize.height = 0;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GRAPH_RANGE_MATRIX)->SetDataTip((1 << MAT_COL_START) | (static_cast<uint16_t>(std::size(this->ranges)) << MAT_ROW_START), 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GRAPH_GRAPH: {
|
||||||
uint x_label_width = 0;
|
uint x_label_width = 0;
|
||||||
|
|
||||||
/* Draw x-axis labels and markings for graphs based on financial quarters and years. */
|
/* Draw x-axis labels and markings for graphs based on financial quarters and years. */
|
||||||
@ -565,13 +589,41 @@ public:
|
|||||||
size.width = std::max<uint>(size.width, ScaleGUITrad(5) + y_label_width + this->num_vert_lines * (x_label_width + ScaleGUITrad(5)) + ScaleGUITrad(9));
|
size.width = std::max<uint>(size.width, ScaleGUITrad(5) + y_label_width + this->num_vert_lines * (x_label_width + ScaleGUITrad(5)) + ScaleGUITrad(9));
|
||||||
size.height = std::max<uint>(size.height, ScaleGUITrad(5) + (1 + MIN_GRAPH_NUM_LINES_Y * 2 + (this->draw_dates ? 3 : 1)) * GetCharacterHeight(FS_SMALL) + ScaleGUITrad(4));
|
size.height = std::max<uint>(size.height, ScaleGUITrad(5) + (1 + MIN_GRAPH_NUM_LINES_Y * 2 + (this->draw_dates ? 3 : 1)) * GetCharacterHeight(FS_SMALL) + ScaleGUITrad(4));
|
||||||
size.height = std::max<uint>(size.height, size.width / 3);
|
size.height = std::max<uint>(size.height, size.width / 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
void DrawWidget(const Rect &r, WidgetID widget) const override
|
||||||
{
|
{
|
||||||
if (widget != WID_GRAPH_GRAPH) return;
|
switch (widget) {
|
||||||
|
case WID_GRAPH_GRAPH:
|
||||||
|
this->DrawGraph(r);
|
||||||
|
break;
|
||||||
|
|
||||||
DrawGraph(r);
|
case WID_GRAPH_RANGE_MATRIX: {
|
||||||
|
uint line_height = GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
uint index = 0;
|
||||||
|
Rect line = r.WithHeight(line_height);
|
||||||
|
for (const auto &str : this->ranges) {
|
||||||
|
bool lowered = !HasBit(this->excluded_range, index);
|
||||||
|
|
||||||
|
/* Redraw frame if lowered */
|
||||||
|
if (lowered) DrawFrameRect(line, COLOUR_BROWN, FR_LOWERED);
|
||||||
|
|
||||||
|
const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
DrawString(text, str, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||||
|
|
||||||
|
line = line.Translate(0, line_height);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual OverflowSafeInt64 GetGraphData(const Company *, int)
|
virtual OverflowSafeInt64 GetGraphData(const Company *, int)
|
||||||
@ -582,7 +634,21 @@ public:
|
|||||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||||
{
|
{
|
||||||
/* Clicked on legend? */
|
/* Clicked on legend? */
|
||||||
if (widget == WID_GRAPH_KEY_BUTTON) ShowGraphLegend();
|
switch (widget) {
|
||||||
|
case WID_GRAPH_KEY_BUTTON:
|
||||||
|
ShowGraphLegend();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GRAPH_RANGE_MATRIX: {
|
||||||
|
int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
|
||||||
|
|
||||||
|
ToggleBit(this->excluded_range, row);
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnGameTick() override
|
void OnGameTick() override
|
||||||
@ -1094,6 +1160,10 @@ struct PaymentRatesGraphWindow : BaseGraphWindow {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
this->BaseGraphWindow::OnClick(pt, widget, click_count);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1591,6 +1661,10 @@ struct IndustryProductionGraphWindow : BaseGraphWindow {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
this->BaseGraphWindow::OnClick(pt, widget, click_count);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1659,6 +1733,8 @@ static constexpr NWidgetPart _nested_industry_production_widgets[] = {
|
|||||||
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
|
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
|
||||||
NWidget(NWID_VERTICAL),
|
NWidget(NWID_VERTICAL),
|
||||||
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_RANGE_MATRIX), SetFill(1, 0), SetResize(0, 0), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_DISABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_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_SPACER), SetMinimalSize(0, 4),
|
||||||
|
@ -36,6 +36,8 @@ enum GraphWidgets : WidgetID {
|
|||||||
WID_GRAPH_MATRIX, ///< Cargo list.
|
WID_GRAPH_MATRIX, ///< Cargo list.
|
||||||
WID_GRAPH_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
WID_GRAPH_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
||||||
|
|
||||||
|
WID_GRAPH_RANGE_MATRIX, ///< Range list.
|
||||||
|
|
||||||
WID_PHG_DETAILED_PERFORMANCE, ///< Detailed performance.
|
WID_PHG_DETAILED_PERFORMANCE, ///< Detailed performance.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user