company_gui.cpp

Go to the documentation of this file.
00001 /* $Id: company_gui.cpp 14815 2009-01-03 18:44:20Z smatz $ */
00002 
00005 #include "stdafx.h"
00006 #include "gui.h"
00007 #include "window_gui.h"
00008 #include "textbuf_gui.h"
00009 #include "viewport_func.h"
00010 #include "gfx_func.h"
00011 #include "company_func.h"
00012 #include "company_base.h"
00013 #include "command_func.h"
00014 #include "network/network.h"
00015 #include "network/network_gui.h"
00016 #include "variables.h"
00017 #include "roadveh.h"
00018 #include "train.h"
00019 #include "aircraft.h"
00020 #include "newgrf.h"
00021 #include "company_manager_face.h"
00022 #include "strings_func.h"
00023 #include "functions.h"
00024 #include "window_func.h"
00025 #include "date_func.h"
00026 #include "string_func.h"
00027 #include "settings_type.h"
00028 #include "widgets/dropdown_func.h"
00029 #include "widgets/dropdown_type.h"
00030 #include "tilehighlight_func.h"
00031 #include "highscore.h"
00032 
00033 #include "table/sprites.h"
00034 #include "table/strings.h"
00035 
00036 enum {
00037   FIRST_GUI_CALL = INT_MAX,  
00038 };
00039 
00040 static void DoShowCompanyFinances(CompanyID company, bool show_small, bool show_stickied, int top = FIRST_GUI_CALL, int left = FIRST_GUI_CALL);
00041 static void DoSelectCompanyManagerFace(Window *parent, bool show_big, int top =  FIRST_GUI_CALL, int left = FIRST_GUI_CALL);
00042 
00043 static void DrawCompanyEconomyStats(const Company *c, bool small)
00044 {
00045   int x, y, i, j, year;
00046   const Money (*tbl)[EXPENSES_END];
00047   Money sum, cost;
00048   StringID str;
00049 
00050   if (!small) { // normal sized economics window
00051     /* draw categories */
00052     DrawStringCenterUnderline(61, 15, STR_700F_EXPENDITURE_INCOME, TC_FROMSTRING);
00053     for (i = 0; i != EXPENSES_END; i++)
00054       DrawString(2, 27 + i * 10, STR_7011_CONSTRUCTION + i, TC_FROMSTRING);
00055     DrawStringRightAligned(111, 27 + 10 * EXPENSES_END + 2, STR_7020_TOTAL, TC_FROMSTRING);
00056 
00057     /* draw the price columns */
00058     year = _cur_year - 2;
00059     j = 3;
00060     x = 215;
00061     tbl = c->yearly_expenses + 2;
00062     do {
00063       if (year >= c->inaugurated_year) {
00064         SetDParam(0, year);
00065         DrawStringRightAlignedUnderline(x, 15, STR_7010, TC_FROMSTRING);
00066         sum = 0;
00067         for (i = 0; i != EXPENSES_END; i++) {
00068           /* draw one row in the price column */
00069           cost = (*tbl)[i];
00070           if (cost != 0) {
00071             sum += cost;
00072 
00073             str = STR_701E;
00074             if (cost < 0) { cost = -cost; str++; }
00075             SetDParam(0, cost);
00076             DrawStringRightAligned(x, 27 + i * 10, str, TC_FROMSTRING);
00077           }
00078         }
00079 
00080         str = STR_701E;
00081         if (sum < 0) { sum = -sum; str++; }
00082         SetDParam(0, sum);
00083         DrawStringRightAligned(x, 27 + EXPENSES_END * 10 + 2, str, TC_FROMSTRING);
00084 
00085         GfxFillRect(x - 75, 27 + 10 * EXPENSES_END, x, 27 + 10 * EXPENSES_END, 215);
00086         x += 95;
00087       }
00088       year++;
00089       tbl--;
00090     } while (--j != 0);
00091 
00092     y = 27 + 10 * EXPENSES_END + 14;
00093 
00094     /* draw max loan aligned to loan below (y += 10) */
00095     SetDParam(0, _economy.max_loan);
00096     DrawString(202, y + 10, STR_MAX_LOAN, TC_FROMSTRING);
00097   } else {
00098     y = 15;
00099   }
00100 
00101   DrawString(2, y, STR_7026_BANK_BALANCE, TC_FROMSTRING);
00102   SetDParam(0, c->money);
00103   DrawStringRightAligned(182, y, STR_7028, TC_FROMSTRING);
00104 
00105   y += 10;
00106 
00107   DrawString(2, y, STR_7027_LOAN, TC_FROMSTRING);
00108   SetDParam(0, c->current_loan);
00109   DrawStringRightAligned(182, y, STR_7028, TC_FROMSTRING);
00110 
00111   y += 12;
00112 
00113   GfxFillRect(182 - 75, y - 2, 182, y - 2, 215);
00114 
00115   SetDParam(0, c->money - c->current_loan);
00116   DrawStringRightAligned(182, y, STR_7028, TC_FROMSTRING);
00117 }
00118 
00119 enum CompanyFinancesWindowWidgets {
00120   CFW_WIDGET_TOGGLE_SIZE   = 2,
00121   CFW_WIDGET_INCREASE_LOAN = 6,
00122   CFW_WIDGET_REPAY_LOAN    = 7,
00123 };
00124 
00125 static const Widget _company_finances_widgets[] = {
00126 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
00127 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   379,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
00128 {     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,   380,   394,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
00129 {  WWT_STICKYBOX,   RESIZE_NONE,  COLOUR_GREY,   395,   406,     0,    13, 0x0,                    STR_STICKY_BUTTON},
00130 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   406,    14, 39 + 10 * EXPENSES_END, 0x0,    STR_NULL},
00131 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   406, 40 + 10 * EXPENSES_END, 73 + 10 * EXPENSES_END, 0x0, STR_NULL},
00132 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,   202, 74 + 10 * EXPENSES_END, 85 + 10 * EXPENSES_END, STR_7029_BORROW,        STR_7035_INCREASE_SIZE_OF_LOAN},
00133 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   203,   406, 74 + 10 * EXPENSES_END, 85 + 10 * EXPENSES_END, STR_702A_REPAY,         STR_7036_REPAY_PART_OF_LOAN},
00134 {   WIDGETS_END},
00135 };
00136 
00137 static const Widget _company_finances_small_widgets[] = {
00138 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
00139 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   253,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
00140 {     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,   254,   267,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
00141 {  WWT_STICKYBOX,   RESIZE_NONE,  COLOUR_GREY,   268,   279,     0,    13, 0x0,                    STR_STICKY_BUTTON},
00142 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,     0, 0x0,                    STR_NULL},
00143 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   279,    14,    47, STR_NULL,               STR_NULL},
00144 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,   139,    48,    59, STR_7029_BORROW,        STR_7035_INCREASE_SIZE_OF_LOAN},
00145 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   140,   279,    48,    59, STR_702A_REPAY,         STR_7036_REPAY_PART_OF_LOAN},
00146 {   WIDGETS_END},
00147 };
00148 
00149 struct CompanyFinancesWindow : Window {
00150   bool small;
00151 
00152   CompanyFinancesWindow(const WindowDesc *desc, CompanyID company, bool show_small,
00153           bool show_stickied, int top, int left) :
00154       Window(desc, company),
00155       small(show_small)
00156   {
00157     this->caption_color = this->window_number;
00158 
00159     if (show_stickied) this->flags4 |= WF_STICKY;
00160 
00161     /* Check if repositioning from default is required */
00162     if (top != FIRST_GUI_CALL && left != FIRST_GUI_CALL) {
00163       this->top = top;
00164       this->left = left;
00165     }
00166 
00167     this->FindWindowPlacementAndResize(desc);
00168   }
00169 
00170   virtual void OnPaint()
00171   {
00172     CompanyID company = (CompanyID)this->window_number;
00173     const Company *c = GetCompany(company);
00174 
00175     /* Recheck the size of the window as it might need to be resized due to the local company changing */
00176     int new_height = ((company != _local_company) ? 0 : 12) + ((this->small != 0) ? 48 : 74 + 10 * EXPENSES_END);
00177     if (this->height != new_height) {
00178       /* Make window dirty before and after resizing */
00179       this->SetDirty();
00180       this->height = new_height;
00181       this->SetDirty();
00182 
00183       this->SetWidgetHiddenState(CFW_WIDGET_INCREASE_LOAN, company != _local_company);
00184       this->SetWidgetHiddenState(CFW_WIDGET_REPAY_LOAN,    company != _local_company);
00185     }
00186 
00187     /* Borrow button only shows when there is any more money to loan */
00188     this->SetWidgetDisabledState(CFW_WIDGET_INCREASE_LOAN, c->current_loan == _economy.max_loan);
00189 
00190     /* Repay button only shows when there is any more money to repay */
00191     this->SetWidgetDisabledState(CFW_WIDGET_REPAY_LOAN, company != _local_company || c->current_loan == 0);
00192 
00193     SetDParam(0, c->index);
00194     SetDParam(1, c->index);
00195     SetDParam(2, LOAN_INTERVAL);
00196     this->DrawWidgets();
00197 
00198     DrawCompanyEconomyStats(c, this->small);
00199   }
00200 
00201   virtual void OnClick(Point pt, int widget)
00202   {
00203     switch (widget) {
00204       case CFW_WIDGET_TOGGLE_SIZE: {/* toggle size */
00205         bool new_mode = !this->small;
00206         bool stickied = !!(this->flags4 & WF_STICKY);
00207         int oldtop = this->top;   
00208         int oldleft = this->left; 
00209         CompanyID company = (CompanyID)this->window_number;
00210 
00211         delete this;
00212         /* Open up the (toggled size) Finance window at the same position as the previous */
00213         DoShowCompanyFinances(company, new_mode, stickied, oldtop, oldleft);
00214       }
00215       break;
00216 
00217       case CFW_WIDGET_INCREASE_LOAN: /* increase loan */
00218         DoCommandP(0, 0, _ctrl_pressed, CMD_INCREASE_LOAN | CMD_MSG(STR_702C_CAN_T_BORROW_ANY_MORE_MONEY));
00219         break;
00220 
00221       case CFW_WIDGET_REPAY_LOAN: /* repay loan */
00222         DoCommandP(0, 0, _ctrl_pressed, CMD_DECREASE_LOAN | CMD_MSG(STR_702F_CAN_T_REPAY_LOAN));
00223         break;
00224     }
00225   }
00226 };
00227 
00228 static const WindowDesc _company_finances_desc = {
00229   WDP_AUTO, WDP_AUTO, 407, 86 + 10 * EXPENSES_END, 407, 86 + 10 * EXPENSES_END,
00230   WC_FINANCES, WC_NONE,
00231   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
00232   _company_finances_widgets,
00233 };
00234 
00235 static const WindowDesc _company_finances_small_desc = {
00236   WDP_AUTO, WDP_AUTO, 280, 60, 280, 60,
00237   WC_FINANCES, WC_NONE,
00238   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
00239   _company_finances_small_widgets,
00240 };
00241 
00253 static void DoShowCompanyFinances(CompanyID company, bool show_small, bool show_stickied, int top, int left)
00254 {
00255   if (!IsValidCompanyID(company)) return;
00256 
00257   if (BringWindowToFrontById(WC_FINANCES, company)) return;
00258   new CompanyFinancesWindow(show_small ? &_company_finances_small_desc : &_company_finances_desc, company, show_small, show_stickied, top, left);
00259 }
00260 
00261 void ShowCompanyFinances(CompanyID company)
00262 {
00263   DoShowCompanyFinances(company, false, false);
00264 }
00265 
00266 /* List of colours for the livery window */
00267 static const StringID _colour_dropdown[] = {
00268   STR_00D1_DARK_BLUE,
00269   STR_00D2_PALE_GREEN,
00270   STR_00D3_PINK,
00271   STR_00D4_YELLOW,
00272   STR_00D5_RED,
00273   STR_00D6_LIGHT_BLUE,
00274   STR_00D7_GREEN,
00275   STR_00D8_DARK_GREEN,
00276   STR_00D9_BLUE,
00277   STR_00DA_CREAM,
00278   STR_00DB_MAUVE,
00279   STR_00DC_PURPLE,
00280   STR_00DD_ORANGE,
00281   STR_00DE_BROWN,
00282   STR_00DF_GREY,
00283   STR_00E0_WHITE,
00284 };
00285 
00286 /* Association of liveries to livery classes */
00287 static const LiveryClass _livery_class[LS_END] = {
00288   LC_OTHER,
00289   LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL,
00290   LC_ROAD, LC_ROAD,
00291   LC_SHIP, LC_SHIP,
00292   LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
00293   LC_ROAD, LC_ROAD,
00294 };
00295 
00296 class DropDownListColourItem : public DropDownListItem {
00297 public:
00298   DropDownListColourItem(int result, bool masked) : DropDownListItem(result, masked) {}
00299 
00300   virtual ~DropDownListColourItem() {}
00301 
00302   StringID String() const
00303   {
00304     return _colour_dropdown[this->result];
00305   }
00306 
00307   uint Height(uint width) const
00308   {
00309     return 14;
00310   }
00311 
00312   bool Selectable() const
00313   {
00314     return true;
00315   }
00316 
00317   void Draw(int x, int y, uint width, uint height, bool sel, int bg_colour) const
00318   {
00319     DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOR_START + this->result, x + 16, y + 7);
00320     DrawStringTruncated(x + 32, y + 3, this->String(), sel ? TC_WHITE : TC_BLACK, width - 30);
00321   }
00322 };
00323 
00324 struct SelectCompanyLiveryWindow : public Window {
00325 private:
00326   uint32 sel;
00327   LiveryClass livery_class;
00328 
00329   enum SelectCompanyLiveryWindowWidgets {
00330     SCLW_WIDGET_CLOSE,
00331     SCLW_WIDGET_CAPTION,
00332     SCLW_WIDGET_CLASS_GENERAL,
00333     SCLW_WIDGET_CLASS_RAIL,
00334     SCLW_WIDGET_CLASS_ROAD,
00335     SCLW_WIDGET_CLASS_SHIP,
00336     SCLW_WIDGET_CLASS_AIRCRAFT,
00337     SCLW_WIDGET_SPACER_CLASS,
00338     SCLW_WIDGET_SPACER_DROPDOWN,
00339     SCLW_WIDGET_PRI_COL_DROPDOWN,
00340     SCLW_WIDGET_SEC_COL_DROPDOWN,
00341     SCLW_WIDGET_MATRIX,
00342   };
00343 
00344   void ShowColourDropDownMenu(uint32 widget)
00345   {
00346     uint32 used_colours = 0;
00347     const Livery *livery;
00348     LiveryScheme scheme;
00349 
00350     /* Disallow other company colours for the primary colour */
00351     if (HasBit(this->sel, LS_DEFAULT) && widget == SCLW_WIDGET_PRI_COL_DROPDOWN) {
00352       const Company *c;
00353       FOR_ALL_COMPANIES(c) {
00354         if (c->index != _local_company) SetBit(used_colours, c->colour);
00355       }
00356     }
00357 
00358     /* Get the first selected livery to use as the default dropdown item */
00359     for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
00360       if (HasBit(this->sel, scheme)) break;
00361     }
00362     if (scheme == LS_END) scheme = LS_DEFAULT;
00363     livery = &GetCompany((CompanyID)this->window_number)->livery[scheme];
00364 
00365     DropDownList *list = new DropDownList();
00366     for (uint i = 0; i < lengthof(_colour_dropdown); i++) {
00367       list->push_back(new DropDownListColourItem(i, HasBit(used_colours, i)));
00368     }
00369 
00370     ShowDropDownList(this, list, widget == SCLW_WIDGET_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget);
00371   }
00372 
00373 public:
00374   SelectCompanyLiveryWindow(const WindowDesc *desc, CompanyID company) : Window(desc, company)
00375   {
00376     this->caption_color = company;
00377     this->livery_class = LC_OTHER;
00378     this->sel = 1;
00379     this->LowerWidget(SCLW_WIDGET_CLASS_GENERAL);
00380     this->OnInvalidateData(_loaded_newgrf_features.has_2CC);
00381     this->FindWindowPlacementAndResize(desc);
00382   }
00383 
00384   virtual void OnPaint()
00385   {
00386     const Company *c = GetCompany((CompanyID)this->window_number);
00387     LiveryScheme scheme = LS_DEFAULT;
00388     int y = 51;
00389 
00390     /* Disable dropdown controls if no scheme is selected */
00391     this->SetWidgetDisabledState(SCLW_WIDGET_PRI_COL_DROPDOWN, this->sel == 0);
00392     this->SetWidgetDisabledState(SCLW_WIDGET_SEC_COL_DROPDOWN, this->sel == 0);
00393 
00394     if (this->sel != 0) {
00395       for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
00396         if (HasBit(this->sel, scheme)) break;
00397       }
00398       if (scheme == LS_END) scheme = LS_DEFAULT;
00399     }
00400 
00401     SetDParam(0, STR_00D1_DARK_BLUE + c->livery[scheme].colour1);
00402     SetDParam(1, STR_00D1_DARK_BLUE + c->livery[scheme].colour2);
00403 
00404     this->DrawWidgets();
00405 
00406     for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
00407       if (_livery_class[scheme] == this->livery_class) {
00408         bool sel = HasBit(this->sel, scheme) != 0;
00409 
00410         if (scheme != LS_DEFAULT) {
00411           DrawSprite(c->livery[scheme].in_use ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, 2, y);
00412         }
00413 
00414         DrawString(15, y, STR_LIVERY_DEFAULT + scheme, sel ? TC_WHITE : TC_BLACK);
00415 
00416         DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(c->livery[scheme].colour1), 152, y);
00417         DrawString(165, y, STR_00D1_DARK_BLUE + c->livery[scheme].colour1, sel ? TC_WHITE : TC_GOLD);
00418 
00419         if (!this->IsWidgetHidden(SCLW_WIDGET_SEC_COL_DROPDOWN)) {
00420           DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(c->livery[scheme].colour2), 277, y);
00421           DrawString(290, y, STR_00D1_DARK_BLUE + c->livery[scheme].colour2, sel ? TC_WHITE : TC_GOLD);
00422         }
00423 
00424         y += 14;
00425       }
00426     }
00427   }
00428 
00429   virtual void OnClick(Point pt, int widget)
00430   {
00431     /* Number of liveries in each class, used to determine the height of the livery window */
00432     static const byte livery_height[] = {
00433       1,
00434       13,
00435       4,
00436       2,
00437       3,
00438     };
00439 
00440     switch (widget) {
00441       /* Livery Class buttons */
00442       case SCLW_WIDGET_CLASS_GENERAL:
00443       case SCLW_WIDGET_CLASS_RAIL:
00444       case SCLW_WIDGET_CLASS_ROAD:
00445       case SCLW_WIDGET_CLASS_SHIP:
00446       case SCLW_WIDGET_CLASS_AIRCRAFT: {
00447         LiveryScheme scheme;
00448 
00449         this->RaiseWidget(this->livery_class + SCLW_WIDGET_CLASS_GENERAL);
00450         this->livery_class = (LiveryClass)(widget - SCLW_WIDGET_CLASS_GENERAL);
00451         this->sel = 0;
00452         this->LowerWidget(this->livery_class + SCLW_WIDGET_CLASS_GENERAL);
00453 
00454         /* Select the first item in the list */
00455         for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
00456           if (_livery_class[scheme] == this->livery_class) {
00457             this->sel = 1 << scheme;
00458             break;
00459           }
00460         }
00461         this->height = 49 + livery_height[this->livery_class] * 14;
00462         this->widget[SCLW_WIDGET_MATRIX].bottom = this->height - 1;
00463         this->widget[SCLW_WIDGET_MATRIX].data = livery_height[this->livery_class] << 8 | 1;
00464         MarkWholeScreenDirty();
00465         break;
00466       }
00467 
00468       case SCLW_WIDGET_PRI_COL_DROPDOWN: /* First colour dropdown */
00469         ShowColourDropDownMenu(SCLW_WIDGET_PRI_COL_DROPDOWN);
00470         break;
00471 
00472       case SCLW_WIDGET_SEC_COL_DROPDOWN: /* Second colour dropdown */
00473         ShowColourDropDownMenu(SCLW_WIDGET_SEC_COL_DROPDOWN);
00474         break;
00475 
00476       case SCLW_WIDGET_MATRIX: {
00477         LiveryScheme scheme;
00478         LiveryScheme j = (LiveryScheme)((pt.y - 48) / 14);
00479 
00480         for (scheme = LS_BEGIN; scheme <= j; scheme++) {
00481           if (_livery_class[scheme] != this->livery_class) j++;
00482           if (scheme >= LS_END) return;
00483         }
00484         if (j >= LS_END) return;
00485 
00486         /* If clicking on the left edge, toggle using the livery */
00487         if (pt.x < 10) {
00488           DoCommandP(0, j | (2 << 8), !GetCompany((CompanyID)this->window_number)->livery[j].in_use, CMD_SET_COMPANY_COLOR);
00489         }
00490 
00491         if (_ctrl_pressed) {
00492           ToggleBit(this->sel, j);
00493         } else {
00494           this->sel = 1 << j;
00495         }
00496         this->SetDirty();
00497         break;
00498       }
00499     }
00500   }
00501 
00502   virtual void OnDropdownSelect(int widget, int index)
00503   {
00504     for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
00505       if (HasBit(this->sel, scheme)) {
00506         DoCommandP(0, scheme | (widget == SCLW_WIDGET_PRI_COL_DROPDOWN ? 0 : 256), index, CMD_SET_COMPANY_COLOR);
00507       }
00508     }
00509   }
00510 
00511   virtual void OnInvalidateData(int data = 0)
00512   {
00513     static bool has2cc = true;
00514 
00515     if (has2cc == !!data) return;
00516 
00517     has2cc = !!data;
00518 
00519     int r = this->widget[has2cc ? SCLW_WIDGET_SEC_COL_DROPDOWN : SCLW_WIDGET_PRI_COL_DROPDOWN].right;
00520     this->SetWidgetHiddenState(SCLW_WIDGET_SEC_COL_DROPDOWN, !has2cc);
00521     this->widget[SCLW_WIDGET_CAPTION].right = r;
00522     this->widget[SCLW_WIDGET_SPACER_CLASS].right = r;
00523     this->widget[SCLW_WIDGET_MATRIX].right = r;
00524     this->width = r + 1;
00525   }
00526 };
00527 
00528 static const Widget _select_company_livery_widgets[] = {
00529 { WWT_CLOSEBOX, RESIZE_NONE,  COLOUR_GREY,   0,  10,   0,  13, STR_00C5,                  STR_018B_CLOSE_WINDOW },
00530 {  WWT_CAPTION, RESIZE_NONE,  COLOUR_GREY,  11, 399,   0,  13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS },
00531 {   WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,   0,  21,  14,  35, SPR_IMG_COMPANY_GENERAL,   STR_LIVERY_GENERAL_TIP },
00532 {   WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,  22,  43,  14,  35, SPR_IMG_TRAINLIST,         STR_LIVERY_TRAIN_TIP },
00533 {   WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,  44,  65,  14,  35, SPR_IMG_TRUCKLIST,         STR_LIVERY_ROADVEH_TIP },
00534 {   WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,  66,  87,  14,  35, SPR_IMG_SHIPLIST,          STR_LIVERY_SHIP_TIP },
00535 {   WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,  88, 109,  14,  35, SPR_IMG_AIRPLANESLIST,     STR_LIVERY_AIRCRAFT_TIP },
00536 {    WWT_PANEL, RESIZE_NONE,  COLOUR_GREY, 110, 399,  14,  35, 0x0,                       STR_NULL },
00537 {    WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,   0, 149,  36,  47, 0x0,                       STR_NULL },
00538 { WWT_DROPDOWN, RESIZE_NONE,  COLOUR_GREY, 150, 274,  36,  47, STR_02BD,                  STR_LIVERY_PRIMARY_TIP },
00539 { WWT_DROPDOWN, RESIZE_NONE,  COLOUR_GREY, 275, 399,  36,  47, STR_02E1,                  STR_LIVERY_SECONDARY_TIP },
00540 {   WWT_MATRIX, RESIZE_NONE,  COLOUR_GREY,   0, 399,  48,  48 + 1 * 14, (1 << 8) | 1,     STR_LIVERY_PANEL_TIP },
00541 { WIDGETS_END },
00542 };
00543 
00544 static const WindowDesc _select_company_livery_desc = {
00545   WDP_AUTO, WDP_AUTO, 400, 49 + 1 * 14, 400, 49 + 1 * 14,
00546   WC_COMPANY_COLOR, WC_NONE,
00547   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00548   _select_company_livery_widgets,
00549 };
00550 
00558 void DrawCompanyManagerFace(CompanyManagerFace cmf, int color, int x, int y)
00559 {
00560   GenderEthnicity ge = (GenderEthnicity)GetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, GE_WM);
00561 
00562   bool has_moustache   = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE,   ge) != 0;
00563   bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
00564   bool has_glasses     = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
00565   SpriteID pal;
00566 
00567   /* Modify eye colour palette only if 2 or more valid values exist */
00568   if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
00569     pal = PAL_NONE;
00570   } else {
00571     switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
00572       default: NOT_REACHED();
00573       case 0: pal = PALETTE_TO_BROWN; break;
00574       case 1: pal = PALETTE_TO_BLUE;  break;
00575       case 2: pal = PALETTE_TO_GREEN; break;
00576     }
00577   }
00578 
00579   /* Draw the gradient (background) */
00580   DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOR(color), x, y);
00581 
00582   for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
00583     switch (cmfv) {
00584       case CMFV_MOUSTACHE:   if (!has_moustache)   continue; break;
00585       case CMFV_LIPS:        /* FALL THROUGH */
00586       case CMFV_NOSE:        if (has_moustache)    continue; break;
00587       case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
00588       case CMFV_GLASSES:     if (!has_glasses)     continue; break;
00589       default: break;
00590     }
00591     DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
00592   }
00593 }
00594 
00596 static const Widget _select_company_manager_face_widgets[] = {
00597 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},              // SCMFW_WIDGET_CLOSEBOX
00598 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   174,     0,    13, STR_7043_FACE_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},    // SCMFW_WIDGET_CAPTION
00599 {     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,   175,   189,     0,    13, SPR_LARGE_SMALL_WINDOW,  STR_FACE_ADVANCED_TIP},              // SCMFW_WIDGET_TOGGLE_LARGE_SMALL
00600 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   189,    14,   150, 0x0,                     STR_NULL},                           // SCMFW_WIDGET_SELECT_FACE
00601 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,    94,   151,   162, STR_012E_CANCEL,         STR_7047_CANCEL_NEW_FACE_SELECTION}, // SCMFW_WIDGET_CANCEL
00602 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   189,   151,   162, STR_012F_OK,             STR_7048_ACCEPT_NEW_FACE_SELECTION}, // SCMFW_WIDGET_ACCEPT
00603 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   187,    75,    86, STR_7044_MALE,           STR_7049_SELECT_MALE_FACES},         // SCMFW_WIDGET_MALE
00604 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   187,    87,    98, STR_7045_FEMALE,         STR_704A_SELECT_FEMALE_FACES},       // SCMFW_WIDGET_FEMALE
00605 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     2,    93,   137,   148, STR_7046_NEW_FACE,       STR_704B_GENERATE_RANDOM_NEW_FACE},  // SCMFW_WIDGET_RANDOM_NEW_FACE
00606 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   187,    16,    27, STR_FACE_ADVANCED,       STR_FACE_ADVANCED_TIP},              // SCMFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON
00607 {   WIDGETS_END},
00608 };
00609 
00611 static const Widget _select_company_manager_face_adv_widgets[] = {
00612 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},              // SCMFW_WIDGET_CLOSEBOX
00613 {    WWT_CAPTION,   RESIZE_NONE,  COLOUR_GREY,    11,   204,     0,    13, STR_7043_FACE_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},    // SCMFW_WIDGET_CAPTION
00614 {     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,   205,   219,     0,    13, SPR_LARGE_SMALL_WINDOW,  STR_FACE_SIMPLE_TIP},                // SCMFW_WIDGET_TOGGLE_LARGE_SMALL
00615 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   219,    14,   207, 0x0,                     STR_NULL},                           // SCMFW_WIDGET_SELECT_FACE
00616 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,    94,   208,   219, STR_012E_CANCEL,         STR_7047_CANCEL_NEW_FACE_SELECTION}, // SCMFW_WIDGET_CANCEL
00617 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   219,   208,   219, STR_012F_OK,             STR_7048_ACCEPT_NEW_FACE_SELECTION}, // SCMFW_WIDGET_ACCEPT
00618 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,    96,   156,    32,    43, STR_7044_MALE,           STR_7049_SELECT_MALE_FACES},         // SCMFW_WIDGET_MALE
00619 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,   157,   217,    32,    43, STR_7045_FEMALE,         STR_704A_SELECT_FEMALE_FACES},       // SCMFW_WIDGET_FEMALE
00620 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     2,    93,   137,   148, STR_RANDOM,              STR_704B_GENERATE_RANDOM_NEW_FACE},  // SCMFW_WIDGET_RANDOM_NEW_FACE
00621 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    95,   217,    16,    27, STR_FACE_SIMPLE,         STR_FACE_SIMPLE_TIP},                // SCMFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON
00622 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     2,    93,   158,   169, STR_FACE_LOAD,           STR_FACE_LOAD_TIP},                  // SCMFW_WIDGET_LOAD
00623 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     2,    93,   170,   181, STR_FACE_FACECODE,       STR_FACE_FACECODE_TIP},              // SCMFW_WIDGET_FACECODE
00624 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     2,    93,   182,   193, STR_FACE_SAVE,           STR_FACE_SAVE_TIP},                  // SCMFW_WIDGET_SAVE
00625 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,    96,   156,    46,    57, STR_FACE_EUROPEAN,       STR_FACE_SELECT_EUROPEAN},           // SCMFW_WIDGET_ETHNICITY_EUR
00626 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,   157,   217,    46,    57, STR_FACE_AFRICAN,        STR_FACE_SELECT_AFRICAN},            // SCMFW_WIDGET_ETHNICITY_AFR
00627 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   175,   217,    60,    71, STR_EMPTY,               STR_FACE_MOUSTACHE_EARRING_TIP},     // SCMFW_WIDGET_HAS_MOUSTACHE_EARRING
00628 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   175,   217,    72,    83, STR_EMPTY,               STR_FACE_GLASSES_TIP},               // SCMFW_WIDGET_HAS_GLASSES
00629 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   110,   121, SPR_ARROW_LEFT,          STR_FACE_EYECOLOUR_TIP},             // SCMFW_WIDGET_EYECOLOUR_L
00630 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   110,   121, STR_EMPTY,               STR_FACE_EYECOLOUR_TIP},             // SCMFW_WIDGET_EYECOLOUR
00631 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   110,   121, SPR_ARROW_RIGHT,         STR_FACE_EYECOLOUR_TIP},             // SCMFW_WIDGET_EYECOLOUR_R
00632 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   158,   169, SPR_ARROW_LEFT,          STR_FACE_CHIN_TIP},                  // SCMFW_WIDGET_CHIN_L
00633 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   158,   169, STR_EMPTY,               STR_FACE_CHIN_TIP},                  // SCMFW_WIDGET_CHIN
00634 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   158,   169, SPR_ARROW_RIGHT,         STR_FACE_CHIN_TIP},                  // SCMFW_WIDGET_CHIN_R
00635 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,    98,   109, SPR_ARROW_LEFT,          STR_FACE_EYEBROWS_TIP},              // SCMFW_WIDGET_EYEBROWS_L
00636 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,    98,   109, STR_EMPTY,               STR_FACE_EYEBROWS_TIP},              // SCMFW_WIDGET_EYEBROWS
00637 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,    98,   109, SPR_ARROW_RIGHT,         STR_FACE_EYEBROWS_TIP},              // SCMFW_WIDGET_EYEBROWS_R
00638 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   146,   157, SPR_ARROW_LEFT,          STR_FACE_LIPS_MOUSTACHE_TIP},        // SCMFW_WIDGET_LIPS_MOUSTACHE_L
00639 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   146,   157, STR_EMPTY,               STR_FACE_LIPS_MOUSTACHE_TIP},        // SCMFW_WIDGET_LIPS_MOUSTACHE
00640 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   146,   157, SPR_ARROW_RIGHT,         STR_FACE_LIPS_MOUSTACHE_TIP},        // SCMFW_WIDGET_LIPS_MOUSTACHE_R
00641 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   134,   145, SPR_ARROW_LEFT,          STR_FACE_NOSE_TIP},                  // SCMFW_WIDGET_NOSE_L
00642 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   134,   145, STR_EMPTY,               STR_FACE_NOSE_TIP},                  // SCMFW_WIDGET_NOSE
00643 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   134,   145, SPR_ARROW_RIGHT,         STR_FACE_NOSE_TIP},                  // SCMFW_WIDGET_NOSE_R
00644 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,    86,    97, SPR_ARROW_LEFT,          STR_FACE_HAIR_TIP},                  // SCMFW_WIDGET_HAIR_L
00645 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,    86,    97, STR_EMPTY,               STR_FACE_HAIR_TIP},                  // SCMFW_WIDGET_HAIR
00646 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,    86,    97, SPR_ARROW_RIGHT,         STR_FACE_HAIR_TIP},                  // SCMFW_WIDGET_HAIR_R
00647 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   170,   181, SPR_ARROW_LEFT,          STR_FACE_JACKET_TIP},                // SCMFW_WIDGET_JACKET_L
00648 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   170,   181, STR_EMPTY,               STR_FACE_JACKET_TIP},                // SCMFW_WIDGET_JACKET
00649 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   170,   181, SPR_ARROW_RIGHT,         STR_FACE_JACKET_TIP},                // SCMFW_WIDGET_JACKET_R
00650 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   182,   193, SPR_ARROW_LEFT,          STR_FACE_COLLAR_TIP},                // SCMFW_WIDGET_COLLAR_L
00651 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   182,   193, STR_EMPTY,               STR_FACE_COLLAR_TIP},                // SCMFW_WIDGET_COLLAR
00652 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   182,   193, SPR_ARROW_RIGHT,         STR_FACE_COLLAR_TIP},                // SCMFW_WIDGET_COLLAR_R
00653 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   194,   205, SPR_ARROW_LEFT,          STR_FACE_TIE_EARRING_TIP},           // SCMFW_WIDGET_TIE_EARRING_L
00654 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   194,   205, STR_EMPTY,               STR_FACE_TIE_EARRING_TIP},           // SCMFW_WIDGET_TIE_EARRING
00655 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   194,   205, SPR_ARROW_RIGHT,         STR_FACE_TIE_EARRING_TIP},           // SCMFW_WIDGET_TIE_EARRING_R
00656 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    175,  183,   122,   133, SPR_ARROW_LEFT,          STR_FACE_GLASSES_TIP_2},             // SCMFW_WIDGET_GLASSES_L
00657 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,    184,  208,   122,   133, STR_EMPTY,               STR_FACE_GLASSES_TIP_2},             // SCMFW_WIDGET_GLASSES
00658 { WWT_PUSHIMGBTN,   RESIZE_NONE,  COLOUR_GREY,    209,  217,   122,   133, SPR_ARROW_RIGHT,         STR_FACE_GLASSES_TIP_2},             // SCMFW_WIDGET_GLASSES_R
00659 {   WIDGETS_END},
00660 };
00661 
00662 class SelectCompanyManagerFaceWindow : public Window
00663 {
00664   CompanyManagerFace face; 
00665   bool advanced; 
00666 
00667   GenderEthnicity ge;
00668   bool is_female;
00669   bool is_moust_male;
00670 
00676   enum SelectCompanyManagerFaceWidgets {
00677     SCMFW_WIDGET_CLOSEBOX = 0,
00678     SCMFW_WIDGET_CAPTION,
00679     SCMFW_WIDGET_TOGGLE_LARGE_SMALL,
00680     SCMFW_WIDGET_SELECT_FACE,
00681     SCMFW_WIDGET_CANCEL,
00682     SCMFW_WIDGET_ACCEPT,
00683     SCMFW_WIDGET_MALE,
00684     SCMFW_WIDGET_FEMALE,
00685     SCMFW_WIDGET_RANDOM_NEW_FACE,
00686     SCMFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON,
00687     /* from here is the advanced company manager face selection window */
00688     SCMFW_WIDGET_LOAD,
00689     SCMFW_WIDGET_FACECODE,
00690     SCMFW_WIDGET_SAVE,
00691     SCMFW_WIDGET_ETHNICITY_EUR,
00692     SCMFW_WIDGET_ETHNICITY_AFR,
00693     SCMFW_WIDGET_HAS_MOUSTACHE_EARRING,
00694     SCMFW_WIDGET_HAS_GLASSES,
00695     SCMFW_WIDGET_EYECOLOUR_L,
00696     SCMFW_WIDGET_EYECOLOUR,
00697     SCMFW_WIDGET_EYECOLOUR_R,
00698     SCMFW_WIDGET_CHIN_L,
00699     SCMFW_WIDGET_CHIN,
00700     SCMFW_WIDGET_CHIN_R,
00701     SCMFW_WIDGET_EYEBROWS_L,
00702     SCMFW_WIDGET_EYEBROWS,
00703     SCMFW_WIDGET_EYEBROWS_R,
00704     SCMFW_WIDGET_LIPS_MOUSTACHE_L,
00705     SCMFW_WIDGET_LIPS_MOUSTACHE,
00706     SCMFW_WIDGET_LIPS_MOUSTACHE_R,
00707     SCMFW_WIDGET_NOSE_L,
00708     SCMFW_WIDGET_NOSE,
00709     SCMFW_WIDGET_NOSE_R,
00710     SCMFW_WIDGET_HAIR_L,
00711     SCMFW_WIDGET_HAIR,
00712     SCMFW_WIDGET_HAIR_R,
00713     SCMFW_WIDGET_JACKET_L,
00714     SCMFW_WIDGET_JACKET,
00715     SCMFW_WIDGET_JACKET_R,
00716     SCMFW_WIDGET_COLLAR_L,
00717     SCMFW_WIDGET_COLLAR,
00718     SCMFW_WIDGET_COLLAR_R,
00719     SCMFW_WIDGET_TIE_EARRING_L,
00720     SCMFW_WIDGET_TIE_EARRING,
00721     SCMFW_WIDGET_TIE_EARRING_R,
00722     SCMFW_WIDGET_GLASSES_L,
00723     SCMFW_WIDGET_GLASSES,
00724     SCMFW_WIDGET_GLASSES_R,
00725   };
00734   void DrawFaceStringLabel(byte widget_index, StringID str, uint8 val, bool is_bool_widget)
00735   {
00736     /* Write the label in gold (0x2) to the left of the button. */
00737     DrawStringRightAligned(this->widget[widget_index].left - (is_bool_widget ? 5 : 14), this->widget[widget_index].top + 1, str, TC_GOLD);
00738 
00739     if (!this->IsWidgetDisabled(widget_index)) {
00740       if (is_bool_widget) {
00741         /* if it a bool button write yes or no */
00742         str = (val != 0) ? STR_FACE_YES : STR_FACE_NO;
00743       } else {
00744         /* else write the value + 1 */
00745         SetDParam(0, val + 1);
00746         str = STR_JUST_INT;
00747       }
00748 
00749       /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
00750       DrawStringCentered(this->widget[widget_index].left + (this->widget[widget_index].right - this->widget[widget_index].left) / 2 +
00751         this->IsWidgetLowered(widget_index), this->widget[widget_index].top + 1 + this->IsWidgetLowered(widget_index), str, TC_WHITE);
00752     }
00753   }
00754 
00755   void UpdateData()
00756   {
00757     this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
00758     this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
00759     this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
00760   }
00761 
00762 public:
00763   SelectCompanyManagerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced, int top, int left) : Window(desc, parent->window_number)
00764   {
00765     this->parent = parent;
00766     this->caption_color = this->window_number;
00767     this->face = GetCompany((CompanyID)this->window_number)->face;
00768     this->advanced = advanced;
00769 
00770     this->UpdateData();
00771 
00772     /* Check if repositioning from default is required */
00773     if (top != FIRST_GUI_CALL && left != FIRST_GUI_CALL) {
00774       this->top = top;
00775       this->left = left;
00776     }
00777 
00778     this->FindWindowPlacementAndResize(desc);
00779   }
00780 
00781   virtual void OnPaint()
00782   {
00783     /* lower the non-selected gender button */
00784     this->SetWidgetLoweredState(SCMFW_WIDGET_MALE,  !this->is_female);
00785     this->SetWidgetLoweredState(SCMFW_WIDGET_FEMALE, this->is_female);
00786 
00787     /* advanced company manager face selection window */
00788     if (this->advanced) {
00789       /* lower the non-selected ethnicity button */
00790       this->SetWidgetLoweredState(SCMFW_WIDGET_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
00791       this->SetWidgetLoweredState(SCMFW_WIDGET_ETHNICITY_AFR,  HasBit(this->ge, ETHNICITY_BLACK));
00792 
00793 
00794       /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
00795       * (or in other words you haven't any choice).
00796       * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
00797 
00798       /* Eye colour buttons */
00799       this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
00800         SCMFW_WIDGET_EYECOLOUR, SCMFW_WIDGET_EYECOLOUR_L, SCMFW_WIDGET_EYECOLOUR_R, WIDGET_LIST_END);
00801 
00802       /* Chin buttons */
00803       this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
00804         SCMFW_WIDGET_CHIN, SCMFW_WIDGET_CHIN_L, SCMFW_WIDGET_CHIN_R, WIDGET_LIST_END);
00805 
00806       /* Eyebrows buttons */
00807       this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
00808         SCMFW_WIDGET_EYEBROWS, SCMFW_WIDGET_EYEBROWS_L, SCMFW_WIDGET_EYEBROWS_R, WIDGET_LIST_END);
00809 
00810       /* Lips or (if it a male face with a moustache) moustache buttons */
00811       this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
00812         SCMFW_WIDGET_LIPS_MOUSTACHE, SCMFW_WIDGET_LIPS_MOUSTACHE_L, SCMFW_WIDGET_LIPS_MOUSTACHE_R, WIDGET_LIST_END);
00813 
00814       /* Nose buttons | male faces with moustache haven't any nose options */
00815       this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
00816         SCMFW_WIDGET_NOSE, SCMFW_WIDGET_NOSE_L, SCMFW_WIDGET_NOSE_R, WIDGET_LIST_END);
00817 
00818       /* Hair buttons */
00819       this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
00820         SCMFW_WIDGET_HAIR, SCMFW_WIDGET_HAIR_L, SCMFW_WIDGET_HAIR_R, WIDGET_LIST_END);
00821 
00822       /* Jacket buttons */
00823       this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
00824         SCMFW_WIDGET_JACKET, SCMFW_WIDGET_JACKET_L, SCMFW_WIDGET_JACKET_R, WIDGET_LIST_END);
00825 
00826       /* Collar buttons */
00827       this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
00828         SCMFW_WIDGET_COLLAR, SCMFW_WIDGET_COLLAR_L, SCMFW_WIDGET_COLLAR_R, WIDGET_LIST_END);
00829 
00830       /* Tie/earring buttons | female faces without earring haven't any earring options */
00831       this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
00832           (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
00833         SCMFW_WIDGET_TIE_EARRING, SCMFW_WIDGET_TIE_EARRING_L, SCMFW_WIDGET_TIE_EARRING_R, WIDGET_LIST_END);
00834 
00835       /* Glasses buttons | faces without glasses haven't any glasses options */
00836       this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
00837         SCMFW_WIDGET_GLASSES, SCMFW_WIDGET_GLASSES_L, SCMFW_WIDGET_GLASSES_R, WIDGET_LIST_END);
00838     }
00839 
00840     this->DrawWidgets();
00841 
00842     /* Draw dynamic button value and labels for the advanced company manager face selection window */
00843     if (this->advanced) {
00844       if (this->is_female) {
00845         /* Only for female faces */
00846         this->DrawFaceStringLabel(SCMFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_EARRING,   GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true );
00847         this->DrawFaceStringLabel(SCMFW_WIDGET_TIE_EARRING,           STR_FACE_EARRING,   GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING,     this->ge), false);
00848       } else {
00849         /* Only for male faces */
00850         this->DrawFaceStringLabel(SCMFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_MOUSTACHE,