diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 5bf80d43d1..1d2502a7ee 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -495,6 +495,12 @@ protected: this->InitNested(number); } + void UpdateCargoExcludingGraphs() { + this->SetDirty(); + InvalidateWindowData(WC_DELIVERED_CARGO, 0); + InvalidateWindowData(WC_PAYMENT_RATES, 0); + } + public: void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { @@ -724,16 +730,150 @@ void ShowIncomeGraph() /* DELIVERED CARGO */ /*******************/ -struct DeliveredCargoGraphWindow : BaseGraphWindow { - DeliveredCargoGraphWindow(WindowDesc *desc, WindowNumber window_number) : - BaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_COMMA) +struct ExcludingCargoBaseGraphWindow : BaseGraphWindow { + uint line_height; ///< Pixel height of each cargo type row. + uint icon_size; ///< Size of the cargo color icon. + Scrollbar *vscroll; ///< Cargo list scrollbar. + uint legend_width; ///< Width of legend 'blob'. + + ExcludingCargoBaseGraphWindow(WindowDesc *desc, int widget, StringID format_str_y_axis): + BaseGraphWindow(desc, widget, format_str_y_axis) + {} + + void OnInit() override { - this->InitializeWindow(window_number); + /* Width of the legend blob. */ + this->legend_width = (FONT_HEIGHT_SMALL - ScaleGUITrad(1)) * 8 / 5; + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + if (widget != WID_ECBG_MATRIX) { + BaseGraphWindow::UpdateWidgetSize(widget, size, padding, fill, resize); + return; + } + + for (const CargoSpec *cs : _sorted_standard_cargo_specs) { + SetDParam(0, cs->name); + Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO); + d.width += this->legend_width + WidgetDimensions::scaled.hsep_normal; // colour field + d.width += WidgetDimensions::scaled.framerect.Horizontal(); + d.height += WidgetDimensions::scaled.framerect.Vertical(); + *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; + } + + virtual void DrawWidget(const Rect &r, int widget) const + { + if (widget != WID_ECBG_MATRIX) { + BaseGraphWindow::DrawWidget(r, widget); + return; + } + + bool rtl = _current_text_dir == TD_RTL; + + int pos = this->vscroll->GetPosition(); + int max = pos + this->vscroll->GetCapacity(); + + Rect line = r.WithHeight(this->line_height); + for (const CargoSpec *cs : _sorted_standard_cargo_specs) { + if (pos-- > 0) continue; + if (--max < 0) break; + + bool lowered = !HasBit(_legend_excluded_cargo, cs->Index()); + + /* Redraw frame if lowered */ + if (lowered) DrawFrameRect(line, COLOUR_BROWN, FR_LOWERED); + + const Rect text = line.Shrink(WidgetDimensions::scaled.framerect).Translate(lowered ? WidgetDimensions::scaled.pressed : 0, lowered ? WidgetDimensions::scaled.pressed : 0); + + /* Cargo-colour box with outline */ + const Rect cargo = text.WithWidth(this->legend_width, rtl); + GfxFillRect(cargo, PC_BLACK); + GfxFillRect(cargo.Shrink(WidgetDimensions::scaled.bevel), cs->legend_colour); + + /* Cargo name */ + SetDParam(0, cs->name); + DrawString(text.Indent(this->legend_width + WidgetDimensions::scaled.hsep_normal, rtl), STR_GRAPH_CARGO_PAYMENT_CARGO); + + line = line.Translate(0, this->line_height); + } + } + + virtual void OnClick(Point pt, int widget, int click_count) + { + switch (widget) { + case WID_CV_KEY_BUTTON: + ShowGraphLegend(); + break; + + case WID_ECBG_ENABLE_CARGOES: + /* Remove all cargoes from the excluded lists. */ + _legend_excluded_cargo = 0; + this->UpdateCargoExcludingGraphs(); + break; + + case WID_ECBG_DISABLE_CARGOES: { + /* Add all cargoes to the excluded lists. */ + int i = 0; + for (const CargoSpec *cs : _sorted_standard_cargo_specs) { + SetBit(_legend_excluded_cargo, cs->Index()); + i++; + } + this->UpdateCargoExcludingGraphs(); + break; + } + + case WID_ECBG_MATRIX: { + uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_ECBG_MATRIX); + if (row >= this->vscroll->GetCount()) return; + + for (const CargoSpec *cs : _sorted_standard_cargo_specs) { + if (row-- > 0) continue; + + ToggleBit(_legend_excluded_cargo, cs->Index()); + this->UpdateCargoExcludingGraphs(); + break; + } + break; + } + } + } + + virtual void OnResize() + { + this->vscroll->SetCapacityFromWidget(this, WID_ECBG_MATRIX); + } +}; + +struct DeliveredCargoGraphWindow : ExcludingCargoBaseGraphWindow { + DeliveredCargoGraphWindow(WindowDesc *desc, WindowNumber window_number) : + ExcludingCargoBaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_COMMA) + { + this->CreateNestedTree(); + this->vscroll = this->GetScrollbar(WID_ECBG_MATRIX_SCROLLBAR); + this->vscroll->SetCount(_sorted_standard_cargo_specs.size()); + this->UpdateStatistics(true); + this->FinishInitNested(window_number); } OverflowSafeInt64 GetGraphData(const Company *c, int j) override { - return c->old_economy[j].delivered_cargo.GetSum(); + if (_legend_excluded_cargo == 0) { + return c->old_economy[j].delivered_cargo.GetSum(); + } + OverflowSafeInt64 total_delivered = 0; + for (const CargoSpec *cs : _sorted_standard_cargo_specs) { + if (!HasBit(_legend_excluded_cargo, cs->Index())){ + total_delivered += c->old_economy[j].delivered_cargo[cs->Index()]; + } + } + return total_delivered; } }; @@ -750,8 +890,19 @@ static const NWidgetPart _nested_delivered_cargo_graph_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_EMPTY, COLOUR_BROWN, WID_CV_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), - NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), - NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), + NWidget(NWID_SPACER), SetMinimalSize(0, 4), SetFill(0, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_ECBG_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_ECBG_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_ECBG_MATRIX), SetFill(0, 2), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_ECBG_MATRIX_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_ECBG_MATRIX_SCROLLBAR), + EndContainer(), + NWidget(NWID_SPACER), SetMinimalSize(0, 4), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0), + NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), + EndContainer(), EndContainer(), EndContainer(), EndContainer(), @@ -1006,7 +1157,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { /* Remove all cargoes from the excluded lists. */ _legend_excluded_cargo = 0; this->excluded_data = 0; - this->SetDirty(); + this->UpdateCargoExcludingGraphs(); break; case WID_CPR_DISABLE_CARGOES: { @@ -1017,7 +1168,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { SetBit(this->excluded_data, i); i++; } - this->SetDirty(); + this->UpdateCargoExcludingGraphs(); break; } @@ -1030,7 +1181,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { ToggleBit(_legend_excluded_cargo, cs->Index()); this->UpdateExcludedData(); - this->SetDirty(); + this->UpdateCargoExcludingGraphs(); break; } break; diff --git a/src/widgets/graph_widget.h b/src/widgets/graph_widget.h index 93c5566b0d..9a23170750 100644 --- a/src/widgets/graph_widget.h +++ b/src/widgets/graph_widget.h @@ -76,4 +76,14 @@ enum PerformanceRatingDetailsWidgets { WID_PRD_COMPANY_LAST = WID_PRD_COMPANY_FIRST + MAX_COMPANIES - 1, ///< Last company. }; +/** Widget of the #ExcludingCargoBaseGraphWindow class. */ +enum ExcludingCargoBaseGraphWindowWidgets { + WID_ECBG_FOOTER = 0x80, ///< Footer. + WID_ECBG_ENABLE_CARGOES, ///< Enable cargoes button. + WID_ECBG_DISABLE_CARGOES, ///< Disable cargoes button. + WID_ECBG_MATRIX, ///< Cargo list. + WID_ECBG_MATRIX_SCROLLBAR,///< Cargo list scrollbar. + WID_ECBG_CARGO_FIRST, ///< First cargo in the list. +}; + #endif /* WIDGETS_GRAPH_WIDGET_H */