src/graph_gui.cpp
changeset 10207 c291a21b304e
parent 10054 69258fa808b7
child 10208 72c00af5c95d
equal deleted inserted replaced
10206:0050610c0368 10207:c291a21b304e
    19 #include "sortlist_type.h"
    19 #include "sortlist_type.h"
    20 
    20 
    21 #include "table/strings.h"
    21 #include "table/strings.h"
    22 #include "table/sprites.h"
    22 #include "table/sprites.h"
    23 
    23 
    24 /* Bitmasks of player and cargo indices that shouldn't be drawn. */
    24 /* Bitmasks of company and cargo indices that shouldn't be drawn. */
    25 static uint _legend_excluded_players;
    25 static uint _legend_excluded_companies;
    26 static uint _legend_excluded_cargo;
    26 static uint _legend_excluded_cargo;
    27 
    27 
    28 /* Apparently these don't play well with enums. */
    28 /* Apparently these don't play well with enums. */
    29 static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
    29 static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
    30 static const uint INVALID_DATAPOINT_POS = UINT_MAX;  // Used to determine if the previous point was drawn.
    30 static const uint INVALID_DATAPOINT_POS = UINT_MAX;  // Used to determine if the previous point was drawn.
    35 
    35 
    36 struct GraphLegendWindow : Window {
    36 struct GraphLegendWindow : Window {
    37 	GraphLegendWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
    37 	GraphLegendWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
    38 	{
    38 	{
    39 		for (uint i = 3; i < this->widget_count; i++) {
    39 		for (uint i = 3; i < this->widget_count; i++) {
    40 			if (!HasBit(_legend_excluded_players, i - 3)) this->LowerWidget(i);
    40 			if (!HasBit(_legend_excluded_companies, i - 3)) this->LowerWidget(i);
    41 		}
    41 		}
    42 
    42 
    43 		this->FindWindowPlacementAndResize(desc);
    43 		this->FindWindowPlacementAndResize(desc);
    44 	}
    44 	}
    45 
    45 
    46 	virtual void OnPaint()
    46 	virtual void OnPaint()
    47 	{
    47 	{
    48 		for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) {
    48 		for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
    49 			if (IsValidPlayerID(p)) continue;
    49 			if (IsValidCompanyID(c)) continue;
    50 
    50 
    51 			SetBit(_legend_excluded_players, p);
    51 			SetBit(_legend_excluded_companies, c);
    52 			this->RaiseWidget(p + 3);
    52 			this->RaiseWidget(c + 3);
    53 		}
    53 		}
    54 
    54 
    55 		this->DrawWidgets();
    55 		this->DrawWidgets();
    56 
    56 
    57 		const Player *p;
    57 		const Company *c;
    58 		FOR_ALL_PLAYERS(p) {
    58 		FOR_ALL_COMPANIES(c) {
    59 			DrawPlayerIcon(p->index, 4, 18 + p->index * 12);
    59 			DrawCompanyIcon(c->index, 4, 18 + c->index * 12);
    60 
    60 
    61 			SetDParam(0, p->index);
    61 			SetDParam(0, c->index);
    62 			SetDParam(1, p->index);
    62 			SetDParam(1, c->index);
    63 			DrawString(21, 17 + p->index * 12, STR_7021, HasBit(_legend_excluded_players, p->index) ? TC_BLACK : TC_WHITE);
    63 			DrawString(21, 17 + c->index * 12, STR_7021, HasBit(_legend_excluded_companies, c->index) ? TC_BLACK : TC_WHITE);
    64 		}
    64 		}
    65 	}
    65 	}
    66 
    66 
    67 	virtual void OnClick(Point pt, int widget)
    67 	virtual void OnClick(Point pt, int widget)
    68 	{
    68 	{
    69 		if (!IsInsideMM(widget, 3, 11)) return;
    69 		if (!IsInsideMM(widget, 3, 11)) return;
    70 
    70 
    71 		ToggleBit(_legend_excluded_players, widget - 3);
    71 		ToggleBit(_legend_excluded_companies, widget - 3);
    72 		this->ToggleWidgetLoweredState(widget);
    72 		this->ToggleWidgetLoweredState(widget);
    73 		this->SetDirty();
    73 		this->SetDirty();
    74 		InvalidateWindow(WC_INCOME_GRAPH, 0);
    74 		InvalidateWindow(WC_INCOME_GRAPH, 0);
    75 		InvalidateWindow(WC_OPERATING_PROFIT, 0);
    75 		InvalidateWindow(WC_OPERATING_PROFIT, 0);
    76 		InvalidateWindow(WC_DELIVERED_CARGO, 0);
    76 		InvalidateWindow(WC_DELIVERED_CARGO, 0);
   153 		uint x, y;                       ///< Reused whenever x and y coordinates are needed.
   153 		uint x, y;                       ///< Reused whenever x and y coordinates are needed.
   154 		OverflowSafeInt64 highest_value; ///< Highest value to be drawn.
   154 		OverflowSafeInt64 highest_value; ///< Highest value to be drawn.
   155 		int x_axis_offset;               ///< Distance from the top of the graph to the x axis.
   155 		int x_axis_offset;               ///< Distance from the top of the graph to the x axis.
   156 
   156 
   157 		/* the colors and cost array of GraphDrawer must accomodate
   157 		/* the colors and cost array of GraphDrawer must accomodate
   158 		* both values for cargo and players. So if any are higher, quit */
   158 		* both values for cargo and companies. So if any are higher, quit */
   159 		assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_PLAYERS);
   159 		assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_COMPANIES);
   160 		assert(this->num_vert_lines > 0);
   160 		assert(this->num_vert_lines > 0);
   161 
   161 
   162 		byte grid_colour = _colour_gradient[COLOUR_GREY][4];
   162 		byte grid_colour = _colour_gradient[COLOUR_GREY][4];
   163 
   163 
   164 		/* The coordinates of the opposite edges of the graph. */
   164 		/* The coordinates of the opposite edges of the graph. */
   352 public:
   352 public:
   353 	virtual void OnPaint()
   353 	virtual void OnPaint()
   354 	{
   354 	{
   355 		this->DrawWidgets();
   355 		this->DrawWidgets();
   356 
   356 
   357 		uint excluded_players = _legend_excluded_players;
   357 		uint excluded_companies = _legend_excluded_companies;
   358 
   358 
   359 		/* Exclude the players which aren't valid */
   359 		/* Exclude the companies which aren't valid */
   360 		for (PlayerID p = PLAYER_FIRST; p < MAX_PLAYERS; p++) {
   360 		for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
   361 			if (!IsValidPlayerID(p)) SetBit(excluded_players, p);
   361 			if (!IsValidCompanyID(c)) SetBit(excluded_companies, c);
   362 		}
   362 		}
   363 		this->excluded_data = excluded_players;
   363 		this->excluded_data = excluded_companies;
   364 		this->num_vert_lines = 24;
   364 		this->num_vert_lines = 24;
   365 
   365 
   366 		byte nums = 0;
   366 		byte nums = 0;
   367 		const Player *p;
   367 		const Company *c;
   368 		FOR_ALL_PLAYERS(p) {
   368 		FOR_ALL_COMPANIES(c) {
   369 			nums = max(nums, p->num_valid_stat_ent);
   369 			nums = max(nums, c->num_valid_stat_ent);
   370 		}
   370 		}
   371 		this->num_on_x_axis = min(nums, 24);
   371 		this->num_on_x_axis = min(nums, 24);
   372 
   372 
   373 		int mo = (_cur_month / 3 - nums) * 3;
   373 		int mo = (_cur_month / 3 - nums) * 3;
   374 		int yr = _cur_year;
   374 		int yr = _cur_year;
   379 
   379 
   380 		this->year = yr;
   380 		this->year = yr;
   381 		this->month = mo;
   381 		this->month = mo;
   382 
   382 
   383 		int numd = 0;
   383 		int numd = 0;
   384 		for (PlayerID k = PLAYER_FIRST; k < MAX_PLAYERS; k++) {
   384 		for (CompanyID k = COMPANY_FIRST; k < MAX_COMPANIES; k++) {
   385 			if (IsValidPlayerID(k)) {
   385 			if (IsValidCompanyID(k)) {
   386 				p = GetPlayer(k);
   386 				c = GetCompany(k);
   387 				this->colors[numd] = _colour_gradient[p->player_color][6];
   387 				this->colors[numd] = _colour_gradient[c->colour][6];
   388 				for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
   388 				for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
   389 					this->cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(p, j);
   389 					this->cost[numd][i] = (j >= c->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(c, j);
   390 					i++;
   390 					i++;
   391 				}
   391 				}
   392 			}
   392 			}
   393 			numd++;
   393 			numd++;
   394 		}
   394 		}
   396 		this->num_dataset = numd;
   396 		this->num_dataset = numd;
   397 
   397 
   398 		this->DrawGraph();
   398 		this->DrawGraph();
   399 	}
   399 	}
   400 
   400 
   401 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   401 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   402 	{
   402 	{
   403 		return INVALID_DATAPOINT;
   403 		return INVALID_DATAPOINT;
   404 	}
   404 	}
   405 
   405 
   406 	virtual void OnClick(Point pt, int widget)
   406 	virtual void OnClick(Point pt, int widget)
   419 			BaseGraphWindow(desc, window_number, 2, 18, 136, true, STR_CURRCOMPACT)
   419 			BaseGraphWindow(desc, window_number, 2, 18, 136, true, STR_CURRCOMPACT)
   420 	{
   420 	{
   421 		this->FindWindowPlacementAndResize(desc);
   421 		this->FindWindowPlacementAndResize(desc);
   422 	}
   422 	}
   423 
   423 
   424 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   424 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   425 	{
   425 	{
   426 		return p->old_economy[j].income + p->old_economy[j].expenses;
   426 		return c->old_economy[j].income + c->old_economy[j].expenses;
   427 	}
   427 	}
   428 };
   428 };
   429 
   429 
   430 static const Widget _operating_profit_widgets[] = {
   430 static const Widget _operating_profit_widgets[] = {
   431 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
   431 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
   458 			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_CURRCOMPACT)
   458 			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_CURRCOMPACT)
   459 	{
   459 	{
   460 		this->FindWindowPlacementAndResize(desc);
   460 		this->FindWindowPlacementAndResize(desc);
   461 	}
   461 	}
   462 
   462 
   463 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   463 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   464 	{
   464 	{
   465 		return p->old_economy[j].income;
   465 		return c->old_economy[j].income;
   466 	}
   466 	}
   467 };
   467 };
   468 
   468 
   469 static const Widget _income_graph_widgets[] = {
   469 static const Widget _income_graph_widgets[] = {
   470 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
   470 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
   495 			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_7024)
   495 			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_7024)
   496 	{
   496 	{
   497 		this->FindWindowPlacementAndResize(desc);
   497 		this->FindWindowPlacementAndResize(desc);
   498 	}
   498 	}
   499 
   499 
   500 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   500 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   501 	{
   501 	{
   502 		return p->old_economy[j].delivered_cargo;
   502 		return c->old_economy[j].delivered_cargo;
   503 	}
   503 	}
   504 };
   504 };
   505 
   505 
   506 static const Widget _delivered_cargo_graph_widgets[] = {
   506 static const Widget _delivered_cargo_graph_widgets[] = {
   507 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
   507 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
   532 			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_7024)
   532 			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_7024)
   533 	{
   533 	{
   534 		this->FindWindowPlacementAndResize(desc);
   534 		this->FindWindowPlacementAndResize(desc);
   535 	}
   535 	}
   536 
   536 
   537 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   537 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   538 	{
   538 	{
   539 		return p->old_economy[j].performance_history;
   539 		return c->old_economy[j].performance_history;
   540 	}
   540 	}
   541 
   541 
   542 	virtual void OnClick(Point pt, int widget)
   542 	virtual void OnClick(Point pt, int widget)
   543 	{
   543 	{
   544 		if (widget == 3) ShowPerformanceRatingDetail();
   544 		if (widget == 3) ShowPerformanceRatingDetail();
   576 			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_CURRCOMPACT)
   576 			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_CURRCOMPACT)
   577 	{
   577 	{
   578 		this->FindWindowPlacementAndResize(desc);
   578 		this->FindWindowPlacementAndResize(desc);
   579 	}
   579 	}
   580 
   580 
   581 	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
   581 	virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
   582 	{
   582 	{
   583 		return p->old_economy[j].company_value;
   583 		return c->old_economy[j].company_value;
   584 	}
   584 	}
   585 };
   585 };
   586 
   586 
   587 static const Widget _company_value_graph_widgets[] = {
   587 static const Widget _company_value_graph_widgets[] = {
   588 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},
   588 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},
   666 		for (CargoID c = 0; c < NUM_CARGO; c++) {
   666 		for (CargoID c = 0; c < NUM_CARGO; c++) {
   667 			const CargoSpec *cs = GetCargo(c);
   667 			const CargoSpec *cs = GetCargo(c);
   668 			if (!cs->IsValid()) continue;
   668 			if (!cs->IsValid()) continue;
   669 
   669 
   670 			/* Only draw labels for widgets that exist. If the widget doesn't
   670 			/* Only draw labels for widgets that exist. If the widget doesn't
   671 				* exist then the local player has used the climate cheat or
   671 			 * exist then the local company has used the climate cheat or
   672 				* changed the NewGRF configuration with this window open. */
   672 			 * changed the NewGRF configuration with this window open. */
   673 			if (i + 3 < this->widget_count) {
   673 			if (i + 3 < this->widget_count) {
   674 				/* Since the buttons have no text, no images,
   674 				/* Since the buttons have no text, no images,
   675 					* both the text and the colored box have to be manually painted.
   675 				 * both the text and the colored box have to be manually painted.
   676 					* clk_dif will move one pixel down and one pixel to the right
   676 				 * clk_dif will move one pixel down and one pixel to the right
   677 					* when the button is clicked */
   677 				 * when the button is clicked */
   678 				byte clk_dif = this->IsWidgetLowered(i + 3) ? 1 : 0;
   678 				byte clk_dif = this->IsWidgetLowered(i + 3) ? 1 : 0;
   679 
   679 
   680 				GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0);
   680 				GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0);
   681 				GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour);
   681 				GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour);
   682 				SetDParam(0, cs->name);
   682 				SetDParam(0, cs->name);
   757 	return _performance_titles[minu(value, 1000) >> 6];
   757 	return _performance_titles[minu(value, 1000) >> 6];
   758 }
   758 }
   759 
   759 
   760 class CompanyLeagueWindow : public Window {
   760 class CompanyLeagueWindow : public Window {
   761 private:
   761 private:
   762 	GUIList<const Player*> players;
   762 	GUIList<const Company*> companies;
   763 
   763 
   764 	/**
   764 	/**
   765 	 * (Re)Build the company league list
   765 	 * (Re)Build the company league list
   766 	 */
   766 	 */
   767 	void BuildPlayerList()
   767 	void BuildCompanyList()
   768 	{
   768 	{
   769 		if (!this->players.NeedRebuild()) return;
   769 		if (!this->companies.NeedRebuild()) return;
   770 
   770 
   771 		this->players.Clear();
   771 		this->companies.Clear();
   772 
   772 
   773 		const Player *p;
   773 		const Company *c;
   774 		FOR_ALL_PLAYERS(p) {
   774 		FOR_ALL_COMPANIES(c) {
   775 			*this->players.Append() = p;
   775 			*this->companies.Append() = c;
   776 		}
   776 		}
   777 
   777 
   778 		this->players.Compact();
   778 		this->companies.Compact();
   779 		this->players.RebuildDone();
   779 		this->companies.RebuildDone();
   780 	}
   780 	}
   781 
   781 
   782 	/** Sort the company league by performance history */
   782 	/** Sort the company league by performance history */
   783 	static int CDECL PerformanceSorter(const Player* const *p1, const Player* const *p2)
   783 	static int CDECL PerformanceSorter(const Company* const *c1, const Company* const *c2)
   784 	{
   784 	{
   785 		return (*p2)->old_economy[1].performance_history - (*p1)->old_economy[1].performance_history;
   785 		return (*c2)->old_economy[1].performance_history - (*c1)->old_economy[1].performance_history;
   786 	}
   786 	}
   787 
   787 
   788 public:
   788 public:
   789 	CompanyLeagueWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
   789 	CompanyLeagueWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
   790 	{
   790 	{
   791 		this->players.ForceRebuild();
   791 		this->companies.ForceRebuild();
   792 		this->players.NeedResort();
   792 		this->companies.NeedResort();
   793 
   793 
   794 		this->FindWindowPlacementAndResize(desc);
   794 		this->FindWindowPlacementAndResize(desc);
   795 	}
   795 	}
   796 
   796 
   797 	virtual void OnPaint()
   797 	virtual void OnPaint()
   798 	{
   798 	{
   799 		this->BuildPlayerList();
   799 		this->BuildCompanyList();
   800 		this->players.Sort(&PerformanceSorter);
   800 		this->companies.Sort(&PerformanceSorter);
   801 
   801 
   802 		this->DrawWidgets();
   802 		this->DrawWidgets();
   803 
   803 
   804 		for (uint i = 0; i != this->players.Length(); i++) {
   804 		for (uint i = 0; i != this->companies.Length(); i++) {
   805 			const Player *p = this->players[i];
   805 			const Company *c = this->companies[i];
   806 			SetDParam(0, i + STR_01AC_1ST);
   806 			SetDParam(0, i + STR_01AC_1ST);
   807 			SetDParam(1, p->index);
   807 			SetDParam(1, c->index);
   808 			SetDParam(2, p->index);
   808 			SetDParam(2, c->index);
   809 			SetDParam(3, GetPerformanceTitleFromValue(p->old_economy[1].performance_history));
   809 			SetDParam(3, GetPerformanceTitleFromValue(c->old_economy[1].performance_history));
   810 
   810 
   811 			DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING);
   811 			DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING);
   812 			DrawPlayerIcon(p->index, 27, 16 + i * 10);
   812 			DrawCompanyIcon(c->index, 27, 16 + i * 10);
   813 		}
   813 		}
   814 	}
   814 	}
   815 
   815 
   816 	virtual void OnTick()
   816 	virtual void OnTick()
   817 	{
   817 	{
   818 		if (this->players.NeedResort()) {
   818 		if (this->companies.NeedResort()) {
   819 			this->SetDirty();
   819 			this->SetDirty();
   820 		}
   820 		}
   821 	}
   821 	}
   822 
   822 
   823 	virtual void OnInvalidateData(int data)
   823 	virtual void OnInvalidateData(int data)
   824 	{
   824 	{
   825 		if (data == 0) {
   825 		if (data == 0) {
   826 			this->players.ForceRebuild();
   826 			this->companies.ForceRebuild();
   827 		} else {
   827 		} else {
   828 			this->players.ForceResort();
   828 			this->companies.ForceResort();
   829 		}
   829 		}
   830 	}
   830 	}
   831 };
   831 };
   832 
   832 
   833 
   833 
   856 /*****************************/
   856 /*****************************/
   857 
   857 
   858 struct PerformanceRatingDetailWindow : Window {
   858 struct PerformanceRatingDetailWindow : Window {
   859 private:
   859 private:
   860 	enum PerformanteRatingWidgets {
   860 	enum PerformanteRatingWidgets {
   861 		PRW_PLAYER_FIRST = 13,
   861 		PRW_COMPANY_FIRST = 13,
   862 		PRW_PLAYER_LAST  = 20,
   862 		PRW_COMPANY_LAST  = 20,
   863 	};
   863 	};
   864 
   864 
   865 public:
   865 public:
   866 	static PlayerID player;
   866 	static CompanyID company;
   867 	int timeout;
   867 	int timeout;
   868 
   868 
   869 	PerformanceRatingDetailWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
   869 	PerformanceRatingDetailWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
   870 	{
   870 	{
   871 		/* Disable the players who are not active */
   871 		/* Disable the companies who are not active */
   872 		for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) {
   872 		for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
   873 			this->SetWidgetDisabledState(i + PRW_PLAYER_FIRST, !IsValidPlayerID(i));
   873 			this->SetWidgetDisabledState(i + PRW_COMPANY_FIRST, !IsValidCompanyID(i));
   874 		}
   874 		}
   875 
   875 
   876 		this->UpdatePlayerStats();
   876 		this->UpdateCompanyStats();
   877 
   877 
   878 		if (player != INVALID_PLAYER) this->LowerWidget(player + PRW_PLAYER_FIRST);
   878 		if (company != INVALID_COMPANY) this->LowerWidget(company + PRW_COMPANY_FIRST);
   879 
   879 
   880 		this->FindWindowPlacementAndResize(desc);
   880 		this->FindWindowPlacementAndResize(desc);
   881 	}
   881 	}
   882 
   882 
   883 	void UpdatePlayerStats()
   883 	void UpdateCompanyStats()
   884 	{
   884 	{
   885 		/* Update all player stats with the current data
   885 		/* Update all company stats with the current data
   886 		 * (this is because _score_info is not saved to a savegame) */
   886 		 * (this is because _score_info is not saved to a savegame) */
   887 		Player *p;
   887 		Company *c;
   888 		FOR_ALL_PLAYERS(p) {
   888 		FOR_ALL_COMPANIES(c) {
   889 			UpdateCompanyRatingAndValue(p, false);
   889 			UpdateCompanyRatingAndValue(c, false);
   890 		}
   890 		}
   891 
   891 
   892 		this->timeout = DAY_TICKS * 5;
   892 		this->timeout = DAY_TICKS * 5;
   893 
   893 
   894 	}
   894 	}
   901 		int color_done, color_notdone;
   901 		int color_done, color_notdone;
   902 
   902 
   903 		/* Draw standard stuff */
   903 		/* Draw standard stuff */
   904 		this->DrawWidgets();
   904 		this->DrawWidgets();
   905 
   905 
   906 		/* Check if the currently selected player is still active. */
   906 		/* Check if the currently selected company is still active. */
   907 		if (player == INVALID_PLAYER || !IsValidPlayerID(player)) {
   907 		if (company == INVALID_COMPANY || !IsValidCompanyID(company)) {
   908 			if (player != INVALID_PLAYER) {
   908 			if (company != INVALID_COMPANY) {
   909 				/* Raise and disable the widget for the previous selection. */
   909 				/* Raise and disable the widget for the previous selection. */
   910 				this->RaiseWidget(player + PRW_PLAYER_FIRST);
   910 				this->RaiseWidget(company + PRW_COMPANY_FIRST);
   911 				this->DisableWidget(player + PRW_PLAYER_FIRST);
   911 				this->DisableWidget(company + PRW_COMPANY_FIRST);
   912 				this->SetDirty();
   912 				this->SetDirty();
   913 
   913 
   914 				player = INVALID_PLAYER;
   914 				company = INVALID_COMPANY;
   915 			}
   915 			}
   916 
   916 
   917 			for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) {
   917 			for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
   918 				if (IsValidPlayerID(i)) {
   918 				if (IsValidCompanyID(i)) {
   919 					/* Lower the widget corresponding to this player. */
   919 					/* Lower the widget corresponding to this company. */
   920 					this->LowerWidget(i + PRW_PLAYER_FIRST);
   920 					this->LowerWidget(i + PRW_COMPANY_FIRST);
   921 					this->SetDirty();
   921 					this->SetDirty();
   922 
   922 
   923 					player = i;
   923 					company = i;
   924 					break;
   924 					break;
   925 				}
   925 				}
   926 			}
   926 			}
   927 		}
   927 		}
   928 
   928 
   929 		/* If there are no active players, don't display anything else. */
   929 		/* If there are no active companies, don't display anything else. */
   930 		if (player == INVALID_PLAYER) return;
   930 		if (company == INVALID_COMPANY) return;
   931 
   931 
   932 		/* Paint the player icons */
   932 		/* Paint the company icons */
   933 		for (PlayerID i = PLAYER_FIRST; i < MAX_PLAYERS; i++) {
   933 		for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
   934 			if (!IsValidPlayerID(i)) {
   934 			if (!IsValidCompanyID(i)) {
   935 				/* Check if we have the player as an active player */
   935 				/* Check if we have the company as an active company */
   936 				if (!this->IsWidgetDisabled(i + PRW_PLAYER_FIRST)) {
   936 				if (!this->IsWidgetDisabled(i + PRW_COMPANY_FIRST)) {
   937 					/* Bah, player gone :( */
   937 					/* Bah, company gone :( */
   938 					this->DisableWidget(i + PRW_PLAYER_FIRST);
   938 					this->DisableWidget(i + PRW_COMPANY_FIRST);
   939 
   939 
   940 					/* We need a repaint */
   940 					/* We need a repaint */
   941 					this->SetDirty();
   941 					this->SetDirty();
   942 				}
   942 				}
   943 				continue;
   943 				continue;
   944 			}
   944 			}
   945 
   945 
   946 			/* Check if we have the player marked as inactive */
   946 			/* Check if we have the company marked as inactive */
   947 			if (this->IsWidgetDisabled(i + PRW_PLAYER_FIRST)) {
   947 			if (this->IsWidgetDisabled(i + PRW_COMPANY_FIRST)) {
   948 				/* New player! Yippie :p */
   948 				/* New company! Yippie :p */
   949 				this->EnableWidget(i + PRW_PLAYER_FIRST);
   949 				this->EnableWidget(i + PRW_COMPANY_FIRST);
   950 				/* We need a repaint */
   950 				/* We need a repaint */
   951 				this->SetDirty();
   951 				this->SetDirty();
   952 			}
   952 			}
   953 
   953 
   954 			x = (i == player) ? 1 : 0;
   954 			x = (i == company) ? 1 : 0;
   955 			DrawPlayerIcon(i, i * 37 + 13 + x, 16 + x);
   955 			DrawCompanyIcon(i, i * 37 + 13 + x, 16 + x);
   956 		}
   956 		}
   957 
   957 
   958 		/* The colors used to show how the progress is going */
   958 		/* The colors used to show how the progress is going */
   959 		color_done = _colour_gradient[COLOUR_GREEN][4];
   959 		color_done = _colour_gradient[COLOUR_GREEN][4];
   960 		color_notdone = _colour_gradient[COLOUR_RED][4];
   960 		color_notdone = _colour_gradient[COLOUR_RED][4];
   961 
   961 
   962 		/* Draw all the score parts */
   962 		/* Draw all the score parts */
   963 		for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
   963 		for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
   964 			int val    = _score_part[player][i];
   964 			int val    = _score_part[company][i];
   965 			int needed = _score_info[i].needed;
   965 			int needed = _score_info[i].needed;
   966 			int score  = _score_info[i].score;
   966 			int score  = _score_info[i].score;
   967 
   967 
   968 			y += 20;
   968 			y += 20;
   969 			/* SCORE_TOTAL has his own rulez ;) */
   969 			/* SCORE_TOTAL has his own rulez ;) */
  1022 	}
  1022 	}
  1023 
  1023 
  1024 	virtual void OnClick(Point pt, int widget)
  1024 	virtual void OnClick(Point pt, int widget)
  1025 	{
  1025 	{
  1026 		/* Check which button is clicked */
  1026 		/* Check which button is clicked */
  1027 		if (IsInsideMM(widget, PRW_PLAYER_FIRST, PRW_PLAYER_LAST + 1)) {
  1027 		if (IsInsideMM(widget, PRW_COMPANY_FIRST, PRW_COMPANY_LAST + 1)) {
  1028 			/* Is it no on disable? */
  1028 			/* Is it no on disable? */
  1029 			if (!this->IsWidgetDisabled(widget)) {
  1029 			if (!this->IsWidgetDisabled(widget)) {
  1030 				this->RaiseWidget(player + PRW_PLAYER_FIRST);
  1030 				this->RaiseWidget(company + PRW_COMPANY_FIRST);
  1031 				player = (PlayerID)(widget - PRW_PLAYER_FIRST);
  1031 				company = (CompanyID)(widget - PRW_COMPANY_FIRST);
  1032 				this->LowerWidget(player + PRW_PLAYER_FIRST);
  1032 				this->LowerWidget(company + PRW_COMPANY_FIRST);
  1033 				this->SetDirty();
  1033 				this->SetDirty();
  1034 			}
  1034 			}
  1035 		}
  1035 		}
  1036 	}
  1036 	}
  1037 
  1037 
  1038 	virtual void OnTick()
  1038 	virtual void OnTick()
  1039 	{
  1039 	{
  1040 		if (_pause_game != 0) return;
  1040 		if (_pause_game != 0) return;
  1041 
  1041 
  1042 		/* Update the player score every 5 days */
  1042 		/* Update the company score every 5 days */
  1043 		if (--this->timeout == 0) {
  1043 		if (--this->timeout == 0) {
  1044 			this->UpdatePlayerStats();
  1044 			this->UpdateCompanyStats();
  1045 			this->SetDirty();
  1045 			this->SetDirty();
  1046 		}
  1046 		}
  1047 	}
  1047 	}
  1048 };
  1048 };
  1049 
  1049 
  1050 PlayerID PerformanceRatingDetailWindow::player = INVALID_PLAYER;
  1050 CompanyID PerformanceRatingDetailWindow::company = INVALID_COMPANY;
  1051 
  1051 
  1052 
  1052 
  1053 static const Widget _performance_rating_detail_widgets[] = {
  1053 static const Widget _performance_rating_detail_widgets[] = {
  1054 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
  1054 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
  1055 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   298,     0,    13, STR_PERFORMANCE_DETAIL, STR_018C_WINDOW_TITLE_DRAG_THIS},
  1055 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   298,     0,    13, STR_PERFORMANCE_DETAIL, STR_018C_WINDOW_TITLE_DRAG_THIS},