graph_gui.cpp

Go to the documentation of this file.
00001 /* $Id: graph_gui.cpp 17081 2009-08-06 00:04:00Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "gui.h"
00008 #include "window_gui.h"
00009 #include "company_base.h"
00010 #include "company_gui.h"
00011 #include "economy_func.h"
00012 #include "cargotype.h"
00013 #include "strings_func.h"
00014 #include "window_func.h"
00015 #include "date_func.h"
00016 #include "gfx_func.h"
00017 #include "sortlist_type.h"
00018 
00019 #include "table/strings.h"
00020 
00021 /* Bitmasks of company and cargo indices that shouldn't be drawn. */
00022 static uint _legend_excluded_companies;
00023 static uint _legend_excluded_cargo;
00024 
00025 /* Apparently these don't play well with enums. */
00026 static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
00027 static const uint INVALID_DATAPOINT_POS = UINT_MAX;  // Used to determine if the previous point was drawn.
00028 
00029 /****************/
00030 /* GRAPH LEGEND */
00031 /****************/
00032 
00033 struct GraphLegendWindow : Window {
00034   GraphLegendWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
00035   {
00036     for (uint i = 3; i < this->widget_count; i++) {
00037       if (!HasBit(_legend_excluded_companies, i - 3)) this->LowerWidget(i);
00038     }
00039 
00040     this->FindWindowPlacementAndResize(desc);
00041   }
00042 
00043   virtual void OnPaint()
00044   {
00045     for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00046       if (IsValidCompanyID(c)) continue;
00047 
00048       SetBit(_legend_excluded_companies, c);
00049       this->RaiseWidget(c + 3);
00050     }
00051 
00052     this->DrawWidgets();
00053 
00054     const Company *c;
00055     FOR_ALL_COMPANIES(c) {
00056       DrawCompanyIcon(c->index, 4, 18 + c->index * 12);
00057 
00058       SetDParam(0, c->index);
00059       SetDParam(1, c->index);
00060       DrawString(21, 17 + c->index * 12, STR_7021, HasBit(_legend_excluded_companies, c->index) ? TC_BLACK : TC_WHITE);
00061     }
00062   }
00063 
00064   virtual void OnClick(Point pt, int widget)
00065   {
00066     if (!IsInsideMM(widget, 3, MAX_COMPANIES + 3)) return;
00067 
00068     ToggleBit(_legend_excluded_companies, widget - 3);
00069     this->ToggleWidgetLoweredState(widget);
00070     this->SetDirty();
00071     InvalidateWindow(WC_INCOME_GRAPH, 0);
00072     InvalidateWindow(WC_OPERATING_PROFIT, 0);
00073     InvalidateWindow(WC_DELIVERED_CARGO, 0);
00074     InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
00075     InvalidateWindow(WC_COMPANY_VALUE, 0);
00076   }
00077 };
00078 
00079 static const Widget _graph_legend_widgets[] = {
00080 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
00081 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   249,     0,    13, STR_704E_KEY_TO_COMPANY_GRAPHS, STR_018C_WINDOW_TITLE_DRAG_THIS},
00082 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   249,    14,   195, 0x0,                            STR_NULL},
00083 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    16,    27, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00084 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    28,    39, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00085 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    40,    51, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00086 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    52,    63, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00087 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    64,    75, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00088 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    76,    87, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00089 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,    88,    99, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00090 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   100,   111, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00091 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   112,   123, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00092 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   124,   135, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00093 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   136,   147, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00094 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   148,   159, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00095 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   160,   171, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00096 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   172,   183, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00097 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,   247,   184,   195, 0x0,                            STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00098 {   WIDGETS_END},
00099 };
00100 
00101 static const WindowDesc _graph_legend_desc(
00102   WDP_AUTO, WDP_AUTO, 250, 196, 250, 196,
00103   WC_GRAPH_LEGEND, WC_NONE,
00104   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00105   _graph_legend_widgets
00106 );
00107 
00108 static void ShowGraphLegend()
00109 {
00110   AllocateWindowDescFront<GraphLegendWindow>(&_graph_legend_desc, 0);
00111 }
00112 
00113 /******************/
00114 /* BASE OF GRAPHS */
00115 /*****************/
00116 
00117 struct BaseGraphWindow : Window {
00118 protected:
00119   enum {
00120     GRAPH_MAX_DATASETS = 32,
00121     GRAPH_AXIS_LINE_COLOUR  = 215,
00122 
00123     GRAPH_X_POSITION_BEGINNING  = 44,  
00124     GRAPH_X_POSITION_SEPARATION = 22,  
00125 
00126     GRAPH_NUM_LINES_Y = 9, 
00127     /* 9 is convenient as that means the distance between them is the gd_height of the graph / 8,
00128      * which is the same
00129      * as height >> 3. */
00130   };
00131 
00132   uint excluded_data; 
00133   byte num_dataset;
00134   byte num_on_x_axis;
00135   bool has_negative_values;
00136   byte num_vert_lines;
00137   static const TextColour graph_axis_label_colour = TC_BLACK; 
00138 
00139   /* The starting month and year that values are plotted against. If month is
00140    * 0xFF, use x_values_start and x_values_increment below instead. */
00141   byte month;
00142   Year year;
00143 
00144   /* These values are used if the graph is being plotted against values
00145    * rather than the dates specified by month and year. */
00146   uint16 x_values_start;
00147   uint16 x_values_increment;
00148 
00149   int gd_left, gd_top;  
00150   uint gd_height;    
00151   StringID format_str_y_axis;
00152   byte colours[GRAPH_MAX_DATASETS];
00153   OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][24]; 
00154 
00155   void DrawGraph() const
00156   {
00157     uint x, y;                       
00158     OverflowSafeInt64 highest_value; 
00159     int x_axis_offset;               
00160 
00161     /* the colours and cost array of GraphDrawer must accomodate
00162      * both values for cargo and companies. So if any are higher, quit */
00163     assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_COMPANIES);
00164     assert(this->num_vert_lines > 0);
00165 
00166     byte grid_colour = _colour_gradient[COLOUR_GREY][4];
00167 
00168     /* The coordinates of the opposite edges of the graph. */
00169     int bottom = this->gd_top + this->gd_height - 1;
00170     int right  = this->gd_left + GRAPH_X_POSITION_BEGINNING + this->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1;
00171 
00172     /* Draw the vertical grid lines. */
00173 
00174     /* Don't draw the first line, as that's where the axis will be. */
00175     x = this->gd_left + GRAPH_X_POSITION_BEGINNING + GRAPH_X_POSITION_SEPARATION;
00176 
00177     for (int i = 0; i < this->num_vert_lines; i++) {
00178       GfxFillRect(x, this->gd_top, x, bottom, grid_colour);
00179       x += GRAPH_X_POSITION_SEPARATION;
00180     }
00181 
00182     /* Draw the horizontal grid lines. */
00183     x = this->gd_left + GRAPH_X_POSITION_BEGINNING;
00184     y = this->gd_height + this->gd_top;
00185 
00186     for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
00187       GfxFillRect(x, y, right, y, grid_colour);
00188       y -= (this->gd_height / (GRAPH_NUM_LINES_Y - 1));
00189     }
00190 
00191     /* Draw the y axis. */
00192     GfxFillRect(x, this->gd_top, x, bottom, GRAPH_AXIS_LINE_COLOUR);
00193 
00194     /* Find the distance from the gd_top of the graph to the x axis. */
00195     x_axis_offset = this->gd_height;
00196 
00197     /* The graph is currently symmetrical about the x axis. */
00198     if (this->has_negative_values) x_axis_offset /= 2;
00199 
00200     /* Draw the x axis. */
00201     y = x_axis_offset + this->gd_top;
00202     GfxFillRect(x, y, right, y, GRAPH_AXIS_LINE_COLOUR);
00203 
00204     /* Find the largest value that will be drawn. */
00205     if (this->num_on_x_axis == 0)
00206       return;
00207 
00208     assert(this->num_on_x_axis > 0);
00209     assert(this->num_dataset > 0);
00210 
00211     /* Start of with a value of twice the gd_height of the graph in pixels. It's a
00212      * bit arbitrary, but it makes the cargo payment graph look a little nicer,
00213      * and prevents division by zero when calculating where the datapoint
00214      * should be drawn. */
00215     highest_value = x_axis_offset * 2;
00216 
00217     for (int i = 0; i < this->num_dataset; i++) {
00218       if (!HasBit(this->excluded_data, i)) {
00219         for (int j = 0; j < this->num_on_x_axis; j++) {
00220           OverflowSafeInt64 datapoint = this->cost[i][j];
00221 
00222           if (datapoint != INVALID_DATAPOINT) {
00223             /* For now, if the graph has negative values the scaling is
00224              * symmetrical about the x axis, so take the absolute value
00225              * of each data point. */
00226             highest_value = max(highest_value, abs(datapoint));
00227           }
00228         }
00229       }
00230     }
00231 
00232     /* Round up highest_value so that it will divide cleanly into the number of
00233      * axis labels used. */
00234     int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1);
00235     if (round_val != 0) highest_value += (GRAPH_NUM_LINES_Y - 1 - round_val);
00236 
00237     /* draw text strings on the y axis */
00238     int64 y_label = highest_value;
00239     int64 y_label_separation = highest_value / (GRAPH_NUM_LINES_Y - 1);
00240 
00241     /* If there are negative values, the graph goes from highest_value to
00242      * -highest_value, not highest_value to 0. */
00243     if (this->has_negative_values) y_label_separation *= 2;
00244 
00245     x = this->gd_left + GRAPH_X_POSITION_BEGINNING + 1;
00246     y = this->gd_top - 3;
00247 
00248     for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
00249       SetDParam(0, this->format_str_y_axis);
00250       SetDParam(1, y_label);
00251       DrawStringRightAligned(x, y, STR_0170, graph_axis_label_colour);
00252 
00253       y_label -= y_label_separation;
00254       y += (this->gd_height / (GRAPH_NUM_LINES_Y - 1));
00255     }
00256 
00257     /* draw strings on the x axis */
00258     if (this->month != 0xFF) {
00259       x = this->gd_left + GRAPH_X_POSITION_BEGINNING;
00260       y = this->gd_top + this->gd_height + 1;
00261       byte month = this->month;
00262       Year year  = this->year;
00263       for (int i = 0; i < this->num_on_x_axis; i++) {
00264         SetDParam(0, month + STR_0162_JAN);
00265         SetDParam(1, month + STR_0162_JAN + 2);
00266         SetDParam(2, year);
00267         DrawString(x, y, month == 0 ? STR_016F : STR_016E, graph_axis_label_colour);
00268 
00269         month += 3;
00270         if (month >= 12) {
00271           month = 0;
00272           year++;
00273         }
00274         x += GRAPH_X_POSITION_SEPARATION;
00275       }
00276     } else {
00277       /* Draw the label under the data point rather than on the grid line. */
00278       x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2) + 1;
00279       y = this->gd_top + this->gd_height + 1;
00280       uint16 label = this->x_values_start;
00281 
00282       for (int i = 0; i < this->num_on_x_axis; i++) {
00283         SetDParam(0, label);
00284         DrawStringCentered(x, y, STR_01CB, graph_axis_label_colour);
00285 
00286         label += this->x_values_increment;
00287         x += GRAPH_X_POSITION_SEPARATION;
00288       }
00289     }
00290 
00291     /* draw lines and dots */
00292     for (int i = 0; i < this->num_dataset; i++) {
00293       if (!HasBit(this->excluded_data, i)) {
00294         /* Centre the dot between the grid lines. */
00295         x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2);
00296 
00297         byte colour  = this->colours[i];
00298         uint prev_x = INVALID_DATAPOINT_POS;
00299         uint prev_y = INVALID_DATAPOINT_POS;
00300 
00301         for (int j = 0; j < this->num_on_x_axis; j++) {
00302           OverflowSafeInt64 datapoint = this->cost[i][j];
00303 
00304           if (datapoint != INVALID_DATAPOINT) {
00305             /*
00306              * Check whether we need to reduce the 'accuracy' of the
00307              * datapoint value and the highest value to splut overflows.
00308              * And when 'drawing' 'one million' or 'one million and one'
00309              * there is no significant difference, so the least
00310              * significant bits can just be removed.
00311              *
00312              * If there are more bits needed than would fit in a 32 bits
00313              * integer, so at about 31 bits because of the sign bit, the
00314              * least significant bits are removed.
00315              */
00316             int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint));
00317             int reduce_range = max(mult_range - 31, 0);
00318 
00319             /* Handle negative values differently (don't shift sign) */
00320             if (datapoint < 0) {
00321               datapoint = -(abs(datapoint) >> reduce_range);
00322             } else {
00323               datapoint >>= reduce_range;
00324             }
00325 
00326             y = this->gd_top + x_axis_offset - (x_axis_offset * datapoint) / (highest_value >> reduce_range);
00327 
00328             /* Draw the point. */
00329             GfxFillRect(x - 1, y - 1, x + 1, y + 1, colour);
00330 
00331             /* Draw the line connected to the previous point. */
00332             if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, colour);
00333 
00334             prev_x = x;
00335             prev_y = y;
00336           } else {
00337             prev_x = INVALID_DATAPOINT_POS;
00338             prev_y = INVALID_DATAPOINT_POS;
00339           }
00340 
00341           x += GRAPH_X_POSITION_SEPARATION;
00342         }
00343       }
00344     }
00345   }
00346 
00347 
00348   BaseGraphWindow(const WindowDesc *desc, WindowNumber window_number, int left,
00349                   int top, int height, bool has_negative_values, StringID format_str_y_axis) :
00350       Window(desc, window_number), has_negative_values(has_negative_values),
00351       gd_left(left), gd_top(top), gd_height(height), format_str_y_axis(format_str_y_axis)
00352   {
00353     InvalidateWindow(WC_GRAPH_LEGEND, 0);
00354   }
00355 
00356 public:
00357   virtual void OnPaint()
00358   {
00359     this->DrawWidgets();
00360 
00361     uint excluded_companies = _legend_excluded_companies;
00362 
00363     /* Exclude the companies which aren't valid */
00364     for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00365       if (!IsValidCompanyID(c)) SetBit(excluded_companies, c);
00366     }
00367     this->excluded_data = excluded_companies;
00368     this->num_vert_lines = 24;
00369 
00370     byte nums = 0;
00371     const Company *c;
00372     FOR_ALL_COMPANIES(c) {
00373       nums = max(nums, c->num_valid_stat_ent);
00374     }
00375     this->num_on_x_axis = min(nums, 24);
00376 
00377     int mo = (_cur_month / 3 - nums) * 3;
00378     int yr = _cur_year;
00379     while (mo < 0) {
00380       yr--;
00381       mo += 12;
00382     }
00383 
00384     this->year = yr;
00385     this->month = mo;
00386 
00387     int numd = 0;
00388     for (CompanyID k = COMPANY_FIRST; k < MAX_COMPANIES; k++) {
00389       if (IsValidCompanyID(k)) {
00390         c = GetCompany(k);
00391         this->colours[numd] = _colour_gradient[c->colour][6];
00392         for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
00393           this->cost[numd][i] = (j >= c->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(c, j);
00394           i++;
00395         }
00396       }
00397       numd++;
00398     }
00399 
00400     this->num_dataset = numd;
00401 
00402     this->DrawGraph();
00403   }
00404 
00405   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00406   {
00407     return INVALID_DATAPOINT;
00408   }
00409 
00410   virtual void OnClick(Point pt, int widget)
00411   {
00412     /* Clicked on legend? */
00413     if (widget == 2) ShowGraphLegend();
00414   }
00415 };
00416 
00417 /********************/
00418 /* OPERATING PROFIT */
00419 /********************/
00420 
00421 struct OperatingProfitGraphWindow : BaseGraphWindow {
00422   OperatingProfitGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00423       BaseGraphWindow(desc, window_number, 2, 18, 136, true, STR_CURRCOMPACT)
00424   {
00425     this->FindWindowPlacementAndResize(desc);
00426   }
00427 
00428   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00429   {
00430     return c->old_economy[j].income + c->old_economy[j].expenses;
00431   }
00432 };
00433 
00434 static const Widget _operating_profit_widgets[] = {
00435 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
00436 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   525,     0,    13, STR_7025_OPERATING_PROFIT_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS},
00437 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   526,   575,     0,    13, STR_704C_KEY,                    STR_704D_SHOW_KEY_TO_GRAPHS},
00438 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   575,    14,   173, 0x0,                             STR_NULL},
00439 {   WIDGETS_END},
00440 };
00441 
00442 static const WindowDesc _operating_profit_desc(
00443   WDP_AUTO, WDP_AUTO, 576, 174, 576, 174,
00444   WC_OPERATING_PROFIT, WC_NONE,
00445   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00446   _operating_profit_widgets
00447 );
00448 
00449 
00450 void ShowOperatingProfitGraph()
00451 {
00452   AllocateWindowDescFront<OperatingProfitGraphWindow>(&_operating_profit_desc, 0);
00453 }
00454 
00455 
00456 /****************/
00457 /* INCOME GRAPH */
00458 /****************/
00459 
00460 struct IncomeGraphWindow : BaseGraphWindow {
00461   IncomeGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00462       BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_CURRCOMPACT)
00463   {
00464     this->FindWindowPlacementAndResize(desc);
00465   }
00466 
00467   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00468   {
00469     return c->old_economy[j].income;
00470   }
00471 };
00472 
00473 static const Widget _income_graph_widgets[] = {
00474 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
00475 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   525,     0,    13, STR_7022_INCOME_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS},
00476 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   526,   575,     0,    13, STR_704C_KEY,          STR_704D_SHOW_KEY_TO_GRAPHS},
00477 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   575,    14,   141, 0x0,                   STR_NULL},
00478 {   WIDGETS_END},
00479 };
00480 
00481 static const WindowDesc _income_graph_desc(
00482   WDP_AUTO, WDP_AUTO, 576, 142, 576, 142,
00483   WC_INCOME_GRAPH, WC_NONE,
00484   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00485   _income_graph_widgets
00486 );
00487 
00488 void ShowIncomeGraph()
00489 {
00490   AllocateWindowDescFront<IncomeGraphWindow>(&_income_graph_desc, 0);
00491 }
00492 
00493 /*******************/
00494 /* DELIVERED CARGO */
00495 /*******************/
00496 
00497 struct DeliveredCargoGraphWindow : BaseGraphWindow {
00498   DeliveredCargoGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00499       BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_7024)
00500   {
00501     this->FindWindowPlacementAndResize(desc);
00502   }
00503 
00504   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00505   {
00506     return c->old_economy[j].delivered_cargo;
00507   }
00508 };
00509 
00510 static const Widget _delivered_cargo_graph_widgets[] = {
00511 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
00512 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   525,     0,    13, STR_7050_UNITS_OF_CARGO_DELIVERED, STR_018C_WINDOW_TITLE_DRAG_THIS},
00513 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   526,   575,     0,    13, STR_704C_KEY,                      STR_704D_SHOW_KEY_TO_GRAPHS},
00514 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   575,    14,   141, 0x0,                               STR_NULL},
00515 {   WIDGETS_END},
00516 };
00517 
00518 static const WindowDesc _delivered_cargo_graph_desc(
00519   WDP_AUTO, WDP_AUTO, 576, 142, 576, 142,
00520   WC_DELIVERED_CARGO, WC_NONE,
00521   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00522   _delivered_cargo_graph_widgets
00523 );
00524 
00525 void ShowDeliveredCargoGraph()
00526 {
00527   AllocateWindowDescFront<DeliveredCargoGraphWindow>(&_delivered_cargo_graph_desc, 0);
00528 }
00529 
00530 /***********************/
00531 /* PERFORMANCE HISTORY */
00532 /***********************/
00533 
00534 struct PerformanceHistoryGraphWindow : BaseGraphWindow {
00535   PerformanceHistoryGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00536       BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_7024)
00537   {
00538     this->FindWindowPlacementAndResize(desc);
00539   }
00540 
00541   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00542   {
00543     return c->old_economy[j].performance_history;
00544   }
00545 
00546   virtual void OnClick(Point pt, int widget)
00547   {
00548     if (widget == 3) ShowPerformanceRatingDetail();
00549     this->BaseGraphWindow::OnClick(pt, widget);
00550   }
00551 };
00552 
00553 static const Widget _performance_history_widgets[] = {
00554 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                             STR_018B_CLOSE_WINDOW},
00555 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   475,     0,    13, STR_7051_COMPANY_PERFORMANCE_RATINGS, STR_018C_WINDOW_TITLE_DRAG_THIS},
00556 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   526,   575,     0,    13, STR_704C_KEY,                         STR_704D_SHOW_KEY_TO_GRAPHS},
00557 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   476,   525,     0,    13, STR_PERFORMANCE_DETAIL_KEY,           STR_SHOW_DETAILED_PERFORMANCE_RATINGS},
00558 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   575,    14,   237, 0x0,                                  STR_NULL},
00559 {   WIDGETS_END},
00560 };
00561 
00562 static const WindowDesc _performance_history_desc(
00563   WDP_AUTO, WDP_AUTO, 576, 238, 576, 238,
00564   WC_PERFORMANCE_HISTORY, WC_NONE,
00565   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00566   _performance_history_widgets
00567 );
00568 
00569 void ShowPerformanceHistoryGraph()
00570 {
00571   AllocateWindowDescFront<PerformanceHistoryGraphWindow>(&_performance_history_desc, 0);
00572 }
00573 
00574 /*****************/
00575 /* COMPANY VALUE */
00576 /*****************/
00577 
00578 struct CompanyValueGraphWindow : BaseGraphWindow {
00579   CompanyValueGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00580       BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_CURRCOMPACT)
00581   {
00582     this->FindWindowPlacementAndResize(desc);
00583   }
00584 
00585   virtual OverflowSafeInt64 GetGraphData(const Company *c, int j)
00586   {
00587     return c->old_economy[j].company_value;
00588   }
00589 };
00590 
00591 static const Widget _company_value_graph_widgets[] = {
00592 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},
00593 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   525,     0,    13, STR_7052_COMPANY_VALUES, STR_018C_WINDOW_TITLE_DRAG_THIS},
00594 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   526,   575,     0,    13, STR_704C_KEY,            STR_704D_SHOW_KEY_TO_GRAPHS},
00595 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   575,    14,   237, 0x0,                     STR_NULL},
00596 {   WIDGETS_END},
00597 };
00598 
00599 static const WindowDesc _company_value_graph_desc(
00600   WDP_AUTO, WDP_AUTO, 576, 238, 576, 238,
00601   WC_COMPANY_VALUE, WC_NONE,
00602   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00603   _company_value_graph_widgets
00604 );
00605 
00606 void ShowCompanyValueGraph()
00607 {
00608   AllocateWindowDescFront<CompanyValueGraphWindow>(&_company_value_graph_desc, 0);
00609 }
00610 
00611 /*****************/
00612 /* PAYMENT RATES */
00613 /*****************/
00614 
00615 struct PaymentRatesGraphWindow : BaseGraphWindow {
00616   PaymentRatesGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
00617       BaseGraphWindow(desc, window_number, 2, 24, 200, false, STR_CURRCOMPACT)
00618   {
00619     uint num_active = 0;
00620     for (CargoID c = 0; c < NUM_CARGO; c++) {
00621       if (GetCargo(c)->IsValid()) num_active++;
00622     }
00623 
00624     /* Resize the window to fit the cargo types */
00625     ResizeWindow(this, 0, max(num_active, 12U) * 8);
00626 
00627     /* Add widgets for each cargo type */
00628     this->widget_count += num_active;
00629     this->widget = ReallocT(this->widget, this->widget_count + 1);
00630     this->widget[this->widget_count].type = WWT_LAST;
00631 
00632     /* Set the properties of each widget */
00633     for (uint i = 0; i != num_active; i++) {
00634       Widget *wi = &this->widget[3 + i];
00635       wi->type     = WWT_PANEL;
00636       wi->display_flags = RESIZE_NONE;
00637       wi->colour   = COLOUR_ORANGE;
00638       wi->left     = 493;
00639       wi->right    = 562;
00640       wi->top      = 24 + i * 8;
00641       wi->bottom   = wi->top + 7;
00642       wi->data     = 0;
00643       wi->tooltips = STR_7064_TOGGLE_GRAPH_FOR_CARGO;
00644 
00645       if (!HasBit(_legend_excluded_cargo, i)) this->LowerWidget(i + 3);
00646     }
00647 
00648     this->SetDirty();
00649 
00650     this->gd_height = this->height - 38;
00651     this->num_on_x_axis = 20;
00652     this->num_vert_lines = 20;
00653     this->month = 0xFF;
00654     this->x_values_start     = 10;
00655     this->x_values_increment = 10;
00656 
00657     this->FindWindowPlacementAndResize(desc);
00658   }
00659 
00660   virtual void OnPaint()
00661   {
00662     this->DrawWidgets();
00663 
00664     this->excluded_data = _legend_excluded_cargo;
00665 
00666     int x = 495;
00667     int y = 24;
00668 
00669     uint i = 0;
00670     for (CargoID c = 0; c < NUM_CARGO; c++) {
00671       const CargoSpec *cs = GetCargo(c);
00672       if (!cs->IsValid()) continue;
00673 
00674       /* Only draw labels for widgets that exist. If the widget doesn't
00675        * exist then the local company has used the climate cheat or
00676        * changed the NewGRF configuration with this window open. */
00677       if (i + 3 < this->widget_count) {
00678         /* Since the buttons have no text, no images,
00679          * both the text and the coloured box have to be manually painted.
00680          * clk_dif will move one pixel down and one pixel to the right
00681          * when the button is clicked */
00682         byte clk_dif = this->IsWidgetLowered(i + 3) ? 1 : 0;
00683 
00684         GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0);
00685         GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour);
00686         SetDParam(0, cs->name);
00687         DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, TC_FROMSTRING);
00688         y += 8;
00689       }
00690 
00691       this->colours[i] = cs->legend_colour;
00692       for (uint j = 0; j != 20; j++) {
00693         this->cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 4 + 4, c);
00694       }
00695 
00696       i++;
00697     }
00698     this->num_dataset = i;
00699 
00700     this->DrawGraph();
00701 
00702     DrawString(2 + 46, 24 + this->gd_height + 7, STR_7062_DAYS_IN_TRANSIT, TC_FROMSTRING);
00703     DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, TC_FROMSTRING);
00704   }
00705 
00706   virtual void OnClick(Point pt, int widget)
00707   {
00708     if (widget >= 3) {
00709       ToggleBit(_legend_excluded_cargo, widget - 3);
00710       this->ToggleWidgetLoweredState(widget);
00711       this->SetDirty();
00712     }
00713   }
00714 };
00715 
00716 static const Widget _cargo_payment_rates_widgets[] = {
00717 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                     STR_018B_CLOSE_WINDOW},
00718 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   567,     0,    13, STR_7061_CARGO_PAYMENT_RATES, STR_018C_WINDOW_TITLE_DRAG_THIS},
00719 {      WWT_PANEL, RESIZE_BOTTOM,  COLOUR_GREY,     0,   567,    14,    45, 0x0,                          STR_NULL},
00720 {   WIDGETS_END},
00721 };
00722 
00723 static const WindowDesc _cargo_payment_rates_desc(
00724   WDP_AUTO, WDP_AUTO, 568, 46, 568, 46,
00725   WC_PAYMENT_RATES, WC_NONE,
00726   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00727   _cargo_payment_rates_widgets
00728 );
00729 
00730 
00731 void ShowCargoPaymentRates()
00732 {
00733   AllocateWindowDescFront<PaymentRatesGraphWindow>(&_cargo_payment_rates_desc, 0);
00734 }
00735 
00736 /************************/
00737 /* COMPANY LEAGUE TABLE */
00738 /************************/
00739 
00740 static const StringID _performance_titles[] = {
00741   STR_7066_ENGINEER,
00742   STR_7066_ENGINEER,
00743   STR_7067_TRAFFIC_MANAGER,
00744   STR_7067_TRAFFIC_MANAGER,
00745   STR_7068_TRANSPORT_COORDINATOR,
00746   STR_7068_TRANSPORT_COORDINATOR,
00747   STR_7069_ROUTE_SUPERVISOR,
00748   STR_7069_ROUTE_SUPERVISOR,
00749   STR_706A_DIRECTOR,
00750   STR_706A_DIRECTOR,
00751   STR_706B_CHIEF_EXECUTIVE,
00752   STR_706B_CHIEF_EXECUTIVE,
00753   STR_706C_CHAIRMAN,
00754   STR_706C_CHAIRMAN,
00755   STR_706D_PRESIDENT,
00756   STR_706E_TYCOON,
00757 };
00758 
00759 static inline StringID GetPerformanceTitleFromValue(uint value)
00760 {
00761   return _performance_titles[minu(value, 1000) >> 6];
00762 }
00763 
00764 class CompanyLeagueWindow : public Window {
00765 private:
00766   GUIList<const Company*> companies;
00767 
00771   void BuildCompanyList()
00772   {
00773     if (!this->companies.NeedRebuild()) return;
00774 
00775     this->companies.Clear();
00776 
00777     const Company *c;
00778     FOR_ALL_COMPANIES(c) {
00779       *this->companies.Append() = c;
00780     }
00781 
00782     this->companies.Compact();
00783     this->companies.RebuildDone();
00784   }
00785 
00787   static int CDECL PerformanceSorter(const Company * const *c1, const Company * const *c2)
00788   {
00789     return (*c2)->old_economy[1].performance_history - (*c1)->old_economy[1].performance_history;
00790   }
00791 
00792 public:
00793   CompanyLeagueWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
00794   {
00795     this->companies.ForceRebuild();
00796     this->companies.NeedResort();
00797 
00798     this->FindWindowPlacementAndResize(desc);
00799   }
00800 
00801   virtual void OnPaint()
00802   {
00803     this->BuildCompanyList();
00804     this->companies.Sort(&PerformanceSorter);
00805 
00806     this->DrawWidgets();
00807 
00808     for (uint i = 0; i != this->companies.Length(); i++) {
00809       const Company *c = this->companies[i];
00810       SetDParam(0, i + STR_01AC_1ST);
00811       SetDParam(1, c->index);
00812       SetDParam(2, c->index);
00813       SetDParam(3, GetPerformanceTitleFromValue(c->old_economy[1].performance_history));
00814 
00815       DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING);
00816       DrawCompanyIcon(c->index, 27, 16 + i * 10);
00817     }
00818   }
00819 
00820   virtual void OnTick()
00821   {
00822     if (this->companies.NeedResort()) {
00823       this->SetDirty();
00824     }
00825   }
00826 
00827   virtual void OnInvalidateData(int data)
00828   {
00829     if (data == 0) {
00830       this->companies.ForceRebuild();
00831     } else {
00832       this->companies.ForceResort();
00833     }
00834   }
00835 };
00836 
00837 
00838 static const Widget _company_league_widgets[] = {
00839 {   WWT_CLOSEBOX, RESIZE_NONE,  COLOUR_GREY,   0,  10,  0,  13, STR_00C5,                      STR_018B_CLOSE_WINDOW},
00840 {    WWT_CAPTION, RESIZE_NONE,  COLOUR_GREY,  11, 387,  0,  13, STR_7053_COMPANY_LEAGUE_TABLE, STR_018C_WINDOW_TITLE_DRAG_THIS},
00841 {  WWT_STICKYBOX, RESIZE_NONE,  COLOUR_GREY, 388, 399,  0,  13, STR_NULL,                      STR_STICKY_BUTTON},
00842 {      WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,   0, 399, 14, 166, 0x0,                           STR_NULL},
00843 {   WIDGETS_END},
00844 };
00845 
00846 static const WindowDesc _company_league_desc(
00847   WDP_AUTO, WDP_AUTO, 400, 167, 400, 167,
00848   WC_COMPANY_LEAGUE, WC_NONE,
00849   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00850   _company_league_widgets
00851 );
00852 
00853 void ShowCompanyLeagueTable()
00854 {
00855   AllocateWindowDescFront<CompanyLeagueWindow>(&_company_league_desc, 0);
00856 }
00857 
00858 /*****************************/
00859 /* PERFORMANCE RATING DETAIL */
00860 /*****************************/
00861 
00862 struct PerformanceRatingDetailWindow : Window {
00863 private:
00864   enum PerformanteRatingWidgets {
00865     PRW_COMPANY_FIRST = 13,
00866     PRW_COMPANY_LAST  = PRW_COMPANY_FIRST + MAX_COMPANIES - 1,
00867   };
00868 
00869 public:
00870   static CompanyID company;
00871   int timeout;
00872 
00873   PerformanceRatingDetailWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
00874   {
00875     /* Disable the companies who are not active */
00876     for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00877       this->SetWidgetDisabledState(i + PRW_COMPANY_FIRST, !IsValidCompanyID(i));
00878     }
00879 
00880     this->UpdateCompanyStats();
00881 
00882     if (company != INVALID_COMPANY) this->LowerWidget(company + PRW_COMPANY_FIRST);
00883 
00884     this->FindWindowPlacementAndResize(desc);
00885   }
00886 
00887   void UpdateCompanyStats()
00888   {
00889     /* Update all company stats with the current data
00890      * (this is because _score_info is not saved to a savegame) */
00891     Company *c;
00892     FOR_ALL_COMPANIES(c) {
00893       UpdateCompanyRatingAndValue(c, false);
00894     }
00895 
00896     this->timeout = DAY_TICKS * 5;
00897 
00898   }
00899 
00900   virtual void OnPaint()
00901   {
00902     byte x;
00903     uint16 y = 27;
00904     int total_score = 0;
00905     int colour_done, colour_notdone;
00906 
00907     /* Draw standard stuff */
00908     this->DrawWidgets();
00909 
00910     /* Check if the currently selected company is still active. */
00911     if (company == INVALID_COMPANY || !IsValidCompanyID(company)) {
00912       if (company != INVALID_COMPANY) {
00913         /* Raise and disable the widget for the previous selection. */
00914         this->RaiseWidget(company + PRW_COMPANY_FIRST);
00915         this->DisableWidget(company + PRW_COMPANY_FIRST);
00916         this->SetDirty();
00917 
00918         company = INVALID_COMPANY;
00919       }
00920 
00921       for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00922         if (IsValidCompanyID(i)) {
00923           /* Lower the widget corresponding to this company. */
00924           this->LowerWidget(i + PRW_COMPANY_FIRST);
00925           this->SetDirty();
00926 
00927           company = i;
00928           break;
00929         }
00930       }
00931     }
00932 
00933     /* If there are no active companies, don't display anything else. */
00934     if (company == INVALID_COMPANY) return;
00935 
00936     /* Paint the company icons */
00937     for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00938       if (!IsValidCompanyID(i)) {
00939         /* Check if we have the company as an active company */
00940         if (!this->IsWidgetDisabled(i + PRW_COMPANY_FIRST)) {
00941           /* Bah, company gone :( */
00942           this->DisableWidget(i + PRW_COMPANY_FIRST);
00943 
00944           /* We need a repaint */
00945           this->SetDirty();
00946         }
00947         continue;
00948       }
00949 
00950       /* Check if we have the company marked as inactive */
00951       if (this->IsWidgetDisabled(i + PRW_COMPANY_FIRST)) {
00952         /* New company! Yippie :p */
00953         this->EnableWidget(i + PRW_COMPANY_FIRST);
00954         /* We need a repaint */
00955         this->SetDirty();
00956       }
00957 
00958       x = (i == company) ? 1 : 0;
00959       DrawCompanyIcon(i, (i % 8) * 37 + 13 + x, (i < 8 ? 0 : 13) + 16 + x);
00960     }
00961 
00962     /* The colours used to show how the progress is going */
00963     colour_done = _colour_gradient[COLOUR_GREEN][4];
00964     colour_notdone = _colour_gradient[COLOUR_RED][4];
00965 
00966     /* Draw all the score parts */
00967     for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
00968       int val    = _score_part[company][i];
00969       int needed = _score_info[i].needed;
00970       int score  = _score_info[i].score;
00971 
00972       y += 20;
00973       /* SCORE_TOTAL has his own rulez ;) */
00974       if (i == SCORE_TOTAL) {
00975         needed = total_score;
00976         score = SCORE_MAX;
00977       } else {
00978         total_score += score;
00979       }
00980 
00981       DrawString(7, y, STR_PERFORMANCE_DETAIL_VEHICLES + i, TC_FROMSTRING);
00982 
00983       /* Draw the score */
00984       SetDParam(0, score);
00985       DrawStringRightAligned(107, y, STR_PERFORMANCE_DETAIL_INT, TC_FROMSTRING);
00986 
00987       /* Calculate the %-bar */
00988       x = Clamp(val, 0, needed) * 50 / needed;
00989 
00990       /* SCORE_LOAN is inversed */
00991       if (val < 0 && i == SCORE_LOAN) x = 0;
00992 
00993       /* Draw the bar */
00994       if (x !=  0) GfxFillRect(112,     y - 2, 112 + x,  y + 10, colour_done);
00995       if (x != 50) GfxFillRect(112 + x, y - 2, 112 + 50, y + 10, colour_notdone);
00996 
00997       /* Calculate the % */
00998       x = Clamp(val, 0, needed) * 100 / needed;
00999 
01000       /* SCORE_LOAN is inversed */
01001       if (val < 0 && i == SCORE_LOAN) x = 0;
01002 
01003       /* Draw it */
01004       SetDParam(0, x);
01005       DrawStringCentered(137, y, STR_PERFORMANCE_DETAIL_PERCENT, TC_FROMSTRING);
01006 
01007       /* SCORE_LOAN is inversed */
01008       if (i == SCORE_LOAN) val = needed - val;
01009 
01010       /* Draw the amount we have against what is needed
01011        * For some of them it is in currency format */
01012       SetDParam(0, val);
01013       SetDParam(1, needed);
01014       switch (i) {
01015         case SCORE_MIN_PROFIT:
01016         case SCORE_MIN_INCOME:
01017         case SCORE_MAX_INCOME:
01018         case SCORE_MONEY:
01019         case SCORE_LOAN:
01020           DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY, TC_FROMSTRING);
01021           break;
01022         default:
01023           DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_INT, TC_FROMSTRING);
01024       }
01025     }
01026   }
01027 
01028   virtual void OnClick(Point pt, int widget)
01029   {
01030     /* Check which button is clicked */
01031     if (IsInsideMM(widget, PRW_COMPANY_FIRST, PRW_COMPANY_LAST + 1)) {
01032       /* Is it no on disable? */
01033       if (!this->IsWidgetDisabled(widget)) {
01034         this->RaiseWidget(company + PRW_COMPANY_FIRST);
01035         company = (CompanyID)(widget - PRW_COMPANY_FIRST);
01036         this->LowerWidget(company + PRW_COMPANY_FIRST);
01037         this->SetDirty();
01038       }
01039     }
01040   }
01041 
01042   virtual void OnTick()
01043   {
01044     if (_pause_game != 0) return;
01045 
01046     /* Update the company score every 5 days */
01047     if (--this->timeout == 0) {
01048       this->UpdateCompanyStats();
01049       this->SetDirty();
01050     }
01051   }
01052 };
01053 
01054 CompanyID PerformanceRatingDetailWindow::company = INVALID_COMPANY;
01055 
01056 
01057 static const Widget _performance_rating_detail_widgets[] = {
01058 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
01059 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   298,     0,    13, STR_PERFORMANCE_DETAIL, STR_018C_WINDOW_TITLE_DRAG_THIS},
01060 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,    14,    40, 0x0,                    STR_NULL},
01061 
01062 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,    41,    60, 0x0,                    STR_PERFORMANCE_DETAIL_VEHICLES_TIP},
01063 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,    61,    80, 0x0,                    STR_PERFORMANCE_DETAIL_STATIONS_TIP},
01064 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,    81,   100, 0x0,                    STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP},
01065 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   101,   120, 0x0,                    STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP},
01066 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   121,   140, 0x0,                    STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP},
01067 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   141,   160, 0x0,                    STR_PERFORMANCE_DETAIL_DELIVERED_TIP},
01068 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   161,   180, 0x0,                    STR_PERFORMANCE_DETAIL_CARGO_TIP},
01069 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   181,   200, 0x0,                    STR_PERFORMANCE_DETAIL_MONEY_TIP},
01070 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   201,   220, 0x0,                    STR_PERFORMANCE_DETAIL_LOAN_TIP},
01071 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   221,   240, 0x0,                    STR_PERFORMANCE_DETAIL_TOTAL_TIP},
01072 
01073 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,    38,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01074 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    39,    75,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01075 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    76,   112,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01076 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   113,   149,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01077 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   150,   186,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01078 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   187,   223,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01079 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   224,   260,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01080 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   261,   297,    14,    26, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01081 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,    38,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01082 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    39,    75,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01083 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    76,   112,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01084 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   113,   149,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01085 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   150,   186,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01086 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   187,   223,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01087 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   224,   260,    27,    39, 0x0,                    STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
01088 {   WIDGETS_END},
01089 };
01090 
01091 static const WindowDesc _performance_rating_detail_desc(
01092   WDP_AUTO, WDP_AUTO, 299, 241, 299, 241,
01093   WC_PERFORMANCE_DETAIL, WC_NONE,
01094   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
01095   _performance_rating_detail_widgets
01096 );
01097 
01098 void ShowPerformanceRatingDetail()
01099 {
01100   AllocateWindowDescFront<PerformanceRatingDetailWindow>(&_performance_rating_detail_desc, 0);
01101 }

Generated on Thu Oct 1 11:03:13 2009 for OpenTTD by  doxygen 1.5.6