29 #include "table/strings.h" 
   36 static uint _legend_excluded_companies;
 
   37 static uint _legend_excluded_cargo;
 
   41 static const uint INVALID_DATAPOINT_POS = UINT_MAX;  
 
   70     DrawCompanyIcon(cid, rtl ? r.right - d.width - 2 : r.left + 2, r.top + (r.bottom - r.top - d.height) / 2);
 
   98     if (!gui_scope) 
return;
 
  101     SetBit(_legend_excluded_companies, data);
 
  121     panel->
SetDataTip(0x0, STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP);
 
  128 static const NWidgetPart _nested_graph_legend_widgets[] = {
 
  149   _nested_graph_legend_widgets, 
lengthof(_nested_graph_legend_widgets)
 
  152 static void ShowGraphLegend()
 
  154   AllocateWindowDescFront<GraphLegendWindow>(&_graph_legend_desc, 0);
 
  169   static const int GRAPH_MAX_DATASETS     =  32;
 
  170   static const int GRAPH_AXIS_LINE_COLOUR = 
PC_BLACK;
 
  189   uint16 x_values_start;
 
  190   uint16 x_values_increment;
 
  194   byte colours[GRAPH_MAX_DATASETS];
 
  205     assert(num_hori_lines > 0);
 
  208     current_interval.
highest = INT64_MIN;
 
  209     current_interval.
lowest  = INT64_MAX;
 
  211     for (
int i = 0; i < this->num_dataset; i++) {
 
  213       for (
int j = 0; j < this->num_on_x_axis; j++) {
 
  216         if (datapoint != INVALID_DATAPOINT) {
 
  225     current_interval.
lowest =  (11 * current_interval.
lowest) / 10;
 
  228     double abs_lower  = (current_interval.
lowest > 0) ? 0 : (
double)
abs(current_interval.
lowest);
 
  229     double abs_higher = (current_interval.
highest < 0) ? 0 : (
double)current_interval.
highest;
 
  234     if (abs_lower != 0 || abs_higher != 0) {
 
  236       num_pos_grids = (int)floor(0.5 + num_hori_lines * abs_higher / (abs_higher + abs_lower));
 
  239       if (num_pos_grids == 0 && abs_higher != 0) num_pos_grids++;
 
  240       if (num_pos_grids == num_hori_lines && abs_lower != 0) num_pos_grids--;
 
  243       int64 grid_size_higher = (abs_higher > 0) ? ((int64)abs_higher + num_pos_grids - 1) / num_pos_grids : 0;
 
  244       int64 grid_size_lower = (abs_lower > 0) ? ((int64)abs_lower + num_hori_lines - num_pos_grids - 1) / (num_hori_lines - num_pos_grids) : 0;
 
  245       grid_size = 
max(grid_size_higher, grid_size_lower);
 
  248       num_pos_grids = num_hori_lines / 2;
 
  252     current_interval.
highest = num_pos_grids * grid_size;
 
  253     current_interval.
lowest = -(num_hori_lines - num_pos_grids) * grid_size;
 
  254     return current_interval;
 
  265     int64 y_label = current_interval.
highest;
 
  266     int64 y_label_separation = (current_interval.
highest - current_interval.
lowest) / num_hori_lines;
 
  270     for (
int i = 0; i < (num_hori_lines + 1); i++) {
 
  274       if (d.width > max_width) max_width = d.width;
 
  276       y_label -= y_label_separation;
 
  295     assert(this->num_vert_lines > 0);
 
  310     if (resize > 0) num_hori_lines += 
resize;
 
  316     r.left += label_width;
 
  318     int x_sep = (r.right - r.left) / this->num_vert_lines;
 
  319     int y_sep = (r.bottom - r.top) / num_hori_lines;
 
  323     r.right = r.left + x_sep * this->num_vert_lines;
 
  324     r.bottom = r.top + y_sep * num_hori_lines;
 
  328     x_axis_offset = (int)((r.bottom - r.top) * (double)interval.
highest / (
double)interval_size);
 
  335     for (
int i = 0; i < this->num_vert_lines; i++) {
 
  343     for (
int i = 0; i < (num_hori_lines + 1); i++) {
 
  344       GfxFillRect(r.left - 3, y, r.left - 1, y, GRAPH_AXIS_LINE_COLOUR);
 
  350     GfxFillRect(r.left, r.top, r.left, r.bottom, GRAPH_AXIS_LINE_COLOUR);
 
  353     y = x_axis_offset + r.top;
 
  354     GfxFillRect(r.left, y, r.right, y, GRAPH_AXIS_LINE_COLOUR);
 
  357     if (this->num_on_x_axis == 0) 
return;
 
  359     assert(this->num_on_x_axis > 0);
 
  360     assert(this->num_dataset > 0);
 
  363     int64 y_label = interval.
highest;
 
  364     int64 y_label_separation = 
abs(interval.
highest - interval.
lowest) / num_hori_lines;
 
  368     for (
int i = 0; i < (num_hori_lines + 1); i++) {
 
  373       y_label -= y_label_separation;
 
  378     if (this->month != 0xFF) {
 
  381       byte month = this->month;
 
  382       Year year  = this->year;
 
  383       for (
int i = 0; i < this->num_on_x_axis; i++) {
 
  384         SetDParam(0, month + STR_MONTH_ABBREV_JAN);
 
  385         SetDParam(1, month + STR_MONTH_ABBREV_JAN + 2);
 
  400       uint16 label = this->x_values_start;
 
  402       for (
int i = 0; i < this->num_on_x_axis; i++) {
 
  406         label += this->x_values_increment;
 
  413     uint pointoffs1 = (linewidth + 1) / 2;
 
  414     uint pointoffs2 = linewidth + 1 - pointoffs1;
 
  415     for (
int i = 0; i < this->num_dataset; i++) {
 
  418         x = r.left + (x_sep / 2);
 
  420         byte colour  = this->colours[i];
 
  421         uint prev_x = INVALID_DATAPOINT_POS;
 
  422         uint prev_y = INVALID_DATAPOINT_POS;
 
  424         for (
int j = 0; j < this->num_on_x_axis; j++) {
 
  427           if (datapoint != INVALID_DATAPOINT) {
 
  440             int reduce_range = 
max(mult_range - 31, 0);
 
  444               datapoint = -(
abs(datapoint) >> reduce_range);
 
  446               datapoint >>= reduce_range;
 
  448             y = r.top + x_axis_offset - ((r.bottom - r.top) * datapoint) / (interval_size >> reduce_range);
 
  451             GfxFillRect(x - pointoffs1, y - pointoffs1, x + pointoffs2, y + pointoffs2, colour);
 
  454             if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, colour, linewidth);
 
  459             prev_x = INVALID_DATAPOINT_POS;
 
  460             prev_y = INVALID_DATAPOINT_POS;
 
  472       format_str_y_axis(format_str_y_axis)
 
  475     this->num_vert_lines = 24;
 
  476     this->graph_widget = widget;
 
  490     if (widget != this->graph_widget) 
return;
 
  492     uint x_label_width = 0;
 
  494     if (this->month != 0xFF) {
 
  495       byte month = this->month;
 
  496       Year year  = this->year;
 
  497       for (
int i = 0; i < this->num_on_x_axis; i++) {
 
  498         SetDParam(0, month + STR_MONTH_ABBREV_JAN);
 
  499         SetDParam(1, month + STR_MONTH_ABBREV_JAN + 2);
 
  519     size->width  = max<uint>(size->width,  5 + y_label_width + this->num_on_x_axis * (x_label_width + 5) + 9);
 
  521     size->height = max<uint>(size->height, size->width / 3);
 
  526     if (widget != this->graph_widget) 
return;
 
  533     return INVALID_DATAPOINT;
 
  554     if (!gui_scope) 
return;
 
  564     uint excluded_companies = _legend_excluded_companies;
 
  573     FOR_ALL_COMPANIES(c) {
 
  584     if (!initialize && this->
excluded_data == excluded_companies && this->num_on_x_axis == nums &&
 
  585         this->year == yr && this->month == mo) {
 
  591     this->num_on_x_axis = nums;
 
  600         for (
int j = this->num_on_x_axis, i = 0; --j >= 0;) {
 
  608     this->num_dataset = numd;
 
  621     this->InitializeWindow(window_number);
 
  630 static const NWidgetPart _nested_operating_profit_widgets[] = {
 
  651   WDP_AUTO, 
"graph_operating_profit", 0, 0,
 
  654   _nested_operating_profit_widgets, 
lengthof(_nested_operating_profit_widgets)
 
  658 void ShowOperatingProfitGraph()
 
  660   AllocateWindowDescFront<OperatingProfitGraphWindow>(&_operating_profit_desc, 0);
 
  672     this->InitializeWindow(window_number);
 
  681 static const NWidgetPart _nested_income_graph_widgets[] = {
 
  705   _nested_income_graph_widgets, 
lengthof(_nested_income_graph_widgets)
 
  708 void ShowIncomeGraph()
 
  710   AllocateWindowDescFront<IncomeGraphWindow>(&_income_graph_desc, 0);
 
  721     this->InitializeWindow(window_number);
 
  730 static const NWidgetPart _nested_delivered_cargo_graph_widgets[] = {
 
  750 static WindowDesc _delivered_cargo_graph_desc(
 
  751   WDP_AUTO, 
"graph_delivered_cargo", 0, 0,
 
  754   _nested_delivered_cargo_graph_widgets, 
lengthof(_nested_delivered_cargo_graph_widgets)
 
  757 void ShowDeliveredCargoGraph()
 
  759   AllocateWindowDescFront<DeliveredCargoGraphWindow>(&_delivered_cargo_graph_desc, 0);
 
  770     this->InitializeWindow(window_number);
 
  785 static const NWidgetPart _nested_performance_history_widgets[] = {
 
  807   WDP_AUTO, 
"graph_performance", 0, 0,
 
  810   _nested_performance_history_widgets, 
lengthof(_nested_performance_history_widgets)
 
  813 void ShowPerformanceHistoryGraph()
 
  815   AllocateWindowDescFront<PerformanceHistoryGraphWindow>(&_performance_history_desc, 0);
 
  826     this->InitializeWindow(window_number);
 
  835 static const NWidgetPart _nested_company_value_graph_widgets[] = {
 
  856   WDP_AUTO, 
"graph_company_value", 0, 0,
 
  859   _nested_company_value_graph_widgets, 
lengthof(_nested_company_value_graph_widgets)
 
  862 void ShowCompanyValueGraph()
 
  864   AllocateWindowDescFront<CompanyValueGraphWindow>(&_company_value_graph_desc, 0);
 
  877     this->num_on_x_axis = 20;
 
  878     this->num_vert_lines = 20;
 
  880     this->x_values_start     = 10;
 
  881     this->x_values_increment = 10;
 
  888     this->UpdateLoweredWidgets();
 
  898       this->UpdateLoweredWidgets();
 
  903   void UpdateExcludedData()
 
  915   void UpdateLoweredWidgets()
 
  959     GfxFillRect(rect_x + 1, y + 1 + clk_dif, rect_x + 7, y + 4 + clk_dif, cs->legend_colour);
 
  961     DrawString(rtl ? r.left : x + 14 + clk_dif, (rtl ? r.right - 14 + clk_dif : r.right), y + clk_dif, STR_GRAPH_CARGO_PAYMENT_CARGO);
 
  969         _legend_excluded_cargo = 0;
 
  971         this->UpdateLoweredWidgets();
 
  984         this->UpdateLoweredWidgets();
 
  994           this->UpdateExcludedData();
 
 1013     if (!gui_scope) 
return;
 
 1019     this->UpdateExcludedData();
 
 1024       this->colours[i] = cs->legend_colour;
 
 1025       for (uint j = 0; j != 20; j++) {
 
 1026         this->
cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 4 + 4, cs->
Index());
 
 1030     this->num_dataset = i;
 
 1041     leaf->
tool_tip = STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO;
 
 1051 static const NWidgetPart _nested_cargo_payment_rates_widgets[] = {
 
 1062       NWidget(
WWT_TEXT, COLOUR_GREY, 
WID_CPR_HEADER), 
SetMinimalSize(0, 6), 
SetPadding(2, 0, 2, 0), 
SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_TITLE, STR_NULL),
 
 1079       NWidget(
WWT_TEXT, COLOUR_GREY, 
WID_CPR_FOOTER), 
SetMinimalSize(0, 6), 
SetPadding(2, 0, 2, 0), 
SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL, STR_NULL),
 
 1087   WDP_AUTO, 
"graph_cargo_payment_rates", 0, 0,
 
 1090   _nested_cargo_payment_rates_widgets, 
lengthof(_nested_cargo_payment_rates_widgets)
 
 1094 void ShowCargoPaymentRates()
 
 1096   AllocateWindowDescFront<PaymentRatesGraphWindow>(&_cargo_payment_rates_desc, 0);
 
 1103 static const StringID _performance_titles[] = {
 
 1104   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER,
 
 1105   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER,
 
 1106   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER,
 
 1107   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER,
 
 1108   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR,
 
 1109   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR,
 
 1110   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR,
 
 1111   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR,
 
 1112   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR,
 
 1113   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR,
 
 1114   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE,
 
 1115   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE,
 
 1116   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN,
 
 1117   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN,
 
 1118   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT,
 
 1119   STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON,
 
 1122 static inline StringID GetPerformanceTitleFromValue(uint value)
 
 1124   return _performance_titles[
minu(value, 1000) >> 6];
 
 1142     this->companies.
Clear();
 
 1145     FOR_ALL_COMPANIES(c) {
 
 1146       *this->companies.
Append() = c;
 
 1156     return (*c2)->old_economy[0].performance_history - (*c1)->old_economy[0].performance_history;
 
 1189     for (uint i = 0; i != this->companies.
Length(); i++) {
 
 1190       const Company *c = this->companies[i];
 
 1191       DrawString(ordinal_left, ordinal_right, y, i + STR_ORDINAL_NUMBER_1ST, i == 0 ? TC_WHITE : TC_YELLOW);
 
 1198       DrawString(text_left, text_right, y, STR_COMPANY_LEAGUE_COMPANY_NAME);
 
 1213     uint widest_width = 0;
 
 1214     uint widest_title = 0;
 
 1215     for (uint i = 0; i < 
lengthof(_performance_titles); i++) {
 
 1217       if (width > widest_width) {
 
 1219         widest_width = 
width;
 
 1228     FOR_ALL_COMPANIES(c) {
 
 1231       SetDParam(2, _performance_titles[widest_title]);
 
 1265 static const NWidgetPart _nested_company_league_widgets[] = {
 
 1279   _nested_company_league_widgets, 
lengthof(_nested_company_league_widgets)
 
 1282 void ShowCompanyLeagueTable()
 
 1284   AllocateWindowDescFront<CompanyLeagueWindow>(&_company_league_desc, 0);
 
 1297     this->UpdateCompanyStats();
 
 1303   void UpdateCompanyStats()
 
 1308     FOR_ALL_COMPANIES(c) {
 
 1315   uint score_info_left;
 
 1316   uint score_info_right;
 
 1321   uint score_detail_left;
 
 1322   uint score_detail_right;
 
 1331         uint score_info_width = 0;
 
 1332         for (uint i = SCORE_BEGIN; i < 
SCORE_END; i++) {
 
 1347         int max = -(999999999 - 500);
 
 1360         if (_currency->rate < 1000) max /= _currency->rate;
 
 1365         size->width = 7 + score_info_width + 5 + this->bar_width + 5 + score_detail_width + 7;
 
 1367         uint right = size->width - 7;
 
 1370         this->score_info_left  = rtl ? right - score_info_width : 
left;
 
 1371         this->score_info_right = rtl ? right : left + score_info_width;
 
 1373         this->score_detail_left  = rtl ? left : right - score_detail_width;
 
 1374         this->score_detail_right = rtl ? left + score_detail_width : right;
 
 1376         this->bar_left  = left + (rtl ? score_detail_width : score_info_width) + 5;
 
 1377         this->bar_right = this->bar_left + this->bar_width;
 
 1390       int offset = (cid == this->company) ? 1 : 0;
 
 1392       DrawCompanyIcon(cid, (r.left + r.right - sprite_size.width) / 2 + offset, (r.top + r.bottom - sprite_size.height) / 2 + offset);
 
 1405     int val    = _score_part[company][score_type];
 
 1416     uint text_top = bar_top + 2;
 
 1418     DrawString(this->score_info_left, this->score_info_right, text_top, STR_PERFORMANCE_DETAIL_VEHICLES + score_type);
 
 1422     DrawString(this->score_info_left, this->score_info_right, text_top, STR_BLACK_COMMA, TC_FROMSTRING, 
SA_RIGHT);
 
 1425     uint x = 
Clamp(val, 0, needed) * this->bar_width / needed;
 
 1428       x = this->bar_right - x;
 
 1430       x = this->bar_left + x;
 
 1434     if (x != this->bar_left)  
GfxFillRect(this->bar_left, bar_top, x, bar_top + this->bar_height, rtl ? colour_notdone : colour_done);
 
 1435     if (x != this->bar_right) 
GfxFillRect(x, bar_top, this->bar_right, bar_top + this->bar_height, rtl ? colour_done : colour_notdone);
 
 1439     DrawString(this->bar_left, this->bar_right, text_top, STR_PERFORMANCE_DETAIL_PERCENT, TC_FROMSTRING, 
SA_HOR_CENTER);
 
 1442     if (score_type == SCORE_LOAN) val = needed - val;
 
 1448     switch (score_type) {
 
 1449       case SCORE_MIN_PROFIT:
 
 1450       case SCORE_MIN_INCOME:
 
 1451       case SCORE_MAX_INCOME:
 
 1454         DrawString(this->score_detail_left, this->score_detail_right, text_top, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY);
 
 1457         DrawString(this->score_detail_left, this->score_detail_right, text_top, STR_PERFORMANCE_DETAIL_AMOUNT_INT);
 
 1480     if (--this->timeout == 0) {
 
 1481       this->UpdateCompanyStats();
 
 1493     if (!gui_scope) 
return;
 
 1508       FOR_ALL_COMPANIES(c) {
 
 1509         this->company = c->
index;
 
 1529   const StringID performance_tips[] = {
 
 1530     STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP,
 
 1531     STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP,
 
 1532     STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP,
 
 1533     STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP,
 
 1534     STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP,
 
 1535     STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP,
 
 1536     STR_PERFORMANCE_DETAIL_CARGO_TOOLTIP,
 
 1537     STR_PERFORMANCE_DETAIL_MONEY_TOOLTIP,
 
 1538     STR_PERFORMANCE_DETAIL_LOAN_TOOLTIP,
 
 1539     STR_PERFORMANCE_DETAIL_TOTAL_TOOLTIP,
 
 1561 static const NWidgetPart _nested_performance_rating_detail_widgets[] = {
 
 1574 static WindowDesc _performance_rating_detail_desc(
 
 1578   _nested_performance_rating_detail_widgets, 
lengthof(_nested_performance_rating_detail_widgets)
 
 1581 void ShowPerformanceRatingDetail()
 
 1583   AllocateWindowDescFront<PerformanceRatingDetailWindow>(&_performance_rating_detail_desc, 0);