OpenTTD
company_gui.cpp
Go to the documentation of this file.
1 /* $Id: company_gui.cpp 27893 2017-08-13 18:38:42Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "error.h"
14 #include "gui.h"
15 #include "window_gui.h"
16 #include "textbuf_gui.h"
17 #include "viewport_func.h"
18 #include "company_func.h"
19 #include "command_func.h"
20 #include "network/network.h"
21 #include "network/network_gui.h"
22 #include "network/network_func.h"
23 #include "newgrf.h"
24 #include "company_manager_face.h"
25 #include "strings_func.h"
26 #include "date_func.h"
27 #include "widgets/dropdown_type.h"
28 #include "tilehighlight_func.h"
29 #include "company_base.h"
30 #include "core/geometry_func.hpp"
31 #include "object_type.h"
32 #include "rail.h"
33 #include "engine_base.h"
34 #include "window_func.h"
35 #include "road_func.h"
36 #include "water.h"
37 #include "station_func.h"
38 #include "zoom_func.h"
39 
40 #include "widgets/company_widget.h"
41 
42 #include "safeguards.h"
43 
44 
46 static const uint EXP_LINESPACE = 2;
47 static const uint EXP_BLOCKSPACE = 10;
48 
49 static void DoSelectCompanyManagerFace(Window *parent);
50 static void ShowCompanyInfrastructure(CompanyID company);
51 
67 };
68 
87 };
88 
90 struct ExpensesList {
91  const ExpensesType *et;
92  const uint length;
93  const uint num_subtotals;
94 
95  ExpensesList(ExpensesType *et, int length, int num_subtotals) : et(et), length(length), num_subtotals(num_subtotals)
96  {
97  }
98 
99  uint GetHeight() const
100  {
101  /* heading + line + texts of expenses + sub-totals + total line + total text */
103  }
104 
106  uint GetCategoriesWidth() const
107  {
108  uint width = 0;
109  bool invalid_expenses_measured = false; // Measure 'Total' width only once.
110  for (uint i = 0; i < this->length; i++) {
111  ExpensesType et = this->et[i];
112  if (et == INVALID_EXPENSES) {
113  if (!invalid_expenses_measured) {
114  width = max(width, GetStringBoundingBox(STR_FINANCES_TOTAL_CAPTION).width);
115  invalid_expenses_measured = true;
116  }
117  } else {
118  width = max(width, GetStringBoundingBox(STR_FINANCES_SECTION_CONSTRUCTION + et).width);
119  }
120  }
121  return width;
122  }
123 };
124 
125 static const ExpensesList _expenses_list_types[] = {
128 };
129 
135 static void DrawCategories(const Rect &r)
136 {
137  int y = r.top;
138 
139  DrawString(r.left, r.right, y, STR_FINANCES_EXPENDITURE_INCOME_TITLE, TC_FROMSTRING, SA_HOR_CENTER, true);
141 
143  for (uint i = 0; i < _expenses_list_types[type].length; i++) {
144  const ExpensesType et = _expenses_list_types[type].et[i];
145  if (et == INVALID_EXPENSES) {
146  y += EXP_LINESPACE;
147  DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
149  } else {
150  DrawString(r.left, r.right, y, STR_FINANCES_SECTION_CONSTRUCTION + et);
151  y += FONT_HEIGHT_NORMAL;
152  }
153  }
154 
155  DrawString(r.left, r.right, y + EXP_LINESPACE, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
156 }
157 
165 static void DrawPrice(Money amount, int left, int right, int top)
166 {
167  StringID str = STR_FINANCES_NEGATIVE_INCOME;
168  if (amount < 0) {
169  amount = -amount;
170  str++;
171  }
172  SetDParam(0, amount);
173  DrawString(left, right, top, str, TC_FROMSTRING, SA_RIGHT);
174 }
175 
183 static void DrawYearColumn(const Rect &r, int year, const Money (*tbl)[EXPENSES_END])
184 {
185  int y = r.top;
186 
187  SetDParam(0, year);
188  DrawString(r.left, r.right, y, STR_FINANCES_YEAR, TC_FROMSTRING, SA_RIGHT, true);
190 
191  Money sum = 0;
192  Money subtotal = 0;
194  for (uint i = 0; i < _expenses_list_types[type].length; i++) {
195  const ExpensesType et = _expenses_list_types[type].et[i];
196  if (et == INVALID_EXPENSES) {
197  Money cost = subtotal;
198  subtotal = 0;
199  GfxFillRect(r.left, y, r.right, y, PC_BLACK);
200  y += EXP_LINESPACE;
201  DrawPrice(cost, r.left, r.right, y);
203  } else {
204  Money cost = (*tbl)[et];
205  subtotal += cost;
206  sum += cost;
207  if (cost != 0) DrawPrice(cost, r.left, r.right, y);
208  y += FONT_HEIGHT_NORMAL;
209  }
210  }
211 
212  GfxFillRect(r.left, y, r.right, y, PC_BLACK);
213  y += EXP_LINESPACE;
214  DrawPrice(sum, r.left, r.right, y);
215 }
216 
217 static const NWidgetPart _nested_company_finances_widgets[] = {
219  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
220  NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION), SetDataTip(STR_FINANCES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
221  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW),
222  NWidget(WWT_SHADEBOX, COLOUR_GREY),
223  NWidget(WWT_STICKYBOX, COLOUR_GREY),
224  EndContainer(),
225  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_PANEL),
226  NWidget(WWT_PANEL, COLOUR_GREY),
228  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_CATEGORY), SetMinimalSize(120, 0), SetFill(0, 0),
229  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE1), SetMinimalSize(86, 0), SetFill(0, 0),
230  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE2), SetMinimalSize(86, 0), SetFill(0, 0),
231  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE3), SetMinimalSize(86, 0), SetFill(0, 0),
232  EndContainer(),
233  EndContainer(),
234  EndContainer(),
235  NWidget(WWT_PANEL, COLOUR_GREY),
237  NWidget(NWID_VERTICAL), // Vertical column with 'bank balance', 'loan'
238  NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_FINANCES_BANK_BALANCE_TITLE, STR_NULL), SetFill(1, 0),
239  NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_FINANCES_LOAN_TITLE, STR_NULL), SetFill(1, 0),
240  NWidget(NWID_SPACER), SetFill(0, 1),
241  EndContainer(),
242  NWidget(NWID_SPACER), SetFill(0, 0), SetMinimalSize(30, 0),
243  NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
244  NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_BALANCE_VALUE), SetDataTip(STR_NULL, STR_NULL),
245  NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_LOAN_VALUE), SetDataTip(STR_NULL, STR_NULL),
246  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_LOAN_LINE), SetMinimalSize(0, 2), SetFill(1, 0),
247  NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_TOTAL_VALUE), SetDataTip(STR_NULL, STR_NULL),
248  EndContainer(),
249  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_MAXLOAN),
251  NWidget(NWID_SPACER), SetFill(0, 1), SetMinimalSize(25, 0),
252  NWidget(NWID_VERTICAL), // Max loan information
253  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_MAXLOAN_GAP), SetFill(0, 0),
254  NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_MAXLOAN_VALUE), SetDataTip(STR_FINANCES_MAX_LOAN, STR_NULL),
255  NWidget(NWID_SPACER), SetFill(0, 1),
256  EndContainer(),
257  EndContainer(),
258  EndContainer(),
259  NWidget(NWID_SPACER), SetFill(1, 1),
260  EndContainer(),
261  EndContainer(),
262  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_BUTTONS),
264  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INCREASE_LOAN), SetFill(1, 0), SetDataTip(STR_FINANCES_BORROW_BUTTON, STR_FINANCES_BORROW_TOOLTIP),
265  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_REPAY_LOAN), SetFill(1, 0), SetDataTip(STR_FINANCES_REPAY_BUTTON, STR_FINANCES_REPAY_TOOLTIP),
266  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INFRASTRUCTURE), SetFill(1, 0), SetDataTip(STR_FINANCES_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
267  EndContainer(),
268  EndContainer(),
269 };
270 
276  static Money max_money;
277  bool small;
278 
279  CompanyFinancesWindow(WindowDesc *desc, CompanyID company) : Window(desc)
280  {
281  this->small = false;
282  this->CreateNestedTree();
283  this->SetupWidgets();
284  this->FinishInitNested(company);
285 
286  this->owner = (Owner)this->window_number;
287  }
288 
289  virtual void SetStringParameters(int widget) const
290  {
291  switch (widget) {
292  case WID_CF_CAPTION:
293  SetDParam(0, (CompanyID)this->window_number);
294  SetDParam(1, (CompanyID)this->window_number);
295  break;
296 
298  SetDParam(0, _economy.max_loan);
299  break;
300 
302  case WID_CF_REPAY_LOAN:
304  break;
305  }
306  }
307 
308  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
309  {
311  switch (widget) {
313  size->width = _expenses_list_types[type].GetCategoriesWidth();
314  size->height = _expenses_list_types[type].GetHeight();
315  break;
316 
317  case WID_CF_EXPS_PRICE1:
318  case WID_CF_EXPS_PRICE2:
319  case WID_CF_EXPS_PRICE3:
320  size->height = _expenses_list_types[type].GetHeight();
321  FALLTHROUGH;
322 
324  case WID_CF_LOAN_VALUE:
325  case WID_CF_TOTAL_VALUE:
327  size->width = max(GetStringBoundingBox(STR_FINANCES_NEGATIVE_INCOME).width, GetStringBoundingBox(STR_FINANCES_POSITIVE_INCOME).width) + padding.width;
328  break;
329 
330  case WID_CF_MAXLOAN_GAP:
331  size->height = FONT_HEIGHT_NORMAL;
332  break;
333  }
334  }
335 
336  virtual void DrawWidget(const Rect &r, int widget) const
337  {
338  switch (widget) {
340  DrawCategories(r);
341  break;
342 
343  case WID_CF_EXPS_PRICE1:
344  case WID_CF_EXPS_PRICE2:
345  case WID_CF_EXPS_PRICE3: {
346  const Company *c = Company::Get((CompanyID)this->window_number);
347  int age = min(_cur_year - c->inaugurated_year, 2);
348  int wid_offset = widget - WID_CF_EXPS_PRICE1;
349  if (wid_offset <= age) {
350  DrawYearColumn(r, _cur_year - (age - wid_offset), c->yearly_expenses + (age - wid_offset));
351  }
352  break;
353  }
354 
355  case WID_CF_BALANCE_VALUE: {
356  const Company *c = Company::Get((CompanyID)this->window_number);
357  SetDParam(0, c->money);
358  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
359  break;
360  }
361 
362  case WID_CF_LOAN_VALUE: {
363  const Company *c = Company::Get((CompanyID)this->window_number);
364  SetDParam(0, c->current_loan);
365  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
366  break;
367  }
368 
369  case WID_CF_TOTAL_VALUE: {
370  const Company *c = Company::Get((CompanyID)this->window_number);
371  SetDParam(0, c->money - c->current_loan);
372  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
373  break;
374  }
375 
376  case WID_CF_LOAN_LINE:
377  GfxFillRect(r.left, r.top, r.right, r.top, PC_BLACK);
378  break;
379  }
380  }
381 
387  {
388  int plane = this->small ? SZSP_NONE : 0;
389  this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
390  this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
391 
392  CompanyID company = (CompanyID)this->window_number;
393  plane = (company != _local_company) ? SZSP_NONE : 0;
394  this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
395  }
396 
397  virtual void OnPaint()
398  {
399  if (!this->IsShaded()) {
400  if (!this->small) {
401  /* Check that the expenses panel height matches the height needed for the layout. */
403  if (_expenses_list_types[type].GetHeight() != this->GetWidget<NWidgetBase>(WID_CF_EXPS_CATEGORY)->current_y) {
404  this->SetupWidgets();
405  this->ReInit();
406  return;
407  }
408  }
409 
410  /* Check that the loan buttons are shown only when the user owns the company. */
411  CompanyID company = (CompanyID)this->window_number;
412  int req_plane = (company != _local_company) ? SZSP_NONE : 0;
413  if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
414  this->SetupWidgets();
415  this->ReInit();
416  return;
417  }
418 
419  const Company *c = Company::Get(company);
420  this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan == _economy.max_loan); // Borrow button only shows when there is any more money to loan.
421  this->SetWidgetDisabledState(WID_CF_REPAY_LOAN, company != _local_company || c->current_loan == 0); // Repay button only shows when there is any more money to repay.
422  }
423 
424  this->DrawWidgets();
425  }
426 
427  virtual void OnClick(Point pt, int widget, int click_count)
428  {
429  switch (widget) {
430  case WID_CF_TOGGLE_SIZE: // toggle size
431  this->small = !this->small;
432  this->SetupWidgets();
433  if (this->IsShaded()) {
434  /* Finances window is not resizable, so size hints given during unshading have no effect
435  * on the changed appearance of the window. */
436  this->SetShaded(false);
437  } else {
438  this->ReInit();
439  }
440  break;
441 
442  case WID_CF_INCREASE_LOAN: // increase loan
443  DoCommandP(0, 0, _ctrl_pressed, CMD_INCREASE_LOAN | CMD_MSG(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY));
444  break;
445 
446  case WID_CF_REPAY_LOAN: // repay loan
447  DoCommandP(0, 0, _ctrl_pressed, CMD_DECREASE_LOAN | CMD_MSG(STR_ERROR_CAN_T_REPAY_LOAN));
448  break;
449 
450  case WID_CF_INFRASTRUCTURE: // show infrastructure details
451  ShowCompanyInfrastructure((CompanyID)this->window_number);
452  break;
453  }
454  }
455 
456  virtual void OnHundredthTick()
457  {
458  const Company *c = Company::Get((CompanyID)this->window_number);
461  this->SetupWidgets();
462  this->ReInit();
463  }
464  }
465 };
466 
469 
470 static WindowDesc _company_finances_desc(
471  WDP_AUTO, "company_finances", 0, 0,
473  0,
474  _nested_company_finances_widgets, lengthof(_nested_company_finances_widgets)
475 );
476 
483 {
484  if (!Company::IsValidID(company)) return;
485  if (BringWindowToFrontById(WC_FINANCES, company)) return;
486 
487  new CompanyFinancesWindow(&_company_finances_desc, company);
488 }
489 
490 /* List of colours for the livery window */
491 static const StringID _colour_dropdown[] = {
492  STR_COLOUR_DARK_BLUE,
493  STR_COLOUR_PALE_GREEN,
494  STR_COLOUR_PINK,
495  STR_COLOUR_YELLOW,
496  STR_COLOUR_RED,
497  STR_COLOUR_LIGHT_BLUE,
498  STR_COLOUR_GREEN,
499  STR_COLOUR_DARK_GREEN,
500  STR_COLOUR_BLUE,
501  STR_COLOUR_CREAM,
502  STR_COLOUR_MAUVE,
503  STR_COLOUR_PURPLE,
504  STR_COLOUR_ORANGE,
505  STR_COLOUR_BROWN,
506  STR_COLOUR_GREY,
507  STR_COLOUR_WHITE,
508 };
509 
510 /* Association of liveries to livery classes */
511 static const LiveryClass _livery_class[LS_END] = {
512  LC_OTHER,
513  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,
514  LC_ROAD, LC_ROAD,
515  LC_SHIP, LC_SHIP,
516  LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
517  LC_ROAD, LC_ROAD,
518 };
519 
521 public:
522  DropDownListColourItem(int result, bool masked) : DropDownListItem(result, masked) {}
523 
524  virtual ~DropDownListColourItem() {}
525 
526  StringID String() const
527  {
528  return _colour_dropdown[this->result];
529  }
530 
531  uint Height(uint width) const
532  {
533  return max(FONT_HEIGHT_NORMAL, ScaleGUITrad(12) + 2);
534  }
535 
536  bool Selectable() const
537  {
538  return true;
539  }
540 
541  void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
542  {
543  bool rtl = _current_text_dir == TD_RTL;
544  int height = bottom - top;
545  int icon_y_offset = height / 2;
546  int text_y_offset = (height - FONT_HEIGHT_NORMAL) / 2 + 1;
547  DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOUR_START + this->result,
548  rtl ? right - 2 - ScaleGUITrad(14) : left + ScaleGUITrad(14) + 2,
549  top + icon_y_offset);
550  DrawString(rtl ? left + 2 : left + ScaleGUITrad(28) + 4,
551  rtl ? right - ScaleGUITrad(28) - 4 : right - 2,
552  top + text_y_offset, this->String(), sel ? TC_WHITE : TC_BLACK);
553  }
554 };
555 
558 private:
559  uint32 sel;
560  LiveryClass livery_class;
561  Dimension square;
562  Dimension box;
563  uint line_height;
564 
565  void ShowColourDropDownMenu(uint32 widget)
566  {
567  uint32 used_colours = 0;
568  const Livery *livery;
569  LiveryScheme scheme;
570 
571  /* Disallow other company colours for the primary colour */
572  if (HasBit(this->sel, LS_DEFAULT) && widget == WID_SCL_PRI_COL_DROPDOWN) {
573  const Company *c;
574  FOR_ALL_COMPANIES(c) {
575  if (c->index != _local_company) SetBit(used_colours, c->colour);
576  }
577  }
578 
579  /* Get the first selected livery to use as the default dropdown item */
580  for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
581  if (HasBit(this->sel, scheme)) break;
582  }
583  if (scheme == LS_END) scheme = LS_DEFAULT;
584  livery = &Company::Get((CompanyID)this->window_number)->livery[scheme];
585 
586  DropDownList *list = new DropDownList();
587  for (uint i = 0; i < lengthof(_colour_dropdown); i++) {
588  *list->Append() = new DropDownListColourItem(i, HasBit(used_colours, i));
589  }
590 
591  ShowDropDownList(this, list, widget == WID_SCL_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget);
592  }
593 
594 public:
595  SelectCompanyLiveryWindow(WindowDesc *desc, CompanyID company) : Window(desc)
596  {
597  this->livery_class = LC_OTHER;
598  this->sel = 1;
599 
600  this->square = GetSpriteSize(SPR_SQUARE);
601  this->box = maxdim(GetSpriteSize(SPR_BOX_CHECKED), GetSpriteSize(SPR_BOX_EMPTY));
602  this->line_height = max(max(this->square.height, this->box.height), (uint)FONT_HEIGHT_NORMAL) + 4;
603 
604  this->InitNested(company);
605  this->owner = company;
606  this->LowerWidget(WID_SCL_CLASS_GENERAL);
607  this->InvalidateData(1);
608  }
609 
610  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
611  {
612  switch (widget) {
614  /* The matrix widget below needs enough room to print all the schemes. */
615  Dimension d = {0, 0};
616  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
617  d = maxdim(d, GetStringBoundingBox(STR_LIVERY_DEFAULT + scheme));
618  }
619  size->width = max(size->width, 5 + this->box.width + d.width + WD_FRAMERECT_RIGHT);
620  break;
621  }
622 
623  case WID_SCL_MATRIX: {
624  uint livery_height = 0;
625  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
626  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
627  livery_height++;
628  }
629  }
630  size->height = livery_height * this->line_height;
631  this->GetWidget<NWidgetCore>(WID_SCL_MATRIX)->widget_data = (livery_height << MAT_ROW_START) | (1 << MAT_COL_START);
632  break;
633  }
634 
637  size->width = 0;
638  break;
639  }
640  FALLTHROUGH;
641 
643  int padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10;
644  for (const StringID *id = _colour_dropdown; id != endof(_colour_dropdown); id++) {
645  size->width = max(size->width, GetStringBoundingBox(*id).width + padding);
646  }
647  break;
648  }
649  }
650  }
651 
652  virtual void OnPaint()
653  {
654  /* Disable dropdown controls if no scheme is selected */
655  this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, this->sel == 0);
656  this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, this->sel == 0);
657 
658  this->DrawWidgets();
659  }
660 
661  virtual void SetStringParameters(int widget) const
662  {
663  switch (widget) {
666  const Company *c = Company::Get((CompanyID)this->window_number);
667  LiveryScheme scheme = LS_DEFAULT;
668 
669  if (this->sel != 0) {
670  for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
671  if (HasBit(this->sel, scheme)) break;
672  }
673  if (scheme == LS_END) scheme = LS_DEFAULT;
674  }
675  SetDParam(0, STR_COLOUR_DARK_BLUE + ((widget == WID_SCL_PRI_COL_DROPDOWN) ? c->livery[scheme].colour1 : c->livery[scheme].colour2));
676  break;
677  }
678  }
679  }
680 
681  virtual void DrawWidget(const Rect &r, int widget) const
682  {
683  if (widget != WID_SCL_MATRIX) return;
684 
685  bool rtl = _current_text_dir == TD_RTL;
686 
687  /* Horizontal coordinates of scheme name column. */
688  const NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SCL_SPACER_DROPDOWN);
689  int sch_left = nwi->pos_x;
690  int sch_right = sch_left + nwi->current_x - 1;
691  /* Horizontal coordinates of first dropdown. */
692  nwi = this->GetWidget<NWidgetBase>(WID_SCL_PRI_COL_DROPDOWN);
693  int pri_left = nwi->pos_x;
694  int pri_right = pri_left + nwi->current_x - 1;
695  /* Horizontal coordinates of second dropdown. */
696  nwi = this->GetWidget<NWidgetBase>(WID_SCL_SEC_COL_DROPDOWN);
697  int sec_left = nwi->pos_x;
698  int sec_right = sec_left + nwi->current_x - 1;
699 
700  int text_left = (rtl ? (uint)WD_FRAMERECT_LEFT : (this->box.width + 5));
701  int text_right = (rtl ? (this->box.width + 5) : (uint)WD_FRAMERECT_RIGHT);
702 
703  int box_offs = (this->line_height - this->box.height) / 2;
704  int square_offs = (this->line_height - this->square.height) / 2 + 1;
705  int text_offs = (this->line_height - FONT_HEIGHT_NORMAL) / 2 + 1;
706 
707  int y = r.top;
708  const Company *c = Company::Get((CompanyID)this->window_number);
709  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
710  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
711  bool sel = HasBit(this->sel, scheme) != 0;
712 
713  /* Optional check box + scheme name. */
714  if (scheme != LS_DEFAULT) {
715  DrawSprite(c->livery[scheme].in_use ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, (rtl ? sch_right - (this->box.width + 5) + WD_FRAMERECT_RIGHT : sch_left) + WD_FRAMERECT_LEFT, y + box_offs);
716  }
717  DrawString(sch_left + text_left, sch_right - text_right, y + text_offs, STR_LIVERY_DEFAULT + scheme, sel ? TC_WHITE : TC_BLACK);
718 
719  /* Text below the first dropdown. */
720  DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(c->livery[scheme].colour1), (rtl ? pri_right - (this->box.width + 5) + WD_FRAMERECT_RIGHT : pri_left) + WD_FRAMERECT_LEFT, y + square_offs);
721  DrawString(pri_left + text_left, pri_right - text_right, y + text_offs, STR_COLOUR_DARK_BLUE + c->livery[scheme].colour1, sel ? TC_WHITE : TC_GOLD);
722 
723  /* Text below the second dropdown. */
724  if (sec_right > sec_left) { // Second dropdown has non-zero size.
725  DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(c->livery[scheme].colour2), (rtl ? sec_right - (this->box.width + 5) + WD_FRAMERECT_RIGHT : sec_left) + WD_FRAMERECT_LEFT, y + square_offs);
726  DrawString(sec_left + text_left, sec_right - text_right, y + text_offs, STR_COLOUR_DARK_BLUE + c->livery[scheme].colour2, sel ? TC_WHITE : TC_GOLD);
727  }
728 
729  y += this->line_height;
730  }
731  }
732  }
733 
734  virtual void OnClick(Point pt, int widget, int click_count)
735  {
736  switch (widget) {
737  /* Livery Class buttons */
739  case WID_SCL_CLASS_RAIL:
740  case WID_SCL_CLASS_ROAD:
741  case WID_SCL_CLASS_SHIP:
743  this->RaiseWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
744  this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
745  this->LowerWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
746 
747  /* Select the first item in the list */
748  this->sel = 0;
749  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
750  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
751  this->sel = 1 << scheme;
752  break;
753  }
754  }
755 
756  this->ReInit();
757  break;
758 
759  case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
760  ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
761  break;
762 
763  case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
764  ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
765  break;
766 
767  case WID_SCL_MATRIX: {
768  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SCL_MATRIX);
769  LiveryScheme j = (LiveryScheme)((pt.y - wid->pos_y) / this->line_height);
770 
771  for (LiveryScheme scheme = LS_BEGIN; scheme <= j; scheme++) {
772  if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
773  if (scheme >= LS_END) return;
774  }
775  if (j >= LS_END) return;
776 
777  /* If clicking on the left edge, toggle using the livery */
778  if (_current_text_dir == TD_RTL ? pt.x - wid->pos_x > wid->current_x - (this->box.width + 5) : pt.x - wid->pos_x < (this->box.width + 5)) {
779  DoCommandP(0, j | (2 << 8), !Company::Get((CompanyID)this->window_number)->livery[j].in_use, CMD_SET_COMPANY_COLOUR);
780  }
781 
782  if (_ctrl_pressed) {
783  ToggleBit(this->sel, j);
784  } else {
785  this->sel = 1 << j;
786  }
787  this->SetDirty();
788  break;
789  }
790  }
791  }
792 
793  virtual void OnDropdownSelect(int widget, int index)
794  {
795  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
796  /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
797  if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
798  DoCommandP(0, scheme | (widget == WID_SCL_PRI_COL_DROPDOWN ? 0 : 256), index, CMD_SET_COMPANY_COLOUR);
799  }
800  }
801  }
802 
808  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
809  {
810  if (!gui_scope) return;
812 
813  bool current_class_valid = this->livery_class == LC_OTHER;
814  if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
815  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
817  if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
818  this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
819  } else {
820  ClrBit(this->sel, scheme);
821  }
822  }
823  }
824 
825  if (!current_class_valid) {
826  Point pt = {0, 0};
827  this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
828  } else if (data == 0) {
829  this->ReInit();
830  }
831  }
832 };
833 
834 static const NWidgetPart _nested_select_company_livery_widgets [] = {
836  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
837  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
838  EndContainer(),
840  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
841  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
842  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
843  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
844  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
845  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(),
846  EndContainer(),
848  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(),
849  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_BLACK_STRING, STR_LIVERY_PRIMARY_TOOLTIP),
850  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1),
851  SetDataTip(STR_BLACK_STRING, STR_LIVERY_SECONDARY_TOOLTIP),
852  EndContainer(),
853  NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 15), SetFill(1, 0), SetMatrixDataTip(1, 1, STR_LIVERY_PANEL_TOOLTIP),
854 };
855 
856 static WindowDesc _select_company_livery_desc(
857  WDP_AUTO, "company_livery", 0, 0,
859  0,
860  _nested_select_company_livery_widgets, lengthof(_nested_select_company_livery_widgets)
861 );
862 
870 void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
871 {
873 
874  bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
875  bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
876  bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
877  PaletteID pal;
878 
879  /* Modify eye colour palette only if 2 or more valid values exist */
880  if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
881  pal = PAL_NONE;
882  } else {
883  switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
884  default: NOT_REACHED();
885  case 0: pal = PALETTE_TO_BROWN; break;
886  case 1: pal = PALETTE_TO_BLUE; break;
887  case 2: pal = PALETTE_TO_GREEN; break;
888  }
889  }
890 
891  /* Draw the gradient (background) */
892  DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
893 
894  for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
895  switch (cmfv) {
896  case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
897  case CMFV_LIPS:
898  case CMFV_NOSE: if (has_moustache) continue; break;
899  case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
900  case CMFV_GLASSES: if (!has_glasses) continue; break;
901  default: break;
902  }
903  DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
904  }
905 }
906 
910  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
911  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
912  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP),
913  EndContainer(),
914  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
916  NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
919  NWidget(NWID_SPACER), SetFill(1, 0),
920  NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCMF_FACE), SetMinimalSize(92, 119),
921  NWidget(NWID_SPACER), SetFill(1, 0),
922  EndContainer(),
924  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetDataTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
925  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
927  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
928  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetDataTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
929  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetDataTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
930  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetDataTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
931  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
932  EndContainer(),
933  EndContainer(),
934  EndContainer(),
936  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
938  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
940  NWidget(NWID_SPACER), SetFill(0, 1),
941  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
942  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
943  NWidget(NWID_SPACER), SetFill(0, 1),
944  EndContainer(),
945  EndContainer(),
946  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
950  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
951  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
952  EndContainer(),
955  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
956  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
957  EndContainer(),
961  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
962  EndContainer(),
964  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
965  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
966  EndContainer(),
967  NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
969  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
970  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
971  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
972  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
973  EndContainer(),
975  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
976  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
977  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
978  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
979  EndContainer(),
981  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
982  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
983  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
984  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
985  EndContainer(),
987  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
988  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
989  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
990  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
991  EndContainer(),
993  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
994  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
995  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
996  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
997  EndContainer(),
999  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1000  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1001  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1002  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1003  EndContainer(),
1005  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1006  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1007  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
1008  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1009  EndContainer(),
1011  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1012  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1013  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
1014  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1015  EndContainer(),
1017  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1018  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1019  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
1020  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1021  EndContainer(),
1023  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1024  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1025  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
1026  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1027  EndContainer(),
1028  NWidget(NWID_SPACER), SetFill(0, 1),
1029  EndContainer(),
1030  EndContainer(),
1031  EndContainer(),
1032  EndContainer(),
1034  EndContainer(),
1036  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1037  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1038  EndContainer(),
1039 };
1040 
1043 {
1045  bool advanced;
1046 
1048  bool is_female;
1050 
1053 
1054  static const StringID PART_TEXTS_IS_FEMALE[];
1055  static const StringID PART_TEXTS[];
1056 
1064  void DrawFaceStringLabel(byte widget_index, uint8 val, bool is_bool_widget) const
1065  {
1066  StringID str;
1067  const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1068  if (!nwi_widget->IsDisabled()) {
1069  if (is_bool_widget) {
1070  /* if it a bool button write yes or no */
1071  str = (val != 0) ? STR_FACE_YES : STR_FACE_NO;
1072  } else {
1073  /* else write the value + 1 */
1074  SetDParam(0, val + 1);
1075  str = STR_JUST_INT;
1076  }
1077 
1078  /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
1079  DrawString(nwi_widget->pos_x + nwi_widget->IsLowered(), nwi_widget->pos_x + nwi_widget->current_x - 1 - nwi_widget->IsLowered(),
1080  nwi_widget->pos_y + 1 + nwi_widget->IsLowered(), str, TC_WHITE, SA_HOR_CENTER);
1081  }
1082  }
1083 
1084  void UpdateData()
1085  {
1086  this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1087  this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1088  this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1089  }
1090 
1091 public:
1092  SelectCompanyManagerFaceWindow(WindowDesc *desc, Window *parent) : Window(desc)
1093  {
1094  this->advanced = false;
1095  this->CreateNestedTree();
1096  this->SelectDisplayPlanes(this->advanced);
1097  this->FinishInitNested(parent->window_number);
1098  this->parent = parent;
1099  this->owner = (Owner)this->window_number;
1100  this->face = Company::Get((CompanyID)this->window_number)->face;
1101 
1102  this->UpdateData();
1103  }
1104 
1109  void SelectDisplayPlanes(bool advanced)
1110  {
1111  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1112  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1113  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1114  this->GetWidget<NWidgetCore>(WID_SCMF_RANDOM_NEW_FACE)->widget_data = advanced ? STR_FACE_RANDOM : STR_FACE_NEW_FACE_BUTTON;
1115 
1116  NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1117  if (advanced) {
1118  wi->SetDataTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1119  } else {
1120  wi->SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1121  }
1122  }
1123 
1124  virtual void OnInit()
1125  {
1126  /* Size of the boolean yes/no button. */
1127  Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
1128  yesno_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1129  yesno_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1130  /* Size of the number button + arrows. */
1131  Dimension number_dim = {0, 0};
1132  for (int val = 1; val <= 12; val++) {
1133  SetDParam(0, val);
1134  number_dim = maxdim(number_dim, GetStringBoundingBox(STR_JUST_INT));
1135  }
1136  uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT);
1137  number_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + arrows_width;
1138  number_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1139  /* Compute width of both buttons. */
1140  yesno_dim.width = max(yesno_dim.width, number_dim.width);
1141  number_dim.width = yesno_dim.width - arrows_width;
1142 
1143  this->yesno_dim = yesno_dim;
1144  this->number_dim = number_dim;
1145  }
1146 
1147  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1148  {
1149  switch (widget) {
1150  case WID_SCMF_FACE: {
1151  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
1152  size->width = max(size->width, face_size.width);
1153  size->height = max(size->height, face_size.height);
1154  break;
1155  }
1156 
1159  int offset = (widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2;
1160  *size = maxdim(GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset]), GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset + 1]));
1161  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1162  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1163  break;
1164  }
1165 
1167  *size = maxdim(GetStringBoundingBox(STR_FACE_LIPS), GetStringBoundingBox(STR_FACE_MOUSTACHE));
1168  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1169  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1170  break;
1171 
1173  case WID_SCMF_HAIR_TEXT:
1176  case WID_SCMF_GLASSES_TEXT:
1177  case WID_SCMF_NOSE_TEXT:
1178  case WID_SCMF_CHIN_TEXT:
1179  case WID_SCMF_JACKET_TEXT:
1180  case WID_SCMF_COLLAR_TEXT:
1181  *size = GetStringBoundingBox(PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT]);
1182  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1183  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1184  break;
1185 
1187  case WID_SCMF_HAS_GLASSES:
1188  *size = this->yesno_dim;
1189  break;
1190 
1191  case WID_SCMF_EYECOLOUR:
1192  case WID_SCMF_CHIN:
1193  case WID_SCMF_EYEBROWS:
1195  case WID_SCMF_NOSE:
1196  case WID_SCMF_HAIR:
1197  case WID_SCMF_JACKET:
1198  case WID_SCMF_COLLAR:
1199  case WID_SCMF_TIE_EARRING:
1200  case WID_SCMF_GLASSES:
1201  *size = this->number_dim;
1202  break;
1203  }
1204  }
1205 
1206  virtual void OnPaint()
1207  {
1208  /* lower the non-selected gender button */
1209  this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2, WIDGET_LIST_END);
1210  this->SetWidgetsLoweredState( this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2, WIDGET_LIST_END);
1211 
1212  /* advanced company manager face selection window */
1213 
1214  /* lower the non-selected ethnicity button */
1215  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
1216  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
1217 
1218 
1219  /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1220  * (or in other words you haven't any choice).
1221  * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1222 
1223  /* Eye colour buttons */
1224  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1226 
1227  /* Chin buttons */
1228  this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1230 
1231  /* Eyebrows buttons */
1232  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1234 
1235  /* Lips or (if it a male face with a moustache) moustache buttons */
1236  this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1238 
1239  /* Nose buttons | male faces with moustache haven't any nose options */
1240  this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1242 
1243  /* Hair buttons */
1244  this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1246 
1247  /* Jacket buttons */
1248  this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1250 
1251  /* Collar buttons */
1252  this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1254 
1255  /* Tie/earring buttons | female faces without earring haven't any earring options */
1256  this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1257  (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1259 
1260  /* Glasses buttons | faces without glasses haven't any glasses options */
1261  this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1263 
1264  this->DrawWidgets();
1265  }
1266 
1267  virtual void DrawWidget(const Rect &r, int widget) const
1268  {
1269  switch (widget) {
1272  StringID str = PART_TEXTS_IS_FEMALE[(widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2 + this->is_female];
1273  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_GOLD, SA_RIGHT);
1274  break;
1275  }
1276 
1278  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, (this->is_moust_male) ? STR_FACE_MOUSTACHE : STR_FACE_LIPS, TC_GOLD, SA_RIGHT);
1279  break;
1280 
1282  case WID_SCMF_HAIR_TEXT:
1285  case WID_SCMF_GLASSES_TEXT:
1286  case WID_SCMF_NOSE_TEXT:
1287  case WID_SCMF_CHIN_TEXT:
1288  case WID_SCMF_JACKET_TEXT:
1289  case WID_SCMF_COLLAR_TEXT:
1290  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT], TC_GOLD, SA_RIGHT);
1291  break;
1292 
1293 
1295  if (this->is_female) { // Only for female faces
1296  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true);
1297  } else { // Only for male faces
1298  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge), true);
1299  }
1300  break;
1301 
1302  case WID_SCMF_TIE_EARRING:
1303  this->DrawFaceStringLabel(WID_SCMF_TIE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1304  break;
1305 
1307  if (this->is_moust_male) { // Only for male faces with moustache
1308  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_MOUSTACHE, this->ge), false);
1309  } else { // Only for female faces or male faces without moustache
1310  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_LIPS, this->ge), false);
1311  }
1312  break;
1313 
1314  case WID_SCMF_HAS_GLASSES:
1315  this->DrawFaceStringLabel(WID_SCMF_HAS_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1316  break;
1317 
1318  case WID_SCMF_HAIR:
1319  this->DrawFaceStringLabel(WID_SCMF_HAIR, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1320  break;
1321 
1322  case WID_SCMF_EYEBROWS:
1323  this->DrawFaceStringLabel(WID_SCMF_EYEBROWS, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1324  break;
1325 
1326  case WID_SCMF_EYECOLOUR:
1327  this->DrawFaceStringLabel(WID_SCMF_EYECOLOUR, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1328  break;
1329 
1330  case WID_SCMF_GLASSES:
1331  this->DrawFaceStringLabel(WID_SCMF_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1332  break;
1333 
1334  case WID_SCMF_NOSE:
1335  this->DrawFaceStringLabel(WID_SCMF_NOSE, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1336  break;
1337 
1338  case WID_SCMF_CHIN:
1339  this->DrawFaceStringLabel(WID_SCMF_CHIN, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1340  break;
1341 
1342  case WID_SCMF_JACKET:
1343  this->DrawFaceStringLabel(WID_SCMF_JACKET, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1344  break;
1345 
1346  case WID_SCMF_COLLAR:
1347  this->DrawFaceStringLabel(WID_SCMF_COLLAR, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1348  break;
1349 
1350  case WID_SCMF_FACE:
1351  DrawCompanyManagerFace(this->face, Company::Get((CompanyID)this->window_number)->colour, r.left, r.top);
1352  break;
1353  }
1354  }
1355 
1356  virtual void OnClick(Point pt, int widget, int click_count)
1357  {
1358  switch (widget) {
1359  /* Toggle size, advanced/simple face selection */
1362  this->advanced = !this->advanced;
1363  this->SelectDisplayPlanes(this->advanced);
1364  this->ReInit();
1365  break;
1366 
1367  /* OK button */
1368  case WID_SCMF_ACCEPT:
1369  DoCommandP(0, 0, this->face, CMD_SET_COMPANY_MANAGER_FACE);
1370  FALLTHROUGH;
1371 
1372  /* Cancel button */
1373  case WID_SCMF_CANCEL:
1374  delete this;
1375  break;
1376 
1377  /* Load button */
1378  case WID_SCMF_LOAD:
1379  this->face = _company_manager_face;
1380  ScaleAllCompanyManagerFaceBits(this->face);
1381  ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, WL_INFO);
1382  this->UpdateData();
1383  this->SetDirty();
1384  break;
1385 
1386  /* 'Company manager face number' button, view and/or set company manager face number */
1387  case WID_SCMF_FACECODE:
1388  SetDParam(0, this->face);
1389  ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, this, CS_NUMERAL, QSF_NONE);
1390  break;
1391 
1392  /* Save button */
1393  case WID_SCMF_SAVE:
1394  _company_manager_face = this->face;
1395  ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, WL_INFO);
1396  break;
1397 
1398  /* Toggle gender (male/female) button */
1399  case WID_SCMF_MALE:
1400  case WID_SCMF_FEMALE:
1401  case WID_SCMF_MALE2:
1402  case WID_SCMF_FEMALE2:
1403  SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1404  ScaleAllCompanyManagerFaceBits(this->face);
1405  this->UpdateData();
1406  this->SetDirty();
1407  break;
1408 
1409  /* Randomize face button */
1411  RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced);
1412  this->UpdateData();
1413  this->SetDirty();
1414  break;
1415 
1416  /* Toggle ethnicity (european/african) button */
1419  SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1420  ScaleAllCompanyManagerFaceBits(this->face);
1421  this->UpdateData();
1422  this->SetDirty();
1423  break;
1424 
1425  default:
1426  /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1427  * First it checks which CompanyManagerFaceVariable is being changed, and then either
1428  * a: invert the value for boolean variables, or
1429  * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1430  if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1431  CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1432 
1433  if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1434  switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1435  default: NOT_REACHED();
1436  case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1437  case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1438  }
1439  SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1440  ScaleAllCompanyManagerFaceBits(this->face);
1441  } else { // Value buttons
1442  switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1443  default: NOT_REACHED();
1444  case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1445  case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1446  case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1447  case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1448  case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1449  case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1450  case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1451  case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1452  case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1453  case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1454  }
1455  /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1456  IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1457  }
1458  this->UpdateData();
1459  this->SetDirty();
1460  }
1461  break;
1462  }
1463  }
1464 
1465  virtual void OnQueryTextFinished(char *str)
1466  {
1467  if (str == NULL) return;
1468  /* Set a new company manager face number */
1469  if (!StrEmpty(str)) {
1470  this->face = strtoul(str, NULL, 10);
1471  ScaleAllCompanyManagerFaceBits(this->face);
1472  ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, WL_INFO);
1473  this->UpdateData();
1474  this->SetDirty();
1475  } else {
1476  ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, WL_INFO);
1477  }
1478  }
1479 };
1480 
1483  STR_FACE_MOUSTACHE, STR_FACE_EARRING, // WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
1484  STR_FACE_TIE, STR_FACE_EARRING, // WID_SCMF_TIE_EARRING_TEXT
1485 };
1486 
1489  STR_FACE_GLASSES, // WID_SCMF_HAS_GLASSES_TEXT
1490  STR_FACE_HAIR, // WID_SCMF_HAIR_TEXT
1491  STR_FACE_EYEBROWS, // WID_SCMF_EYEBROWS_TEXT
1492  STR_FACE_EYECOLOUR, // WID_SCMF_EYECOLOUR_TEXT
1493  STR_FACE_GLASSES, // WID_SCMF_GLASSES_TEXT
1494  STR_FACE_NOSE, // WID_SCMF_NOSE_TEXT
1495  STR_FACE_CHIN, // WID_SCMF_CHIN_TEXT
1496  STR_FACE_JACKET, // WID_SCMF_JACKET_TEXT
1497  STR_FACE_COLLAR, // WID_SCMF_COLLAR_TEXT
1498 };
1499 
1502  WDP_AUTO, "company_face", 0, 0,
1505  _nested_select_company_manager_face_widgets, lengthof(_nested_select_company_manager_face_widgets)
1506 );
1507 
1517 {
1518  if (!Company::IsValidID((CompanyID)parent->window_number)) return;
1519 
1521  new SelectCompanyManagerFaceWindow(&_select_company_manager_face_desc, parent);
1522 }
1523 
1524 static const NWidgetPart _nested_company_infrastructure_widgets[] = {
1526  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1527  NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), SetDataTip(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1528  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1529  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1530  EndContainer(),
1531  NWidget(WWT_PANEL, COLOUR_GREY),
1533  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1534  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1535  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1536  EndContainer(),
1537  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1538  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1539  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1540  EndContainer(),
1541  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1542  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1543  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1544  EndContainer(),
1545  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1546  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1547  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1548  EndContainer(),
1549  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1550  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
1551  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
1552  EndContainer(),
1553  EndContainer(),
1554  EndContainer(),
1555 };
1556 
1561 {
1564 
1566 
1567  CompanyInfrastructureWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
1568  {
1569  this->UpdateRailRoadTypes();
1570 
1571  this->InitNested(window_number);
1572  this->owner = (Owner)this->window_number;
1573  }
1574 
1575  void UpdateRailRoadTypes()
1576  {
1577  this->railtypes = RAILTYPES_NONE;
1578  this->roadtypes = ROADTYPES_ROAD; // Road is always available.
1579 
1580  /* Find the used railtypes. */
1581  Engine *e;
1582  FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
1583  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1584 
1585  this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1586  }
1587 
1588  /* Get the date introduced railtypes as well. */
1589  this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY);
1590 
1591  /* Tram is only visible when there will be a tram. */
1592  FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
1593  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1594  if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
1595 
1596  this->roadtypes |= ROADTYPES_TRAM;
1597  break;
1598  }
1599  }
1600 
1603  {
1604  const Company *c = Company::Get((CompanyID)this->window_number);
1605  Money total;
1606 
1607  uint32 rail_total = c->infrastructure.GetRailTotal();
1608  for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1609  if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1610  }
1612 
1615 
1618  total += AirportMaintenanceCost(c->index);
1619 
1620  return total;
1621  }
1622 
1623  virtual void SetStringParameters(int widget) const
1624  {
1625  switch (widget) {
1626  case WID_CI_CAPTION:
1627  SetDParam(0, (CompanyID)this->window_number);
1628  break;
1629  }
1630  }
1631 
1632  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1633  {
1634  const Company *c = Company::Get((CompanyID)this->window_number);
1635 
1636  switch (widget) {
1637  case WID_CI_RAIL_DESC: {
1638  uint lines = 1;
1639 
1640  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width);
1641 
1642  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1643  if (HasBit(this->railtypes, rt)) {
1644  lines++;
1645  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
1646  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1647  }
1648  }
1649  if (this->railtypes != RAILTYPES_NONE) {
1650  lines++;
1651  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + WD_FRAMERECT_LEFT);
1652  }
1653 
1654  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1655  break;
1656  }
1657 
1658  case WID_CI_ROAD_DESC: {
1659  uint lines = 1;
1660 
1661  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT).width);
1662 
1663  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
1664  lines++;
1665  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD).width + WD_FRAMERECT_LEFT);
1666  }
1667  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
1668  lines++;
1669  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY).width + WD_FRAMERECT_LEFT);
1670  }
1671 
1672  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1673  break;
1674  }
1675 
1676  case WID_CI_WATER_DESC:
1677  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width);
1678  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + WD_FRAMERECT_LEFT);
1679  break;
1680 
1681  case WID_CI_STATION_DESC:
1682  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width);
1683  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + WD_FRAMERECT_LEFT);
1684  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + WD_FRAMERECT_LEFT);
1685  break;
1686 
1687  case WID_CI_RAIL_COUNT:
1688  case WID_CI_ROAD_COUNT:
1689  case WID_CI_WATER_COUNT:
1690  case WID_CI_STATION_COUNT:
1691  case WID_CI_TOTAL: {
1692  /* Find the maximum count that is displayed. */
1693  uint32 max_val = 1000; // Some random number to reserve enough space.
1694  Money max_cost = 10000; // Some random number to reserve enough space.
1695  uint32 rail_total = c->infrastructure.GetRailTotal();
1696  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1697  max_val = max(max_val, c->infrastructure.rail[rt]);
1698  max_cost = max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1699  }
1700  max_val = max(max_val, c->infrastructure.signal);
1701  max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1702  for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1703  max_val = max(max_val, c->infrastructure.road[rt]);
1704  max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
1705  }
1706  max_val = max(max_val, c->infrastructure.water);
1707  max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1708  max_val = max(max_val, c->infrastructure.station);
1709  max_cost = max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1710  max_val = max(max_val, c->infrastructure.airport);
1711  max_cost = max(max_cost, AirportMaintenanceCost(c->index));
1712 
1713  SetDParamMaxValue(0, max_val);
1714  uint count_width = GetStringBoundingBox(STR_WHITE_COMMA).width + 20; // Reserve some wiggle room
1715 
1717  SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1718  this->total_width = GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width + 20;
1719  size->width = max(size->width, this->total_width);
1720 
1721  SetDParamMaxValue(0, max_cost * 12); // Convert to per year
1722  count_width += max(this->total_width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width);
1723  }
1724 
1725  size->width = max(size->width, count_width);
1726 
1727  /* Set height of the total line. */
1728  if (widget == WID_CI_TOTAL) {
1730  }
1731  break;
1732  }
1733  }
1734  }
1735 
1743  void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1744  {
1745  SetDParam(0, count);
1746  DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA, TC_FROMSTRING, SA_RIGHT);
1747 
1749  SetDParam(0, monthly_cost * 12); // Convert to per year
1750  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
1751  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
1752  }
1753  }
1754 
1755  virtual void DrawWidget(const Rect &r, int widget) const
1756  {
1757  const Company *c = Company::Get((CompanyID)this->window_number);
1758  int y = r.top;
1759 
1760  int offs_left = _current_text_dir == TD_LTR ? WD_FRAMERECT_LEFT : 0;
1761  int offs_right = _current_text_dir == TD_LTR ? 0 : WD_FRAMERECT_LEFT;
1762 
1763  switch (widget) {
1764  case WID_CI_RAIL_DESC:
1765  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
1766 
1767  if (this->railtypes != RAILTYPES_NONE) {
1768  /* Draw name of each valid railtype. */
1769  RailType rt;
1771  if (HasBit(this->railtypes, rt)) {
1772  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
1773  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
1774  }
1775  }
1776  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
1777  } else {
1778  /* No valid railtype. */
1779  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
1780  }
1781 
1782  break;
1783 
1784  case WID_CI_RAIL_COUNT: {
1785  /* Draw infrastructure count for each valid railtype. */
1786  uint32 rail_total = c->infrastructure.GetRailTotal();
1787  RailType rt;
1789  if (HasBit(this->railtypes, rt)) {
1790  this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1791  }
1792  }
1793  if (this->railtypes != RAILTYPES_NONE) {
1794  this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
1795  }
1796  break;
1797  }
1798 
1799  case WID_CI_ROAD_DESC:
1800  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT);
1801 
1802  if (this->roadtypes != ROADTYPES_NONE) {
1803  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD);
1804  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY);
1805  } else {
1806  /* No valid roadtypes. */
1807  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
1808  }
1809 
1810  break;
1811 
1812  case WID_CI_ROAD_COUNT:
1813  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
1815  }
1816  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
1818  }
1819  break;
1820 
1821  case WID_CI_WATER_DESC:
1822  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
1823  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
1824  break;
1825 
1826  case WID_CI_WATER_COUNT:
1827  this->DrawCountLine(r, y, c->infrastructure.water, CanalMaintenanceCost(c->infrastructure.water));
1828  break;
1829 
1830  case WID_CI_TOTAL:
1832  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
1833  GfxFillRect(left, y, left + this->total_width, y, PC_WHITE);
1834  y += EXP_LINESPACE;
1835  SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1836  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
1837  }
1838  break;
1839 
1840  case WID_CI_STATION_DESC:
1841  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
1842  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
1843  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
1844  break;
1845 
1846  case WID_CI_STATION_COUNT:
1847  this->DrawCountLine(r, y, c->infrastructure.station, StationMaintenanceCost(c->infrastructure.station));
1848  this->DrawCountLine(r, y, c->infrastructure.airport, AirportMaintenanceCost(c->index));
1849  break;
1850  }
1851  }
1852 
1858  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1859  {
1860  if (!gui_scope) return;
1861 
1862  this->UpdateRailRoadTypes();
1863  this->ReInit();
1864  }
1865 };
1866 
1867 static WindowDesc _company_infrastructure_desc(
1868  WDP_AUTO, "company_infrastructure", 0, 0,
1870  0,
1871  _nested_company_infrastructure_widgets, lengthof(_nested_company_infrastructure_widgets)
1872 );
1873 
1879 {
1880  if (!Company::IsValidID(company)) return;
1881  AllocateWindowDescFront<CompanyInfrastructureWindow>(&_company_infrastructure_desc, company);
1882 }
1883 
1884 static const NWidgetPart _nested_company_widgets[] = {
1886  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1887  NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), SetDataTip(STR_COMPANY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1888  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1889  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1890  EndContainer(),
1891  NWidget(WWT_PANEL, COLOUR_GREY),
1892  NWidget(NWID_HORIZONTAL), SetPIP(4, 6, 4),
1893  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
1894  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1895  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
1896  EndContainer(),
1899  NWidget(NWID_VERTICAL), SetPIP(4, 5, 5),
1900  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INAUGURATION), SetDataTip(STR_COMPANY_VIEW_INAUGURATED_TITLE, STR_NULL), SetFill(1, 0),
1901  NWidget(NWID_HORIZONTAL), SetPIP(0, 5, 0),
1902  NWidget(WWT_LABEL, COLOUR_GREY, WID_C_DESC_COLOUR_SCHEME), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE, STR_NULL),
1903  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME_EXAMPLE), SetMinimalSize(30, 0), SetFill(0, 1),
1904  NWidget(NWID_SPACER), SetFill(1, 0),
1905  EndContainer(),
1906  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
1908  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_VEHICLE), SetDataTip(STR_COMPANY_VIEW_VEHICLES_TITLE, STR_NULL),
1909  NWidget(NWID_SPACER), SetFill(0, 1),
1910  EndContainer(),
1912  NWidget(NWID_SPACER), SetFill(1, 0),
1913  EndContainer(),
1914  EndContainer(),
1915  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
1917  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_VIEW_HQ_BUTTON, STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP),
1918  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_BUILD_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_BUILD_HQ_BUTTON, STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP),
1919  EndContainer(),
1920  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_RELOCATE),
1921  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
1923  EndContainer(),
1924  NWidget(NWID_SPACER), SetFill(0, 1),
1925  EndContainer(),
1926  EndContainer(),
1927  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_COMPANY_VALUE), SetDataTip(STR_COMPANY_VIEW_COMPANY_VALUE, STR_NULL), SetFill(1, 0),
1928  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
1929  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
1931  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE, STR_NULL),
1932  NWidget(NWID_SPACER), SetFill(0, 1),
1933  EndContainer(),
1936  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
1937  NWidget(NWID_SPACER), SetFill(0, 1), SetMinimalSize(90, 0),
1938  EndContainer(),
1939  EndContainer(),
1940  EndContainer(),
1943  NWidget(NWID_VERTICAL), SetPIP(5, 5, 4),
1944  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_OWNERS), SetMinimalTextLines(3, 0),
1945  NWidget(NWID_SPACER), SetFill(0, 1),
1946  EndContainer(),
1947  EndContainer(),
1948  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
1949  NWidget(NWID_SPACER), SetMinimalSize(90, 0), SetFill(0, 1),
1950  /* Multi player buttons. */
1952  NWidget(WWT_EMPTY, COLOUR_GREY, WID_C_HAS_PASSWORD),
1954  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_PASSWORD), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_COMPANY_VIEW_PASSWORD_TOOLTIP),
1955  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
1956  EndContainer(),
1957  EndContainer(),
1958  EndContainer(),
1959  EndContainer(),
1960  EndContainer(),
1961  EndContainer(),
1962  EndContainer(),
1963  /* Button bars at the bottom. */
1964  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_BUTTONS),
1966  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_NEW_FACE), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_NEW_FACE_BUTTON, STR_COMPANY_VIEW_NEW_FACE_TOOLTIP),
1967  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COLOUR_SCHEME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON, STR_COMPANY_VIEW_COLOUR_SCHEME_TOOLTIP),
1968  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_PRESIDENT_NAME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PRESIDENT_NAME_BUTTON, STR_COMPANY_VIEW_PRESIDENT_NAME_TOOLTIP),
1969  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_NAME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_COMPANY_NAME_BUTTON, STR_COMPANY_VIEW_COMPANY_NAME_TOOLTIP),
1970  EndContainer(),
1972  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_BUY_SHARE), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_BUY_SHARE_BUTTON, STR_COMPANY_VIEW_BUY_SHARE_TOOLTIP),
1973  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_SELL_SHARE), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_SELL_SHARE_BUTTON, STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP),
1974  EndContainer(),
1975  EndContainer(),
1976 };
1977 
1978 int GetAmountOwnedBy(const Company *c, Owner owner)
1979 {
1980  return (c->share_owners[0] == owner) +
1981  (c->share_owners[1] == owner) +
1982  (c->share_owners[2] == owner) +
1983  (c->share_owners[3] == owner);
1984 }
1985 
1988  STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
1989 };
1990 
1995 {
1996  CompanyWidgets query_widget;
1997 
2000  /* Display planes of the #WID_C_SELECT_MULTIPLAYER selection widget. */
2001  CWP_MP_C_PWD = 0,
2003 
2004  /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2005  CWP_VB_VIEW = 0,
2007 
2008  /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2009  CWP_RELOCATE_SHOW = 0,
2011 
2012  /* Display planes of the #WID_C_SELECT_BUTTONS selection widget. */
2013  CWP_BUTTONS_LOCAL = 0,
2015  };
2016 
2017  CompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2018  {
2019  this->InitNested(window_number);
2020  this->owner = (Owner)this->window_number;
2021  this->OnInvalidateData();
2022  }
2023 
2024  virtual void OnPaint()
2025  {
2026  const Company *c = Company::Get((CompanyID)this->window_number);
2027  bool local = this->window_number == _local_company;
2028 
2029  if (!this->IsShaded()) {
2030  bool reinit = false;
2031 
2032  /* Button bar selection. */
2033  int plane = local ? CWP_BUTTONS_LOCAL : CWP_BUTTONS_OTHER;
2034  NWidgetStacked *wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS);
2035  if (plane != wi->shown_plane) {
2036  wi->SetDisplayedPlane(plane);
2037  this->InvalidateData();
2038  return;
2039  }
2040 
2041  /* Build HQ button handling. */
2042  plane = (local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW;
2043  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ);
2044  if (plane != wi->shown_plane) {
2045  wi->SetDisplayedPlane(plane);
2046  this->SetDirty();
2047  return;
2048  }
2049 
2050  this->SetWidgetDisabledState(WID_C_VIEW_HQ, c->location_of_HQ == INVALID_TILE);
2051 
2052  /* Enable/disable 'Relocate HQ' button. */
2053  plane = (!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW;
2054  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE);
2055  if (plane != wi->shown_plane) {
2056  wi->SetDisplayedPlane(plane);
2057  this->SetDirty();
2058  return;
2059  }
2060 
2061  /* Owners of company */
2062  plane = SZSP_HORIZONTAL;
2063  for (uint i = 0; i < lengthof(c->share_owners); i++) {
2064  if (c->share_owners[i] != INVALID_COMPANY) {
2065  plane = 0;
2066  break;
2067  }
2068  }
2069  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_DESC_OWNERS);
2070  if (plane != wi->shown_plane) {
2071  wi->SetDisplayedPlane(plane);
2072  reinit = true;
2073  }
2074 
2075  /* Multiplayer buttons. */
2076  plane = ((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN));
2077  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER);
2078  if (plane != wi->shown_plane) {
2079  wi->SetDisplayedPlane(plane);
2080  reinit = true;
2081  }
2082  this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
2083 
2084  if (reinit) {
2085  this->ReInit();
2086  return;
2087  }
2088  }
2089 
2090  this->DrawWidgets();
2091  }
2092 
2093  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2094  {
2095  switch (widget) {
2096  case WID_C_FACE: {
2097  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
2098  size->width = max(size->width, face_size.width);
2099  size->height = max(size->height, face_size.height);
2100  break;
2101  }
2102 
2104  Point offset;
2105  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2106  d.width -= offset.x;
2107  d.height -= offset.y;
2108  *size = maxdim(*size, d);
2109  break;
2110  }
2111 
2113  SetDParam(0, INT64_MAX); // Arguably the maximum company value
2114  size->width = GetStringBoundingBox(STR_COMPANY_VIEW_COMPANY_VALUE).width;
2115  break;
2116 
2118  SetDParamMaxValue(0, 5000); // Maximum number of vehicles
2119  for (uint i = 0; i < lengthof(_company_view_vehicle_count_strings); i++) {
2120  size->width = max(size->width, GetStringBoundingBox(_company_view_vehicle_count_strings[i]).width);
2121  }
2122  break;
2123 
2125  SetDParamMaxValue(0, UINT_MAX);
2126  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL).width);
2127  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD).width);
2128  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER).width);
2129  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION).width);
2130  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT).width);
2131  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE).width);
2132  break;
2133 
2134  case WID_C_DESC_OWNERS: {
2135  const Company *c2;
2136 
2137  FOR_ALL_COMPANIES(c2) {
2138  SetDParamMaxValue(0, 75);
2139  SetDParam(1, c2->index);
2140 
2141  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_SHARES_OWNED_BY).width);
2142  }
2143  break;
2144  }
2145 
2146 #ifdef ENABLE_NETWORK
2147  case WID_C_HAS_PASSWORD:
2148  *size = maxdim(*size, GetSpriteSize(SPR_LOCK));
2149  break;
2150 #endif /* ENABLE_NETWORK */
2151  }
2152  }
2153 
2154  virtual void DrawWidget(const Rect &r, int widget) const
2155  {
2156  const Company *c = Company::Get((CompanyID)this->window_number);
2157  switch (widget) {
2158  case WID_C_FACE:
2159  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2160  break;
2161 
2162  case WID_C_FACE_TITLE:
2163  SetDParam(0, c->index);
2164  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
2165  break;
2166 
2168  Point offset;
2169  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2170  d.height -= offset.y;
2171  DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, (r.top + r.bottom - d.height) / 2 - offset.y);
2172  break;
2173  }
2174 
2176  uint amounts[4];
2177  amounts[0] = c->group_all[VEH_TRAIN].num_vehicle;
2178  amounts[1] = c->group_all[VEH_ROAD].num_vehicle;
2179  amounts[2] = c->group_all[VEH_SHIP].num_vehicle;
2180  amounts[3] = c->group_all[VEH_AIRCRAFT].num_vehicle;
2181 
2182  int y = r.top;
2183  if (amounts[0] + amounts[1] + amounts[2] + amounts[3] == 0) {
2184  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2185  } else {
2186  assert_compile(lengthof(amounts) == lengthof(_company_view_vehicle_count_strings));
2187 
2188  for (uint i = 0; i < lengthof(amounts); i++) {
2189  if (amounts[i] != 0) {
2190  SetDParam(0, amounts[i]);
2191  DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[i]);
2192  y += FONT_HEIGHT_NORMAL;
2193  }
2194  }
2195  }
2196  break;
2197  }
2198 
2200  uint y = r.top;
2201 
2202  /* Collect rail and road counts. */
2203  uint rail_pices = c->infrastructure.signal;
2204  uint road_pieces = 0;
2205  for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pices += c->infrastructure.rail[i];
2206  for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
2207 
2208  if (rail_pices == 0 && road_pieces == 0 && c->infrastructure.water == 0 && c->infrastructure.station == 0 && c->infrastructure.airport == 0) {
2209  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2210  } else {
2211  if (rail_pices != 0) {
2212  SetDParam(0, rail_pices);
2213  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
2214  y += FONT_HEIGHT_NORMAL;
2215  }
2216  if (road_pieces != 0) {
2217  SetDParam(0, road_pieces);
2218  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
2219  y += FONT_HEIGHT_NORMAL;
2220  }
2221  if (c->infrastructure.water != 0) {
2223  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
2224  y += FONT_HEIGHT_NORMAL;
2225  }
2226  if (c->infrastructure.station != 0) {
2228  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
2229  y += FONT_HEIGHT_NORMAL;
2230  }
2231  if (c->infrastructure.airport != 0) {
2233  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
2234  }
2235  }
2236 
2237  break;
2238  }
2239 
2240  case WID_C_DESC_OWNERS: {
2241  const Company *c2;
2242  uint y = r.top;
2243 
2244  FOR_ALL_COMPANIES(c2) {
2245  uint amt = GetAmountOwnedBy(c, c2->index);
2246  if (amt != 0) {
2247  SetDParam(0, amt * 25);
2248  SetDParam(1, c2->index);
2249 
2250  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_SHARES_OWNED_BY);
2251  y += FONT_HEIGHT_NORMAL;
2252  }
2253  }
2254  break;
2255  }
2256 
2257 #ifdef ENABLE_NETWORK
2258  case WID_C_HAS_PASSWORD:
2260  DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top);
2261  }
2262  break;
2263 #endif /* ENABLE_NETWORK */
2264  }
2265  }
2266 
2267  virtual void SetStringParameters(int widget) const
2268  {
2269  switch (widget) {
2270  case WID_C_CAPTION:
2271  SetDParam(0, (CompanyID)this->window_number);
2272  SetDParam(1, (CompanyID)this->window_number);
2273  break;
2274 
2276  SetDParam(0, Company::Get((CompanyID)this->window_number)->inaugurated_year);
2277  break;
2278 
2280  SetDParam(0, CalculateCompanyValue(Company::Get((CompanyID)this->window_number)));
2281  break;
2282  }
2283  }
2284 
2285  virtual void OnClick(Point pt, int widget, int click_count)
2286  {
2287  switch (widget) {
2288  case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2289 
2290  case WID_C_COLOUR_SCHEME:
2291  if (BringWindowToFrontById(WC_COMPANY_COLOUR, this->window_number)) break;
2292  new SelectCompanyLiveryWindow(&_select_company_livery_desc, (CompanyID)this->window_number);
2293  break;
2294 
2295  case WID_C_PRESIDENT_NAME:
2296  this->query_widget = WID_C_PRESIDENT_NAME;
2297  SetDParam(0, this->window_number);
2298  ShowQueryString(STR_PRESIDENT_NAME, STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION, MAX_LENGTH_PRESIDENT_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
2299  break;
2300 
2301  case WID_C_COMPANY_NAME:
2302  this->query_widget = WID_C_COMPANY_NAME;
2303  SetDParam(0, this->window_number);
2304  ShowQueryString(STR_COMPANY_NAME, STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION, MAX_LENGTH_COMPANY_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
2305  break;
2306 
2307  case WID_C_VIEW_HQ: {
2308  TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
2309  if (_ctrl_pressed) {
2311  } else {
2312  ScrollMainWindowToTile(tile);
2313  }
2314  break;
2315  }
2316 
2317  case WID_C_BUILD_HQ:
2318  if ((byte)this->window_number != _local_company) return;
2319  if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2321  this->RaiseButtons();
2322  break;
2323  }
2324  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2325  SetTileSelectSize(2, 2);
2326  this->LowerWidget(WID_C_BUILD_HQ);
2327  this->SetWidgetDirty(WID_C_BUILD_HQ);
2328  break;
2329 
2330  case WID_C_RELOCATE_HQ:
2331  if (this->IsWidgetLowered(WID_C_RELOCATE_HQ)) {
2333  this->RaiseButtons();
2334  break;
2335  }
2336  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2337  SetTileSelectSize(2, 2);
2338  this->LowerWidget(WID_C_RELOCATE_HQ);
2339  this->SetWidgetDirty(WID_C_RELOCATE_HQ);
2340  break;
2341 
2343  ShowCompanyInfrastructure((CompanyID)this->window_number);
2344  break;
2345 
2346  case WID_C_BUY_SHARE:
2347  DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
2348  break;
2349 
2350  case WID_C_SELL_SHARE:
2351  DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
2352  break;
2353 
2354 #ifdef ENABLE_NETWORK
2356  if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
2357  break;
2358 
2359  case WID_C_COMPANY_JOIN: {
2360  this->query_widget = WID_C_COMPANY_JOIN;
2361  CompanyID company = (CompanyID)this->window_number;
2362  if (_network_server) {
2365  } else if (NetworkCompanyIsPassworded(company)) {
2366  /* ask for the password */
2367  ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, this, CS_ALPHANUMERAL, QSF_NONE);
2368  } else {
2369  /* just send the join command */
2370  NetworkClientRequestMove(company);
2371  }
2372  break;
2373  }
2374 #endif /* ENABLE_NETWORK */
2375  }
2376  }
2377 
2378  virtual void OnHundredthTick()
2379  {
2380  /* redraw the window every now and then */
2381  this->SetDirty();
2382  }
2383 
2384  virtual void OnPlaceObject(Point pt, TileIndex tile)
2385  {
2386  if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)) && !_shift_pressed) {
2388  this->RaiseButtons();
2389  }
2390  }
2391 
2392  virtual void OnPlaceObjectAbort()
2393  {
2394  this->RaiseButtons();
2395  }
2396 
2397  virtual void OnQueryTextFinished(char *str)
2398  {
2399  if (str == NULL) return;
2400 
2401  switch (this->query_widget) {
2402  default: NOT_REACHED();
2403 
2404  case WID_C_PRESIDENT_NAME:
2405  DoCommandP(0, 0, 0, CMD_RENAME_PRESIDENT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_PRESIDENT), NULL, str);
2406  break;
2407 
2408  case WID_C_COMPANY_NAME:
2409  DoCommandP(0, 0, 0, CMD_RENAME_COMPANY | CMD_MSG(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME), NULL, str);
2410  break;
2411 
2412 #ifdef ENABLE_NETWORK
2413  case WID_C_COMPANY_JOIN:
2414  NetworkClientRequestMove((CompanyID)this->window_number, str);
2415  break;
2416 #endif /* ENABLE_NETWORK */
2417  }
2418  }
2419 
2420 
2426  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2427  {
2428  if (this->window_number == _local_company) return;
2429 
2430  if (_settings_game.economy.allow_shares) { // Shares are allowed
2431  const Company *c = Company::Get(this->window_number);
2432 
2433  /* If all shares are owned by someone (none by nobody), disable buy button */
2434  this->SetWidgetDisabledState(WID_C_BUY_SHARE, GetAmountOwnedBy(c, INVALID_OWNER) == 0 ||
2435  /* Only 25% left to buy. If the company is human, disable buying it up.. TODO issues! */
2436  (GetAmountOwnedBy(c, INVALID_OWNER) == 1 && !c->is_ai) ||
2437  /* Spectators cannot do anything of course */
2439 
2440  /* If the company doesn't own any shares, disable sell button */
2441  this->SetWidgetDisabledState(WID_C_SELL_SHARE, (GetAmountOwnedBy(c, _local_company) == 0) ||
2442  /* Spectators cannot do anything of course */
2444  } else { // Shares are not allowed, disable buy/sell buttons
2445  this->DisableWidget(WID_C_BUY_SHARE);
2446  this->DisableWidget(WID_C_SELL_SHARE);
2447  }
2448  }
2449 };
2450 
2451 static WindowDesc _company_desc(
2452  WDP_AUTO, "company", 0, 0,
2454  0,
2455  _nested_company_widgets, lengthof(_nested_company_widgets)
2456 );
2457 
2462 void ShowCompany(CompanyID company)
2463 {
2464  if (!Company::IsValidID(company)) return;
2465 
2466  AllocateWindowDescFront<CompanyWindow>(&_company_desc, company);
2467 }
2468 
2474 {
2475  SetWindowDirty(WC_COMPANY, company);
2477 }
2478 
2480  BuyCompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2481  {
2482  this->InitNested(window_number);
2483  }
2484 
2485  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2486  {
2487  switch (widget) {
2488  case WID_BC_FACE:
2489  *size = GetSpriteSize(SPR_GRADIENT);
2490  break;
2491 
2492  case WID_BC_QUESTION:
2493  const Company *c = Company::Get((CompanyID)this->window_number);
2494  SetDParam(0, c->index);
2495  SetDParam(1, c->bankrupt_value);
2496  size->height = GetStringHeight(STR_BUY_COMPANY_MESSAGE, size->width);
2497  break;
2498  }
2499  }
2500 
2501  virtual void SetStringParameters(int widget) const
2502  {
2503  switch (widget) {
2504  case WID_BC_CAPTION:
2505  SetDParam(0, STR_COMPANY_NAME);
2506  SetDParam(1, Company::Get((CompanyID)this->window_number)->index);
2507  break;
2508  }
2509  }
2510 
2511  virtual void DrawWidget(const Rect &r, int widget) const
2512  {
2513  switch (widget) {
2514  case WID_BC_FACE: {
2515  const Company *c = Company::Get((CompanyID)this->window_number);
2516  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2517  break;
2518  }
2519 
2520  case WID_BC_QUESTION: {
2521  const Company *c = Company::Get((CompanyID)this->window_number);
2522  SetDParam(0, c->index);
2523  SetDParam(1, c->bankrupt_value);
2524  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING, SA_CENTER);
2525  break;
2526  }
2527  }
2528  }
2529 
2530  virtual void OnClick(Point pt, int widget, int click_count)
2531  {
2532  switch (widget) {
2533  case WID_BC_NO:
2534  delete this;
2535  break;
2536 
2537  case WID_BC_YES:
2538  DoCommandP(0, this->window_number, 0, CMD_BUY_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_COMPANY));
2539  break;
2540  }
2541  }
2542 };
2543 
2544 static const NWidgetPart _nested_buy_company_widgets[] = {
2546  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2547  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2548  EndContainer(),
2549  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2550  NWidget(NWID_VERTICAL), SetPIP(8, 8, 8),
2551  NWidget(NWID_HORIZONTAL), SetPIP(8, 10, 8),
2552  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2553  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2554  EndContainer(),
2555  NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(100, 10, 100),
2556  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
2557  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
2558  EndContainer(),
2559  EndContainer(),
2560  EndContainer(),
2561 };
2562 
2563 static WindowDesc _buy_company_desc(
2564  WDP_AUTO, NULL, 0, 0,
2567  _nested_buy_company_widgets, lengthof(_nested_buy_company_widgets)
2568 );
2569 
2575 {
2576  AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, company);
2577 }
Used for iterations.
Definition: rail_type.h:35
Button to view the HQ.
Functions related to OTTD&#39;s strings.
Button to make new face.
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:48
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Dimension number_dim
Dimension of a number widget of a part in the advanced face window.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
Jacket right.
Collar left.
Definition of stuff that is very close to a company, like the company struct itself.
#define FOR_ALL_SORTED_RAILTYPES(var)
Loop header for iterating over railtypes, sorted by sortorder.
Definition: rail.h:442
Text about collar.
bool _networking
are we in networking mode?
Definition: network.cpp:56
void ShowBuyCompanyDialog(CompanyID company)
Show the query to buy another company.
Button to sell a share.
Caption of window.
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:296
Tie / Earring right.
RailTypes
The different roadtypes we support, but then a bitmask of them.
Definition: rail_type.h:52
Title for the face.
static const uint8 PC_WHITE
White palette colour.
Definition: gfx_func.h:210
Horizontally center the text.
Definition: gfx_func.h:99
Window with detailed information about the company&#39;s infrastructure.
Select panel or nothing.
Button to relocate the HQ.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:112
LiveryScheme
List of different livery schemes.
Definition: livery.h:22
Dropdown for secondary colour.
Button to change company name.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3120
byte landscape
the landscape we&#39;re currently in
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:29
Lowest bit of the number of columns.
Definition: widget_type.h:27
Button to join company.
Caption of the window.
High level window description.
Definition: window_gui.h:168
Has company password lock.
Functions related to roads.
EconomySettings economy
settings to change the economy
Selection to display the load/save/number buttons in the advanced view.
bool expenses_layout
layout of expenses window
Text about moustache and earring.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
Text about hair.
Functions related to dates.
Chin right.
const uint length
Number of items in list.
Definition: company_gui.cpp:92
Centered label.
Definition: widget_type.h:57
GUIs related to networking.
static T ToggleBit(T &x, const uint8 y)
Toggles a bit in a variable.
Basic road type.
Definition: road_type.h:24
Stacked widgets, widgets all occupying the same space in the window.
Definition: widget_type.h:405
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Management class for customizing the face of the company manager.
CompanyManagerFace _company_manager_face
for company manager face storage in openttd.cfg
Definition: company_cmd.cpp:49
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
uint32 GetRailTotal() const
Get total sum of all owned track bits.
Definition: company_base.h:40
View company infrastructure.
Year inaugurated_year
Year of starting the company.
Definition: company_base.h:79
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
static WindowDesc _select_company_manager_face_desc(WDP_AUTO, "company_face", 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WDF_CONSTRUCTION, _nested_select_company_manager_face_widgets, lengthof(_nested_select_company_manager_face_widgets))
Company manager face selection window description.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Lips / Moustache.
Horizontal container.
Definition: widget_type.h:75
This bit set means a female, otherwise male.
void SetTileSelectSize(int w, int h)
Highlight w by h tiles at the cursor.
Definition: viewport.cpp:2295
Toggle for large or small.
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:38
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:37
Text about nose.
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1065
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:82
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Glasses left.
Rail specific functions.
Used for iterations.
Definition: road_type.h:26
Column for year Y-1 expenses.
Toggle for large or small.
Expense list container.
Definition: company_gui.cpp:90
Company livery colour scheme window.
Display the join company button.
static const int LOAN_INTERVAL
The "steps" in loan size, in British Pounds!
Definition: economy_type.h:192
const ExpensesType * et
Expenses items.
Definition: company_gui.cpp:91
Button to change colour scheme.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Buyout company (merger); Window numbers:
Definition: window_type.h:579
Caption of the window.
Create random new face.
Caption of window.
Types related to the company widgets.
static const StringID _company_view_vehicle_count_strings[]
Strings for the company vehicle counts.
static const uint EXP_LINESPACE
Company GUI constants.
Definition: company_gui.cpp:46
void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
Draws the face of a company manager&#39;s face.
Description of road.
buy a company which is bankrupt
Definition: command_type.h:259
Jacket left.
void NetworkClientRequestMove(CompanyID company_id, const char *pass)
Notify the server of this client wanting to be moved to another company.
Column for year Y expenses.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
static Money SignalMaintenanceCost(uint32 num)
Calculates the maintenance cost of a number of signals.
Definition: rail.h:410
int GetStringHeight(const char *str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition: gfx.cpp:547
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
Close box (at top-left of a window)
Definition: widget_type.h:69
Selection widget for the button bar.
static const uint MAX_LENGTH_PRESIDENT_NAME_CHARS
The maximum length of a president name in characters including &#39;\0&#39;.
Definition: company_type.h:41
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:965
The client is spectating.
Definition: company_type.h:37
bool in_use
Set if this livery should be used instead of the default livery.
Definition: livery.h:77
bool NetworkCompanyIsPassworded(CompanyID company_id)
Check if the company we want to join requires a password.
Definition: network.cpp:225
Button to build the HQ.
Max loan widget.
Stuff related to the text buffer GUI.
static const byte LIT_COMPANY
Show the liveries of your own company.
Definition: livery.h:18
A male of Caucasian origin (white)
uint32 station
Count of company owned station tiles.
Definition: company_base.h:36
Line for summing bank balance and loan.
Eyecolour right.
CompanyWindowPlanes
Display planes in the company window.
RoadType
The different roadtypes we support.
Definition: road_type.h:22
Bank balance value.
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:26
Tie / Earring.
bool infrastructure_maintenance
enable monthly maintenance fee for owner infrastructure
Pure simple text.
Definition: widget_type.h:58
Description of station.
bool IsDisabled() const
Return whether the widget is disabled.
Definition: widget_type.h:358
Running costs trains.
Definition: economy_type.h:153
Caption of window.
Functions, definitions and such used only by the GUI.
Servers always have this ID.
Definition: network_type.h:45
T * Append(uint to_add=1)
Append an item and return it.
void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
Helper for drawing the counts line.
Column for year Y-2 expenses.
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
bool allow_shares
allow the buying/selling of shares
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Functions related to (drawing on) viewports.
Has moustache or earring.
static const CompanyManagerFaceBitsInfo _cmf_info[]
Lookup table for indices into the CompanyManagerFace, valid ranges and sprites.
Data structure for an opened window.
Definition: window_gui.h:271
No button.
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
Text about tie and earring.
Selection of maxloan column.
Spacer for dropdown.
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1032
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
Hair right.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Bottom offset of the text of the frame.
Definition: window_gui.h:75
Female button in the advanced view.
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
Aircraft vehicle type.
Definition: vehicle_type.h:27
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Yes button.
uint32 CompanyManagerFace
Company manager face bits, info see in company_manager_face.h.
Definition: company_type.h:55
Lowest bit of the number of rows.
Definition: widget_type.h:31
Only numeric ones.
Definition: string_type.h:28
Text about glasses.
Selection of buttons.
uint32 signal
Count of company owned signals.
Definition: company_base.h:33
Invisible widget that takes some space.
Definition: widget_type.h:79
decrease the loan from the bank
Definition: command_type.h:239
Glasses right.
Types related to object tiles.
Text about ethnicity african.
Functions related to errors.
void ShowCompany(CompanyID company)
Show the window with the overview of the company.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Colour scheme example.
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:210
void SetDataTip(uint32 widget_data, StringID tool_tip)
Set data and tool tip of the nested widget.
Definition: widget.cpp:894
Income from road vehicles.
Definition: economy_type.h:159
static const StringID PART_TEXTS[]
Fixed strings to describe parts of the face.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
increase the loan from the bank
Definition: command_type.h:238
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
static const uint EXP_BLOCKSPACE
Amount of vertical space between two blocks of numbers.
Definition: company_gui.cpp:47
Money GetTotalMaintenanceCost() const
Get total infrastructure maintenance cost.
Female button in the simple view.
Count of rail.
Count of water.
Money current_loan
Amount of money borrowed from the bank.
Definition: company_base.h:66
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Simple vector template class, with automatic delete.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:389
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition: station.cpp:558
virtual void OnPlaceObjectAbort()
The user cancelled a tile highlight mode that has been set.
TileIndex location_of_HQ
Northern tile of HQ; INVALID_TILE when there is none.
Definition: company_base.h:74
Definition of base types and functions in a cross-platform compatible way.
Center both horizontally and vertically.
Definition: gfx_func.h:108
the length of the string is counted in characters
Definition: textbuf_gui.h:24
static const uint MAX_LENGTH_COMPANY_NAME_CHARS
The maximum length of a company name in characters including &#39;\0&#39;.
Definition: company_type.h:42
uint32 road[ROADTYPE_END]
Count of company owned track bits for each road type.
Definition: company_base.h:32
A number of safeguards to prevent using unsafe methods.
Trams.
Definition: road_type.h:25
GenderEthnicity ge
Gender and ethnicity.
Load face.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced. ...
Definition: rail.h:255
static void RandomCompanyManagerFaceBits(CompanyManagerFace &cmf, GenderEthnicity ge, bool adv, bool interactive=true)
Make a random new face.
Geometry functions.
rectangle (stations, depots, ...)
Simple depressed panel.
Definition: widget_type.h:50
Window class displaying the company finances.
static ExpensesType _expenses_list_2[]
Grouped list of expenses.
Definition: company_gui.cpp:70
static void DrawCategories(const Rect &r)
Draw the expenses categories.
static ExpensesType _expenses_list_1[]
Standard unsorted list of expenses.
Definition: company_gui.cpp:53
set the manager&#39;s face of the company
Definition: command_type.h:235
Finances of a company; Window numbers:
Definition: window_type.h:518
Information about a particular livery.
Definition: livery.h:76
Tie / Earring left.
RailTypes railtypes
Valid railtypes.
static const byte LIT_ALL
Show the liveries of all companies.
Definition: livery.h:19
static void IncreaseCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, int8 amount)
Increase/Decrease the company manager&#39;s face variable by the given amount.
static void SetCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, uint val)
Sets the company manager&#39;s face bits for the given company manager&#39;s face variable.
Company colour selection; Window numbers:
Definition: window_type.h:225
CompanyWidgets
Widgets of the CompanyWindow class.
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
Definition: company_base.h:122
virtual void OnPaint()
The window must be repainted.
change the company name
Definition: command_type.h:245
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition: economy.cpp:113
set the colour of the company
Definition: command_type.h:236
Gap above max loan widget.
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:142
ExpensesType
Types of expenses.
Definition: economy_type.h:150
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:94
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
Money money
Money owned by the company.
Definition: company_base.h:64
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
Dropdown for primary colour.
Baseclass for nested widgets.
Definition: widget_type.h:126
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:499
Basic functions/variables used all over the place.
Current face.
uint16 num_vehicle
Number of vehicles.
Definition: group.h:26
Functions related to stations.
Text about jacket.
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:527
uint32 airport
Count of company owned airports.
Definition: company_base.h:37
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
Road vehicle type.
Definition: vehicle_type.h:25
Lips / Moustache right.
Grid of rows and columns.
Definition: widget_type.h:59
static void DoSelectCompanyManagerFace(Window *parent)
Open the simple/advanced company manager face selection window.
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:390
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Right offset of the image in the button.
Definition: window_gui.h:41
uint GetCategoriesWidth() const
Compute width of the expenses categories in pixels.
void DrawFaceStringLabel(byte widget_index, uint8 val, bool is_bool_widget) const
Draw dynamic a label to the left of the button and a value in the button.
Money max_loan
NOSAVE: Maximum possible loan.
Definition: economy_type.h:22
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
Running costs ships.
Definition: economy_type.h:156
Text is written left-to-right by default.
Definition: strings_type.h:25
static const uint8 PC_BLACK
Black palette colour.
Definition: gfx_func.h:207
Infrastructure count.
byte colour2
Second colour, for vehicles with 2CC support.
Definition: livery.h:79
virtual void OnPaint()
The window must be repainted.
virtual void OnInit()
Notification that the nested widget tree gets initialized.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
Text about chin.
Count of road.
CompanyManagerFace face
Face description of the president.
Definition: company_base.h:62
Trams.
Definition: road_type.h:39
const uint num_subtotals
Number of sub-totals in the list.
Definition: company_gui.cpp:93
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition: road_type.h:36
static void DrawPrice(Money amount, int left, int right, int top)
Draw an amount of money.
static const int WIDGET_LIST_END
indicate the end of widgets&#39; list for vararg functions
Definition: widget_type.h:22
virtual void OnPlaceObject(Point pt, TileIndex tile)
The user clicked some place on the map when a tile highlight mode has been set.
Income from aircrafts.
Definition: economy_type.h:160
Text about lips and moustache.
virtual void OnPaint()
The window must be repainted.
static SpriteID GetCompanyManagerFaceSprite(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Gets the sprite to draw for the given company manager&#39;s face variable.
Ship vehicle type.
Definition: vehicle_type.h:26
Eyecolour left.
bool _shift_pressed
Is Shift pressed?
Definition: gfx.cpp:37
void ShowExtraViewPortWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
bool advanced
advanced company manager face selection window
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Increase loan.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
virtual void OnHundredthTick()
Called once every 100 (game) ticks.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:125
Lips / Moustache left.
uint32 rail[RAILTYPE_END]
Count of company owned track bits for each rail type.
Definition: company_base.h:34
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
Construction costs.
Definition: economy_type.h:151
View of the face.
void SetupWidgets()
Setup the widgets in the nested tree, such that the finances window is displayed properly.
Company infrastructure overview; Window numbers:
Definition: window_type.h:572
Text about eyebrows.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Functions related to companies.
Collar right.
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
Definition: viewport.cpp:3151
Count of total.
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition: sprites.h:1538
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Used for iterations.
Definition: road_type.h:23
Base class for engines.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Description of water.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Running costs road vehicles.
Definition: economy_type.h:154
Toggle windows size.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Functionality related to the company manager&#39;s face.
CompanyManagerFace face
company manager face bits
bool IsLowered() const
Return whether the widget is lowered.
Definition: widget_type.h:343
GUISettings gui
settings related to the GUI
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
Description of total.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
static Money StationMaintenanceCost(uint32 num)
Calculates the maintenance cost of a number of station tiles.
Definition: station_func.h:61
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
OwnerByte share_owners[4]
Owners of the 4 shares of the company. INVALID_OWNER if nobody has bought them yet.
Definition: company_base.h:77
sell a share from a company
Definition: command_type.h:258
Class general.
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
byte colour
Company colour.
Definition: company_base.h:68
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:105
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE, WID_SCMF_SEL_MALEFEMALE, and WID_SCMF_SEL_PARTS.
Decrease loan..
Count of station.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Vertical container.
Definition: widget_type.h:77
Property costs.
Definition: economy_type.h:157
Selection to display the male/female buttons in the simple view.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
Display the build button.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
change the president name
Definition: command_type.h:246
Functions related to zooming.
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:420
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
Panel about &#39;Relocate HQ&#39;.
No rail types.
Definition: rail_type.h:53
#define endof(x)
Get the end element of an fixed size array.
Definition: stdafx.h:427
Get the face code.
Running costs aircrafts.
Definition: economy_type.h:155
LiveryClass
List of different livery classes, used only by the livery GUI.
Definition: livery.h:66
#define MAX_DAY
The number of days till the last day.
Definition: date_type.h:97
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition: newgrf.h:162
static Money CanalMaintenanceCost(uint32 num)
Calculates the maintenance cost of a number of canal tiles.
Definition: water.h:51
Alter company face window; Window numbers:
Definition: window_type.h:231
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2268
Button to buy a share.
Functions related to commands.
Network functions used by other parts of OpenTTD.
Text about eyecolour.
No roadtypes.
Definition: road_type.h:37
bool _network_server
network-server is active
Definition: network.cpp:57
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:768
void SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition: widget.cpp:1084
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
Button to set company password.
This bit set means black, otherwise white.
uint64 used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition: newgrf.h:163
Income from trains.
Definition: economy_type.h:158
Drop down list.
Definition: widget_type.h:70
Face button.
Eyebrows left.
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:106
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Multiplayer selection panel.
Caption of window.
Text about glasses.
Buttons of the other companies.
New vehicles.
Definition: economy_type.h:152
virtual void OnHundredthTick()
Called once every 100 (game) ticks.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
Income from ships.
Definition: economy_type.h:161
static void ScaleAllCompanyManagerFaceBits(CompanyManagerFace &cmf)
Scales all company manager&#39;s face bits to the correct scope.
Money yearly_expenses[3][EXPENSES_END]
Expenses of the company for the last three years, in every #Expenses category.
Definition: company_base.h:96
GenderEthnicity
The gender/race combinations that we have faces for.
StringID name
Name of this rail type.
Definition: rail.h:165
Panel about infrastructure.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
byte liveries
options for displaying company liveries, 0=none, 1=self, 2=all
Definition: settings_type.h:92
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition: error.h:23
Class aircraft.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including &#39;\0&#39; (must be >= NETWORK_SERVER_ID_LENGTH) ...
Definition: config.h:47
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
byte colour1
First colour, for all vehicles.
Definition: livery.h:78
#define CMD_MSG(x)
Used to combine a StringID with the command.
Definition: command_type.h:366
Used for iterations.
Definition: rail_type.h:30
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:695
Invalid expense type.
Definition: economy_type.h:165
GameCreationSettings game_creation
settings used during the creation of a game (map)
buy a share from a company
Definition: command_type.h:257
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows)...
Definition: viewport.cpp:3211
Question text.
Specification of a rectangle with absolute coordinates of all edges.
Number of expense types.
Definition: economy_type.h:164
RoadTypes roadtypes
Valid roadtypes.
Text is written right-to-left by default.
Definition: strings_type.h:26
Right align the text (must be a single bit).
Definition: gfx_func.h:100
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:307
Other expenses.
Definition: economy_type.h:163
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:154
Eyebrows right.
static void DrawYearColumn(const Rect &r, int year, const Money(*tbl)[EXPENSES_END])
Draw a column with prices.
Functions related to tile highlights.
uint total_width
String width of the total cost line.
Save face.
Owner
Enum for all companies/owners.
Definition: company_type.h:20
Window functions not directly related to making/drawing windows.
virtual void OnPaint()
The window must be repainted.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition: newgrf.cpp:77
Find a place automatically.
Definition: window_gui.h:156
Functions related to water (management)
(Toggle) Button with image
Definition: widget_type.h:52
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
static const NWidgetPart _nested_select_company_manager_face_widgets[]
Nested widget description for the company manager face selection dialog.
Male button in the advanced view.
Button to change president name.
Nose right.
Text about ethnicity european.
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
GUI functions that shouldn&#39;t be here.
static Money RailMaintenanceCost(RailType railtype, uint32 num, uint32 total_num)
Calculates the maintenance cost of a number of track bits.
Definition: rail.h:399
byte climates
Climates supported by the engine.
Definition: engine_type.h:138
Hide the relocate HQ button.
Window with general information about a company.
static uint GetCompanyManagerFaceBits(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Gets the company manager&#39;s face bits for the given company manager&#39;s face variable.
Company view; Window numbers:
Definition: window_type.h:364
An invalid company.
Definition: company_type.h:32
Left offset of the image in the button.
Definition: window_gui.h:40
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Male button in the simple view.
Base list item class from which others are derived.
Definition: dropdown_type.h:24
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
Add the rail types that are to be introduced at the given date.
Definition: rail.cpp:225
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
static void ShowCompanyInfrastructure(CompanyID company)
Open the infrastructure window of a company.
static const StringID PART_TEXTS_IS_FEMALE[]
Strings depending on is_female, used to describe parts (2 entries for a part).
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition: window.cpp:1234
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
static const ObjectType OBJECT_HQ
HeadQuarter of a player.
Definition: object_type.h:22
Dimension yesno_dim
Dimension of a yes/no button of a part in the advanced face window.
static Money RoadMaintenanceCost(RoadType roadtype, uint32 num)
Calculates the maintenance cost of a number of road bits.
Definition: road_func.h:172
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:833
Owner in Owners.
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1076
bool is_moust_male
Male face with a moustache.
Column for expenses category strings.
An invalid owner.
Definition: company_type.h:31
static Money max_money
The maximum amount of money a company has had this &#39;run&#39;.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1461
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:620
(Toggle) Button with text
Definition: widget_type.h:55
build an object
Definition: command_type.h:189
Description of rail.
Train vehicle type.
Definition: vehicle_type.h:24
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:284
bool small
Window is toggled to &#39;small&#39;.
Selection to display the buttons for setting each part of the face in the advanced view...
Interest payments over the loan.
Definition: economy_type.h:162
uint32 water
Count of company owned track bits for canals.
Definition: company_base.h:35
Base for the NewGRF implementation.